<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

 <title>GoTo RetroCode BLOG</title>
 <link href="https://www.opengate.at/blog/atom.xml" rel="self"/>
 <link href="https://www.opengate.at/blog/"/>
 <updated>2026-01-02T01:43:46+01:00</updated>
 <id>https://www.opengate.at/blog</id>
 <author>
   <name>Stefan</name>
   <email>blog@opengate.at</email>
 </author>

 
 <entry>
   <title>Pinebook Pro Akku manuell laden</title>
   <link href="https://www.opengate.at/blog/2025/04/pinebook-battery/"/>
   <published>2025-04-27T13:00:00+02:00</published>
   <updated>2025-04-27T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2025/04/pinebook-battery</id>
   <category term="hardware" />
   <summary type="text">Ich besitze zu viel Hardware, und auch zu viele Laptops.
Folglich liegt ein Gerät auch gerne mal ein Jahr unbenutzt im Kasten.

Und als ich vorhin mein PineBook von 
Pine64 wieder in Betrieb nehmen wollte blieb
der Bildschirm einfach schwarz.

</summary>
   <content type="html">&lt;p&gt;Ich besitze zu viel Hardware, und auch zu viele Laptops.
Folglich liegt ein Gerät auch gerne mal ein Jahr unbenutzt im Kasten.&lt;/p&gt;

&lt;p&gt;Und als ich vorhin mein &lt;code&gt;PineBook&lt;/code&gt; von 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Pine64&quot;&gt;Pine64&lt;/a&gt; wieder in Betrieb nehmen wollte blieb
der Bildschirm einfach schwarz.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Dass der Akku von unbenutzten Laptops auch entlädt ist bekannt.
Man schließt das Ladegerät an, wartet etwas und startet
die Maschine ganz normal.&lt;/p&gt;

&lt;p&gt;Doch das funktionierte diesmal nicht.&lt;br /&gt;
Mir fiel die blinkende Lade-LED auf und so fand ich im Netz heraus, dass
ein Blinken im Sekundentakt auf einen “Hardwareschaden” hinweist.&lt;br /&gt;
Kurz gesagt: Der Akku lädt nicht … und hochfahren lät sich
das System so auch nicht.&lt;br /&gt;
Weder das Herstellernetzteil noch der alternative USB-C-Port funktionierte.&lt;/p&gt;

&lt;h3 id=&quot;tiefentladung-vermutet&quot;&gt;Tiefentladung vermutet&lt;/h3&gt;

&lt;p&gt;Nach ein paar Tränen, schraubte ich den Laptop auf und koppelte den
Akku ab. Mein Multimeter zeigte 2.7 Volt zwischen den roten und schwarzen
Adern an, was auf einen zu tiefen Ladestand hinwies, der aber noch nicht 
tödlich sein musste.&lt;/p&gt;

&lt;p&gt;Darauf hin schaltete ich mein Labornetzteil auf 4 Volt, und leitete für
einige Minuten wieder etwas Strom in den Akku zurück.
Eine erneute Messung zeigte dann wieder 3.4 Volt an. Somit schloss ich den
Akku wieder an und versuchte eine reguläre Aufladung.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/pinebook_battery.jpg&quot; alt=&quot;Pinebook Pro Battery&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Das Herstellernetzteil ließ leider wieder die LED im Fehlermodus blinken,
doch eine Aufladung per USB-C klappte plötzlich. Die Lade-LED leuchtete
durchgehend und schon konnte ich das System starten.&lt;/p&gt;

&lt;h3 id=&quot;ladevorgang&quot;&gt;Ladevorgang&lt;/h3&gt;

&lt;p&gt;Nach dem Boot von &lt;a href=&quot;https://en.wikipedia.org/wiki/Armbian&quot;&gt;Armbian&lt;/a&gt; checkte ich
den Status per Linux &lt;code&gt;sysfs&lt;/code&gt;.&lt;br /&gt;
&lt;code&gt;cat /sys/class/power_supply/cw2015-battery/capacity&lt;/code&gt; zeigt die 
Ladekapazität in Prozent und dieser Wert stieg alle paar Minuten.
… das Aufladen funktionierte also wieder.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;/sys/class/power_supply/cw2015-battery/voltage_now&lt;/code&gt; zeigt auch die aktuelle
Akkuspannung an und auch dieser Wert stieg im Minutentakt an.&lt;/p&gt;

&lt;p&gt;Interessant ist der Wert in
&lt;code&gt;/sys/class/power_supply/cw2015-battery/voltage_min_design&lt;/code&gt;, denn dieser liegt
fest bei 3000000 uV, also genau 3 Volt.&lt;br /&gt;
Es macht also Sinn, dass auch die verbaute Hardware einen Akku unter 3V nicht
mehr akzeptiert.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Mit der Entladung habe ich den Akku sicher geschädigt und seine 
Kapazität wie auch Lebensdauer reduziert.&lt;br /&gt;
Doch durch die Wiederbelebung mit ein bisschen Extrastrom kann mein
&lt;code&gt;PineBook&lt;/code&gt; wieder booten und ich kann wieder ein bisschen experimentieren.&lt;/p&gt;

&lt;p&gt;Ein neuer Nachbau Akku kommt auf 30 Euro, ist also leistbar.
Doch … wie gesagt, ich besitze zu viele Laptops … es zahlt sich nicht
wirklich aus jedes Jahr einen neuen Akku zu kaufen, denn dafür nutze
ich die Maschine leider nicht oft genug.&lt;/p&gt;

&lt;p&gt;Zumindest werde ich jetzt häufiger mal das Ladekabel anschließen
um weitere Tiefentladungen zu vermeiden.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>CMAKE v4.0 Update</title>
   <link href="https://www.opengate.at/blog/2025/04/cmake4-update/"/>
   <published>2025-04-20T13:00:00+02:00</published>
   <updated>2025-04-20T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2025/04/cmake4-update</id>
   <category term="software" />
   <summary type="text">Frisch aus der Build-Fabrik wird weiter 
CMake Version 4.0 ins Netz verteilt.

Nun stellt sich die Frage:


  Wird mein Code weiter damit gebaut werden können?


</summary>
   <content type="html">&lt;p&gt;Frisch aus der Build-Fabrik wird weiter 
&lt;a href=&quot;https://de.wikipedia.org/wiki/CMake&quot;&gt;CMake&lt;/a&gt; Version 4.0 ins Netz verteilt.&lt;/p&gt;

&lt;p&gt;Nun stellt sich die Frage:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Wird mein Code weiter damit gebaut werden können?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Antwort:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;aber nicht immer.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ich habe nicht so ganz verstanden, warum nach 3.31 Version 4.0 folgte.
Denn ich sehe keine wirklich “großen” Features. Es fühlt sich - wie
schon oft gesagt - eher an wie ein Sprung von 3.31 auf 3.40.&lt;/p&gt;

&lt;p&gt;Eine wichtige Änderung gibt es aber: Die Mindest-Version in &lt;code&gt;CMake&lt;/code&gt;
Scripts muss jetzt größer gleich 3.10 sein.&lt;/p&gt;

&lt;p&gt;Ich hatte schon beim Wechsel von 3.26 auf 3.27 feststellen müssen, dass ein
CMake-Minimum-Requirement jetzt 3.5 ist und ältere Angaben einfach nicht
mehr gebaut werden können.&lt;br /&gt;
Mit der Erhöhung auf 3.10 ist nun auch ein Update meine GATE Quellcodes
notwendig, um dynamisch auf den Versionszwang reagieren zu können.&lt;/p&gt;

&lt;h3 id=&quot;problem-alte-plattformen&quot;&gt;Problem: Alte Plattformen&lt;/h3&gt;

&lt;p&gt;Ich brauch in Wahrheit nur selten Features, die über v3.1 liegen.
Für Builds auf Windows 2000 ist v3.4 die jüngste Version, die auf
diesem System noch ausführbar ist.&lt;br /&gt;
Folglich hatte ich ursprünglich:&lt;/p&gt;

&lt;div class=&quot;language-cmake highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;cmake_minimum_required(VERSION 3.4)
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;in meiner &lt;code&gt;CMakeLists.txt&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Nach der Veröffentlichung von 3.27, hatte ich das auf 3.5 erhöht, 
um zumindest auf “allen” Folgesystemen baubar zu sein.&lt;br /&gt;
Die alten Debian Varianten wie Debian-9 kamen schließlich mit 
CMake v3.7 heraus, womit mein Build direkt auf solchen Plattformen 
lauffähig ist.&lt;/p&gt;

&lt;p&gt;Mit der erneuten Erhöhung beschloss ich das ganze “flexibel” zu gestalten:&lt;/p&gt;

&lt;div class=&quot;language-cmake highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;if(CMAKE_VERSION VERSION_GREATER &amp;quot;3.14.99&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;  cmake_minimum_required(VERSION 3.15)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;elseif(CMAKE_VERSION VERSION_GREATER &amp;quot;3.4.99&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  cmake_minimum_required(VERSION 3.5)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;else()
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;  cmake_minimum_required(VERSION 3.1)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;endif()
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;blockquote&gt;
  &lt;p&gt;Tja, CMake-Macher … ihr dachtet wohl, 
ihr erkönnt mich zum Upgrade zwingen.&lt;br /&gt;
Falsch gedacht! Denn ich weiß mit &lt;code&gt;IF&lt;/code&gt; umzugehen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ja, &lt;code&gt;CMake&lt;/code&gt; Erweiterungen sind gut … aber dieser v4 Sprung kommt mir 
doch etwas seltsam vor.&lt;/p&gt;

&lt;p&gt;Dass die älteren Minimum-Requirements mal erhöht werden, war mir klar.
Dass das aber so schnell passieren würde, überraschte mich doch etwas.&lt;/p&gt;

&lt;p&gt;Wie auch immer … die flexible Lösung passt sich jetzt an die installierte
CMake Version an und somit kann ich weiter die alte mit der neuen Welt
“verbinden”.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>C64 Keyboard Upgrade</title>
   <link href="https://www.opengate.at/blog/2025/04/c64-keyboard/"/>
   <published>2025-04-13T13:00:00+02:00</published>
   <updated>2025-04-13T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2025/04/c64-keyboard</id>
   <category term="hardware" />
   <summary type="text">Die alte leider nicht mehr so ganz gut funktionierende Tastatur meines
Commodore 64 Models hindert mich noch
irgend etwas mit dem Gerät anstellen zu können.

Frage:


  Kann man das C64 Keyboard ersetzen?


</summary>
   <content type="html">&lt;p&gt;Die alte leider nicht mehr so ganz gut funktionierende Tastatur meines
&lt;a href=&quot;https://de.wikipedia.org/wiki/Commodore_64&quot;&gt;Commodore 64&lt;/a&gt; Models hindert mich noch
irgend etwas mit dem Gerät anstellen zu können.&lt;/p&gt;

&lt;p&gt;Frage:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Kann man das C64 Keyboard ersetzen?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Antwort:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ja. Kaufen oder selber machen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Tatsächlich hat sich ein Tüftler das 
&lt;a href=&quot;https://www.breadbox64.com/blog/the-mechboard64/&quot;&gt;MechBoard64&lt;/a&gt; einfallen
lassen. Dabei handelt es sich um eine Platinenblaupause, die moderne 
mechanische Tasten im Layout des C64 einfügen lässt, die mit dem
Board-Anschluss des C64 kompatibel ist.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/c64-keyboard-mechboard.jpg&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Kurz gesagt:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Man lässt sich eine Mechboard-Platine anfertigen&lt;/li&gt;
  &lt;li&gt;Man kauft mechanische Tastatur-Schalter (Key-Switches), die auf die 
Platine gelötet werden.&lt;/li&gt;
  &lt;li&gt;Man kauft Tastenkappen (Key-Caps), die auf die Schalter gesetzt werden.&lt;/li&gt;
  &lt;li&gt;Man schraubt die Platine auf die Halterung, die im C64 eingesetzt wird.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Und tatsächlich klappt das auch so.&lt;br /&gt;
Mein 3D-Drucker konnte ein ungefähres Ersatzstück für die Metall-Halterung
nachbilden. Diese bestand aus 3 Teilen und musste zu einem Rahmen 
zusammengeklebt werden.&lt;/p&gt;

&lt;p&gt;Und mit “kleben” verstand ich per “Heißluft zusammenschmelzen”.&lt;br /&gt;
Das sieht in Videos immer so leicht aus, aber ich hab’s leider
ziemlich versaut. Man kann nicht sagen, dass es stabil war,
aber es war offenbar “stabil genug”.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/c64-keyboard-3dframe.jpg&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Am Mechboard wäre auch Platz für eine Schaltung des C64 Capslock gewesen,
doch da mir das nicht so wichtig war, habe ich das weggelassen.
Capslock funktioniert dann zwar nicht, aber damit kann ich leben.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/c64-keyboard-3dwithkeys.jpg&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Mein Pech war am Ende, dass ich keine C64-Tastenkappen hatte,
sondern nur die eines regulären PCs.
Folglich passten einige Sonderformate nicht und ich musste andere
Bezeichnungen für C64-exklusive Tasten hernehmen.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/c64-keyboard-upgrade.jpg&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Am Ende war ich dann aber schon überrascht, dass die “neue” Tastatur
wieder (fast) perfekt funktionierte.&lt;/p&gt;

&lt;p&gt;Ich hätte mir die Sache auch leichter machen können und bei einem
Händler eine “professionelle” Ersatztastatur für den C64 einkaufen
können.&lt;/p&gt;

&lt;p&gt;Doch das selbst-machen ist eben interessanter.&lt;/p&gt;

&lt;p&gt;Die defekte originale Tastatur behalte ich natürlich, denn mein Ersatz 
sieht auch nicht wirklich gut aus. Vielleicht kaufe ich in der Zukunft
doch noch ein besseres Keyboard, aber vorerst bin ich zufrieden,
dass ich das Gerät wieder in Betrieb nehmen kann.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Doxygen per CMake</title>
   <link href="https://www.opengate.at/blog/2025/04/doxygen-cmake/"/>
   <published>2025-04-06T13:00:00+02:00</published>
   <updated>2025-04-06T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2025/04/doxygen-cmake</id>
   <category term="devel" /><category term="software" />
   <summary type="text">Doxygen ist im GATE Projekt ein “alter Hut”.
Das Programm ist im CI Docker 
und Script integriert und wartet nur auf seinen Aufruf.
Aber …


  Wäre es nicht besser alle Tools (und auch Doxygen) über 
CMake anzusteuern?


</summary>
   <content type="html">&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Doxygen&quot;&gt;Doxygen&lt;/a&gt; ist im GATE Projekt ein “alter Hut”.
Das Programm ist im CI &lt;a href=&quot;https://de.wikipedia.org/wiki/Docker_(Software)&quot;&gt;Docker&lt;/a&gt; 
und Script integriert und wartet nur auf seinen Aufruf.&lt;br /&gt;
Aber …&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Wäre es nicht besser alle Tools (und auch Doxygen) über 
&lt;a href=&quot;https://de.wikipedia.org/wiki/CMake&quot;&gt;CMake&lt;/a&gt; anzusteuern?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;In der Entwicklung haben wir unterschiedliche Tools, die wir unterschiedlich
kombinieren und in Scripts unterschiedlich zusammenwürfeln.&lt;br /&gt;
Jetzt ist es aber oft ärgerlich, wenn man immer wieder mal aus der 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Integrierte_Entwicklungsumgebung&quot;&gt;IDE&lt;/a&gt; zur
Konsole wechseln muss, um wieder eines der Tools anzuwerfen.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_Studio_Code&quot;&gt;VSCode&lt;/a&gt; bietet in seinem 
&lt;code&gt;CMake&lt;/code&gt; Plugin immer eine Übersicht über alle ausführbaren Targets. 
Ein Klick auf ein solches baut es und ein anderer Klick im 
Test-Fenster startet die Tests.&lt;/p&gt;

&lt;h3 id=&quot;idee-doxygen-wird-per-cmake-als-utility-ausgeführt&quot;&gt;Idee: Doxygen wird per CMake als Utility ausgeführt&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;CMake&lt;/code&gt; bietet mit 
&lt;a href=&quot;https://cmake.org/cmake/help/latest/command/add_custom_target.html&quot;&gt;add_custom_target()&lt;/a&gt;
eine einfache Möglichkeit jedes beliebige Programm als Target zu registrieren.
Beim “Bauen” des Targets wird das registrierte Programm mit einstellbaren 
Parametern gestartet.&lt;/p&gt;

&lt;p&gt;Ich habe meine &lt;code&gt;CMakeLists.txt&lt;/code&gt; daher um folgende Zeilen erweitert:&lt;/p&gt;

&lt;div class=&quot;language-cmake highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;function(gate_add_doxygen_target)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;  find_package(Doxygen REQUIRED)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  add_custom_target(util_doxygen_run
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;    COMMAND ${DOXYGEN_EXECUTABLE} &amp;quot;${CMAKE_SOURCE_DIR}/Doxyfile&amp;quot;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;    WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;    COMMENT &amp;quot;Executing doxygen documentation generation&amp;quot;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;  )
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;endfunction()
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;find_package(Doxygen QUIET)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;option(GATE_BUILD_DOXYGEN &amp;quot;Build doxygen docu&amp;quot; ${DOXYGEN_FOUND})
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;if(GATE_BUILD_DOXYGEN)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;  gate_add_doxygen_target()
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;endif()
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Wird das Program &lt;code&gt;doxygen&lt;/code&gt; im System gefunden, wird die &lt;code&gt;CMake&lt;/code&gt; Option 
&lt;code&gt;GATE_BUILD_DOXYGEN&lt;/code&gt; aktiviert und dann die Funktion zum Hinzufügen des
Targets aufgerufen. Über die Option kann man das dann auch manuell
aus/einschalten.&lt;/p&gt;

&lt;p&gt;Da ein &lt;code&gt;Doxyfile&lt;/code&gt; ohne schon im Projekt ist, fehlt nur die Aufruf von
&lt;code&gt;doxygen&lt;/code&gt; mit der Datei als Parameter.&lt;/p&gt;

&lt;p&gt;Und mit dem nächsten &lt;code&gt;Configure&lt;/code&gt; Klick in der VSCode CMake UI, finde ich
schon das neue Target &lt;code&gt;util_doxygen_run&lt;/code&gt; in meiner Liste.&lt;br /&gt;
Ab sofort kann ich also einfach per Klick die Doku bauen lassen und 
im Browser parallel überprüfen.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/vscode-cmake-doxygen.png&quot; alt=&quot;VSCode CMake Doxygen&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;Oft sind es die kleinen Dinge, die viel bewirken.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Man kann &lt;code&gt;doxygen&lt;/code&gt; natürlich weiter manuell starten, aber der einfache
Klick im &lt;code&gt;VSCode&lt;/code&gt; Fenster spart Zeit.&lt;/p&gt;

&lt;p&gt;Ganz besonders wenn ich immer wieder Änderungen mache und das Ergebnis
sofort sehen will, öffne ich im Browser die HTML-Datei und brauche
dann nur einen VSCode-Klick und einen F5-Refresh im Browser um 
die neu-generierte Doku gegenlesen zu können.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>CMake 4.0 (ist zuuu neu)</title>
   <link href="https://www.opengate.at/blog/2025/03/cmake4/"/>
   <published>2025-03-30T13:00:00+02:00</published>
   <updated>2025-03-30T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2025/03/cmake4</id>
   <category term="devel" /><category term="software" />
   <summary type="text">Mit dem Erscheinen von CMake Version 4 geht 
das defacto Standard C/C++ Build-System in
eine neue Runde.

Es fühlt sich aber eher wie ein CMake 3.40 an, das auf die letzte 
3er-Version 3.31 folgt.
</summary>
   <content type="html">&lt;p&gt;Mit dem Erscheinen von &lt;a href=&quot;https://de.wikipedia.org/wiki/CMake&quot;&gt;CMake&lt;/a&gt; Version 4 geht 
das defacto Standard &lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B&quot;&gt;C/C++&lt;/a&gt; Build-System in
eine neue Runde.&lt;/p&gt;

&lt;p&gt;Es fühlt sich aber eher wie ein &lt;code&gt;CMake&lt;/code&gt; 3.40 an, das auf die letzte 
3er-Version 3.31 folgt.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Ich kenne &lt;code&gt;CMake&lt;/code&gt; nun seit fast 10 Jahren und nutze es privat wie beruflich
in den letzten 6 Jahren täglich.&lt;br /&gt;
Eigentlich stellt sich für mich immer wieder die Frage, warum ich es nicht
schon seit 16 Jahren durchgehend nutze … naja … eine andere Geschichte.&lt;/p&gt;

&lt;p&gt;Version 4.0 bringt für mich keine wichtigen Neuerungen mit, leider beschert
uns allen der Umstieg eher Probleme, weil Dinge fehlen.&lt;/p&gt;

&lt;p&gt;Ab v4.0 wird der Minimum-Standard auf v3.10 gehoben. Das ist formal kein
großes Thema, weil alles weiter funktioniert, was bis v3.9 da war,
wenn man von ein paar Sonderfällen und Spezial-Policies und -Defaults absieht.&lt;/p&gt;

&lt;p&gt;Doch wer in seinem Script ein&lt;/p&gt;

&lt;div class=&quot;language-cmake highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;cmake_minimum_required(VERSION 3.9)
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;oder generell &lt;code&gt;&amp;lt; 3.10&lt;/code&gt; drinnen hat, bekommt jetzt einen Fehler mit Abbruch,
wo in den letzten Versionen nur eine Deprecation-Warning stand.&lt;/p&gt;

&lt;p&gt;Viele kleinere Projekte wie z.B.: &lt;a href=&quot;https://de.wikipedia.org/wiki/Zlib&quot;&gt;zlib&lt;/a&gt; nutzen
nur Basis-Funktionen in &lt;code&gt;CMake&lt;/code&gt;, die alle schon in v3.0 oder 3.1 enthalten
waren. Folglich ist deren Minimum-Requirement auch für diese alten 
Versionen gesetzt.&lt;/p&gt;

&lt;p&gt;Mit &lt;code&gt;CMake&lt;/code&gt; 4.0 lässt sich dieser Code dann nicht mehr verwalten.
Das trifft mich vor allem bei &lt;a href=&quot;https://de.wikipedia.org/wiki/Conan_(Software)&quot;&gt;Conan&lt;/a&gt;
Projekten, denn dort sind alle fertigen Pakete und Rezepte fixiert und werden
nicht fortlaufend geändert.&lt;br /&gt;
Um sie kompilieren zu können ist also in Zukunft ein älteres &lt;code&gt;CMake&lt;/code&gt; zwingend
erforderlich.&lt;/p&gt;

&lt;p&gt;Version 3.26 ist das jüngste “alte CMake-3”, welches von v3.0 bis 3.26 alle
Varianten ohne Deprecation-Warning behandeln kann.&lt;/p&gt;

&lt;h3 id=&quot;gate-anpassungen&quot;&gt;GATE Anpassungen&lt;/h3&gt;

&lt;p&gt;Ich werde mir jetzt wohl etwas einfallen lassen müssen, damit GATE unter
CMake 4 genau so bauen kann wie unter CMake 3. Mein altes Test-Ubuntu 16.04
kommt noch mit CMake 3.7 um die Ecke und ich nutze kaum Funktionen über 3.5.&lt;/p&gt;

&lt;p&gt;Vermutlich lässt sich &lt;code&gt;cmake_minimum_required&lt;/code&gt; variabel gestalten, je nachdem,
was wirklich installiert wird. Dummerweise gibt es ohne diese &lt;code&gt;required&lt;/code&gt; Zeile
auch Warnungen und Fehler, dass das Minimum nicht festgelegt ist.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;CMake&lt;/code&gt; ist grundsätzlich genial … obwohl es uns eine scheußliche 
Scriptsprache aufzwingt. Da würde mir &lt;code&gt;xmake&lt;/code&gt; mit 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Lua&quot;&gt;LUA&lt;/a&gt; schon besser gefallen … doch wenn es 
um den Support älterer wie neuerer Compiler und alle Arten von exotischen 
Plattformen geht, kommt man an diesem Universalwerkzeug einfach nicht vorbei.&lt;/p&gt;

&lt;p&gt;Vorläufig musste ich CMake 4.0 wieder deinstallieren und durch 3.31 ersetzen.
Gespannt bin ich, wie &lt;code&gt;Conan&lt;/code&gt; Projekte auf die Änderung reagieren werden.
Conan selbst setzt ja 3.15 voraus, aber wie gesagt: Die &lt;code&gt;CMakeLists.txt&lt;/code&gt;
Dateien vieler Projekte nutzen oft Werte kleiner 3.10.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ich rieche Patches, die auf uns zukommen.&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>Pinball: Bally Air Aces</title>
   <link href="https://www.opengate.at/blog/2025/03/pinball/"/>
   <published>2025-03-23T12:00:00+01:00</published>
   <updated>2025-03-23T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2025/03/pinball</id>
   <category term="retro" />
   <summary type="text">Das letzte Erinnerungsstück an das Wirtshaus meiner Großeltern wurde gefunden:

Hinter einem Kasten verbarg sich seit den 90er Jahren die Anzeige
Glasplatte des Flipperautomaten, 
der damals die Gäste bespaßte.

</summary>
   <content type="html">&lt;p&gt;Das letzte Erinnerungsstück an das Wirtshaus meiner Großeltern wurde gefunden:&lt;/p&gt;

&lt;p&gt;Hinter einem Kasten verbarg sich seit den 90er Jahren die Anzeige
Glasplatte des &lt;a href=&quot;https://de.wikipedia.org/wiki/Flipperautomat&quot;&gt;Flipperautomaten&lt;/a&gt;, 
der damals die Gäste bespaßte.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;An den Flipper Automaten Bally Air Aces habe ich immer noch so manche 
Erinnerungen.&lt;/p&gt;

&lt;p&gt;Er muss wohl Ende der 70er oder Anfang der 80er Jahre angeschafft worden
sein und wurde dann Mitte der 80er mit Verkauf des Lokal außer Dienst 
gestellt.&lt;/p&gt;

&lt;p&gt;Das alles war vor meiner Zeit … doch weil niemand etwas mit dem Gerät
anfangen konnte, wanderte es in den Keller meiner Mutter und so fand ich
die Maschine Anfang der 90er als kleiner Junge begeistert vor.&lt;/p&gt;

&lt;p&gt;Man konnte ihn zwar bestromen und ein tolles Lichterspiel bewundern, doch
leider reagierten die Flügel nicht mehr womit ein echtes Spiel unmöglich
wurde.&lt;br /&gt;
Aber da das Schutzglas über der Spielfläche entfernt war, ging ich immer 
wieder mal in der Keller und ließ die Kugel manuell von oben nach unten 
rollen. Und immer wenn wo eine Lampe blinkte, funkelten meine Augen.&lt;/p&gt;

&lt;p&gt;Doch Platz im Keller war rar und so wurde bald ein befreundeter Mechaniker
eingeladen, der den Apparat demontierte, Schrauben und Lämpchen für den
Eigenbedarf sicherte und die große Kiste entsorgte.&lt;/p&gt;

&lt;p&gt;An diesem Tag versündigte sich meine Familie schwer … denn einen der 
immer weniger werdenden Flipper zu zerstören ist aus heutiger Sicht
eine Schandtat … damals war es “normal” so mehr Platz zu schaffen.&lt;/p&gt;

&lt;p&gt;Offenbar wurde jedoch das Display-Glas mit den typischen Motiven dieser
Zeit nicht entsorgt und landete hinter einem Kasten, wo es ungestört bis
ins Jahr 2025 überdauerte.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/pinball-ball-air-aces.jpg&quot; alt=&quot;Pinball Bally Air Aces&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Ein guter Bekannter, mit dem ich zufällig darüber sprach, war sofort
Feuer und Flamme für das alte Erbstück und so freue ich mich, dass
ich dem letzten Teil des Flippers ein neues Zuhause verschaffen konnte.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;Bitte passt auf die alten Flipper auf!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Wie gesagt: Hardwarezerstörung ist eine Todsünde.&lt;/p&gt;

&lt;p&gt;Mit heutigen Mitteln und vielen Interessenten im Internet hätte das 
alte Modell immer noch Freude und vor allem Geld einbringen können.&lt;/p&gt;

&lt;p&gt;Ich bezweifle, dass die ausgebauten Schrauben und Blinklampen je den
Wert oder Nutzen erreicht haben, den das Gesamtmodell heute hätte 
erzielen können.&lt;/p&gt;

&lt;p&gt;Tja … was soll man machen.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Leb wohl, Flipper!&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>VBScript mit mehr Rechten</title>
   <link href="https://www.opengate.at/blog/2025/03/vbscript-elevated/"/>
   <published>2025-03-16T12:00:00+01:00</published>
   <updated>2025-03-16T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2025/03/vbscript-elevated</id>
   <category term="devel" /><category term="software" />
   <summary type="text">Wenn man alte Scripts durchsieht, findet man die eine oder andere “Krampe”,
die einen schmunzeln lässt.

Und eine davon schrieb ich vor 15 Jahren zum Setup von Windows-Embedded 
Terminals in VBScript.
Der Zweck: Das Script soll mit Admin-Rechten laufen und diese einfordern,
wenn sie noch nicht vorhanden sind.

</summary>
   <content type="html">&lt;p&gt;Wenn man alte Scripts durchsieht, findet man die eine oder andere “Krampe”,
die einen schmunzeln lässt.&lt;/p&gt;

&lt;p&gt;Und eine davon schrieb ich vor 15 Jahren zum Setup von Windows-Embedded 
Terminals in &lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_Basic_Script&quot;&gt;VBScript&lt;/a&gt;.&lt;br /&gt;
Der Zweck: Das Script soll mit Admin-Rechten laufen und diese einfordern,
wenn sie noch nicht vorhanden sind.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Mein Code sah so aus:&lt;/p&gt;

&lt;div class=&quot;language-vb highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;Public Function RunElevated()
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;  Const ElevationFlag = &amp;quot;E_L_E_V_A_T_E_D&amp;quot;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  Dim i
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  Dim strArgs
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;  strArgs = &amp;quot;&amp;quot;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  For i = 0 To WScript.Arguments.Length - 1
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;    If (WScript.Arguments(i) = ElevationFlag) Then
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;      RunElevated = True
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;      Exit Function
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;    End If
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;    strArgs = strArgs &amp;amp; &amp;quot; &amp;quot;&amp;quot;&amp;quot; &amp;amp; WScript.Arguments(i) &amp;amp; &amp;quot;&amp;quot;&amp;quot;&amp;quot;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;  Next
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;  Dim sysShell
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;  Set sysShell = CreateObject(&amp;quot;Shell.Application&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;  Call sysShell.ShellExecute(&amp;quot;wscript.exe&amp;quot;, &amp;quot;&amp;quot;&amp;quot;&amp;quot; &amp;amp; _
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;    WScript.ScriptFullName &amp;amp; &amp;quot;&amp;quot;&amp;quot;&amp;quot; &amp;amp; strArgs &amp;amp; &amp;quot; &amp;quot; &amp;amp; _
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;    ElevationFlag, &amp;quot;&amp;quot;, &amp;quot;runas&amp;quot;, 1)    
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  RunElevated = False
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n21&quot; name=&quot;n21&quot;&gt;21&lt;/a&gt;&lt;/span&gt;End Function
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n22&quot; name=&quot;n22&quot;&gt;22&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n23&quot; name=&quot;n23&quot;&gt;23&lt;/a&gt;&lt;/span&gt;Public Sub Main()
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n24&quot; name=&quot;n24&quot;&gt;24&lt;/a&gt;&lt;/span&gt;  ......
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n25&quot; name=&quot;n25&quot;&gt;25&lt;/a&gt;&lt;/span&gt;End Sub
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n26&quot; name=&quot;n26&quot;&gt;26&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n27&quot; name=&quot;n27&quot;&gt;27&lt;/a&gt;&lt;/span&gt;If RunElevated() Then
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n28&quot; name=&quot;n28&quot;&gt;28&lt;/a&gt;&lt;/span&gt;  Call Main()
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n29&quot; name=&quot;n29&quot;&gt;29&lt;/a&gt;&lt;/span&gt;End If
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Weil ein Script nicht weiß, ob es mit “erhöhten (=Admin-) Rechten”
oder ohne gestartet wurde, startet es sich selbst mit einem
“geheimen” Parameter neu und diesmal mit den notwendigen Rechten.&lt;/p&gt;

&lt;p&gt;Wird die Funktion&lt;br /&gt;
&lt;code&gt;ShellExecute(file, arguments, directory, operation, show)&lt;/code&gt; mit
dem &lt;code&gt;operation&lt;/code&gt; Parameter &lt;code&gt;runas&lt;/code&gt; aufgerufen, übernimmt die Shell
die Anzeige des üblichen Dialogs für erhöhte Rechte, oder startet
das Programm direkt, wenn die notwendigen Rechte schon vorhanden
waren.&lt;/p&gt;

&lt;p&gt;Beim ersten Aufruf startet sich das Script somit selbst mit
erhöhten Rechten und fügt den geheimen Parameter an.&lt;br /&gt;
Der zweite Aufruf (mit den höheren Rechten) erkennt den geheimen
Parameter und springt dann zum eigentlich gewünschten Scriptcode.&lt;/p&gt;

&lt;h3 id=&quot;apropos-runas&quot;&gt;Apropos runas&lt;/h3&gt;

&lt;p&gt;Dass das Execute-Verb &lt;code&gt;runas&lt;/code&gt; die UAC auffordert, den Zielprozess
mit erhöhten Rechten zu starten, ist heute unter der
&lt;a href=&quot;https://learn.microsoft.com/en-us/windows/win32/api/shellapi/nf-shellapi-shellexecutea&quot;&gt;ShellExecute&lt;/a&gt;
Funktion dokumentiert.&lt;br /&gt;
Im Jahr 2010 mit den Platform-SDKs von 2008 fehlte diese Info
jedoch und so war eine lange Suche im Netz notwendig, bis ich
den Hinweis gefunden hatte.&lt;/p&gt;

&lt;p&gt;Wenn man den neuen Prozess nicht per Pipes fernsteuern können
muss, ist &lt;code&gt;ShellExecute(runas)&lt;/code&gt; die übliche Methode mehr
Recht zu erhalten. Die Alternative mit den Login-APIs
ist recht kompliziert und funktioniert auch nicht in jedem
Kontext.&lt;/p&gt;

&lt;p&gt;Hier hat mir also ein Script vorgezeigt, wie meine nachfolgenden
&lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B&quot;&gt;C++&lt;/a&gt; Implementierungen auszusehen hatten 
und haben.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Hier lobe ich mir &lt;a href=&quot;https://de.wikipedia.org/wiki/Sudo&quot;&gt;sudo&lt;/a&gt; und 
&lt;a href=&quot;https://man.openbsd.org/doas&quot;&gt;doas&lt;/a&gt; aus der 
&lt;a href=&quot;https://de.wikipedia.org/wiki/POSIX&quot;&gt;POSIX&lt;/a&gt; Welt.&lt;br /&gt;
Man kann jedes Programm und jedes Script einfach mit &lt;code&gt;root&lt;/code&gt;
Rechten starten und braucht keine Umwege.&lt;/p&gt;

&lt;p&gt;Das Script entstand um sowohl von der Konsole mit Parametern
oder direkt per Doppelklick vom Explorer gestartet werden zu
können und funktionierte bei allen damaligen Installationen.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Den Code hätte man etwas einfacher gestalten können 
… aber hey, es funktioniert.&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>GIF Animationen</title>
   <link href="https://www.opengate.at/blog/2025/03/gif-animation/"/>
   <published>2025-03-09T12:00:00+01:00</published>
   <updated>2025-03-09T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2025/03/gif-animation</id>
   <category term="devel" />
   <summary type="text">Wir alle mögen bewegte Bilder. Doch fette Medien-Inhalte kann ich im GATE
Projekte jetzt nicht einarbeiten … dafür war das Projekt nicht gedacht.

Aber im kleinen Stil kann man schon ein bisschen was bewegen, daher lautet
die Frage heute:


  Wie lädt man eigentlich animierte 
GIF
Dateien mit giflib ?


</summary>
   <content type="html">&lt;p&gt;Wir alle mögen bewegte Bilder. Doch fette Medien-Inhalte kann ich im GATE
Projekte jetzt nicht einarbeiten … dafür war das Projekt nicht gedacht.&lt;/p&gt;

&lt;p&gt;Aber im kleinen Stil kann man schon ein bisschen was bewegen, daher lautet
die Frage heute:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Wie lädt man eigentlich animierte 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Graphics_Interchange_Format&quot;&gt;GIF&lt;/a&gt;
Dateien mit &lt;code&gt;giflib&lt;/code&gt; ?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Die &lt;code&gt;giflib&lt;/code&gt; ist - woher kenne ich das bloß - eine Low+High-level Bibliothek.
Sie bietet primitive Funktionen zum Laden und Speichern einzelner Blöcke an,
und hat dann noch ein paar einfache Alleskönner-Funktionen, die einem die 
Kleinarbeit wieder abnehmen.&lt;/p&gt;

&lt;p&gt;Animierte GIFs sind einfach mehrere GIF-Bilder in einer Datei, die noch mit
einer Wartelänge verknüpft sind. Und die &lt;code&gt;giflib&lt;/code&gt; lädt das alles problemlos
in den Speicher.&lt;/p&gt;

&lt;h3 id=&quot;auf-den-freien-speicher-kommt-es-an&quot;&gt;Auf den freien Speicher kommt es an&lt;/h3&gt;

&lt;p&gt;Jetzt wäre die Sache recht einfach, wenn mein einfach nur &lt;code&gt;DGifSlurp()&lt;/code&gt;
aufruft und dann auf alle Bilder über das &lt;code&gt;SavedImages&lt;/code&gt; Array in der
&lt;code&gt;GifFileType&lt;/code&gt; Instanz zugreifen würde.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/MS-DOS&quot;&gt;DOS&lt;/a&gt; kann aber nur 64 KB in einem Segment 
allokieren und nach 9 Segmenten (Bildern) ist dann Schluss.&lt;/p&gt;

&lt;p&gt;Es macht also Sinn, den GIF-Datenstrom selbst zu verwalten und die 
fertigen Bilder gleich auszugeben und nicht zu speichern.&lt;/p&gt;

&lt;h3 id=&quot;gifs-stück-für-stück-lesen&quot;&gt;GIFs Stück für Stück lesen&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;DGifOpen()&lt;/code&gt; liest bereits den Header aus dem GIF Stream und gibt uns
Infos über die Auflösung des Gesamtbildes.
Nun wird per &lt;code&gt;DGifGetRecordType()&lt;/code&gt; festgestellt, welcher Block folgt.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Das ist entweder ein &lt;code&gt;EXTENSION_RECORD_TYPE&lt;/code&gt; den man dann per
&lt;code&gt;DGifGetExtension()&lt;/code&gt; und &lt;code&gt;DGifExtensionToGCB()&lt;/code&gt; ausliest um an Infos wie
die transparente Farbe oder die Frame-Delay-Time zu kommen.&lt;/li&gt;
  &lt;li&gt;Oder man bekommt einen &lt;code&gt;IMAGE_DESC_RECORD_TYPE&lt;/code&gt;, wo man per 
&lt;code&gt;DGifGetImageDesc()&lt;/code&gt; Infos zum Frame einholt und dann für jede Pixelzeile
ein &lt;code&gt;DGifGetLine()&lt;/code&gt; ausführt um an die Pixels zu kommen.&lt;/li&gt;
  &lt;li&gt;Der letzte Recordtype wäre dann ein &lt;code&gt;TERMINATE_RECORD_TYPE&lt;/code&gt; mit dem 
die Datei endet.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Das heißt also, man führt das Record-Lesen in einer Schleife aus, kombiniert
immer einen &lt;code&gt;EXTENSION_RECORD&lt;/code&gt; mit einem &lt;code&gt;IMAGE_DESC_RECORD&lt;/code&gt; zu einem Frame
und “zeichnet” ihn auf das Ausgabegerät. Dann wartet man die gewünschte
Delay-Time ab und setzt so lange fort, bis kein Frame mehr kommt.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Die gesamte Prozedur lernt man, wenn man sich die Codes von der Highlevel
Funktion &lt;code&gt;DGifSlurp()&lt;/code&gt; ansieht, die das gleiche macht und alle Daten in
allokierte Speicherblöcke schreibt.&lt;/p&gt;

&lt;p&gt;Mit der Eigenentwicklung schafft man nun die Möglichkeiten kleine 
Animationen auch unter &lt;code&gt;DOS&lt;/code&gt; direkt von der Datei ins Video-RAM zu laden.
(Die entsprechende Farbraumkonvertierung kommt natürlich auch noch hinzu.)&lt;/p&gt;

&lt;p&gt;Ich habe das Beispiel mal als Demo-Tool mit Namen &lt;code&gt;aniplay&lt;/code&gt; gespeichert.&lt;/p&gt;

&lt;p&gt;Für die Zukunft sehe ich aber ein viel interessanteres Projekt:&lt;br /&gt;
Das Erstellen von animierten GIFs z.B. von kürzeren Bildschirmaufnahmen,
denn Textfenster ändern sich recht wenig (wenn kein echtes Video läuft),
und das kann ein GIF vernünftig einfangen.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Radxa Rock 5 ITX</title>
   <link href="https://www.opengate.at/blog/2025/03/radxa-itx/"/>
   <published>2025-03-02T12:00:00+01:00</published>
   <updated>2025-03-02T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2025/03/radxa-itx</id>
   <category term="hardware" />
   <summary type="text">Ich besitze viele ARM-basierte Boards. 
Raspberry Pi Modelle, aber auch
viele OrangePi und andere *Pi Alternativen.

Doch all dieser Kleinkram lässt sich nicht für den täglich Gebrauch nutzen.

Und dann kam endlich ein richtiges Mainboard mit dem Rock 5 ITX.

</summary>
   <content type="html">&lt;p&gt;Ich besitze viele ARM-basierte Boards. 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Raspberry_Pi&quot;&gt;Raspberry Pi&lt;/a&gt; Modelle, aber auch
viele OrangePi und andere *Pi Alternativen.&lt;/p&gt;

&lt;p&gt;Doch all dieser Kleinkram lässt sich nicht für den täglich Gebrauch nutzen.&lt;/p&gt;

&lt;p&gt;Und dann kam endlich ein richtiges Mainboard mit dem &lt;code&gt;Rock 5 ITX&lt;/code&gt;.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/rock5itx_box.jpg&quot; alt=&quot;Radxa Rock5 ITX Box&quot; /&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Auf die Größe kommt es an.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Und mit der Größe verbunden ist auch die weitere Peripherie.&lt;br /&gt;
Denn eine richtige Festplatte konnte man beim Raspberry PI lange Zeit nur
über holprige Umwege ansprechen. Booten konnte man davon sowieso nicht.&lt;/p&gt;

&lt;p&gt;Und dann ist da noch die Platzfrage. Die Chipkarten-SoCs sehen zwar kompakt
aus, jedoch haben sie gar nicht den nötigen Platz um Steckplätze und 
Standardschnittstellen zu etablieren.&lt;/p&gt;

&lt;p&gt;Am Ende fällt dann das Gerät permanent um oder wird per Kabel versehentlich
durch das Zimmer gezogen, weil es eben nicht die nötige “Größe” eines
echten PC’s hat.&lt;/p&gt;

&lt;h3 id=&quot;ein-itx-board-mit-arm-prozessor&quot;&gt;Ein ITX-Board mit ARM Prozessor&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/rock5itx_board.jpg&quot; alt=&quot;Radxa Rock5 ITX&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Radxa&lt;/code&gt; hat es richtig gemacht. Sie haben ihr Wissen und die Chips von 
ihren kleinen SoCs genommen und auf ein Standard-ITX Board verfrachtet.&lt;br /&gt;
Hier passen neben einem Standard-ATX-Anschluss auch ein ordentlicher 
Kühlkörper, mehrere SATA-Ports, zwei “richtige” HDMI Ausgänge 
(also kein Mini/Micro) und alle möglichen Front-Panel-Anschlüsse, wie wir
sie von jedem üblichen PC-Mainboard kennen.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/rock5itx_fan.jpg&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Erstmals konnte ich also ein ARM-Mainboard in ein richtiges PC-Gehäuse 
einbauen, unter den Schreibtisch stellen und als tägliches Arbeitsgerät 
einsetzen.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;… und soetwas liebe ich einfach nur!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/rock5itx_back.jpg&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Besonders wichtig ist der Preis: Schon ab 120 Euro erhält man eine 4 GB
Variante und mein Board mit 16 GB kam auf etwa 180 Euro.
(Tatsächlich ist der fest verbaute RAM der einzige Nachteil, denn ein 
Nachrüsten gibt es hier leider nicht.)&lt;/p&gt;

&lt;p&gt;Dafür erhält man aber mit 8 Kernen (4x 1.8 und 4x 2.4 GHz) eine Power,
die einen ebenso günstigen Intel NM100 übertrifft.&lt;/p&gt;

&lt;p&gt;Das Board lässt sich mit einem 24-poligen ATX-Anschluss bestromen, unterstützt
aber auch eine 12 Volt Buchse und kann direkt von einem handelsüblichen 
Netzteil gespeist werden.&lt;/p&gt;

&lt;p&gt;2 Gigabit-Ethernet Ports, 2 USB-2, 4 USB-3 Ports und 1 USB-C Port, sowie eine
Audio In- und Out- Klinkenbuchse runden das Back-Panel neben den bereits 
erwähnten HDMI-Ports ab.&lt;/p&gt;

&lt;p&gt;Ein Passiv-Betrieb ist laut Hersteller zwar möglich, dennoch ist für 
Rechenintensive Aufgaben ein Kühlung vorgesehen und so nahm ich auch gleich
den von &lt;code&gt;Radxa&lt;/code&gt; angebotenen Kühler dazu, der über dem CPU-Block auf dem
Mainboard angeschraubt werden kann.&lt;/p&gt;

&lt;h3 id=&quot;software&quot;&gt;Software&lt;/h3&gt;

&lt;p&gt;Ein vorbereitetes Debian-12 Image steht 
&lt;a href=&quot;https://docs.radxa.com/en/rock5/rock5itx/download&quot;&gt;zum Download&lt;/a&gt;
bereit und kann direkt auf eine SD-Karte für den ersten Boot übertragen werden.&lt;/p&gt;

&lt;p&gt;Der Standard Bootloader auf dem Board liegt im SPI Speicher und unterstützt 
bereits den Boot von SD-Karten und SATA.&lt;br /&gt;
Ich konnte also das Linux Image von der SD-Karte auch einfach auf eine
Festplatte übertragen, anschließen und davon booten.&lt;/p&gt;

&lt;p&gt;Aber wenn das nicht zum Erfolg führt, bietet &lt;code&gt;Radxa&lt;/code&gt; ihr eigenes Tool&lt;br /&gt;
&lt;code&gt;rsetup&lt;/code&gt; im Linux Image an, welches den Bootloader aktualisieren und neu
auf das Board flashen kann.&lt;br /&gt;
Sollte auch das gebrochen sein, gibt es noch die Möglichkeit die Firmware
remote über USB aufzuspielen, was aber bei mir nicht nötig war.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/rock5itx_rsetup.png&quot; alt=&quot;Radxa Rock5 ITX RSetup&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Raxda&lt;/code&gt; hat das Debian Image so angepasst, dass &lt;code&gt;apt&lt;/code&gt; auch Updates von
den &lt;code&gt;Raxda&lt;/code&gt; Servern beziehen kann, wo angepasste Versionen von Kernel und
Treiber vorliegen. Ein &lt;code&gt;apt update &amp;amp;&amp;amp; apt upgrade&lt;/code&gt; erledigt also bereits
alles Notwendige um das System aktuell zu halten.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Von all den ARM Boards, die ich bisher besessen hatte ist das Rock5-ITX
schon alleine deshalb das beste, weil es endlich ein “richtiger PC” ist.
Darauf habe ich viele Jahre gewartet und ich hoffe, dass noch viele weitere
Hersteller den Schritt in Richtung Standard-PC-Board gehen.&lt;br /&gt;
(Unter der Marke &lt;code&gt;Milk&lt;/code&gt; gibt es das ja auch schon, allerdings teurer.)&lt;/p&gt;

&lt;p&gt;Software-Entwicklung mit allen Sprachen unter &lt;code&gt;VSCode&lt;/code&gt;, Webbrowsing mit
&lt;code&gt;Chromium&lt;/code&gt; und &lt;code&gt;Firefox&lt;/code&gt;, Dokumente schreiben mit &lt;code&gt;LibreOffice&lt;/code&gt; … all das
läuft hoch performant und flüssig und macht dieses Board zur ersten
richtigen Alternative zu einem X86 System.&lt;/p&gt;

&lt;p&gt;Einen Mangel muss ich leider noch anmerken: Content-Protection.
Leider gibt es bisher keine fertigen Bibliotheken für geschützten Content
in Web-Browsern für ARM64.&lt;br /&gt;
Und genau deshalb laufen dann &lt;code&gt;Netflix&lt;/code&gt;, &lt;code&gt;Disney+&lt;/code&gt; und andere Streaming-Dienste
nicht auf dieser Plattform. Freie Dienste von &lt;code&gt;YouTube&lt;/code&gt; bis &lt;code&gt;PeerTube&lt;/code&gt; sind 
aber in bester Qualität zu genießen.&lt;/p&gt;

&lt;p&gt;Ich hoffe, dass die wenigen Mankos bei ARM64 Bibliotheken schnell behoben 
sind und freue mich nun auf das Arbeiten mit meinem neuen Entwickler-PC
unter Linux.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>cppcheck</title>
   <link href="https://www.opengate.at/blog/2025/02/cppcheck/"/>
   <published>2025-02-23T12:00:00+01:00</published>
   <updated>2025-02-23T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2025/02/cppcheck</id>
   <category term="software" />
   <summary type="text">
  Der Compiler ist nicht genug!


Nicht erst seit der Rust
Bedrohung braucht C++ Code jedes 
Codereview, das es kriegen kann.

cppcheck war und ist “das” 
Standard-Tool, dass hier den Anfang macht.

</summary>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;Der Compiler ist nicht genug!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Nicht erst seit der &lt;a href=&quot;https://de.wikipedia.org/wiki/Rust_(Programmiersprache)&quot;&gt;Rust&lt;/a&gt;
Bedrohung braucht &lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B&quot;&gt;C++ Code&lt;/a&gt; jedes 
Codereview, das es kriegen kann.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Cppcheck&quot;&gt;cppcheck&lt;/a&gt; war und ist “das” 
Standard-Tool, dass hier den Anfang macht.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Statische Code-Analyse hilft Fehler zu erkennen, die Entwicklung und
Compiler nicht als solche ansehen.&lt;br /&gt;
Es macht also Sinn den eigenen Code durch möglichst viele Tests zu jagen
und Fehlermeldung und Hinweise einzusammeln.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;cppcheck&lt;/code&gt; erkennt viele Formfehler wie uninitialisierte Variablen, oder
“seltsam” aussehende Blockverzweigungen und noch vieles mehr.&lt;br /&gt;
Ich habe das Tool daher als &lt;code&gt;CMake&lt;/code&gt;-Custom-Target eingebaut, womit ich es
während der Entwicklung immer wieder direkt per &lt;code&gt;VSCode&lt;/code&gt;-Klick ausführen
kann um Verbesserungen oder Verschlechterungen in neuem Code zu erkennen.&lt;/p&gt;

&lt;h3 id=&quot;cppcheck-als-cmake-target&quot;&gt;cppcheck als CMake Target&lt;/h3&gt;

&lt;p&gt;Ein Code sagt mehr als tausend Worte:&lt;/p&gt;

&lt;div class=&quot;language-cmake highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;if(CMAKE_HOST_WIN32)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  find_program(CPPCHECK_APP
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;    NAMES &amp;quot;cppcheck&amp;quot;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;    PATHS &amp;quot;C:\\Program Files\\Cppcheck&amp;quot; &amp;quot;C:\\Program Files (x86)\\Cppcheck&amp;quot; &amp;quot;C:\\Cppcheck&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;else()
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  find_program(CPPCHECK_APP cppcheck)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;endif()
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;if(CPPCHECK_APP)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;  option(CPPCHECK_CMAKE_TARGETS &amp;quot;Adds a CPPCHECK targets to analyze code quality&amp;quot; ON)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;  set(CPPCHECK_SOURCE_DIR &amp;quot;${CMAKE_SOURCE_DIR}&amp;quot; CACHE FILEPATH &amp;quot;CPPCHECK source scan directory&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;  set(CPPCHECK_RESULTS_XML_FILE &amp;quot;${CMAKE_BINARY_DIR}/cppcheck_results.xml&amp;quot; CACHE FILEPATH &amp;quot;CPPCHECK results output file&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;  set(CPPCHECK_RESULTS_HTML_DIR &amp;quot;${CMAKE_BINARY_DIR}/cppcheck_report&amp;quot;  CACHE PATH &amp;quot;CPPCHECK HTML report output directory&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;  if(CPPCHECK_CMAKE_TARGETS)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;    set(CPPCHECK_CMD &amp;quot;${CPPCHECK_APP}&amp;quot; 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;      --enable=all --language=c++ --std=c++11
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n21&quot; name=&quot;n21&quot;&gt;21&lt;/a&gt;&lt;/span&gt;      --suppress=cstyleCast
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n22&quot; name=&quot;n22&quot;&gt;22&lt;/a&gt;&lt;/span&gt;      --xml --xml-version=2 -j 8 . 2&amp;gt; &amp;quot;${CPPCHECK_RESULTS_XML_FILE}&amp;quot;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n23&quot; name=&quot;n23&quot;&gt;23&lt;/a&gt;&lt;/span&gt;    )
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n24&quot; name=&quot;n24&quot;&gt;24&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n25&quot; name=&quot;n25&quot;&gt;25&lt;/a&gt;&lt;/span&gt;    ## add CPPCHECK process execution target
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n26&quot; name=&quot;n26&quot;&gt;26&lt;/a&gt;&lt;/span&gt;    add_custom_target(cppcheck_execute
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n27&quot; name=&quot;n27&quot;&gt;27&lt;/a&gt;&lt;/span&gt;      COMMAND ${CPPCHECK_CMD}
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n28&quot; name=&quot;n28&quot;&gt;28&lt;/a&gt;&lt;/span&gt;      WORKING_DIRECTORY &amp;quot;${CPPCHECK_SOURCE_DIR}&amp;quot;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n29&quot; name=&quot;n29&quot;&gt;29&lt;/a&gt;&lt;/span&gt;      COMMENT &amp;quot;Running cppcheck...&amp;quot;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n30&quot; name=&quot;n30&quot;&gt;30&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;    )
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n31&quot; name=&quot;n31&quot;&gt;31&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n32&quot; name=&quot;n32&quot;&gt;32&lt;/a&gt;&lt;/span&gt;    file(MAKE_DIRECTORY &amp;quot;${CPPCHECK_RESULTS_HTML_DIR}&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n33&quot; name=&quot;n33&quot;&gt;33&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n34&quot; name=&quot;n34&quot;&gt;34&lt;/a&gt;&lt;/span&gt;    set(CPPCHECK_REPORT_CMD cppcheck-htmlreport 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n35&quot; name=&quot;n35&quot;&gt;35&lt;/a&gt;&lt;/span&gt;      &amp;quot;--title=${PROJECT_NAME}&amp;quot; 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n36&quot; name=&quot;n36&quot;&gt;36&lt;/a&gt;&lt;/span&gt;      --source-dir=. 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n37&quot; name=&quot;n37&quot;&gt;37&lt;/a&gt;&lt;/span&gt;      &amp;quot;--file=${CPPCHECK_RESULTS_XML_FILE}&amp;quot; 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n38&quot; name=&quot;n38&quot;&gt;38&lt;/a&gt;&lt;/span&gt;      &amp;quot;--report-dir=${CPPCHECK_RESULTS_HTML_DIR}&amp;quot;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n39&quot; name=&quot;n39&quot;&gt;39&lt;/a&gt;&lt;/span&gt;    )
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n40&quot; name=&quot;n40&quot;&gt;40&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n41&quot; name=&quot;n41&quot;&gt;41&lt;/a&gt;&lt;/span&gt;    ## add CPPCHECK HTML report generation target
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n42&quot; name=&quot;n42&quot;&gt;42&lt;/a&gt;&lt;/span&gt;    add_custom_target(cppcheck_generate_report
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n43&quot; name=&quot;n43&quot;&gt;43&lt;/a&gt;&lt;/span&gt;      COMMAND ${CPPCHECK_REPORT_CMD}
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n44&quot; name=&quot;n44&quot;&gt;44&lt;/a&gt;&lt;/span&gt;      WORKING_DIRECTORY &amp;quot;${CPPCHECK_SOURCE_DIR}&amp;quot;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n45&quot; name=&quot;n45&quot;&gt;45&lt;/a&gt;&lt;/span&gt;      COMMENT &amp;quot;Generating cppcheck html report&amp;quot;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n46&quot; name=&quot;n46&quot;&gt;46&lt;/a&gt;&lt;/span&gt;    )
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n47&quot; name=&quot;n47&quot;&gt;47&lt;/a&gt;&lt;/span&gt;  endif(CPPCHECK_CMAKE_TARGETS)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n48&quot; name=&quot;n48&quot;&gt;48&lt;/a&gt;&lt;/span&gt;endif()
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Hier werden zwei zusätzlich Targets angelegt:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;cppcheck_execute&lt;/code&gt; führt &lt;code&gt;cppcheck&lt;/code&gt; aus und generiert die XML-Datei mit 
gefundenen Problemen.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;cppcheck_generate_report&lt;/code&gt; lässt über das Tool &lt;code&gt;cppcheck-htmlreport&lt;/code&gt; aus
der XML Datei eine HTML Seite generieren.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Natürlich müssen beide Tools im Vorfeld im System installiert sein, damit
sie auch gefunden und ausgeführt werden können.&lt;/p&gt;

&lt;p&gt;In Visual Studio Code erscheinen die beiden Targets im &lt;code&gt;CMake&lt;/code&gt; Fenster im
&lt;code&gt;Project Outline&lt;/code&gt; und können jeweils per Klick gestartet werden.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Natürlich könnte man die beiden Tool-Ausführungen in ein Custom-Target 
zusammenfassen, um nur noch einen Klick zu brauchen.&lt;br /&gt;
Der Hintergrund für Trennung war Windows, denn die Standard-Installation
von &lt;code&gt;cppcheck&lt;/code&gt; führt dort &lt;code&gt;html-report&lt;/code&gt; Tool nicht mit. Linux Paketmanager 
installieren aber immer beide Tools.&lt;/p&gt;

&lt;p&gt;So konnte ich dann entscheiden, ob ich nur den ersten oder beide Schritte
ausführen wollte.&lt;/p&gt;

&lt;p&gt;Die Ergebnisse auf der HTML Seite haben mir schon oft Grund für kleine
Änderungen und Verbesserungen gegeben.&lt;br /&gt;
Folglich sollte eine &lt;code&gt;cppcheck&lt;/code&gt; Auswertung in keinem Projekt mehr fehlen.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>PinePhone PostmarketOS Update</title>
   <link href="https://www.opengate.at/blog/2025/02/postmarket-update/"/>
   <published>2025-02-16T12:00:00+01:00</published>
   <updated>2025-02-16T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2025/02/postmarket-update</id>
   <category term="hardware" /><category term="software" />
   <summary type="text">Um mein PinePhone mit einem neuen 
postmarketOS Image auszustatten lud ich
mir früher ein Installer-Image auf eine SD-Karte, legte diese ein, dann 
startete beim Boot ein Setup welches das Image auf die eMMC des Telefons 
übertrug, und fertig.

Aber jetzt ist alles anders.

</summary>
   <content type="html">&lt;p&gt;Um mein &lt;a href=&quot;https://de.wikipedia.org/wiki/PinePhone&quot;&gt;PinePhone&lt;/a&gt; mit einem neuen 
&lt;a href=&quot;https://en.wikipedia.org/wiki/PostmarketOS&quot;&gt;postmarketOS&lt;/a&gt; Image auszustatten lud ich
mir früher ein Installer-Image auf eine SD-Karte, legte diese ein, dann 
startete beim Boot ein Setup welches das Image auf die &lt;code&gt;eMMC&lt;/code&gt; des Telefons 
übertrug, und fertig.&lt;/p&gt;

&lt;p&gt;Aber jetzt ist alles anders.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Mein letztes Images aus dem Jahr 2023 ist schon etwas angestaubt und weil ich
letztens selten zum Linux-Telefon gegriffen habe, fiel mir das gar nicht auf.&lt;/p&gt;

&lt;p&gt;Es ist Zeit das System zu aktualisieren.&lt;/p&gt;

&lt;h3 id=&quot;kein-installer-image-mehr-vorhanden&quot;&gt;Kein Installer-Image mehr vorhanden&lt;/h3&gt;

&lt;p&gt;Die neuen &lt;code&gt;postmarketOS&lt;/code&gt; Images lassen sich weiter problemlos auf die SD-Karte
übertragen und beim Boot erscheint sofort das neue OS.&lt;br /&gt;
Doch es gibt keinen Installer, der es von der SD-Karte zur eingebauten 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Multimedia_Card#eMMC&quot;&gt;eMMC&lt;/a&gt; 
überträgt und somit bootet man immer von der langsamen SD-Karte.&lt;/p&gt;

&lt;p&gt;Die Recherche ergab, dass mit Ende 2023 diese alten Installer-Images 
eingestellt wurden und vorläufig nicht mehr angeboten werden.&lt;/p&gt;

&lt;p&gt;Doch eine Alternative ist die Installation via &lt;code&gt;JumpDrive&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;per-jumpdrive-über-usb-zum-emmc-medium&quot;&gt;Per JumpDrive über USB zum EMMC Medium&lt;/h3&gt;

&lt;p&gt;Ein &lt;a href=&quot;https://github.com/dreemurrs-embedded/Jumpdrive/&quot;&gt;JumpDrive&lt;/a&gt; Image ist
ein kleines bootfähiges SD-Karten Image für PinePhones 
(aber nicht PinePhone PRO), welches nur einen USB-Dienst hochfährt, der alle
Medien per USB als Laufwerk anbietet.&lt;/p&gt;

&lt;p&gt;Man überträgt also die &lt;code&gt;pine64-pinephone.img.xz&lt;/code&gt; mit Tools wie &lt;code&gt;rufus&lt;/code&gt; unter
Windows oder &lt;code&gt;dd&lt;/code&gt; unter Linux auf eine SD-Karte, schiebt diese dann ins 
PinePhone und startet es.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/pinephone-sdcard.jpg&quot; alt=&quot;Pinephone SD card&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Sobald das Bild mit dem verbundenen USB-Kabel erscheint, schließt man sein
Telefon an den PC via USB-Kabel an und schon erkennt dieser zwei neue
Laufwerke.&lt;br /&gt;
Das eine ist die eingelegte SD-Karte selbst, das andere ist das eMMC Modul.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/pinephone-jumpdrive.jpg&quot; alt=&quot;Pinephone JumpDrive&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Nun kann man erneut sein Flash-Tool (also wieder &lt;code&gt;rufus&lt;/code&gt; oder &lt;code&gt;dd&lt;/code&gt;) einsetzen
um das postmarketOS-Image direkt auf die eMMC zu übertragen.&lt;/p&gt;

&lt;p&gt;Ist das erledigt, kann man das Telefon abschalten, die SD-Karte entfernen
und anschließend das PinePhone neu starten.&lt;/p&gt;

&lt;p&gt;Und schon hat man die neueste OS-Version vor sich.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ich gebe zu, ich mochte die Installer-Variante mehr. Es ist für mich logisch
ein Installations-Medium anzulegen und von diesem zu installieren.&lt;br /&gt;
Oder man hat im von SD gebooteten Livesystem ein “Copy-To-eMMC” Tool.&lt;/p&gt;

&lt;p&gt;Dass man &lt;code&gt;JumpDrive&lt;/code&gt; braucht um dann das richtige Image zu übertragen,
funktioniert zwar wunderbar, fühlt sich aber dennoch ungewohnt an.&lt;/p&gt;

&lt;p&gt;Wie auch immer … am Ende habe ich frische Software am Linux-Telefon
und nach etwas Suchen fand ich auch das Standard-Passwort mit der
Zahlen-Kombi &lt;code&gt;147147&lt;/code&gt;, um den Lockscreen überwinden zu können.&lt;/p&gt;

&lt;p&gt;Alles in allem gefällt mir aber sehr, dass das PinePhone, welches inzwischen
nicht mehr produziert wird immer noch brav mit Software-Updates versorgt wird.&lt;/p&gt;

&lt;p&gt;Es gibt auch eine Prozedur um ein Update vom Telefon aus herunterzuladen und
auszurollen … doch da hier Tipparbeit an der Konsole notwendig ist, 
ist die SD-Karte-Methode aus meiner Sicht praktischer.&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>Odroid X2</title>
   <link href="https://www.opengate.at/blog/2025/02/odroid-x2/"/>
   <published>2025-02-09T12:00:00+01:00</published>
   <updated>2025-02-09T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2025/02/odroid-x2</id>
   <category term="hardware" />
   <summary type="text">Vor 12 Jahren wollte meine damalige Firma weg von X86 und Windows Embedded
hin zu ARM und 
Linux.
Und zufällig habe ich heute in meiner Rumpelkiste genau das Development-Board
gefunden, welches fast zum Produkt geworden wäre:
Ein Odroid X2

</summary>
   <content type="html">&lt;p&gt;Vor 12 Jahren wollte meine damalige Firma weg von X86 und Windows Embedded
hin zu &lt;a href=&quot;https://de.wikipedia.org/wiki/ARM-Architektur&quot;&gt;ARM&lt;/a&gt; und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt;.&lt;br /&gt;
Und zufällig habe ich heute in meiner Rumpelkiste genau das Development-Board
gefunden, welches fast zum Produkt geworden wäre:&lt;br /&gt;
Ein &lt;a href=&quot;https://de.wikipedia.org/wiki/ODROID&quot;&gt;Odroid&lt;/a&gt; X2&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Im Jahr 2013 war der Raspberry PI 1 mit seinem einen Kern mit 700 MHz zwar
toll um “ein bisschen” Linux “zu machen” … aber für richtige 
Rechenoperationen war er deutlich zu schwach.&lt;/p&gt;

&lt;p&gt;Das galt besonders für Bildverarbeitung welche damals von Interesse war.
Also machten sich Kollegen auf die Suche nach anderen kleinen SoC Boards
und stießen auf die &lt;code&gt;Odroid&lt;/code&gt; Serie des Koreanischen Unternehmens 
&lt;a href=&quot;https://www.hardkernel.com/&quot;&gt;Hardkernel&lt;/a&gt;&lt;/p&gt;

&lt;h3 id=&quot;der-odroid-x2&quot;&gt;Der ODROID X2&lt;/h3&gt;

&lt;p&gt;Die 4x 1.7 GHz ARM Cortex-A9 CPU ließ den RasPi klar hinter sich und konnte
auch mit 2 GB RAM und einem Mali-400 3D Grafikchip punkten.&lt;/p&gt;

&lt;p&gt;Nicht ganz unerheblich war auch die Möglichkeit mit einem &lt;code&gt;eMMC&lt;/code&gt; Chip zu 
arbeiten, die in Sachen Performance die üblichen MicroSD Karten überholten,
was bei häufigen Zugriffen durchaus ein Thema war.&lt;/p&gt;

&lt;p&gt;Wir nutzten damals ein angepasstes Ubuntu und ich erinnere mich, dass dieses
aus dem Hause &lt;a href=&quot;https://www.linaro.org&quot;&gt;linaro.org&lt;/a&gt; stammte.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/odroid-x2.jpg&quot; alt=&quot;Odroid-X2&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Heute ist das Board bereits lange “Geschichte”, doch vielleicht findet man
in den Archiven der Hersteller sogar noch die Basis, die wir damals nutzten:&lt;br /&gt;
&lt;a href=&quot;https://releases.linaro.org/archive/&quot;&gt;releases.linaro.org/archive&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/odroid-x2-back.jpg&quot; alt=&quot;Odroid-X2-back&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;software-update&quot;&gt;Software Update&lt;/h3&gt;

&lt;p&gt;Um zu sehen, ob das Board noch einsatztauglich ist, habe ich im Archiv
von &lt;a href=&quot;https://wiki.odroid.com/old_product/odroid-x_u_q/x2_release_linux_ubuntu&quot;&gt;wiki.odroid.com&lt;/a&gt;
gesucht und fand sogar ein aktualisiertes Ubuntu 14.04 Image, doch die
Downloads waren alle nicht mehr verfügbar.&lt;/p&gt;

&lt;p&gt;Doch über den Dateinamen fand ich das Image-Verzeichnis
&lt;a href=&quot;https://odroid.in/ubuntu_14.04lts/&quot;&gt;odroid.in/ubuntu_14.04lts&lt;/a&gt;
und lud mir unmittelbar das 
&lt;a href=&quot;https://odroid.in/ubuntu_14.04lts/ubuntu-14.04.2lts-lubuntu-odroid-x2-20150224.img.xz&quot;&gt;ubuntu-14.04.2lts-lubuntu-odroid-x2-20150224.img&lt;/a&gt;
Image herunter.&lt;/p&gt;

&lt;p&gt;Das 5 GB große Abbild beinhaltet eine vollständige X11-Umgebung mit Standard
Software. Der interne Name von Ubuntu 14 ist Trusty und als Compiler wird die
alte GCC 4.8 eingesetzt.&lt;/p&gt;

&lt;p&gt;Nach dem üblich &lt;code&gt;apt-get update &amp;amp;&amp;amp; apt-get upgrade&lt;/code&gt; wollte ich auf die nächste
LTS-Version von Ubuntu wechseln. Ubuntu 16.04 ist auch bekannt als Xenial und
so musste ich nur int &lt;code&gt;/etc/apt/sources.list&lt;/code&gt; und in den Unterverzeichnissen mit
weiteren Download-Listen den Token &lt;code&gt;trusty&lt;/code&gt; durch &lt;code&gt;xenial&lt;/code&gt; ersetzen.&lt;/p&gt;

&lt;p&gt;Danach startete ein &lt;code&gt;apt-get update&lt;/code&gt; gefolgt von &lt;code&gt;apt-get dist-upgrade&lt;/code&gt; die
Installation der nächsten OS-Version.&lt;/p&gt;

&lt;p&gt;Doch leider war das ein totaler Fehlschlag und das System war nicht mehr
startbar. Dieses Schicksal erleiden viele ARM-Boards, die keinen neuen
Kernel erhalten und Upgrades auf neue Distributionen daher versagen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ein weiteres Stück Geschichte wird hiermit ein meine Sammlung aufgenommen.
Ich finde es echt schade, dass Linux-Kernel und Distributionen so schnell
das Ende einer Hardware einläuten können.&lt;/p&gt;

&lt;p&gt;Hier sehen wir erst wie unglaublich wertvoll das Raspberry-PI Projekt ist,
welches auch heute noch aktualisierte Software für Hardware von vor über
10 Jahren herausbringt.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Odroid&lt;/code&gt; produziert bis heute neue SoC Boards und stellt damit eine Alternative
zu anderen Herstellern wie &lt;code&gt;Radxa&lt;/code&gt; oder der &lt;code&gt;Orange PI&lt;/code&gt; Familie dar.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>C++ CGI-Plugins am Webserver debuggen</title>
   <link href="https://www.opengate.at/blog/2025/02/cgi-debug/"/>
   <published>2025-02-02T12:00:00+01:00</published>
   <updated>2025-02-02T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2025/02/cgi-debug</id>
   <category term="devel" /><category term="projects" />
   <summary type="text">Man konnte doch schon in den 80er Jahren C-Programme auf Webservern ausführen,
die Webseiten und anderen Schnick-Schnack generierten.

Heute scheint das vergessen, aber es klappt immer noch … mit etwas Hilfe.

</summary>
   <content type="html">&lt;p&gt;Man konnte doch schon in den 80er Jahren C-Programme auf Webservern ausführen,
die Webseiten und anderen Schnick-Schnack generierten.&lt;/p&gt;

&lt;p&gt;Heute scheint das vergessen, aber es klappt immer noch … mit etwas Hilfe.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Unter &lt;code&gt;CGI&lt;/code&gt; verstehen heute alle nur noch 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Computer_Generated_Imagery&quot;&gt;Computer Generated Imagery&lt;/a&gt;,
also Computer-Grafiken.&lt;br /&gt;
Doch die ersten Webentwickler verstanden darunter das 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Common_Gateway_Interface&quot;&gt;Common Gateway Interface&lt;/a&gt;,
also eine Schnittstelle, wie ein Webserver externe Programme aufrufen konnte,
um dort Inhalte dynamisch generieren zu lassen.&lt;/p&gt;

&lt;h3 id=&quot;cgi&quot;&gt;CGI&lt;/h3&gt;

&lt;p&gt;Die Idee war simpel: Ein Prozess wurde mit einer Reihe spezieller 
Umgebungsvariablen gestartet, die als Input dienen sollten und der Prozess
schrieb auf &lt;code&gt;STDOUT&lt;/code&gt;, was als HTTP-Content zurückgegeben werden sollte.&lt;/p&gt;

&lt;p&gt;Der Webserver übernahm also das Parsen der HTTP-Anfrage, startete den Prozess
mit den Parametern und leitete dessen Output mit geringen Protokollzusätzen
an die Clients weiter.&lt;br /&gt;
Die Prozesse konnten - wie auf &lt;a href=&quot;https://de.wikipedia.org/wiki/POSIX&quot;&gt;POSIX&lt;/a&gt;
Systemen üblich - echte native Programme oder Shell-Scripts sein, die ja mit 
dem Interpret auch wie native Programme nach außen wirkten.&lt;/p&gt;

&lt;p&gt;So entstand die erste große Reihe von dynamischen Web-Content durch Sprachen
wie &lt;a href=&quot;https://de.wikipedia.org/wiki/Perl_(Programmiersprache)&quot;&gt;Perl&lt;/a&gt;
oder &lt;a href=&quot;https://de.wikipedia.org/wiki/PHP&quot;&gt;PHP&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Im Laufe der Zeit wurde das Konzept der separaten Prozesse aber als veraltet
angesehen und durch neuere Verfahren wie 
&lt;a href=&quot;https://de.wikipedia.org/wiki/FastCGI&quot;&gt;FastCGI&lt;/a&gt; ersetzt.&lt;br /&gt;
Mit FastCGI wird ein Prozess nur einmal gestartet und kommuniziert mit dem
HTTP-Server über Sockets. Somit können Zustände im RAM bleiben und ein 
Prozess kann auch mehrere Anfragen parallel (multithreaded) bearbeiten.&lt;/p&gt;

&lt;h3 id=&quot;einsatz-mit-c&quot;&gt;Einsatz mit C++&lt;/h3&gt;

&lt;p&gt;Ich setzte CGI mit &lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B&quot;&gt;C++&lt;/a&gt; schon vor 
12 Jahren ein, um ferige Datensätze aus Auswertungen und graphische 
Darstellung aus einer Desktop-UI ins Web zu verlagern.&lt;br /&gt;
Weil CGI-Parameter einfach per 
&lt;a href=&quot;https://en.cppreference.com/w/cpp/utility/program/getenv&quot;&gt;getenv()&lt;/a&gt; gelesen
und der HTTP Output per &lt;code&gt;std::cout&lt;/code&gt; geschrieben werden kann, konnte ich
Datensätze mit wenigen Zeilen Code als &lt;code&gt;JSON&lt;/code&gt; Objekte ausgeben und an den 
Client zurücksenden lassen.&lt;/p&gt;

&lt;p&gt;Das Thema Authentifizierung übernahm der WebServer (IIS unter Windows, 
Apache unter Linux) und ich schrieb noch schnell ein paar Zeilen mit 
statischem HTML-Code um die per JSON gelieferten Daten “bunt” anzeigen
zu können.&lt;/p&gt;

&lt;p&gt;In Sachen Deployment is “das Web” natürlich jeder Desktop-App überlegen,
und somit konnte ich die Vorteile zweier Welten nutzen:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Fertige C++ Libs lieferten bereits die gewünschten Ergebnisse
und mussten nur als JSON Datensatz formatiert werden&lt;/li&gt;
  &lt;li&gt;HTML Seiten schreiben sich schneller als native Desktop-Apps.
Jeder geänderte Buchstabe um UI kann mit einem F5 sofort angezeigt
werden … das spart viel Zeit, wenn man nicht dauernd was neu
kompilieren muss.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Meine Webserver unterstützen alle (mit ein paar Config-Anpassungen)
CGI-Programme.&lt;br /&gt;
Folglich könnte ich auch hier wieder GATE Plugins schreiben, die Features 
für das Web offenlegen.&lt;/p&gt;

&lt;p&gt;Das könnte eine hervorragende Ergänzung zu 
&lt;a href=&quot;https://de.wikipedia.org/wiki/WebAssembly&quot;&gt;WASM&lt;/a&gt; sein, denn während WASM
moderne Browser voraussetzt, kann ein simples CGI-Tool auch klassischen
HTML-Code generieren, der auf Browsern von vor 20 Jahren lauffähig ist.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Super Mario Armbanduhr</title>
   <link href="https://www.opengate.at/blog/2025/01/mario-watch/"/>
   <published>2025-01-26T12:00:00+01:00</published>
   <updated>2025-01-26T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2025/01/mario-watch</id>
   <category term="hardware" />
   <summary type="text">Meine Mutter ist nicht nur ein Schatz, sie hortet auch einen.

Und so fand ich neulich in ihrer “Alte-Uhren-Lade” den Begleiter
meiner Kindheit:
Eine Super-Mario-Bros-3
Armbanduhr von Nintendo.

</summary>
   <content type="html">&lt;p&gt;Meine Mutter ist nicht nur ein Schatz, sie hortet auch einen.&lt;/p&gt;

&lt;p&gt;Und so fand ich neulich in ihrer “Alte-Uhren-Lade” den Begleiter
meiner Kindheit:&lt;br /&gt;
Eine &lt;a href=&quot;https://de.wikipedia.org/wiki/Super_Mario_Bros._3&quot;&gt;Super-Mario-Bros-3&lt;/a&gt;
Armbanduhr von &lt;a href=&quot;https://de.wikipedia.org/wiki/Nintendo&quot;&gt;Nintendo&lt;/a&gt;.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;In den 90er Jahren bekam ich von &lt;code&gt;Super Mario&lt;/code&gt; nur zwei Formen mit,
nämlich &lt;a href=&quot;https://de.wikipedia.org/wiki/Super_Mario_Land&quot;&gt;Super Mario Land&lt;/a&gt; und
&lt;a href=&quot;https://de.wikipedia.org/wiki/Super_Mario_Land_2:_6_Golden_Coins&quot;&gt;Super Mario Land 2&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;An den beiden Spielen gab es am originalen 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Game_Boy&quot;&gt;Gameboy&lt;/a&gt; kein Vorbeikommen und 
ich glaube, jeder in meiner Klasse mit einem Gameboy hatte die beiden Titel.&lt;br /&gt;
Das ging sogar so weit, dass die hiesige Bank einen Speedrun Wettbewerb mit
Super Mario Land veranstaltete und kleine Preise für die Gewinner stiftete.&lt;/p&gt;

&lt;p&gt;Vermutlich war es die starke Präsenz von “Mario” in allen Medien, die mir dann
unerwartet die 
&lt;a href=&quot;https://www.mariowiki.com/Super_Mario_Bros._3_(Nelsonic_Game_Watch)&quot;&gt;Super Mario Bros.3 Armbanduhr&lt;/a&gt;
als Geburtstagsgeschenk verschaffte.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/mario_bros3_watch.jpg&quot; alt=&quot;MarioBros3-Watch&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Neben der üblichen Digitaluhr-Anzeige und einer einstellbaren Wecker-Zeit,
konnte man eine Mario Figur durch geschicktes Timing auf fixe Positionen
steuern, Hindernissen ausweichen und am Ende Bowser anstupsen um zur Prinzessin
zu gelangen.&lt;/p&gt;

&lt;p&gt;Die Herausforderung war dabei, diese eigentlich kurze Sequenz von etwa 20
Sekunden möglichst oft schadfrei zu Wiederholen.&lt;br /&gt;
Ich erinnere mich daran, dass es mir in den Ferien mal durch ein stundenlanges
Spiel gelungen war, die Punktezähler zum Überlauf zu bekommen … doch 
das enttäuschende Ergebnis war, dass er wieder bei Null startete.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/mariobros3_watch_screen.jpg&quot; alt=&quot;MarioBros3-Watch-Screen&quot; /&gt;&lt;/p&gt;

&lt;p&gt;In Summe war die Uhr aber ein kleiner Schatz, denn dieses Teil besaß nur
ich allein … und wir wissen, wie sehr sich Kinder wünschen “einzigartig”
zu sein.&lt;/p&gt;

&lt;h3 id=&quot;super-mario-bros-und-andere-titel&quot;&gt;Super Mario Bros. und andere Titel&lt;/h3&gt;

&lt;p&gt;Dass es parallel auch eine 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Nintendo_Entertainment_System&quot;&gt;Konsole für den Fernseher&lt;/a&gt;
gab, wo es andere Mario Titel gab als am Gameboy, war mir gar nicht bewusst.
Vielleicht hatte man mal in der Werbung davon gehört, aber vorstellen konnte
ich mir das nicht.&lt;br /&gt;
Ich wusste auch nicht, was das “Bros. 3” bedeutete, denn dass Mario noch einen
Bruder hatte und schon 3 andere große Abenteuer erlebt hatte, hat mir der
Gameboy nicht verraten.&lt;/p&gt;

&lt;p&gt;Tatsächlich habe ich Mario Bros. Teile bis heute nie durchgespielt, bestenfalls
ein paar Level mal angespielt.&lt;br /&gt;
Das ist vielleicht eine Bildungslücke, die ich nachholen sollte.&lt;/p&gt;

&lt;p&gt;Für mich begann Mario auf der Konsole durch “Super Mario World” auf dem
&lt;a href=&quot;https://de.wikipedia.org/wiki/Super_Nintendo_Entertainment_System&quot;&gt;SNES&lt;/a&gt;.
Zwar habe ich ein solches nie besessen, aber auf diversen “Veranstaltungen”
war für Kinder ein solches Gerät bereitgestellt worden.&lt;br /&gt;
Konkret fällt mir da die Landesausstellung im 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Schloss_Ruegers&quot;&gt;Schloss Riegersburg&lt;/a&gt; ein, 
an die ich mich heute nur deshalb erinnere, weil ich dort durch 
&lt;code&gt;Super Mario World&lt;/code&gt; durchgehüpft bin, während die Verwandtschaft altklug über 
die schöne Ausstellung beim Kaffeestand plauderte.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Mit einer üblichen Knopfzelle, die in jedem Supermarkt erwerbbar ist, konnte
ich meine alte Uhr aus der Schulzeit wieder reaktivieren.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/mariobros3_watch_opened.jpg&quot; alt=&quot;MarioBros3-Watch-Opened&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Seither spielt sie das Mario-Thema als Weckruf ab und ich denke dabei immer
wieder gerne zurück, wie sehr man sich als Kind über so ein einfaches Stück
Technik gefreut hatte.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Damals war eben alles besser, 
… ausgenommen die Reaktionszeit der Tasten.&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>WinCE 4.x mit RTTI</title>
   <link href="https://www.opengate.at/blog/2025/01/wince-rtti/"/>
   <published>2025-01-19T12:00:00+01:00</published>
   <updated>2025-01-19T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2025/01/wince-rtti</id>
   <category term="software" />
   <summary type="text">Wenn ich von Windows CE 
Builds spreche, dann handelt es sich um CE 5.0 oder neuer, denn das war 
die Basis für das alte Windows Mobile und Industrie-Geräte
aus meiner Arbeitswelt.

Doch beim Test mit CE 4.2 (2003) Builds erhielt ich Fehler dieser Art:


  1error LNK2001: unresolved external symbol &amp;quot;const type_info::`vftable&apos;&amp;quot; (??_7type_info@@6B@)




</summary>
   <content type="html">&lt;p&gt;Wenn ich von &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_CE&quot;&gt;Windows CE&lt;/a&gt; 
Builds spreche, dann handelt es sich um CE 5.0 oder neuer, denn das war 
die Basis für das alte &lt;code&gt;Windows Mobile&lt;/code&gt; und Industrie-Geräte
aus meiner Arbeitswelt.&lt;/p&gt;

&lt;p&gt;Doch beim Test mit CE 4.2 (2003) Builds erhielt ich Fehler dieser Art:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;error LNK2001: unresolved external symbol &amp;quot;const type_info::`vftable&apos;&amp;quot; (??_7type_info@@6B@)
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_Studio&quot;&gt;Visual Studio&lt;/a&gt; 2005 kam aus der
Schachtel mit Support für alte Organizer unter dem Titel &lt;code&gt;PocketPC2003&lt;/code&gt;. 
Alte &lt;a href=&quot;https://de.wikipedia.org/wiki/CMake&quot;&gt;CMake&lt;/a&gt; Varianten bis v3.11 
ermöglichten das Erstellen von Solutions für diese Plattform mit dem Generator:&lt;br /&gt;
&lt;code&gt;Visual Studio 8 2005 Pocket PC 2003 (ARMV4)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Doch beim Bauen von C++ Code tauchen dann beim Linken zahlreiche Fehler
zur &lt;code&gt;type_info&lt;/code&gt; VTable und auch fehlende &lt;code&gt;std::exception&lt;/code&gt; Implementierungen
auf.&lt;/p&gt;

&lt;p&gt;Beim Öffnen des Ordners&lt;br /&gt;
&lt;code&gt;C:\Program Files\Microsoft Visual Studio 8\SmartDevices\SDK\PocketPC2003\Lib\armv4&lt;/code&gt;&lt;br /&gt;
fiel mir spontan die Bibliothek &lt;code&gt;ccrtrtti.lib&lt;/code&gt; auf, die sich nach
&lt;code&gt;RTTI&lt;/code&gt; anhörte und so fügte ich sie manuell zu den Link-Libraries hinzu,
und … siehe da … die Build lief fehlerfrei durch.&lt;/p&gt;

&lt;p&gt;Es reicht also nicht die Option &lt;code&gt;Enable Runtime Type Information&lt;/code&gt; 
(also den &lt;code&gt;/GR&lt;/code&gt; Switch) zu setzen, sondern man brauch auch noch &lt;code&gt;ccrtrtti.lib&lt;/code&gt;
mit der Implementierung.&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;CMake&lt;/code&gt; lautet die magische Formel auf:&lt;/p&gt;

&lt;div class=&quot;language-cmake highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;if(WINCE)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;  if(MSVC)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;    target_link_libraries(${PROJECT_NAME} &amp;quot;ccrtrtti.lib&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  endif()
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;endif()
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Die Pocket-PC-Reihe kenne ich nur vom Sehen und war für mich nie relevant.
Es schadet aber nicht auf diese Plattform vorbereitet zu sein … selbst
wenn sie heute als ausgestorben gilt.&lt;/p&gt;

&lt;p&gt;Sobald meine Zeitmaschine fertig ist und ich ins Jahr 2005 zurückreise, bin
ich froh, wenn ich die notwendigen Patches bereits parat habe. ;)&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Mit HTML zur WASM UI</title>
   <link href="https://www.opengate.at/blog/2025/01/wasm-html/"/>
   <published>2025-01-12T12:00:00+01:00</published>
   <updated>2025-01-12T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2025/01/wasm-html</id>
   <category term="devel" />
   <summary type="text">
  Ich liebe WASM, WebAssemblies 
und Emscripten.
Aber wie bzw. was soll ich mit meinen Desktop-Programmen im
Web machen?


Antwort: Was man im Browser immer macht: Ein UI

</summary>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;Ich liebe WASM, &lt;a href=&quot;https://de.wikipedia.org/wiki/WebAssembly&quot;&gt;WebAssemblies&lt;/a&gt; 
und Emscripten.
Aber wie bzw. was soll ich mit meinen Desktop-Programmen im
Web machen?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Antwort: Was man im Browser immer macht: Ein UI&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Meine Diagnose steht seit vielen Jahren fest:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ein “produktives” UI braucht nur folgende Controls:
Labels, Textboxes, Buttons, Checkboxes, Comboboxes, 
Listviews und Treeviews.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ein Framework, das diese Elemente anbietet, kann alles bereitstellen, was man
zum täglichen Arbeiten braucht.&lt;/p&gt;

&lt;p&gt;Und tatsächlich stellt &lt;a href=&quot;https://de.wikipedia.org/wiki/Hypertext_Markup_Language&quot;&gt;HTML&lt;/a&gt;
die ersten 5 direkt bereit, und sowohl Listviews als auch Treeviews lassen
sich sogar mit HTML 4 leicht nachbauen.&lt;/p&gt;

&lt;p&gt;Meine Idee ist daher: &lt;code&gt;WASM&lt;/code&gt; erzeugt UIs per 
&lt;a href=&quot;https://de.wikipedia.org/wiki/JavaScript&quot;&gt;Javascript&lt;/a&gt;,
welches das DOM  einer Seite manipuliert.&lt;/p&gt;

&lt;h3 id=&quot;erste-experimente&quot;&gt;Erste Experimente&lt;/h3&gt;

&lt;p&gt;Der größte Aufwand bei dieser Idee entsteht beim Mapping und der Vermittlung
zwischen der &lt;code&gt;WASM&lt;/code&gt;- und der Browser-Welt.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Emscripten&lt;/code&gt; lässt uns per &lt;code&gt;emscripten_run_script_string()&lt;/code&gt; einen jeden 
Javascript Block als C-String zum Browser schicken. Folglich braucht man nur
noch den richtigen Code zusammenbauen der per
&lt;code&gt;document.createElement()&lt;/code&gt; neue HTML Element erzeugt und dann Eigenschaften
zuweist.&lt;/p&gt;

&lt;p&gt;Die Praxis sieht aber viel komplizierter aus, da wir solche Scripts sowohl aus
dem Browser-UI-Thread, als auch aus einem &lt;code&gt;WASM&lt;/code&gt;-Worker senden können müssen.&lt;br /&gt;
Im zweiten Fall muss der String am Heap liegen und zum UI-Thread geschickt 
werden, welcher dann die Verarbeitung und Deallokierung übernimmt.&lt;/p&gt;

&lt;p&gt;Genau hier schleichen sich gerne Bugs und Leaks ein, was oft schwer abzutesten
ist.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Mein erste Prototyp ist gebaut und beweist, dass man ein Label und eine
Textbox per WASM im Browser generieren lassen kann.&lt;/p&gt;

&lt;p&gt;Ein nächstes Problem wird nun die “Idee eines Fensters” sein, denn im Browser
(und besonders am Smartphone) sind Popup-Fenster heute ein Fremdkörper.&lt;/p&gt;

&lt;p&gt;Es zeigt sich also, dass nicht jedes Desktop-Feature leicht übertragbar sein
wird.&lt;/p&gt;

&lt;p&gt;Trotzdem gefällt mit die Vorstellung, dass man Desktop-UIs “einfach fürs 
Web kompilieren kann”. Und damit geht diese Analyse in die nächste Runde.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>QR-Code Encode</title>
   <link href="https://www.opengate.at/blog/2025/01/qrencode/"/>
   <published>2025-01-05T12:00:00+01:00</published>
   <updated>2025-01-05T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2025/01/qrencode</id>
   <category term="devel" />
   <summary type="text">
  Na und wer hat nicht schon mal im Bett eine 
QR-Code Bibliothek überarbeitet?


Oder: Was man über Weihnachten sonst noch alles machen kann.

</summary>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;Na und wer hat nicht schon mal im Bett eine 
&lt;a href=&quot;https://de.wikipedia.org/wiki/QR-Code&quot;&gt;QR-Code&lt;/a&gt; Bibliothek überarbeitet?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Oder: Was man über Weihnachten sonst noch alles machen kann.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Mit dem Projekt &lt;code&gt;quirc&lt;/code&gt; kann ich schon seit einiger Zeit QR-Codes aus Bildern
lesen und ihren Inhalt extrahieren. Doch eigene QR-Codes erzeugen konnte ich
mit diese Bibliothek nicht.&lt;/p&gt;

&lt;p&gt;Neben anderen (teils sehr aufgeblähten) Projekten fiel mir eines ins Auge:&lt;br /&gt;
nämlich &lt;a href=&quot;https://github.com/ricmoo/QRCode&quot;&gt;github.com/ricmoo/QRCode&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Es glänzt durch seine Einfachheit und dem Fehlen von &lt;code&gt;malloc&lt;/code&gt; oder anderen
Heap-Allokationen im Quellcode.&lt;br /&gt;
Damit ist es ideal für Mikrokontroller Projekt geeignet und auch ein würdiger
Kandidat für das GATE Projekt.&lt;/p&gt;

&lt;h3 id=&quot;codebase&quot;&gt;Codebase&lt;/h3&gt;

&lt;p&gt;Leider fielen mir neben der kompakten Codebase auch ein paar Unschönheiten auf.
Der Build liefert zahlreiche Warnungen bezüglich nicht zusammenpassenden 
Datentypen auf.&lt;/p&gt;

&lt;p&gt;Es wird wild zwischen 8, 16 und 32 bit Typen hin und her gecastet, während 
sich auch Wechsel zwischen &lt;code&gt;signed&lt;/code&gt; und &lt;code&gt;unsigned&lt;/code&gt; häufen.&lt;/p&gt;

&lt;p&gt;Aus diesem Grund habe ich einen Fork angelegt und mir vorgenommen, 
dieses alte Projekt etwas aufzupolieren.&lt;/p&gt;

&lt;h3 id=&quot;codeupdate&quot;&gt;Codeupdate&lt;/h3&gt;

&lt;p&gt;Tatsächlich lassen sich viele Warnungen durch die Umstellung auf einheitliche
Datentypen bzw. &lt;code&gt;typedef&lt;/code&gt;s fixen.&lt;br /&gt;
An den Stellen, wo wirklich Casts notwendig sind, werden diese explizit
durchgeführt, womit der Typenwechsel auch sichtbar wird.&lt;/p&gt;

&lt;p&gt;Da der Code bereits im C99 Stil geschrieben ist, ich jedoch noch ältere 
Compiler unterstützen möchte, habe ich auch hier einiges verschieben müssen.&lt;/p&gt;

&lt;p&gt;Die Deklaration von Variablen kommt C90-like an den Anfang jeder Funktion.
Und der einmalige Einsatz von lokalen variablen Arraylängen wurde durch
eine feste Arraylänge mit einem Maximumwert ersetzt.&lt;/p&gt;

&lt;p&gt;Um vom optionalen &lt;code&gt;stdint.h&lt;/code&gt; loszukommen, wurden &lt;code&gt;typedef&lt;/code&gt;s nach dem
Schema &lt;code&gt;qrcode_intX_t&lt;/code&gt; eingeführt.&lt;/p&gt;

&lt;p&gt;Und am Ende wird &lt;code&gt;CMake&lt;/code&gt; benutzt um festzustellen, ob Header und Features
vorhanden sind und um die &lt;code&gt;typedef&lt;/code&gt;s auf Standards oder Fallback Werte
zu setzen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Am Ende habe ich nun eine überarbeitete Version von &lt;code&gt;QRCode&lt;/code&gt;, die auch mit
meinen &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_CE&quot;&gt;Windows CE&lt;/a&gt;
Builds oder unter &lt;a href=&quot;https://de.wikipedia.org/wiki/Watcom_C/C%2B%2B&quot;&gt;Watcom&lt;/a&gt;
und MS-DOS kompilierbar ist.&lt;/p&gt;

&lt;p&gt;Obwohl fast jede Zeile überarbeitet wurde, ist die Funktionalität gleich
geblieben.&lt;/p&gt;

&lt;p&gt;Und weil die Resultate nicht nur für das GATE Projekt relevant sind,
habe ich ein eigenes Repo auf Codeberg dafür angelegt:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://codeberg.org/gatelinker/QRCodeGenPort&quot;&gt;codeberg.org/gatelinker/QRCodeGenPort&lt;/a&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Happy New Year 2025</title>
   <link href="https://www.opengate.at/blog/2025/01/happy-new-2025/"/>
   <published>2025-01-01T12:00:00+01:00</published>
   <updated>2025-01-01T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2025/01/happy-new-2025</id>
   <category term="general" />
   <summary type="text">
  Das neue Jahr ist da - Hurra!


Trotz Knallgewitter gegen Mitternacht, steht die Welt noch.

</summary>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;Das neue Jahr ist da - Hurra!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Trotz Knallgewitter gegen Mitternacht, steht die Welt noch.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Es wird Zeit für Veränderung.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Prosit Neujahr!&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>Das Jahr 2024</title>
   <link href="https://www.opengate.at/blog/2024/12/year2024/"/>
   <published>2024-12-31T12:00:00+01:00</published>
   <updated>2024-12-31T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2024/12/year2024</id>
   <category term="general" />
   <summary type="text">
  Das Jahr 2024 haben wir jetzt auch geschafft.


Oder man könnte auch sagen:


  Es hat uns geschafft.


</summary>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;Das Jahr 2024 haben wir jetzt auch geschafft.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Oder man könnte auch sagen:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Es hat uns geschafft.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;cmake-und-conan&quot;&gt;CMake und CONAN&lt;/h3&gt;

&lt;p&gt;2024 war “mein &lt;a href=&quot;https://de.wikipedia.org/wiki/CMake&quot;&gt;CMake&lt;/a&gt; 
und &lt;a href=&quot;https://de.wikipedia.org/wiki/Conan_(Software)&quot;&gt;Conan&lt;/a&gt; Jahr”. Denn durch
meine Erfahrung im GATE Projekt mit diesen beiden Tools konnte ich auch 
beruflich eine große Umstellaktion vorantreiben, in welcher alle Schmerzpunkte
von CONAN v1 entfernt und eine sauberere CONAN v2 Umgebung aufgesetzt 
werden konnte.&lt;/p&gt;

&lt;p&gt;Es ist faszinierend, wie viel Codemüll sich ansammelt, wenn man Workaround
über Workaround legt, nur weil man nicht weiß, wie es richtig gemacht 
werden kann.&lt;/p&gt;

&lt;p&gt;Mehr als 50 % an CMake und CONAN Code konnte gestrichen werden, als 
Kernfunktionen beider Technologien effizienter eingesetzt wurden.
Es ist in etwa so, als hätte man das Gewicht eines Autos von 
1.8 Tonnen (SUV) auf 0.9 Tonnen (Kleinwagen) reduziert, wobei Platz,
Geschwindigkeit und Komfort gleich geblieben sind.&lt;/p&gt;

&lt;h3 id=&quot;die-unix-renaissance&quot;&gt;Die Unix Renaissance&lt;/h3&gt;

&lt;p&gt;Nach vielen Jahren in der Arbeitswelt mit Windows, lässt sich der 
zunehmende Übergang zu Linux nicht mehr leugnen.&lt;br /&gt;
Linux hat sich von dem defekten Bastelhaufen, der es im Jahr 2000
war, zu einem ernstzunehmenden System entwickelt, das heute nicht
mehr wegzudenken ist.&lt;/p&gt;

&lt;p&gt;Parallel dazu sind meine Fortschritte bei den Builds für NetBSD,
OpenBSD und FreeBSD ein weiterer Meilenstein auf dem Weg zum
Unix-Horizont.&lt;/p&gt;

&lt;p&gt;Und Microsoft hat mit seiner idiotischen KI-Strategie das eigene
Betriebssystem in den letzten Jahren mehr als sträflich vernachlässigt,
was sich in immer schlechterer Performance und nutzlosen UI Spielereien
niederschlägt.&lt;/p&gt;

&lt;p&gt;Ich bin gespannt, wie dieser Trend weiterlaufen wird.&lt;/p&gt;

&lt;h3 id=&quot;weltunordnung&quot;&gt;Welt(un)ordnung&lt;/h3&gt;

&lt;p&gt;Jenseits der Technik sieht es schlecht aus.&lt;br /&gt;
1000 km von mir entfernt wird weiter Krieg geführt.&lt;br /&gt;
Ein seniler Hitzkopf wird gegen alle Vernunft ein weiteres Mal zum
Präsidenten der USA gewählt.&lt;br /&gt;
Und Konzerne sichern sich überall immer mehr Macht, was von dummen Schafen
(genannt Konsumenten) auch noch gefeiert wird.&lt;/p&gt;

&lt;p&gt;Dystopische Filmreihen aus den 80er und 90er Jahren des letzten Jahrhunderts,
fangen langsam an beängstigende realistische Zukunftsvorhersagen darzustellen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ja, 2024 war beides, Fluch und Segen.&lt;br /&gt;
Aber heute wird gefeiert und das gelobt was gut war.&lt;/p&gt;

&lt;p&gt;Und wie schon oft gesagt wurde:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Wenn die Welt untergeht, fahre nach Wien.&lt;br /&gt;
Denn bei uns dauert alles einige Monate oder Jahre länger,
bis es auch bei uns so weit ist.&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>Kein Happy-End</title>
   <link href="https://www.opengate.at/blog/2024/12/no-happy-end/"/>
   <published>2024-12-25T12:00:00+01:00</published>
   <updated>2024-12-25T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2024/12/no-happy-end</id>
   <category term="general" />
   <summary type="text">Als ich vor 22 Jahren nicht wusste, was ich in meinem Leben mit meinem Leben
anfangen sollte, tat das Arbeitsmarktservice das, was es immer tut:
Es schickte mich in einen Kurs.

Und dort saß ich dann neben einem Typen, dessen Geschichte heute nur wenige 
kennen: Rudi.

</summary>
   <content type="html">&lt;p&gt;Als ich vor 22 Jahren nicht wusste, was ich in meinem Leben mit meinem Leben
anfangen sollte, tat das Arbeitsmarktservice das, was es immer tut:&lt;br /&gt;
Es schickte mich in einen Kurs.&lt;/p&gt;

&lt;p&gt;Und dort saß ich dann neben einem Typen, dessen Geschichte heute nur wenige 
kennen: Rudi.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Nachdem wir ein paar Wochen HTML, PHP und MySQL Beispiele abgetippt hatten,
erhielten wir ein Zertifikat mit dem Titel “Internet-Programmierer” und so
dachte Vater Staat, würden gestrandete Möchtegern-IT-ler aus den 90ern das 
neue Jahrtausend beherrschen können.&lt;/p&gt;

&lt;p&gt;Dieser AMS-Kurs hat sicher viel gekostet und entsprechend gar nichts gebracht,
außer einer Sache: 5 Personen aus dieser 10er Gruppe dachten kurz, sie könnten
jetzt eine neue österreichische Microsoft-Variante als Firma gründen.&lt;br /&gt;
Rudi und ich waren zwei davon.&lt;/p&gt;

&lt;p&gt;Ohne das nötige Wissen und Geschäftskontakte war dieses Unterfangen aber 
schwer, und so war nach einigen Monaten auch nicht viel mehr drinnen als ein
paar inoffizielle Aufträge der Marke:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Einzelunternehmer Handwerker Huber will auf seiner Front-Page Webseite ein
paar &lt;code&gt;OnMouseOver&lt;/code&gt;-Einfärbungen seiner Links haben.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Und so verdiente man sich eben 100 Euro zum Arbeitslosengehalt hinzu und 
wartete geduldig auf den Nächsten 30-Minuten Job … bis zu zwei Wochen.&lt;/p&gt;

&lt;p&gt;Ich hatte dann doch das Glück über - man glaubt es kaum, per klassischen
Bewerbungsschreiben - einen richtigen Job zu bekommen und mein Leben in
geordnete Bahnen zu bekommen. Doch was wurde aus Rudi?&lt;/p&gt;

&lt;h2 id=&quot;die-richtige-wahl-im-leben&quot;&gt;Die richtige Wahl im Leben&lt;/h2&gt;

&lt;p&gt;In Fernseh-Sendungen mit Titel “Die Auswanderer” erfährt man skurrile Details
über Wünsche und Ideen im Ausland und dass diese auch scheitern können.
Doch man sieht nie, was dann nach 5 Jahren mit solchen Menschen passiert.&lt;/p&gt;

&lt;p&gt;Rudi hatte noch bevor ich ihn kennenlernte diese Erfahrung auch gemacht.
Alle Ersparnisse wurden in ein Flugticket gesteckt und alle Güter im
Heimatland wurden verkauft.&lt;/p&gt;

&lt;p&gt;Als er dann gezwungenermaßen wieder in Wien ankam, weil ein fehlendes 
Sozialsystem im Ausland und “Kosten” für Medizin nicht gedeckt werden
konnten, war dieser Traum geplatzt.&lt;br /&gt;
Zwar wird “bei uns” keiner leichtfertig dem Tod überlassen, doch auch
unser Sozialsystem reduziert alles auf ein Minimum, wenn Lücken in der
Beitragszahlung bei Versicherungen dokumentiert sind.&lt;/p&gt;

&lt;p&gt;Der AMS-Kurs war dann eine der letzten “großen” Leistungen, die dem 
Kollegen gegönnt wurden, und die auch bei ihm kein Tor zu einem 
Arbeitsplatz öffnen konnten.&lt;/p&gt;

&lt;p&gt;So blieb nichts weiter übrig als alle möglichen Kleinjobs anzunehmen,
und so kamen bei mir gelegentlich Mails an mit der Frage, ob ich
“bei einem Javascript” aushelfen konnte.&lt;/p&gt;

&lt;p&gt;Die skurrilste Szene war dann jene, als mir Rudi einen Zahnarzt 
empfahl, der mich gut versorgte, während Rudi mit der Assistenz versuchte
einen “Deal” auszuhandeln, da er eine neue Füllung brauchte und deren 
PC für die Terminplanung offensichtlich ein paar Windows-Updates notwendig
hatte.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Fun-Fact-Frage: Wenn Zahnfüllung == Windows-Update, was ist dann eine
Wurzelbehandlung wert?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Hier bemerkte ich, wie schwer man es hat, wenn man aus dem Sozialsystem
herausgefallen ist und quasi mittellos dasteht. Ich hatte so etwas nie erlebt
und konnte es mir auch gar nicht vorstellen, dass medizinische Leistungen
einfach nicht erbracht werden.&lt;/p&gt;

&lt;h2 id=&quot;nicht-meine-angelegenheit&quot;&gt;Nicht meine Angelegenheit&lt;/h2&gt;

&lt;p&gt;Während ich nun Schritt für Schritt meine Fähigkeiten in Firmen ausbauen
konnte, riss der Kontakt zu Rudi mehr und mehr ab, bis er eines Tages 
ganz aufhörte. Diverse “gemeinsame Projekte” wie Webspaces wurde aufgelöst
und ich hatte auch weder Lust noch Zeit, weiter kleine PHP-Scripts in 
meiner Freizeit zu schreiben, wenn es doch viel spannender war in
Unternehmen mit X-tausenden Personen Abläufe zu automatisieren.&lt;/p&gt;

&lt;p&gt;Schnell hat man dann Phrasen wie&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ich kann mich nicht am alles kümmern.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;vorgefertigt, um Anrufe schnell enden zu lassen, und man fühlt sich
voll und ganz im Recht dabei.&lt;/p&gt;

&lt;h2 id=&quot;erinnerungen&quot;&gt;Erinnerungen&lt;/h2&gt;

&lt;p&gt;Trotzdem werde ich den etwas pummeligen Mann nie vergessen, der ein 
witziger Kerl war, immer einen klassischen Wiener Spruch drauf hatte 
und ein bisschen wie “Garfield” durchs Leben schlenderte.&lt;/p&gt;

&lt;p&gt;Bis heute spreche ich die Speise &lt;code&gt;Gnocci&lt;/code&gt; (ital. “Njoki” gesprochen) 
scherzhaft mit Rudis Betonung “Gnoootschiii” aus, da er sich diese 
gerne mit diversen Soßen zubereitete.&lt;/p&gt;

&lt;p&gt;Auch andere Wortspiele wie “File-Shave” nutze ich noch heute gelegentlich,
so wie ich sie damals von ihm gehört hatte.&lt;/p&gt;

&lt;p&gt;Und je länger ich darüber nachdenke, wächst mein schlechtes Gewissen, den
Kontakt damals einfach so beendet zu haben.&lt;/p&gt;

&lt;h2 id=&quot;endstation&quot;&gt;Endstation&lt;/h2&gt;

&lt;p&gt;Es war im Jahr 2009, als ich spontan auf die Idee kam, 
nach Rudi per Google zu suchen.&lt;br /&gt;
Gefunden wurde nur ein Eintrag einer Pfarre mit dem Laut:&lt;br /&gt;
&lt;code&gt;Heilige Messe, für verstorbenen R.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Getriggert fragte ich dann weiter herum und so wurde mir die Geschichte 
weitergeleitet, dass sich Rudi wegen seiner vielen Probleme und
körperlichen Situation das Leben genommen hatte.&lt;/p&gt;

&lt;p&gt;Ein Ende, dass sich dieser Mann auch bei all seinen Fehlern wirklich 
nicht verdient hatte.&lt;/p&gt;

&lt;h2 id=&quot;fazit&quot;&gt;Fazit&lt;/h2&gt;

&lt;p&gt;Es ist Weihnachten.&lt;/p&gt;

&lt;p&gt;Es wird wie jedes Jahr Zeit mein Weihnachtsgeld zu überweisen.&lt;/p&gt;

&lt;p&gt;Und immer, wenn ich mich kritisch frage, ob Volkshilfe, Caritas und
andere Organisationen eine Spende verdienen, dann denke ich mir,
ob vielleicht eine weitere Behandlung, ein weiterer Kurs, ein weiteres
Gespräch Rudi von seinem letzten Weg hätte abhalten können.&lt;/p&gt;

&lt;p&gt;Auch ich hätte damals abstürzen können, als ich wenig hatte und es war
eine gute Portion Glück, die mir Arbeit, Einkommen und “Auskommen” beschert
hat. Und all das wurde durch soziale Einrichtungen ermöglicht, die es 
gestatteten schwierige Zeiten zu überstehen.&lt;/p&gt;

&lt;p&gt;Manchmal reicht eben ein kleines Ereignis, das alles ins Rollen bringt, 
zum Guten oder zum Bösen.&lt;/p&gt;

&lt;p&gt;Zitat aus Göthe’s Faust:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Erinnrung hält mich nun, mit kindlichem Gefühle,&lt;br /&gt;
Vom letzten, ernsten Schritt zurück.&lt;br /&gt;
O tönet fort, ihr süßen Himmelslieder!&lt;br /&gt;
Die Träne quillt, die Erde hat mich wieder!&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>Das Öxlein und das Öselein</title>
   <link href="https://www.opengate.at/blog/2024/12/das-eselein/"/>
   <published>2024-12-24T12:00:00+01:00</published>
   <updated>2024-12-24T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2024/12/das-eselein</id>
   <category term="general" />
   <summary type="text">Immer wieder erwähnt meine Mutter in Erzählungen, wie es in ihrer Kindheit 
zu Weihnachten war, als die kleine Dorfkapelle am heiligen Abend voll mit
Mensch war, und wie gemeinsam gesungen wurde.

Und es soll mein Großvater gewesen sein, der damals einen alten Brauch durch
einen neueren ersetzt hat.

</summary>
   <content type="html">&lt;p&gt;Immer wieder erwähnt meine Mutter in Erzählungen, wie es in ihrer Kindheit 
zu Weihnachten war, als die kleine Dorfkapelle am heiligen Abend voll mit
Mensch war, und wie gemeinsam gesungen wurde.&lt;/p&gt;

&lt;p&gt;Und es soll mein Großvater gewesen sein, der damals einen alten Brauch durch
einen neueren ersetzt hat.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Österreich ist sich ganz besonders stolz auf seine großen 
Export-Güter in der Musik:&lt;br /&gt;
&lt;a href=&quot;https://de.wikipedia.org/wiki/Stille_Nacht,_heilige_Nacht&quot;&gt;Stille Nacht, heilige Nacht&lt;/a&gt;
is wohl das “bekannteste” Lied aus der Alpennation, welches in alle Sprachen 
übersetzt und in vermutlich jedem Land irgendwo einmal angestimmt wird.&lt;/p&gt;

&lt;p&gt;Doch in einem kleinen Dorf im Waldviertel, 
hinter den sieben Hügeln&lt;br /&gt;
bei den Hühnern mit den kurzen Flügeln …&lt;br /&gt;
oder so ähnlich, da war alles anders.&lt;/p&gt;

&lt;p&gt;In der Kapelle wurde nämlich von Jahr zu Jahr ein anderes Weihnachtslied 
angestimmt, und zwei alte Herrn machten sich stets einen Spaß daraus, ein
paar Laute so zu verzerren, dass die Kinder sich das Lachen nicht verkneifen
konnten.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ein Öxlein und ein Öselein,&lt;br /&gt;
das mögen gute Tierlein sein.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Natürlich sollte es “ein Öchslein und ein Eselein” sein, die hier
besungen wurden, doch so brannte sich die Zeile ins Gedächtnis der damaligen
Kinder.&lt;/p&gt;

&lt;p&gt;Einige Jahre später drängte (so die Legende) mein Großvater darauf hin, man
möge doch wie alle anderen “zivilisierten” Gemeinden, die “Stille Nacht”
besingen und so setzte sich langsam der Wille zur Veränderung bei den
“Dorfältesten” durch.&lt;/p&gt;

&lt;p&gt;Nur erklingt auch im Waldviertel das Lied aus 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Oberndorf_bei_Salzburg&quot;&gt;Oberndorf&lt;/a&gt; am&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;Dezember.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Doch woher stammte eigentlich das “Öselein”.&lt;/p&gt;

&lt;h3 id=&quot;was-ist-das-doch-ein-holdes-kind&quot;&gt;Was ist das doch ein holdes Kind&lt;/h3&gt;

&lt;p&gt;Das Internet hilft weiter:
Die deutsche Dichterin &lt;a href=&quot;https://de.wikipedia.org/wiki/Luise_Hensel&quot;&gt;Luise Hensel&lt;/a&gt;
erdachte den Text 1871, und irgendwie muss er es auch in den Südosten 
geschafft haben, wo ihn meine Vorfahren gelernt hatten.&lt;br /&gt;
Interessant ist, dass das Lied dem “näheren” Stille-Nacht-Text vorgezogen 
wurde, bis er vermutlich in den 1960er Jahren aufgegeben wurde.&lt;/p&gt;

&lt;p&gt;Die Seite &lt;a href=&quot;https://www.lieder-archiv.de/was_ist_das_doch_ein_holdes_kind-notenblatt_211135.html&quot;&gt;lieder-archiv.de&lt;/a&gt;
hat das Stück für die Nachwelt konserviert, was mir eine große Freude bereitet.&lt;/p&gt;

&lt;p&gt;Trotzdem möchte ich den Text nun hier einfügen, damit er möglichst lange 
erhalten bleibt … und vielleicht möge sich der eine oder andere Leser
bei Strophe 4 zwei alte Bauern vorstellen, die wie Schulkinder aus 
dem “Eselein” ein “Öselein” beim Durchsingen machten.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Was ist das doch ein holdes Kind&lt;br /&gt;
das man hier in der Krippe find’t?&lt;br /&gt;
Ach, solch ein süßes Kindelein,&lt;br /&gt;
das muss gewiss vom Himmel sein.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;Die Frau, die bei der Krippe kniet,&lt;br /&gt;
und selig auf das Kindlein sieht,&lt;br /&gt;
das ist Maria fromm und rein;&lt;br /&gt;
ihr mag recht froh im Herzen sein.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;Der Mann, der zu der Seite steht,&lt;br /&gt;
und still hinauf zum Himmel fleht,&lt;br /&gt;
das muss der fromme Josef sein,&lt;br /&gt;
der tut sich auch des Kindleins freun.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;Und was dort in der Ecke liegt&lt;br /&gt;
und nach dem Kindlein schaut vergnügt,&lt;br /&gt;
ein Öchslein und ein Eselein,&lt;br /&gt;
das mögen gute Tierlein sein.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;Und die dort kommen fromm und gut&lt;br /&gt;
mit langem Stab und rundem Hut,&lt;br /&gt;
das ist der Hirten fromme Schaar,&lt;br /&gt;
die bringen ihre Gaben dar.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;Und was den Stall so helle macht,&lt;br /&gt;
und was so lieblich singt und lacht,&lt;br /&gt;
das sind die lichten Engelein,&lt;br /&gt;
die schaun zu Tür und Fenster ein.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;Und die da kommen ganz von fern&lt;br /&gt;
und gläubig schauen nach dem Stern,&lt;br /&gt;
das werden wohl die Weisen sein&lt;br /&gt;
mit Weihrauch, Gold und Spezerein.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;Und ob dem Stalle flammt der Stern,&lt;br /&gt;
der leuchtet nah und leuchtet fern;&lt;br /&gt;
er leuchtet auch durch unsre Zeit&lt;br /&gt;
und leuchtet bis in Ewigkeit.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;Sei hochgelobt, du dunkle Zell!&lt;br /&gt;
Durch dich die ganze Welt wird hell.&lt;br /&gt;
Klein Kindlein in Mariens Schoß,&lt;br /&gt;
wie bist du so unendlich groß.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;YouTube hat zumindest die ersten 3 Strophen vertont:&lt;/p&gt;

&lt;iframe width=&quot;640&quot; height=&quot;360&quot; src=&quot;/blog/redirect.html?https%3A%2F%2Fwww.youtube-nocookie.com%2Fembed%2FaYhtfO1tnDk&quot; frameborder=&quot;1&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
</content>
 </entry>
 
 <entry>
   <title>Hermes Phettberg ist tot</title>
   <link href="https://www.opengate.at/blog/2024/12/phettberg/"/>
   <published>2024-12-22T12:00:00+01:00</published>
   <updated>2024-12-22T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2024/12/phettberg</id>
   <category term="general" />
   <summary type="text">Er war der Gesprächsstoff in der Schule bei den anderen …
und ich hatte seine Sendung stets verpasst.

Erst nach 2000 sah ich den dicken Mann im Fernsehen und YouTube
konserviert seit 2010, was in den 90ern geschehen ist.

Josef Fenz, auch bekannt als Hermes Phettberg, 
ist vor Kurzem gestorben.

</summary>
   <content type="html">&lt;p&gt;Er war der Gesprächsstoff in der Schule bei den anderen …
und ich hatte seine Sendung stets verpasst.&lt;/p&gt;

&lt;p&gt;Erst nach 2000 sah ich den dicken Mann im Fernsehen und YouTube
konserviert seit 2010, was in den 90ern geschehen ist.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Josef Fenz&lt;/code&gt;, auch bekannt als &lt;code&gt;Hermes Phettberg&lt;/code&gt;, 
ist vor Kurzem gestorben.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Ein (inzwischen ebenfalls verstorbener) Nachbar meinte mal:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Phettberg? Das ist doch dieser gebildete Sandler, oder?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Und … irgendwie passt das.&lt;br /&gt;
Die Kunstfigur Phettberg, ein schwer übergewichtiger, verkommen
wirkender und bestätigt stinkender Mann, trat in den 90er Jahren
im österreichischen Fernsehen mit dem Namen&lt;br /&gt;
&lt;a href=&quot;https://de.wikipedia.org/wiki/Phettbergs_Nette_Leit_Show&quot;&gt;Phettbergs nette Leit’ Show&lt;/a&gt;
auf.
Er lud Künstler, Politiker und Professoren zu sich auf die Bühne ein und 
diskutierte auf hohem Niveau und mit unvergleichlichem Witz über das 
aktuelle Geschehen.&lt;/p&gt;

&lt;p&gt;Die (oft von seiner offen belebten Homosexualität untermalten) frechen
Statements ließen auch so manchen Teenager verlegen erröten und so wurde
Phettbergs’ Show zum Geheimtipp auch an meiner Schule.&lt;/p&gt;

&lt;p&gt;Und trotzdem hatte ich nie auch nur eine einzige Episode im Spätabendprogramm
mitverfolgt, sondern wunderte mich nur über die “neuen Worte”, die am 
Nebentisch während des Unterrichts getuschelt wurden.&lt;/p&gt;

&lt;p&gt;Erst als der damals “neue” &lt;a href=&quot;https://de.wikipedia.org/wiki/ATV_(Fernsehsender)&quot;&gt;Sender ATV&lt;/a&gt;
Phettberg mit einer veränderten Neuauflage des Formats auf die Fernseh-Kästen
projizierte, konnte ich erstmals die Schlagfertigkeit und den selbstironischen
Witz von “Österreichs’ bekanntestem Schwulen” mitverfolgen.&lt;/p&gt;

&lt;p&gt;Legendär war für mich das Video “Phettberg kauf sich einen Computer” im 
Geschäft &lt;code&gt;VDS-Computer&lt;/code&gt; in der Gumpendorfer Straße.&lt;/p&gt;

&lt;iframe width=&quot;640&quot; height=&quot;360&quot; src=&quot;/blog/redirect.html?https%3A%2F%2Fwww.youtube-nocookie.com%2Fembed%2FC9MTubB7VxM&quot; frameborder=&quot;1&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;

&lt;p&gt;Damals schaltete dieser Hardware Händler Inserate in jeder Zeitschrift und
war auch für die Reparatur eines meiner Geräte verantwortlich.&lt;/p&gt;

&lt;p&gt;Und siehe dar, in meiner Sammelkiste überlebte ein letztes Überbleibsel
dieses Unternehmens: Eine Zündholzschachtel mit der Adresse:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/vds-computer.jpg&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Jede Chance etwas “Sexuelles” in die Diskussion einzubringen wurde genutzt.
Und seitdem der “Chello-Mann” das &lt;a href=&quot;https://de.wikipedia.org/wiki/UPC_Austria&quot;&gt;UPC&lt;/a&gt;
Telekabelkabelmodem am neuen PC angeschlossen hatte, war Phettberg “online”.&lt;/p&gt;

&lt;p&gt;Auf der Seite &lt;a href=&quot;https://phettberg.at/&quot;&gt;phettberg.at&lt;/a&gt; wurde stets um Geld 
gebettelt, welches dem Redekünstler Zeit seines Lebens fehlte. Doch dafür gab
es “kostenlos” Auszüge aus seinen Predigten, in denen er gerne den 
belehrenden Dorfpfarrer oder Bischof nachahmte, welcher immer nach 
“jungen Buben in engen Jeans” Ausschau hielt.&lt;/p&gt;

&lt;p&gt;Doch berühmt wird er immer für die “Nette Leit’ Show” bleiben, in denen 
jeder Gast nach “Frucade oder Eierlikör” gefragt wurde.&lt;/p&gt;

&lt;p&gt;Heute noch auf YouTube konserviert sind Schmankerl wie das Gespräch mit
dem Leiter der Lebensmittelanstalt Wiens &lt;code&gt;Alfred Psota&lt;/code&gt;.&lt;/p&gt;

&lt;iframe width=&quot;640&quot; height=&quot;360&quot; src=&quot;/blog/redirect.html?https%3A%2F%2Fwww.youtube-nocookie.com%2Fembed%2Fa4Mdr6uLWzM&quot; frameborder=&quot;1&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Nach Schlaganfällen und dem allgemeinen körperlichen Verfall, wurde 
&lt;code&gt;Franz Fenz&lt;/code&gt; nur noch selten nach dem Jahr 2010 wahrgenommen. Zwar schrieb er
weiter seine Predigten, doch diese hatte nicht mehr die “Fülle” von damals,
wie es auch sein abgemagerter Rumpf darstellte.&lt;/p&gt;

&lt;p&gt;Die Nachricht von Hermes Phettberg’s Tod Ende 2024 lässt mich erkennen, dass 
nun 30 Jahre vergangen sind, seit der Koloss die große Bühne erstmals betrat.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Schnell ist es vergangen, das Leben.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;erklärte mal ein Hinterbliebener nach einem Begräbnis. Und das stimmt.&lt;/p&gt;

&lt;p&gt;Phettberg hat viele Menschen zum Lachen und einige davon auch zum Nachdenken
gebracht. Darauf kann er stolz sein. &lt;br /&gt;
Wir werden ihn dafür in Erinnerung behalten, mit all den Fehlern, 
die ihn zu dem “Ungustl” machten, der er immer gewesen ist.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Neue öffentliche Codeberg Runner</title>
   <link href="https://www.opengate.at/blog/2024/12/codeberg-runners/"/>
   <published>2024-12-15T12:00:00+01:00</published>
   <updated>2024-12-15T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2024/12/codeberg-runners</id>
   <category term="software" />
   <summary type="text">Seit Neuem werden neue (mir unbekannte) Runner in der 
Codeberg Action-Runner UI angezeigt.

Es ist also so weit. Bald haben wir “freie” Build-Server.

</summary>
   <content type="html">&lt;p&gt;Seit Neuem werden neue (mir unbekannte) Runner in der 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Codeberg&quot;&gt;Codeberg&lt;/a&gt; Action-Runner UI angezeigt.&lt;/p&gt;

&lt;p&gt;Es ist also so weit. Bald haben wir “freie” Build-Server.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Codeberg startete mit &lt;a href=&quot;https://de.wikipedia.org/wiki/Woodpecker_CI&quot;&gt;Woodpecker CI&lt;/a&gt;, 
einer externen CI/CD Lösung, die ich bisher nie benutzt hatte.&lt;br /&gt;
Doch parallel implementierte &lt;a href=&quot;https://de.wikipedia.org/wiki/Forgejo&quot;&gt;Forgejo&lt;/a&gt;
(die Software hinter Codeberg) ein zu &lt;a href=&quot;https://de.wikipedia.org/wiki/GitHub&quot;&gt;Github&lt;/a&gt;
kompatibles “Actions” System.&lt;/p&gt;

&lt;p&gt;Seit einem Jahr läuft nun auf einer meiner Privatmaschinen ein Forgejo-Runner
und führt Builds bei jedem Commit aus.&lt;br /&gt;
Das Codeberg-Team hatte damals diese Technik selbst nicht eingesetzt und
konnte daher bei Support-Fragen immer nur an das Forgejo-Team verweisen.&lt;/p&gt;

&lt;p&gt;Doch nun hat Codeberg globale Actions-Runner aktiviert und betreibt nun 
frei verfügbare öffentliche CI/CD Dienste.&lt;br /&gt;
Neben meinen eigenen Build-Runnern werden nun folgende Instanzen angezeigt:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;tiny@actions-tiny.aburayama.m.codeberg.org
    &lt;ul&gt;
      &lt;li&gt;für max. 2 Minuten Jobs&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;small@actions-tiny.aburayama.m.codeberg.org
    &lt;ul&gt;
      &lt;li&gt;für max. 5 Minuten Jobs&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;medium@actions-tiny.aburayama.m.codeberg.org (10 Minuten Jobs)
    &lt;ul&gt;
      &lt;li&gt;für max. 10 Minuten Jobs&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Eine genauere Übersicht wird unter 
&lt;a href=&quot;https://codeberg.org/actions/meta&quot;&gt;codeberg.org/actions/meta&lt;/a&gt;
bereitgestellt.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ich finde das Angebot super. Mein Builds sprengen diese Limits teilweise, 
aber ich könnte mir vorstellen über einen freien Runner einen Webrequest
an einen Cloud-Dienst zu senden, der eine VM hochfährt, die meinen eigenen
Runner ausführt.&lt;br /&gt;
So spare ich Betriebskosten und aktiviere meine Ressourcen nur bei Bedarf,
und die Belastung auf der Seite von Codeberg ist minimal, da ja nur ein
paar HTTP Aufrufe abgesetzt werden.&lt;/p&gt;

&lt;p&gt;Codeberg bietet nun alle Features an, die Produkte wie &lt;code&gt;Github&lt;/code&gt; oder 
&lt;a href=&quot;https://de.wikipedia.org/wiki/GitLab&quot;&gt;Gitlab&lt;/a&gt; auch im Angebot haben … 
nur dass Codeberg ein echtes OpenSource-Projekt mit einer nicht-kommerziellen
Mission ist.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ein großes “Danke!” geht an die Codeberg Betreiber und die Community.&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>CTest Debugging in VSCode</title>
   <link href="https://www.opengate.at/blog/2024/12/ctest-vscode/"/>
   <published>2024-12-08T12:00:00+01:00</published>
   <updated>2024-12-08T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2024/12/ctest-vscode</id>
   <category term="devel" />
   <summary type="text">Per CTest registrierte Tests aus CMake
können in VSCode auf viele 
unterschiedliche Arten und Weisen gestartet werden.

Und jede hat ihre individuellen Eigenarten.

</summary>
   <content type="html">&lt;p&gt;Per &lt;code&gt;CTest&lt;/code&gt; registrierte Tests aus &lt;a href=&quot;https://de.wikipedia.org/wiki/CMake&quot;&gt;CMake&lt;/a&gt;
können in &lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_Studio_Code&quot;&gt;VSCode&lt;/a&gt; auf viele 
unterschiedliche Arten und Weisen gestartet werden.&lt;/p&gt;

&lt;p&gt;Und jede hat ihre individuellen Eigenarten.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Ignorieren wir mal die “Problemchen”, die uns 
&lt;a href=&quot;/blog/2024/11/conan2-tests/&quot;&gt;CONAN einbrocken kann&lt;/a&gt; und sprechen
wir nur über &lt;code&gt;CMake&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Natürlich kann man ein Test-Programm-Target auch als normales &lt;code&gt;CMake&lt;/code&gt;-Debug Target
auswählen und ganz normal zum Debugging starten … doch darum soll es hier nicht
gehen.&lt;/p&gt;

&lt;p&gt;Wird ein Target als Test per &lt;code&gt;add_test()&lt;/code&gt; registriert, erscheint der Test auch
in VSCode’s Test Explorer.&lt;br /&gt;
Dort kann der Test per Klick gestartet werden, was &lt;code&gt;CMake&lt;/code&gt; anwirft und dieses
dann den Test regulär startet.&lt;/p&gt;

&lt;p&gt;Neben dem Start-Pfeil-Button, gibt es noch den Start-Debugging Button neben
jedem Test.&lt;br /&gt;
Beim einem Klick darauf braucht VSCode wieder eine Launch-Konfiguration, die
in etwa so aussehen kann:&lt;/p&gt;

&lt;div class=&quot;language-json highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;/&lt;/span&gt; &lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;v&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;s&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;c&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;o&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;d&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;e&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;l&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;u&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;n&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;c&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;h&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;j&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;s&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;o&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;n&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;0.2.0&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;configurations&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: [
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;    {
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;(gdb) CTest Launch&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;cppdbg&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;MIMode&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;gdb&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;request&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;launch&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;program&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;${cmake.testProgram}&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;args&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: [ &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;${cmake.testArgs}&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; ],
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;cwd&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;${cmake.testWorkingDirectory}&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;    },
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;    {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;(msvc) CTest Launch&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;cppvsdbg&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;request&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;launch&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;program&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;${cmake.testProgram}&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;args&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: [ &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;${cmake.testArgs}&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; ],
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;cwd&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;${cmake.testWorkingDirectory}&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n21&quot; name=&quot;n21&quot;&gt;21&lt;/a&gt;&lt;/span&gt;    }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n22&quot; name=&quot;n22&quot;&gt;22&lt;/a&gt;&lt;/span&gt;  ]
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n23&quot; name=&quot;n23&quot;&gt;23&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Beim “Start-Debugging” erscheint ein Menüs, das uns die beiden definierten
Möglichkeiten anbietet und startet einen Debug-Prozess basierend auf den
&lt;code&gt;CTest&lt;/code&gt;-Einstellungen, die wir gewählt haben.&lt;/p&gt;

&lt;p&gt;Und wenn diese Einstellungen falsch sind, startet gar nichts.&lt;/p&gt;

&lt;h3 id=&quot;cmake-generator-unterschiede&quot;&gt;CMake Generator Unterschiede&lt;/h3&gt;

&lt;p&gt;Ein gravierenden Unterschied zwischen &lt;code&gt;MSVC&lt;/code&gt; und den anderen Compilern ist 
die Visual Studio Solution, und ihre Projekte, die Debug und Release-
Konfigurationen beinhalten, während für andere Compiler eine Konfiguration 
vorausgewählt werden muss.&lt;br /&gt;
Das führt dazu, dass ein GCC immer genau ein Ausgabeverzeichnis für Programme
und Bibliotheken hat, doch Visual Studio erhält zwei, einmal Debug und einmal 
Release.
Der &lt;code&gt;add_test()&lt;/code&gt; Test muss also wissen, wie er Debug und Release-Konfigurationen
unterschiedlich verwaltet.&lt;/p&gt;

&lt;p&gt;Jetzt kommt noch ein weiterer Fall hinzu: nämlich 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Ninja_(Software)&quot;&gt;Ninja&lt;/a&gt;.&lt;br /&gt;
Ninja-Build kann das Bauen wie &lt;code&gt;MSBuild&lt;/code&gt; verwalten, verzichtet aber auf 
Solutions oder VS-Projekte und setzt das unkompliziertere GCC Schema mit 
genau einem vorkonfigurierten Build-Type ein.&lt;/p&gt;

&lt;p&gt;Aus diesem Grund sieht meine &lt;code&gt;add_my_test()&lt;/code&gt; Funktion so aus:&lt;/p&gt;

&lt;div class=&quot;language-cmake highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;set(APP_EXECUTABLE ${PROJECT_NAME})
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;set(TEST_ARGS)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;get_target_property(OUTPUT_FOLDER ${TARGET_NAME} RUNTIME_OUTPUT_DIRECTORY)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;if(MSVC AND NOT (${CMAKE_GENERATOR} MATCHES &amp;quot;Ninja&amp;quot;))
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  set(TEST_WORKING_DIRECTORY &amp;quot;${OUTPUT_FOLDER}/$&amp;lt;CONFIG&amp;gt;&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;else()
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  set(TEST_WORKING_DIRECTORY &amp;quot;${OUTPUT_FOLDER}&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;endif()
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;add_test(NAME &amp;quot;${TEST_NAME}&amp;quot; WORKING_DIRECTORY &amp;quot;${TEST_WORKING_DIRECTORY}&amp;quot; COMMAND &amp;quot;${APP_EXECUTABLE}&amp;quot; ${TEST_ARGS})
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Mit der Launch-Konfiguration für &lt;code&gt;CTest&lt;/code&gt; und ein paar Anpassungen für den Start
kann jedes Testprogramm auch aus dem &lt;code&gt;VSCode&lt;/code&gt; Testing-Tab zum Debuggen gestartet
werden.&lt;/p&gt;

&lt;p&gt;Ich wünschte, ich hätte &lt;code&gt;CTest&lt;/code&gt; und &lt;code&gt;VSCode&lt;/code&gt; schon 10 Jahre früher kennen gelernt 
und eingesetzt, denn strukturiertes Testen kann die Qualität der 
Softwareentwicklung nachhaltig verbessern.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>CMake project oder project C</title>
   <link href="https://www.opengate.at/blog/2024/12/cmake-project-c/"/>
   <published>2024-12-01T12:00:00+01:00</published>
   <updated>2024-12-01T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2024/12/cmake-project-c</id>
   <category term="devel" />
   <summary type="text">
  Es ist zum Durchdrehen.


Mit project(xyz) laufen Standard-Builds (Windows, Linux) aber der 
Tiny C Compiler (TCC) 
streikt, weil CMake hier C++ 
Code-Tests exekutiert.

Mit project(xyz C) streikt wieder 
Watcom, weil der dann 
C++ gar nicht mehr nutzen kann.

</summary>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;Es ist zum Durchdrehen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Mit &lt;code&gt;project(xyz)&lt;/code&gt; laufen Standard-Builds (Windows, Linux) aber der 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Tiny_C_Compiler&quot;&gt;Tiny C Compiler&lt;/a&gt; (TCC) 
streikt, weil &lt;a href=&quot;https://de.wikipedia.org/wiki/CMake&quot;&gt;CMake&lt;/a&gt; hier C++ 
Code-Tests exekutiert.&lt;/p&gt;

&lt;p&gt;Mit &lt;code&gt;project(xyz C)&lt;/code&gt; streikt wieder 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Watcom_C/C%2B%2B&quot;&gt;Watcom&lt;/a&gt;, weil der dann 
C++ gar nicht mehr nutzen kann.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Fangen wir am Anfang an: Es ist ein philosophisches Problem.&lt;/p&gt;

&lt;p&gt;C und C++ sind historisch in fast allen Betriebssystemen stark mit einander
verbunden. Und ich sehe das GATE Projekt als eine Brücke zwischen den beiden
Sprachen.&lt;br /&gt;
Doch in Wahrheit sprechen wir von zwei Sprachen, die wie zwei Länder zwei
getrennte Rechtsräume, Gesetzgebung und Kultur beinhalten.&lt;br /&gt;
Auch &lt;a href=&quot;https://de.wikipedia.org/wiki/Bjarne_Stroustrup&quot;&gt;Bjarne Stroustrup&lt;/a&gt; hat
schon mehrfach verkündet:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Es gibt kein C/C++.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Soll heißen:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Es gibt entweder C oder C++.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;tcc-ist-nur-c&quot;&gt;TCC ist nur C&lt;/h3&gt;

&lt;p&gt;Der Tiny-C-Compiler ist im Gegensatz zu “den großen Brüdern” ein reiner C 
Compiler, während &lt;code&gt;MSVC&lt;/code&gt;, &lt;code&gt;GCC&lt;/code&gt;, &lt;code&gt;CLANG&lt;/code&gt; und &lt;code&gt;WATCOM&lt;/code&gt; beide Welten abdecken.&lt;/p&gt;

&lt;p&gt;Wer also sein &lt;code&gt;CMake&lt;/code&gt; Projekt mit&lt;/p&gt;

&lt;div class=&quot;language-cmake highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;project(myproject)
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;einleitet, lässt &lt;code&gt;CMake&lt;/code&gt; nach einem C und einem C++ Compiler suchen, wobei
zweiteres mit dem TCC fehlschlägt und CMake abbricht.&lt;/p&gt;

&lt;p&gt;Die Lösung lautet:&lt;/p&gt;

&lt;div class=&quot;language-cmake highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;project(myproject C)
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;und alles ist wieder gut.&lt;/p&gt;

&lt;h3 id=&quot;optionaler-c-support&quot;&gt;Optionaler C++ Support&lt;/h3&gt;

&lt;p&gt;Da im GATE Projekt jedoch C und C++ Targets vorkommen, hätte ich bereits
eine &lt;code&gt;NO_CPP&lt;/code&gt; Option eingeführt, die C++ Targets nur dann einschließt, wenn
die &lt;code&gt;NO_CPP&lt;/code&gt; Option NICHT gesetzt ist.&lt;br /&gt;
Das funktioniert auch mit &lt;code&gt;MSVC&lt;/code&gt; und &lt;code&gt;GCC&lt;/code&gt;, doch nun fängt &lt;code&gt;OpenWatcom&lt;/code&gt; an 
zu spinnen.&lt;/p&gt;

&lt;p&gt;Ist dort ein Top-Level-Projekt an die Sprache C gebunden, können keine C++
Unterprojekte mehr angefügt werden.&lt;/p&gt;

&lt;p&gt;Als “schnelle” Lösung fiel mir am Ende nur folgende Lösung ein:&lt;/p&gt;

&lt;div class=&quot;language-cmake highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;option(GATE_NO_CPP &amp;quot;Build C files only, no C++ support&amp;quot; OFF)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;if(GATE_NO_CPP)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  project(gate C)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;else()
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;  project(gate)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;endif()
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Im Toplevel &lt;code&gt;CMakeLists.txt&lt;/code&gt; wird die &lt;code&gt;NO_CPP&lt;/code&gt; Option definiert und abhängig
davon wird ein reines C oder allgemeines Projekt angelegt.&lt;br /&gt;
Die Option wird nur für den TCC of ON geschaltet und im Nachgang können 
weitere C und optional auch C++ angelegt werden.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;Auf Details kommt es an.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ich liebe &lt;code&gt;CMake&lt;/code&gt; für seine unglaublichen vielen Anbindungen an 
unterschiedliche Compiler. Doch hier habe ich einmal ein Problem 
identifiziert, das &lt;code&gt;CMake&lt;/code&gt; nicht selbst löst und mir etwas Nacharbeit 
beschert.&lt;/p&gt;

&lt;p&gt;Toplevel-Projekte sind rein technisch auch gar nicht notwendig, doch sie helfen
in IDEs bei der Schaffung einer überordneten Instanz wie “Solutions” bei 
Visual Studio.&lt;br /&gt;
Dass deren (sonst wirkungslose) Konfiguration Arbeitsläufe negativ
beeinflussen kann, war mir bisher nicht aufgefallen.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;However … wieder was gelernt.&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>CONAN 2 Tests</title>
   <link href="https://www.opengate.at/blog/2024/11/conan2-tests/"/>
   <published>2024-11-24T12:00:00+01:00</published>
   <updated>2024-11-24T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2024/11/conan2-tests</id>
   <category term="devel" />
   <summary type="text">Das Drama mit CONAN ist oft,
dass die Entwicklung in unterschiedlichen Kontexten läuft. Und ein 
conan create führt Builds und Tests manchmal ganz anders aus, als ein
cmake build nach einem conan install.

Auf zur Analyse!

</summary>
   <content type="html">&lt;p&gt;Das Drama mit &lt;a href=&quot;https://de.wikipedia.org/wiki/Conan_(Software)&quot;&gt;CONAN&lt;/a&gt; ist oft,
dass die Entwicklung in unterschiedlichen Kontexten läuft. Und ein 
&lt;code&gt;conan create&lt;/code&gt; führt Builds und Tests manchmal ganz anders aus, als ein
&lt;code&gt;cmake&lt;/code&gt; build nach einem &lt;code&gt;conan install&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Auf zur Analyse!&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;code&gt;conan build&lt;/code&gt; und &lt;code&gt;conan create&lt;/code&gt; laden alle Abhängigkeiten und fügen die
notewendigen Pfade in die &lt;code&gt;PATH&lt;/code&gt; und &lt;code&gt;LD_LIBRARY_PATH&lt;/code&gt; Umgebungsvariablen
ein, wenn Prozesse wie &lt;code&gt;cmake&lt;/code&gt; gestartet werden.&lt;br /&gt;
Laufen dann Tests, erben die Test-Prozesse die Umgebung und alles läuft
problemlos.&lt;/p&gt;

&lt;p&gt;Bei der Entwicklung nutzen wir aber häufig &lt;code&gt;conan install&lt;/code&gt; und 
&lt;code&gt;conan source&lt;/code&gt; und danach starten wir &lt;code&gt;cmake&lt;/code&gt; oder eine IDE 
(wie &lt;code&gt;VSCode&lt;/code&gt;) manuell, wo diese Umgebung fehlt.&lt;br /&gt;
Die Builds laufen dann, aber Tests können die notwendigen Bibliotheken
zur Laufzeit nicht finden und schlagen fehl.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Hinweis: Kleine Projekte haben das Problem nicht, denn wenn alles lokal
gebaut wird, sind die korrekten Pfade des Build-Prozesses in den Binaries
selbst gespeichert. Doch wenn per CI fertige Komponenten auf den eigenen
Conan-Remote hochgeladen wurden und das eigene Projekt diese herunterlädt,
dann passt das Setup nicht mehr zusammen und &lt;code&gt;PATH&lt;/code&gt; bzw.
&lt;code&gt;LD_LIBRARY_PATH&lt;/code&gt; werden zwingend erforderlich.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;conan-virtual-run-environment&quot;&gt;CONAN virtual run environment&lt;/h3&gt;

&lt;p&gt;Die Standard Lösung lautet: Erzeuge ein Run-Environment und starte die
IDE oder den Build-Prozess aus diesem heraus.&lt;br /&gt;
Conan legt hierfür &lt;code&gt;conanrun&lt;/code&gt; Scripts an, die man einfach vor dem Build
oder der IDE starten muss:&lt;/p&gt;

&lt;h4 id=&quot;windows-cmake-und-visual-code-mit-conan-run-environment&quot;&gt;Windows: CMake und Visual Code mit CONAN run environment&lt;/h4&gt;

&lt;div class=&quot;language-batch highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;cd myproject
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;conan install .
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;build\generators\conanrun.bat
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;cmake --preset conan-debug
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;cmake --build --preset conan-debug
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;code .
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;build\generators\deactivate_conanrun.bat
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h4 id=&quot;linux-cmake-und-visual-code-mit-conan-run-environment&quot;&gt;Linux: CMake und Visual Code mit CONAN run environment&lt;/h4&gt;

&lt;div class=&quot;language-shell highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;cd myproject
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;conan install .
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;source build/generators/conanrun.sh
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;cmake --preset conan-debug
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;cmake --build --preset conan-debug
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;code .
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;source build/generators/deactivate_conanrun.sh
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h3 id=&quot;conan-und-cmake-generieren-environment-und-launch-dateien&quot;&gt;CONAN und CMake generieren Environment und Launch Dateien&lt;/h3&gt;

&lt;p&gt;Das wiederholte manuelle Aufrufen von Scripts wird extrem mühsam,
wenn man zwischen vielen Conan-Projekten hin und herwechseln muss.&lt;/p&gt;

&lt;p&gt;Ich wollte daher eine Variante haben, in der jedes Projekt mit
wenigen Zeilen in VSCode geladen werden kann, und zwar mit:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;cd myproject
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;conan install .
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;code .
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Um jetzt das notwendige Environment zu “konservieren”, damit man es beim
Debuggen benutzen kann, erzeuge ich in der Conan &lt;code&gt;generate()&lt;/code&gt; Methode eine
&lt;code&gt;.env&lt;/code&gt; Datei im Build-Verzeichnis.&lt;br /&gt;
Da Windows und Linux etwas unterschiedlich sind, fällt der Code etwas größer
aus und sieht etwa so aus:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#777&quot;&gt;# conanfile.py&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;myProject_ConanFile&lt;/span&gt;(ConanFile):
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  ...
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color:#06B;font-weight:bold&quot;&gt;create_env_file&lt;/span&gt;(&lt;span style=&quot;color:#069&quot;&gt;self&lt;/span&gt;, env_file_path: &lt;span style=&quot;color:#369;font-weight:bold&quot;&gt;str&lt;/span&gt;):
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;    is_windows = &lt;span style=&quot;color:#069&quot;&gt;self&lt;/span&gt;.settings.os == &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Windows&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;    path_name = &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;PATH&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;    path_var = &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;%PATH%&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt; is_windows &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;or&lt;/span&gt; &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;$PATH&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;    lib_name = &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;LIB&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt; is_windows &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;or&lt;/span&gt; &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;LD_LIBRARY_PATH&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;    lib_var = &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;%LIB%&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt; is_windows &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;or&lt;/span&gt; &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;$LD_LIBRARY_PATH&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;    env_bin_paths = []
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;    env_lib_paths = []
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#777&quot;&gt;## add conan dependencies to PATH and LIBS array&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;for&lt;/span&gt; dep &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;in&lt;/span&gt; &lt;span style=&quot;color:#069&quot;&gt;self&lt;/span&gt;.dependencies.values():
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;      env_bin_paths.append(&lt;span style=&quot;color:#369;font-weight:bold&quot;&gt;str&lt;/span&gt;(&lt;span style=&quot;color:#369;font-weight:bold&quot;&gt;bin&lt;/span&gt;)) &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;for&lt;/span&gt; &lt;span style=&quot;color:#369;font-weight:bold&quot;&gt;bin&lt;/span&gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;in&lt;/span&gt; dep.cpp_info.bindirs
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;      env_lib_paths.append(&lt;span style=&quot;color:#369;font-weight:bold&quot;&gt;str&lt;/span&gt;(lib)) &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;for&lt;/span&gt; lib &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;in&lt;/span&gt; dep.cpp_info.libdirs
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;    &lt;span style=&quot;color:#777&quot;&gt;## add current PATH entries&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n21&quot; name=&quot;n21&quot;&gt;21&lt;/a&gt;&lt;/span&gt;    env_bin_paths.extend(os.getenv(path_name, &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;).split(os.pathsep))
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n22&quot; name=&quot;n22&quot;&gt;22&lt;/a&gt;&lt;/span&gt;    env_lib_paths.extend(os.getenv(lib_name, &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;).split(os.pathsep))
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n23&quot; name=&quot;n23&quot;&gt;23&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n24&quot; name=&quot;n24&quot;&gt;24&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#777&quot;&gt;## remove empty entries&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n25&quot; name=&quot;n25&quot;&gt;25&lt;/a&gt;&lt;/span&gt;    env_bin_paths = [e &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;for&lt;/span&gt; e &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;in&lt;/span&gt; env_bin_paths &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt; e]
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n26&quot; name=&quot;n26&quot;&gt;26&lt;/a&gt;&lt;/span&gt;    env_lib_paths = [e &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;for&lt;/span&gt; e &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;in&lt;/span&gt; env_lib_paths &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt; e]
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n27&quot; name=&quot;n27&quot;&gt;27&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n28&quot; name=&quot;n28&quot;&gt;28&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;with&lt;/span&gt; &lt;span style=&quot;color:#369;font-weight:bold&quot;&gt;open&lt;/span&gt;(env_file_path, &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;w&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;) &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;as&lt;/span&gt; f:
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n29&quot; name=&quot;n29&quot;&gt;29&lt;/a&gt;&lt;/span&gt;      path_text = os.pathsep.join(env_bin_paths)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n30&quot; name=&quot;n30&quot;&gt;30&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;      f.write(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;{}={}&lt;/span&gt;&lt;span style=&quot;color:#b0b&quot;&gt;\n&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;.format(path_name, path_text))
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n31&quot; name=&quot;n31&quot;&gt;31&lt;/a&gt;&lt;/span&gt;      lib_text = os.pathsep.join(env_lib_paths)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n32&quot; name=&quot;n32&quot;&gt;32&lt;/a&gt;&lt;/span&gt;      f.write(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;{}={}&lt;/span&gt;&lt;span style=&quot;color:#b0b&quot;&gt;\n&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;.format(lib_name, lib_text))
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n33&quot; name=&quot;n33&quot;&gt;33&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n34&quot; name=&quot;n34&quot;&gt;34&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color:#06B;font-weight:bold&quot;&gt;generate&lt;/span&gt;(&lt;span style=&quot;color:#069&quot;&gt;self&lt;/span&gt;):
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n35&quot; name=&quot;n35&quot;&gt;35&lt;/a&gt;&lt;/span&gt;    tc = CMakeToolchain(&lt;span style=&quot;color:#069&quot;&gt;self&lt;/span&gt;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n36&quot; name=&quot;n36&quot;&gt;36&lt;/a&gt;&lt;/span&gt;    tc.generate()
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n37&quot; name=&quot;n37&quot;&gt;37&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n38&quot; name=&quot;n38&quot;&gt;38&lt;/a&gt;&lt;/span&gt;    cmakedeps = CMakeDeps(&lt;span style=&quot;color:#069&quot;&gt;self&lt;/span&gt;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n39&quot; name=&quot;n39&quot;&gt;39&lt;/a&gt;&lt;/span&gt;    cmakedeps.generate()
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n40&quot; name=&quot;n40&quot;&gt;40&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n41&quot; name=&quot;n41&quot;&gt;41&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt; &lt;span style=&quot;color:#069&quot;&gt;self&lt;/span&gt;.settings.build_type == &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Debug&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;:
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n42&quot; name=&quot;n42&quot;&gt;42&lt;/a&gt;&lt;/span&gt;      env_file_path = os.path.join(&lt;span style=&quot;color:#069&quot;&gt;self&lt;/span&gt;.build_folder, &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;.env&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n43&quot; name=&quot;n43&quot;&gt;43&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#069&quot;&gt;self&lt;/span&gt;.create_env_file(env_file_path)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n44&quot; name=&quot;n44&quot;&gt;44&lt;/a&gt;&lt;/span&gt;  ...
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Anschließend wird in den Launch-Jobs für &lt;code&gt;VSCode&lt;/code&gt; die &lt;code&gt;.env&lt;/code&gt; Datei 
referenziert und somit startet jede Debug-Target-Start bzw. jeder 
Debug-CTest-Start mit den Pfaden, die Conan in seinen Dependencies
bereits aufgelöst hat.&lt;/p&gt;

&lt;div class=&quot;language-json highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;/&lt;/span&gt; &lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;v&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;s&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;c&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;o&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;d&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;e&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;l&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;u&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;n&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;c&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;h&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;j&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;s&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;o&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;n&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;0.2.0&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;configurations&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: [
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;    {
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;(gdb) CMake Target&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;cppdbg&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;MIMode&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;gdb&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;request&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;launch&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;program&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;${command:cmake.launchTargetPath}&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;args&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: [],
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;cwd&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;${command:cmake.buildDirectory}&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;envFile&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;${command:cmake.buildDirectory}/.env&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;    },
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;    {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;(gdb) CTest Launch&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;cppdbg&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;MIMode&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;gdb&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;request&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;launch&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;program&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;${cmake.testProgram}&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n21&quot; name=&quot;n21&quot;&gt;21&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;args&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: [ &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;${cmake.testArgs}&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; ],
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n22&quot; name=&quot;n22&quot;&gt;22&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;cwd&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;${cmake.testWorkingDirectory}&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n23&quot; name=&quot;n23&quot;&gt;23&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;envFile&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;${command:cmake.buildDirectory}/.env&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n24&quot; name=&quot;n24&quot;&gt;24&lt;/a&gt;&lt;/span&gt;    },
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n25&quot; name=&quot;n25&quot;&gt;25&lt;/a&gt;&lt;/span&gt;    {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n26&quot; name=&quot;n26&quot;&gt;26&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;(msvc) CMake Target&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n27&quot; name=&quot;n27&quot;&gt;27&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;cppvsdbg&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n28&quot; name=&quot;n28&quot;&gt;28&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;request&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;launch&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n29&quot; name=&quot;n29&quot;&gt;29&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;program&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;${command:cmake.launchTargetPath}&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n30&quot; name=&quot;n30&quot;&gt;30&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;args&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: [],
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n31&quot; name=&quot;n31&quot;&gt;31&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;cwd&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;${command:cmake.buildDirectory}&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n32&quot; name=&quot;n32&quot;&gt;32&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;envFile&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;${command:cmake.buildDirectory}/.env&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n33&quot; name=&quot;n33&quot;&gt;33&lt;/a&gt;&lt;/span&gt;    },
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n34&quot; name=&quot;n34&quot;&gt;34&lt;/a&gt;&lt;/span&gt;    {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n35&quot; name=&quot;n35&quot;&gt;35&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;(msvc) CTest Launch&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n36&quot; name=&quot;n36&quot;&gt;36&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;cppvsdbg&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n37&quot; name=&quot;n37&quot;&gt;37&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;request&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;launch&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n38&quot; name=&quot;n38&quot;&gt;38&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;program&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;${cmake.testProgram}&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n39&quot; name=&quot;n39&quot;&gt;39&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;args&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: [ &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;${cmake.testArgs}&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; ],
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n40&quot; name=&quot;n40&quot;&gt;40&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;cwd&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;${cmake.testWorkingDirectory}&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n41&quot; name=&quot;n41&quot;&gt;41&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;envFile&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;${command:cmake.buildDirectory}/.env&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n42&quot; name=&quot;n42&quot;&gt;42&lt;/a&gt;&lt;/span&gt;    }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n43&quot; name=&quot;n43&quot;&gt;43&lt;/a&gt;&lt;/span&gt;  ]
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n44&quot; name=&quot;n44&quot;&gt;44&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Wer &lt;code&gt;CTest&lt;/code&gt; direkt (also ohne VS-Code Debugger) startet, hat das gleiche
Problem, doch hier kann man den Fix in &lt;code&gt;CMake&lt;/code&gt; integrieren.&lt;br /&gt;
Die &lt;code&gt;.env&lt;/code&gt; Datei wird gelesen und ihr Inhalt als Array dem CTest-Property
&lt;code&gt;ENVIRONMENT&lt;/code&gt; zugeordnet.&lt;/p&gt;

&lt;div class=&quot;language-cmake highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;set(test_name &amp;quot;my_test&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;set(test_command &amp;quot;${PROJECT_NAME}&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;set(test_args)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;add_test(NAME ${test_name} COMMAND &amp;quot;${test_command}&amp;quot; ${test_args})
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;if(EXISTS &amp;quot;${CMAKE_BINARY_DIR}/.env&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;  file(READ &amp;quot;${CMAKE_BINARY_DIR}/.env&amp;quot; envfile_content)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  # The Windows &amp;quot;path1;path2&amp;quot; format needs to be escaped 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;  # to avoid conflicts with cmake&apos;s array &amp;quot;;&amp;quot; separation
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;  string(REPLACE &amp;quot;\r&amp;quot; &amp;quot;&amp;quot; envfile_content &amp;quot;${envfile_content}&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;  string(REPLACE &amp;quot;;&amp;quot; &amp;quot;\\;&amp;quot; envfile_content &amp;quot;${envfile_content}&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;  string(REPLACE &amp;quot;\n&amp;quot; &amp;quot;;&amp;quot; envfile_entries &amp;quot;${envfile_content}&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;  set_property(TEST ${test_name} 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;    PROPERTY ENVIRONMENT &amp;quot;${envfile_entries}&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;endif()
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Eine andere Option wäre dann noch Conan-Variablen in &lt;code&gt;CMake&lt;/code&gt; zu nutzen,
was ich aber nicht so gerne mache, schließlich soll &lt;code&gt;CMake&lt;/code&gt; nicht von
Conan abhängen.&lt;br /&gt;
Trotzdem helfen folgende Zeilen manchmal sehr:&lt;/p&gt;

&lt;div class=&quot;language-cmake highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;foreach(item ${CONAN_RUNTIME_LIB_DIRS})
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;  list(APPEND path_patches &amp;quot;PATH=path_list_append:${item}&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;endforeach()
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;set_property(TEST ${test_name} 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;  PROPERTY ENVIRONMENT_MODIFICATION ${path_patches})
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ein Problem, viele Möglichkeiten, und unnötig viel Komplexität.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Diese Beispiele sind das Ergebnis einer Monate-langen Herumspielerei.
Wir haben in der Firma 100+ Conan Projekte, die alle über eine gemeinsame
&lt;code&gt;Conan&lt;/code&gt;- und &lt;code&gt;CMake&lt;/code&gt;- Bibliothek zusammenhängen.&lt;/p&gt;

&lt;p&gt;So kann man sicherstellen, dass alle Projekte auf alle Fälle vorbereitet sind.
Im Einzelfall sind diese “Patches” oft nicht notwendig, doch wenn viele Ebenen
aufeinandertreffen, gibt es immer wieder mal Pfad-Probleme, die so zumindest
umgangen werden können.&lt;/p&gt;

&lt;p&gt;Ein Problem ist vor allem, dass jeder Developer anders arbeitet.
Einer startet alles von der Konsole aus, einer nutzt &lt;code&gt;Visual Studio&lt;/code&gt; und
andere nehmen &lt;code&gt;VSCode&lt;/code&gt;. Die Plattformen sind Windows, Linux, 32-bit und 64-bit
für Debug und Release.&lt;/p&gt;

&lt;p&gt;Es war echt mühsam immer wieder feststellen zu müssen, dass es genau in einer
Variante hakte, während alle anderen liefen.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Aber das ist nun einmal unser Job: Nämlich alles zu meistern.&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>Motif Explorer</title>
   <link href="https://www.opengate.at/blog/2024/11/motif-explorer/"/>
   <published>2024-11-17T12:00:00+01:00</published>
   <updated>2024-11-17T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2024/11/motif-explorer</id>
   <category term="devel" /><category term="projects" />
   <summary type="text">Mit der Ausimplementierung von Treeview und Listview Controls mit dem antiken
Motif Framework, kann ich jetzt auch 
meinen File-Browser im Unix-1990 Look-and-Feel schimmern lassen.

</summary>
   <content type="html">&lt;p&gt;Mit der Ausimplementierung von Treeview und Listview Controls mit dem antiken
&lt;a href=&quot;https://de.wikipedia.org/wiki/Motif&quot;&gt;Motif&lt;/a&gt; Framework, kann ich jetzt auch 
meinen File-Browser im Unix-1990 Look-and-Feel schimmern lassen.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Für “einfache” Controls wie Buttons oder Textfelder gibt es im &lt;code&gt;motif&lt;/code&gt; Toolkit
recht selbst-erklärende &lt;code&gt;WidgetClass&lt;/code&gt; Instanzen wie &lt;code&gt;xmPushButtonWidgetClass&lt;/code&gt;
oder &lt;code&gt;xmTextWidgetClass&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Treeviews und Listviews, wie sie in 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_Application_Programming_Interface&quot;&gt;Win32&lt;/a&gt;
seit über 30 Jahren heißen sind aber in der &lt;code&gt;motif&lt;/code&gt; Welt zusammengesetzte 
Widgets und benötigen mehr Aufmerksamkeit um Ihre Entsprechungen zu finden
und zusammenzunähen.&lt;/p&gt;

&lt;h3 id=&quot;treeviews&quot;&gt;Treeviews&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;xmOutlineWidgetClass&lt;/code&gt; bzw. die Funktion &lt;code&gt;XmCreateOutline()&lt;/code&gt; stellen uns einen
Widget-Container bereit, der seine Kind-Elemente hierarchisch ordnen, sowie
dynamisch ein- oder ausblenden kann.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Funfact: &lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_Basic_Classic&quot;&gt;Visual Basic&lt;/a&gt; 4
hatte damals auch ein selbst-fabriziertes “Outline Control”, bevor mit 
Win95/NT3.5 das Win32 Treeview Control auf den 32-bit Plattformen 
eingeführt wurde.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Mit dem Resource-Argument &lt;code&gt;XmNconnectNodes&lt;/code&gt; werden Hierarchielinien zu den
Kindelementen gezeichnet und &lt;code&gt;XmNindentSpace&lt;/code&gt; gibt an, um wie viele Pixel 
ein Kindelement eingerückt werden soll.&lt;/p&gt;

&lt;p&gt;Will man jetzt ein Element einfügen, kann man einen beliebigen Widget 
erzeugen und diesem die Resource &lt;code&gt;XmNparentNode&lt;/code&gt; mit einem Pointer zum
Eltern-Widget mitgeben, oder eben &lt;code&gt;NULL&lt;/code&gt; für ein Top-Level Element.&lt;br /&gt;
Die State-Resource &lt;code&gt;XmNnodeState&lt;/code&gt; gibt an, ob die Kinder ausgeklappt sind
(&lt;code&gt;XmOpen&lt;/code&gt;) oder nicht (&lt;code&gt;XmClosed&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Ich füge hier Push-Button-Widgets ohne sichtbaren Rahmen ein, die einen Click
Callback bei mir aufrufen, womit ich den Ein/Ausklapp-Status wechseln kann.
Der Text des Elements lässt sich wie üblich per &lt;code&gt;XmNlabelString&lt;/code&gt; bearbeiten.&lt;/p&gt;

&lt;p&gt;Und schon ist die Treeview-Alternative fertig.&lt;/p&gt;

&lt;h3 id=&quot;listview&quot;&gt;Listview&lt;/h3&gt;

&lt;p&gt;Listviews (damit meine ich immer die “Detail” Ansicht) sind quasi Tabellen,
also Datensatzlisten mit Zeilen und Spalten.&lt;/p&gt;

&lt;p&gt;Nach langem erfolglosem Herumexperimentieren konnte ich von einer uralten
&lt;code&gt;motif&lt;/code&gt;-Demoanwendung lernen, dass sich das am Besten mit der 
&lt;code&gt;xmContainerWidgetClass&lt;/code&gt; umsetzen lässt.&lt;br /&gt;
Dem kann man nämlich über &lt;code&gt;XmNlayoutType&lt;/code&gt; die Eigenschaft &lt;code&gt;XmDETAIL&lt;/code&gt; zuweisen
und dann per &lt;code&gt;XmNdetailColumnHeadingCount&lt;/code&gt; und &lt;code&gt;XmNdetailColumnHeading&lt;/code&gt; die
Column-Header definieren und benennen lassen.&lt;/p&gt;

&lt;p&gt;Anschließend fügt man pro Zeile eine &lt;code&gt;xmIconGadgetClass&lt;/code&gt; Instanz über
&lt;code&gt;XmCreateIconGadget()&lt;/code&gt; hinzu, bei der Eigenschaften wie &lt;code&gt;XmNlabelString&lt;/code&gt;
den Text der ersten Spalte definieren, und die restlichen per &lt;code&gt;XmNdetail&lt;/code&gt; 
und &lt;code&gt;XmNdetailCount&lt;/code&gt; als String-Array angefügt werden.&lt;br /&gt;
(Das ist ja in Win32 ganz ähnlich gelöst.)&lt;/p&gt;

&lt;p&gt;Sogar Icons lassen sich mit &lt;code&gt;XmNsmallIconPixmap&lt;/code&gt; und &lt;code&gt;XmNsmallIconMask&lt;/code&gt; der
Datenzeile voranstellen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;In Summe ist das Zusammensetzen von Treeviews und Listviews gar nicht so
unterschiedlich zu den Win32 Controls.&lt;br /&gt;
Das größte Problem liegt in der fehlenden Dokumentation, 
bzw. den fehlenden (oder schwer findbaren) Beispielen.&lt;/p&gt;

&lt;p&gt;Man findet tausende Codezeilen im Netz, wenn man eine Explorer-Ansicht unter
Windows selbst mit Win32 Controls ausprogrammieren kann.&lt;/p&gt;

&lt;p&gt;Bei &lt;code&gt;motif&lt;/code&gt; sehen wir nur lange Listen von Resource-Eigenschaften, aber wie
diese zusammenarbeiten und wie man bestimmte Ergebnisse damit produzieren kann
bleibt ein Geheimnis.&lt;/p&gt;

&lt;h4 id=&quot;funfact-ki-ist-dumm&quot;&gt;Funfact: KI ist dumm!&lt;/h4&gt;

&lt;p&gt;Da über &lt;code&gt;motif&lt;/code&gt; wenig Code im Umlauf ist, sind die selbstherrlichen 
Large-Language-Models nicht in der Lage auch nur irgend etwas sinnvolles
darüber herauszufinden.&lt;/p&gt;

&lt;p&gt;Doch KIs kennen die Antwort: “Ich habe keine Ahnung!” eben nicht, und erfinden
APIs, die nicht existieren und teilen selbstsicher mit, dass sie die Lösung
gefunden hätten.&lt;/p&gt;

&lt;p&gt;Es kostete mich viel Recherche-Zeit um festzustellen, dass jede zweite 
Funktion im generierten Code reine Phantasie war.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Merksatz:&lt;br /&gt;
Vertraue keiner KI,&lt;br /&gt;
denn wenn sie was nicht weiß, dann lügt sie.&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>Windows Server 2025</title>
   <link href="https://www.opengate.at/blog/2024/11/server-2025/"/>
   <published>2024-11-10T12:00:00+01:00</published>
   <updated>2024-11-10T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2024/11/server-2025</id>
   <category term="software" />
   <summary type="text">Das neue Windows 11 24H2 muss 
natürlich auch als neuer Server herauskommen, der - wie üblich - 
ein Jahr vordatiert wird.

Früher oder später wird die Software auch bei mir produktiv laufen, aber 
zur Zeit darf sich mal ein Test-Board mit der neuen 
Windows Server 2025
Version abmühen.

</summary>
   <content type="html">&lt;p&gt;Das neue &lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_11&quot;&gt;Windows 11&lt;/a&gt; 24H2 muss 
natürlich auch als neuer Server herauskommen, der - wie üblich - 
ein Jahr vordatiert wird.&lt;/p&gt;

&lt;p&gt;Früher oder später wird die Software auch bei mir produktiv laufen, aber 
zur Zeit darf sich mal ein Test-Board mit der neuen 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_Server_2025&quot;&gt;Windows Server 2025&lt;/a&gt;
Version abmühen.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Es ist ja nur mehr eine Frage der Zeit, bis meine alten ITX Boards mit 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Intel_Atom&quot;&gt;Atom&lt;/a&gt; und Celeron J1xxx und 
J3xxx CPUs nicht mehr offiziell unterstützt werden.&lt;br /&gt;
Doch vorläufig bleiben sie nach wie vor meine “Test-Boards”, die übelst 
langsam arbeitend ganz deutlich aufzeigen, ob Software gut oder schlecht
geschrieben ist.&lt;/p&gt;

&lt;p&gt;Also startete ich das Setup Program von Server 2025 auf dem bereits 
laufenden Server 2022, der nur ein paar Test-VMs aufgesetzt hatte.&lt;/p&gt;

&lt;h3 id=&quot;upgrade-erfolgreich&quot;&gt;Upgrade erfolgreich&lt;/h3&gt;

&lt;p&gt;Dass eine Neuinstallation auf einem J3455 mit 1.5 GHz nicht in 
“blitzschnell” fertig sein wird, war klar.&lt;br /&gt;
Und so dauerte das Erfassen und Ersetzen der Installation die eine 
oder andere Stunde.&lt;/p&gt;

&lt;p&gt;Doch nach einigen Neustarts und der Hardware-Neuerkennung inklusive 
Einrichtung fuhr der neue Server 2025 problemlos hoch.&lt;/p&gt;

&lt;p&gt;Alle VMs waren noch vorhanden und konnten auch gestartet werden.&lt;/p&gt;

&lt;h3 id=&quot;alles-wird-größer-und-langsamer&quot;&gt;Alles wird größer und langsamer&lt;/h3&gt;

&lt;p&gt;Auch wenn die Installation nicht sonderlich angewachsen ist, das eine oder
andere Gigabyte kommt hinzu und bleibt auch, selbst nach einem Aufräumvorgang.&lt;/p&gt;

&lt;p&gt;Die Docker Nanoserver-Images zeigen das Wachstum am deutlichsten:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;mcr.microsoft.com/windows/nanoserver:ltsc2019&lt;/code&gt;: 258 MB&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;mcr.microsoft.com/windows/nanoserver:ltsc2022&lt;/code&gt;: 292 MB&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;mcr.microsoft.com/windows/nanoserver:ltsc2025&lt;/code&gt;: 485 MB&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Da kamen knapp 200 MB hinzu, doch ich wüsste jetzt nicht, dass da mehr 
für mich nützliche Tools hinzugekommen sind.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;mcr.microsoft.com/windows/servercore:ltsc2022&lt;/code&gt;: 4.01 GB&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;mcr.microsoft.com/windows/servercore:ltsc2025&lt;/code&gt;: 7.67 GB&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Und der Core hat sich auch fast verdoppelt!&lt;/p&gt;

&lt;p&gt;In Summe ist auch die gesamte Reaktion des Systems zurückgegangen.
Ja, es ist noch bedienbar, aber das Öffnen diverser Tools leitet immer wieder
Wartezeiten ein.&lt;br /&gt;
Nun, das kennen wir schon von Windows 11 wo alleine der Explorer ein paar 
Sekunden zum Initialisieren braucht, was unter Windows 10 nur eine Sekunde
dauerte.&lt;/p&gt;

&lt;p&gt;Das “kleine” Anwachsen der Installation schlägt also auf der veralteten
Hardware deutlich härter aus, auf modernen Systemen wird das vermutlich
aber kaum merk- oder messbar sein.&lt;/p&gt;

&lt;h3 id=&quot;langzeit-probleme&quot;&gt;Langzeit-Probleme&lt;/h3&gt;

&lt;p&gt;Nachdem ich die Installation des Servers abgehakt hatte und in Summe doch
zufrieden war, vergaß ich die Maschine abzuschalten.&lt;/p&gt;

&lt;p&gt;Als ich am Folgetag die ON-LED erblickte und eine Remote-Verbindung 
aufbauen wollte, konnte ich das System allerdings nicht mehr erreichen.
Es war vermutlich eingefroren und konnte nicht mehr reaktiviert werden.&lt;/p&gt;

&lt;p&gt;Nach einem Reset und Neustart überprüfte ich die Energieeinstellungen und 
stellte sicher, dass kein Sleep-Mechanismus aktiv war.&lt;/p&gt;

&lt;p&gt;Doch leider wiederholte sich diese Art von Blockade immer wieder mal.&lt;/p&gt;

&lt;p&gt;Es sieht so aus, also würde das System bei längerem Leerlauf irgendwann
einfrieren.&lt;br /&gt;
Ob das jetzt ein Treiberproblem meiner alten Hardware ist, oder doch 
ein neues Sleep-Feature, das ich nicht kenne, weiß ich nicht.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Tja … am Ende bin ich etwas unschlüssig. Zwar ist das Upgrade geglückt
und alle Daten sind weiter verfügbar, doch das Einfrieren im Dauerbetrieb
gefällt mir gar nicht.&lt;/p&gt;

&lt;p&gt;Ich werde also warten müssen, bis ich den Server 2025 mal auf einer neueren
Maschine ausrollen werde, bevor ich mir ein Urteil zutrauen kann.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>TAB vs SPACE beim Dokumentieren</title>
   <link href="https://www.opengate.at/blog/2024/11/tab-vs-space/"/>
   <published>2024-11-03T12:00:00+01:00</published>
   <updated>2024-11-03T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2024/11/tab-vs-space</id>
   <category term="software" />
   <summary type="text">Die Debatte über TABs 
vs SPACEs ist uralt und 
wird genau so bissig geführt, wie die Frage welcher Gott der richtige ist.

Und nun erschüttert ausgerechnet 
Doxygen mein Weltbild.

</summary>
   <content type="html">&lt;p&gt;Die Debatte über &lt;a href=&quot;https://de.wikipedia.org/wiki/Tabulatortaste&quot;&gt;TABs&lt;/a&gt; 
vs &lt;a href=&quot;https://de.wikipedia.org/wiki/Leerzeichen&quot;&gt;SPACEs&lt;/a&gt; ist uralt und 
wird genau so bissig geführt, wie die Frage welcher Gott der richtige ist.&lt;/p&gt;

&lt;p&gt;Und nun erschüttert ausgerechnet 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Doxygen&quot;&gt;Doxygen&lt;/a&gt; mein Weltbild.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ich verwende TABs. Schon immer.&lt;br /&gt;
Deshalb muss es richtig sein.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Dass wir gerade in “alten” Umgebungen häufig Tabs finden ist vermutlich der
Tatsache geschuldet, dass alte Editoren in &lt;a href=&quot;https://de.wikipedia.org/wiki/MS-DOS&quot;&gt;DOS&lt;/a&gt;
und Windows vor 30 Jahren keine automatischen Einrückungen für uns gemacht 
haben und man selbst die nötigen Tasten drücken musste.&lt;/p&gt;

&lt;p&gt;Mit &lt;code&gt;TAB&lt;/code&gt; war es eben ein Tastendruck “pro Ebene”, die man einrücken wollte
und damit hoch effizient.&lt;br /&gt;
Ich hätte vermutlich durchgedreht, wenn ich bei jeder Basic-Zeile in einem 
&lt;code&gt;IF&lt;/code&gt; Block immer 4 mal auf &lt;code&gt;SPACE&lt;/code&gt; hätte hauen müssen.&lt;/p&gt;

&lt;p&gt;(Zugegeben, in Basic waren Einrückungen selten … obwohl 
&lt;a href=&quot;https://de.wikipedia.org/wiki/QBasic&quot;&gt;QBASIC&lt;/a&gt; bereits damals 
mit seinen &lt;code&gt;SUB&lt;/code&gt;s damit anfing.)&lt;/p&gt;

&lt;h3 id=&quot;vscode-ist-tab-blind-bei-der-dokumentation&quot;&gt;VSCode ist TAB-Blind bei der Dokumentation&lt;/h3&gt;

&lt;p&gt;Neulich fiel mir auf, dass die automatisch generierte Tooltip-Anzeige mit
Funktionsparametern in 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_Studio_Code&quot;&gt;Visual Studio Code&lt;/a&gt; bei 
meinen Funktionen nicht immer korrekt arbeitete.&lt;/p&gt;

&lt;p&gt;Der Text&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#777&quot;&gt;/**&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#777&quot;&gt; * @brief This is my function&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#777&quot;&gt; * @param[in] a         the first value&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#777&quot;&gt; * @param[in] something the second value&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#777&quot;&gt; */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt; my_func(&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; a, &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; something);
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;wird absolut korrekt angezeigt, wenn nur SPACEs eingesetzt werden.&lt;/p&gt;

&lt;p&gt;Ich nutzte aber nach dem Parameter oft &lt;code&gt;TAB&lt;/code&gt; zur Trennung von Parametername
und Beschreibung, damit die Beschreibungen “schön” untereinander standen.&lt;/p&gt;

&lt;p&gt;Hier verband &lt;code&gt;VSCode&lt;/code&gt; den Namen und das erste Wort der Beschreibung zu einem
Block und formatierte seine Anzeige entsprechend.&lt;/p&gt;

&lt;p&gt;Das ganze ist zwar kein Drama, man kann immer noch alles lesen, doch es 
zeigt mir auf: Doxygen-Code-Parser wollen &lt;code&gt;SPACE&lt;/code&gt;s und haben mit &lt;code&gt;TAB&lt;/code&gt;s
kleine Problemchen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ich werde das GATE Framework jetzt nicht sofort umschreiben 
… doch neue Dokus und auch neue Projekte werden in Zukunft
mehr SPACE lastig sein.&lt;/p&gt;

&lt;p&gt;Ein Kollege meinte mal:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Es gibt Studien, die belegen, dass Programmierer, 
die SPACE einsetzten, mehr Geld verdienen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Nun … wie seriös das auch sein mag, es kann nicht schaden dem Trend 
zu folgen. &lt;br /&gt;
Und der baut eben auf der Leertaste auf.&lt;/p&gt;

&lt;p&gt;Zum Glück gibt uns VSCode in seiner &lt;code&gt;settings.json&lt;/code&gt; die Möglichkeit Tabs
entweder zu erzwingen oder durch SPACEs zu ersetzten.
Und man kann das für jeden Dateityp auch justieren:&lt;/p&gt;

&lt;div class=&quot;language-json highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;/&lt;/span&gt; &lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;g&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;l&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;o&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;b&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;l&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;editor.tabSize&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;color:#00D&quot;&gt;4&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;editor.insertSpaces&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;color:#088&quot;&gt;true&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;/&lt;/span&gt; &lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;i&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;n&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;d&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;i&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;v&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;i&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;d&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;u&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;l&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;[cmake]&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: {
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;editor.tabSize&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;color:#00D&quot;&gt;2&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;editor.insertSpaces&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;color:#088&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>Pipe-streaming</title>
   <link href="https://www.opengate.at/blog/2024/10/pipestream/"/>
   <published>2024-10-27T12:00:00+01:00</published>
   <updated>2024-10-27T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2024/10/pipestream</id>
   <category term="devel" />
   <summary type="text">Individuelle Technologien brauchen individuelle APIs.
Doch, wenn es möglich ist, unterschiedliche Technologien unter eine 
API zu stellen, 
dann entstehen ungeahnte Möglichkeiten.

Und das gilt auch für Pipes.

</summary>
   <content type="html">&lt;p&gt;Individuelle Technologien brauchen individuelle APIs.
Doch, wenn es möglich ist, unterschiedliche Technologien unter eine 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Programmierschnittstelle&quot;&gt;API&lt;/a&gt; zu stellen, 
dann entstehen ungeahnte Möglichkeiten.&lt;/p&gt;

&lt;p&gt;Und das gilt auch für &lt;a href=&quot;https://de.wikipedia.org/wiki/Pipe_(Informatik)&quot;&gt;Pipes&lt;/a&gt;.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Während unter &lt;a href=&quot;https://de.wikipedia.org/wiki/Unix&quot;&gt;Unix&lt;/a&gt; alles eine Datei ist,
führt &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows&quot;&gt;Windows&lt;/a&gt; zusätzliche
APIs ein, wenn man mit Pipes arbeiten möchte.&lt;br /&gt;
Um diese Individualitäten auszugleichen, habe ich neben der &lt;code&gt;gate_pipe&lt;/code&gt;
Abstraktion nun auch den &lt;code&gt;Pipestream&lt;/code&gt; eingeführt, doch wie sich zeigt,
gibt es da einige Tücken, auf die man achten muss.&lt;/p&gt;

&lt;h3 id=&quot;blockaden-und-fehler&quot;&gt;Blockaden und Fehler&lt;/h3&gt;

&lt;p&gt;Pipes verhalten sich sowohl unter Windows und Linux recht seltsam, wenn
sie geschlossen werden, fehlerhaft sind oder gerade nichts anzubieten haben.&lt;/p&gt;

&lt;p&gt;Ein &lt;code&gt;read&lt;/code&gt; oder &lt;code&gt;write&lt;/code&gt; an einem Ende erfordert entweder ein &lt;code&gt;write&lt;/code&gt; / &lt;code&gt;read&lt;/code&gt;
auf der anderen Seite, oder die Funktion blockiert … außer man hat
Puffer aktiviert, wo dann ein paar Bytes ohne Blockaden geschrieben werden,
ohne dass sie sofort gelesen werden müssen.&lt;/p&gt;

&lt;p&gt;Schlimmer ist das Schließen von Pipes, die dann entweder per Signal,
oder speziellem Fehlercode die Gegenseite abbrechen lassen.&lt;/p&gt;

&lt;p&gt;Da Lesefunktionen quasi für immer blockieren können, ist neben dem
klassischen Lesen und Schreiben auch noch eine &lt;code&gt;is_data_available()&lt;/code&gt;
Funktion notwendig. So kann ein Programm den aktuellen Status prüfen und 
im Falle eines Leerlaufes etwas anderes tun.&lt;/p&gt;

&lt;p&gt;Bei Prozessen, die über “Named Pipes” kommunizieren, ist das besonders wichtig,
denn nur so kann man feststellen, ob ein Prozess noch läuft, auf dessen Daten
man per Pipe wartet.&lt;/p&gt;

&lt;h3 id=&quot;win32-implementierung&quot;&gt;Win32 Implementierung&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://learn.microsoft.com/de-de/windows/win32/api/namedpipeapi/nf-namedpipeapi-createpipe&quot;&gt;CreatePipe()&lt;/a&gt;
schafft zwei Enden einer anonymen Pipe. Interessanter sind aber benannte Pipes, 
die mit 
&lt;a href=&quot;https://learn.microsoft.com/de-de/windows/win32/api/winbase/nf-winbase-createnamedpipea&quot;&gt;CreateNamedPipe()&lt;/a&gt;
angelegt werden. Sie müssen im Namensraum &lt;code&gt;\\.\Pipe\&lt;/code&gt; liegen und 
eindeutig sein, z.B.:&lt;br /&gt;
&lt;code&gt;\\.\Pipe\my_named_pipe&lt;/code&gt;.&lt;br /&gt;
Danach kann dieser Pfad beliebig oft mit 
&lt;a href=&quot;https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea&quot;&gt;CreateFile()&lt;/a&gt; 
zum Lesen oder Schreiben geöffnet werden.&lt;/p&gt;

&lt;p&gt;Ob Daten zum Lesen verfügbar sind, ermittelt 
&lt;a href=&quot;https://learn.microsoft.com/de-de/windows/win32/api/namedpipeapi/nf-namedpipeapi-peeknamedpipe&quot;&gt;PeekNamedPipe()&lt;/a&gt;.&lt;br /&gt;
Tatsächlich gelesen wird mit 
&lt;a href=&quot;https://learn.microsoft.com/de-de/windows/win32/api/fileapi/nf-fileapi-readfile&quot;&gt;ReadFile()&lt;/a&gt;, 
wobei im Fehlerfall ein &lt;code&gt;ERROR_BROKEN_PIPE&lt;/code&gt; einem “End-of-stream” entspricht.&lt;/p&gt;

&lt;p&gt;Geschrieben werden Daten wie bei Dateien mit 
&lt;a href=&quot;https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-writefile&quot;&gt;WriteFile()&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;posix-implementierung&quot;&gt;POSIX Implementierung&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://pubs.opengroup.org/onlinepubs/9699919799/functions/pipe.html&quot;&gt;pipe()&lt;/a&gt;
erzeugt anonyme Pipes, aber nur 
&lt;a href=&quot;https://pubs.opengroup.org/onlinepubs/009695399/functions/mkfifo.html&quot;&gt;mkfifo()&lt;/a&gt;
lässt uns eine benannte Pipe anlegen. Einmal angelegt kann diese Pipe dann 
mit &lt;a href=&quot;https://pubs.opengroup.org/onlinepubs/9699919799/functions/open.html&quot;&gt;open()&lt;/a&gt;
zum Lesen oder Schreiben geöffnet werden.&lt;/p&gt;

&lt;p&gt;Leseaktivitäten lassen sich wie bei Sockets mit 
&lt;a href=&quot;https://pubs.opengroup.org/onlinepubs/7908799/xsh/select.html&quot;&gt;select()&lt;/a&gt;
feststellen.&lt;/p&gt;

&lt;p&gt;Zum Lesen und Schreiben sind wie bei Dateien einfach 
&lt;a href=&quot;https://pubs.opengroup.org/onlinepubs/9699919799/functions/read.html#tag_16_474&quot;&gt;read()&lt;/a&gt;
und 
&lt;a href=&quot;https://pubs.opengroup.org/onlinepubs/9699919799/functions/write.html&quot;&gt;write()&lt;/a&gt;
zu benutzen. Doch bei &lt;code&gt;write()&lt;/code&gt; muss auch auf das Signal &lt;code&gt;SIGPIPE&lt;/code&gt; beachtet 
werden, denn dieses wird gesendet, wenn die Pipe bereits geschlossen ist, 
während ein &lt;code&gt;write()&lt;/code&gt; ausgeführt wird.&lt;br /&gt;
Vergisst man darauf, wird der eigene Prozess vom Signal-Händler gekillt.&lt;/p&gt;

&lt;h3 id=&quot;auf-den-namen-kommt-es-an&quot;&gt;Auf den Namen kommt es an&lt;/h3&gt;

&lt;p&gt;Unter Windows gibt es bestimmte Konventionen, wie ein Pipe-Name aussehen 
soll. Unter Linux muss der Pipe-Pfad ein beliebiger gültiger Dateisystempfad
sein, denn genau dort wird die Pipe angelegt.&lt;/p&gt;

&lt;p&gt;Um plattformunabhängig zu sein, erstellt das GATE-Framework einen zufälligen,
aber eindeutigen Namen bei jedem Erzeugungsaufruf.&lt;br /&gt;
Eben diesen Namen kann man dann auch für die Gegenseite benutzen.&lt;/p&gt;

&lt;h3 id=&quot;vererbung&quot;&gt;Vererbung&lt;/h3&gt;

&lt;p&gt;Und am Ende braucht man auch noch eine Möglichkeit eine Pipe per “ID” an ein
Kind zu vererben. Hierzu wird das Pipe-Handle bzw. der File-Deskriptor 
dupliziert und sichergestellt, dass er an Kindprozesse vererbt werden kann.&lt;br /&gt;
Unter Windows geschieht dies mit 
&lt;a href=&quot;https://learn.microsoft.com/de-de/windows/win32/api/handleapi/nf-handleapi-duplicatehandle&quot;&gt;DuplicateHandle()&lt;/a&gt;
mit dem &lt;code&gt;bInheritHandle&lt;/code&gt; Parameter und in POSIX-Umgebungen, wo grundsätzlich 
alles vererbt werden kann, muss das Duplikat vom automatischen Schließen beim
&lt;code&gt;fork()/exec()&lt;/code&gt; ausgenommen werden.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Pipes … diese Dinge erscheinen so einfach und klein, haben mir aber durch 
ihre unterschiedlichen Eigenschaften auf jeder Plattform jede Menge Steine
in den Weg gelegt, als ich eine einheitliche Schnittstelle für die Arbeit
mit ihnen aufsetzen wollte.&lt;/p&gt;

&lt;p&gt;Zumindest ist jetzt mal ein Prototyp im GATE Framework etabliert.
Doch bis dieser in allen Details eingesetzt und getestet werden kann, wird
wohl noch etwas Zeit vergehen.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Ninja-Build für VSCode</title>
   <link href="https://www.opengate.at/blog/2024/10/ninja-build/"/>
   <published>2024-10-20T13:00:00+02:00</published>
   <updated>2024-10-20T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2024/10/ninja-build</id>
   <category term="devel" />
   <summary type="text">Ohne die explizite Angabe eines “Generators” wählt 
CMake das nächst beste
auf der Plattform. Doch wenn man ein Projekt auf mehreren Plattformen 
entwickelt und nicht immer mehrere Konfigurationen haben will,
dann kann Ninja-Build 
die Lösung sein.

Und sau-schnell ist das Tool noch obendrein.

</summary>
   <content type="html">&lt;p&gt;Ohne die explizite Angabe eines “Generators” wählt 
&lt;a href=&quot;https://de.wikipedia.org/wiki/CMake&quot;&gt;CMake&lt;/a&gt; das nächst beste
auf der Plattform. Doch wenn man ein Projekt auf mehreren Plattformen 
entwickelt und nicht immer mehrere Konfigurationen haben will,
dann kann &lt;a href=&quot;https://de.wikipedia.org/wiki/Ninja_(Software)&quot;&gt;Ninja-Build&lt;/a&gt; 
die Lösung sein.&lt;/p&gt;

&lt;p&gt;Und sau-schnell ist das Tool noch obendrein.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Ich finde es grundsätzlich gut, dass &lt;code&gt;CMake&lt;/code&gt; das Standard-Buildsystem der
Umgebung benutzt. Das wäre &lt;a href=&quot;https://de.wikipedia.org/wiki/MSBuild&quot;&gt;MSBUILD&lt;/a&gt; 
auf Windows und &lt;a href=&quot;https://de.wikipedia.org/wiki/Make&quot;&gt;Unix Makefiles&lt;/a&gt; auf 
Linux oder BSD.&lt;/p&gt;

&lt;p&gt;Wenn man aber in Tests oder Debugsitzungen Pfade benötigt 
(also Workingdirectory oder Pfad zur EXE oder Projektunterverzeichnisse 
mit Daten), dann gibt es einen gravierenden Unterschied zwischen
&lt;code&gt;MSBUILD&lt;/code&gt; und den meisten anderen Systemen:&lt;br /&gt;
&lt;code&gt;MSBUILD&lt;/code&gt; erzeugt immer Debug und Release Konfigurationen inklusive deren
Unterverzeichnisse.
Ein Ausgabeverzeichnis für Builds wäre unter Linux&lt;br /&gt;
&lt;code&gt;build/out/&lt;/code&gt; und unter Windows&lt;br /&gt;
&lt;code&gt;build/out/Debug&lt;/code&gt; oder &lt;code&gt;build/out/Release&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Diese “Kleinigkeit” kann sehr schnell lästig werden, wenn man etwa für
Tests oder das Kopieren von Bibliotheken immer ein&lt;br /&gt;
&lt;code&gt;if(WIN32) ... else()&lt;/code&gt; benötigt.&lt;/p&gt;

&lt;h3 id=&quot;lösung-ninja&quot;&gt;Lösung: Ninja&lt;/h3&gt;

&lt;p&gt;Konfiguriert man &lt;code&gt;CMake&lt;/code&gt; für &lt;code&gt;Ninja&lt;/code&gt;, entsteht im Build-Verzeichnis immer 
eine &lt;code&gt;build.ninja&lt;/code&gt; Datei mit allen Instruktionen und das Tool &lt;code&gt;ninja&lt;/code&gt;
startet dann Compiler und Linker ohne &lt;code&gt;MSBUILD&lt;/code&gt; oder &lt;code&gt;make&lt;/code&gt;.&lt;br /&gt;
Hier gibt es dann auch keine &lt;code&gt;Debug&lt;/code&gt; und &lt;code&gt;Release&lt;/code&gt; Ordnern womit die
Builds auf allen Plattformen das gleich Layout bekommen.&lt;/p&gt;

&lt;p&gt;Unter Linux ist &lt;code&gt;ninja&lt;/code&gt; meist als &lt;code&gt;ninja-build&lt;/code&gt; im Paketsystem.&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;apt-get install ninja-build
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;und Windows stellt es per &lt;code&gt;winget&lt;/code&gt; bereit&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;winget install --id=Ninja-build.Ninja
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Allerdings kann man auch auf die Webseite &lt;a href=&quot;https://ninja-build.org/&quot;&gt;ninja-build.org&lt;/a&gt;
gehen und die EXE manuell herunterladen, in ein beliebiges Verzeichnis packen
und dann dieses Verzeichnis in den &lt;code&gt;PATH&lt;/code&gt; aufnehmen.&lt;/p&gt;

&lt;h3 id=&quot;vscode-ninja-konfiguration&quot;&gt;VSCode Ninja Konfiguration&lt;/h3&gt;

&lt;p&gt;Auf der Konsole würde ein &lt;code&gt;cmake -G Ninja ....&lt;/code&gt; reichen, um vom Standard-Build
zu Ninja zu wechseln.&lt;br /&gt;
In VSCode kann man den Ninja-Zwang per &lt;code&gt;.vscode/settings.json&lt;/code&gt; bewirken:&lt;/p&gt;

&lt;div class=&quot;language-json highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;/&lt;/span&gt; &lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;v&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;s&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;c&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;o&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;d&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;e&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;s&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;e&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;t&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;t&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;i&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;n&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;g&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;s&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;j&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;s&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;o&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;n&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;cmake.configureOnOpen&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;color:#088&quot;&gt;false&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;cmake.configureOnEdit&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;color:#088&quot;&gt;false&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;cmake.generator&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Ninja&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;cmake.buildDirectory&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;${workspaceFolder}/build/ninja&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;cmake.sourceDirectory&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;${workspaceFolder}&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;cmake.configureSettings&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: {
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;MY_CMAKE_OPTION&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;color:#088&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Die Einstellung &lt;code&gt;cmake.generator&lt;/code&gt; erzwingt nun bei jedem Aufruf &lt;code&gt;ninja&lt;/code&gt; 
als Generator.
Zusätzlich kann man das &lt;code&gt;cmake.buildDirectory&lt;/code&gt; auf einen eigenen Wert
setzen, wenn einem der Standard &lt;code&gt;${workspaceFolder}/build&lt;/code&gt; nicht gefällt.&lt;/p&gt;

&lt;p&gt;Ich benutze und teste ja unterschiedliche Buildsysteme und lasse daher für
jede Variante in &lt;code&gt;build/&lt;/code&gt; noch ein zusätzliches Unterverzeichnis anlegen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ninja ist nicht nur plattformunabhängig sondern auch schnell. Ich würde
zwar nicht sagen, dass die Builds doppelt so schnell sind, aber etwas
Ersparnis gegenüber &lt;code&gt;MSBUILD&lt;/code&gt; und &lt;code&gt;make&lt;/code&gt; scheint drinnen zu sein.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Ninja&lt;/code&gt; ist daher in meinen VSCode-Debugging-Sessions immer mit dabei.&lt;/p&gt;

&lt;p&gt;Einzig, wenn man Spezialanforderungen hat, (etwa C++/CLI) oder andere 
Systeme wie &lt;a href=&quot;https://de.wikipedia.org/wiki/Conan_(Software)&quot;&gt;Conan&lt;/a&gt;, 
dann ziehe ich den OS-Standard einem Ninja-Build vor, nur um sicher 
zu stellen, dass wir garantiert das richtige Ergebnis bekommen.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>CMake Launch durch VSCode</title>
   <link href="https://www.opengate.at/blog/2024/10/cmake-vscode-launch/"/>
   <published>2024-10-13T13:00:00+02:00</published>
   <updated>2024-10-13T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2024/10/cmake-vscode-launch</id>
   <category term="devel" />
   <summary type="text">Das CMake Plugin in 
Visual Studio Code ist 
echt genial zum Bauen von Quellcodes.
Aber die Ausführung im Debugger
kommt nicht ohne Konfiguration und ein paar Sonderfälle aus.

</summary>
   <content type="html">&lt;p&gt;Das &lt;a href=&quot;https://de.wikipedia.org/wiki/CMake&quot;&gt;CMake&lt;/a&gt; Plugin in 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_Studio_Code&quot;&gt;Visual Studio Code&lt;/a&gt; ist 
echt genial zum Bauen von Quellcodes.&lt;br /&gt;
Aber die Ausführung im &lt;a href=&quot;https://de.wikipedia.org/wiki/Debugger&quot;&gt;Debugger&lt;/a&gt;
kommt nicht ohne Konfiguration und ein paar Sonderfälle aus.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Eigentlich lag meine zögerliche Migration von &lt;code&gt;Visual Studio&lt;/code&gt; zu &lt;code&gt;VSCode&lt;/code&gt; 
nur an einer Sache: die fehlende &lt;code&gt;CMake&lt;/code&gt;-Integration.&lt;br /&gt;
Folglich ist dessen Setup vermutlich der wichtigste Schritt in einem modernen
Projekt.&lt;/p&gt;

&lt;p&gt;Visual Studio Solutions haben den Vorteil, dass sie einem ein vollständiges
Debugging-Environment zur Verfügung stellen.&lt;br /&gt;
Ich schreibe Code, setzte per Maus einen Breakpoint, drücke &lt;code&gt;F5&lt;/code&gt; und 
beobachte den Programmablauf.&lt;br /&gt;
Braucht ein Programm Kommandozeilenparameter, werden die in den 
Projekteigenschaften einfach angegeben, dann &lt;code&gt;F5&lt;/code&gt; und alles läuft.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;VSCode&lt;/code&gt; kennt nur Quelldateien, die es editieren kann. Alles andere muss von
Plugins übernommen und über &lt;a href=&quot;https://de.wikipedia.org/wiki/JSON&quot;&gt;JSON&lt;/a&gt; Dateien
konfiguriert werden.&lt;/p&gt;

&lt;h3 id=&quot;cmake-targets-starten&quot;&gt;CMake Targets starten&lt;/h3&gt;

&lt;p&gt;Hat man Microsoft’s &lt;code&gt;CMake&lt;/code&gt;-Plugin installiert lässt einem der &lt;code&gt;CMake&lt;/code&gt;-Tab 
im Menü folgendes einstellen:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Configure
    &lt;ul&gt;
      &lt;li&gt;Auswahl der Build-Tools (also &lt;code&gt;MSVC&lt;/code&gt; x64, oder GCC ARM64)&lt;/li&gt;
      &lt;li&gt;Auswahl für Debug oder Release Builds&lt;/li&gt;
      &lt;li&gt;Starten des &lt;code&gt;CMake&lt;/code&gt;-Configure Schrittes zum Erzeugen aller notwendigen
Build-Scripts&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Build
    &lt;ul&gt;
      &lt;li&gt;Auswahl entweder eines bestimmten &lt;code&gt;CMake&lt;/code&gt;-Targets zum Bauen
oder Auswahl von “allen” Targets.&lt;/li&gt;
      &lt;li&gt;Starten das Bauens des Projektes für das ausgewählte Target 
oder alle Targets&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Debug
    &lt;ul&gt;
      &lt;li&gt;Auswahl eines Targets, das im Debugger gestartet werden soll&lt;/li&gt;
      &lt;li&gt;Start einer Debug-Sitzung.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nur leider braucht man für das Debuggen immer eine Konfiguration,
und die muss vorher erst mal angelegt werden.
Wir brauchen für jeden unterstützten Debugger einen Launch Eintrag.&lt;/p&gt;

&lt;h3 id=&quot;cmake-debug-launch-in-vscode&quot;&gt;CMake Debug Launch in VSCode&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ein Code sagt mehr als tausend Worte.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Meine &lt;code&gt;.vscode/launch.json&lt;/code&gt; Datei sieht in etwas so aus:&lt;/p&gt;

&lt;div class=&quot;language-json highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;/&lt;/span&gt; &lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;v&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;s&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;c&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;o&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;d&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;e&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;l&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;u&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;n&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;c&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;h&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;j&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;s&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;o&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;n&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;0.2.0&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;configurations&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: [
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;    {
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;(gdb) CMake Launch&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;cppdbg&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;request&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;launch&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;program&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;${command:cmake.launchTargetPath}&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;args&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: [],
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;cwd&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;${workspaceFolder}&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;MIMode&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;gdb&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;setupCommands&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: [
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;        {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;          &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;description&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Enable pretty-printing for gdb&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;          &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;text&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;-enable-pretty-printing&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;          &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;ignoreFailures&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;color:#088&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;        }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;      ]
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;    },
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n21&quot; name=&quot;n21&quot;&gt;21&lt;/a&gt;&lt;/span&gt;    {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n22&quot; name=&quot;n22&quot;&gt;22&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;(msvc) CMake Launch&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n23&quot; name=&quot;n23&quot;&gt;23&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;cppvsdbg&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n24&quot; name=&quot;n24&quot;&gt;24&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;request&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;launch&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n25&quot; name=&quot;n25&quot;&gt;25&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;program&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;${command:cmake.launchTargetPath}&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n26&quot; name=&quot;n26&quot;&gt;26&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;args&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: [],
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n27&quot; name=&quot;n27&quot;&gt;27&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;cwd&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;${workspaceFolder}&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n28&quot; name=&quot;n28&quot;&gt;28&lt;/a&gt;&lt;/span&gt;    }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n29&quot; name=&quot;n29&quot;&gt;29&lt;/a&gt;&lt;/span&gt;  ]
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n30&quot; name=&quot;n30&quot;&gt;30&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Da ich ja immer zwischen Windows und Linux hin- und her wechsle, sind ein
MSVC und GCC Debug-Launcher konfiguriert.&lt;/p&gt;

&lt;p&gt;Die magische Zeile lautet auf:&lt;br /&gt;
&lt;code&gt;&quot;program&quot;: &quot;${command:cmake.launchTargetPath}&quot;&lt;/code&gt;&lt;br /&gt;
Denn die sorgt dafür, dass in einer Debug-Sitzung genau das Programm gestartet
wird, das mit dem aktuell unter &lt;code&gt;Debug&lt;/code&gt; eingetragenen &lt;code&gt;CMake&lt;/code&gt; Target eingestellt
ist.&lt;/p&gt;

&lt;p&gt;Da &lt;code&gt;MSVC&lt;/code&gt; und &lt;code&gt;GDB&lt;/code&gt; unterschiedliche Plugins nutzen, sind auch die Konfigurationen
verschieden aber großteils selbsterklärend.&lt;/p&gt;

&lt;p&gt;Im Feld &lt;code&gt;args&lt;/code&gt; lässt uns Kommandozeilenparameter für das zu startende 
Programm angeben, allerdings gibt es eben nur diesen einen Eintrag.
In Visual Studio könnte man für jedes Projekt eigene Werte eintragen,
hier können wir aber nur “den nächsten Lauf” konfigurieren.&lt;/p&gt;

&lt;p&gt;Beim Starten der Debug-Sitzung erscheint ein Popup, welches einem immer die
beiden Launcher zur Auswahl stellt. Man muss eben selbst wissen, ob man
unter MSVC/WinDebug oder GCC/GDB debug-t.&lt;/p&gt;

&lt;h3 id=&quot;ctest&quot;&gt;CTest&lt;/h3&gt;

&lt;p&gt;Noch komplizierter wird das ganze bei &lt;code&gt;CTest&lt;/code&gt;.
Hat man nämlich Tests definiert, kann man diese im Test-Fenster auch 
mit einer Debug-Session starten.&lt;/p&gt;

&lt;p&gt;Hier braucht man wieder zwei weitere Launcher:&lt;/p&gt;

&lt;div class=&quot;language-json highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;0.2.0&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;configurations&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: [
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;/&lt;/span&gt; &lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;C&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;M&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;k&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;e&lt;/span&gt; &lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;L&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;u&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;n&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;c&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;h&lt;/span&gt; &lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;e&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;n&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;t&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;r&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;i&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;e&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;s&lt;/span&gt; &lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;f&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;r&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;o&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;m&lt;/span&gt; &lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;b&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;o&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;v&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;e&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;    {
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;(gdb) CTest Launch&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;cppdbg&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;request&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;launch&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;cwd&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;${cmake.testWorkingDirectory}&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;program&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;${cmake.testProgram}&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;args&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: [ &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;${cmake.testArgs}&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;],
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;    },
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;    {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;(msvc) CTest Launch&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;cppvsdbg&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;request&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;launch&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;cwd&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;${cmake.testWorkingDirectory}&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;program&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;${cmake.testProgram}&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;args&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: [ &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;${cmake.testArgs}&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;],
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;    }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n21&quot; name=&quot;n21&quot;&gt;21&lt;/a&gt;&lt;/span&gt;  ]
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n22&quot; name=&quot;n22&quot;&gt;22&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Die Token &lt;code&gt;cmake.testProgram&lt;/code&gt; und &lt;code&gt;cmake.testArgs&lt;/code&gt; sorgen dafür, dass
das Testprogramm genau so gestartet wird, wie es in &lt;code&gt;CMake&lt;/code&gt; beschrieben
wurde.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Mit den &lt;code&gt;CMake&lt;/code&gt;-Launch und &lt;code&gt;CTest&lt;/code&gt;-Launch Einträgen kann ich also das gesamte
GATE Projekt auf jeder unterstützten Plattform debuggen. Gesetzte Breakpoints
werden der gewählten Debug-Session übergeben und nun kann man in &lt;code&gt;VSCode&lt;/code&gt; 
fast genau so schön arbeiten wie unter &lt;code&gt;Visual Studio&lt;/code&gt; selbst.&lt;/p&gt;

&lt;p&gt;Der große Vorteil liegt in der Plattformunabhängigkeit.
Einziger Nachteil ist die etwas mühsamere Verwaltung über &lt;code&gt;JSON&lt;/code&gt; Dateien.&lt;/p&gt;

&lt;p&gt;Leider gibt es bei komplexeren Systemen mit Abhängigkeiten auch wieder
ein paar Probleme.&lt;br /&gt;
z.B. mit &lt;a href=&quot;https://de.wikipedia.org/wiki/Conan_(Software)&quot;&gt;Conan&lt;/a&gt;.&lt;br /&gt;
Aber das ist eine andere Geschichte.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>6 Jahre Bloggerei</title>
   <link href="https://www.opengate.at/blog/2024/10/blog-year-6/"/>
   <published>2024-10-06T13:00:00+02:00</published>
   <updated>2024-10-06T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2024/10/blog-year-6</id>
   <category term="projects" />
   <summary type="text">Wieder ein Jahr vorbei und 2018 liegt wieder etwas weiter in der Vergangenheit.

Und ich habe weiter keine Chance auf Frühpensionierung …

</summary>
   <content type="html">&lt;p&gt;Wieder ein Jahr vorbei und 2018 liegt wieder etwas weiter in der Vergangenheit.&lt;/p&gt;

&lt;p&gt;Und ich habe weiter keine Chance auf Frühpensionierung …&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Beruflich wie privat ging es im letzten Jahr recht intensiv zu. Und wenn man
zu viel zu tun hat, reduziert sich die “freiwillige” Schreibarbeit automatisch.&lt;/p&gt;

&lt;p&gt;Wöchentlich 2 Posts zu schreiben war mir zu viel, wodurch sich der Durchsatz 
auf die Hälfte reduziert hat. Das ist auch der Tatsache geschuldet, dass ich
viele Themen, die sich am Anfang des Blogs aufgestaut hatten jetzt abgeflossen
sind und somit nur noch richtige “Tagesthemen” übrigbleiben.&lt;/p&gt;

&lt;h3 id=&quot;code-statistik&quot;&gt;Code Statistik&lt;/h3&gt;

&lt;p&gt;Das GATE Projekt besteht aktuell aus etwa &lt;code&gt;292 000&lt;/code&gt; Zeilen rein von mir 
geschriebenem Code.&lt;br /&gt;
Um etwas anzugeben: Bei einer Norm-A4-Seite mit 30 Zeilen wären das über 
9700 Buchseiten. So erklärt sich mir wie 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Thomas_Brezina&quot;&gt;Thomas Brezina&lt;/a&gt; in meiner 
Kindheit 100 Bücher zur Knickerbockerbande schreiben konnte, wo ein Buch 
etwa 120 Seiten hatte.&lt;/p&gt;

&lt;p&gt;Mein größtes kommerzielles C++ Projekt, an dem ich 8 Jahre gearbeitet hatte,
kam auf etwa &lt;code&gt;475 000&lt;/code&gt; Zeilen C/C++ Code.&lt;/p&gt;

&lt;p&gt;In absoluten Zahlen mit “beigelegten” (und teilweise überarbeiteten) Fremdcode
kommt das GATE Framework auf &lt;code&gt;1 074 000&lt;/code&gt; Zeilen (Tja SSL und SQLite hauen 
eben ordentlich rein). Doch mein früheres Projekt endete mit &lt;code&gt;971 000&lt;/code&gt; Zeilen,
was das GATE Framework nun zu meinen größten selbst verwalteten C/C++Projekt 
macht.&lt;/p&gt;

&lt;p&gt;Wenn man bedenkt, dass das ein Freizeit-Abend-Projekt ist, kann sich das
schon sehen lassen.&lt;/p&gt;

&lt;h3 id=&quot;buildsystem-vs-code&quot;&gt;Buildsystem vs Code&lt;/h3&gt;

&lt;p&gt;Heute ist das automatische Bauen von Projekten, genannt CI/CD oder 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Kontinuierliche_Integration&quot;&gt;Continuous Integration&lt;/a&gt; /
&lt;a href=&quot;https://de.wikipedia.org/wiki/Continuous_Delivery&quot;&gt;Continous Delivery&lt;/a&gt;
ein Hauptbestandteil der Softwareentwicklung. Ich sitze also immer länger
über Build-Scripts und an dem Hinzufügen neuer Plattformen, als am Schreiben
von Protokollen, Formaten oder Infrastruktur … leider.&lt;/p&gt;

&lt;p&gt;Wenn ich mich an meine erstes Projekt erinnere, wo die 32-Bit Windows &lt;code&gt;.exe&lt;/code&gt;
am Nachbar-PC gebaut und gleich so auf den Webspace hochgeladen wurde, läuft
die Welt heute ganz anders.&lt;br /&gt;
Ohne einen Build-Server, der Windows, Linux für je 3 CPU Architekturen baut,
gibt es kein Deployment. Die automatische Ausführung von Unit-Tests ist ebenso
Teil dieses Prozesses, wie das Erstellen von Installationspaketen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Somit verschiebt sich auch der Fokus im Blog von reinem Code etwas in Richtung
Buildserver, aber das schadet sicher nicht.&lt;/p&gt;

&lt;p&gt;Und wenn wieder mal eine neue Technik wie eine Sau durchs Dorf getrieben wird,
bleibt sie auch mir nicht erspart und wird früher oder später integriert.&lt;/p&gt;

&lt;p&gt;Die Herausforderung geht als weiter.&lt;br /&gt;
Mal sehen, was im Jahr 2026 dann alles passieren wird.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>UCONTEXT Puffergröße</title>
   <link href="https://www.opengate.at/blog/2024/09/ucontext-size/"/>
   <published>2024-09-29T13:00:00+02:00</published>
   <updated>2024-09-29T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2024/09/ucontext-size</id>
   <category term="devel" />
   <summary type="text">Meine Tests liefen alle super am PC. Doch unter 
ARM64 krachte es gehörig.

Sieht so aus, als wären (wieder mal) die 
Koroutinen Schuld.

Aber warum?

</summary>
   <content type="html">&lt;p&gt;Meine Tests liefen alle super am PC. Doch unter 
&lt;a href=&quot;https://de.wikipedia.org/wiki/ARM-Architektur&quot;&gt;ARM64&lt;/a&gt; krachte es gehörig.&lt;/p&gt;

&lt;p&gt;Sieht so aus, als wären (wieder mal) die 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Koroutine&quot;&gt;Koroutinen&lt;/a&gt; Schuld.&lt;/p&gt;

&lt;p&gt;Aber warum?&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Im GATE Projekt herrscht in den öffentlich Headern striktes Include-Verbot
für System-spezifische Header.&lt;br /&gt;
Bibliotheken wie &lt;a href=&quot;https://de.wikipedia.org/wiki/Boost_(C%2B%2B-Bibliothek)&quot;&gt;boost&lt;/a&gt; 
versauen einem schon alleine wegen ihrer Includes von &lt;code&gt;windows.h&lt;/code&gt; und unter
Linux von allen Posix-, Netzwerk und Kernel-Headern ein performantes Ergebnis.&lt;/p&gt;

&lt;p&gt;Doch … wie kann man eine öffentliche Datenstruktur schaffen, die 
systemspezifische Typen wie &lt;code&gt;jmp_buf&lt;/code&gt; oder &lt;code&gt;ucontext&lt;/code&gt; beinhaltet ohne dass
die Typen definiert sind?&lt;/p&gt;

&lt;p&gt;Ein Antwort wären Heap-Allokationen … doch diese fragmentieren den Speicher
und erfordern ein zusätzliches Aufräum-Management.&lt;/p&gt;

&lt;p&gt;Die Alternative sind Puffer, die als kleinster gemeinsamer Nenner aller 
möglichen Puffergrößen entsprechend groß sind um “alles” fressen zu können.&lt;/p&gt;

&lt;p&gt;Mit der Strategie bin ich bisher gut gefahren, bis sie mich neulich in den
Arsch biss.&lt;/p&gt;

&lt;h3 id=&quot;arm64-stack-status&quot;&gt;ARM64 Stack-Status&lt;/h3&gt;

&lt;p&gt;Ich messe Puffer für native Datenstrukturen gerne in &lt;code&gt;void*&lt;/code&gt; Einheiten.
Hat eine Struktur 5 Member, sind die selten größer als 5 Pointer, und mit dem
Doppelten kann die Obergrenze nicht überschritten werden … so der Gedanke.&lt;/p&gt;

&lt;p&gt;Bei meinen X86 Systemen kam ich vermutlich bei der Durchsicht der System-
Header auf den Wert &lt;code&gt;64&lt;/code&gt; und legte damit fest, dass ein Stack-Kontext nie
größer als 512 Bytes (bei 64-bit: 8 Bytes * 64 Einheiten) sein wird. Kein 
Prozessor hat mehr als 32 Register … also warum Speicher verschwenden.&lt;/p&gt;

&lt;p&gt;Tja … &lt;code&gt;ARM64&lt;/code&gt; sprengt diese Grenze vielfach, und damit auch alle meine
Prozesse mit Koroutinen-Code.&lt;br /&gt;
Wer in &lt;code&gt;/usr/include/aarch64-linux-gnu/sys/ucontext.h&lt;/code&gt; nachsieht, stellt fest,
dass neben den CPU-Registern noch 4 KByte für FP/SIMD Zustände reserviert werden.&lt;/p&gt;

&lt;p&gt;Und genau hier haben die &lt;code&gt;ucontext&lt;/code&gt; Funktionen in meinen viel zu kleinen 
Puffer Daten im anliegenden Speicher auf dem Stack überschrieben.&lt;/p&gt;

&lt;h3 id=&quot;neue-größenordnung&quot;&gt;Neue Größenordnung&lt;/h3&gt;

&lt;p&gt;Die neue Implementierung geht von 1 KByte für “übliche” Prozessoren aus, sowie
4.5 KByte für &lt;code&gt;ARM64&lt;/code&gt;. Ab sofort kann für jede Architektur ein Makro gesetzt werden,
dass die interne Puffergröße anpasst.&lt;/p&gt;

&lt;p&gt;Kaum war der Patch implementiert, liefen auch wieder alle Tests auf der &lt;code&gt;ARM64&lt;/code&gt;
Plattform problemlos durch.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;4.5 KByte … W-T-F ?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Tja, hier merkt man, dass ich ein Kind der 90er Jahre bin. Das Speichern aller
CPU-Zustände ging sich damals in wenigen Bytes aus. 
64 Bytes waren da schon “viel”.&lt;/p&gt;

&lt;p&gt;Doch heute ist ein Prozessor das, was früher 8 unterschiedliche Prozessoren
waren. Kein Wunder also, dass Linux “zur Sicherheit” gleich mehrere Kilobyte
reserviert.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Also Augen auf bei neuen Plattformen!&lt;br /&gt;
Wie viele Bytes mögen die wohl für einen Kontextstatus brauchen?&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>CONAN Builds mit CTest</title>
   <link href="https://www.opengate.at/blog/2024/09/conan-ctest/"/>
   <published>2024-09-22T13:00:00+02:00</published>
   <updated>2024-09-22T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2024/09/conan-ctest</id>
   <category term="devel" />
   <summary type="text">Tests gehören zum Build-Vorgang fix dazu. Besonders wenn daraus ein 
Conan Paket werden soll.

Es macht also Sinn einen CTest Lauf nach jedem CMake-Build auszuführen.

</summary>
   <content type="html">&lt;p&gt;Tests gehören zum Build-Vorgang fix dazu. Besonders wenn daraus ein 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Conan_(Software)&quot;&gt;Conan&lt;/a&gt; Paket werden soll.&lt;/p&gt;

&lt;p&gt;Es macht also Sinn einen &lt;code&gt;CTest&lt;/code&gt; Lauf nach jedem CMake-Build auszuführen.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Einer der größeren Fehler, die mir und meinen Kollegen beruflich passiert ist,
war die fälschliche Nutzung von &lt;code&gt;Conan&lt;/code&gt; Test-Packages für Unit-Tests.&lt;br /&gt;
Test-Packages sind (wie in der Doku beschreiben) nur dafür da, die Pakete und
ihren Inhalt auf Anwesenheit zu testen, und nicht um komplexe interne 
Funktionstests auszuführen.&lt;/p&gt;

&lt;p&gt;Hier wurde viel herumgescriptet um im Endeffekt eine suboptimale Testreihe
auszuführen.&lt;br /&gt;
Die Lösung wäre so nahe gelegen … aber wir konnten sie alle nicht sehen:
&lt;code&gt;cmake&lt;/code&gt; bzw &lt;code&gt;ctest&lt;/code&gt;&lt;/p&gt;

&lt;h3 id=&quot;ctest&quot;&gt;CTest&lt;/h3&gt;

&lt;p&gt;Der größte Vorteil von &lt;code&gt;CTest&lt;/code&gt; ist, dass sich Tests als Targets in den &lt;code&gt;CMake&lt;/code&gt; 
Baum einfügen, eine von außen abrufbare Schnittstelle haben und daher von IDEs 
direkt oder indirekt unterstützt werden.&lt;/p&gt;

&lt;p&gt;Ein Test ist in C/C++ in der Regel ein eigener Prozess, der mitgebaut wird,
aber nicht per &lt;code&gt;cmake --install&lt;/code&gt; weiterverteilt wird. Jedoch kann er durch den 
Aufruf von &lt;code&gt;ctest&lt;/code&gt; im Build-Verzeichnis ausgeführt werden und sein Ergebnis wird
per Exit-Code als Erfolg oder Misserfolg in einen Bericht eingefügt.&lt;/p&gt;

&lt;p&gt;So entstehen &lt;a href=&quot;https://de.wikipedia.org/wiki/JUnit&quot;&gt;JUnit&lt;/a&gt; XML Dateien, die wiederum 
das Test-Ergebnis an Kontrollsysteme melden können.&lt;/p&gt;

&lt;p&gt;Tests werden aktiviert, wenn man in der Haupt-&lt;code&gt;CMakeLists.txt&lt;/code&gt;-Datei die Zeilen&lt;/p&gt;

&lt;div class=&quot;language-cmake highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;include(CTest)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;enable_testing()
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;einfügt.&lt;br /&gt;
Für jedes Testprogramm ist dann noch ein eigenes Target notwendig, das als Test
registriert wird:&lt;/p&gt;

&lt;div class=&quot;language-cmake highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;project(mytest)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;file(GLOB my_sources &amp;quot;*.h&amp;quot; &amp;quot;*.c&amp;quot; &amp;quot;*.cpp&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;add_executable(${PROJECT_NAME} ${my_sources})
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;add_test(NAME ${PROJECT_NAME} COMMAND ${PROJECT_NAME})
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Idealerweise nutzt man dann noch ein fertiges Test-Framework wie &lt;code&gt;boost::test&lt;/code&gt;
oder Google &lt;code&gt;gtest&lt;/code&gt;, welch per Standard den Exit-Code auf &lt;code&gt;0&lt;/code&gt; oder &lt;code&gt;!=0&lt;/code&gt; im 
Erfolgs- und Fehlerfall setzen.&lt;/p&gt;

&lt;h3 id=&quot;das-conan-dependency-problem&quot;&gt;Das CONAN-Dependency-Problem&lt;/h3&gt;

&lt;p&gt;Tja, und wenn man jetzt sein CONAN-Paket erstellt, sieht der Build+Test
Vorgang etwa so aus:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color:#06B;font-weight:bold&quot;&gt;build&lt;/span&gt;(&lt;span style=&quot;color:#069&quot;&gt;self&lt;/span&gt;):
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;  cmake = CMake(&lt;span style=&quot;color:#069&quot;&gt;self&lt;/span&gt;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  cmake.configure()
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  cmake.build()
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  cmake.ctest()
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Das bedeutet, dass in einem &lt;code&gt;conan create&lt;/code&gt; oder &lt;code&gt;conan build&lt;/code&gt; Prozess auch 
alles funktioniert, da CONAN hier die Umgebungsvariablen so setzt, dass 
Abhängigkeiten im CONAN-Cache per &lt;code&gt;PATH&lt;/code&gt; oder &lt;code&gt;LD_LIBRARY_PATH&lt;/code&gt; gefunden
werden.&lt;/p&gt;

&lt;p&gt;Doch wer nur &lt;code&gt;conan install&lt;/code&gt; einsetzt und dann seinen Code z.B. in 
Visual Studio Code ausführen und debuggen will, dem fehlen nun diverse
&lt;code&gt;.dll&lt;/code&gt;/&lt;code&gt;.so&lt;/code&gt; Pfade.&lt;br /&gt;
Bibliotheken die direkt gelinkt werden haben noch eine “gute Chance” gefunden
zu werden, aber alles was zur Laufzeit geladen wird wie z.B. Plugins oder
optionale Komponenten finden mit &lt;code&gt;LoadLibrary()&lt;/code&gt; oder &lt;code&gt;dl_open()&lt;/code&gt; ihr Ziel
im Conan Cache nicht.&lt;/p&gt;

&lt;p&gt;Meine Lösung für dieses Problem war die Erzeugung einer &lt;code&gt;.env&lt;/code&gt; Environment
Datei, die mit allen Pfaden von bekannten Abhängigkeiten befüllt war.
Eine solche Datei konnte dann auch in &lt;code&gt;CMakeLists.txt&lt;/code&gt; der Test-Ausführung
zugeführt werden um somit die Tests mit dem vollständigen Environment
auszuführen.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color:#06B;font-weight:bold&quot;&gt;gen_env_file_with_conan_deps&lt;/span&gt;(&lt;span style=&quot;color:#069&quot;&gt;self&lt;/span&gt;, envfile_path: &lt;span style=&quot;color:#369;font-weight:bold&quot;&gt;str&lt;/span&gt;):
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;# init with system-defined values&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  all_bin_paths = os.getenv(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;PATH&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;, &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;).split(os.pathsep)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  all_lib_paths = os.getenv(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;LD_LIBRARY_PATH&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;, &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;).split(os.pathsep)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;# add conan dependencies&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;for&lt;/span&gt; dep &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;in&lt;/span&gt; &lt;span style=&quot;color:#069&quot;&gt;self&lt;/span&gt;.dependencies.values():
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;for&lt;/span&gt; lib &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;in&lt;/span&gt; dep.cpp_info.libdirs:
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;      add_lib_paths.append(&lt;span style=&quot;color:#369;font-weight:bold&quot;&gt;str&lt;/span&gt;(lib))
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;for&lt;/span&gt; &lt;span style=&quot;color:#369;font-weight:bold&quot;&gt;bin&lt;/span&gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;in&lt;/span&gt; dep.cpp_info.bindirs:
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;       add_bin_paths.append(&lt;span style=&quot;color:#369;font-weight:bold&quot;&gt;str&lt;/span&gt;(&lt;span style=&quot;color:#369;font-weight:bold&quot;&gt;bin&lt;/span&gt;))
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;with&lt;/span&gt; &lt;span style=&quot;color:#369;font-weight:bold&quot;&gt;open&lt;/span&gt;(envfile_path, &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;w&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;) &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;as&lt;/span&gt; f:
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;    f.write(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;PATH={}&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;.format( os.pathsep.join(add_bin_paths)))
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;    f.write(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;LD_LIBRARY_PATH={}&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;.format( os.pathsep.join(add_bin_paths)))
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Wird diese Methode von Conan’s &lt;code&gt;generate()&lt;/code&gt; Methode aus mit&lt;br /&gt;
&lt;code&gt;self.gen_env_file_with_conan_deps(os.path.join(self.build_folder, &apos;.env&apos;))&lt;/code&gt;&lt;br /&gt;
aufgerufen, dann kann diese Datei von Visual-Studio-Code
Launch-tasks benutzt oder von &lt;code&gt;CMake&lt;/code&gt; ausgelesen werden und mit ein paar
Hacks als &lt;code&gt;ENVIRONMENT&lt;/code&gt; Eigenschaft des Tests gesetzt werden:&lt;/p&gt;

&lt;div class=&quot;language-cmake highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;if(EXISTS &amp;quot;${CMAKE_BINARY_DIR}/.env&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;  file(READ &amp;quot;${CMAKE_BINARY_DIR}/.env&amp;quot; envfile_content)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  string(REPLACE &amp;quot;\r&amp;quot; &amp;quot;&amp;quot; envfile_content &amp;quot;${envfile_content}&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  string(REPLACE &amp;quot;;&amp;quot; &amp;quot;\\;&amp;quot; envfile_content &amp;quot;${envfile_content}&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  string(REPLACE &amp;quot;\n&amp;quot; &amp;quot;;&amp;quot; envfile_entries &amp;quot;${envfile_content}&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;  set_property(TEST ${PROJECT_NAME} PROPERTY ENVIRONMENT &amp;quot;${envfile_entries}&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;endif()
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Tests sind super, Tests sind gut … aber können bei erhöhter Komplexität
auch anstrengend werden.&lt;/p&gt;

&lt;p&gt;Ein grobes Problem mit Conan-Builds ist, dass Tests innerhalb der 
&lt;code&gt;Conan&lt;/code&gt; Umgebung immer anders laufen, als während der Entwicklung innerhalb
einer IDE.&lt;br /&gt;
Und &lt;code&gt;CMake&lt;/code&gt; kennt in erster Line nur Build-Details, jedoch keine erweiterten
Umgebungs- und Ausführungsparameter.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Tja, so ist das Leben.&lt;br /&gt;
Aber es wäre ja langweilig, wenn immer gleich alles auf Anhieb funktioniert.&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>CMake ALIAS target</title>
   <link href="https://www.opengate.at/blog/2024/09/cmake-alias-target/"/>
   <published>2024-09-15T13:00:00+02:00</published>
   <updated>2024-09-15T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2024/09/cmake-alias-target</id>
   <category term="devel" />
   <summary type="text">
  Wie soll man CMake-Targets 
eigentlich benennen?


Die Autoren haben “Vorstellungen”, Conan 
hat “Alternativen” und ich habe meine eigenen Wünsche.

Doch zum Glück lassen sich solche Namen in CMake leicht nachbessern.

</summary>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;Wie soll man &lt;a href=&quot;https://de.wikipedia.org/wiki/CMake&quot;&gt;CMake&lt;/a&gt;-Targets 
eigentlich benennen?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Die Autoren haben “Vorstellungen”, &lt;a href=&quot;https://de.wikipedia.org/wiki/Conan_(Software)&quot;&gt;Conan&lt;/a&gt; 
hat “Alternativen” und ich habe meine eigenen Wünsche.&lt;/p&gt;

&lt;p&gt;Doch zum Glück lassen sich solche Namen in &lt;code&gt;CMake&lt;/code&gt; leicht nachbessern.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Da meine GATE Builds auch mit antiken DOS-Compilern wie 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Watcom&quot;&gt;OpenWatcom&lt;/a&gt; zurecht kommen müssen und deshalb 
erweiterte Einstellungen notwendig sind, habe ich in den &lt;code&gt;extlibs&lt;/code&gt; den 
Buildvorgang einiger Bibliotheken anpassen bzw. selbst ausimplementieren 
müssen.&lt;/p&gt;

&lt;p&gt;Damit am Ende alles mit &lt;code&gt;CMake&lt;/code&gt; läuft, habe ich mir auch ein paar 
“Target-Namen” einfallen lassen, die vom Original abwichen.&lt;/p&gt;

&lt;p&gt;Die &lt;code&gt;zlib&lt;/code&gt; ist hier ein etwas seltsames Beispiel, weil sie für Windows
und Linux unterschiedliche Bibliotheksnamen vorsieht 
(&lt;code&gt;zlib&lt;/code&gt; und &lt;code&gt;libz&lt;/code&gt;, bzw. nur &lt;code&gt;z&lt;/code&gt; als Target)&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Conan&lt;/code&gt; hingegen stülpt über alle Projekte den neuen Standard für 
Target-Namen drüber, und geht von &lt;code&gt;ZLIB::ZLIB&lt;/code&gt; aus.&lt;/p&gt;

&lt;p&gt;Da das GATE Projekt sowohl mit der Eigenlösung, als auch mit &lt;code&gt;Conan&lt;/code&gt; Varianten
zurecht kommen soll, hatte ich ursprünglich jede Menge an &lt;code&gt;if() else()&lt;/code&gt; 
Zeilen im &lt;code&gt;CMake&lt;/code&gt; Code.&lt;/p&gt;

&lt;h3 id=&quot;add_libraryalias&quot;&gt;add_library(ALIAS)&lt;/h3&gt;

&lt;p&gt;Die Sache lässt sich aber viel einfacher lösen.
Anstatt beim Linken auszu-if-fen, ob Target-Name 1 oder 2 gewählt werden soll,
füge ich beim Importieren der gewünschten Quellen gleich einen Alias-Namen
ein, der alle Implementierungen auf den gleichen Namen umleitet, nämlich den
von &lt;code&gt;Conan&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Und so findet man im GATE &lt;code&gt;CMakeLists.txt&lt;/code&gt; Passagen wie:&lt;/p&gt;

&lt;div class=&quot;language-cmake highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;if(GATE_EXTLIB_ZLIB)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;  if(GATE_HAS_EXTLIB_ZLIB AND NOT GATE_NO_LOCAL_EXTLIB_BUILDS)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;    add_subdirectory(&amp;quot;${EXTLIBS_ROOT_PATH}/zlib&amp;quot; &amp;quot;extlibs/zlib&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;    add_library(ZLIB::ZLIB ALIAS &amp;quot;zlib&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  else()
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;    find_package(ZLIB REQUIRED)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  endif()
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;endif(GATE_EXTLIB_ZLIB)
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Hier wird dann entweder “mein” lokaler Name auf das gesetzt, was
&lt;code&gt;Conan&lt;/code&gt; ansonsten erzeugen würde, oder ich benutzte &lt;code&gt;find_package()&lt;/code&gt; 
und erwarte von Anfang an das, was &lt;code&gt;Conan&lt;/code&gt; liefert.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Die Alias Variante ist somit viel eleganter und vereinfacht den Code
im &lt;code&gt;CMake&lt;/code&gt; Projekt.&lt;/p&gt;

&lt;p&gt;Parallel sollte man nicht vergessen, dass auch der von &lt;code&gt;Conan&lt;/code&gt; publizierte
Name im Endeffekt ein Alias auf einen internen Build-Namen ist.&lt;/p&gt;

&lt;p&gt;Wie auch immer … &lt;code&gt;Conan&lt;/code&gt; sollte heute “der” Standard sein, wie 
Bibliotheken benannt sind, damit wir endlich einheitlich mit 
C oder C++ programmieren können.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Windows CE Builds im Docker Container</title>
   <link href="https://www.opengate.at/blog/2024/09/cegcc-docker/"/>
   <published>2024-09-08T13:00:00+02:00</published>
   <updated>2024-09-08T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2024/09/cegcc-docker</id>
   <category term="devel" /><category term="software" /><category term="projects" />
   <summary type="text">Bisher waren für meine Windows CE
Experimente immer eine Windows-XP VM mit Visual Studio 2005 notwendig, 
wo ich per Build-Script einen elend langen Build-Prozess anstarten musste.

Doch neulich fand ich eine GCC
Variante, die WinCE-Binaries bauen konnte, und zwar im Linux Docker Container.

</summary>
   <content type="html">&lt;p&gt;Bisher waren für meine &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_CE&quot;&gt;Windows CE&lt;/a&gt;
Experimente immer eine Windows-XP VM mit Visual Studio 2005 notwendig, 
wo ich per Build-Script einen elend langen Build-Prozess anstarten musste.&lt;/p&gt;

&lt;p&gt;Doch neulich fand ich eine &lt;a href=&quot;https://de.wikipedia.org/wiki/GNU_Compiler_Collection&quot;&gt;GCC&lt;/a&gt;
Variante, die WinCE-Binaries bauen konnte, und zwar im Linux Docker Container.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Im &lt;a href=&quot;https://github.com/enlyze&quot;&gt;Github Account enlyze&lt;/a&gt; befindet sich still
und heimlich die Lösung all meiner Windows-CE Probleme.&lt;br /&gt;
Nämlich ein Linux &lt;a href=&quot;https://de.wikipedia.org/wiki/Docker_(Software)&quot;&gt;Docker&lt;/a&gt; Image 
mit einer speziellen GCC Variante, die Windows-CE Binaries bauen kann.&lt;/p&gt;

&lt;p&gt;Ich habe mir hierfür das Image angepasst und als neues Build-Tag
in mein OpenGATE Repository aufgenommen:&lt;br /&gt;
&lt;a href=&quot;https://hub.docker.com/r/opendockergate/gate-build-env/tags&quot;&gt;hub.docker.com/r/opendockergate/gate-build-env/tags&lt;/a&gt; 
&lt;code&gt;deb.12.cegcc.arm.9.3.1&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Dem Image wurde nur &lt;code&gt;git&lt;/code&gt;, &lt;code&gt;cmake&lt;/code&gt;, &lt;code&gt;nodejs&lt;/code&gt; und ein paar Zusatztools
hinzugefügt, die zum Bauen unter &lt;a href=&quot;https://de.wikipedia.org/wiki/Forgejo&quot;&gt;Forgejo&lt;/a&gt;
notwendig sind.&lt;/p&gt;

&lt;p&gt;Für &lt;code&gt;CMake&lt;/code&gt; wurde dem GATE Projekt eine neue Toolchain-Datei hinzugefügt:&lt;/p&gt;

&lt;div class=&quot;language-cmake highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;set(CMAKE_SYSTEM_NAME &amp;quot;WindowsCE&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;set(CMAKE_SYSTEM_PROCESSOR &amp;quot;arm&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;set(TOOLCHAIN_PREFIX &amp;quot;arm-mingw32ce&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;set(CMAKE_C_COMPILER &amp;quot;${TOOLCHAIN_PREFIX}-gcc&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;set(CMAKE_CXX_COMPILER &amp;quot;${TOOLCHAIN_PREFIX}-g++&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;set(CMAKE_CROSSCOMPILING TRUE)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;set(MINGW TRUE)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;set(CMAKE_FIND_ROOT_PATH &amp;quot;/opt/cegcc-arm&amp;quot; &amp;quot;/opt/cegcc-arm/arm-mingw32ce&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Beim Bauen werden so die richtigen Compiler Tools im Docker Container gefunden.&lt;/p&gt;

&lt;h3 id=&quot;unterschiede-zum-msvc&quot;&gt;Unterschiede zum MSVC&lt;/h3&gt;

&lt;p&gt;Tatsächlich brauchte es jede Menge Tests und Anpassungen am Sourcecode und
am Buildsystem, bis die ersten Binaries erfolgreich gebaut werden konnten.&lt;/p&gt;

&lt;p&gt;Unter &lt;code&gt;MSVC&lt;/code&gt; fehlen große Bestandteile der C-Standard-Bibliothek, welche
durch meine eigene Implementierung ersetzt wurden. Doch im GCC sind einige
dieser Funktionen oder Makros vorhanden, und so musste ich diese Spezialfälle
in meiner &lt;code&gt;stdcpatches&lt;/code&gt; Bibliothek anpassen.&lt;/p&gt;

&lt;p&gt;Früher war ein &lt;code&gt;if(WINCE)&lt;/code&gt; gleichbedeutend mit einem &lt;code&gt;if(MSVC)&lt;/code&gt;, doch nun 
gibt es die feine Unterscheidung:&lt;/p&gt;

&lt;div class=&quot;language-cmake highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;if(WINCE)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;  if(MSVC)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;    # VS2005 patches
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  else()
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;    # GCC-WinCE patches
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;  endif()
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;endif()
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Am Ende gelang das Experiment und ab sofort erzeugt jeder Commit ins
Codeberg GATE Repository auch einen GCC Windows CE Build.&lt;/p&gt;

&lt;p&gt;Tatsächlich existiert auch ein &lt;code&gt;i386&lt;/code&gt; Output, den ich aber nie testen konnte.
Den handelsüblichen &lt;code&gt;ARM&lt;/code&gt; Output habe ich jedoch auf meinen WinCE-Laptop
erfolgreich ausgeführt.&lt;/p&gt;

&lt;p&gt;An dieser Stelle kann ich wieder nur betonen:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Es ist unglaublich, was wir heute mit Linux und dem GCC erreichen können.&lt;br /&gt;
Niemand hätte sich im Jahr 2000 vorstellen können, dass einmal sämtliche
Windows Build von Linux-Maschinen kommen würden.&lt;br /&gt;
… am wenigsten &lt;code&gt;Steve Ballmer&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>Codeberg&apos;s Wiki via Markdown</title>
   <link href="https://www.opengate.at/blog/2024/09/codeberg-wiki/"/>
   <published>2024-09-01T13:00:00+02:00</published>
   <updated>2024-09-01T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2024/09/codeberg-wiki</id>
   <category term="software" />
   <summary type="text">Codeberg’s aufgemotztes Gitea UI stellt allen 
Nutzern ein besonders GIT Repository bereit:
Das Wiki-Repo.

Und mit ein paar Markdown Dateien bildet 
sich automatisch eine ganze Wiki-Seite im eigenen Projekt-Bereich.

</summary>
   <content type="html">&lt;p&gt;Codeberg’s aufgemotztes &lt;a href=&quot;https://de.wikipedia.org/wiki/Gitea&quot;&gt;Gitea&lt;/a&gt; UI stellt allen 
Nutzern ein besonders &lt;a href=&quot;https://de.wikipedia.org/wiki/Git&quot;&gt;GIT&lt;/a&gt; Repository bereit:&lt;br /&gt;
Das Wiki-Repo.&lt;/p&gt;

&lt;p&gt;Und mit ein paar &lt;a href=&quot;https://de.wikipedia.org/wiki/Markdown&quot;&gt;Markdown&lt;/a&gt; Dateien bildet 
sich automatisch eine ganze Wiki-Seite im eigenen Projekt-Bereich.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Lange Zeit spielte ich mit &lt;a href=&quot;https://de.wikipedia.org/wiki/Jekyll_(Software)&quot;&gt;Jekyll&lt;/a&gt;
herum um parallel zu den Postings auch spezielle Seiten verwalten zu können. 
Im Blog sind das die Suche und alles, was im Bereich &lt;code&gt;Dokus und Infos&lt;/code&gt;
zu finden ist.&lt;/p&gt;

&lt;p&gt;Auf der Projekt-Hautseite wollte ich ursprünglich ein paar konzeptionelle
Details zum GATE Framework veröffentlichen … doch weil mir das alles
nicht so recht gefiel, blieb auch die Motivation aus hier weiterzumachen.&lt;/p&gt;

&lt;p&gt;Und dann fiel mir wieder ein:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Codeberg bietet doch Wiki-Pages an!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Die Wiki-Funktion muss in den Einstellungen eines Projekt aktiviert sein,
und wer dann im Bereich namens “MYORG” im Projekt “MYPROJECT” die URL&lt;br /&gt;
&lt;code&gt;https://codeberg.org/MYORG/MYPROJECT.wiki.git&lt;/code&gt; per &lt;code&gt;git&lt;/code&gt; klont,
kann sich seine Wiki-Seiten per Markdown zusammenschustern und bekommt
das Design von Codeberg verpasst, was besser zum Thema Coding und Doku
passt, als experimentelle Eigenerfindungen auf privaten Homepages.&lt;/p&gt;

&lt;h3 id=&quot;home-sidebar-und-footer&quot;&gt;Home, Sidebar und Footer&lt;/h3&gt;

&lt;p&gt;Es gibt 3 besondere Dateinamen, denen eine spezielle Bedeutung zukommt.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;Home.md&lt;/code&gt; ist die Startseite, was wir im Web als &lt;code&gt;index.md&lt;/code&gt; bzw. 
&lt;code&gt;index.html&lt;/code&gt; kennen.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;_Sidebar.md&lt;/code&gt; wird in erster Line als Navigations-Menü immer in einer Box
am Rande der Seite (neben dem eigentlichen Content) eingeblendet.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;_Footer.md&lt;/code&gt; wird jeder Seite am Ende angefügt und eignet sich hervorragend
für Copyright und Impressum-Verweise, oder auch für den “Spruch des Tages”.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Kurz gesagt: Mit &lt;code&gt;Home&lt;/code&gt; startet alles, und &lt;code&gt;_Sidebar&lt;/code&gt; sowie &lt;code&gt;_Footer&lt;/code&gt; werden 
permanent rechts bzw. unterhalb der eigentlichen Seite eingeblendet.&lt;/p&gt;

&lt;h3 id=&quot;weitere-seiten-mit-verlinkung&quot;&gt;Weitere Seiten mit Verlinkung&lt;/h3&gt;

&lt;p&gt;Nun kann man auch neue &lt;code&gt;.md&lt;/code&gt; Dateien mit Markdown Content anlegen.
Verlinkt werden diese wie üblich über &lt;code&gt;[Link-Text](Linkziel)&lt;/code&gt;, wobei das Ziel
des Links nicht als URL, sondern als reiner Dateinamen (aber ohne &lt;code&gt;.md&lt;/code&gt;) 
angegeben wird.&lt;/p&gt;

&lt;p&gt;Eine Datei namens &lt;code&gt;additional_info.md&lt;/code&gt; wird per&lt;/p&gt;

&lt;div class=&quot;language-markdown highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;[Addition Information](additional_info)
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;verlinkt.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Wer also etwas Text zu seinem Codeberg Projekt schreiben will, ist mit dem
internen Wiki an der richtigen Adresse.&lt;/p&gt;

&lt;p&gt;Zusätzlich zur “nativen” Bearbeitung über &lt;code&gt;git&lt;/code&gt; lässt sich der Text auch
online bearbeiten.&lt;br /&gt;
Sogar die Freigabe des Wikis ist möglich, damit jeder Benutzer etwas beisteuern oder ändern kann.&lt;/p&gt;

&lt;p&gt;In Summe also ein absoluter Daumen-hoch für Codeberg’s Wiki Pages.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Ein Junge rettet Bienen und Vögel</title>
   <link href="https://www.opengate.at/blog/2024/08/beesteez/"/>
   <published>2024-08-25T13:00:00+02:00</published>
   <updated>2024-08-25T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2024/08/beesteez</id>
   <category term="general" />
   <summary type="text">Eigentlich ist Youtuber in meinem Vokabular ein Schimpfwort geworden. Denn
seit der Corona Pandemie sieht 
sich jeder Egomane als Content-Creator und glaubt zu jedem Blödsinn seine 
Meinung preisgeben zu müssen.

… und dann gibt es “den netten Jungen/das nette Mädchen” von
Nebenan, der/die ihre Leidenschaft mitteilen will.
Und dabei tun sie vielleicht auch mal etwas sehr sehr Gutes.

</summary>
   <content type="html">&lt;p&gt;Eigentlich ist &lt;code&gt;Youtuber&lt;/code&gt; in meinem Vokabular ein Schimpfwort geworden. Denn
seit der &lt;a href=&quot;https://de.wikipedia.org/wiki/COVID-19-Pandemie&quot;&gt;Corona Pandemie&lt;/a&gt; sieht 
sich jeder Egomane als Content-Creator und glaubt zu jedem Blödsinn seine 
Meinung preisgeben zu müssen.&lt;/p&gt;

&lt;p&gt;… und dann gibt es “den netten Jungen/das nette Mädchen” von
Nebenan, der/die ihre Leidenschaft mitteilen will.&lt;br /&gt;
Und dabei tun sie vielleicht auch mal etwas sehr sehr Gutes.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Wenn Menschen Projekte aus Leidenschaft starten, entsteht eine ganz andere
Souveränität und eine ganz andere Leichtigkeit, wenn sie ihre Ziele vortragen.
Das steht im krassen Gegenteil zu den kühlen formalen Vorträgen, die wir
aus den Nachrichten oder Business-Meetings kennen.&lt;/p&gt;

&lt;p&gt;Jetzt ist dieses Übermaß an Emotionalität nicht immer gut, vor allem nicht,
wenn man damit Leute aufhetzt … und das passiert leider viel zu oft.&lt;/p&gt;

&lt;p&gt;Doch wenn ich z.B.: den &lt;a href=&quot;https://www.youtube.com/@beesteez1&quot;&gt;Beesteez&lt;/a&gt; 
Kanal ansehe, wo ein Junge seinen Lebensweg mitfilmt und dokumentiert, 
wie er zum &lt;a href=&quot;https://de.wikipedia.org/wiki/Imker&quot;&gt;Imker&lt;/a&gt; wurde, weil er Bienen 
mag und ihr zunehmendes Sterben verhindern möchte, dann berührt einen 
diese Geschichte.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Marcel_Reich-Ranicki&quot;&gt;Marcel Reich Ranciki&lt;/a&gt; meinte
mal in einer Diskussion, dass Menschen in erster Linie wegen eines “Stars”
ins Theater oder ins Konzert gehen, was eigentlich die falsche Motivation 
sei, denn es sollte um das Stück und nicht um den Darsteller gehen.&lt;br /&gt;
Doch im gleichen Atemzug erklärte er, dass die Menschen dann trotzdem
den Inhalt des Stückes wahrnehmen und über die Handlung nachdenken und
damit den Zweck der Aufführung voll und ganz erfüllen.&lt;/p&gt;

&lt;p&gt;Vielleicht muss ich, bzw. müssen wir YouTube auch so begreifen und sehen,
dass die komödiantische Selbstdarstellung eines Teenagers oder jungen
Erwachsenen trotz der Vermarktungsstrategie von YouTube dazu führt, dass
wir etwas über Bienen, Vögel und die Natur lernen.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://bienenbuecher.de/QUENTINS-WELT-DER-BIENEN-meetthebeefamily&quot;&gt;Protagonist Quentin&lt;/a&gt;
zeigt nicht nur seine Bienenkästen und wie er Nistkästen für Vögel baut 
und verschenkt, er führt auch Interviews mit Menschen vom Fach für 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Ornithologie&quot;&gt;Ornithologie&lt;/a&gt; und so lernt der an 
“coolen Inhalten” interessierte Follower plötzlich etwas über Biologie, 
was in der Schule stets verhasst war.&lt;/p&gt;

&lt;p&gt;Und wenn es darum geht Motivation weiterzugeben, die Augen zu öffnen, dass
wir etwas für unsere Natur tun müssen, damit sie nicht abstirbt, dann 
ist eben vielleicht genau diese Art von Inhalt eben wesentlich zielführender
als kalte Statistikvorträge, wie viele Insekten jedes Jahr aussterben und
wie auch Vögelbestände stark zurückgehen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;In diesem Sinne muss ich mal einen YouTuber für sein Werk loben, wenn 
gleich ich immer etwas skeptisch bin, wie viel Selbstvermarktung hinter
solchen Videoserien steht.&lt;/p&gt;

&lt;p&gt;Doch wenn es um die konstruktive Rettung des Planeten geht … tja, da
kann man wohl kaum dagegen sein.&lt;br /&gt;
Ich wünschte, dass auch andere Umweltorganisationen vom Demonstrationsmodus
in den Aktionsmodus umschalten würden, und so wie Quentin mit dem Beesteez
Projekt vorleben, was wir aktiv machen können.&lt;/p&gt;

&lt;p&gt;Ich sehe den Garten meiner Mutter, der mir bisher eher als chaotischer 
Wildwuchs aufgefallen ist, nun mit anderen Augen. Denn dort tummelt sich
noch rege Natur, es summt und brummt, und das ist gut so.&lt;br /&gt;
Auf den niedergemähten Fussballfeld-Gärten mancher Nachbarn herrscht
inzwischen Totenstille.&lt;/p&gt;

&lt;p&gt;Von daher kann ich Quentins Aufruf nur zustimmen:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Pflanzt Blumen, möglichst viele unterschiedliche!&lt;br /&gt;
Denn dort fühlen sich Bienen und andere Insekten wohl.&lt;br /&gt;
Und damit retten wir auch unsere einheimischen Vogelarten.&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>conan cache save</title>
   <link href="https://www.opengate.at/blog/2024/08/conan2-save/"/>
   <published>2024-08-18T13:00:00+02:00</published>
   <updated>2024-08-18T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2024/08/conan2-save</id>
   <category term="devel" />
   <summary type="text">Conan v1 hatte in meiner Firma 
einen gravierenden Nachteil, wenn es um CI/CD Build Pipelines ging:


  Wie kann man Pakete lokal exportieren speichern?
Antwort: Gar nicht. 
Nur Uploads ins Artifactory und anschließend Downloads sind gestattet.


Zum Glück haben die Conan v2 Macher dieses Problem aufgegriffen und gelöst.

</summary>
   <content type="html">&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Conan_(Software)&quot;&gt;Conan&lt;/a&gt; v1 hatte in meiner Firma 
einen gravierenden Nachteil, wenn es um CI/CD Build Pipelines ging:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Wie kann man Pakete lokal exportieren speichern?
Antwort: Gar nicht. 
Nur Uploads ins Artifactory und anschließend Downloads sind gestattet.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Zum Glück haben die &lt;code&gt;Conan&lt;/code&gt; v2 Macher dieses Problem aufgegriffen und gelöst.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Im Internet ist Sache mit CON&lt;code&gt;Conan&lt;/code&gt;N einfach:&lt;br /&gt;
Ein &lt;code&gt;Conan&lt;/code&gt; Rezept definiert, wo Quellcodes abgelegt sind, und
welche Abhängigkeiten und Einstellungen für das Kompilieren der
Codes benötigt werden.&lt;/p&gt;

&lt;p&gt;Der Nutzer eines &lt;code&gt;Conan&lt;/code&gt; Pakets bekommt mit &lt;code&gt;conan install&lt;/code&gt; alles
Notwendige heruntergeladen und auch gleich alle Bibliotheken mit
dem eigenen Compiler gebaut.&lt;/p&gt;

&lt;p&gt;Doch … bei mir sahen die Anforderungen ganz anders aus.&lt;/p&gt;

&lt;h3 id=&quot;prebuilt-binary-packages&quot;&gt;Prebuilt binary packages&lt;/h3&gt;

&lt;p&gt;Bei großer Enterprise-Software können wir nicht unzählige Pakete jeden
Tag neu bauen, wir benötigen fertige getestete Bibliotheken für 
jeden Compiler und für jede unterstützte Plattform.&lt;/p&gt;

&lt;p&gt;Aus diesem Grund wurden CI/CD Pipelines eingerichtet, die alle
Varianten eines Lib-Projektes erzeugten, abtesteten und dann 
für die weitere Verwendung ins lokale jFrog-Artifactory hochluden.&lt;/p&gt;

&lt;p&gt;An dieser Stelle musste eine Grenzlinie gezogen werden:&lt;br /&gt;
Pakete aller Plattformen durften nur dann gemeinsam hochgeladen werden,
wenn alle (und zwar wirklich alle) Builds erfolgreich durchgelaufen waren.&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;Conan&lt;/code&gt; v1 konnte man ein Paket aber nur per &lt;code&gt;conan upload&lt;/code&gt; “abspeichern”,
und somit mussten wir für die Builds ein temporäres Repository anlegen,
das erst mal alles annehmen sollte.&lt;br /&gt;
Wenn alle Builds fertig waren, startete ein weiterer Job, der wieder alle
temporären Builds herunterlud und ins eigentliche Zielrepo hochladen sollte.
Beim einem Fehler eines Jobs wurden einfach alle temporären Builds gelöscht
und der Entwickler durfte das Problem suchen.&lt;/p&gt;

&lt;p&gt;Effizient war diese Vorgehensweise nicht … aber sie war besser als alle
anderen Alternativen, wo die Conan-Caches manuell in den nächsten Job
verschoben wurden, wo es dann zum Zusammenprall mit den anderen Builds kam.&lt;/p&gt;

&lt;h3 id=&quot;cache-saverestore&quot;&gt;Cache save/restore&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;Conan&lt;/code&gt; 2 führt zum Glück zwei Kommandos ein, mit denen der &lt;code&gt;Conan&lt;/code&gt; Cache Inhalt
extrahiert werden kann, und zwar auf Paket-Ebene.&lt;br /&gt;
So können wir beim Ende eines Build-Prozesses das lokale Paket mit 
&lt;code&gt;conan cache save -f file.tar.gz&lt;/code&gt; extrahiere und als &lt;code&gt;.tar.gz&lt;/code&gt; zwischenspeichern.&lt;br /&gt;
Dieses “Artefakt” kann nun über die nativen Funktionen der Datenweiterreichung
des Build-Systems zu einem Folgejob geschoben werden, der mit
&lt;code&gt;conan cache restore -f file.tar.gz&lt;/code&gt; alle Build-Resultate importiert und 
gemeinsam ins Ziel-Repository hochlädt.&lt;/p&gt;

&lt;p&gt;Hinweis: Es schadet nicht das Paket im Cache von Source- und Build-Resten zu
befreien. Ein &lt;code&gt;conan cache clean &quot;*&quot;&lt;/code&gt; erledigt das recht zuverlässig.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Es sind oft die kleinen Dinge, die große Erleichterungen bringen.
Ein &lt;code&gt;conan upload&lt;/code&gt; wirkt nicht viel umständlicher als ein &lt;code&gt;conan cache save&lt;/code&gt;,
doch in der Praxis braucht man viele weitere Infos wie unterschiedliche Ziel-Repos
und zusätzliche Build-Cleanup Jobs.&lt;/p&gt;

&lt;p&gt;Mit der &lt;code&gt;conan cache save/restore&lt;/code&gt; und der Nutzung von nativen Build-Artifacts für
die Weitergabe der Daten vereinfachten sich unsere Build-Scripts um einiges.&lt;/p&gt;

&lt;p&gt;In diesem Sinne:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Danke an das &lt;code&gt;Conan&lt;/code&gt; 2 Team für dieses wichtige neue Feature!&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>CMake targets</title>
   <link href="https://www.opengate.at/blog/2024/08/cmake-targets/"/>
   <published>2024-08-11T13:00:00+02:00</published>
   <updated>2024-08-11T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2024/08/cmake-targets</id>
   <category term="devel" />
   <summary type="text">Eine große Last wird in der C/C++ 
Entwicklung von der Vergangenheit erzeugt. Code, der einmal funktioniert
hat, bleibt auf unbestimmte Zeit unverändert.

Doch damit verbaut man sich auch oft viele neue Features und verkompliziert
sich unnötig den Alltag.

</summary>
   <content type="html">&lt;p&gt;Eine große Last wird in der C/&lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B&quot;&gt;C++&lt;/a&gt; 
Entwicklung von der Vergangenheit erzeugt. Code, der einmal funktioniert
hat, bleibt auf unbestimmte Zeit unverändert.&lt;/p&gt;

&lt;p&gt;Doch damit verbaut man sich auch oft viele neue Features und verkompliziert
sich unnötig den Alltag.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Als ich 2019 endlich auch alle meine Projekte auf &lt;code&gt;CMake&lt;/code&gt; umstellte, tat ich 
das wie so oft mit dem Hintergedanken den Abwärtskompatibilität.&lt;/p&gt;

&lt;p&gt;Ich wollte nur “stabile” Features nutzen, die es schon in &lt;code&gt;CMake&lt;/code&gt; 3.4 gab, 
damit ich stets in der Lage war mit alten &lt;code&gt;CMake&lt;/code&gt; Varianten zu arbeiten, die 
noch Codes aus dem Jahre 2000 bauen konnten.&lt;/p&gt;

&lt;p&gt;Und so ergeben sich dann viele Aufrufe nach dem Schema&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;add_definitions(...)&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;include_directories(...)&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;link_directories(...)&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;set(CMAKE_C_FLAGS &quot;${CMAKE_C_FLAGS} --something)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;die zwar alle toll funktionieren, aber den globalen Namensraum verschmutzen
und gleichzeitig in anderen Projekten wiederholt werden müssen, damit es dort
auch klappt.&lt;/p&gt;

&lt;h3 id=&quot;nur-target_xxx_yyytarget--ist-richtig&quot;&gt;Nur &lt;code&gt;target_xxx_yyy(target ...)&lt;/code&gt; ist richtig&lt;/h3&gt;

&lt;p&gt;Modernes &lt;code&gt;CMake&lt;/code&gt; sollte auf dem korrekten Ausbau von &lt;code&gt;targets&lt;/code&gt; aufbauen.
Sobald mit&lt;br /&gt;
&lt;code&gt;add_library(my_target ...)&lt;/code&gt; oder &lt;code&gt;add_executable(my_target ...)&lt;/code&gt;&lt;br /&gt;
ein &lt;code&gt;target&lt;/code&gt; definiert wurde, sollten ihm öffentliche und private Einstellungen
zugewiesen werden.&lt;br /&gt;
Die privaten werden nur für das &lt;code&gt;target&lt;/code&gt; selbst gebraucht, doch öffentliche
vererben sich automatisch an ein Folgeprojekt weiter, das mit&lt;br /&gt;
&lt;code&gt;target_link_libraries(other_target my_target)&lt;/code&gt;&lt;br /&gt;
an seine Abhängigkeit gebunden wird.&lt;/p&gt;

&lt;h4 id=&quot;target_compile_definitions&quot;&gt;target_compile_definitions()&lt;/h4&gt;

&lt;p&gt;Meiner Erfahrung nach sind 90% aller “Definitions” (also von extern gesetzten 
Makros) nur für ein einzelnes Projekt relevant.
Anstatt &lt;code&gt;add_definition(-DBZ_EXPORT)&lt;/code&gt; bei einer &lt;code&gt;bzip2&lt;/code&gt; hineinzuwerfen, 
sollte es &lt;code&gt;target_compile_defintion(bz2 PRIVATE &quot;BZ_EXPORT&quot;)&lt;/code&gt; heißen.&lt;br /&gt;
Ist ein Makro aber in öffentlichen Headern aktiv, kann es mit einer &lt;code&gt;PUBLIC&lt;/code&gt; 
Definition an alle abhängigen Projekt weitervererbt werden.&lt;/p&gt;

&lt;h4 id=&quot;target_compile_options&quot;&gt;target_compile_options()&lt;/h4&gt;

&lt;p&gt;Das schlimmste, was man tun kann, ist: Wegen einer lästigen Warnung alle 
Warnungen in allen Projekten abzuschalten. Krebsgeschwüre wie &lt;code&gt;-fpermissive&lt;/code&gt;
haben so unzählige Opfer infiziert.&lt;br /&gt;
Anstatt mit solchen Optionen per &lt;code&gt;add_definition&lt;/code&gt; den ganzen Baum zu vergiften,
kann man per&lt;br /&gt;
&lt;code&gt;target_compile_options(mydirtylib PRIVATE &quot;-fpermissive&quot;)&lt;/code&gt; nur das eine 
schlampig geschrieben Projekt anpassen.&lt;br /&gt;
Ähnlich verhält es sich auch mit anderen - nicht ganz so bösen - Optionen.&lt;/p&gt;

&lt;h4 id=&quot;target_include_directories&quot;&gt;target_include_directories()&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;include_directories(...)&lt;/code&gt; zwingt dem Verzeichnisbaum einen Include-Pfad auf,
ganz egal, ob es sich um private Sourcen oder öffentliche Header handelt.&lt;br /&gt;
Die richtige Arznei ist: &lt;code&gt;target_include_directories&lt;/code&gt;&lt;/p&gt;

&lt;div class=&quot;language-cmake highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;target_include_directories(mylib 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;  PRIVATE &amp;quot;${CMAKE_CURRENT_SOURCE_DIR}/include/private&amp;quot;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;target_include_directories(mylib 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;  PUBLIC &amp;quot;${CMAKE_CURRENT_SOURCE_DIR}/include/public&amp;quot;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;)
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Private Include-Verzeichnisse gelten nur für das Target selbst, während
öffentliche Includes an alle Targets “vererbt” werden, die das aktuelle
Target linken.&lt;br /&gt;
Das spart einiges an Redundanz, denn bisher mussten “Konsumenten” die
Include-Directory-Vorlieben ihrer Abhängigkeiten kennen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Meine eigenen externen Bibliotheken sind voll von den “alten” Funktionen,
die teils auch von uralten Projekten stammen.&lt;/p&gt;

&lt;p&gt;Doch wer ein neues Projekt auf die Beine stellt sollte 
(von wenigen berechtigten Ausnahmen abgesehen) nur noch Eigenschaften auf
&lt;code&gt;CMake&lt;/code&gt; Targets anwenden.&lt;/p&gt;

&lt;p&gt;Es ist ja auch vollkommen OK, wenn man sich ein öffentliche &lt;code&gt;CMake&lt;/code&gt; Funktion
schreibt, die einem Projekt bestimmt “Standards” angedeihen lässt, womit 
viele Targets ähnlich bzw. gleich aufgesetzt sind.&lt;/p&gt;

&lt;p&gt;“Das Target” ist der König in &lt;code&gt;CMake&lt;/code&gt;, daher muss alles immer erst
mit ebendiesem abgestimmt werden.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>DSL Internet auf dem Dorfe</title>
   <link href="https://www.opengate.at/blog/2024/08/village-inet-speed/"/>
   <published>2024-08-04T13:00:00+02:00</published>
   <updated>2024-08-04T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2024/08/village-inet-speed</id>
   <category term="hardware" />
   <summary type="text">Natürlich liebe ich meine alte Heimat mitten im Grünen und genieße dort 
das schöne Wetter und die Umgebung.

… aber das Internet liebe ich in der Stadt um einiges mehr.

</summary>
   <content type="html">&lt;p&gt;Natürlich liebe ich meine alte Heimat mitten im Grünen und genieße dort 
das schöne Wetter und die Umgebung.&lt;/p&gt;

&lt;p&gt;… aber das Internet liebe ich in der Stadt um einiges mehr.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Zwar gestalte ich nach Möglichkeit meine Programme so, dass sie mit wenig
Platz auskommen und nur geringe Datenmengen übertragen müssen, doch andere
Dienste sind ohne Breitbandanbindung gar nicht mehr denkbar.&lt;/p&gt;

&lt;p&gt;Und so bin ich entsetzt sehen zu müssen, dass ich monatlich zwischen 30 
und 100 GB Daten aus dem Netz ziehe. Der Großteil davon sind natürlich
Streaming-Dienste wie &lt;a href=&quot;https://de.wikipedia.org/wiki/Netflix&quot;&gt;Netflix&lt;/a&gt;, und die 
elenden Youtube-Videos.&lt;br /&gt;
Aber seit dem Ende von Fernsehen und Radio haben eben diese Dienste die
Hintergrundbeschallung übernommen.&lt;/p&gt;

&lt;p&gt;Dass &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows&quot;&gt;Windows&lt;/a&gt; ISOs über 4 GB groß 
sind (die passten mal auf ein 650 MB CD) und auch &lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt;
Images nicht mehr unter 1 GB komprimiert zu bekommen sind, fällt
einem da fast nicht mehr auf.&lt;br /&gt;
… außer man hat schwache Download-Raten.&lt;/p&gt;

&lt;h3 id=&quot;nicht-mehr-als-7-mbit&quot;&gt;Nicht mehr als 7 MBit&lt;/h3&gt;

&lt;p&gt;Wenn einem die Telekom schon sagt, dass das 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Digital_Subscriber_Line&quot;&gt;DSL&lt;/a&gt;-Kabel in meiner Gegend
einfach nicht mehr als 7 MBit hergibt, dann darf man sich nicht wundern, wenn
Downloads nicht schneller als 700 KByte pro Sekunde schaffen.&lt;br /&gt;
Das bedeutet dann aber, dass so ein 4GB ISO Download mindestens 
1,5 Stunden braucht.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/internet-speed-7mbit.jpg&quot; alt=&quot;Internet Speed Test 7Mbit&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Genau das habe ich unterschätzt als ich am Zweitwohnsitz dachte:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Heute aktualisiere ich meine Systeme.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Wenn dann die restliche Belegschaft im Haus parallel Katzenvideos auf 
Facebook ansieht, wird die Wartezeit erstaunlicherweise nicht weniger.&lt;/p&gt;

&lt;h3 id=&quot;online-meetings&quot;&gt;Online meetings&lt;/h3&gt;

&lt;p&gt;Bei den 0,7 MBit/s Upload ist ein Video-Stream oder eine Bildschirmübertragung
ebenso kontraproduktiv.&lt;br /&gt;
Ein einfaches Audio-Gespräch ist zwar machbar, doch falls parallel Aktivitäten
stattfinden (angefangen beim ungewollten Windows-Updates), dürfen die anderen
Meeting-Teilnehmer das Rätselraten starten, was das zerhackte Kauderwelsch
hätte bedeuten sollen.&lt;/p&gt;

&lt;p&gt;Unser Bedarf an Komfort hat die Bitraten hochgeschraubt. Früher wurden 
Audiocodecs nur auf Sprache ausgelegt und kamen mit 50 KBit/s noch zurecht.&lt;/p&gt;

&lt;h3 id=&quot;vorbereitung-ist-alles&quot;&gt;Vorbereitung ist alles&lt;/h3&gt;

&lt;p&gt;Wenn ich nun einen Ausflug zum Zweitwohnsitz plane, nehme ich so viel wie
Möglich am Laptop mit. Mit 100 MBit Download und 20 MBit Upload habe ich 
zwar kein Netz-Rennpferd in Wien, aber der oben erwähnte Download ist bei mir
in 5 bis maximal 10 Minuten fertig.&lt;/p&gt;

&lt;p&gt;Alternativ bietet sich heute auch das Smartphone an, denn sowohl 4G und 
besonders 5G erlauben mir auch auf dem Land mit 30 MBit/s und mehr ins 
Netz zu gehen.&lt;br /&gt;
Da kann der alte DSL Anschluss einfach nicht mithalten.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;Wir brauchen besseres Internet!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Als Software-Entwickler würde ich gerne auch die Hersteller von Webseiten,
Streamingdiensten und Messengern dazu zwingen wieder schlankeren Content und
bessere Codecs mit besseren Einstellungen auf den Markt zu bringen.&lt;/p&gt;

&lt;p&gt;Doch leider fehlt mir die nötige Macht und Gewalt, die Kollegen zu besserem
Output zu bewegen.&lt;/p&gt;

&lt;p&gt;Und so bleibt einem heute nur der Weg der guten Vorbereitung vor jeder Reise,
dass man nur so wenig wie möglich auf Onlinedaten angewiesen ist.&lt;/p&gt;

&lt;p&gt;Ich habe inzwischen sogar wieder angefangen, mir Dokumentationen von Sprachen,
APIs und Technologien mir offline zu sichern, damit das tägliche Nachschlagen
keinen Traffic mehr produziert.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>ZIG Build</title>
   <link href="https://www.opengate.at/blog/2024/07/zig-build/"/>
   <published>2024-07-28T13:00:00+02:00</published>
   <updated>2024-07-28T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2024/07/zig-build</id>
   <category term="devel" />
   <summary type="text">zig ist nicht nur eine Sprache und ein alternative C/C++ Compiler,
es ist auch ein ganzes Build-System und füllt damit auch jene Lücken aus,
die andere Compiler mit CMake stopfen müssen.

</summary>
   <content type="html">&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Zig_(Programmiersprache)&quot;&gt;zig&lt;/a&gt; ist nicht nur eine Sprache und ein alternative C/C++ Compiler,
es ist auch ein ganzes Build-System und füllt damit auch jene Lücken aus,
die andere Compiler mit &lt;a href=&quot;https://de.wikipedia.org/wiki/CMake&quot;&gt;CMake&lt;/a&gt; stopfen müssen.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Mal ehrlich … warum war es in 50 Jahren C und 40 Jahren C++ ums 
Verrecken nicht möglich, das hinzubekommen, was “ein Junge aus New York”
(Andrew Kelley) jetzt einfach an die Tafel bzw. ins Netz schreibt?&lt;/p&gt;

&lt;p&gt;&lt;code&gt;zig&lt;/code&gt; entwickelt sich in meinen Augen immer mehr zu dem Vorzeigebeispiel,
was alle Compiler eigentlich können sollten, egal welcher Sprachfamilie
sie angehören.&lt;/p&gt;

&lt;p&gt;Die Idee ist einfach:
&lt;code&gt;zig&lt;/code&gt; kann eine “spezielle” Datei mit Standard-&lt;code&gt;zig&lt;/code&gt; Code dazu benutzen,
einen Build-Prozess zu beschreiben um andere Sourcen zu einem Projekt
zusammenzufassen, Abhängigkeiten herunterzuladen und zu bauen.&lt;/p&gt;

&lt;p&gt;Man braucht also kein zusätzliches &lt;code&gt;git&lt;/code&gt; oder einen OS-Paketmanager 
für den Download, keinen Build-Graph-Manager zum Dateien-Herauspicken
und keinen externen Prozess, der den Compiler steuert.&lt;br /&gt;
Alles das macht die &lt;code&gt;zig.exe&lt;/code&gt; selbst.&lt;/p&gt;

&lt;h3 id=&quot;abhängigkeiten-per-zon&quot;&gt;Abhängigkeiten per .zon&lt;/h3&gt;

&lt;p&gt;Als Javascript seine Objekt-Syntax als Dateiformat namens 
&lt;a href=&quot;https://de.wikipedia.org/wiki/JSON&quot;&gt;JSON&lt;/a&gt; (JavaScript Object Notation) neu 
vermarktete, war das schon echt genial und hat unser Denken reformiert.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;zig&lt;/code&gt; führt mit ZIG-Object-Notation (ZON) genau das gleiche Konzept ein
und stützt sich dabei auf seine Möglichkeit, anonyme Strukturen überall 
frei definieren zu können.&lt;/p&gt;

&lt;div class=&quot;language-zig highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;const mystruct = .{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;    .a: &amp;quot;hello&amp;quot;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;    .b: 42
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;};
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Einziger Unterschied zu JSON ist der &lt;code&gt;.&lt;/code&gt; vor den Membern.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Wie geil wäre es wohl gewesen, hätten wir das in C schon 
seit den 90ern?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Und nun stelle man sich noch vor, in einer solchen &lt;code&gt;.zon&lt;/code&gt; Datei wären
URLs mit ZIP-Dateien hinterlegt, wo Sourcecodes drinnen sind und &lt;code&gt;zig&lt;/code&gt;
würde diese Inhalte herunterladen und für Build-Prozesse nutzen.&lt;br /&gt;
&lt;strong&gt;Genial!&lt;/strong&gt;&lt;/p&gt;

&lt;h3 id=&quot;buildzig&quot;&gt;build.zig&lt;/h3&gt;

&lt;p&gt;Statt eine Pseudo-Sprache wie &lt;code&gt;cmake&lt;/code&gt;, schreiben wir echten &lt;code&gt;zig&lt;/code&gt; Code,
der in etwa so aussieht:&lt;/p&gt;

&lt;div class=&quot;language-zig highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;const std = @import(&amp;quot;std&amp;quot;);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;pub fn build(b: *std.Build) void {
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;    const lib = b.addStaticLibrary(....);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;    lib.addIncludePath(....);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;    lib.addCSourceFile(....);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;    lib.linkLibC();
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;    b.installArtifact(lib);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;    const exe = b.addExecutable(....);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;    exe.linkLibrary(lib);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;    b.installArtifact(exe);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Oder anders gesagt: &lt;code&gt;zig&lt;/code&gt; kompiliert eine &lt;code&gt;build()&lt;/code&gt; Funktion, die wir 
geschrieben haben, wo &lt;code&gt;zig&lt;/code&gt; sein eigenes &lt;code&gt;std.Build&lt;/code&gt; Objekt hineinwirft
und wir dort Build-Vorgaben machen, wie Projekte zu ihren Dateien und
Abhängigkeiten kommen.&lt;/p&gt;

&lt;p&gt;Am Ende führt ein &lt;code&gt;zig build&lt;/code&gt; einfach den Code in unserer &lt;code&gt;build.zig&lt;/code&gt;
Datei aus um zu Erfahren, wie der Build ablaufen soll … und macht dann 
genau das.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ich kann jedem nur empfehlen, ein leeres Verzeichnis anzulegen, dann&lt;br /&gt;
&lt;code&gt;zig init&lt;/code&gt; darin auszuführen und den generierten Code anzusehen.&lt;/p&gt;

&lt;p&gt;Genau das hätte jeder C-Compilerhersteller schon vor Jahrzehnten einführen
können … doch leider Nein.&lt;/p&gt;

&lt;p&gt;Ich gebe zu, dass nicht alle Objektmethoden des ZIG-Build Objektes perfekt
sind … um nicht zu sagen, dass es kompliziert werden kann, wenn man 
viele unterschiedliche Einstellungen setzen will.&lt;/p&gt;

&lt;p&gt;Dennoch ist alleine die Idee, dass der Compiler den gesamten Buildprozess
gestaltet und alles in einer Sprache ohne zusätzliches externes Scripting
auskommt, einfach nur &lt;strong&gt;schön&lt;/strong&gt; und durchdacht umgesetzt.&lt;/p&gt;

&lt;p&gt;Hätte es &lt;code&gt;zig&lt;/code&gt; schon vor 10 Jahren auf die große Bühne geschafft, so hätte
ich heute das GATE Projekt vermutlich ausschließlich in &lt;code&gt;zig&lt;/code&gt; geschrieben.
Leider hat mir hier die Zeitlinie dann doch einen Streich gespielt.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;… aber die große Zeit von &lt;code&gt;zig&lt;/code&gt; kommt … unaufhaltsam.&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>Deadpool &amp; Wolverine</title>
   <link href="https://www.opengate.at/blog/2024/07/deadpool/"/>
   <published>2024-07-24T13:00:00+02:00</published>
   <updated>2024-07-24T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2024/07/deadpool</id>
   <category term="entertainment" />
   <summary type="text">Nach einer laaangen Durststecke konnten 
Marvel
Fans in dieser Woche den neuesten Film in den Kinos genießen, der laut Werbung
das Versprechen aufbrachte, dass der Multiversum-Handlungsrahmen nun endlich
in die richtige Richtung gedreht wird.

… Naja … die Werbung …

</summary>
   <content type="html">&lt;p&gt;Nach einer laaangen Durststecke konnten 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Marvel_Cinematic_Universe&quot;&gt;Marvel&lt;/a&gt;
Fans in dieser Woche den neuesten Film in den Kinos genießen, der laut Werbung
das Versprechen aufbrachte, dass der Multiversum-Handlungsrahmen nun endlich
in die richtige Richtung gedreht wird.&lt;/p&gt;

&lt;p&gt;… Naja … die Werbung …&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Für mich ist heute die Hoffnung gestorben, dass Marvel nochmals ein Meisterwerk
wir &lt;a href=&quot;https://de.wikipedia.org/wiki/Avengers:_Endgame&quot;&gt;Endgame&lt;/a&gt; hinbekommen wird. 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Deadpool_%26_Wolverine&quot;&gt;Deadpool&lt;/a&gt; liefert eben nur 
“Deadpool”, also eine Ansammlung an Referenzen, Kritiken und Ironie.&lt;br /&gt;
Und genau dieser Teil war verdammt lustig.&lt;/p&gt;

&lt;p&gt;Dass der Charakter während der Handlung schon ausspricht, was der Zuschauer
denkt bzw. denken soll, ist für Deadpool typisch.&lt;br /&gt;
Der Charakter sitzt quasi neben uns Zusehern im Kino und kommentiert seine
eigene Handlung gleich mit.
Somit musste nicht der Nerd mit Brille in Reihe 1 ausrufen:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Hey, da ist ja ein Cameo Auftritt von XXX, den wir schon Staffel YYY von
ZZZ gesehen haben.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Nein, genau diesen Zwischenruf macht Deadpool gleich selbst.&lt;/p&gt;

&lt;h3 id=&quot;wer-schreibt-die-user-story&quot;&gt;Wer schreibt die User-Story?&lt;/h3&gt;

&lt;p&gt;Die große Frage war für mich: Wo wird uns der Film hinbringen … 
im Multiversum?
Und die Antwort war (für mich): Nirgends.&lt;/p&gt;

&lt;p&gt;Avengers Endgame, Loki, Quantumania und Multiverse of Madness haben jeweils 
ganz andere Zusammenhänge zwischen Zeitlinien und Universen gezeigt. Am Ende
gibt es nichts, auf das man sich verlassen kann.&lt;br /&gt;
Und Deadpool setzt hier noch einen drauf, und legt fest, dass jedes Universum
jetzt noch eine “Anker”-Person hat, ohne die es zerbricht … hier kommt dann
willkürlich ein Wolverine hinzu.&lt;/p&gt;

&lt;p&gt;Zwar waren die Charaktere und ihr permanentes Gefluche schon witzig, aber
nachvollziehen konnte ich es nicht. Viel mehr standen Kasperl und das 
Krokodil auf der Bühne und tauschten wie in Final-Fantasy 7 Rundenkämpfen
KLeinangriffe aus, bis man kurz vor dem Sieg einfach aus dem Kampf floh.&lt;/p&gt;

&lt;p&gt;In diesem Streifen wurden Personen so oft durch Stichwerkzeuge durchbohrt
und im Anschluss wieder durch Selbstheilung “gefixt”, dass es schon an 
sich lächerlich war … aber auf ein lustige Art und Weise.&lt;/p&gt;

&lt;p&gt;Und nachdem alle neu eingeführten Charaktere am Ende Tod waren, lohnt es 
sich gar nicht, weiter über sie zu sprechen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ja, es war ein “gewöhnlich” lustiger Kinoabend, wie man es von Marvel
gewohnt ist und die beiden Hauptcharaktere tragen den Film wirklich gut
auf ihren breiten, muskulösen Schultern, denn Homoerotik gab es im Überfluss.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/movie-marvel-deadpool.jpg&quot; alt=&quot;Deadpool Wolverine&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Eigentlich ist dieser Marvel-ige Film gar kein Marvel-Film, weil er kein
MCU-Film ist, obwohl er auf alles darin anspielt.
Es ist eine Standup-Comedy-Vorführung von 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Ryan_Reynolds&quot;&gt;Ryan Reynolds&lt;/a&gt; und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Hugh_Jackman&quot;&gt;Hugh Jackman&lt;/a&gt; mit stets verschwindenden
CGI-Zauberblut.&lt;br /&gt;
… und damit kann ich gut leben.&lt;/p&gt;

&lt;p&gt;Und trotzdem sehne ich mich nach einem neuen MCU-Film, der einfach nicht
in die Kinos kommen will.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>CMake Install</title>
   <link href="https://www.opengate.at/blog/2024/07/cmake-install/"/>
   <published>2024-07-21T13:00:00+02:00</published>
   <updated>2024-07-21T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2024/07/cmake-install</id>
   <category term="devel" />
   <summary type="text">CMake ist “das” Werkzeug zum Bauen von 
C/C++ Software.
Doch danach soll diese auch verteilt werden können.

Und genau hierfür müssen die erzeugten Binärdateien und auch Interface
Sourcecodes an die richtige Stelle geschoben werden.

</summary>
   <content type="html">&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/CMake&quot;&gt;CMake&lt;/a&gt; ist “das” Werkzeug zum Bauen von 
&lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B&quot;&gt;C/C++&lt;/a&gt; Software.
Doch danach soll diese auch verteilt werden können.&lt;/p&gt;

&lt;p&gt;Und genau hierfür müssen die erzeugten Binärdateien und auch Interface
Sourcecodes an die richtige Stelle geschoben werden.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Auf Grund meiner “Windows-Vergangenheit”, sah ich &lt;code&gt;CMake&lt;/code&gt; in erster Linie
immer als Build-Generator, der nur das Kompilieren kontrollieren soll.&lt;/p&gt;

&lt;p&gt;In der &lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt; Welt ist die “Installation” des
fertigen Kompilats an die richtige Stelle im &lt;code&gt;/&lt;/code&gt; Dateisystem aber ebenso 
wichtig. Lässt man &lt;code&gt;CMake&lt;/code&gt; auch diesen Schritt übernehmen, 
ergeben sich gleich mehrere Vorteile.&lt;/p&gt;

&lt;h3 id=&quot;installtargets&quot;&gt;install(TARGETS)&lt;/h3&gt;

&lt;p&gt;Wenn man die öffentlichen Header in einem Projekt auch als solche in
&lt;code&gt;CMake&lt;/code&gt; bekannt gegeben hat, dann können diese parallel zu den Binaries
auch gleich mitinstalliert werden.&lt;br /&gt;
Ein &lt;code&gt;CMake&lt;/code&gt;-Projekt sieht dann beispielsweise so aus:&lt;/p&gt;

&lt;div class=&quot;language-cmake highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;project(MyProject)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;file(GLOB MY_HEADERS &amp;quot;*.h&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;file(GLOB MY_SOURCES &amp;quot;*.c&amp;quot; &amp;quot;*.cpp&amp;quot; )
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;add_library(${PROJECT_NAME}
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  ${MY_HEADERS} ${MY_SOURCES})
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;set_target_properties(${PROJECT_NAME} PROPERTIES
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  PUBLIC_HEADER &amp;quot;${MY_HEADERS}&amp;quot;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;target_link_libraries(${PROJECT_NAME}
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;  mydependency
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;install(TARGETS ${PROJECT_NAME}
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;  ARCHIVE DESTINATION &amp;quot;lib&amp;quot;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;  LIBRARY DESTINATION &amp;quot;lib&amp;quot;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  RUNTIME DESTINATION &amp;quot;bin&amp;quot;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n21&quot; name=&quot;n21&quot;&gt;21&lt;/a&gt;&lt;/span&gt;  PUBLIC_HEADER DESTINATION &amp;quot;include&amp;quot;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n22&quot; name=&quot;n22&quot;&gt;22&lt;/a&gt;&lt;/span&gt;)
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Wie in &lt;code&gt;make&lt;/code&gt; lässt sich auch in &lt;code&gt;cmake&lt;/code&gt; ein Prefix-Directory angeben und
in diesem werden die Dateien in die Unterverzeichnisse &lt;code&gt;lib&lt;/code&gt;, &lt;code&gt;bin&lt;/code&gt; und 
&lt;code&gt;include&lt;/code&gt; am Ende installiert.&lt;/p&gt;

&lt;p&gt;Der Standard-Prefix-Pfad ist &lt;code&gt;/usr&lt;/code&gt; unter Linux, womit wir am Ende bei
den Standardverzeichnissen &lt;code&gt;/usr/bin&lt;/code&gt;, &lt;code&gt;/usr/lib&lt;/code&gt; und &lt;code&gt;/usr/include&lt;/code&gt; landen.&lt;/p&gt;

&lt;h3 id=&quot;conan-pakete&quot;&gt;Conan Pakete&lt;/h3&gt;

&lt;p&gt;Tatsächlich haben mich erst &lt;a href=&quot;https://de.wikipedia.org/wiki/Conan_(Software)&quot;&gt;Conan&lt;/a&gt; 
Pakete auf die Notwendigkeit einer korrekten Installation aufmerksam gemacht.&lt;br /&gt;
Wenn nämlich ein &lt;code&gt;cmake&lt;/code&gt; Install-Schritt alle Dateien in die 
Unterverzeichnisse &lt;code&gt;bin&lt;/code&gt;, &lt;code&gt;lib&lt;/code&gt; und &lt;code&gt;include&lt;/code&gt; eines Zielverzeichnisses
verschieben kann, dann ist die Conan &lt;code&gt;package()&lt;/code&gt; Methode nichts weiter 
als ein:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color:#06B;font-weight:bold&quot;&gt;package&lt;/span&gt;(&lt;span style=&quot;color:#069&quot;&gt;self&lt;/span&gt;):
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;    cmake = CMake(&lt;span style=&quot;color:#069&quot;&gt;self&lt;/span&gt;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;    cmake.install()
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h3 id=&quot;runtime-pfade&quot;&gt;Runtime-Pfade&lt;/h3&gt;

&lt;p&gt;Wenn man komplexere Bibliotheken erstellt, ordnet man diese gerne in
Hierarchien von Unterverzeichnissen ein. Die Dateien liegen dann nicht
einfach in &lt;code&gt;lib/&lt;/code&gt; sondern z.B.: in &lt;code&gt;lib/component/version/something.so&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Wenn man jetzt ein Projekt mit Bibliotheken und Programmen baut, linken
die Programme direkt gegen die Pfade im Build-System.&lt;br /&gt;
Das wäre dann z.B.: ein &lt;code&gt;~/my_project/build/output/mycorp/mylib.so&lt;/code&gt;.
Doch genau diesen Pfad wird es am Ende nicht mehr geben, weil wir die 
&lt;code&gt;.so&lt;/code&gt; in &lt;code&gt;/usr/lib/mycorp/mylib.so&lt;/code&gt; installieren wollen.&lt;/p&gt;

&lt;p&gt;Das Programm findet &lt;code&gt;mylib.so&lt;/code&gt; somit nicht mehr und verweigert die 
Ausführung.&lt;br /&gt;
Zur Lösung dieses Problems hat jedes Programm das &lt;code&gt;RPATH&lt;/code&gt; Feld (Runtime-Path),
welches die Verzeichnisse enthält, wo &lt;code&gt;.so&lt;/code&gt; Dateien gesucht werden sollen.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;cmake --install path/to/build_dir&lt;/code&gt; ändert bei einer Installation eines 
Programms auch diesen Pfad auf das neue Installationsziel um.&lt;br /&gt;
Dadurch erspart man sich üble Anpassungen der Library-Loader-Konfiguration
oder das Setzen von &lt;code&gt;LD_LIBRARY_PATH&lt;/code&gt; auf die eigenen Unterverzeichnisse.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;install(TARGETS)&lt;/code&gt; ist nun in allen meinen Projekten nachgepflegt, wo es
bisher fehlte … und einem Tool wie &lt;code&gt;Conan&lt;/code&gt; gefällt das sehr.&lt;/p&gt;

&lt;p&gt;Bisher war das Thema Runtime-Pfade für mich eher nebensächlich, da ich in
erste Linie statisch kompiliere und auf &lt;code&gt;.dll&lt;/code&gt; / &lt;code&gt;.so&lt;/code&gt; Varianten gerne
verzichte.&lt;br /&gt;
Ein “ordentliches” Projekt muss aber mit beiden Möglichkeiten umgehen können
und somit gehören Shared Libraries und deren korrekte Installation auch zum
erwarteten Standard.&lt;/p&gt;

&lt;p&gt;Es gibt da noch die interessante Möglichkeit den &lt;code&gt;RPATH&lt;/code&gt; “relativ” zu setzen
… aber das ist eine andere Geschichte.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>WinCE Browser mit PIEDocView</title>
   <link href="https://www.opengate.at/blog/2024/07/wince-piedocview/"/>
   <published>2024-07-14T13:00:00+02:00</published>
   <updated>2024-07-14T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2024/07/wince-piedocview</id>
   <category term="devel" /><category term="software" />
   <summary type="text">Das WebBrowser-Control und WebView2
befähigen Win32 Anwendungen, eine Web-Ansicht ins eigene Programm zu holen.

Doch was war mit Windows CE?
Dort war der Pocket Internet Explorer am Start und auch dieser ist
“modular” aufgebaut.

</summary>
   <content type="html">&lt;p&gt;Das WebBrowser-Control und &lt;a href=&quot;/blog/2024/07/webview2/&quot;&gt;WebView2&lt;/a&gt;
befähigen Win32 Anwendungen, eine Web-Ansicht ins eigene Programm zu holen.&lt;/p&gt;

&lt;p&gt;Doch was war mit &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_CE&quot;&gt;Windows CE&lt;/a&gt;?&lt;br /&gt;
Dort war der Pocket Internet Explorer am Start und auch dieser ist
“modular” aufgebaut.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Das Internet vergisst und Nischenprodukte wie Windows CE sind schon fast
gänzlich dem Online-Alzheimer zum Opfer gefallen.&lt;/p&gt;

&lt;p&gt;Doch so wie das Standard-Windows seit Version 98 und NT 5 (2000) mit dem
Internet Explorer (und dem &lt;code&gt;SHDocVwCtl.WebBrowser&lt;/code&gt; ActiveX Browser Control)
ausgeliefert wurde, so konnte man in ein Windows CE Image den 
Pocket Internet Explorer integrieren und darüber das Web besuchen.&lt;/p&gt;

&lt;p&gt;Die Performance des Pocket-IE war katastrophal, weil die CE-Geräte 
grundsätzlich schwachbrüstig waren und mit Auflösungen von 320 x 240
Pixel auf den alten “Organizern” erst recht nicht mit üblichen
Webseiten umgehen konnten.&lt;/p&gt;

&lt;p&gt;Hatte man also keine für WinCE optimierte Webseite (ich frage mich,
ob es solche überhaupt gab), quälte man sich mit Scrollbars herum,
die mit dem Nachzeichnen der Seitenbruchstücke immer das System
überlasteten.&lt;/p&gt;

&lt;h3 id=&quot;das-microsoftpiedocview-interface&quot;&gt;Das Microsoft.PIEDocView Interface&lt;/h3&gt;

&lt;p&gt;Und trotzdem … auch hier gab es eine ActiveX-Komponente, mit der man eine
Webansicht in die eigene Anwendung einbinden konnte.&lt;br /&gt;
Sie funktionierte identisch zu &lt;code&gt;SHDocVwCtl&lt;/code&gt; und benutzte sogar die gleichen
Interface GUIDs, nur ihr “Anfang” war etwas anders.&lt;/p&gt;

&lt;p&gt;Das Geheimnis ist in den Windows-CE Beispielen versteckt, die man bei der
Installation von Visual Studio 2005 mit “SmartDevices” (also WinCE) finden kann:&lt;/p&gt;

&lt;p&gt;Während man im regulären Windows &lt;code&gt;atl.dll&lt;/code&gt; lädt und dort die Funktionen&lt;br /&gt;
&lt;code&gt;AtlAxWinInit()&lt;/code&gt;, &lt;code&gt;AtlAxGetControl()&lt;/code&gt;, &lt;code&gt;AtlAxGetHost()&lt;/code&gt; einsetzt,
braucht man unter Windows CE die &lt;code&gt;atlce300.dll&lt;/code&gt; Bibliothek, doch die
Funktionsnamen und Signaturen sind identisch.&lt;/p&gt;

&lt;p&gt;Und wenn wir dann ein Fenster mit der Klasse &lt;code&gt;AtlAxWin&lt;/code&gt; erstellen,
wird es unter Windows mit der Prog-ID &lt;code&gt;SHDocVwCtl.WebBrowser&lt;/code&gt; gefüttert,
doch Windows CE erfordert hier &lt;code&gt;Microsoft.PIEDocView&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Aber das war es dann auch schon.
Alles andere (Interfaces, Callbacks) verläuft identisch zum Standard Windows
WebBrowser Control.&lt;br /&gt;
Es reichen also 2 &lt;code&gt;#if WINCE&lt;/code&gt; Zeilen im Code für die Portierung eines Win32
WebBrowsers nach Windows CE.
(OK, ein paar &lt;code&gt;HWND&lt;/code&gt;-Flags existieren in CE auch nicht und brauchen 
Nachbearbeitung.)&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ich konnte somit meine WebBrowser-Demo-UI mit wenigen Zeilen auf Windows CE
portieren, was ich mir nie hätte träumen lassen.&lt;/p&gt;

&lt;p&gt;Wäre ich heute wieder im Jahr 2007, als mir Windows CE zum ersten Mal unter
die Nase gekommen ist, hätte ich jetzt “coole” Ideen für Webanwendungen auf
Industrie-Terminals … was damals undenkbar war.&lt;/p&gt;

&lt;p&gt;Naja … in einer anderen Zeitlinie hat das sicher geklappt.&lt;br /&gt;
Und ich freue mich eben, dass ich über 15 Jahre später dieses Geheimnis
lüften konnte.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Browser mit WebView2</title>
   <link href="https://www.opengate.at/blog/2024/07/webview2/"/>
   <published>2024-07-07T13:00:00+02:00</published>
   <updated>2024-07-07T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2024/07/webview2</id>
   <category term="devel" /><category term="software" />
   <summary type="text">Seitdem der Internet Explorer 
verschwunden und “Edge” die Herrschaft übernommen hat, ist auch die alte 
SHDocVwCtl.WebBrowser ActiveX
Webbrowser-Komponente zum Einbinden in eigene Programme abgekündigt.

An deren Stelle tritt WebView bzw. 
WebView2, 
womit man sich einen 
Chromium-Browser
selbst bauen kann.

</summary>
   <content type="html">&lt;p&gt;Seitdem der &lt;a href=&quot;https://de.wikipedia.org/wiki/Internet_Explorer&quot;&gt;Internet Explorer&lt;/a&gt; 
verschwunden und “Edge” die Herrschaft übernommen hat, ist auch die alte 
&lt;code&gt;SHDocVwCtl.WebBrowser&lt;/code&gt; &lt;a href=&quot;https://de.wikipedia.org/wiki/ActiveX&quot;&gt;ActiveX&lt;/a&gt;
Webbrowser-Komponente zum Einbinden in eigene Programme abgekündigt.&lt;/p&gt;

&lt;p&gt;An deren Stelle tritt WebView bzw. 
&lt;a href=&quot;https://learn.microsoft.com/en-us/microsoft-edge/webview2/&quot;&gt;WebView2&lt;/a&gt;, 
womit man sich einen 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Chromium_(Browser)&quot;&gt;Chromium-Browser&lt;/a&gt;
selbst bauen kann.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Microsoft hat Edge (zum Glück) mit einer ähnlichen COM-ActiveX Schnittstelle
ausgestattet, wie damals den alten Internet Explorer.
Somit kann jede Win32-Anwendung auch ein Fenster erzeugen und darin die
Edge-WebView2-Komponente eine 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Hypertext_Markup_Language&quot;&gt;HTML&lt;/a&gt; Seite rendern lassen.&lt;br /&gt;
Genau das wird heute immer wichtiger, wo Content nicht mehr in nativen
Controls als Text, Labels und Buttons dargestellt wird, sondern nur noch
als HTML Code.&lt;/p&gt;

&lt;p&gt;Hat man erst ein WebView2-Interface in seinen Händen, kann man es URLs
ansurfen oder direkt HTML Code rendern lassen.&lt;br /&gt;
Allerdings muss man dafür zwischen einem “echten Fenster” und dem 
Interface ein paar Daten austauschen können.
z.B.:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Größenänderungen des Fensters dem WebView2-Interface bekannt geben lassen&lt;/li&gt;
  &lt;li&gt;Events aus der Webseite “von außen” bestätigen lassen
    &lt;ul&gt;
      &lt;li&gt;z.B.: eine neue URL soll geladen werden&lt;/li&gt;
      &lt;li&gt;ein neues Fenster soll geöffnet werden&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;implementierung&quot;&gt;Implementierung&lt;/h3&gt;

&lt;p&gt;Alles beginnt mit einer &lt;code&gt;.dll&lt;/code&gt;, die wir mitliefern müssen und sich um die
Kommunikation mit der Edge/WebView2 Installation kümmert.&lt;br /&gt;
Sie heißt &lt;code&gt;WebView2Loader.dll&lt;/code&gt; und stellt Funktionen wie 
&lt;code&gt;CreateCoreWebView2EnvironmentWithOptions()&lt;/code&gt; bereit.
Danach läuft alles über COM-Interfaces, die eine Funktion meist
asynchron anstarten und wir müssen ein Callback-Interface gleich mitübergeben,
welches über die Fertigstellung eines Ergebnisses wieder in den eigenen
Code zurückspringen kann.&lt;/p&gt;

&lt;h4 id=&quot;ein-webview2-fenster-anlegen&quot;&gt;Ein WebView2 Fenster anlegen&lt;/h4&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;code&gt;CreateCoreWebView2EnvironmentWithOptions()&lt;/code&gt; wird mit einem selbst 
implementierten &lt;code&gt;ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler&lt;/code&gt; 
Pointer aufgerufen um eine Sitzung vorzubereiten.&lt;/li&gt;
  &lt;li&gt;Wir erhalten einen &lt;code&gt;ICoreWebView2Environment&lt;/code&gt; Pointer über die Callback 
Methode &lt;code&gt;Invoke()&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Nun können wir per &lt;code&gt;CreateWindowEx&lt;/code&gt; ein beliebiges &lt;code&gt;HWND&lt;/code&gt; Fenster erzeugen,
in welchem WebView laufen soll.&lt;/li&gt;
  &lt;li&gt;Über den Environment Pointer rufen wir &lt;code&gt;CreateCoreWebView2Controller()&lt;/code&gt; mit 
auf dem neuen &lt;code&gt;HWND&lt;/code&gt; auf um über einen 
&lt;code&gt;ICoreWebView2CreateCoreWebView2ControllerCompletedHandler&lt;/code&gt; Callback an 
eine neue &lt;code&gt;ICoreWebView2Controller&lt;/code&gt; Instanz zu kommen.&lt;/li&gt;
  &lt;li&gt;Per &lt;code&gt;controller-&amp;gt;get_CoreWebView2()&lt;/code&gt; erhalten wir nun ein 
&lt;code&gt;ICoreWebView2&lt;/code&gt; Interface, mit dem wir den Web-Inhalt in unserem Fenster 
steuern können.&lt;/li&gt;
  &lt;li&gt;Nun können wir beliebig viele Event-Handler als Callback-COM Objekte
registrieren. Hier ein paar Beispiele:
    &lt;ul&gt;
      &lt;li&gt;&lt;code&gt;NavigationStarting&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;&lt;code&gt;ContentLoading&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;&lt;code&gt;SourceChanged&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;&lt;code&gt;HistoryChanged&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;&lt;code&gt;FrameNavigationStarging&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;&lt;code&gt;FrameNavigationCompleted&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;&lt;code&gt;ScriptDialogOpening&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;&lt;code&gt;PermissionRequested&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;&lt;code&gt;WebMessageReceived&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;&lt;code&gt;NewWindowRequested&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;&lt;code&gt;DocumentTitleChanged&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;&lt;code&gt;ContainsFullScreenElementChanged&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;&lt;code&gt;WindowCloseRequested&lt;/code&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Wenn man auf diese Events reagiert, kann man ihr Verhalten
beeinflussen, ihre Bearbeitung verhindern oder überhaupt erst
ermöglichen. Das hängt von der Art der Anwendung ab.&lt;/p&gt;

&lt;p&gt;Das &lt;code&gt;WebView2&lt;/code&gt; Fenster ist somit fertig erzeugt.&lt;br /&gt;
Über das &lt;code&gt;ICoreWebView2Controller&lt;/code&gt; Interface kann man mit Methoden wie 
&lt;code&gt;put_IsVisible()&lt;/code&gt; den Browser sichtbar oder unsichtbar machen oder die Größe
des Fensters per &lt;code&gt;put_Bounds()&lt;/code&gt; explizit anpassen.&lt;/p&gt;

&lt;p&gt;Das &lt;code&gt;ICoreWebView2&lt;/code&gt; Interface lässt uns mit &lt;code&gt;Navigate()&lt;/code&gt; eine URL ansurfen
oder per &lt;code&gt;NavigateToString&lt;/code&gt; gleich HTML Code als String rendern.
Zusätzlich helfen Methoden wie &lt;code&gt;GoBack()&lt;/code&gt; &lt;code&gt;GoForward()&lt;/code&gt; oder &lt;code&gt;Stop()&lt;/code&gt; das
typische Verhalten eines Webbrowsers auszuführen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Auch wenn die Interfaces etwas anders benannt sind und mehr asynchrone 
Ausführung mit Callbacks erfordern, so ist die Funktionsweise zum alten 
IE Code doch recht ähnlich.&lt;/p&gt;

&lt;p&gt;Das Öffnen von neuen Fenstern ist am kompliziertesten, weil man hier aus 
einem Callback heraus wieder im Hintergrund ein neues natives Fenster
erzeugen muss, bevor man eine weitere WebView2 Instanz+Controller damit 
verknüpfen kann.&lt;/p&gt;

&lt;p&gt;Ich habe eine Demo-Implementierung in den Win32-UI Teil übernommen und diese
wird immer automatisch aktiv, wenn mein Demo-WebBrowser zusammen mit einer
&lt;code&gt;WebView2Loader.dll&lt;/code&gt; gestartet wird und WebView2 im System vorhanden ist.
Falls nicht fällt der Code auf das alte &lt;code&gt;SHDocVwCtl.WebBrowser&lt;/code&gt; Interface 
zurück, das auch im aktuellen Windows 11 trotz fehlendem Internet Explorer
immer noch die altes IE-Engine im eignen Prozess ausführt.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>WinRM</title>
   <link href="https://www.opengate.at/blog/2024/06/winrm/"/>
   <published>2024-06-30T13:00:00+02:00</published>
   <updated>2024-06-30T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2024/06/winrm</id>
   <category term="software" />
   <summary type="text">Als ich vor 14 Jahren die Verantwortung für 
Windows Embedded Standard 7 
Installationen übernahm, stellte sich vor allem die Frage:


  Wie kann man die Systeme aus der Ferne verwalten.


RDP und 
VNC 
mit voller UI ist zwar nett, aber nicht wirklich automatisierbar.
Hier kam dann 
WinRM ins Spiel.

</summary>
   <content type="html">&lt;p&gt;Als ich vor 14 Jahren die Verantwortung für 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_IoT&quot;&gt;Windows Embedded Standard 7&lt;/a&gt; 
Installationen übernahm, stellte sich vor allem die Frage:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Wie kann man die Systeme aus der Ferne verwalten.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Remote_Desktop_Protocol&quot;&gt;RDP&lt;/a&gt; und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Virtual_Network_Computing&quot;&gt;VNC&lt;/a&gt; 
mit voller UI ist zwar nett, aber nicht wirklich automatisierbar.
Hier kam dann 
&lt;a href=&quot;https://en.wikipedia.org/wiki/Windows_Remote_Management&quot;&gt;WinRM&lt;/a&gt; ins Spiel.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;code&gt;WinRM&lt;/code&gt; ist die “kurze” Microsoft-Antwort auf 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Secure_Shell&quot;&gt;SSH&lt;/a&gt; aus der 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Unix&quot;&gt;Unix&lt;/a&gt; Welt.&lt;/p&gt;

&lt;p&gt;Es handelt sich dabei um ein 
&lt;a href=&quot;https://de.wikipedia.org/wiki/SOAP&quot;&gt;SOAP&lt;/a&gt;-über-&lt;a href=&quot;https://de.wikipedia.org/wiki/Hypertext_Transfer_Protocol&quot;&gt;HTTP&lt;/a&gt;
Protokoll, welches eine “Aufgabe” auf ein Zielsystem senden kann, 
und das Ergebnis zurückliefert.&lt;/p&gt;

&lt;p&gt;Der kleinste gemeinsame Nenner zwischen &lt;code&gt;SSH&lt;/code&gt; und &lt;code&gt;WinRM&lt;/code&gt; ist das starten 
von Prozessen, man kann z.B. &lt;code&gt;cmd.exe&lt;/code&gt; auf dem Zielsystem starten und 
vom lokalen System per Tastatur steuern.&lt;/p&gt;

&lt;p&gt;Im restlichen Feature-Set unterscheiden sich die beiden Techniken aber.
&lt;code&gt;SSH&lt;/code&gt; kann Dateien verwalten (SFTP) und TCP-Ports weiterleiten (tunneln), 
was &lt;code&gt;WinRM&lt;/code&gt; nicht kann.&lt;br /&gt;
Dafür gibt &lt;code&gt;WinRM&lt;/code&gt; einem Zugriff auf alles, was durch 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_Management_Instrumentation&quot;&gt;WMI&lt;/a&gt;
erreichbar ist, was wiederum den Unix-Derivaten fremd ist.&lt;/p&gt;

&lt;h3 id=&quot;winrm-einrichten&quot;&gt;WinRM einrichten&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;WinRM&lt;/code&gt; ist ein Windows Systemdienst, der seit Windows Vista/7 deaktiviert 
ausgeliefert wird. Für Windows XP und Server 2003 gab es Upgrades um es auch
dort nachzusinstallieren.&lt;/p&gt;

&lt;p&gt;Aktivieren kann man den Dienst durch folgende Befehl als Administrator auf 
der Konsole:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;winrm quickconfig -force -q
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Diese Befehlszeile ist auf beiden Systemen (also dem lokalen System und dem
zu verwaltenden System) auszuführen.&lt;/p&gt;

&lt;p&gt;Das &lt;code&gt;-q&lt;/code&gt; (quiet) Flag verhindert die Nachfrage, ob man wirklich Änderungen
durchführen will.&lt;/p&gt;

&lt;h4 id=&quot;lokalen-winrm-client-einrichten&quot;&gt;Lokalen WinRM Client einrichten&lt;/h4&gt;

&lt;p&gt;Per Standard erfordert &lt;code&gt;WinRM&lt;/code&gt; die Kommunikation über HTTPS auf Port &lt;code&gt;5986&lt;/code&gt;,
doch da wir hierfür gültige Zertifikate und eine Public-Key Infrastruktur
benötigen, richte ich für Tests (oder in anders gesicherten Netzen) &lt;code&gt;WinRM&lt;/code&gt;
via HTTP ohne Zertifikatzwang auf Standard-Port &lt;code&gt;5985&lt;/code&gt; ein.&lt;/p&gt;

&lt;p&gt;Außerdem muss der Client explizit wissen, welche Server er ansprechen darf.
Das lässt sich aber mit dem Wildcard-Eintrag &lt;code&gt;*&lt;/code&gt; auf “alle” Systeme ausweiten.&lt;/p&gt;

&lt;p&gt;Folgende Kommandos sind also nötig:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;winrm set winrm/config/client @{AllowUnencrypted=&amp;quot;true&amp;quot;}
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;winrm set winrm/config/client @{TrustedHosts=&amp;quot;*&amp;quot;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h4 id=&quot;winrm-service-auf-dem-zielsystem-einrichten&quot;&gt;WinRM Service auf dem Zielsystem einrichten&lt;/h4&gt;

&lt;p&gt;Am Zielcomputer ist ebenfalls die Kommunikation auf “UnEncrypted” zu stellen:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;winrm set winrm/config/service @{AllowUnencrypted=&amp;quot;true&amp;quot;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Auf einem Windows Server ohne User-Account-Control wäre man jetzt fertig und
könnte sich mit einem Administrator Account+Passwort einloggen.&lt;br /&gt;
Doch unsere heutigen Windows Clients entfernen ja die Administrationsrechte
beim Login, und somit wird der Zugang zu &lt;code&gt;WinRM&lt;/code&gt; verweigert.&lt;/p&gt;

&lt;p&gt;Man erhält eine Fehlermeldung wie:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Winrs error:Access is denied.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Hierfür müssen wir einer anderen Gruppe die nötigen Rechte erteilen und
unseren Login-Account in diese Gruppe aufnehmen. Die Gruppe
“Remote Management Users” bietet sich hierfür perfekt an.&lt;/p&gt;

&lt;p&gt;Mit dem Aufruf von&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;winrm configSDDL default
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;öffnet sich der Dialog zum Editieren der Zugriffsrechte und hier kann man die
Gruppe &lt;code&gt;Remote Management Users&lt;/code&gt; mit Lese- und Ausführungsrechten hinzufügen.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/winrm-sddl.png&quot; alt=&quot;WinRM SDDL config&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;remote-shell-starten&quot;&gt;Remote Shell starten&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;winrs&lt;/code&gt; ist das Werkzeug, mit dem die Verbindung zur Konsole des Zielsystems
hergestellt wird. Die Befehlszeile lautet:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;winrs -r:http://remote_ip:5985 -u:remote_login -p:remote_password cmd.exe
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Lässt man den &lt;code&gt;-p:&lt;/code&gt; Eintrag weg, wird man zur Eingabe des Passworts 
aufgefordert.&lt;/p&gt;

&lt;p&gt;Und mit etwas Glück sieht man dann auch schon den Inhalt des entfernten
Systems und kann es mit üblichen Windows-Konsolenkommandos bearbeiten.&lt;/p&gt;

&lt;h4 id=&quot;sonderfall-domain-mitgliedschaften&quot;&gt;Sonderfall Domain-Mitgliedschaften&lt;/h4&gt;

&lt;p&gt;Ist das Zielsystem in einer Domäne, braucht man den Domänennamen vor dem
Account, also:&lt;/p&gt;

&lt;div class=&quot;language-batch highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;winrs -r:http://remote_ip:5985 -u:mydomain\my_dom_account cmd.exe
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Und wenn man auf einem Domänen-PC einen lokalen Account erreichen will,
kann man das mit einem vorangestellten Backslash erreichen 
(oder man stellt den PC-Namen statt der Domäne vorne an):&lt;/p&gt;

&lt;div class=&quot;language-batch highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;winrs -r:http://remote_ip:5985 -u:\my_local_account cmd.exe
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Die Aktivierung von &lt;code&gt;WinRM&lt;/code&gt; auf Industrie-Terminals hat mir schon ein paar
Mal “den Arsch gerettet”, denn so konnten Fehlkonfigurationen im Hintergrund
behoben werden, ohne dass man die Arbeit am Terminal per &lt;code&gt;RDP&lt;/code&gt; oder &lt;code&gt;VNC&lt;/code&gt; 
unterbrechen musste, was den Anwender oft irritierte.&lt;/p&gt;

&lt;p&gt;Die Remote-Shell ist zwar kein gleichwertiger Alternative zu einem SSH Dienst,
aber ein wirklich hilfreiches Werkzeug, das bei jeder Standard-Windows 
Installation vorhanden ist und nur aktiviert werden muss.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Windows Server Backup Cleanup</title>
   <link href="https://www.opengate.at/blog/2024/06/backup-cleanup/"/>
   <published>2024-06-23T13:00:00+02:00</published>
   <updated>2024-06-23T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2024/06/backup-cleanup</id>
   <category term="software" />
   <summary type="text">Täglich läuft nachts der Windows-Server
Backup-Dienst an und sichert alle Daten auf eine externe Festplatte.
Das Backup läuft zwar inkrementell, aber dennoch sammeln sich unzählige 
Änderungen und neuere Downloads an, die das Backup-Medium an die Grenzen
bringen.


  Frage: Wie kann man alte Backup-Zustände löschen?


</summary>
   <content type="html">&lt;p&gt;Täglich läuft nachts der &lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_Server_2022&quot;&gt;Windows-Server&lt;/a&gt;
Backup-Dienst an und sichert alle Daten auf eine externe Festplatte.&lt;br /&gt;
Das Backup läuft zwar inkrementell, aber dennoch sammeln sich unzählige 
Änderungen und neuere Downloads an, die das Backup-Medium an die Grenzen
bringen.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Frage: Wie kann man alte Backup-Zustände löschen?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Bei täglicher Ausführung kommen pro Jahr 365 Backup-Einträge zusammen.
Auf meinem Dateiserver kommen monatlich neue Software und OS-Images auf
die Platte, die ein älteres Image ablösen.&lt;/p&gt;

&lt;p&gt;Im Dateisystem sind diese “Altlasten” schnell gelöscht, doch das Backup
behält diese Stände und wächst somit ordentlich an.&lt;/p&gt;

&lt;p&gt;Und da ich nicht jede Variante von 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Debian&quot;&gt;Debian&lt;/a&gt; Installern bis 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows&quot;&gt;Windows&lt;/a&gt; Versionen im
Backup brauche, möchte ich gerne die gespeicherten (und unbenutzten)
Backup-Zwischenstände löschen.&lt;/p&gt;

&lt;h3 id=&quot;mit-wbadmin-alte-backup-stände-löschen-lassen&quot;&gt;Mit &lt;code&gt;wbadmin&lt;/code&gt; alte Backup Stände löschen lassen&lt;/h3&gt;

&lt;p&gt;Wenn ich bereits weiß, dass ich alle alten Backups, bis auf die letzten 
10 Tage löschen möchte, so lautet das Kommando:&lt;/p&gt;

&lt;div class=&quot;language-batch highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;wbadmin delete backup -keepVersion:10
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Der Parameter &lt;code&gt;-keepVersion&lt;/code&gt; bewahrt die jüngsten 10 Stände (also 10 Tage bei
mir) und entfernt den Rest.&lt;/p&gt;

&lt;p&gt;Das bringt in meinem Fall oft hunderte Gigabyte an freiem Speicher auf der
Sicherungsplatte. Vor allem wenn ich temporär Filme oder andere Daten am
Dateiserver ablege, die später auf DVD oder 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Blu-ray_Disc&quot;&gt;Blu-ray&lt;/a&gt; gebrannt oder einfach
gelöscht werden, wird ordentlich Overhead im Backup Speicher generiert.&lt;/p&gt;

&lt;p&gt;Die Ausgabe des Tools sieht dann etwa so aus:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;C:\&amp;gt;wbadmin delete backup -keepVersions:10
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;wbadmin 1.0 - Backup command-line tool
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;(C) Copyright Microsoft Corporation. All rights reserved.
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;Enumerating backups...
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;Found 283 backups,
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;10 will be left after the delete operation.
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;Do you want to delete the backups?
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;[Y] Yes [N] No y
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;Deleting backup version 09/13/2023-01:30 (1 out of 273)...
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;Deleting backup version 09/14/2023-01:30 (2 out of 273)...
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Theoretisch könnte ich mir jetzt noch einen automatisch auszuführenden Job
setzen, der das Kommando monatlich startet 
… aber das war bisher noch nicht notwendig.&lt;/p&gt;

&lt;p&gt;Ich führe diese manuelle Löschung jedes Jahr an einem freien Wochenende 
durch, wenn ich generell meine Datenbestände aufräume. So weiß ich dann 
auch, dass ich die Altlasten sicher nicht mehr brauche.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>ISO auf CD/DVD brennen mit Windows 10/11</title>
   <link href="https://www.opengate.at/blog/2024/06/isoburn/"/>
   <published>2024-06-16T13:00:00+02:00</published>
   <updated>2024-06-16T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2024/06/isoburn</id>
   <category term="hardware" /><category term="software" />
   <summary type="text">Eigentlich haben wir in Windows seit Jahrzehnten bei 
ISO Dateien den Kontextmenü
Eintrag Burn to disc oder deutsch Auf Datenträger brennen.
Und der macht aus der Datei per CD/DVD/Bluray Brenner ein “klassisches” 
Medium.

Doch dieser Eintrag fehlt bei mir auf fast allen Installationen …
</summary>
   <content type="html">&lt;p&gt;Eigentlich haben wir in Windows seit Jahrzehnten bei 
&lt;a href=&quot;https://de.wikipedia.org/wiki/ISO-Abbild&quot;&gt;ISO Dateien&lt;/a&gt; den Kontextmenü
Eintrag &lt;code&gt;Burn to disc&lt;/code&gt; oder deutsch &lt;code&gt;Auf Datenträger brennen&lt;/code&gt;.
Und der macht aus der Datei per CD/DVD/Bluray Brenner ein “klassisches” 
Medium.&lt;/p&gt;

&lt;p&gt;Doch dieser Eintrag fehlt bei mir auf fast allen Installationen …
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;wenn-7zip-das-cddvd-brennen-versteckt&quot;&gt;Wenn 7zip das CD/DVD-Brennen versteckt&lt;/h3&gt;

&lt;p&gt;Tja … wenn man einem &lt;a href=&quot;https://de.wikipedia.org/wiki/7-Zip&quot;&gt;7zip&lt;/a&gt; oder einem
anderen Tool erlaubt, ISO Dateien öffnen zu lassen, überschreibt man damit 
auch die Standard-Registrywerte, die festlegen, dass jede ISO-Datei mit dem 
Windows-internen ISO Brenner verknüpft wird.&lt;/p&gt;

&lt;p&gt;Man findet dann den Eintrag &lt;code&gt;Burn to disc&lt;/code&gt; beim Rechtsklick auf eine &lt;code&gt;ISO&lt;/code&gt;
Datei nicht mehr.&lt;/p&gt;

&lt;h3 id=&quot;isoburnexe-mit-iso-verknüpfen&quot;&gt;isoburn.exe mit .iso verknüpfen&lt;/h3&gt;

&lt;p&gt;In &lt;code&gt;c:\windows\system32&lt;/code&gt; liegt das Programm &lt;code&gt;isoburn.exe&lt;/code&gt; und eben dieses 
verwaltet den Brennvorgang.&lt;/p&gt;

&lt;p&gt;Mit dem Aufruf von &lt;code&gt;isoburn path\to\myimage.iso&lt;/code&gt; öffnet sich der gewohnte
Dialog, der einen das Ziel-CD/DVD-Laufwerk auswählen und den Vorgang starten
lässt.&lt;/p&gt;

&lt;p&gt;Der schnellste Fix für den fehlenden Eintrag im Kontextmenü ist also:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Rechtsklick auf eine &lt;code&gt;.iso&lt;/code&gt; Datei&lt;/li&gt;
  &lt;li&gt;Im Kontextmenü: &lt;code&gt;Open with&lt;/code&gt; (&lt;code&gt;Öffnen mit&lt;/code&gt;)&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;Choose another app&lt;/code&gt; (&lt;code&gt;Andere App auswählen&lt;/code&gt;)&lt;/li&gt;
  &lt;li&gt;Runterscrollen und &lt;code&gt;Choose an app on your PC&lt;/code&gt; (&lt;code&gt;Andere App auf diesem PC suchen&lt;/code&gt;) wählen.&lt;/li&gt;
  &lt;li&gt;Dann &lt;code&gt;c:\windows\system32\isoburn.exe&lt;/code&gt; suchen und auswählen.&lt;/li&gt;
  &lt;li&gt;Und dann den neuen Eintrag &lt;code&gt;Windows Disc Image Burner&lt;/code&gt; 
(&lt;code&gt;Windows-Brenner für Datenträgerabbilder&lt;/code&gt;) mit &lt;code&gt;Always&lt;/code&gt; für immer mit 
ISO-Dateien verknüpfen.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ein Doppelklick auf eine &lt;code&gt;.iso&lt;/code&gt; Datei öffnet nun &lt;code&gt;isoburn.exe&lt;/code&gt; und das Brennen
kann beginnen.&lt;/p&gt;

&lt;p&gt;Alternativ kann man das auch über den Dialog &lt;code&gt;Default apps&lt;/code&gt; oder &lt;code&gt;Default programs&lt;/code&gt; 
(je nach Windows-Version) in der Settings-App oder in der Systemsteuerung durchführen
lassen.&lt;br /&gt;
Man sucht auch dort nach &lt;code&gt;.iso&lt;/code&gt; Dateien und verbindet sie mit dem
&lt;code&gt;Windows Disk Image Burner&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Bevor Windows mit Version 7 das Brennen endlich selbst in die Hand nahm, sah 
sich unsereiner bei jedem Laufwerk mit einer anderen Software konfrontiert.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Nero_Burning_ROM&quot;&gt;Nero Burning ROM&lt;/a&gt; kam da zwar
am häufigsten vor, aber ich erinnere mich da noch an anderen, an deren Namen
ich mich wiederum nicht mehr erinnere.&lt;/p&gt;

&lt;p&gt;Zwar werden CDs und DVDs immer unwichtiger, doch so manche Retro-Hardware-
Installation klappt per Scheibe immer noch viel besser, als per USB-Stick.
Und deshalb ist die Verfügbarkeit des Windows-Brenn-Tools immer wieder 
aufs Neue wichtig.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;7zip&lt;/code&gt; kann eine ISO auch über das 7zip-Kontextmenü öffnen, von daher ist 
das Umregistrieren der “Default-App” kein Problem.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>StarFive VisionFive2</title>
   <link href="https://www.opengate.at/blog/2024/06/star-v/"/>
   <published>2024-06-15T13:00:00+02:00</published>
   <updated>2024-06-15T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2024/06/star-v</id>
   <category term="hardware" />
   <summary type="text">Immer mehr RISC-V Development Boards kommen 
auf den Markt, und das ist gut so. Mit dem VisionFive2 wird auch meine 
Familie wieder um ein Mitglied reicher.

</summary>
   <content type="html">&lt;p&gt;Immer mehr &lt;a href=&quot;https://de.wikipedia.org/wiki/RISC-V&quot;&gt;RISC-V&lt;/a&gt; Development Boards kommen 
auf den Markt, und das ist gut so. Mit dem &lt;code&gt;VisionFive2&lt;/code&gt; wird auch meine 
Familie wieder um ein Mitglied reicher.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/visionfive2.jpg&quot; alt=&quot;StarFive VisionFive2&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Mit einem 4x 1.5 GHz JH7110 Prozessor, 8 GB RAM, HDMI Grafik, 4 USB Ports,
2 Ethernet.Ports und Medienunterstützung für SD-Karten, eMMC und NVME M2 SSDs
bietet StarFive mit dem Entwickler-Board &lt;code&gt;VisionFive2&lt;/code&gt; einen hervorragendes 
RISC-V SoC-Computer zum kleinen Preis von etwa 100 Euro.&lt;br /&gt;
Die 4 GB Variante ist etwa 20 Euro günstiger.&lt;/p&gt;

&lt;p&gt;Einen großen Vorteil gegenüber dem &lt;a href=&quot;/blog/2023/09/star64/&quot;&gt;Pine64 Star64&lt;/a&gt;
stellen folgenden Faktoren dar:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Die kompaktere Plantine,&lt;/li&gt;
  &lt;li&gt;der NVME M2 Support,&lt;/li&gt;
  &lt;li&gt;und eine USB-C Bestromung.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;software-installation&quot;&gt;Software Installation&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Debian&quot;&gt;Debian&lt;/a&gt; plant in seinem nächsten großen 
Release (Debian 13 - Trixie) RISC-V 64 und diverse Boards vollständig zu
unterstützen, doch bis dahin müssen wir uns mit einem Unstable-Development
Stand des Betriebssystems begnügen.&lt;/p&gt;

&lt;p&gt;Eine Beschreibung der Installation ist unter 
&lt;a href=&quot;https://rvspace.org/en/project/VisionFive2_Debian_Wiki_202403_Release&quot;&gt;rvspace.org&lt;/a&gt;
abgelegt, welcher ich gefolgt bin.&lt;/p&gt;

&lt;p&gt;Ein vorbereitetes Debian-Image ist bereits auf einigen Filehostern vorhanden, 
darunter eine öffentliche 
&lt;a href=&quot;https://onedrive.live.com/?id=8DAB77C937089CE9%21316442&amp;amp;cid=8DAB77C937089CE9&amp;amp;sb=name&amp;amp;sd=1&amp;amp;view=0&quot;&gt;One-Drive Instanz&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Das Image muss nur auf eine SD-Karte übertragen werden.
Vor dem Boot sollte geprüft werden, dass die beiden DIP-Schalter auf dem 
Board auch korrekt gesetzt sind.
Bei mir klappte es mit der “Flash” Einstellung (beide Schalter zeigen in 
Richtung des &lt;code&gt;ONKE&lt;/code&gt; Textes), denn im internen Speicher des Geräts ist bereits
ein &lt;code&gt;uBoot&lt;/code&gt; Loader installiert, der danach den SD-Karten Boot durchführt.&lt;/p&gt;

&lt;p&gt;Den erfolgreichen Boot erkennt man nach einigen Sekunden Wartezeit an der 
grün blinkenden LED am Board. Denn in der ersten Minute bleibt der Bildschirm
schwarz und man weiß nicht so recht, ob das System nun wirklich bootet oder
eben kein Medium erkannt wurde.&lt;/p&gt;

&lt;p&gt;Doch letztendlich kann man sich grafisch mit dem Benutzer &lt;code&gt;user&lt;/code&gt; und dem 
Passwort &lt;code&gt;starfive&lt;/code&gt; einloggen.&lt;br /&gt;
Die Gnome-Wayland Umgebung wirkt allerdings recht träge und erinnert
etwas an eine UI-Installation auf einem Raspberry PI Zero oder Model 2.&lt;br /&gt;
Es funktioniert zwar, läuft aber nicht, sondern kriecht.&lt;/p&gt;

&lt;p&gt;Wenn man aber per&lt;br /&gt;
&lt;code&gt;sudo systemctl set-default multi-user.target&lt;/code&gt; das System nicht grafisch 
sondern nur per Konsole betreibt, kann man “normal” damit arbeiten.&lt;br /&gt;
Denn nachdem mit &lt;code&gt;apt install&lt;/code&gt; notwendige Build Utilities installiert sind,
lässt sich mit z.B. &lt;code&gt;neovim&lt;/code&gt; Software Entwicklung durchführen.&lt;br /&gt;
Und hier steht der &lt;code&gt;VisionFive2&lt;/code&gt; in Sachen GPIO und Library-Support in
nichts nach.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ich vermute, dass mit künftigen Software-Updates die aktuelle Trägheit des
Systems zurückgehen wird. Denn für 4x 1.5 GHz ist der Betrieb wirklich
bedenklich langsam. Das liegt vermutlich auch an den Treibern.&lt;/p&gt;

&lt;p&gt;Der Stromverbrauch liegt unbelastet bei 4-5 Watt und steigt bei einer 
Vollauslastung aller Kerne (beim Kompilieren) auf 8 Watt.&lt;br /&gt;
Das ist zwar etwas mehr als diverse schwachbrüstige ARM-SoCs, aber auch 
nicht wirklich viel. Ein 2A-Netzteil reicht also aus. 3A / 15 Watt
sind aber trotzdem zu empfehlen, wenn weitere Peripheriegeräte
angeschlossen sind.&lt;/p&gt;

&lt;p&gt;Nichts desto trotz haben wir mit dem &lt;code&gt;VisionFive2&lt;/code&gt; ein Stückchen Zukunft
in den Händen. RISC-V ist immer noch kein Rennpferd und hinkt einer
ARM64 Plattform noch ein paar Jahre hinterher.&lt;br /&gt;
Doch die OpenSource-Idee und Patentfreiheit der Hardware macht sie für 
moderne Unternehmen preiswert und daher interessant.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Workfolders über HTTP</title>
   <link href="https://www.opengate.at/blog/2024/06/workfolders-http/"/>
   <published>2024-06-09T13:00:00+02:00</published>
   <updated>2024-06-09T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2024/06/workfolders-http</id>
   <category term="software" />
   <summary type="text">Microsoft erklärt uns bei der Einrichtung von Workfolders 
(deutsch: Arbeitsordner), dass diese nur mit HTTPS funktionieren. Das hat 
inzwischen auch so manche KI gelernt und versteift sich jetzt darauf.

Das stimmt aber nicht.
</summary>
   <content type="html">&lt;p&gt;Microsoft erklärt uns bei der Einrichtung von Workfolders 
(deutsch: Arbeitsordner), dass diese nur mit HTTPS funktionieren. Das hat 
inzwischen auch so manche KI gelernt und versteift sich jetzt darauf.&lt;/p&gt;

&lt;p&gt;Das stimmt aber nicht.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Meine Beziehung zum Workfolders-Feature unter &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows&quot;&gt;Windows&lt;/a&gt; ist schwankend.
Ich finde es super, dass man seinen eigenen “One-Drive-Service” auf einem 
Server einrichten und dann Daten von mehreren Clients hin- und her-
synchronisieren kann.&lt;/p&gt;

&lt;p&gt;Wenn es aber um die SSL-Einrichtung/Aktualisierung geht, hasse ich das Teil!&lt;/p&gt;

&lt;p&gt;Ein fehlendes UI und fehlende “gute” Dokumentation sind der Grund dafür,
dass man dann stundenlang Konfigurationsdateien editieren und Zertifikate
erzeugen, exportieren und importieren muss.&lt;/p&gt;

&lt;p&gt;Es geht aber auch einfacher: Man schaltet das HTTPS-Requirement einfach aus
und nutzt das ganze unverschlüsselt.&lt;br /&gt;
Das sollte man im Unternehmensbereich nicht machen … aber auf meinem
internen Netzwerk, das vom Internet durch zwei Router getrennt ist, 
wollen wir mal nicht so pingelig sein.&lt;/p&gt;

&lt;h3 id=&quot;windows-workfolders-mit-http-statt-https-betreiben&quot;&gt;Windows Workfolders mit HTTP statt HTTPS betreiben&lt;/h3&gt;

&lt;p&gt;Man legt einfach auf der Client-Maschine im Registry Key:&lt;br /&gt;
&lt;code&gt;HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\WorkFolders&lt;/code&gt;&lt;br /&gt;
einen &lt;code&gt;DWORD&lt;/code&gt; Eintrag namens &lt;code&gt;AllowUnsecureConnection&lt;/code&gt; an und setzt 
den Wert auf &lt;code&gt;1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Dann beendet man am Besten den Workfolders Dienst (interner Name 
&lt;code&gt;workfolderssvc&lt;/code&gt;) und öffnet dann im Control-Panel das Workfolders
Plugin und beginnt mit der Einrichtung.&lt;br /&gt;
Dort wählt man aus, dass man eine URL eingeben möchte und setzt nun:&lt;br /&gt;
&lt;code&gt;http://myserver.tld&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Ohne &lt;code&gt;AllowUnsecureConnection&lt;/code&gt; kommt die Fehlermeldung, dass die URL
mit &lt;code&gt;https://&lt;/code&gt; beginnen muss, doch &lt;strong&gt;mit&lt;/strong&gt; der Einstellung startet 
die Synchronisierung problemlos.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Genau für solche “Spielereien” erwartete ich von einem ordentlichen
Produkt, dass man in einem Zusatzdialog namens “Erweiterte Konfiguration”
einfach einen Haken setzen kann, um den HTTPS Zwang deaktivieren zu können.&lt;/p&gt;

&lt;p&gt;Doch leider bleibt die Registry … seit mittlerweile 30 Jahren … immer 
noch das einzige Tool, mit dem man Windows wirklich konfigurieren kann.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Windows Vista WSUS Update</title>
   <link href="https://www.opengate.at/blog/2024/06/vista-update/"/>
   <published>2024-06-02T13:00:00+02:00</published>
   <updated>2024-06-02T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2024/06/vista-update</id>
   <category term="software" /><category term="retro" />
   <summary type="text">Auch wenn es denkbar unwahrscheinlich ist, dass jemand heute noch 
Windows Vista
hegt und pflegt … ich habe nach wie vor eine Test-
VM mit diesem System.

Doch WSUS
Updates ließen sich um’s Verrecken nicht einrichten, da der 
Update-Dienst mit hoher CPU Auslastung einfach hängen bleibt.
</summary>
   <content type="html">&lt;p&gt;Auch wenn es denkbar unwahrscheinlich ist, dass jemand heute noch 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_Vista&quot;&gt;Windows Vista&lt;/a&gt;
hegt und pflegt … ich habe nach wie vor eine Test-
&lt;a href=&quot;https://de.wikipedia.org/wiki/Virtuelle_Maschine&quot;&gt;VM&lt;/a&gt; mit diesem System.&lt;/p&gt;

&lt;p&gt;Doch &lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_Server_Update_Services&quot;&gt;WSUS&lt;/a&gt;
Updates ließen sich um’s Verrecken nicht einrichten, da der 
Update-Dienst mit hoher CPU Auslastung einfach hängen bleibt.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;So wie bei anderen “historischen” Systemen, habe ich auch für Windows Vista:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;eine WSUS Gruppe am Server angelegt und Updates freigegeben&lt;/li&gt;
  &lt;li&gt;dem Client werden neue Zertifikate eingepflanzt,&lt;/li&gt;
  &lt;li&gt;die Registry mit Einträgen für den WSUS erweitert&lt;/li&gt;
  &lt;li&gt;und &lt;code&gt;wuauclt&lt;/code&gt; mit &lt;code&gt;/resetauthentication&lt;/code&gt;, &lt;code&gt;/reportnow&lt;/code&gt; und &lt;code&gt;/detectnow&lt;/code&gt;
ausgeführt.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Doch nach dem ersten Selbstupdate, läuft der Update-Dienst danach zwar an,
sammelt offenbar Daten zusammen und bleibt dann mit einem CPU-Kern auf 
Vollauslastung für alle Ewigkeiten hängen.&lt;br /&gt;
Ich hatte die VM ein Woche “arbeiten” lassen und es brachte nichts, außer
viel verbratener CPU Zeit.&lt;br /&gt;
Auch das Löschen von &lt;code&gt;C:\Windows\SoftwareDistribution&lt;/code&gt; brachte nichts.&lt;/p&gt;

&lt;p&gt;An der Stelle möchte man aufgeben und akzeptieren, dass das System einfach
nicht mehr zeitgemäß ist. (Obwohl: Windows 2000/XP Updates laufen brav weiter).&lt;/p&gt;

&lt;h3 id=&quot;updates-manuell-einspielen&quot;&gt;Updates manuell einspielen.&lt;/h3&gt;

&lt;p&gt;Zahlreiche Erklärungen und Hinweise im Web halfen mir nicht, bis ich dann 
auf eine 
&lt;a href=&quot;https://answers.microsoft.com/en-us/windows/forum/all/windows-vista-windows-update-stuck-on-checking-for/7630b66e-38dd-4ee5-985c-945880ccf4a1&quot;&gt;Microsoft-Forum Antwort&lt;/a&gt;
stieß.&lt;/p&gt;

&lt;p&gt;Hier heißt es, man soll die Updates&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.catalog.update.microsoft.com/Search.aspx?q=KB3205638&quot;&gt;KB3205638&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.catalog.update.microsoft.com/Search.aspx?q=KB4012583&quot;&gt;KB4012583&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.catalog.update.microsoft.com/Search.aspx?q=KB4014661&quot;&gt;KB4014661&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.catalog.update.microsoft.com/Search.aspx?q=KB4015195&quot;&gt;KB4015195&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.catalog.update.microsoft.com/Search.aspx?q=KB4015380&quot;&gt;KB4015380&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;einspielen und es nochmals versuchen.&lt;/p&gt;

&lt;p&gt;Nach dem Herunterladen der MSU Dateien muss man Windows Updates deaktivieren.
Also die Einstellung &lt;code&gt;Never check for updates (not recommended)&lt;/code&gt; setzen, weil
sonst auch beim manuellen Ausführen der Updates eine endlose Suche startet.&lt;/p&gt;

&lt;p&gt;Doch nach der Installation der 5 Updates und einem Reboot, und dem Aktivieren
von Updates, konnte der Dienst tatsächlich seine Suche abschließen und 
fehlende weitere Updates von meiner WSUS Maschine herunterladen und integrieren.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Windows Vista lässt sich also genau wie Windows XP auch im Jahr 2024 noch mit 
WSUS auf den letzten Stand bringen, wenn man helfend eingreift.&lt;/p&gt;

&lt;p&gt;Dass sich der Update-Dienst aber selbst zerstört und dann das System mit einer
Endlosschleife blockiert, ist aber eigentlich nicht hinnehmbar.&lt;/p&gt;

&lt;p&gt;Solche Fehlkonstruktionen passieren leider häufiger, wenn der offizielle 
Support beendet wird. Dennoch sollte man nicht vergessen, dass der erweiterte
Support und die Versorgung mit den letzten Updates 10 bis 15 Jahre weiterläuft
und genau diese Funktion muss ein Update-System sicherstellen können.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>PowerQuest Partition Magic</title>
   <link href="https://www.opengate.at/blog/2024/05/pqmagic/"/>
   <published>2024-05-26T13:00:00+02:00</published>
   <updated>2024-05-26T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2024/05/pqmagic</id>
   <category term="software" /><category term="retro" />
   <summary type="text">Es war wieder mal eine Heft-CD, die mich mit einer der wichtigsten 
Software-Lösungen in den 90ern zusammenbrachte.

PQMagic war der ultimative Partitions-Manager, der mich damals in 
die Lage versetzte mehrere Betriebssysteme parallel installieren zu können.

</summary>
   <content type="html">&lt;p&gt;Es war wieder mal eine Heft-CD, die mich mit einer der wichtigsten 
Software-Lösungen in den 90ern zusammenbrachte.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/PartitionMagic&quot;&gt;PQMagic&lt;/a&gt; war der ultimative Partitions-Manager, der mich damals in 
die Lage versetzte mehrere Betriebssysteme parallel installieren zu können.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;blockquote&gt;
  &lt;p&gt;Partitionen sind eine “gefährliche” Sache. 
Verkackt man sie, ist alles weg.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Meinen erster größeren Datenverlust verdanke ich 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt; und einer falsch abgetippten Zahl
beim manuellen Verändern der Partitionstabelle.
Das muss so im Jahr 1998 gewesen sein, als die ersten Linux-Distros
auf den berühmten Magazin-Heft-CDs auch mich hinter den 7 Bergen
erreichten.&lt;/p&gt;

&lt;p&gt;In der &lt;a href=&quot;https://de.wikipedia.org/wiki/MS-DOS&quot;&gt;DOS&lt;/a&gt; und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows&quot;&gt;Windows&lt;/a&gt; Welt gab es 
damals eine Regel:&lt;br /&gt;
&lt;strong&gt;Es kann nur ein OS geben.&lt;/strong&gt;&lt;br /&gt;
Und deshalb konnten Tools wie &lt;code&gt;fdisk&lt;/code&gt; unter DOS auch nur genau eine 
primäre Partition mit Boot-Flag anlegen und alles weitere waren 
“logische Laufwerke” auf der erweiterten (nicht boot-baren) Partition.&lt;/p&gt;

&lt;p&gt;Eine kleine Ausnahme gab es: Wer ein 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_NT_4.0&quot;&gt;Windows NT 4&lt;/a&gt; auf einer
primären Partition installierte und das Dateisystem auf NTFS konvertierte, 
konnte im NT Festplatten-Tool weitere primäre FAT-Partitionen anlegen und 
sogar das Boot-Flag auf diese setzen.&lt;br /&gt;
So konnte man dann wieder von DOS-Diskette starten und auf der 2. primären
Partition DOS oder Windows 3x/9x installieren, denn diese erkannten NTFS
nicht und so konnte man auch per &lt;code&gt;fdisk&lt;/code&gt; zwischen diesen Systemen per 
Bootflag hin- und her-schalten.&lt;/p&gt;

&lt;p&gt;Aber eigentlich war es erst Linux, das mich auf die Idee brachte, auf 
einem PC mehr als ein OS zu installieren.&lt;br /&gt;
… bis ich es verkackt hatte … und Linux lange dafür hasste.&lt;/p&gt;

&lt;p&gt;Und dann kam endlich die Heft-CD mit dem Tool, das alles veränderte:
&lt;code&gt;PowerQuest Partition Magic&lt;/code&gt; oder kurz &lt;code&gt;pqmagic.exe&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/dos-prog-pqmagic.png&quot; alt=&quot;DOS Program PQMagic 4&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;pqmagic-ein-dos-tool-im-windows-look&quot;&gt;PQMagic, ein DOS Tool im Windows Look&lt;/h3&gt;

&lt;p&gt;Mich fasziniert bis heute, dass sich jemand die Mühe gemacht hat das volle
Look&amp;amp;Feel von Windows 95 in einer DOS-Anwendung im 640x480 VGA Modus 
nachzustellen. Denn das Fenster, das Menü und die Buttons sehen wirklich
fast exakt so aus, als wären sie mit der 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_Application_Programming_Interface&quot;&gt;WinAPI&lt;/a&gt; 
gezeichnet worden.&lt;/p&gt;

&lt;p&gt;Viel wichtiger war aber, dass &lt;code&gt;PQMagic&lt;/code&gt; eine grafische Oberfläche für 
Partitionen, einige Sicherheits-Checks und bis dato unbekannte Features
bereitstellte.&lt;/p&gt;

&lt;h3 id=&quot;mehrere-primäre-partition&quot;&gt;Mehrere primäre Partition&lt;/h3&gt;

&lt;p&gt;Endlich konnte man auf einer Festplatte mehrere Partition anlegen und
sogar FAT16 und FAT32 Dateisystem aufsetzen.&lt;br /&gt;
Damit sich mehrere parallele Windows oder DOS Installation nicht gegenseitig
störten, wurde die Funktion &lt;code&gt;Versteckte Partition&lt;/code&gt; eingeführt, womit eine
FAT Partition einfach einen unbekannten Partitions-Typ zugewiesen bekam
und damit von DOS und Windows nicht mehr erkannt wurde.&lt;/p&gt;

&lt;p&gt;Per &lt;code&gt;PQMagic&lt;/code&gt; konnte man dann beim Wechsel des Boot-Flags die versteckte
Partition wieder in eine sichtbare umwandeln und die andere dann verstecken.&lt;/p&gt;

&lt;h3 id=&quot;anpassung-der-größe&quot;&gt;Anpassung der Größe&lt;/h3&gt;

&lt;p&gt;Das wichtigste Feature war jedoch die Änderung der Größe einer Partition
und des Dateisystems. Und damit ist nicht einfach nur die Anpassung der
Grenzen gemeint, sondern eine vollständige Restrukturierung des Dateisystems,
wenn dies notwendig war.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/File_Allocation_Table&quot;&gt;FAT&lt;/a&gt; nutzt Cluster, die bei 
größeren Kapazitäten ebenso größer werden müssen, um mit 16-bit Indizes 
adressiert werden zu können.&lt;br /&gt;
Wer eine 500 MB Partition mit einer 8KB Clustergröße um 100 MB vergrößern
wollte, war mit der 512MB-Grenze gezwungen auf 16KB Cluster zu wechseln.
Dafür musste jede einzelne Datei in neue Cluster zusammengefasst werden, 
was bei der üblichen Fragmentierung ein vollständiges Neuschreiben von 
allen Daten notwendig machte.&lt;/p&gt;

&lt;p&gt;Und genau diesen Job erledigte &lt;code&gt;PQMagic&lt;/code&gt; bei mir immer fehlerfrei und ohne
Datenverlust.&lt;br /&gt;
Auch heutige Tools in Windows, die Laufwerksgrößen anpassen können, tun
dies nur in den Dimensionen, wo sie keine bestehenden Daten verändern müssen.
&lt;code&gt;PQMagic&lt;/code&gt; konnte also schon damals wesentlich mehr.&lt;/p&gt;

&lt;p&gt;Ein Sonderfall war dann hier auch noch die Konvertierung von &lt;code&gt;FAT16&lt;/code&gt; zu &lt;code&gt;FAT32&lt;/code&gt;
und umgekehrt. Das neue &lt;code&gt;FAT32&lt;/code&gt;, welches mit Windows 95b und Win98 eingeführt 
wurde konnte wieder von NT4 nicht erkannt werden und anstatt jetzt Daten bei 
der falschen Dateisystemwahl hin- und herzukopieren, konnte &lt;code&gt;PQMagic&lt;/code&gt; mit 
einer Konvertierung das Problem viel eleganter lösen (so lange die 2GB Grenze 
nicht überschritten wurde).&lt;/p&gt;

&lt;h3 id=&quot;verschiebung-backups-und-spezialfälle&quot;&gt;Verschiebung, Backups und Spezialfälle&lt;/h3&gt;

&lt;p&gt;Auch das Verschieben von Partitionen und allen enthaltenen Daten war mit 
diesem Tool erstmals möglich. Wer bestehende Partitionen in der Größe
anpasste, hatte dann auch großes Interesse entstandene Lücken aufzufüllen.&lt;/p&gt;

&lt;p&gt;Und wer eine zweite größere Festplatte gekauft hatte, konnte &lt;code&gt;PQMagic&lt;/code&gt;
für das effiziente Kopieren aller Daten auf das neue Medium einsetzen.
Auch dem System unbekannte Dateisysteme wie &lt;code&gt;NTFS&lt;/code&gt; oder &lt;code&gt;ext2&lt;/code&gt; konnten 
so Byte für Byte gespiegelt werden.&lt;/p&gt;

&lt;p&gt;Und für die Bit-Hacker gab es dann auch noch Tools zum Anpassen der
&lt;code&gt;FAT&lt;/code&gt;-Stammverzeichnisgröße. Diese wird beim Formatieren auf einen festen Wert
gesetzt und kann beim Erreichen dieser Grenze dann keine neuen Dateien oder
Unterverzeichnisse mehr behandeln … außer man nutzt &lt;code&gt;PQMagic&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Die Prüfung auf fehlerhafte Sektoren hört sich neben den anderen genialen
Features dann schon fast trivial an.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;PQMagic&lt;/code&gt; ermöglichte mir den Multiboot von allen Microsoft-Betriebssystemen
auf einer Festplatte viele Jahre bevor dies von Microsoft vorgesehen war.
Und da alle Aktionen per UI “deppensicher” durchgeführt wurden, konnte man
auch gar keine falschen Werte eintippen, die eine Partition zerstört hätte,
so wie es mir mit Linux erging.&lt;br /&gt;
(OK, den Partition-Löschen Befehl mit Sicherheitsfrage mal ausgenommen.)&lt;/p&gt;

&lt;p&gt;Es war vermutlich auch dieses Werkzeug und mein zuvor erlittener Fehlschlag,
der mich damals lehrte, dass gute Software anwenderfreundlich und 
fehlerabweisend geschrieben sein muss.&lt;br /&gt;
Heute ist diese Erkenntnis auch in Linux angekommen und hat seinen heutigen
Erfolg ermöglicht.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;PQMagic&lt;/code&gt; hat aber weiter einen besonderen Platz in meinem Retro-Herzen und
bekommt auf meinen &lt;a href=&quot;/blog/2024/05/pocket386/&quot;&gt;Pocket386-Laptop&lt;/a&gt; 
und in &lt;a href=&quot;https://de.wikipedia.org/wiki/QEMU&quot;&gt;QEMU&lt;/a&gt; Images wieder neue Aufgaben.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Pocket386</title>
   <link href="https://www.opengate.at/blog/2024/05/pocket386/"/>
   <published>2024-05-19T13:00:00+02:00</published>
   <updated>2024-05-19T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2024/05/pocket386</id>
   <category term="hardware" />
   <summary type="text">Weil mich mein Book8088 
so glücklich gemacht hat, bestellte ich auch gleich
sein Brudermodel: Den Pocket386.

Nun kam mein zweiter Minilaptop mit 40 MHz 
80386 CPU und 8 MB RAM an.
Jetzt habe ich endlich mal ein echtes 
Windows 95, dass sich genau 
so verhält, wie es damals vor 30 Jahren der Fall war.

</summary>
   <content type="html">&lt;p&gt;Weil mich mein &lt;a href=&quot;/blog/2024/04/book8088/&quot;&gt;Book8088&lt;/a&gt; 
so glücklich gemacht hat, bestellte ich auch gleich
sein Brudermodel: Den Pocket386.&lt;/p&gt;

&lt;p&gt;Nun kam mein zweiter Minilaptop mit 40 MHz 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Intel_80386&quot;&gt;80386 CPU&lt;/a&gt; und 8 MB RAM an.
Jetzt habe ich endlich mal ein echtes 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_95&quot;&gt;Windows 95&lt;/a&gt;, dass sich genau 
so verhält, wie es damals vor 30 Jahren der Fall war.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Erneut lässt ein Produkt aus China mein Retro-Herz schneller schlagen.&lt;br /&gt;
Der &lt;code&gt;Pocket386&lt;/code&gt; verbaut einen Embedded 386-Prozessor mit einem LCD
Screen, 8 MB RAM und einer Compact-Flash Karte in einem kleinen 
Plastik-Laptop-Gehäuse und lässt mich nun das Abenteuer
Windows 95 erstmals seit 25 Jahren wieder neu erleben.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/pocket386_win95.jpg&quot; alt=&quot;Pocket386 Win95&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Der &lt;a href=&quot;https://www.cpushack.com/ULi.html&quot;&gt;Ali M6117&lt;/a&gt; ist mit 40 MHz 
getaktet was für einen 386er viel, für die Windows 9x aber ein 
kritisches Minimum darstellt.&lt;/p&gt;

&lt;p&gt;Trotz der für diese Verhältnisse schnellen 
&lt;a href=&quot;https://de.wikipedia.org/wiki/CompactFlash&quot;&gt;CompactFlash&lt;/a&gt; Karte, startet
und reagiert das System relativ träge … aber ausreichend, dass
man damit arbeiten kann.&lt;/p&gt;

&lt;p&gt;Ein 4000 mA LiPo-Akku ermöglicht das Arbeiten für mindestens eine halbe Stunde.
(Mehr habe ich noch nicht ausgetestet.)
Geladen wird das Gerät über ein 12V 1.5A Netzteil.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/pocket386_back.jpg&quot; alt=&quot;Pocket386 back&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Interessant ist vor allem die Maus-Integration.&lt;br /&gt;
Diese kann entweder per Tastatur simuliert werden, oder man 
bedient sich eines PS/2 Adapters und schließt eine echte Maus an dessen
Buchse an.&lt;br /&gt;
Eine reale Maus ist zu empfehlen, denn die Tastatursteuerung mit den
Pfeiltasten ist wahrlich ein Graus.&lt;/p&gt;

&lt;p&gt;An der Seite befindet sich wie beim Book8088 der CF-Kartenslot und eine
USB-Buchse für einen FAT-formatierten USB-Stick, der per DOS-Treiber
eingebunden werden kann.&lt;br /&gt;
Auf eine reguläre serielle Schnittstelle wird verzichtet, doch dafür erhalten
wir ein PIN-Interface für eine parallele Schnittstelle, wie sie Drucker aus 
jener Zeit benötigten.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/pocket386_left.jpg&quot; alt=&quot;Pocket386 left&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Auf der Rückseite können spezielle Flachbandkabel an einen von 4 Ports 
angestöpselt werden:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Ein ISA-GPIO Port, der eine serielle Schnittstelle mit TTL 
(und nicht RS232!) Elektronik bereitstellt.&lt;/li&gt;
  &lt;li&gt;Der PS2/VGA Port für eine externe Tastatur und Maus, 
wie auch einen VGA-Monitor&lt;/li&gt;
  &lt;li&gt;Ein ISA-16-bit Port&lt;/li&gt;
  &lt;li&gt;Der vom 8088 bekannte ISA-8-bit Port&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/pocket386_ports.jpg&quot; alt=&quot;Pocket386 ports&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;betrieb&quot;&gt;Betrieb&lt;/h3&gt;

&lt;h4 id=&quot;lcd-display&quot;&gt;LCD Display&lt;/h4&gt;

&lt;p&gt;Der 7 Zoll große (21x12 cm) Display kann nur mit 640 x 480 Pixel
betrieben werden, doch über das OSD-Menü per &lt;code&gt;Fn+F4&lt;/code&gt; kann der 
Screen zwischen 16:9 und 4:3 hin und hergeschaltet werden, wo beim
16:9 Modus die 640 x 480 Pixel einfach auf 800 x 480 gestreckt werden.&lt;/p&gt;

&lt;p&gt;Das sieht zwar etwas verzerrt, aber immer noch akzeptabel aus und verbessert
die Lesbarkeit von Texten.&lt;/p&gt;

&lt;h4 id=&quot;peripheriegeräte&quot;&gt;Peripheriegeräte&lt;/h4&gt;

&lt;p&gt;Mit der Tastenkombination &lt;code&gt;Fn+F5&lt;/code&gt; erscheint ein Menü mit Infos zum
Akkustand und mit dem Status zu Soundkarte, Parallel Port, VGA und
Mouse.&lt;/p&gt;

&lt;p&gt;Folgende weiter Tastenkombination sind möglich:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;Fn+3&lt;/code&gt; Sound Ausgang ein/ausschalten (also auf laut oder still schalten)&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;Fn+O&lt;/code&gt; OPL3 Soundkarte ganz deaktivieren&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;Fn+P&lt;/code&gt; Parallel Port ein/ausschalten&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;Fn+1&lt;/code&gt; Zwischen LCD und externem VGA Monitor hin- und herschalten&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;Fn+5&lt;/code&gt; PS/2 Tastaturmaus ein/ausschalten&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;tastaturmaus&quot;&gt;Tastaturmaus&lt;/h4&gt;

&lt;p&gt;Ist diese aktiviert, kann man mit den Tasten rechts-unten auf der
Tastatur eine virtuelle Maus steuern.&lt;/p&gt;

&lt;p&gt;Der PS/2 Maus Port muss dafür im BIOS aktiviert sein.
Hierfür wechselt man per &lt;code&gt;Delete&lt;/code&gt; Taste beim Einschalten ins 
&lt;a href=&quot;https://de.wikipedia.org/wiki/BIOS&quot;&gt;BIOS&lt;/a&gt; zum&lt;br /&gt;
&lt;code&gt;Advanced CMOS Setup&lt;/code&gt; und beim Punkt &lt;code&gt;Mouse Support&lt;/code&gt; per&lt;br /&gt;
&lt;code&gt;PgDn&lt;/code&gt; Taste (also &lt;code&gt;Fn+Pfeil-runter&lt;/code&gt;) auf &lt;code&gt;Enabled&lt;/code&gt;.&lt;br /&gt;
&lt;code&gt;Esc&lt;/code&gt; + &lt;code&gt;Save Settings and Exit&lt;/code&gt; speichern die Einstellung.&lt;/p&gt;

&lt;p&gt;Nach dem Start steuern folgende Tasten die virtuelle Maus:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Pfeiltasten: Bewegen den Mauszeiger nach links/rechts/oben/unten&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;?&lt;/code&gt; führt einen Linksklick durch&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;Shift&lt;/code&gt; führt einen Rechtsklick durch&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;usb-stick&quot;&gt;USB Stick&lt;/h4&gt;

&lt;p&gt;Der vom &lt;code&gt;Book8088&lt;/code&gt; bekannte USB-Port ist ebenso vorhanden und wird
über den gleichen DOS-Treiber aktiviert.&lt;br /&gt;
Ist vor dem Start ein FAT16 USB Stick angeschlossen und der
Treiber in &lt;code&gt;config.sys&lt;/code&gt; registriert, ist der Stick-Inhalt als
Laufwerk &lt;code&gt;D:&lt;/code&gt; wie eine zusätzliche Festplatte eingebunden.&lt;/p&gt;

&lt;p&gt;Plug &amp;amp; Play gibt es nicht. Das System muss heruntergefahren werden,
um den Stick zu wechseln und der neue Stick vor dem nächsten Start
entsprechend eingesteckt sein.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ah, es fühlt sich an wie damals … also echt langsam.
Aber meine alten DOS-Spiele laufen auf dem 40 MHz System doch noch um einiges
besser und schneller als am Book8088.&lt;/p&gt;

&lt;p&gt;Und der Support für 32-bit Code macht es nun auch möglich eine gesamte 
&lt;a href=&quot;https://de.wikipedia.org/wiki/FreeDOS&quot;&gt;FreeDOS&lt;/a&gt;
Installation auf dem Pocket386 zu installieren. 
(Einige FreeDOS Tools sind nur für 32-bit kompiliert.)&lt;/p&gt;

&lt;p&gt;In Summe ergänzen sich die beiden Brüder perfekt für Retro-Computing Aufgaben.
Und besonders die Unterstützung von externen Eingabegeräten und einem Monitor
holen diese Museums-Repliken ins aktuelle Jahrhundert zurück.&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>Arch Linux Keys</title>
   <link href="https://www.opengate.at/blog/2024/05/arch-keys/"/>
   <published>2024-05-12T13:00:00+02:00</published>
   <updated>2024-05-12T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2024/05/arch-keys</id>
   <category term="software" />
   <summary type="text">Da installiere ich mir Arch Linux
 als WSL Distro und 
 möchte ein Update mit pacman -Syu durchführen.

Schon erscheinen zahlreiche Fehler nach dem Schema:


  error: curl: signature from “Someone someone@archlinux.org” is unknown trust
:: File /var/cache/pacman/pkg/something-x86_64.pkg.tar.zst is corrupted (invalid or corrupted package (PGP signature)).


</summary>
   <content type="html">&lt;p&gt;Da installiere ich mir &lt;a href=&quot;https://de.wikipedia.org/wiki/Arch_Linux&quot;&gt;Arch Linux&lt;/a&gt;
 als &lt;a href=&quot;https://de.wikipedia.org/wiki/Windows-Subsystem_für_Linux&quot;&gt;WSL&lt;/a&gt; Distro und 
 möchte ein Update mit &lt;code&gt;pacman -Syu&lt;/code&gt; durchführen.&lt;/p&gt;

&lt;p&gt;Schon erscheinen zahlreiche Fehler nach dem Schema:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;error: curl: signature from “Someone &lt;a href=&quot;mailto:someone@archlinux.org&quot;&gt;someone@archlinux.org&lt;/a&gt;” is unknown trust&lt;br /&gt;
:: File /var/cache/pacman/pkg/something-x86_64.pkg.tar.zst is corrupted (invalid or corrupted package (PGP signature)).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;lösung-pacman-key&quot;&gt;Lösung: pacman-key&lt;/h3&gt;

&lt;p&gt;Nach etwas Herumsuchen findet man die Lösung:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;pacman-key --init
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;pacman-key --populate
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;pacman-key --refresh-keys
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Hier läuft dann &lt;code&gt;--refresh-keys&lt;/code&gt; recht lange und holt sich, was es kriegen
kann (obwohl auch hier noch manchmal &lt;code&gt;Error&lt;/code&gt; im Output steht).&lt;/p&gt;

&lt;p&gt;Doch danach lässt sich &lt;code&gt;pacman -Syu&lt;/code&gt; und auch jedes andere 
&lt;code&gt;pacman -S PACKNAME&lt;/code&gt; problemlos ausführen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ich hatte ArchLinux schon vor einigen Monaten mal auf WSL bringen wollen
und brach demotiviert wegen der fehlerhaften Key-Sache ab.&lt;br /&gt;
Reguläre Installationen von offiziellen Medien funktionierten, aber das
WSL Image dürfte wohl veraltet sein.&lt;/p&gt;

&lt;p&gt;Eigentlich gefällt mir so etwas gar nicht, wenn ein OS so geliefert wird,
dass es ohne Fachwissen unbenutzbar ist. Doch zum Glück hat die Community
das Problem gelöst … jetzt muss sich das Wissen nur noch überall hin
verbreiten.&lt;/p&gt;

&lt;p&gt;In diesem Sinne:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Verbreitet die Zeilen:&lt;br /&gt;
&lt;code&gt;pacman-key --init&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;pacman-key --populate&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;pacman-key --refresh-keys&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</content>
 </entry>
 
 <entry>
   <title>ZIG und C&apos;s undefined-behavior</title>
   <link href="https://www.opengate.at/blog/2024/05/zig-c-ub/"/>
   <published>2024-05-05T13:00:00+02:00</published>
   <updated>2024-05-05T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2024/05/zig-c-ub</id>
   <category term="devel" />
   <summary type="text">Ich baue meine Win32 App mit MSVC: läuft.
Ich baue meine Win32 App mit MinGW: läuft.
Ich baue meine Win32 App mit CLANG: läuft.
Ich baue meine Win32 App mit ZIG: Prozess weg.


  W-T-F? Was macht ZIG, das auf LLVM aufsetzt, anders?


Spoiler: ZIG ist einfach nur genial!

</summary>
   <content type="html">&lt;p&gt;Ich baue meine Win32 App mit &lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_C%2B%2B&quot;&gt;MSVC&lt;/a&gt;: läuft.&lt;br /&gt;
Ich baue meine Win32 App mit &lt;a href=&quot;https://de.wikipedia.org/wiki/MinGW&quot;&gt;MinGW&lt;/a&gt;: läuft.&lt;br /&gt;
Ich baue meine Win32 App mit &lt;a href=&quot;https://de.wikipedia.org/wiki/Clang&quot;&gt;CLANG&lt;/a&gt;: läuft.&lt;br /&gt;
Ich baue meine Win32 App mit &lt;a href=&quot;https://de.wikipedia.org/wiki/Zig_(Programmiersprache)&quot;&gt;ZIG&lt;/a&gt;: Prozess weg.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;W-T-F? Was macht ZIG, das auf LLVM aufsetzt, anders?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Spoiler: &lt;em&gt;ZIG ist einfach nur genial!&lt;/em&gt;&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Finde den Fehler:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt; foo(&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt;* ptr_chars, size_t slice_offset) {
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;  assert(
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;    ((ptr_chars == &lt;span style=&quot;color:#069&quot;&gt;NULL&lt;/span&gt;) &amp;amp;&amp;amp; (slice_offset == &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;))
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;    || (ptr_chars != &lt;span style=&quot;color:#069&quot;&gt;NULL&lt;/span&gt;)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  );
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt;* &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt; ptr_char = ptr_chars + slice_offset;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt;(ptr_char != &lt;span style=&quot;color:#069&quot;&gt;NULL&lt;/span&gt;) {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;    do_something_with(*ptr_char);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;  }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;else&lt;/span&gt; {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;    printf(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Nothing to do&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;  }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Unser &lt;code&gt;assert()&lt;/code&gt; geht immer OK durch, weil entweder beide Funktionsparameter
gesetzt sind, oder beide auf &lt;code&gt;NULL&lt;/code&gt; bzw &lt;code&gt;0&lt;/code&gt; verweisen.&lt;/p&gt;

&lt;p&gt;Leider führt &lt;code&gt;zig cc&lt;/code&gt; in der Folgezeile manchmal ein &lt;code&gt;abort()&lt;/code&gt; aus.&lt;/p&gt;

&lt;p&gt;Und der Grund lautet auf:&lt;/p&gt;

&lt;h3 id=&quot;undefiniertes-verhalten&quot;&gt;Undefiniertes Verhalten&lt;/h3&gt;

&lt;p&gt;Setzt man die Zeile&lt;br /&gt;
&lt;code&gt;char* ptr_char = ptr_chars + slice_offset;&lt;/code&gt;
stur in Maschinensprache um, ist auch alles perfekt in Ordnung,
denn entweder entsteht ein nicht-NULL-Pointer zu Daten oder ein 
NULL-Pointer (weil dann ja beide Parameter &lt;code&gt;0&lt;/code&gt; sind).&lt;/p&gt;

&lt;p&gt;Der nachfolgende Code prüft auf den NULL-Pointer und sortiert ihn beim
Auftreten aus.&lt;/p&gt;

&lt;p&gt;Doch leider darf man mit NULL Pointer nur zwei Dinge machen:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Man darf sie zuweisen&lt;br /&gt;
&lt;code&gt;my_ptr = NULL;&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Man darf sie mit anderen Pointern vergleichen&lt;br /&gt;
&lt;code&gt;if(my_ptr == NULL)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Der Fehler liegt bereits in der Addition, denn wenn &lt;code&gt;ptr_chars&lt;/code&gt; schon NULL
ist, darf man keinen Wert addieren, subtrahieren oder anders verknüpfen.&lt;/p&gt;

&lt;p&gt;Rein logisch ist &lt;code&gt;NULL + 0&lt;/code&gt; wieder &lt;code&gt;NULL&lt;/code&gt;, und zur Laufzeit stimmt das auch.&lt;/p&gt;

&lt;p&gt;Doch wenn der Compiler schon beim Übersetzen nachvollziehen kann, dass beide 
Parameter auf &lt;code&gt;NULL&lt;/code&gt; bzw. &lt;code&gt;0&lt;/code&gt; gesetzt werden, dann weiß er, dass es sich
bereits um undefiniertes Verhalten handelt und dann darf er auch jeden
beliebigen Blödsinn machen.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;zig cc&lt;/code&gt; bricht dann den Prozess ab, während meine anderen Compiler einen
durchlaufenden Prozess ermöglichen.&lt;/p&gt;

&lt;h3 id=&quot;lösung&quot;&gt;Lösung&lt;/h3&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt; foo(&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt;* ptr_chars, size_t slice_offset) {
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;  assert(
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;    ((ptr_chars == &lt;span style=&quot;color:#069&quot;&gt;NULL&lt;/span&gt;) &amp;amp;&amp;amp; (slice_offset == &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;))
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;    || (ptr_chars != &lt;span style=&quot;color:#069&quot;&gt;NULL&lt;/span&gt;)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  );
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt;(ptr_chars == &lt;span style=&quot;color:#069&quot;&gt;NULL&lt;/span&gt;) {
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;    printf(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Nothing to do&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;else&lt;/span&gt; {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt;* &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt; ptr_char = ptr_chars + slice_offset;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;    do_something_with(*ptr_char);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;  }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Wenn wir einen NULL-Pointer haben, darf er nicht angefasst werden,
nur Vergleiche sind zulässig.&lt;/p&gt;

&lt;p&gt;Solche Pointer-Additionen kamen bei mir leider vor, und zwar auch bei
“wissentlich” leeren Objekten und diese waren schlicht falsch.&lt;br /&gt;
(Liebe Grüße vom Leer-String-Objekt!)&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;code&gt;zig&lt;/code&gt;, ich liebe dich!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Alle Tools und Tests laufen jetzt auch durch, wenn sie von
&lt;code&gt;zig cc&lt;/code&gt; gebaut wurden.&lt;/p&gt;

&lt;p&gt;Natürlich kann man darüber diskutieren, dass manche Compiler den Begriff
des UB (Undefined Behavior) überinterpretieren.&lt;br /&gt;
Täten sie genau das, was ich ihnen vorschreibe, wäre alles in Ordnung.&lt;/p&gt;

&lt;p&gt;Doch so ist es nicht. UB Regeln sind absolut relevant und ich bin 
echt froh, dass mich &lt;code&gt;zig&lt;/code&gt; nun auf ein altes “Denkproblem” aufmerksam
gemacht hat.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;code&gt;zig&lt;/code&gt; hat damit maßgeblich die Korrektheit und Speichersicherheit 
im GATE Framework verbessert.&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>Bildausschnitte per Line-Padding</title>
   <link href="https://www.opengate.at/blog/2024/04/image-line-padding/"/>
   <published>2024-04-28T13:00:00+02:00</published>
   <updated>2024-04-28T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2024/04/image-line-padding</id>
   <category term="devel" /><category term="hardware" />
   <summary type="text">Die Arbeit mit meinem Book8088 
inspirierte mich mein Grafik-Konzept zu überdenken:
Ein Rasterimage ist nicht ein Array of Pixels, 
es ist ein Array of Pixel-Lines.

Und daraus folgt: Ein Bildausschnitt ist
Originalbild + Offset + Padding

</summary>
   <content type="html">&lt;p&gt;Die Arbeit mit meinem &lt;a href=&quot;/blog/2024/04/book8088/&quot;&gt;Book8088&lt;/a&gt; 
inspirierte mich mein Grafik-Konzept zu überdenken:&lt;br /&gt;
Ein Rasterimage ist nicht ein &lt;code&gt;Array of Pixels&lt;/code&gt;, &lt;br /&gt;
es ist ein &lt;code&gt;Array of Pixel-Lines&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Und daraus folgt: Ein Bildausschnitt ist&lt;br /&gt;
&lt;code&gt;Originalbild&lt;/code&gt; + &lt;code&gt;Offset&lt;/code&gt; + &lt;code&gt;Padding&lt;/code&gt;&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Ich wollte im GATE Framework “ein” generisches Bildformat haben,
und das sollte RGBA (32-bit) sein.&lt;br /&gt;
Jedes beliebige Format kann man nach RGBA konvertieren und somit
wird die Bildmanipulation nur noch auf RGBA durchgeführt.&lt;/p&gt;

&lt;p&gt;Doch dann kam &lt;a href=&quot;https://de.wikipedia.org/wiki/MS-DOS&quot;&gt;DOS&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Über die unterschiedlichen komplizierten Speicherformate von 
EGA/VGA/SVGA usw. Bildern könnte man Bücher schreiben und es ist ein Segen,
dass wir uns in Windows, Linux, &lt;a href=&quot;https://de.wikipedia.org/wiki/X_Window_System&quot;&gt;X11&lt;/a&gt;
oder &lt;a href=&quot;https://de.wikipedia.org/wiki/OpenGL&quot;&gt;OpenGL&lt;/a&gt;
nicht mehr um solche Details kümmern müssen.&lt;/p&gt;

&lt;p&gt;Der &lt;code&gt;Mode 13&lt;/code&gt; war der einzige VGA-Modus, in welchem 256 Farben als lineare
Paletten-Pixel Werte im Speicher abgelegt werden konnten und so mit
einer Auflösung von 320 x 200 Pixel ein bisschen Grafik am DOS-PC ohne
Aufwand produziert werden konnte.&lt;/p&gt;

&lt;p&gt;Und genau aus diesem Grund sind 8-Bit Farbpaletten Grafik neben RGBA nun
ein weiteres “generisches” Format, dass ich unterstütze.&lt;br /&gt;
Denn so passt ein Bildschirm-Inhalt in ein einziges 64-KB Segment.&lt;/p&gt;

&lt;h3 id=&quot;performance-problem&quot;&gt;Performance Problem&lt;/h3&gt;

&lt;p&gt;Doch die Idee, ich könnte einen Framebuffer mit den vollen 320 x 200 Pixeln
bearbeiten und dann als ganzes ins Video-RAM (&lt;code&gt;0xa000:0&lt;/code&gt;) kopieren, scheitert
am 8 MHz Prozessor: Denn das dauert ewig … aus Sicht des Gamers.&lt;/p&gt;

&lt;p&gt;Dass das Kopieren von 64000 Bytes messbar lange dauert, kann sich heute kaum
jemand mehr vorstellen.&lt;br /&gt;
Doch die Lösung ist oft einfach: Man überträgt nur Änderungen.&lt;/p&gt;

&lt;p&gt;Bei Spielen ändert sich nicht immer gleich der ganze Bildschirm-Inhalt, es
werden meist nur einige wenige Figuren verschoben.&lt;br /&gt;
Doch wenn man jetzt ein großes Bild in einzelne separate Teilbilder zerlegt,
fragmentiert und vergrößert man den Speicherverbrauch.&lt;/p&gt;

&lt;h3 id=&quot;ein-besseres-pixel-layout&quot;&gt;Ein besseres Pixel-Layout&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;Was wäre, wenn man (wie bei Strings und String-Views) den Inhalt 
eines Speicherblocks mehreren Konsumenten gleichzeitig anbietet?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Man “verkauft” Ausschnitte eines großen Bildes als mehrere Teilbilder,
obwohl die nur das Originalbild “mit anderen Abmessungen” benutzen.&lt;/p&gt;

&lt;p&gt;Bisher bestand ein Bild bei mir aus einer Breiten- und Höhenangabe
und einem Pointer auf die Rohdaten.
Pixelpositionen ergaben sich nach der Formel:&lt;br /&gt;
&lt;code&gt;pixel_pointer = start_pointer + y * width + x&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Führt man aber noch einen &lt;code&gt;line-padding&lt;/code&gt; Wert ein und betrachtet ein
Bild nicht als fixen Block, sondern als ein Array von Zeilen, dann
bekommt man eine Bildzeile per:&lt;br /&gt;
&lt;code&gt;pixel_pointer = start_pointer + y * (width + padding) + x&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Man muss jetzt zwar bei jedem Zeilenwechsel (y) den Pointer neu berechnen,
doch nun können Unterbilder über Pointer und Padding auf das Originalbild
verweisen.&lt;/p&gt;

&lt;h3 id=&quot;neues-altes-interface&quot;&gt;Neues altes Interface&lt;/h3&gt;

&lt;p&gt;Mit diesem Update kann ich nun beliebige Raster-Rahmen-Objekte für die
gleichen Bilddaten erstellen und Reference-Counting sichert die korrekte
Nutzung und Freigabe der Ressourcen.&lt;/p&gt;

&lt;p&gt;Die einzige Änderung ist, dass man nun nicht mehr das Bild als einen fetten
Puffer bearbeiten kann, sondern immer nur Zeilenweise.&lt;/p&gt;

&lt;p&gt;Das ist tatsächlich auch wieder ein Overhead, aber dieser fällt hier 
wenig bis gar nicht auf.&lt;br /&gt;
Denn anstatt in separate Speicher zu zeichnen und diese dann 
zusammenkopieren zu müssen, wird alles in einen Block (aber an die richtige
Stelle) geschrieben.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Und wieder hat mir die “alte Welt” eine Lehre erteilt.&lt;br /&gt;
Man muss nicht Megabytes an Daten generieren und dann wieder wegwerfen, 
sondern man kann durch “Kooperation” mit einem Bruchteil der Ressourcen
zum gleichen Ergebnis kommen.&lt;/p&gt;

&lt;p&gt;Oder anders formuliert:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Wir brauchen weniger Speicher&lt;/li&gt;
  &lt;li&gt;Wir nutzen daher Caches besser&lt;/li&gt;
  &lt;li&gt;Wir reduzieren Kopien drastisch&lt;/li&gt;
  &lt;li&gt;Wir erhöhen den Durchsatz&lt;/li&gt;
  &lt;li&gt;Wir reduzieren den Strombedarf&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;… das bräuchten wir auch bei der Klima- und Umweltdebatte.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Ranish Partition Editor</title>
   <link href="https://www.opengate.at/blog/2024/04/ranish/"/>
   <published>2024-04-21T13:00:00+02:00</published>
   <updated>2024-04-21T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2024/04/ranish</id>
   <category term="software" />
   <summary type="text">Der Ranish
Partition-Manager gehörte vor dem Jahr 2000 zu meiner 
“Standardinstallation” unter DOS.
Dieses Miniprogramm lässt eine jede MBR
Festplatten-Partition und jedes FAT Dateisystem inspizieren und manipulieren.

Dennoch hatte ich immer Angst vor diesem mächtigen Werkzeug.

</summary>
   <content type="html">&lt;p&gt;Der &lt;a href=&quot;https://en.wikipedia.org/wiki/Ranish_Partition_Manager&quot;&gt;Ranish&lt;/a&gt;
Partition-Manager gehörte vor dem Jahr 2000 zu meiner 
“Standardinstallation” unter &lt;a href=&quot;https://de.wikipedia.org/wiki/MS-DOS&quot;&gt;DOS&lt;/a&gt;.&lt;br /&gt;
Dieses Miniprogramm lässt eine jede &lt;a href=&quot;https://de.wikipedia.org/wiki/Master_Boot_Record&quot;&gt;MBR&lt;/a&gt;
Festplatten-Partition und jedes FAT Dateisystem inspizieren und manipulieren.&lt;/p&gt;

&lt;p&gt;Dennoch hatte ich immer Angst vor diesem mächtigen Werkzeug.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Mit &lt;code&gt;fdisk&lt;/code&gt; hatte MS-DOS zwar seinen eigenen Partition-Manager, aber der
taugte nur zum Einrichten einer primären und einigen sekundären 
(erweiterten) Partitionen.&lt;/p&gt;

&lt;p&gt;Ich wollte aber mehrere Betriebssysteme (DOS, Win95, 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_NT_4.0&quot;&gt;NT4&lt;/a&gt;) auf einem PC
haben und musste daher recht “perverse” Installations-Methoden durchführen.
Denn &lt;code&gt;fdisk&lt;/code&gt; konnte nur mit einer primären Partition umgehen, von der man
letztendlich booten konnte.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Zuerst Windows NT installieren (erste primäre Partition) auf 
&lt;a href=&quot;https://de.wikipedia.org/wiki/NTFS&quot;&gt;NTFS&lt;/a&gt; Basis&lt;/li&gt;
  &lt;li&gt;Mit NT 2 weitere primäre Partitionen anlegen. (Unter NT ging das zum Glück.)&lt;/li&gt;
  &lt;li&gt;Aktive Boot-Partition auf Nr. 2 setzen.&lt;/li&gt;
  &lt;li&gt;Dann per Diskette DOS auf die neue Boot-Partition installieren.&lt;/li&gt;
  &lt;li&gt;Per &lt;code&gt;fdisk&lt;/code&gt; die 3. Partition auf “Aktiv” setzen.&lt;/li&gt;
  &lt;li&gt;Nun per Win95-Bootdiskette starten und Windows 95 Installation einleiten.&lt;/li&gt;
  &lt;li&gt;Am Ende vom DOS-Modus aus &lt;code&gt;vamos&lt;/code&gt; installieren, um beim Boot die
aktive Partition per Menü auswählen zu können.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Und weil DOS ja nur innerhalb der ersten 2 GB booten kann, durfte die
NT-Partition nicht zu groß sein.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Es war eine Katastrophe.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;die-suche-nach-partitionverwaltungstools&quot;&gt;Die Suche nach Partitionverwaltungstools&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;ranish&lt;/code&gt; war damals schon auf diversen CDs von Computer Magazinen und fand
so schnell einen Platz bei mir.&lt;/p&gt;

&lt;p&gt;Doch weil &lt;code&gt;ranish&lt;/code&gt; sooo “Low-Level” gestaltet war, war die Zerstörung einer
Installation bei mir quasi vorprogrammiert.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/dos-ranish.png&quot; alt=&quot;DOS Ranish&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Man kann alle Einträge des Master-Boot-Records frei editieren und damit auch
jede Menge Blödsinn einstellen.
Das fängt bei falschen Werten für C-H-S (Cylinder-Head-Sector) Werten für den
Anfang und das Ende von Partition an und hört bei falschen Partitionstypen auf.&lt;/p&gt;

&lt;p&gt;Das merkte man natürlich erst beim nächsten Reboot, wo die Festplatte nicht
mehr startbar oder lesbar war und nur noch durch eine “professionelle Nutzung” 
von &lt;code&gt;ranish&lt;/code&gt; von der Bootdiskette mit Glück wiederhergestellt werden konnte.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Merksatz: Immer zuerst eine Diskette oder bootfähige CD mit Reparatur-Tools
anlegen, bevor man am System herumspielt.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Kurz danach erhielt ich mit &lt;code&gt;PQMagic&lt;/code&gt; (PowerQuest Partition Magic) ein 
grafisches Werkzeug, mit dem Fehlkonfigurationen ziemlich gut ausgeschlossen
werden konnten und nutzte dieses primär.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ranish&lt;/code&gt; blieb aber immer als Fail-Safe-Tool bei mir, weil es so herrlich klein
war und direkten Einblick in den MBR boot.&lt;/p&gt;

&lt;h3 id=&quot;ranish-für-das-book8088&quot;&gt;Ranish für das Book8088&lt;/h3&gt;

&lt;p&gt;Neue Freude mit &lt;code&gt;ranish&lt;/code&gt; habe ich heute … also 25 Jahre später.
Denn es stellte sich heraus, dass &lt;a href=&quot;https://de.wikipedia.org/wiki/CompactFlash&quot;&gt;CF-Karten&lt;/a&gt;
für mein &lt;code&gt;book-8088&lt;/code&gt; nicht erkannt werden, 
wenn sie mit Windows formatiert werden.&lt;/p&gt;

&lt;p&gt;Die MBR Einträge von heutigen Tools werden auf größere Lese-/Schreibkopf
Werte gesetzt, als das uralte BIOS verkraften kann. Hier dürfen nicht mehr
als 16 Köpfe und 1024 Sektoren benutzt werden.&lt;/p&gt;

&lt;p&gt;Es scheint auch so zu sein, dass sich der CF-Controller bzw. die Software 
an den MBR-Einträgen orientiert, wenn aus dem linearen Flash-Speicher 
eine C-H-S-Adressierung emuliert wird.&lt;/p&gt;

&lt;p&gt;Hier konnte ich also mit Ranish eine Partition auf einem 2 GB Modul künstlich
anlegen, die von C-H-S &lt;code&gt;(0, 1, 1)&lt;/code&gt; bis C-H-S &lt;code&gt;(952, 15, 63)&lt;/code&gt; reichte und 
somit etwa 470 MB groß war und vom alten BIOS erkannt werden konnte.&lt;/p&gt;

&lt;p&gt;Ohne diesen Trick hätte ich nur noch 256 MB Karten benutzen können, denn 
selbst CF Karten mit 512 MB sind bereits um ein paar Bytes zu groß und würden
mit einer Kopf-Anzahl jenseits von 16 behandelt werden.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;ranish&lt;/code&gt; ist sogar heute noch als Open-Source Software verfügbar, und wurde
vor nicht all zu langer Zeit auch auf 
&lt;a href=&quot;https://codeberg.org/boeckmann/ranish&quot;&gt;Codeberg&lt;/a&gt; abgelegt.&lt;/p&gt;

&lt;p&gt;Dass mir dieses puritanische Experten-Tool auch heute noch gute Dienste 
leistet ist faszinierend. Denn wo findet man heute noch Tools kleiner 100 KB,
die Zugriff auf “alles” bieten.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Dem/den Macher/n, den Distributoren und Magazin-Autoren von damals 
spreche ich jedenfalls meinen Dank für dieses Juwel aus.&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>Book 8088</title>
   <link href="https://www.opengate.at/blog/2024/04/book8088/"/>
   <published>2024-04-14T13:00:00+02:00</published>
   <updated>2024-04-14T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2024/04/book8088</id>
   <category term="hardware" /><category term="retro" />
   <summary type="text">
  4 bzw. 8 MHz und 640 KB RAM!
China hat es geschafft in den 2020ern einen Laptop aus Bauteilen 
und Standards der 1980er auf den Markt zu bringen.


Ich bin wieder in den 80ern … also eigentlich noch vor “meiner Zeit”,
und damit genau “in meiner Zeit”, denn den ersten PC, den ich in den
90ern in der Schule zu Gesicht bekam war ein 
IBM PC XT.

</summary>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;4 bzw. 8 MHz und 640 KB RAM!&lt;br /&gt;
China hat es geschafft in den 2020ern einen Laptop aus Bauteilen 
und Standards der 1980er auf den Markt zu bringen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ich bin wieder in den 80ern … also eigentlich noch vor “meiner Zeit”,
und damit genau “in meiner Zeit”, denn den ersten PC, den ich in den
90ern in der Schule zu Gesicht bekam war ein 
&lt;a href=&quot;https://de.wikipedia.org/wiki/IBM_Personal_Computer_XT&quot;&gt;IBM PC XT&lt;/a&gt;.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Das &lt;code&gt;Book8088&lt;/code&gt; ist seit einigen Monaten auf AliExpress zu finden und schwankt
dort ja nach Anbieter, Versandkosten und Zubehör zwischen 180 und 280 Euro.&lt;/p&gt;

&lt;p&gt;Ich bin froh die günstigst Variante erstanden zu haben, denn der Zoll ballert
dann ohnehin nochmal 80 Euro drauf. Aber dann hatte ich endlich auch wieder
einen neuen alten PC mit &lt;a href=&quot;https://de.wikipedia.org/wiki/Intel_8088&quot;&gt;8088&lt;/a&gt;
kompatiblen Prozessor vor mir.&lt;/p&gt;

&lt;h3 id=&quot;hardware&quot;&gt;Hardware&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/book8088_parts.jpg&quot; alt=&quot;Book8088, ISA-Board&quot; /&gt;&lt;/p&gt;

&lt;p&gt;In einem &lt;code&gt;24,5 cm x 15 cm&lt;/code&gt; und &lt;code&gt;3 cm&lt;/code&gt; hohen zusammengeklappten Plastikgehäuse
sind ein 7-Zoll Display, eine Tastatur und ein Mainboard mit einem 
&lt;a href=&quot;https://de.wikipedia.org/wiki/NEC_V20&quot;&gt;NEC V20&lt;/a&gt; Prozessor verbaut, der 
Pin- und Instruktionen-kompatibel zum Intel 8088 ist und sogar etwas höher
getaktet werden kann.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/book8088_closed.jpg&quot; alt=&quot;Book8088 closed&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Unter der Tastatur lässt sich der Prozessor und auch eine 
&lt;a href=&quot;https://en.wikipedia.org/wiki/Yamaha_OPL#OPL3&quot;&gt;OPL3&lt;/a&gt;-Soundkarte
über 2 Plastikklappen freilegen, und auch noch optional ein 8087 
Koprozessor einstecken, falls wer noch einen zu Hause hat.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/book8088_cpu.jpg&quot; alt=&quot;Book8088: CPU, Soundcard&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Auf der Unterseite finden werden ebenfalls zwei Klappen um den Akku und die
Grafikkarte austauschen zu können.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Da hat jemand “modular” mitgedacht. Respekt!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Mit &lt;code&gt;4000 mAh&lt;/code&gt; kann man die Maschine schon eine Zeit lang ohne Stromkabel
laufen lassen. Wie lange weiß ich nicht, aber die eine oder andere Stunde
konnte ich damit schon kabellos “arbeiten”.&lt;br /&gt;
Aufgeladen wird der Laptop über ein 12V Ladegerät mit 1.5 Ampere.&lt;/p&gt;

&lt;p&gt;Hinweis: Die Plastikklappen sollte man aber nur wenn nötig öffnen, denn das 
Material sieht nicht so aus, als könnte es zahlreiche Öffnungsvorgänge lange 
überleben.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/book8088_battery.jpg&quot; alt=&quot;Book8088: Battery, Videocard&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Die Rückseite legt einen seriellen COM-Port und einen Parallel-Port frei, 
womit Kommunikation durchgeführt und auch eine klassische Maus angeschlossen
werden kann.&lt;/p&gt;

&lt;p&gt;Rechts finden wir einen Pin-Steckplatz um auch noch eine 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Industry_Standard_Architecture&quot;&gt;ISA&lt;/a&gt; 8-bit
Erweiterungsplatine anzukoppeln, über die man dann echte ISA-Karten an das
Gerät anschließen kann.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Genial!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/book8088_back.jpg&quot; alt=&quot;Book8088: COM, LPT, ISA&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Auf der linken Seite lässt sich eine 
&lt;a href=&quot;https://de.wikipedia.org/wiki/CompactFlash&quot;&gt;CompactFlash&lt;/a&gt; Karte als 
Festplatte einschieben, und über einen USB-Port erhält man sogar die 
Möglichkeit einen USB-Stick in Betrieb zu nehmen. Der USB-Port wird aber
nicht vom &lt;a href=&quot;https://de.wikipedia.org/wiki/BIOS&quot;&gt;BIOS&lt;/a&gt; erkannt, sondern braucht
einen eigenen DOS-Treiber, der ihn als zusätzliche Festplatte fest einbindet.&lt;br /&gt;
Eine USB-Maus oder -Tastatur lassen sich damit nicht betreiben.&lt;/p&gt;

&lt;p&gt;Außerdem zeigen ein paar LEDs den Ladezustand oder CF-Karten Zugriffe an.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/book8088_left.jpg&quot; alt=&quot;Book8088: CF-Card, USB, LEDs&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;software&quot;&gt;Software&lt;/h3&gt;

&lt;p&gt;Die beigelegt 256 MB große CF-Karte wird vom BIOS erkannt und ist mit
&lt;a href=&quot;https://de.wikipedia.org/wiki/MS-DOS&quot;&gt;MS-DOS&lt;/a&gt; 6.22 und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_3.0&quot;&gt;Windows 3.0&lt;/a&gt; und 
einigen alten DOS-Spielen befüllt.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/book8088_boot_dos.jpg&quot; alt=&quot;Book8088&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Ein Laufwerk &lt;code&gt;A:&lt;/code&gt; gibt es leider nicht, doch durch den DOS-USB-Stick-Treiber
lassen sich Programme auch so auf die CF-Karte im Betrieb übertragen.&lt;br /&gt;
Da es kein Plug&amp;amp;Play gibt, muss bei jedem Stick-Wechsel neu gestartet werden.&lt;/p&gt;

&lt;p&gt;Windows 3.0 im Schwarz-Weiß Modus ist die letzte Variante, die auf einer
alten 8088 CPU mit 640 KB RAM lauffähig ist.&lt;br /&gt;
Der Start ist allerdings kein Vergnügen und lässt mich an die Zeit 
zurückdenken, wo es üblich war, dass man nach einem &lt;code&gt;ENTER&lt;/code&gt; die Hand
von der Tastatur nehmen konnte … denn es dauerte eine Weile, bis 
Programme vollständig geladen waren.&lt;/p&gt;

&lt;h4 id=&quot;turbo-modus&quot;&gt;Turbo Modus&lt;/h4&gt;

&lt;p&gt;Mit der Tastenkombination &lt;code&gt;Fn&lt;/code&gt; + &lt;code&gt;F6&lt;/code&gt; lässt sich der CPU-Turbo aktivieren,
womit die CPU auf 8 MHz hochtaktet und damit fast doppelt so schnell läuft,
wie die ursprünglich üblichen 4.7 MHz.&lt;/p&gt;

&lt;p&gt;Bei Spielen wie &lt;a href=&quot;https://de.wikipedia.org/wiki/Prince_of_Persia&quot;&gt;Prince of Persia&lt;/a&gt;
merkt man den Turbo sofort. Während ohne Beschleunigung der Spieler nur träge 
vorankommt, erreicht man mit 8 MHz einen halbwegs flüssigen Verlauf.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ich liebe dieses Gerät.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ja, wir haben Emulatoren und können auf 24+ Zoll Monitoren mit 
&lt;a href=&quot;https://de.wikipedia.org/wiki/DOSBox&quot;&gt;DOSBoX&lt;/a&gt; “spielen”, aber nichts fühlt 
sich realistischer an, als ein echter Prozessor mit den Limits von damals.&lt;/p&gt;

&lt;p&gt;Software Hersteller waren seinerzeit wahre Künstler und schafften es ihren
Code in dieser eingeengten Umgebung lauffähig zu halten. Kein Byte wurde
verschwendet, kein Taktzyklus geopfert.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ein Lob auf die kreativen Köpfe, die sich dieses neue Laptop-Board-Design
überlegt haben und dort alte wie neue Chip-Reserven für uns Retro-Fans
verbaut haben.&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>Und dann kamen SystemD Services...</title>
   <link href="https://www.opengate.at/blog/2024/04/systemd/"/>
   <published>2024-04-07T13:00:00+02:00</published>
   <updated>2024-04-07T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2024/04/systemd</id>
   <category term="devel" />
   <summary type="text">
  systemd ist die Zukunft. 
Alle neuen Linux Dienste nutzen
diesen Standard um sich im System zu registrieren.


Auch falsch! (Langsam zeichnet sich ein Muster ab.)

Mir bleibt wirklich gar nichts erspart, und somit kommen jetzt
(beruflich wie privat) auch noch .service Dateien in meine Welt.

</summary>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Systemd&quot;&gt;systemd&lt;/a&gt; ist die Zukunft. 
Alle neuen &lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt; Dienste nutzen
diesen Standard um sich im System zu registrieren.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Auch falsch!&lt;/strong&gt; (Langsam zeichnet sich ein Muster ab.)&lt;/p&gt;

&lt;p&gt;Mir bleibt wirklich gar nichts erspart, und somit kommen jetzt
(beruflich wie privat) auch noch &lt;code&gt;.service&lt;/code&gt; Dateien in meine Welt.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Eigentlich ist &lt;code&gt;systemd&lt;/code&gt; der ausgereifteste Ansatz, wie man Dienste verwalten
kann. Denn hier werden nicht lose Scripts irgendwie ausgeführt, sondern ein 
verwalteter und definierter Hauptdienst startet und verwaltet alles Andere.&lt;/p&gt;

&lt;p&gt;Init-Scripts sind quasi selbstverantwortlich, wie sie ihre zugehörigen
Prozesse starten. Ob hier 1x oder 2x ge&lt;code&gt;fork()&lt;/code&gt;t wird, ob man den Account
wechselt, das ist alles ein Script-Geheimnis.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;systemd&lt;/code&gt; versucht uns alle Optionen als Konfiguration zur Verfügung zu
stellen, so dass wir einfach nur noch Variablen (bzw. Einstellungen) setzen
und kein selbstgeschriebener Code mehr notwendig ist.&lt;/p&gt;

&lt;p&gt;Man legt quasi eine &lt;a href=&quot;https://de.wikipedia.org/wiki/Initialisierungsdatei&quot;&gt;INI-Datei&lt;/a&gt;,
als “Service-Unit” im Verzeichnis &lt;code&gt;/etc/systemd/system/&lt;/code&gt; an, deren Inhalt
beschreibt, wie der Daemon gestartet werden soll.&lt;br /&gt;
Beispiel: &lt;code&gt;/etc/systemd/system/myserviced.service&lt;/code&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-ìni&quot;&gt;[Unit]
Description=MyService Daemon
Requires=other_daemon1,other_daemon2

[Service]
Type=exec
ExecStart=/usr/bin/myserviced

[Install]
WantedBy=multi-user.target
&lt;/code&gt;&lt;/pre&gt;

&lt;h4 id=&quot;der-exec-typ&quot;&gt;Der exec Typ&lt;/h4&gt;

&lt;p&gt;Es gibt mehrere “Typen” von Diensten, und &lt;code&gt;exec&lt;/code&gt; ist (neben dem ähnlich Typ &lt;code&gt;simple&lt;/code&gt;)
der einfachste, weil sich hier &lt;code&gt;systemd&lt;/code&gt; um die gesamte Laufzeit kümmert.&lt;br /&gt;
Es startet den Prozess im Hintergrund und überwacht ihn. Wird von außen die 
Beendigung eingefordert, schickt &lt;code&gt;systemd&lt;/code&gt; die notwendigen Standard-Signale an 
den Prozess.&lt;/p&gt;

&lt;h4 id=&quot;der-oneshot-typ&quot;&gt;Der oneshot Typ&lt;/h4&gt;

&lt;p&gt;Manchmal bedeutet “Dienst” auch nur “eine-Aktion-und-fertig”.
Genau dafür ist der &lt;code&gt;oneshot&lt;/code&gt;-Typ erschaffen worden. Das ausgeführte Programm
darf sich nämlich nach seiner “Aktion” beenden, aber &lt;code&gt;systemd&lt;/code&gt; behandelt den
Dienst weiter als “laufend”, obwohl gar kein Prozess mehr am Arbeiten ist.&lt;/p&gt;

&lt;p&gt;Das hilft einem vor allem bei Abhängigkeiten, wenn ein Dienst einen anderen
braucht. Wird nämlich ein Dienst beendet, beendet &lt;code&gt;systemd&lt;/code&gt; auch alle von
ihm abhängigen Dienste.&lt;br /&gt;
Mit &lt;code&gt;oneshot&lt;/code&gt; lässt sich so eine Kette von Aufgaben bilden, die 
hintereinander ausgeführt werden, die sich aber nach ihrem Ende nicht 
gegenseitig abbrechen.&lt;/p&gt;

&lt;h4 id=&quot;der-forking-typ&quot;&gt;Der forking Typ&lt;/h4&gt;

&lt;p&gt;Viele alte Init-Script Daemons haben sich selbst verwaltet, also sich selbst
ge&lt;code&gt;fork()&lt;/code&gt;t, und für solche Fälle ist dieser Typ gut geeignet.
Hier kann man dann eine PID-Datei und eine Beendigungsroutine konfigurieren,
um geforkte Dienste zu beenden:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-ìni&quot;&gt;[Unit]
Description=MyService Daemon
Requires=other_daemon1,other_daemon2

[Service]
Type=forking
ExecStart=/usr/bin/myserviced --start-me
ExecStop=/usr/bin/myserviced --kill-me
PIDFile=/var/run/myserviced.pid

[Install]
WantedBy=multi-user.target
&lt;/code&gt;&lt;/pre&gt;

&lt;h4 id=&quot;und-vieles-mehr&quot;&gt;Und vieles mehr&lt;/h4&gt;

&lt;p&gt;Dann gibt es da noch diverse andere Typen, die über &lt;code&gt;dbus&lt;/code&gt; mit ihrem Prozess 
kommunizieren, aber die sind für meine Zwecke zu komplex.&lt;/p&gt;

&lt;p&gt;Außerdem lassen sich in &lt;code&gt;systemd&lt;/code&gt; Service Dateien jede Menge Sonderfälle
spezifizieren wie:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Wiederhole den Start X mal, wenn sich der Prozess beendet/aufhängt.&lt;/li&gt;
  &lt;li&gt;Interpretiere/Ignoriere den Exit-Code eines Prozesses anders.&lt;/li&gt;
  &lt;li&gt;Führe ein anderes Programm/Script vor oder nach dem Daemon-Prozess aus.&lt;/li&gt;
  &lt;li&gt;Definiere Timeouts, wie lange Einzelschritte dauern dürfen.&lt;/li&gt;
  &lt;li&gt;Festlegung, ob oder welche Kindprozesse mitüberwacht und mitverwaltet 
werden sollen.&lt;/li&gt;
  &lt;li&gt;Wechsele den Account, das Verzeichnis oder das Environment&lt;/li&gt;
  &lt;li&gt;Definition von Abhängigkeiten, was vor oder nach wem gestartet wird, und 
was automatisch wieder beendet werden soll, wenn der eigene Dienst terminiert.&lt;/li&gt;
  &lt;li&gt;usw., siehe: &lt;a href=&quot;https://www.freedesktop.org/software/systemd/man/latest/systemd.service.html&quot;&gt;systemd.service&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;nutzung-von-systemctl&quot;&gt;Nutzung von systemctl&lt;/h3&gt;

&lt;p&gt;Das Zentrale Tool zur Verwaltung ist &lt;code&gt;systemctl&lt;/code&gt;.&lt;br /&gt;
Ist eine &lt;code&gt;.service&lt;/code&gt; Datei angelegt, werden mit &lt;code&gt;systemctl daemon-reload&lt;/code&gt; 
alle Service-Dateien eingelesen und integriert.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;systemctl enable myserviced.service&lt;/code&gt; aktiviert das Service für den 
automatischen Start.&lt;/p&gt;

&lt;p&gt;Mit &lt;code&gt;systemctl start|stop|status myserviced&lt;/code&gt; lässt sich wie mit klassischen
Init-Scripts ein Daemon starten, stoppen oder dessen aktueller Status ausgeben.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Tja, wie schon mal gesagt:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;code&gt;systemd&lt;/code&gt; ist super, aber…&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ich werde also künftig &lt;code&gt;.service&lt;/code&gt; Dateien mit Typ &lt;code&gt;forking&lt;/code&gt; anlegen, 
die aber auf meine alten Init-Scripts verweisen.&lt;/p&gt;

&lt;p&gt;Der Grund dafür: &lt;a href=&quot;https://de.wikipedia.org/wiki/Docker_(Software)&quot;&gt;Docker&lt;/a&gt;&lt;br /&gt;
Leider ist &lt;code&gt;systemd&lt;/code&gt; nicht ohne Workarounds in Docker-Containern nutzbar,
Init-Scripts funktionieren dort aber wie gehabt.&lt;/p&gt;

&lt;p&gt;Es macht für mich also Sinn, das “neue” System mit meiner “alten” Technik
zu verbinden.&lt;/p&gt;

&lt;p&gt;Aber gäbe es die Container-Einschränkung nicht, wäre &lt;code&gt;systemd&lt;/code&gt; vermutlich
genau das, was ich in Linux immer vermisst habe und was in Windows seit NT 4
Standard ist:&lt;br /&gt;
Nämlich eine ordentliche Instanz zur zentralen und einheitlichen
Verwaltung von System-Diensten.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>OpenBSD Daemons registrieren</title>
   <link href="https://www.opengate.at/blog/2024/03/openbsd-daemon/"/>
   <published>2024-03-31T13:00:00+02:00</published>
   <updated>2024-03-31T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2024/03/openbsd-daemon</id>
   <category term="devel" />
   <summary type="text">
  OK, FreeBSD und NetBSD verwalten ihre Daemons fast identisch.
Perfekt! Somit kann ich mit einem Daemon-Script-Skelett alle BSDs behandeln.


Wieder falsch!
Denn OpenBSD
setzt auf “leicht andere” Variablennamen.

Und wieder fließen weitere ifdef XXXBSD statements in meine Codebase.
</summary>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;OK, FreeBSD und NetBSD verwalten ihre Daemons fast identisch.&lt;br /&gt;
Perfekt! Somit kann ich mit einem Daemon-Script-Skelett alle BSDs behandeln.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Wieder falsch!&lt;/strong&gt;&lt;br /&gt;
Denn &lt;a href=&quot;https://de.wikipedia.org/wiki/OpenBSD&quot;&gt;OpenBSD&lt;/a&gt;
setzt auf “leicht andere” Variablennamen.&lt;/p&gt;

&lt;p&gt;Und wieder fließen weitere &lt;code&gt;ifdef XXXBSD&lt;/code&gt; statements in meine Codebase.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Ich hätte erwartet, dass OpenBSD die “antiksten” Scripts mit dem geringsten
Ausbau an gemeinsamen Funktionen bereitstellt.&lt;br /&gt;
Doch Fehlanzeige.&lt;/p&gt;

&lt;p&gt;OpenBSD setzt auf Funktionen anstatt von Variablen und wirkt damit
fast objektorientiert und modern.&lt;/p&gt;

&lt;p&gt;Ein Beispiel-Script sieht so aus:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;#!/bin/sh
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;daemon=&amp;quot;/usr/local/bin/myserviced&amp;quot;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;daemon_flags=&amp;quot;--optional_daemon_flag=value&amp;quot;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;. /etc/rc.d/rc.subr
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;rc_start() {
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;  ${rcexec} ${daemon} ${daemon_flags} &amp;amp;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;}
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;rc_check() {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;  get_myserviced_status()
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;}
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;rc_stop() {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;  kill_or_whatever_myserviced()
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;}
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;rc_cmd $1
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Hier schreibt man also &lt;code&gt;rc_*&lt;/code&gt; Funktionen um die notwendigen Schritte für’s
Starten, Stoppen und Status-Abfragen ausführen zu lassen.&lt;br /&gt;
Wenn aber &lt;code&gt;rc_check()&lt;/code&gt; und &lt;code&gt;rc_stop()&lt;/code&gt; weggelassen werden, so versucht 
&lt;code&gt;rc_cmd&lt;/code&gt; diese Funktionalität “handelsüblich” auszuführen.&lt;/p&gt;

&lt;p&gt;Das Tool &lt;code&gt;rcctl&lt;/code&gt; erhält in OpenBSD auch noch ein paar Zusatzfunktionen:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;rcctl start|stop|status daemon_name&lt;/code&gt; verhält sich “wie gewohnt”.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;rcctl enable daemon_name&lt;/code&gt; aktiviert den automatischen Start beim Boot.&lt;/li&gt;
  &lt;li&gt;und &lt;code&gt;rcctl disable daemon_name&lt;/code&gt; deaktiviert die Ausführung des Scripts.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;OpenBSD weicht somit vom Verhalten von Free/NetBSD ab, tut dies aber in
einer mir sehr sympathischen Art und Weise.&lt;/p&gt;

&lt;p&gt;Wenn ein minimales Init-Script nur noch so aussieht:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;#!/bin/sh
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;daemon=&amp;quot;/usr/local/bin/myserviced&amp;quot;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;daemon_flags=&amp;quot;--optional_daemon_flag=value&amp;quot;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;. /etc/rc.d/rc.subr
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;rc_start() {
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;  ${rcexec} ${daemon} ${daemon_flags} &amp;amp;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;}
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;rc_cmd $1
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;dann hat OpenBSD für mich eindeutig den Init-Script-Contest gewonnen.&lt;/p&gt;

&lt;p&gt;Wie auch immer … im GATE Framework sind meine Prozesse ja 
eigenverantwortlich, somit nutzen die 3 Funktionen meinen Daemon-Prozess
selbst um den Status zu ermitteln.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>BSD Daemons registrieren</title>
   <link href="https://www.opengate.at/blog/2024/03/bsd-daemon/"/>
   <published>2024-03-24T12:00:00+01:00</published>
   <updated>2024-03-24T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2024/03/bsd-daemon</id>
   <category term="devel" />
   <summary type="text">
  BSD und 
Linux sind beides Unix-Kinder, 
also sehen die intern recht ähnlich aus…


Falsch!
Ich bin immer wieder überrascht, wie unterschiedlich sich diese beiden
Brüder entwickelt haben.

Und mich zwingt das jetzt in die Situation, dass ich alle 
Daemon-Scripts doppelt schreiben muss.

</summary>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Berkeley_Software_Distribution&quot;&gt;BSD&lt;/a&gt; und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt; sind beides Unix-Kinder, 
also sehen die intern recht ähnlich aus…&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Falsch!&lt;/strong&gt;&lt;br /&gt;
Ich bin immer wieder überrascht, wie unterschiedlich sich diese beiden
Brüder entwickelt haben.&lt;/p&gt;

&lt;p&gt;Und mich zwingt das jetzt in die Situation, dass ich alle 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Daemon&quot;&gt;Daemon&lt;/a&gt;-Scripts doppelt schreiben muss.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Die BSD Blutlinie hat sich ja leider auch aufgespalten in 
&lt;a href=&quot;https://de.wikipedia.org/wiki/OpenBSD&quot;&gt;OpenBSD&lt;/a&gt;,
&lt;a href=&quot;https://de.wikipedia.org/wiki/NetBSD&quot;&gt;NetBSD&lt;/a&gt; und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/FreeBSD&quot;&gt;FreeBSD&lt;/a&gt;.&lt;br /&gt;
Fangen wir mal Net- und FreeBSD an, denn bei deren DNS sieht man noch 
direkter die Verbindung.&lt;/p&gt;

&lt;h3 id=&quot;init-scripts-in-freebsd-und-netbsd&quot;&gt;Init Scripts in FreeBSD und NetBSD&lt;/h3&gt;

&lt;p&gt;BSD Init Scripts liegen in &lt;code&gt;/etc/rc.d/&lt;/code&gt;und sehen im Wesentlichen so aus:
(Ein Code sagt mehr als 1000 Worte)&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;#!/bin/sh
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;# PROVIDE: myserviced
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;# REQUIRE: dependent_from_daemon
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;#include OS-script functions:
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;. /etc/rc.subr
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;#set required variables:
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;name=myserviced
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;command=&amp;quot;/usr/bin/myserviced&amp;quot;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;command_args=&amp;quot;--my_additional_arg=value&amp;quot;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;pidfile=&amp;quot;/var/run/myserviced.pid&amp;quot;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;start_cmd=&amp;quot;/usr/bin/myserviced whatever_start_arg $command_arg&amp;quot;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;stop_cmd=&amp;quot;whatever_daemon_stop_function&amp;quot;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;#execute OS-daemon start scripts
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;load_rc_config $name
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;run_rc_command &amp;quot;$1&amp;quot;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Das Geheimnis liegt also darin Variablen zu befüllen, die den System-internen
Scripts sagen, wie man den Dienst wirklich startet und dann führt man diese
Funktionen (&lt;code&gt;run_rc_command&lt;/code&gt;) einfach aus.&lt;/p&gt;

&lt;p&gt;Mit den &lt;code&gt;PROVIDE&lt;/code&gt; und &lt;code&gt;REQUIRE&lt;/code&gt; Meta-Kommentaren lässt sich auch eine einfache
Abhängigkeitskette bilden und durch die Variablen sehen BSD Scripts eigentlich
immer recht aufgeräumt aus.&lt;/p&gt;

&lt;p&gt;Eine separate Registrierung der Scripts ist nicht erforderlich, die bloße
Präsenz in &lt;code&gt;/etc/rc.d/&lt;/code&gt; reicht aus.&lt;/p&gt;

&lt;p&gt;Beim konkreten Starten und Stoppen gibt es schon Unterschiede:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;In FreeBSD nutzt man &lt;code&gt;rcctl start|stop|status daemon_name&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Während in NetBSD die Scripts direkt aufgerufen werden mit:&lt;br /&gt;
&lt;code&gt;/etc/rc.d/daemon_name start|stop|status&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Im GATE Projekt lasse ich ja meine eigenen Daemons selbst forken, womit der
Start nur ein Aufruf ist und ein Stoppen durch &lt;code&gt;kill&lt;/code&gt; umgesetzt werden kann.&lt;/p&gt;

&lt;p&gt;In Summe ist ein solches BSD Init Script auch trotz einiger Unterschiede
recht einheitlich aufgebaut.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Linux Daemons registrieren</title>
   <link href="https://www.opengate.at/blog/2024/03/linux-daemon/"/>
   <published>2024-03-17T12:00:00+01:00</published>
   <updated>2024-03-17T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2024/03/linux-daemon</id>
   <category term="devel" />
   <summary type="text">
  Wer richtet eigentlich Daemons (also Hintergrunddienste) in 
Linux ein?


Antwort: Die Distributionsmacher scripten sich das zusammen, wie sie es 
brauchen.

Aber was macht man als “3rd Party Developer?”

</summary>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;Wer richtet eigentlich Daemons (also Hintergrunddienste) in 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt; ein?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Antwort: Die Distributionsmacher scripten sich das zusammen, wie sie es 
brauchen.&lt;/p&gt;

&lt;p&gt;Aber was macht man als “3rd Party Developer?”&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Die &lt;a href=&quot;/blog/2022/02/daemonize/&quot;&gt;daemonize()&lt;/a&gt; Funktion ist nur
der halbe Weg, man muss auch sicherstellen, dass der 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Daemon&quot;&gt;Daemon&lt;/a&gt; beim Start des
Systems hochgefahren wird.&lt;/p&gt;

&lt;h3 id=&quot;init-scripts-und-die-lsb&quot;&gt;Init-Scripts und die LSB&lt;/h3&gt;

&lt;p&gt;Im klassischen Linux gibt es einen ungeschriebenen Standard für das Verwalten
von Daemon-Scripts.&lt;/p&gt;

&lt;p&gt;Ein Daemon mit Namen &lt;code&gt;myserviced&lt;/code&gt; …&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;… liegt als Binär-Datei in &lt;code&gt;/usr/bin/myserviced&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;… hat ein init-Script in &lt;code&gt;/etc/init.d/myserviced&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;… nutzt eine PID-Datei mit Namen &lt;code&gt;/var/run/myserviced.pid&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Aus der &lt;a href=&quot;https://de.wikipedia.org/wiki/Linux_Standard_Base&quot;&gt;Linux-Standard-Base&lt;/a&gt; 
hatte ich dann folgenden 
&lt;a href=&quot;https://refspecs.linuxfoundation.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/initscrcomconv.html&quot;&gt;Aufbau&lt;/a&gt;
abgeleitet:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;#!/bin/sh
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;### BEGIN INIT INFO
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;# Provides:          myserviced
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;# Required-Start:    $local_fs $network $named $remote_fs $syslog
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;# Required-Stop:     $local_fs $network $named $remote_fs $syslog
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;# Default-Start:     3 4 5
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;# Default-Stop:      0 1 2 6
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;# Short-Description: myserviced service process
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;# Description:       myserviced is known best for healing cancer
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;### END INIT INFO
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;PATH=/sbin:/usr/sbin:/bin:/usr/bin
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;NAME=myserviced
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;DAEMON=&amp;quot;/usr/bin/$NAME&amp;quot;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;DAEMON_ARGS=
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;PIDFILE=&amp;quot;/var/run/$NAME.pid&amp;quot;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;SCRIPTNAME=&amp;quot;/etc/init.d/$NAME&amp;quot;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;#import init functions
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;. /lib/lsb/init-functions
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n21&quot; name=&quot;n21&quot;&gt;21&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n22&quot; name=&quot;n22&quot;&gt;22&lt;/a&gt;&lt;/span&gt;do_start()
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n23&quot; name=&quot;n23&quot;&gt;23&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n24&quot; name=&quot;n24&quot;&gt;24&lt;/a&gt;&lt;/span&gt;  start_daemon -p $PIDFILE $DAEMON $DAEMON_ARGS
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n25&quot; name=&quot;n25&quot;&gt;25&lt;/a&gt;&lt;/span&gt;}
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n26&quot; name=&quot;n26&quot;&gt;26&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n27&quot; name=&quot;n27&quot;&gt;27&lt;/a&gt;&lt;/span&gt;do_stop()
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n28&quot; name=&quot;n28&quot;&gt;28&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n29&quot; name=&quot;n29&quot;&gt;29&lt;/a&gt;&lt;/span&gt;  killproc -p $PIDFILE $DAEMON
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n30&quot; name=&quot;n30&quot;&gt;30&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;}
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n31&quot; name=&quot;n31&quot;&gt;31&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n32&quot; name=&quot;n32&quot;&gt;32&lt;/a&gt;&lt;/span&gt;do_statuscheck()
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n33&quot; name=&quot;n33&quot;&gt;33&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n34&quot; name=&quot;n34&quot;&gt;34&lt;/a&gt;&lt;/span&gt;  pidofproc -p $PIDFILE $DAEMON
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n35&quot; name=&quot;n35&quot;&gt;35&lt;/a&gt;&lt;/span&gt;}
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n36&quot; name=&quot;n36&quot;&gt;36&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n37&quot; name=&quot;n37&quot;&gt;37&lt;/a&gt;&lt;/span&gt;case &amp;quot;$1&amp;quot; in
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n38&quot; name=&quot;n38&quot;&gt;38&lt;/a&gt;&lt;/span&gt;  start)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n39&quot; name=&quot;n39&quot;&gt;39&lt;/a&gt;&lt;/span&gt;    do_start
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n40&quot; name=&quot;n40&quot;&gt;40&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;    ;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n41&quot; name=&quot;n41&quot;&gt;41&lt;/a&gt;&lt;/span&gt;  stop)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n42&quot; name=&quot;n42&quot;&gt;42&lt;/a&gt;&lt;/span&gt;    do_stop
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n43&quot; name=&quot;n43&quot;&gt;43&lt;/a&gt;&lt;/span&gt;    ;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n44&quot; name=&quot;n44&quot;&gt;44&lt;/a&gt;&lt;/span&gt;  force-reload|reload|force-restart|restart)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n45&quot; name=&quot;n45&quot;&gt;45&lt;/a&gt;&lt;/span&gt;    do_stop
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n46&quot; name=&quot;n46&quot;&gt;46&lt;/a&gt;&lt;/span&gt;    do_start
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n47&quot; name=&quot;n47&quot;&gt;47&lt;/a&gt;&lt;/span&gt;    ;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n48&quot; name=&quot;n48&quot;&gt;48&lt;/a&gt;&lt;/span&gt;  status)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n49&quot; name=&quot;n49&quot;&gt;49&lt;/a&gt;&lt;/span&gt;    do_statuscheck
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n50&quot; name=&quot;n50&quot;&gt;50&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;    ;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n51&quot; name=&quot;n51&quot;&gt;51&lt;/a&gt;&lt;/span&gt;  *)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n52&quot; name=&quot;n52&quot;&gt;52&lt;/a&gt;&lt;/span&gt;    echo &amp;quot;Usage: $SCRIPTNAME {start|stop|restart|status}&amp;quot;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n53&quot; name=&quot;n53&quot;&gt;53&lt;/a&gt;&lt;/span&gt;    exit 1
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n54&quot; name=&quot;n54&quot;&gt;54&lt;/a&gt;&lt;/span&gt;    ;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n55&quot; name=&quot;n55&quot;&gt;55&lt;/a&gt;&lt;/span&gt;esac
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Das funktionierte auf manchen Distros, aber nie auf allen, und so musste ich
aus-if-en, ob &lt;code&gt;/lib/lsb/init-functions&lt;/code&gt; überhaupt vorhanden war und 
Workarounds für die Sonderfälle schreiben.&lt;/p&gt;

&lt;p&gt;Ein paar solcher Alternativen sind:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://man7.org/linux/man-pages/man8/start-stop-daemon.8.html&quot;&gt;start-stop-daemon&lt;/a&gt;&lt;br /&gt;
Das sieht man auf auf Debian&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.unix.com/man_page/suse/8/startproc/&quot;&gt;startproc&lt;/a&gt;&lt;br /&gt;
Dieser non-Standard kam mir in SuSE unter&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;$DAEMON $DAEMON_ARGS &amp;amp;&lt;/code&gt;&lt;br /&gt;
So startet man Daemons, wenn man nicht mehr weiter weiß.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;read PID &amp;lt; $PIDFILE&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;ps -p $PID &amp;gt; /dev/null 2&amp;gt;&amp;amp;1&lt;/code&gt;&lt;br /&gt;
… um zu wissen, ob der Daemon schon läuft&lt;/li&gt;
  &lt;li&gt;Noch schlimmer: auf etwas warten:
    &lt;div class=&quot;language-shell highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;COUNTER=0
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;while [ $COUNTER -lt 50 ]; do
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  if some_check_function;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  then
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;    sleep 0.1
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;    COUNTER=$((COUNTER+1))
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  else
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;    COUNTER=$((COUNTER+50))
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;  fi
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;done
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;Und noch einige andere Schweinereien&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;script-registrieren&quot;&gt;Script registrieren&lt;/h3&gt;

&lt;p&gt;Irgendwo liegt das Tool &lt;code&gt;update-rc.d&lt;/code&gt;, z.B. in&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;/sbin&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;/usr/sbin&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;/bin&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;/usr/bin&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;und hat man es gefunden, kann man es aufrufen mit&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;update-rc.d myserviced defaults
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;update-rc.d myserviced enable
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Erst jetzt ist das Init-Script im System registriert und wird automatisch
ausgeführt, wenn das System startet (bzw. den richtigen Run-Level erreicht).&lt;/p&gt;

&lt;h3 id=&quot;teilweise-übergang-zu-systemd&quot;&gt;Teilweise Übergang zu systemd&lt;/h3&gt;

&lt;p&gt;Dieser ganze Zauber wurde zwischen 2010 und 2020 durch 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Systemd&quot;&gt;SystemD&lt;/a&gt; ersetzt 
… aber das ist eine andere Geschichte.&lt;/p&gt;

&lt;p&gt;Doch weil es bis heute Umgebungen ohne &lt;code&gt;systemd&lt;/code&gt; gibt, wie z.B.
&lt;a href=&quot;https://de.wikipedia.org/wiki/Docker_(Software)&quot;&gt;Docker&lt;/a&gt; 
oder &lt;a href=&quot;https://de.wikipedia.org/wiki/Windows-Subsystem_f%C3%BCr_Linux&quot;&gt;WSL&lt;/a&gt; 1,
sind Init-Scripts für Daemons immer noch ein Thema und in Debian 
funktionieren die alten Tools bis heute.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Kurz gesagt:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Nichts ist so unsäglich zersplittert wie das Daemon- und 
Initialisierungs-System von Linux.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;(OK, Paket-Manager könnten das noch toppen.)&lt;/p&gt;

&lt;p&gt;Jede Distribution wollte ihre Individualität einfließen lassen und so wurden
über Jahrzehnte unzählige Arbeitsstunden für die Portierung verbraten.&lt;/p&gt;

&lt;p&gt;Am Ende geht es aber immer nur darum:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Starte einen Prozess im Hintergrund.&lt;/li&gt;
  &lt;li&gt;Setze den Exit-Code so, dass 0 Erfolg und alles andere Misserfolg ausdrückt.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Klingt komisch … ist aber so.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>JPEGs aus Minimum runterdrücken</title>
   <link href="https://www.opengate.at/blog/2024/03/jpeg-compress/"/>
   <published>2024-03-10T12:00:00+01:00</published>
   <updated>2024-03-10T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2024/03/jpeg-compress</id>
   <category term="software" /><category term="projects" />
   <summary type="text">Auf Codeberg Pages
kann man ja ganz toll Webseiten hosten, die einfach in einem Repository 
eingecheckt sind.
Für statischen HTML
Kram ist das super, aber was macht man mit Bildern?

Um jetzt nicht alles unnötig aufzublähen, setzte ich mir ein Ziel:


  Meine JPEGs müssen so klein wie möglich werden!


</summary>
   <content type="html">&lt;p&gt;Auf &lt;a href=&quot;https://docs.codeberg.org/codeberg-pages/&quot;&gt;Codeberg Pages&lt;/a&gt;
kann man ja ganz toll Webseiten hosten, die einfach in einem Repository 
eingecheckt sind.&lt;br /&gt;
Für statischen &lt;a href=&quot;https://de.wikipedia.org/wiki/Hypertext_Markup_Language&quot;&gt;HTML&lt;/a&gt;
Kram ist das super, aber was macht man mit Bildern?&lt;/p&gt;

&lt;p&gt;Um jetzt nicht alles unnötig aufzublähen, setzte ich mir ein Ziel:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Meine JPEGs müssen so klein wie möglich werden!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Als Entwickler wäre meine Antwort jetzt: 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Libjpeg&quot;&gt;libjpeg&lt;/a&gt;!
Hier kann man die Kompressionsstärke per &lt;code&gt;jpeg_set_quality()&lt;/code&gt; auf einen Wert
zwischen 0 und 100 Prozent setzen.&lt;/p&gt;

&lt;p&gt;Doch da die öffentliche API im GATE-Framework nur 4-bit Kompressions-Stufen
(also 16 Zustände) zulässt, müsste ich jetzt einen weiteren Finetuning Kanal
nach außen legen, und deshalb soll das ganze einfacher funktionieren.&lt;/p&gt;

&lt;h3 id=&quot;cjpeg-kann-auch-bilder-komprimieren&quot;&gt;cjpeg kann auch Bilder komprimieren&lt;/h3&gt;

&lt;p&gt;Das Tool &lt;code&gt;cjpeg&lt;/code&gt; hat bereits die erforderliche
Funktionalität und kann wie folgt installiert werden:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;apt install libjpeg-progs
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Es liest eine unkomprimierte Datei (zB. &lt;code&gt;.bmp&lt;/code&gt;), komprimiert
die Bilddaten im JPEG Format und gibt das Ergebnis auf der Konsole aus.&lt;/p&gt;

&lt;p&gt;Der Aufruf&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;cjpeg -quality 4 input.bmp &amp;gt; output.jpeg
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;lässt den Inhalt von &lt;code&gt;input.bmp&lt;/code&gt; mit der Qualität von &lt;code&gt;4&lt;/code&gt;% auf die Konsole 
schreiben, welche im Beispiel in die Datei &lt;code&gt;output.jpeg&lt;/code&gt; umgeleitet wird.&lt;/p&gt;

&lt;p&gt;Auf diese Weise kann man sich schnell ein Script schreiben, das alle &lt;code&gt;*.jpeg&lt;/code&gt;
Dateien durchläuft, per &lt;code&gt;djpeg&lt;/code&gt; als Bitmap speichert und diese dann mit der
neuen Kompression wieder in eine JPEG verwandelt.&lt;/p&gt;

&lt;h4 id=&quot;jpeg-zu-bmp-und-zu-neuer-jpeg-konvertieren&quot;&gt;JPEG zu BMP und zu neuer JPEG konvertieren&lt;/h4&gt;

&lt;div class=&quot;language-shell highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;djpeg -bmp input.jpeg &amp;gt; temp.bmp
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;cjpeg -quality 4 temp.bmp &amp;gt; output.jpeg
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h4 id=&quot;jpeg-direkt-konvertieren-per-pipes&quot;&gt;JPEG direkt konvertieren per Pipes&lt;/h4&gt;

&lt;div class=&quot;language-shell highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;djpeg input.jpeg | cjpeg -quality 4 &amp;gt; output.jpeg
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h3 id=&quot;warum-4-&quot;&gt;Warum 4% ?&lt;/h3&gt;

&lt;p&gt;Ich konnte nun etwas experimentieren und stellte fest, dass man ab 3% Qualität
auf meinen Fotos ein Minimum an Inhalt erkennen konnte. Bei kleineren Werten
wird es wirklich unkenntlich und größere Werte schlagen sich sofort in jeder
Menge zusätzlicher Bytes nieder.&lt;/p&gt;

&lt;p&gt;Mit 4 % konnte ich so die 45 MB an Bild-Dateien auf etwa MB runterdrücken, 
womit ich auch mein &lt;code&gt;git&lt;/code&gt; Repository mit besserem Gewissen belasten kann.&lt;/p&gt;

&lt;h4 id=&quot;vergleich-von-jpeg-bild-qualitäten&quot;&gt;Vergleich von JPEG Bild-Qualitäten&lt;/h4&gt;

&lt;h5 id=&quot;original-bild-75-167-kb&quot;&gt;Original Bild ~75% (167 KB)&lt;/h5&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/kurpark-oberlaa-04.jpg&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;

&lt;h5 id=&quot;qualität-10-26-kb&quot;&gt;Qualität 10% (26 KB)&lt;/h5&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/kurpark-oberlaa-04-q10.jpg&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;

&lt;h5 id=&quot;qualität-8-23-kb&quot;&gt;Qualität 8% (23 KB)&lt;/h5&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/kurpark-oberlaa-04-q8.jpg&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;

&lt;h5 id=&quot;qualität-6-19-kb&quot;&gt;Qualität 6% (19 KB)&lt;/h5&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/kurpark-oberlaa-04-q6.jpg&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;

&lt;h5 id=&quot;qualität-4-15-kb&quot;&gt;Qualität 4% (15 KB)&lt;/h5&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/kurpark-oberlaa-04-q4.jpg&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;

&lt;h5 id=&quot;qualität-2-11-kb&quot;&gt;Qualität 2% (11 KB)&lt;/h5&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/kurpark-oberlaa-04-q2.jpg&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Die JPEG Tools sind schon eine feine Beilage und ermöglichen
eine schnelle Konvertierung von Fotos.&lt;/p&gt;

&lt;p&gt;Ich erinnere mich noch gut an jene Zeiten, als Webspace-Hoster
ihre Upload-Größen auf wenige 100 KB reduzierten (um das Jahr 2000).
Damals saß ich lange vor Tools wie &lt;code&gt;WebGraphics-Optimizer&lt;/code&gt; um alle Bilder
“kleiner” zu speichern.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;cjpeg&lt;/code&gt; hätte mir da viel Klickarbeit abnehmen können.&lt;br /&gt;
Erst die Programmierung mit &lt;code&gt;libjpeg&lt;/code&gt; hat mich mit dessen erweiterten
Tools bekannt gemacht.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>SSH Public Key Logins</title>
   <link href="https://www.opengate.at/blog/2024/03/ssh-public-key/"/>
   <published>2024-03-03T12:00:00+01:00</published>
   <updated>2024-03-03T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2024/03/ssh-public-key</id>
   <category term="software" />
   <summary type="text">Passwörter sind für mich immer noch das beste … weil ich sie im Gehirn
speichern und überall hin mitnehmen kann.

Aber sicherer wären natürlich Zertifikate.
Auch beim Login auf SSH Servern.

Und wie ging das noch?
</summary>
   <content type="html">&lt;p&gt;Passwörter sind für mich immer noch das beste … weil ich sie im Gehirn
speichern und überall hin mitnehmen kann.&lt;/p&gt;

&lt;p&gt;Aber sicherer wären natürlich Zertifikate.&lt;br /&gt;
Auch beim Login auf &lt;a href=&quot;https://de.wikipedia.org/wiki/Secure_Shell&quot;&gt;SSH&lt;/a&gt; Servern.&lt;/p&gt;

&lt;p&gt;Und wie ging das noch?
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Die Idee dabei ist:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Ein User &lt;code&gt;myuser&lt;/code&gt; generiert sich ein Schlüssel-Paar (Public + Private Key).&lt;/li&gt;
  &lt;li&gt;Der Public-Key wird auf den SSH-Server kopiert und mit dem dortigen Login-User &lt;code&gt;ssh_user&lt;/code&gt; verknüpft.&lt;/li&gt;
  &lt;li&gt;Beim Login von &lt;code&gt;myuser&lt;/code&gt; auf dem Server mit dem &lt;code&gt;ssh_user&lt;/code&gt;, erkennt der Server,
dass &lt;code&gt;myuser&lt;/code&gt;’s Verschlüsselung zum verknüpften Schlüssel von &lt;code&gt;ssh_user&lt;/code&gt; pass.&lt;/li&gt;
  &lt;li&gt;Und schon läuft die SSH Session wie gewohnt.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;einrichtung-einer-public-key-authentifizierung&quot;&gt;Einrichtung einer Public-Key Authentifizierung&lt;/h3&gt;

&lt;p&gt;Das Tool &lt;code&gt;ssh-keygen&lt;/code&gt; erzeugt (falls nicht abgeändert) die beiden Dateien
&lt;code&gt;~/.ssh/id_rsa&lt;/code&gt; und &lt;code&gt;~/.ssh/id_rsa.pub&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Der öffentliche Schlüssel muss jetzt “irgendwie” auf den SSH Server kopiert werden,
entweder direkt, z.B.: per USB stick oder über eine andere SSH-Verbindung.
Dort muss sein Inhalt in die Datei &lt;code&gt;~/.ssh/authorized_keys&lt;/code&gt; eingefügt werden, die im 
Homeverzeichnis des Ziel-Login-Useraccounts liegt.&lt;/p&gt;

&lt;p&gt;Nachdem der Inhalt nur angefügt werden soll, reicht ein:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;mkdir -p ~/.ssh
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;touch ~/.ssh/authorized_keys
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;cat  /tmp/uploaded_data/id_rsa.pub &amp;gt;&amp;gt; ~/.ssh/authorized_keys
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Das war es auch schon.&lt;br /&gt;
Ab sofort kann man sich per SSH über das Kommando:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;ssh -i ~/.ssh/id_rsa ssh_user@ssh_server_host_or_ip
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;einloggen.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Hinweis: Das SSH Tool erfordert, dass der private Schlüssel von keinem
anderen User gelesen werden kann.&lt;br /&gt;
Ein &lt;code&gt;chmod -c 600 ~/.ssh/id_rsa&lt;/code&gt; kann also noch erforderlich sein.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4 id=&quot;putty&quot;&gt;PuTTY&lt;/h4&gt;

&lt;p&gt;Das Tool &lt;code&gt;putty&lt;/code&gt; verwendet ein eigenes Format und folglich muss der private
SSH Schlüssel in eine &lt;code&gt;.ppk&lt;/code&gt; Datei konvertiert werden.&lt;/p&gt;

&lt;p&gt;Das mitgelieferte Programm &lt;code&gt;PuTTY Key Generator&lt;/code&gt; erledigt das über seinen
&lt;code&gt;Load&lt;/code&gt; Button, wonach man nur noch auf &lt;code&gt;Save private key&lt;/code&gt; klicken muss,
und den Namen der neuen &lt;code&gt;.ppk&lt;/code&gt; angeben muss.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/putty-keygen.png&quot; alt=&quot;PuTTY Key Generator&quot; /&gt;&lt;/p&gt;

&lt;p&gt;In einer neuen &lt;code&gt;PuTTY&lt;/code&gt; Sitzung wird unter&lt;br /&gt;
&lt;code&gt;Connection&lt;/code&gt; - &lt;code&gt;SSH&lt;/code&gt; - &lt;code&gt;Auth&lt;/code&gt; - &lt;code&gt;Credentials&lt;/code&gt;&lt;br /&gt;
dann der Pfad zur gespeicherten private-key Datei angegeben,
und schon startet beim Connect eine Schlüssel-gesicherte Übertragung.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/putty-privatekey.png&quot; alt=&quot;PuTTY private key&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Public-Key Authentifizierung funktioniert eigentlich gegengleich
zu Passwörtern.&lt;/p&gt;

&lt;p&gt;Bei einer Passwort-Authentifizierung muss ich das Passwort eines 
Accounts auf dem Server kennen, damit ich mich einloggen kann.&lt;/p&gt;

&lt;p&gt;Bei der Public-Key-Authentifizierung muss im Server-Account ein
Public-Key bekannt sein, der zu meinem lokalen privaten Schlüssel passt.&lt;/p&gt;

&lt;p&gt;Passwörter kann man eher erraten als generierte private Schlüssel,
von daher ist diese Methode sicherer und zu bevorzugen.&lt;/p&gt;

&lt;p&gt;… aber wie schon gesagt … Passwörter haben die Vorteil, dass man
sie im Gehirn speichern und mittragen kann.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>LLVM bzw. CLANG</title>
   <link href="https://www.opengate.at/blog/2024/02/llvm/"/>
   <published>2024-02-25T12:00:00+01:00</published>
   <updated>2024-02-25T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2024/02/llvm</id>
   <category term="devel" />
   <summary type="text">MSVC und 
GCC begleiten mich
jetzt bald 20 Jahre beruflich und privat in unterschiedlichen 
Softwareprojekten. Dann kommt noch ein bisschen 
Watcom für die Retro-Schiene hinzu.

clang und die 
LLVM Toolchain waren für mich bisher 
immer ferne Trabanten, die ich zwar immer wieder mal beobachtete, 
aber nie aktiv einsetzte.

</summary>
   <content type="html">&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_C%2B%2B&quot;&gt;MSVC&lt;/a&gt; und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/GNU_Compiler_Collection&quot;&gt;GCC&lt;/a&gt; begleiten mich
jetzt bald 20 Jahre beruflich und privat in unterschiedlichen 
Softwareprojekten. Dann kommt noch ein bisschen 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Watcom&quot;&gt;Watcom&lt;/a&gt; für die Retro-Schiene hinzu.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Clang&quot;&gt;clang&lt;/a&gt; und die 
&lt;a href=&quot;https://de.wikipedia.org/wiki/LLVM&quot;&gt;LLVM&lt;/a&gt; Toolchain waren für mich bisher 
immer ferne Trabanten, die ich zwar immer wieder mal beobachtete, 
aber nie aktiv einsetzte.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Nun gut … so ganz stimmt das nicht. Ich setze ja immer mehr und mehr 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Zig_(Programmiersprache)&quot;&gt;ZIG&lt;/a&gt; 
mit Leidenschaft ein, und da läuft ein LLVM-Derivat drinnen.&lt;/p&gt;

&lt;p&gt;Und außerdem baut mein &lt;a href=&quot;https://de.wikipedia.org/wiki/WebAssembly&quot;&gt;WASM&lt;/a&gt; 
Build mit &lt;a href=&quot;https://de.wikipedia.org/wiki/Emscripten&quot;&gt;embscripten&lt;/a&gt; auch mit
&lt;code&gt;clang&lt;/code&gt; im Hintergrund.&lt;/p&gt;

&lt;p&gt;Aber: &lt;code&gt;clang&lt;/code&gt; nutzt aber auf vielen Plattformen die nativen Compiler des 
Systems und ist daher ohne diese of unvollständig.&lt;/p&gt;

&lt;p&gt;Auf der Ebene können alternative Tools zur Diagnose und eine bessere
Optimierung eingefügt werden, aber das Rad wird damit nicht neu erfunden.
Und deshalb nutze ich CLANG in der aktiven Entwicklung eher selten.&lt;/p&gt;

&lt;h3 id=&quot;clang-installation&quot;&gt;CLANG Installation&lt;/h3&gt;

&lt;p&gt;Ein übliches&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;apt install clang llvm
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;oder&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;winget install --id LLVM.LLVM
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;reicht aus, um &lt;code&gt;clang&lt;/code&gt; auf dem System nutzen zu können. Hier braucht man
dann natürlich noch einen entsprechenden GCC oder MSVC inklusive dessen
Umgebungsvariablen, damit das Toolset benutzt werden kann.&lt;/p&gt;

&lt;h3 id=&quot;cmake&quot;&gt;CMAKE&lt;/h3&gt;

&lt;p&gt;Für CMAKE ist es erforderlich, die &lt;code&gt;clang&lt;/code&gt; Executables als Compiler 
einzutragen. Ich mache das in der Regel über eine Toolchain-Datei:&lt;/p&gt;

&lt;div class=&quot;language-cmake highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;set(CMAKE_SYSTEM_NAME Linux)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;set(CMAKE_SYSTEM_PROCESSOR x86_64)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;set(target_id x86_64-linux-gnu)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;set(CMAKE_C_COMPILER clang)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;set(CMAKE_C_COMPILER_TARGET ${target_id})
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;set(CMAKE_CXX_COMPILER clang++)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;set(CMAKE_CXX_COMPILER_TARGET ${target_id})
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;CMake findet dann &lt;code&gt;clang&lt;/code&gt; und über die &lt;code&gt;Target-ID&lt;/code&gt; werden auch die 
richtigen Tools (im Fall von Cross-Compiling) benutzt um ein Projekt 
zu übersetzen.&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;cmake -DCMAKE_TOOLCHAIN_FILE=path/to/clang.x86_64-linux-gnu.toolchain.cmake ...
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Mit der CMake-Bedingung&lt;/p&gt;

&lt;div class=&quot;language-cmake highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;if(CMAKE_C_COMPILER_ID STREQUAL &amp;quot;Clang&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;  # clang-specific stuff
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;endif()
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;lassen sich in CMake auch Sonderfälle für das Compiler-Interface definieren.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;LLVM&lt;/code&gt; und &lt;code&gt;clang&lt;/code&gt; werden somit vom GATE Framework unterstützt. Ein paar
Problemchen können bei Plattform-Header auftreten, die etwa bei einer GCC
oder MSVC Suche in CMake gefunden werden und mit &lt;code&gt;clang&lt;/code&gt; eben nicht.&lt;br /&gt;
Doch das hat man meist schnell gefunden und ge-patch-t.&lt;/p&gt;

&lt;p&gt;Super finde ich die zusätzlichen Warnungen bei schlechtem Code, die mir
schon einige Bugs aufgezeigt haben.&lt;/p&gt;

&lt;p&gt;Nicht so gut finde ich die längeren Kompilier- und Link-Zeiten … aber
für stabileren Code bezahle ich so einen Zusatz gerne.&lt;/p&gt;

&lt;p&gt;Ein &lt;code&gt;clang&lt;/code&gt; Build sollte also bei keinem Projekt fehlen, obwohl ich für
Releases dann doch eher wieder zu den bewährten Standard-Compilern greife.&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>C structs Ausnullen</title>
   <link href="https://www.opengate.at/blog/2024/02/struct-init/"/>
   <published>2024-02-18T12:00:00+01:00</published>
   <updated>2024-02-18T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2024/02/struct-init</id>
   <category term="devel" />
   <summary type="text">Seit Ewigkeiten nutze ich
struct structtype instance = {0};
um Strukturen am Stack “generisch” mit Nullen zu initialisieren.

Doch … effizient ist das nicht, wenn man auf den generierten Code schaut.
</summary>
   <content type="html">&lt;p&gt;Seit Ewigkeiten nutze ich&lt;br /&gt;
&lt;code&gt;struct structtype instance = {0};&lt;/code&gt;&lt;br /&gt;
um Strukturen am Stack “generisch” mit Nullen zu initialisieren.&lt;/p&gt;

&lt;p&gt;Doch … effizient ist das nicht, wenn man auf den generierten Code schaut.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;watcoms-dos-exen&quot;&gt;Watcom’s DOS EXEn&lt;/h3&gt;

&lt;p&gt;Dass Programme “zu groß” sind fällt mir immer nur in der 
&lt;a href=&quot;https://de.wikipedia.org/wiki/MS-DOS&quot;&gt;DOS&lt;/a&gt; Welt auf.
Schließlich hat keiner mehr einen Überblick, ob die Windows CRT oder 
Linux GLIBC jetzt 100 oder 200 KB einfach nur so zum Spaß anhängen.
Man akzeptiert den digitalen Müll einfach.&lt;/p&gt;

&lt;p&gt;Aber wenn das Programm zum Auflisten eines Verzeichnisses plötzlich
50 KByte groß wird, und man weiß, dass es funktional nur wenige KB
sein dürften, dann wird man wach.&lt;/p&gt;

&lt;p&gt;Das tolle ist, dass Watcom beim Kompilieren immer sein &lt;code&gt;.map&lt;/code&gt; Dateien
anlegt, wo jede Funktion und jeder Datenblock mit Adresse und Größe
in einer lesbaren Tabelle landet.&lt;br /&gt;
Und dort sind mir dann einige Blöcke aufgefallen, die mehrere Kilobytes
groß waren.&lt;/p&gt;

&lt;h3 id=&quot;kopier-schatten-bei-der-initialisierung&quot;&gt;Kopier-Schatten bei der Initialisierung&lt;/h3&gt;

&lt;p&gt;Wenn ich am Anfang einer C-Funktion die Variablen deklariere, werden die
meistens ausgenullt. Bei &lt;code&gt;struct&lt;/code&gt;s führt ein &lt;code&gt;= { 0 }&lt;/code&gt; dazu, dass alle
Felder (und nicht nur das erste) ausgenullt werden.&lt;/p&gt;

&lt;p&gt;Als ich spaßhalber mal eine der Initialisierungen entfernt hatte, sank
sofort die Größe der EXE und auch die Ausdehnung des Datenbereiches in 
der &lt;code&gt;.map&lt;/code&gt; Tabelle.&lt;/p&gt;

&lt;p&gt;Offenbar erzeugt der Compiler einen statisch mit Nullen ausgefülltes Feld
im Datenbereich und kopiert dieses bei der Initialisierung über die 
Variable auf dem Stack.&lt;br /&gt;
Das fällt natürlich bei Kleinkram niemandem auf, doch ich erzeuge ja gerne
Puffer-Strukturen, die dann Member mit mehrere Kilobytes haben.&lt;br /&gt;
Wenn diese &lt;code&gt;struct&lt;/code&gt;s also bei jeder Initialisierung zu einer versteckten
Leerkopie im Datensegment führen, bläht sich mein Programm unnötig auf.&lt;/p&gt;

&lt;h3 id=&quot;lösung-memset&quot;&gt;Lösung: memset&lt;/h3&gt;

&lt;p&gt;Ich ging also durch meine Initialisierungszeilen durch und ersetzte diese 
beiden größeren Objekten durch ein:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#777&quot;&gt;//struct mytype struct_var = {0};&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;struct&lt;/span&gt; mytype struct_var;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;memset(&amp;amp;struct_var, &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;, &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;sizeof&lt;/span&gt;(struct_var));
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Resultat: Meine DOS EXEen sind wieder um 20 KByte kleiner geworden.&lt;br /&gt;
Der größte Zuwachs kam durch meine Koroutinen-Implementierung ins 
Framework, denn diese wird in DOS jetzt zwingend am Start initialisiert
und dort wurde für mehrere potentielle Stacks Verwaltungsbereich
vorinitialisiert.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Tja … es kann gut sein, dass andere Compiler hier besser optimieren und
es gar nicht zu solchen Init-Kopien kommt. Aber nachdem man es nicht 
ausschließen kann, gilt für mich ab sofort die Regel:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;code&gt;struct&lt;/code&gt;s größer als 32 Bytes dürfen nicht mehr per &lt;code&gt;{ 0 }&lt;/code&gt; 
initialisiert werden.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Und wieder einmal belehrt mich ein Altsystem, dass ich fahrlässig mit 
Ressourcen umgegangen bin. Und so lernt man aus der Vergangenheit, 
wie man mit einer Zeile eine bessere Zukunft “aufbauen” kann.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>FAT - Dateizuordnungstabelle</title>
   <link href="https://www.opengate.at/blog/2024/02/fat/"/>
   <published>2024-02-11T12:00:00+01:00</published>
   <updated>2024-02-11T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2024/02/fat</id>
   <category term="devel" />
   <summary type="text">Das FAT Dateisystem war in den 90igern die absolute Nummer ein am PC und wurde
erst nach dem Jahr 2000 mit Windows XP
durch NTFS bzw durch 
Linux mit 
ext2/3 ersetzt.

Für meine Retro-PC und Disketten
Experimente benötige ich ein Tool zum Auslesen der alten Datenträger, also
implementiere ich mir eine FAT12/16 Reader schnell selbst.
</summary>
   <content type="html">&lt;p&gt;Das FAT Dateisystem war in den 90igern die absolute Nummer ein am PC und wurde
erst nach dem Jahr 2000 mit &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_XP&quot;&gt;Windows XP&lt;/a&gt;
durch &lt;a href=&quot;https://de.wikipedia.org/wiki/NTFS&quot;&gt;NTFS&lt;/a&gt; bzw durch 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt; mit 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Extended_filesystem&quot;&gt;ext2/3&lt;/a&gt; ersetzt.&lt;/p&gt;

&lt;p&gt;Für meine Retro-PC und &lt;a href=&quot;https://de.wikipedia.org/wiki/Diskette&quot;&gt;Disketten&lt;/a&gt;
Experimente benötige ich ein Tool zum Auslesen der alten Datenträger, also
implementiere ich mir eine FAT12/16 Reader schnell selbst.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;ein-paar-daten-und-fakten-zu-fat&quot;&gt;Ein paar Daten und Fakten zu FAT&lt;/h3&gt;

&lt;p&gt;Auf Disketten ist FAT12 auch heute noch die Nummer 1. Weder Linux noch WinNT
wagten und wagen es, hier ein anderes Dateisystem aufzuspielen.&lt;br /&gt;
FAT16 konnte damals Festplattenpartitionen bis knapp 2 GB bedienen und wird
heute noch in kleinen SD-Karten z.B. am Mikrokontroller benutzt.&lt;br /&gt;
Und FAT32 haben wir fast überall im Einsatz, weil jeder USB Stick und jede
übliche SD Karte damit formatiert ist, und die meisten Anwender nutzen 
bekanntlich genau so, wie es aus der Packung kam.&lt;/p&gt;

&lt;p&gt;Die Idee von FAT war, dass der Datenträger in “Cluster” unterteilt wird.
Auf Disketten war ein Cluster genau ein Sektor groß, doch auf größeren Medien
wurden mehrere Sektoren zu einem Cluster zusammengefasst.&lt;br /&gt;
FAT12 hat (Wer errät es?) eine 12-bit breite Cluster-Adressierung und kann etwa
4000 Cluster verwalten (genau 4084, weil ein paar IDs reserviert sind).
FAT16 schafft 65000 Cluster (genau 65524) und FAT32 kommt auf 268 000 000
(genau 268435444) weil nur 28 bit und noch die vollen 32 bits benutzt werden.&lt;/p&gt;

&lt;p&gt;Ein 1-Sektor-Cluster (512 Bytes) unter FAT16 könnte nur 32 MB große Laufwerke 
verwalten. Mit 2-Sektor großen Clustern (1024 Bytes) verdoppelt sich das auf 
64 MB, bis man mit einer Clustergröße von 64 Sektoren (32 KB) erreicht hat
und damit knapp 2 GB adressieren kann.&lt;/p&gt;

&lt;p&gt;Windows NT konnte auch 128 Sektoren (64 KB) zusammen-clustern und damit 4 GB
ansprechen, doch da spielten DOS und Windows 3x/9x nicht mit. Unter DOS ist
das fast logisch, weil man mit einem 64 KB großen Datenblock ein 
Speichersegment zum Überlaufen gebracht hätte.&lt;/p&gt;

&lt;h3 id=&quot;fat12-implementierung&quot;&gt;FAT12 Implementierung&lt;/h3&gt;

&lt;p&gt;FAT12 ist für mich deshalb interessant, weil ich ja meine alten Toshiba 
Disketten auslesen möchte. Daher startete ich in der &lt;code&gt;gate/tech&lt;/code&gt; Bibliothek
ein Modul für Dateisystemstrukturen.&lt;/p&gt;

&lt;p&gt;Im ersten Sektor (Bootsektor) einer Diskette befindet sich im 
“BIOS Parameter Block” (kurz &lt;code&gt;BPB&lt;/code&gt;) eine Auflistung wichtiger Kennzahlen des 
Dateisystems, wie etwa Anzahl der Sektoren, Sektoren pro Cluster, Länge des
Stammverzeichnisses.&lt;br /&gt;
Mit diesen Infos kann man später die logischen Sektorpositionen ausrechnen, um
zu den Nutzdaten zu kommen.&lt;/p&gt;

&lt;p&gt;Grundsätzlich liegen die in den Sektoren so hintereinander:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Reservierte Sektoren
    &lt;ul&gt;
      &lt;li&gt;Bootsektor&lt;/li&gt;
      &lt;li&gt;Optional andere unbenutzte Sektoren&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;FAT Sektoren
    &lt;ul&gt;
      &lt;li&gt;FAT-1 (Primäre FAT)&lt;/li&gt;
      &lt;li&gt;FAT-2 (Kopie der FAT als Backup für Reparatur)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Stammverzeichnis Sektoren&lt;/li&gt;
  &lt;li&gt;Cluster Sektoren
    &lt;ul&gt;
      &lt;li&gt;Dateifragmente&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Daraus ergeben sich folgenden Formeln:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;first_fat_sector = bpb.reserved_sectors&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;total_fat_sectors = bpb.sectors_per_fat * bpb.fat_copies&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;root_dir_sectors = bpb.root_dir_entries / 32&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;total_cluster_sectors = bpb.total_sectors - (bpb.reserved_sectors + total_fat_sectors + root_dir_sectors)&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;total_cluster_count = total_cluster_sectors / bpb.sectors_per_cluster&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;first_cluster_sector = bpb.reserved_sectors + total_fat_sectors + root_dir_sectors&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Das Stammverzeichnis hat also unter FAT immer eine feste Länge und kann nicht
nachträglich wachsen (außer man strukturiert den ganzen Datenträger neu).&lt;/p&gt;

&lt;h3 id=&quot;fat-funktionsweise&quot;&gt;FAT Funktionsweise&lt;/h3&gt;

&lt;p&gt;Die FAT selbst speichert für jeden Cluster eine Zahl der anzeigt, ob damit
ein weiterer Cluster verknüpft ist. Es ist also eine 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Liste_(Datenstruktur)&quot;&gt;Single-Linked-List&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Ein Dateieintrag im Stammverzeichnis (oder Unterverzeichnis) nennt den ersten 
Cluster einer Datei. Den kann man mal auslesen.
Dann sieht man in der FAT nach, was in dessen Cluster-Liste steht und findet
dort entweder die nächste Cluster-Nummer oder eine “Ende-Markierung”.&lt;/p&gt;

&lt;p&gt;Die logischen Cluster-IDs &lt;code&gt;0&lt;/code&gt; und &lt;code&gt;1&lt;/code&gt; sowie die größten 9 am Ende sind 
reserviert.&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;0&lt;/code&gt;  bedeutet, dass ein Cluster unbenutzt ist&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;ffff&lt;/code&gt; (also die höchste ID in FAT16) steht für “Ende”, es sind also keine
weiteren Cluster mehr mit der Datei (Cluster-Kette) verknüpft.&lt;/li&gt;
&lt;/ul&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Index&lt;/th&gt;
      &lt;th&gt;Inhalt&lt;/th&gt;
      &lt;th&gt;Bedeutung&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;#2&lt;/td&gt;
      &lt;td&gt;3&lt;/td&gt;
      &lt;td&gt;Cluster 2 verlinkt auf 3&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;#3&lt;/td&gt;
      &lt;td&gt;4&lt;/td&gt;
      &lt;td&gt;Cluster 3 verlinkt auf 4&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;#4&lt;/td&gt;
      &lt;td&gt;ffff&lt;/td&gt;
      &lt;td&gt;Ende erreicht&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;#5&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;Cluster ist frei&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;#6&lt;/td&gt;
      &lt;td&gt;ffff&lt;/td&gt;
      &lt;td&gt;Ende erreicht&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;#7&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;Cluster ist frei&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;#8&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;Cluster ist frei&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h3 id=&quot;spezialfall-fat12&quot;&gt;Spezialfall FAT12&lt;/h3&gt;

&lt;p&gt;Während FAT16 und FAT32 einfach 16 und 32-bit Werte hintereinander in die FAT
schreiben, sind bei FAT12 immer zwei Einträge in 3 Bytes verschränkt.&lt;br /&gt;
Die logischen Cluster-Nummern &lt;code&gt;0x0aaa&lt;/code&gt; und &lt;code&gt;0x0bbb&lt;/code&gt; werden in FAT12 als&lt;br /&gt;
&lt;code&gt;aa ba bb&lt;/code&gt; gespeichert.&lt;/p&gt;

&lt;p&gt;Das wirkt auf den ersten Blick komisch, macht aber in der 8-bit 
Little-Endian-Welt von X86 total Sinn.&lt;br /&gt;
Liest man nämlich den 16-bit Wert von Adresse 0 und dann von Adresse 1,
erhält man die Werte &lt;code&gt;0xbaaa&lt;/code&gt; und &lt;code&gt;0xbbba&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Jetzt braucht man den ersten nur noch mit &lt;code&gt;AND 0x0fff&lt;/code&gt; verknüpfen und den
zweiten um 4 Bits nach links verschieben und schon hat man die gewünschten
Werte von &lt;code&gt;0x0aaa&lt;/code&gt; und &lt;code&gt;0x0bbb&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;FAT ist gar nicht so schwer.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Gut, ein paar Rechenfehler macht man am Anfang, wenn man die Cluster, die bei
&lt;code&gt;2&lt;/code&gt; zu zählen anfangen, dann auch genau so zum ausrechnen der Sektoren nimmt
und man dann daneben liegt … aber mit einer Referenzdiskette findet man das 
schnell selbst heraus, fügt das &lt;code&gt;-2&lt;/code&gt; in die Formel ein und alles ist gut.&lt;/p&gt;

&lt;p&gt;Spannend sind so Sachen wie, dass man Pseudo-Hardlinks erstellen konnte, wenn
einfach zwei Dateieinträge auf den gleichen Start-Cluster zeigten. Das ist in
FAT eigentlich nicht erlaubt, doch ich hatte sogar noch so ein alte Diskette
mit einem manipulierten Inhaltsverzeichnis.&lt;/p&gt;

&lt;p&gt;Ein großes Lob geht an Seiten wie &lt;code&gt;wiki.osdev.org&lt;/code&gt;, die den Aufbau wunderbar 
bildlich dargestellt haben. So konnte ich meine selbsterstellte 
Erstimplementierung gegenprüfen und korrigieren.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Device-Independent-Bitmaps</title>
   <link href="https://www.opengate.at/blog/2024/02/dibsection/"/>
   <published>2024-02-03T12:00:00+01:00</published>
   <updated>2024-02-03T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2024/02/dibsection</id>
   <category term="devel" />
   <summary type="text">Seit 15 Jahren nutze ich DIBSections der 
WinAPI
um Grafiken in GUI Apps zu verwalten und mit der Zeit hinterfragt man gar 
nicht mehr, was alles ausimplementiert ist, wie es ist 
… man kopiert es einfach.

Doch DIBSections gab es in 
Windows 3.x
nicht und auch unter NT 3.5
funktionieren einige meiner Codes nicht.


  Frage: Warum?


</summary>
   <content type="html">&lt;p&gt;Seit 15 Jahren nutze ich &lt;code&gt;DIBSections&lt;/code&gt; der 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_Application_Programming_Interface&quot;&gt;WinAPI&lt;/a&gt;
um Grafiken in GUI Apps zu verwalten und mit der Zeit hinterfragt man gar 
nicht mehr, was alles ausimplementiert ist, wie es ist 
… man kopiert es einfach.&lt;/p&gt;

&lt;p&gt;Doch &lt;code&gt;DIBSections&lt;/code&gt; gab es in 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_3.1&quot;&gt;Windows 3.x&lt;/a&gt;
nicht und auch unter &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_NT_3.51&quot;&gt;NT 3.5&lt;/a&gt;
funktionieren einige meiner Codes nicht.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Frage: Warum?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Das GDI ist vermutlich die älteste API in Windows, die sich bis heute am
wenigsten verändert hat … bzw. die heute noch so funktioniert, wie man es
in den 80er Jahren für richtig gehalten hat.&lt;/p&gt;

&lt;p&gt;Mit den erwähnten DIBSections kam um das Jahr 1995 eine zusätzliche 
“modernere” Schnittstelle hinzu, die eigentlich bis heute “ausreicht”.&lt;br /&gt;
Device-Independent-Bitmaps (DIBs) sind Rastergrafiken, wo der Nutzer 
entscheidet, wie sie intern aufgebaut sind. Man kann Farbpaletten für 
4 oder 8 Bit Grafiken definieren, oder gleich 16- oder 24-bit RGB 
Farbwerte speichern. (Später kam noch 32-bit RGBA mit Transparenz hinzu.)&lt;/p&gt;

&lt;p&gt;Eine solche “unabhängige” Bitmap wurde den WinAPIs übergeben und dieses 
zeichnete alles passend auf Bildschirme, in den Speicher oder auf den Drucker.&lt;/p&gt;

&lt;p&gt;Doch das war nicht immer so …&lt;/p&gt;

&lt;h3 id=&quot;am-anfang-war-das-bit&quot;&gt;Am Anfang war das Bit.&lt;/h3&gt;

&lt;p&gt;Bitmaps waren mal 1-Bit Grafiken, also rein schwarz-weiß. 
&lt;a href=&quot;https://de.wikipedia.org/wiki/X_Window_System&quot;&gt;X11&lt;/a&gt; unterscheidet
daher folgerichtig Bitmaps für 1-Bit-Bilder und Pixmaps für Farbpixel-Bilder.
Und aus dieser Zeit stammt der Standard, dass eine neue Bitmap mit einem Bit
pro Pixel erzeugt wird.&lt;/p&gt;

&lt;p&gt;DIBs gab es auch schon von Anfang an und sie wurden per &lt;code&gt;CreateDIBitmap()&lt;/code&gt; 
über ein bestehendes Device-Context-Handle (&lt;code&gt;HDC&lt;/code&gt;) erzeugt. Danach konnte man
sie über den &lt;code&gt;HDC&lt;/code&gt; per &lt;code&gt;GetPixel&lt;/code&gt; und &lt;code&gt;SetPixel&lt;/code&gt; und ein paar andere Linien- und 
Polygon-Zeichenroutinen befüllen.&lt;/p&gt;

&lt;p&gt;Und das war so f*cking langsam, weshalb man per &lt;code&gt;CreateDIBSection()&lt;/code&gt; das 
gleiche nochmal implementierte, und zusätzlich den Pointer zu den Rohdaten
im Speicher bekam.&lt;br /&gt;
Die Coder erzeugten dann nur noch 32-bit DIB-Sections und manipulierten sich
die Pixel selbst so hin, wie sie es brauchten, und umgangen so das langsame
umwandeln von Pixel-Operationen in GDI Device-Contexts.&lt;/p&gt;

&lt;p&gt;Früher musste man ohne DIB-Section entweder alle Pixel bereits mit 
&lt;code&gt;CreateDIBBitmap()&lt;/code&gt; dem neu entstehenden Objekt eingravieren, oder mit den
genannten GDI-Zeichenprimitiven dann drübermalen.&lt;/p&gt;

&lt;h3 id=&quot;finde-den-fehler&quot;&gt;Finde den Fehler:&lt;/h3&gt;

&lt;p&gt;Und so sah also einer meiner Retro-Codeblöcke für Win3X aus, der auch auf 
heutigen System noch lauffähig sein muss:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;HDC desktop = GetDC(&lt;span style=&quot;color:#069&quot;&gt;NULL&lt;/span&gt;); &lt;span style=&quot;color:#777&quot;&gt;/* get default-DC from Screen */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;HDC mydc = CreateCompatibleDC(desktop);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;HBITMAP mybitmap = CreateDIBitmap(mydc, 
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;    &amp;amp;bitmapHeader, CBM_INIT, init_buffer, 
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;    &amp;amp;infoheader, DIB_RGB_COLORS);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;HGDIOBJ backup = SelectObject(mydc, mybitmap);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#777&quot;&gt;/* draw into bitmap */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;SetPixel(mydc, x, y, RGB(r, g, b));
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#777&quot;&gt;/* cleanup */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;SelectObject(mydc, backup);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;DeleteObject(mybitmap);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;DeleteDC(mydc);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;ReleaseDC(&lt;span style=&quot;color:#069&quot;&gt;NULL&lt;/span&gt;, desktop);
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Und egal wo ich meine so erstellte &lt;code&gt;mybitmap&lt;/code&gt; ausgeben wollte, ich sah immer
nur eine Schwarz/Weiß-Grafik.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Der Fehler liegt in &lt;code&gt;mydc&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Wenn man einen “compatible DC” erzeugt, hat der wie vor 40 Jahren eine 
1-Bit Bitmap mit 1x1 Pixel drinnen und wenn man dann &lt;code&gt;CreateDIBitmap&lt;/code&gt; 
aufruft, erzeugt das eine Bitmap, die kompatibel mit dem DC ist und 
konvertiert meine “externen” DIBitmap-Daten in das Zielformat, und so
wird ein 1-bit Abbildung daraus.&lt;/p&gt;

&lt;h3 id=&quot;lösung&quot;&gt;Lösung:&lt;/h3&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;HDC desktop = GetDC(&lt;span style=&quot;color:#069&quot;&gt;NULL&lt;/span&gt;); &lt;span style=&quot;color:#777&quot;&gt;/* get default-DC from Screen */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;HDC mydc = CreateCompatibleDC(desktop);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;HBITMAP mybitmap = CreateDIBitmap(desktop, &lt;span style=&quot;color:#777&quot;&gt;/* &amp;lt;- use desktop-DC  */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;    &amp;amp;bitmapHeader, CBM_INIT, init_buffer,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;    &amp;amp;infoheader, DIB_RGB_COLORS);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;...
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Anstatt &lt;code&gt;mydc&lt;/code&gt; in &lt;code&gt;CreateDIBitmap&lt;/code&gt; zu nutzen, kann man dort den DC des 
Bildschirms nutzen. Der sollte nämlich genau die grafischen Eigenschaften
haben, wie es gerade in der Grafikkarte eingestellt ist.&lt;br /&gt;
Man erhält also eine Bitmap, die genau das Farbschema hat, das gerade
angezeigt werden kann und die eigenen Bitmapdaten werden in genau dieses
Format konvertiert.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Tja, der wahre Unterschied zwischen &lt;code&gt;CreateDIBitmap&lt;/code&gt; und &lt;code&gt;CreateDIBSection&lt;/code&gt; 
ist, dass &lt;code&gt;CreateDIBitmap&lt;/code&gt; wie &lt;code&gt;CreateCompatibleBitmap&lt;/code&gt; ein zum DC kompatible
Bitmap erzeugt und &lt;code&gt;CreateDIBSection&lt;/code&gt; die Bitmap so herstellt, wie man es 
angegeben hat.&lt;/p&gt;

&lt;p&gt;Die Sache ist sogar noch schlimmer, denn mir ist der Fehler auch mit 
&lt;code&gt;CreateDIBSection(mydc, ...)&lt;/code&gt; unterlaufen.&lt;br /&gt;
Es sieht aber so aus, als würden neuere Windows Varianten beim Zeichnen, dann
das Format der DIB-Section nutzen, und nicht das Format des DCs, das wegen
&lt;code&gt;CreateCompatibleDC&lt;/code&gt; nur 1 Bit breit ist.&lt;/p&gt;

&lt;p&gt;Ältere Windows Versionen sind da aber strenger … und jetzt erklärt es
sich mir auch, warum mein OpenGL-Code unter Windows 95 nur Schwarz-Weiß 
Ergebnisse im Test lieferte. Ein weiterer Fix steht bevor.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Wichtige Erkenntnis: Windows korrigiert Fehler!&lt;br /&gt;
Und deshalb programmieren wir schlampig … 
weil uns die Fehler nicht als solche auffallen.&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>Nintendo DS</title>
   <link href="https://www.opengate.at/blog/2024/01/nintendo-ds/"/>
   <published>2024-01-28T12:00:00+01:00</published>
   <updated>2024-01-28T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2024/01/nintendo-ds</id>
   <category term="hardware" /><category term="retro" />
   <summary type="text">Etwa im Jahr 2010 setzt bei mir die zweite Kindheit in Sachen Spielekonsole
ein. Und so kaufte ich mir in den folgenden Jahren die Modelle:
NDS,
3DS, 3DSXL
und schließlich noch den New 3DSXL.

</summary>
   <content type="html">&lt;p&gt;Etwa im Jahr 2010 setzt bei mir die zweite Kindheit in Sachen Spielekonsole
ein. Und so kaufte ich mir in den folgenden Jahren die Modelle:&lt;br /&gt;
&lt;a href=&quot;https://de.wikipedia.org/wiki/Nintendo_DS&quot;&gt;NDS&lt;/a&gt;,
&lt;a href=&quot;https://de.wikipedia.org/wiki/Nintendo_3DS&quot;&gt;3DS, 3DSXL&lt;/a&gt;
und schließlich noch den &lt;code&gt;New 3DSXL&lt;/code&gt;.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;blockquote&gt;
  &lt;p&gt;Es begann mit &lt;a href=&quot;https://de.wikipedia.org/wiki/Pok%C3%A9mon&quot;&gt;Pokemon&lt;/a&gt; …&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Es beginnt doch eigentlich immer alles mit Pokemon, oder?&lt;br /&gt;
Im Jahr 2000 brachte mich &lt;a href=&quot;http://problemkaputt.de/gmb.htm&quot;&gt;No$GMB&lt;/a&gt;
mit Pokemon-RGB zusammen, und 10 Jahre später war es 
&lt;a href=&quot;https://www.bisafans.de&quot;&gt;bisafans.de&lt;/a&gt; und seine hoch motivierte Community,
die den Hype um die kommende 5. Generation anfachte.&lt;/p&gt;

&lt;p&gt;Ursprünglich startete ich auch wieder mit Emulatoren, doch gab es damals 
noch einige Probleme im für den DS erweiterten 
&lt;a href=&quot;https://www.nogba.com/&quot;&gt;No$gba&lt;/a&gt; und dem neueren
&lt;a href=&quot;https://github.com/TASEmulators/desmume/&quot;&gt;DeSmuMe&lt;/a&gt;, womit Spiele gelegentlich
einfrieren konnten.&lt;br /&gt;
Genau das vermiest einem dann das Spielegefühl.&lt;/p&gt;

&lt;p&gt;Und als dann 2011 der 3DS auf den Markt kam, dachte ich mir:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ach warum nicht … ich kaufe mir einen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;cheat-freiheit-erhöht-den-reiz&quot;&gt;Cheat-Freiheit erhöht den Reiz&lt;/h3&gt;

&lt;p&gt;Mit dem 3DS lernte ich, dass Emulatoren den Spielreiz zerstören. Schließlich
kann man an jeder Stelle per Save-State sichern und wieder neu anfangen.
Damit verliert man nicht, aber das Spiel wird damit belanglos.&lt;/p&gt;

&lt;p&gt;Doch beim Nachspielen der 4. und 5. Generation auf dem 3DS fühlte ich mich
wieder wie ein Kind und war glücklich weil ich mir jeden Orden auch “verdient”
hatte.&lt;/p&gt;

&lt;p&gt;Und neben Pokemon konnte ich mich dann auch für die DS-Titel der 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Kingdom_Hearts&quot;&gt;Kingdom Hearts&lt;/a&gt;
Reihe begeistern, deren Haupttitel ich im 
&lt;a href=&quot;https://de.wikipedia.org/wiki/PlayStation_2&quot;&gt;PS2&lt;/a&gt;
Emulator mal angespielt hatte.&lt;/p&gt;

&lt;p&gt;In den 10 Jahren zuvor wurden mir Spiele immer schnell langweilig, doch das
lag meist an den Emulatoren. Mit dem 3DS kam endlich die notwendige 
Zufriedenheit zurück, wenn man was geschafft hatte, oder die Rastlosigkeit,
wenn man ein Ziel nicht erreicht hatte.&lt;/p&gt;

&lt;h3 id=&quot;bewegung-ist-gesund&quot;&gt;Bewegung ist gesund!&lt;/h3&gt;

&lt;p&gt;Für 1000 registrierte Schritte mit dem 3DS erhält man 10 Spielemünzen, die in
Nintendos eigener MII-Lobby oder in anderen Spielen eingetauscht werden können.
Dafür erhielt man dann Items oder eben eine weitere Minispielchen-Runde.&lt;/p&gt;

&lt;p&gt;Das hatte zur Folge, dass der 3DS ein fester Bestandteil in meinem Rucksack 
wurde. Die tausend Schritte sind zwar nicht viel, aber dennoch oft ein Grund
gewesen, die Weg zur Arbeit zu Fuß und nicht per Bus zurückzulegen.&lt;/p&gt;

&lt;h3 id=&quot;andere-spieler-treffen&quot;&gt;Andere Spieler treffen&lt;/h3&gt;

&lt;p&gt;Durch sein eigenes abgewandeltes &lt;a href=&quot;https://de.wikipedia.org/wiki/Wireless_Local_Area_Network&quot;&gt;WLAN&lt;/a&gt;
konnten sich 3DS Geräte gegenseitig erkennen und so wurde die virtuelle 
Spieler-Identität (MII) ausgetauscht, was ebenso die genannten Minispielchen
befeuerte.&lt;/p&gt;

&lt;p&gt;Und zwischen 2011 und 2017 konnte man tatsächlich immer wieder neue MIIs
am Gerät finden, wenn man ein paar Straßen durch die Stadt wanderte, oder
einfach in die U-Bahn einstieg.&lt;/p&gt;

&lt;p&gt;Ein echtes MII-Feuerwerk erlebte man mit dem 3DS bei Veranstaltungen, wie 
bei &lt;a href=&quot;https://de.wikipedia.org/wiki/Anime-_und_Manga-Convention&quot;&gt;Anime-Conventions&lt;/a&gt;
oder Spielemessen wie der 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Game_City&quot;&gt;Game-City&lt;/a&gt; in Wien.&lt;br /&gt;
Ich war dort ein paar mal nur um 3 Stunden lang diverse MII-Spiele 
abzuschließen, weil dort im Minutentakt neue MIIs und damit Spielerunden
reinkamen.&lt;/p&gt;

&lt;h3 id=&quot;3ds-xl&quot;&gt;3DS-XL&lt;/h3&gt;

&lt;p&gt;Aus dem Jahr 2013 stammt meine Aussage:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Mein Augenarzt hat unrecht!&lt;br /&gt;
Ich brauche keine Brille,&lt;br /&gt;
ich brauchte nur einen größeren Monitor.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Und genau das erfüllte der 3DSXL pünktlich zum Release von 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Pok%C3%A9mon_X_und_Y&quot;&gt;Pokemon X/Y&lt;/a&gt;.
Das größere Display zahlte sich wirklich aus, und außerdem war mein erster
3DS schon etwas abgenutzt.&lt;/p&gt;

&lt;h3 id=&quot;new3ds&quot;&gt;New3DS&lt;/h3&gt;

&lt;p&gt;Der 3D Effekt des 3DS hatte mich anfangs nicht überzeugt. Im Gegenteil, bei
überladenen Spielen wie Kingdom-Hearts 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Kingdom_Hearts#Hauptreihe&quot;&gt;Dream-Drop-Distance&lt;/a&gt;
musste ich es vollkommen abschalten um Kopfschmerzen zu verhindern. Es war 
also eher was für ruhige Spiele, für Pokemon war es “optional” OK.&lt;/p&gt;

&lt;p&gt;Als ich mir Anfang 2016 dann einen New3DS zulegte, war die Verbesserung nicht
zu leugnen. Eine eigene Augen-Kamera verfolgt dabei das Gesicht des Spielers 
und passt den 3D-Effekt an den Sichtwinkel an und so konnte man das Feature
tatsächlich genießen.&lt;/p&gt;

&lt;p&gt;Doch am Ende muss ich sagen … wirklich gebraucht hat man das nicht.
Neue Spieletitel wie &lt;a href=&quot;https://de.wikipedia.org/wiki/The_Legend_of_Zelda&quot;&gt;Zelda&lt;/a&gt;
oder  &lt;a href=&quot;https://de.wikipedia.org/wiki/Yo-kai_Watch&quot;&gt;Yokai Watch&lt;/a&gt;
überzeugten durch ihre Story und ihren Stil und nicht durch 3D Effekte.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/nintendo-ds-3dsxl.jpg&quot; alt=&quot;Nintendo-DS and 3DSXL&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;2017 Endete meine DS-Phase dann, als der Wechsel zur 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Nintendo_Switch&quot;&gt;Switch&lt;/a&gt; stattfand und
Pokemon Mond/Sonne auch nicht mehr wirklich “spannend” am 3DS erschienen.&lt;/p&gt;

&lt;p&gt;Dennoch hat mich diese Gerätefamilie über 5 Jahre sehr gut unterhalten.
Frustration aus Arbeit und Alltag verflogen, wenn man sich am Abend eine
Stunde auf ein Spiel konzentrierte.&lt;/p&gt;

&lt;p&gt;Tatsächlich brachte mir der DS oft Entspannung nach stressigen Arbeitstagen.
Und während andere sich Pillen oder Alkohol einwarfen, brachte mich die
Konsole in den Ruhemodus.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Und wie komme ich jetzt zu dem Thema?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ich habe eine alte Nintendo-eShop Karte mit 25 Euro gefunden, die ich nie
eingelöst habe. Und da leider alle 3DS Online Dienste inzwischen abgeschaltet
sind, ist die Wertkarte verfallen.&lt;/p&gt;

&lt;p&gt;Doch bei der Gelegenheit wurden meine Geräte wieder gestartet und sie 
funktionieren immer noch einwandfrei.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Bootsektor von Disketten</title>
   <link href="https://www.opengate.at/blog/2024/01/bootsector/"/>
   <published>2024-01-21T12:00:00+01:00</published>
   <updated>2024-01-21T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2024/01/bootsector</id>
   <category term="devel" />
   <summary type="text">
  Ja damals, als wir noch unsere eigenen Betriebssystem schreiben wollten …


Da hat alles mit einer Diskette
angefangen. Es wird Zeit diese Epoche wieder etwas aufleben zu lassen. 
Also schreiben wir mal ein paar Bytes in den Bootsektor.

</summary>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;Ja damals, als wir noch unsere eigenen Betriebssystem schreiben wollten …&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Da hat alles mit einer &lt;a href=&quot;https://de.wikipedia.org/wiki/Diskette&quot;&gt;Diskette&lt;/a&gt;
angefangen. Es wird Zeit diese Epoche wieder etwas aufleben zu lassen. 
Also schreiben wir mal ein paar Bytes in den Bootsektor.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;512 Bytes ist ein üblicher Datensektor (also die kleinste als Block lesbare 
Einheit) einer Diskette groß. Und bis heute ist dieser Standard geblieben.
Zwar haben Festplatten um 2010 herum auf 4096 Bytes umgesattelt, doch 
Schnittstellen von Betriebssystemen legen diese Größe bis heute als 
virtuellen Grenzwert fest, auch wenn die Hardware dahinter dann was
anderes macht.&lt;/p&gt;

&lt;p&gt;Und wenn ein PC startete, dann las er früher (vor dem 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Unified_Extensible_Firmware_Interface&quot;&gt;UEFI&lt;/a&gt;
Standard) den ersten Sektor des Bootmediums und führte den Code darin aus.&lt;/p&gt;

&lt;h3 id=&quot;bios-bootvorgang&quot;&gt;BIOS Bootvorgang&lt;/h3&gt;

&lt;p&gt;Nachdem das BIOS geladen ist und dieses sich ein Bootmedium auserkoren hat,
lädt es dessen ersten Sektor in den 16-bit Realmode Speicherbereich 
&lt;code&gt;0000:7c00&lt;/code&gt; und springt an diese Adresse.&lt;/p&gt;

&lt;p&gt;Dass heißt, dass man den Bootsektor einfach mit Instruktionen füllen kann,
und diese werden dann sofort ausgeführt.&lt;/p&gt;

&lt;p&gt;Doch für eine ordentliche Plattform benötigt man Standards und Dateisysteme.
Damals war das ein &lt;a href=&quot;https://de.wikipedia.org/wiki/File_Allocation_Table&quot;&gt;FAT Dateisystem&lt;/a&gt;
bzw. FAT12 für Disketten und der Bootsektor sollte anzeigen,
welches Dateisystem genutzt wird, und wie dessen Daten verteilt sind.&lt;/p&gt;

&lt;p&gt;Deshalb ist der Bootsektor so aufgebaut, dass die ersten 3 Bytes für eine X86
Jump-Anweisung reserviert sind und danach sofort Datenfelder kommen, die das
FAT Dateisystem (oder andere) beschreiben.&lt;br /&gt;
Der eigentliche Bootcode wird erst danach gespeichert, und genau dorthin muss
die erste JUMP-Anweisung hinspringen.&lt;/p&gt;

&lt;p&gt;Will man jetzt seinen eigenen kleinen Bootcode schreiben, sollte man die 
FAT-Info Daten bestehen lassen und nur den restlichen Codebereich nutzen.&lt;/p&gt;

&lt;p&gt;Was ich früher oft vergessen habe: Ein Bootsektor endet mit einer Signatur
mit den Bytes &lt;code&gt;0x55&lt;/code&gt; und &lt;code&gt;0xaa&lt;/code&gt;. Fehlen diese beiden Bytes am Ende, 
überspringt das BIOS das Medium beim Bootvorgang.&lt;/p&gt;

&lt;h3 id=&quot;netwide-assembler&quot;&gt;Netwide Assembler&lt;/h3&gt;

&lt;p&gt;Der &lt;a href=&quot;https://de.wikipedia.org/wiki/Netwide_Assembler&quot;&gt;nasm&lt;/a&gt; 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Assembler_(Informatik)&quot;&gt;Assembler&lt;/a&gt; 
lässt uns einen solchen Bootsektor ganz leicht zubereiten. Und mit ein paar
“magischen” Zeichen (siehe &lt;code&gt;emtpy_space&lt;/code&gt;) lässt sich auch ein Speicherbereich
bis zu einer bestimmten Marke mit Nullen füllen, damit am Ende eine 512 Byte
Ausgabedatei entsteht, die man in den Bootsektor übertragen kann.&lt;/p&gt;

&lt;p&gt;Das sieht dann als Skelett wie folgt aus kann mit 
&lt;code&gt;nasm bootsect.asm -f bin -o bootsect.bin&lt;/code&gt; kompiliert werden:&lt;/p&gt;

&lt;div class=&quot;language-asm highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;    ; bootsect.asm
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;    org 7c00h       ; boot sector is loaded and executed in [0000:7c00]
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;                    ; Offset |Description
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;                    ;-------------------------
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;main:               ; 0000: startup code (jump over data fields)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;    jmp short boot_code
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;    nop
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;    ; OEM system name
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;    db &apos;MSDOS5.0&apos;   ; 0003: format name (8 chars)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;    ; BPB (BIOS Parameter Block)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;    dw     0200h    ; 000b: bytes per sector
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;    db       01h    ; 000d: sectors per cluster
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;    dw     0001h    ; 000e: reserved sectors (starting at 0)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;    db       02h    ; 0010: number of FATs on disk
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;    dw     00e0h    ; 0011: reserved root directory entries
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;    dw     0b40h    ; 0013: total sectors on disk
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;    db      0f0h    ; 0015: media descriptor byte
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n21&quot; name=&quot;n21&quot;&gt;21&lt;/a&gt;&lt;/span&gt;                    ;       f0: 3.5&amp;quot; 1.44M -or- 3.5&amp;quot; 2.88M
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n22&quot; name=&quot;n22&quot;&gt;22&lt;/a&gt;&lt;/span&gt;                    ;       f8: hard-disk
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n23&quot; name=&quot;n23&quot;&gt;23&lt;/a&gt;&lt;/span&gt;                    ;       f9: 3.5&amp;quot; 720K -or- 5.25&amp;quot; 1.2M
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n24&quot; name=&quot;n24&quot;&gt;24&lt;/a&gt;&lt;/span&gt;                    ;       fc: 5.25&amp;quot; 180K
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n25&quot; name=&quot;n25&quot;&gt;25&lt;/a&gt;&lt;/span&gt;                    ;       fd: 5.25&amp;quot; 360K -or- 8&amp;quot; 500K
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n26&quot; name=&quot;n26&quot;&gt;26&lt;/a&gt;&lt;/span&gt;                    ;       fe: 5.25&amp;quot; 160K -or- 8&amp;quot; 250K -or- 8&amp;quot; 1.2M
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n27&quot; name=&quot;n27&quot;&gt;27&lt;/a&gt;&lt;/span&gt;                    ;       ff: 5.25&amp;quot; 320K
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n28&quot; name=&quot;n28&quot;&gt;28&lt;/a&gt;&lt;/span&gt;    dw     0007h    ; 0016: sectors per FAT
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n29&quot; name=&quot;n29&quot;&gt;29&lt;/a&gt;&lt;/span&gt;    dw     000fh    ; 0018: sectors per track
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n30&quot; name=&quot;n30&quot;&gt;30&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;    dw     0002h    ; 001a: heads
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n31&quot; name=&quot;n31&quot;&gt;31&lt;/a&gt;&lt;/span&gt;    dd 00000000h    ; 001c: reserved
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n32&quot; name=&quot;n32&quot;&gt;32&lt;/a&gt;&lt;/span&gt;    dd 00000000h    ; 0020: reserved
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n33&quot; name=&quot;n33&quot;&gt;33&lt;/a&gt;&lt;/span&gt;    dw     0000h    ; 0024: reserved
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n34&quot; name=&quot;n34&quot;&gt;34&lt;/a&gt;&lt;/span&gt;    db       29h    ; 0026: extended BPB enabled with 0x29 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n35&quot; name=&quot;n35&quot;&gt;35&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n36&quot; name=&quot;n36&quot;&gt;36&lt;/a&gt;&lt;/span&gt;    dd 00000000h    ; 0027: volume serial
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n37&quot; name=&quot;n37&quot;&gt;37&lt;/a&gt;&lt;/span&gt;    db &apos;0123456789a&apos;; 002b: volume label (11 chars)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n38&quot; name=&quot;n38&quot;&gt;38&lt;/a&gt;&lt;/span&gt;    db &apos;FAT12   &apos;   ; 0036: file system ID (8 chars)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n39&quot; name=&quot;n39&quot;&gt;39&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n40&quot; name=&quot;n40&quot;&gt;40&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;boot_code:          ; 003e: boot code
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n41&quot; name=&quot;n41&quot;&gt;41&lt;/a&gt;&lt;/span&gt;    ...
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n42&quot; name=&quot;n42&quot;&gt;42&lt;/a&gt;&lt;/span&gt;empty_space:
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n43&quot; name=&quot;n43&quot;&gt;43&lt;/a&gt;&lt;/span&gt;    times 0200h - 2 - ($ - $$)  db 0    ; fill with &apos;0&apos; until position 01fe
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n44&quot; name=&quot;n44&quot;&gt;44&lt;/a&gt;&lt;/span&gt; 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n45&quot; name=&quot;n45&quot;&gt;45&lt;/a&gt;&lt;/span&gt; boot_sector_signature:
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n46&quot; name=&quot;n46&quot;&gt;46&lt;/a&gt;&lt;/span&gt;    dw    0aa55h    ; 01fe: boot sector signature
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Man kann mit der &lt;code&gt;times N - ($ - $$) db 0&lt;/code&gt; Anweisung aus dem 512 
Byte-Bootsektor auch ein ganzes leeres Diskettenimage machen, und das würde 
dann so enden:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;   ...
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;empty_space:
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;    times 0200h - 2 - ($ - $$)  db 0    ; fill with &apos;0&apos; until position 01fe
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt; 
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt; boot_sector_signature:
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;    dw    0aa55h    ; 01fe: boot sector signature
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;floppy_space:
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;    times 1474560 - ($ - $$)  db 0
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Die &lt;code&gt;1 474 560&lt;/code&gt; Bytes große Datei umspannt eine ganze 1.44MB 3.5” Diskette und 
kann sofort in einer VM mit BIOS Support gebootet werden (sogar in 
MS &lt;a href=&quot;https://de.wikipedia.org/wiki/Hyper-V&quot;&gt;Hyper-V&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Im &lt;code&gt;boot_code&lt;/code&gt; kann man sich dann austoben und bis zu 400 Bytes große 
Programme schreiben. Wer mehr will, muss alles auf weitere Sektoren 
verteilen und diese mit dem &lt;a href=&quot;https://en.wikipedia.org/wiki/INT_13H&quot;&gt;int 13h&lt;/a&gt;
zusätzlich in den Speicher laden.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Vor 25 Jahren war es mein großer Traum per Assembler ein kleines OS bzw.
OS-unabhängiges Programm zu schreiben. Und bis heute kann ich von dem damals
gelernten Wissen profitieren.&lt;/p&gt;

&lt;p&gt;Es ist Schade, dass wir heute auf unseren komplexen Geräten weder Lust noch 
Laune verspüren oder überhaupt die Möglichkeit haben, ein eigenes System 
hochzuziehen. UEFI macht es uns zwar möglich, aber Smartphones und 
Mikrokontroller sind oft so standardfern, dass es wenig bring, sich damit zu
befassen und Google versucht überhaupt uns per Codesignaturen davon abzuhalten,
auf ihren Geräten etwas eigenes ausführen zu lassen.&lt;/p&gt;

&lt;p&gt;Also bleiben uns nur VMs und vielleicht das eine oder andere Altgerät, das
immer noch startfähig ist, um “den Kern” unserer Systeme zu verstehen.&lt;/p&gt;

&lt;p&gt;Ich freue mich jedenfalls, wenn ich ein paar Boot-Assemblerzeilen sehe und
merke dabei, dass die OS-Hersteller damals wie heute auch nur mit Wasser 
kochen.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Sterbende SSDs und M2s?</title>
   <link href="https://www.opengate.at/blog/2024/01/ssd-crash/"/>
   <published>2024-01-14T12:00:00+01:00</published>
   <updated>2024-01-14T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2024/01/ssd-crash</id>
   <category term="hardware" />
   <summary type="text">Die günstigen SSDs
und M.2 Chips aus 
Fernost versprechen beste Qualität und am Anfang stimmt das auch.
Aber nach dem einen oder anderen Jahr bricht das Kartenhaus in sich zusammen.
</summary>
   <content type="html">&lt;p&gt;Die günstigen &lt;a href=&quot;https://de.wikipedia.org/wiki/Solid-State-Drive&quot;&gt;SSDs&lt;/a&gt;
und &lt;a href=&quot;https://de.wikipedia.org/wiki/M.2&quot;&gt;M.2&lt;/a&gt; Chips aus 
Fernost versprechen beste Qualität und am Anfang stimmt das auch.&lt;br /&gt;
Aber nach dem einen oder anderen Jahr bricht das Kartenhaus in sich zusammen.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Die niedrigsten SSD Preise bei AliExpress sehen aktuell etwa so aus:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;128 GB: 10 €&lt;/li&gt;
  &lt;li&gt;256 GB: 15 €&lt;/li&gt;
  &lt;li&gt;512 GB: 30 €&lt;/li&gt;
  &lt;li&gt;1 TB: 50 €&lt;/li&gt;
  &lt;li&gt;2 TB: 100 €&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Wenn man das mit diversen Markenprodukten in ortsansässigen Händlern 
vergleicht, sieht man den Faktor 1.5 bis Faktor 2, besonders bei den 
größeren Kapazitäten. Vor 2 bis 3 Jahren waren noch Faktor zwischen 
2 und 3 ablesbar.&lt;/p&gt;

&lt;p&gt;Folglich kaufte ich damals einige SSDs, M.2 und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Serial_ATA#mini-SATA_(mSATA)&quot;&gt;mSATA&lt;/a&gt; 
Speichermedien und verbaute diese in meinen Testrechnern, aber auch in meiner
regulären Arbeitsmaschine.&lt;/p&gt;

&lt;p&gt;Als dann letztes Jahr mein &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_10&quot;&gt;Windows 10&lt;/a&gt;
“manchmal” extrem lange beim Booten brauchte, dachte ich an 
“dumme Windows-Dienste”, die im Hintergrund Schabernak treiben. Doch dann ging
plötzlich der Explorer nicht mehr auf und nicht mal der Taskmanager reagierte.&lt;br /&gt;
Wenn man aber 10 Minuten lange wartete, normalisierte sich die Situation.&lt;/p&gt;

&lt;p&gt;Ich kaufte einen neuen Marken-M.2-Chip, kopierte erfolgreich alle Daten und
alles war wieder gut.&lt;/p&gt;

&lt;p&gt;Neulich fing das gleich dann auf meinem sekundären Server an, wo ebenso 
eine preiswerte SSD verbaut war.&lt;/p&gt;

&lt;h3 id=&quot;empfehlung-nicht-mehr-als-33-platz-belegen&quot;&gt;Empfehlung: Nicht mehr als 33% Platz belegen!&lt;/h3&gt;

&lt;p&gt;Endbenutzer-SSDs sind heute nur deshalb so günstig, weil wir die internen
Daten(arbeiter) schlecht behandeln und unzureichend bezahlen.&lt;br /&gt;
Natürlich gibt es auch die hoch-stabilen Premiumprodukte, doch da kosten
dann 100 Gigabyte 100 €, wo wir heute eine Terabyte zum gleich Preis erwarten.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;SLC&lt;/code&gt; (Single-Level Cell) heißt die Technik hinter so einem Prämiumprodukt,
denn dort wird jedes Bit in einer eigenen Zelle gespeichert, was jedem Bit
ein Maximum an Produktionsaufwand aber auch Stabilität zusichert.&lt;/p&gt;

&lt;p&gt;Daher hat man schnell die &lt;code&gt;MLC&lt;/code&gt; (&lt;a href=&quot;https://de.wikipedia.org/wiki/MLC-Speicherzelle&quot;&gt;Multi-Level Cell&lt;/a&gt; ) 
Technik erfunden, wo 2 Bits in einer logischen Zelle gespeichert werden. 
Damit kann man doppelt so viel Speicher mit der gleichen Zellenanzahl 
bereitstellen, allerdings sinkt auch die Stabilität und maximale 
Wiederbeschreibbarkeit, da bei einem Schreibzugriff nicht ein Bit sondern
immer beide neu geschrieben werden müssen.&lt;/p&gt;

&lt;p&gt;Mit &lt;code&gt;TLC&lt;/code&gt; (Triple-Level-Cell) haben wir 3 Bits in einer Zelle, und das ist
genau das, was in billigen SSDs eingesetzt wird.
Teilweise kommt auch das neuere &lt;code&gt;QLC&lt;/code&gt; (Quad-Level-Cell) mit 4 Bits pro Zelle
zum Einsatz.&lt;/p&gt;

&lt;p&gt;Die wahre Magie stammt vom Kontrollchip, der bei Schreibzugriffen zuerst
mal alle neuen Bits auf alle leeren Zellen verteilt. Bei &lt;code&gt;TLC&lt;/code&gt; kann man also
33% des Datenträgers mit Hochgeschwindigkeit vollschreiben.&lt;br /&gt;
Danach werden weitere Bits zu den bestehenden Zellen hinzugefügt.&lt;/p&gt;

&lt;p&gt;Und hier (so wird es jedenfalls im Netz behauptet) kommt dann der “billige”
Speicherchip mit der einfacheren (oft auch veralteten) Software ins Wanken.
Datenblöcke und Bits müssen umgeordnet werden und dann blockiert das Medium
eben so lange, bis es mit der internen Arbeit fertig ist.&lt;/p&gt;

&lt;h3 id=&quot;laaaaange-datensicherung&quot;&gt;Laaaaange Datensicherung&lt;/h3&gt;

&lt;p&gt;Ich habe also einen zusätzlichen Kühlkörper auf meine bockigen Billig-SSDs
und -M.2s gepackt, die im Betrieb deutlich heiß wurden, und alle Daten auf 
frische neue Marken-SSDs kopiert (die heute zum Glück billiger geworden sind).&lt;/p&gt;

&lt;p&gt;Die Aktion dauerte ewig, da die Datenraten auf unter 100 KB/s sanken, doch
Datenfehler sind mir bisher keine aufgefallen.&lt;/p&gt;

&lt;p&gt;Ich hatte etwa 70% des Speichers benutzt, also so 350 GB von 500 GB.
Zum Glück stiegen die Geschwindigkeiten auch teilweise wieder in den 10-MB/s
Bereich, denn hätte ich alles mit 100 KB/s kopieren müssen, wäre wohl ein
Jahr oder mehr notwendig gewesen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;Wer billig kauft, kauft teuer.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;meinte mal ein Kollege. Und das stimmt hier wieder … wobei, wenn man die 
Technik kennt, kann man sie auch zielgerichtet einsetzen.
Wenn ich also nur 200 GB von 500 nutze, und immer wieder brav ein &lt;code&gt;TRIM&lt;/code&gt; 
durchlaufen lasse, verteilen sich die Bits ganz gut ohne Blockaden und eine
eine 200 GB SLC Platte ist immer noch deutlich teurer als die 500 TLC 
Variante.&lt;/p&gt;

&lt;p&gt;Die scheinbar defekten SSDs wurden nach der Sicherung gelöscht, ge-TRIM-t
und scheinen jetzt offenbar wieder super zu laufen.&lt;/p&gt;

&lt;p&gt;Ich werde jetzt zwar nicht meine Daily-Business Daten darauf speichern, aber
in Testsystemen für eine Quick&amp;amp;Dirty Linux oder Windows-Installation sind 
die Datenträger allemal gut genug.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>SQLITE EXPLAIN</title>
   <link href="https://www.opengate.at/blog/2024/01/sqlite-explain/"/>
   <published>2024-01-07T12:00:00+01:00</published>
   <updated>2024-01-07T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2024/01/sqlite-explain</id>
   <category term="software" />
   <summary type="text">
  Wie baut man SQL Queries und Indexe so,
dass sie möglichst einfach und 
kurz sind und dabei trotzdem hoch effizient sind?


Es ist häufig eine “Glaubensfrage”, was eine Datenbank wirklich durchführt,
womit man seine Statements “religiös” motiviert absetzt.

Doch da gibt es so ein Kommando, das den Nebel lichten kann…
</summary>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;Wie baut man &lt;a href=&quot;https://de.wikipedia.org/wiki/SQL&quot;&gt;SQL&lt;/a&gt; Queries und Indexe so,
dass sie möglichst einfach und 
kurz sind und dabei trotzdem hoch effizient sind?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Es ist häufig eine “Glaubensfrage”, was eine Datenbank wirklich durchführt,
womit man seine Statements “religiös” motiviert absetzt.&lt;/p&gt;

&lt;p&gt;Doch da gibt es so ein Kommando, das den Nebel lichten kann…
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Wenn man Tabellen per SQL abfragt und die Abfrage etwas komplizierter wird,
und dann auch noch Sortierungen hinzukommen, kann es passieren, dass die
Ausführung bei vielen Daten plötzlich extrem lange braucht.&lt;/p&gt;

&lt;p&gt;Nun führt man Indexe ein und erhofft sich eine Verbesserung, die dann aber
leider ausbleibt.&lt;/p&gt;

&lt;p&gt;Tatsächlich kann es je nach Datenbank einen großen Unterschied ausmachen,
ob man links mit rechts oder umgekehrt vergleicht, oder ob man zuerst sortiert
und dann filtert oder anders herum.&lt;/p&gt;

&lt;p&gt;Ein solches Problem quälte mich neulich in der Firma und ich verstand um’s
Verrecken nicht, warum die benutzte &lt;a href=&quot;https://de.wikipedia.org/wiki/SQLite&quot;&gt;SQLite&lt;/a&gt;
 Datenbank trotz Index so schlechte Antwortzeiten lieferte.&lt;/p&gt;

&lt;p&gt;Wenn man aber ein &lt;code&gt;EXPLAIN QUERY PLAN &lt;/code&gt; vor die eigentliche Abfrage packt,
gibt einem SQLite (und auch so manche andere Datenbank) eine Liste der 
durchgeführten Schritte an.&lt;/p&gt;

&lt;p&gt;Diese Information ist wahrlich Gold wert, denn nun kann man unterschiedliche
Abfrage Varianten lokal testen und sieht sofort, wann und wenn ein Index
genutzt wird und wann nicht.&lt;/p&gt;

&lt;p&gt;Ohne den Query-Plan musste ich Abfragen mit riesigen Datenmengen quasi am
Live-System ausprobieren, um zu sehen, dass etwas nicht OK war.&lt;/p&gt;

&lt;p&gt;In meinem Fall musste ich eine “einfache Query”, die den Index ignorierte,
durch eine etwas kompliziertere ersetzen um das gleiche Ergebnis aber mit
Nutzung eines Index-Boost zu erhalten.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ein Lob auf meinen Kollegen, der mir &lt;code&gt;EXPLAIN QUERY PLAN&lt;/code&gt; in Erinnerung rief!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Mir war gar nicht bewusst, dass es dieses Kommando in den erweiterten 
SQL-Standard geschafft hat und auf vielen Plattformen aushilft.&lt;/p&gt;

&lt;p&gt;Zukünftig werde ich bei neuen Queries immer mal “nachsehen”, ob die Datenbank
meinen Input auch so versteht, wie ich es sehe.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Happy New Year 2024</title>
   <link href="https://www.opengate.at/blog/2024/01/new-year-2024/"/>
   <published>2024-01-01T12:00:00+01:00</published>
   <updated>2024-01-01T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2024/01/new-year-2024</id>
   <category term="general" />
   <summary type="text">Die Welt ist wieder nicht untergegangen … auch in Wien nicht.

In diesem Sinne: Prosit Neujahr!
</summary>
   <content type="html">&lt;p&gt;Die Welt ist wieder nicht untergegangen … auch in Wien nicht.&lt;/p&gt;

&lt;p&gt;In diesem Sinne: Prosit Neujahr!
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Ich lasse es gleich bleiben irgend welche Vorsätze aufzustellen.&lt;br /&gt;
Nachdem ohnehin alle über &lt;a href=&quot;https://de.wikipedia.org/wiki/K%C3%BCnstliche_Intelligenz&quot;&gt;K.I.&lt;/a&gt; 
sprechen, nur damit die eigene fehlende “N.I.” nicht so hart auffällt, warte 
ich mal, ob mir ein Algorithmus sagen kann, wie ich mein Leben besser 
gestalten soll.&lt;/p&gt;

&lt;p&gt;Das neue Jahr fängt für mich super an. Ich habe viele Themen, die mich alle
interessieren, dass ich gar nicht weiß, wo ich anfangen soll.&lt;br /&gt;
Aufgaben gibt es noch und nöcher, egal ob im Beruf oder privat.&lt;/p&gt;

&lt;p&gt;Warum soll man da nicht einfach etwas Vertrauen haben, dass das ein gutes
Jahr werden wird.&lt;/p&gt;

&lt;p&gt;In diesem Sinne nochmal:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Prosit Neujahr!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/new-year.jpg&quot; alt=&quot;New year 2024&quot; /&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Das Jahr 2023</title>
   <link href="https://www.opengate.at/blog/2023/12/year2023/"/>
   <published>2023-12-31T12:00:00+01:00</published>
   <updated>2023-12-31T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2023/12/year2023</id>
   <category term="general" />
   <summary type="text">
  Das Jahr 2023 haben wir jetzt auch geschafft.


Oder man könnte auch sagen:


  Es hat uns geschafft.


</summary>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;Das Jahr 2023 haben wir jetzt auch geschafft.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Oder man könnte auch sagen:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Es hat uns geschafft.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;die-seuche-ist-vorbei&quot;&gt;Die Seuche ist vorbei&lt;/h3&gt;

&lt;p&gt;Nachdem die Jahre 2020, 21 und 22 von Covid-19 und der Pandemie geprägt waren,
verlief 2023 erstmals wieder “normal”, soweit man das überhaupt so sagen kann.&lt;/p&gt;

&lt;p&gt;Öffentliche Veranstaltungen fanden wieder regulär statt, Masken werden nur
noch selten (also nur von aktuell Kranken) getragen und die WHO erklärte die
Seuche im Mai für beendet.&lt;/p&gt;

&lt;p&gt;Während diverse rückwärts gewante Politiker bis heute ihre Opferrolle 
zelebrieren, sich weiterhin eingesperrt fühlen, obwohl dies nur ihrem
beschränkten Verstand geschuldet ist, haben viele leider schon wieder 
vergessen, dass es nur der respektablen Arbeit aller Menschen in der Medizin
und im Gesundheitsbereich zu verdanken ist, dass wir großteils gut 
überlebt haben.&lt;/p&gt;

&lt;p&gt;20 Million Tote und eine Vielzahl von Langzeitgeschädigte machen erst klar,
wie anfällig jeder von uns ist. Das Leben von Nachbarn und Bekannten, denen
ein geliebter Mensch abhanden kommen ist, sieht weiterhin trist aus, und 
so kann ich nur mehr als froh sein, dass es in meiner direkten Familie keine
Todesfälle auf Grund von Corona gegeben hat.&lt;br /&gt;
… die Sache sieht 2 bis 3 Häuser weiter leider schon ganz anders aus.&lt;/p&gt;

&lt;h3 id=&quot;neue-welten&quot;&gt;Neue Welten&lt;/h3&gt;

&lt;p&gt;In meiner neuen Heimat &lt;a href=&quot;https://codeberg.org&quot;&gt;Codeberg&lt;/a&gt; kann das GATE 
Projekt nun wirklich aufblühen und auch öffentlich eingesehen werden.&lt;/p&gt;

&lt;p&gt;Während ich früher primär nur einen Windows-32-bit Build lokal durchgetestet
habe und damit fertig war, nimmt die Anzahl der Linux-Plattformen heute weiter
zu. Jede Codeänderung und neue Abhängigkeit erhöht die Chance eines Fehlers 
und so bin ich froh, dass ich automatische CI Builds für x86, ARMv7 und ARMv8,
sowie unterschiedliche C-Runtimes wie &lt;code&gt;glibc&lt;/code&gt; oder &lt;code&gt;muslibc&lt;/code&gt; ausführen lassen
kann, um Patzer schneller zu finden.&lt;/p&gt;

&lt;p&gt;Ich bin zwar nicht immer glücklich mit dieser zunehmenden Komplexität, 
nehme die Herausforderung aber genere sportlich an.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Das Jahr ist somit abgehagt.&lt;br /&gt;
Einiges wurde erledigt, einiges blieb offen.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Auf ein Neues!&lt;br /&gt;
Aber erst ab morgen.&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>Windows 11 Upgrade</title>
   <link href="https://www.opengate.at/blog/2023/12/win11/"/>
   <published>2023-12-30T12:00:00+01:00</published>
   <updated>2023-12-30T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2023/12/win11</id>
   <category term="software" />
   <summary type="text">Etwas widerwillig erfolgt jetzt die Umstellung meines Hauptsystems auf 
Windows 11. 
Nicht weil es notwendigt ist, sondern weil es gerade möglich ist.

Und außerdem will man ja mit gutem Beispiel vorangehen.
</summary>
   <content type="html">&lt;p&gt;Etwas widerwillig erfolgt jetzt die Umstellung meines Hauptsystems auf 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_11&quot;&gt;Windows 11&lt;/a&gt;. 
Nicht weil es notwendigt ist, sondern weil es gerade möglich ist.&lt;/p&gt;

&lt;p&gt;Und außerdem will man ja mit gutem Beispiel vorangehen.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Das letzte Windows, das ich rein optisch als Bereicherung empfunden habe, 
war tatsächlich Windows 8. Weder 10 noch 11 können mich mit ihren Designs
sonderlich begeistern.&lt;/p&gt;

&lt;p&gt;Es gibt aber neben diversen API-Updates und optionalen Features einen Grund,
mit dem neuen System zu arbeiten: Nämlich um UI Erfahrung für den Support
zu sammeln.&lt;/p&gt;

&lt;p&gt;Wie sehr hasse ich es, wenn mir jemand sagt: Ich habe auf “A” und “B” geklickt,
und dann ist “C” verschwunden, und wenn ich dann bei mir gar kein “B” mehr 
vorfinde. Und schon deshalb muss ich mir angewöhnen, mit dem aktuellen System
im Alltag zu arbeiten, schließlich will auch meine Firma demnächst darauf
umsteigen. (Die haben sich eh recht lange Zeit gelassen.)&lt;/p&gt;

&lt;h3 id=&quot;windows-10-vor-windows-11&quot;&gt;Windows 10 vor Windows 11&lt;/h3&gt;

&lt;p&gt;Da ich auf ein vollständiges Windows 10 vorerst nicht verzichten will, wird
beides installiert. Zuerst kommt ein 64-Bit Windows 10 auf den Anfang einer
leeren Platte, und danach folgt die Windows 11 Installation in einer neuen
Partition.&lt;/p&gt;

&lt;p&gt;Mit dieser Vorgehensweise erkennt das neue Windows stets die ältere 
Parallelinstallation und fügt sie automatisch ins Bootmenü ein.&lt;br /&gt;
Diese Prozedur setze ich seit Beginn des 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Unified_Extensible_Firmware_Interface&quot;&gt;UEFI&lt;/a&gt;
Zeitalters immer ein.&lt;/p&gt;

&lt;p&gt;Und so wie bisher ein Windows 8 “hinter” meinem Windows 10 lief, so
läuft ab jetzt Windows 10 hinter meinem aktuellen Windows 11.&lt;/p&gt;

&lt;h3 id=&quot;ui-bleibt-weiter-furchtbar&quot;&gt;UI bleibt weiter furchtbar&lt;/h3&gt;

&lt;p&gt;Meine &lt;a href=&quot;https://de.wikipedia.org/wiki/Arm-Architektur#Armv8-A_(2011)&quot;&gt;ARM64&lt;/a&gt; 
Geräte haben mich ja schon gut auf Win11 vorbereitet und daher weiß ich 
bereits, welche Registry-Keys zu setzen sind, damit dieses unerträgliche 
Anfänger-Kontextmenü nicht erscheint.&lt;/p&gt;

&lt;p&gt;Doch viele andere Dinge passen mir einfach nicht ins Bild bzw. ins Fenster.
Und das fängt mit den abgerundeten Fensterecken mit den dünnen kaum 
erkennbaren Umrandungen an und endet bei Scrollbars, die fast unbenutzbar 
werden, weil man sie nicht mehr sehen kann.&lt;/p&gt;

&lt;p&gt;Diesen Schwachsinn hatten Linux-Desktops schon vor 10 Jahren eingeführt und 
ich weiß nicht, was ich verbrochen habe, dass ich jetzt auch noch von 
einem kommerziellen Produkt eine solche “Behinderung” vorgesetzt bekomme.&lt;/p&gt;

&lt;p&gt;Das Startmenü ist für Anfänger sicher OK, für mich ist es aber ein Stop-Menü,
weil ich nicht mehr wie in Win10 meine große Anzahl an relevanter Software
übersichtlich ordnen kann.&lt;br /&gt;
Das fiel mir auf meinem ARM64 System nicht so auf, weil ich dort weniger
installiert hatte … doch am Hauptrechner reicht das einfach nicht.&lt;/p&gt;

&lt;p&gt;Einiger positiver Aspekt sind die Tabs im Explorer.&lt;br /&gt;
Eigentlich dachte ich nicht, dass ich die groß brauch werde, aber es ist
wirklich praktisch, wenn im laufenden Betrieb per Klick eine neue
Dateiansicht öffnen kann und leicht hin und herschalten kann.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Die Installation und der eigentliche Betrieb sind OK. Ich rechne immer
mit Problemen, doch hier gab es keine und das muss man lobend erwähnen.&lt;/p&gt;

&lt;p&gt;Aber sich mit dem UI anzufreunden, wird noch Zeit brauchen.&lt;br /&gt;
Nachdem nun fast alle Entwicklungsumgebungen und VMs auf das neue System
übertragen sind, kann ich es voll und ganz nutzen.&lt;/p&gt;

&lt;p&gt;Ja, ein bisschen langsamer als Win10 fühlt es sich an … aber der Eindruck
kann auch täuschen. Ich bin gespannt, wie performant die Maschine in
einem Jahr noch sein wird.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Erinnerungen an Narnia</title>
   <link href="https://www.opengate.at/blog/2023/12/narnia/"/>
   <published>2023-12-24T12:00:00+01:00</published>
   <updated>2023-12-24T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2023/12/narnia</id>
   <category term="general" />
   <summary type="text">Als in den 90ern die deutsch synchronisierte BBC Serie von
Die Chroniken von Narnia
auch bei uns im Fernsehen ausgestrahlt wurde, begründete sie vermutlich den 
Anfang meines Interesses am Fantasy Genre im Allgemeinen.

Heute - in der Spätjugend - erkennt man darin die Nacherzählung von
christlichen Werten gepaart mit europäischen Imperialismus.
</summary>
   <content type="html">&lt;p&gt;Als in den 90ern die deutsch synchronisierte BBC Serie von
&lt;a href=&quot;https://de.wikipedia.org/wiki/Die_Chroniken_von_Narnia:_Der_K%C3%B6nig_von_Narnia_(1988)&quot;&gt;Die Chroniken von Narnia&lt;/a&gt;
auch bei uns im Fernsehen ausgestrahlt wurde, begründete sie vermutlich den 
Anfang meines Interesses am Fantasy Genre im Allgemeinen.&lt;/p&gt;

&lt;p&gt;Heute - in der Spätjugend - erkennt man darin die Nacherzählung von
christlichen Werten gepaart mit europäischen Imperialismus.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Zu Weihnachten entsteht förmlich der Druck die Welt wieder mit den Augen 
vergangener Jahrhunderte zu sehen. Schulklassen studieren Krippenspiele ein,
um sie theatralisch vortragen zu können und dann wird wieder die Geschichte
des “Christ-Kinds” erzählt, welches die Geschenke brachte, bevor Coca Cola
mit Santa Claus quasi das “Apple-Konkurrenzprodukt” besser am Markt 
durchsetzen konnte.&lt;/p&gt;

&lt;p&gt;Über Jahrhunderte haben diese Geschichten besonders die jüngsten unter uns
mit Wertgleichnissen versorgt, um aus Ihnen bessere Menschen zu machen.
Doch auch Eltern hatten so allen Grund für ihren Nachwuchs einmal im Jahr
zwingend eine Zeremonie des Guten abzuhalten.&lt;/p&gt;

&lt;p&gt;Doch mit dem Einsetzen der modernen Medien hat sich diese Tradition zumindest
in unseren Breiten gewandelt.&lt;br /&gt;
Kinder lernen heute mehr von Harry Potter über den Kampf von Gut gegen Böse, 
als von Jesus Christus und dessen “Abenteuern im Morgenland”.&lt;/p&gt;

&lt;h3 id=&quot;die-geschichte-von-narnia&quot;&gt;Die Geschichte von Narnia&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/C._S._Lewis&quot;&gt;C.S. Lewis&lt;/a&gt; brachte mit den Büchern
rund um das “Zauberland” Narnia eine fiktive Welt hervor, die ich damals
immer wieder und wieder auf VHS-Kasette aufgezeichnet ansah.&lt;br /&gt;
Ich liebte es, wie vier Kinder durch “ihre reinen Herzen” zu den besseren
Königinnen und Königen eines Landes wurden, in dem Tiere sprechen konnten und
Magie jede Handlung durchzog.&lt;/p&gt;

&lt;p&gt;Es stand für mich im krassen Gegensatz zu den trüben Erzählungen aus dem
Religionsunterricht, wo von einem Prädiger die Rede war, der umherzog und 
Menschen bekehrte.&lt;/p&gt;

&lt;p&gt;Dann las ich über C.S. Lewis christliche Überzeugung und dass er 
diese in seine Werke hatte einfließen lassen.&lt;/p&gt;

&lt;p&gt;Und wenn ich heute die alte Serie nochmals ansehe, erkenne ich eine
Bibelszene nach der anderen.
Am Ende entpuppt sich auch der Löwe Aslan, der König der Tiere, als Jesus
in anderer Form, der geheimnisvoll meint:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;In eurer Welt habe ich einen anderen Namen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Und somit erhält jedes Opfer, das in den Handlungen rund um Narnia erbracht wurde,
eine Äquivalent aus dem neuen Testament.&lt;/p&gt;

&lt;p&gt;Ohne es zu Wissen hatte ich einen Teil Bibel gelesen … nur eben 
“ein bisschen anders erzählt”.&lt;/p&gt;

&lt;h3 id=&quot;das-bedürfnis-nach-frieden-und-führung&quot;&gt;Das Bedürfnis nach Frieden und Führung&lt;/h3&gt;

&lt;p&gt;Und heute würde ich mir diese kindliche Sichweise gerne wieder herbeiwünschen.
4 Kinder, die durch ihren guten Willen die Welt retten. Sie entmachten die
Übeltäter, die allesamt gierige alte Menschen sind und nur an ihrer Macht
interessiert sind.&lt;/p&gt;

&lt;p&gt;Es ist beeindruckend, wie schnell in der Welt von Narnia alle von den 
Kinderkönigen überzeugt sind und sofort für eben diese in die Schlacht ziehen
… natürlich nur um Gutes durchzusetzen.&lt;/p&gt;

&lt;p&gt;Ja, plötzlich ist man sich sicher: Für das Gute darf, nein, muss man zu den
Waffen greifen, denn eine solche Schlacht ist schließlich von Gott gewollt.&lt;/p&gt;

&lt;p&gt;An der Stelle bleibt einem dann doch noch der Bissen im Halse stecken, wenn
man bisher glaubte eine biblische Geschichte vor sich zu haben.
Denn es ist gefährlich Politik mit Religion in dieser Weise zu vermischen.
Und es ist falsch die Begehren von Menschen mit Begriffen wie Gut und Böse
absolut gleichzusetzen.&lt;/p&gt;

&lt;p&gt;Gerne hätte ich gesagt:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Narnia, Harry Potter und vielleicht noch Herr der Ringe sind 
Bibelgeschichten neu erzählt.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Doch das stimmt nicht. Eher könnte man sagen:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Es sind Bibelgeschichten neu verdreht.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ich glaube, dass WIR beides brauchen:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Modernere Heldengeschichten&lt;/li&gt;
  &lt;li&gt;Und Klassische Religionsgleichnisse.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Des Rätsels Lösung liegt in der Befassung mit beiden.
Man sollte die ersten Bilder dieser Geschichten reißerisch auf sich wirken
lassen, und danach darüber nachdenken, was der/die Author/en ausdrücken wollten,
welche Werte sie uns vermitteln wollten.&lt;/p&gt;

&lt;p&gt;Hat heute vor 2000 Jahren wirklich eine “Jungfrau” den Heiland in einem Stall in 
Betlehem geboren, der durch Handauflegung Kranke heilen konnte und für alle Sünde
am Kreuz gestorben ist?
Oder sollen wir uns vielleicht nur daran erinnen, dass anderen zu helfen der 
höchste Wert im Leben sein sollte?&lt;/p&gt;

&lt;p&gt;Wie auch immer … es ist jedenfalls eine schön erzählbare Geschichte.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Frohe Weihnachten an alle!&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>Am Ende ist C doch am besten</title>
   <link href="https://www.opengate.at/blog/2023/12/more-c/"/>
   <published>2023-12-17T12:00:00+01:00</published>
   <updated>2023-12-17T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2023/12/more-c</id>
   <category term="devel" />
   <summary type="text">So sehr ich meine Ausflüge ins ZIG
Land liebe, so sehr freut es mich, wenn ich dann doch wieder in die C/C++ 
Welt zurück nach Hause kommen kann.

Denn dort ist es eben doch am schönsten, und Code am besten schreibbar.
</summary>
   <content type="html">&lt;p&gt;So sehr ich meine Ausflüge ins &lt;a href=&quot;https://de.wikipedia.org/wiki/Zig_(Programmiersprache)&quot;&gt;ZIG&lt;/a&gt;
Land liebe, so sehr freut es mich, wenn ich dann doch wieder in die C/C++ 
Welt zurück nach Hause kommen kann.&lt;/p&gt;

&lt;p&gt;Denn dort ist es eben doch am schönsten, und Code am besten schreibbar.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Es gibt viele semantische und “optische” Gründe, warum moderne Sprachen wie
&lt;code&gt;ZIG&lt;/code&gt; dem klassischen C überlegen sind.&lt;/p&gt;

&lt;p&gt;Doch wenn ich an mein Kernziel des GATE Projektes denke, wo die Unterstützung
von möglichst vielen Zielplattformen oberstes Ziel ist, dann stelle ich fest,
dass es eben nur in C und C++ möglich ist, hier effiziert voranzukommen.&lt;/p&gt;

&lt;h3 id=&quot;beispiel-makros&quot;&gt;Beispiel Makros&lt;/h3&gt;

&lt;p&gt;Ja, Makros waren oft wie eine Seuche in der IT Geschicht. Einmal davon befallen,
wird ein Projekt schnell unwartbar. Unleserlich ist es dann sowieso schon.&lt;/p&gt;

&lt;p&gt;Aus diesem Grund entschied man sich in ZIG, ohne Makros auszukommen.&lt;/p&gt;

&lt;p&gt;Nun sehe ich mir die WinAPI mit ihrer ANSI- und Unicode Variante an und muss
feststellen, dass man das nur mit Makros effizient gelöst bekommt, wenn man
beide Varianten unterstützen will.&lt;/p&gt;

&lt;p&gt;Ob man jetzt 8-bit oder 16-bit Strings erzeugen will, oder automatisch ein 
“A” oder “W” ans Ende eines Funktionsnamen schreibt, lässt sich über ein Makro
“dynamisch” zusammenbauen, während man ohne Makros oft Code doppelt 
ausimplementieren muss.&lt;/p&gt;

&lt;p&gt;(ZIG’s &lt;code&gt;comptime&lt;/code&gt; kann das zwar auch lösen, braucht aber mehr Codeaufwand
um Ziel zu kommen.)&lt;/p&gt;

&lt;h3 id=&quot;beispiel-nullpointer&quot;&gt;Beispiel Nullpointer&lt;/h3&gt;

&lt;p&gt;Nullpointer sind der Grund für jede Menge Probleme und Abstürze. 
In &lt;code&gt;ZIG&lt;/code&gt; sind solche Pointer erst mal verboten, dafür gibt es jedoch
&lt;code&gt;Optional&lt;/code&gt;s, die man immer explizit prüfen muss.&lt;br /&gt;
Das erzeugt wirklich sicheren Code.&lt;/p&gt;

&lt;p&gt;Es kann aber auch kontraproduktiv sein, wenn die Sprache keine Möglichkeit 
bereitstellt, dass man auf einen Zustand vertrauen kann.&lt;br /&gt;
Wenn C-Pointer permanent auf Null und Nicht-Null Inhalt geprüft werden müssen,
kann daraus kein effizienter Code entstehen.
Das kann man zwar innerhalb der eigenen Funktionen gut optimieren, doch 
wenn es um Schnittstellen wie z.B.: Funktionspointer geht, wird das mühsam.&lt;/p&gt;

&lt;p&gt;Wenn eine Schnittstellendefinition einen Pointer aus “Mandatory” definiert,
dann darf bzw. muss man auch darauf vertrauen können, dass die Gegenseite
es richtig macht.&lt;/p&gt;

&lt;p&gt;Ein anderer Punkt wären dann Plattformen, die “Null” nicht als ungültig
definieren. In x86-16 und somit auch in DOS liegt an Adresse &lt;code&gt;Null&lt;/code&gt; 
die Interrupt-Vektor-Tabelle, und wer einen Debugger oder Code-Guard schreibt,
muss eben auch auf diese Adresse schreiben dürfen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Unabhängig von den tollen Verbesserungen, die neue Sprachen einführen, 
verbauen sie durch Ihre Architektur aber manchmal auch die Möglichkeit, 
auf speziellen Systemen korrekt zu funktionieren.&lt;br /&gt;
Das bedeutet wir verlieren somit den Support auf diesen Systemen und
verringern damit die Bandbreite der Zielplattformen.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;C&lt;/code&gt; hat daher ganz bewusst viele Bereiche als “undefiniert” eingestuft, damit
die Sprache für wirklich “alles” offen ist. Und ja, das bedeutet auch, dass
man sich in den Fuß schießen kann.&lt;br /&gt;
Aber wir würden ja auch nicht Messer weltweit abschaffen, nur weil es möglich
ist, sich damit umzubringen.&lt;/p&gt;

&lt;p&gt;Die Flexibilität von C wird heute leider nicht mehr als Vorteil gesehen,
sondern bei Fehlern immer als Nachteil ausgelegt.&lt;/p&gt;

&lt;p&gt;Tatsächlich brauchen wir jedoch mehr Programmierer, die ihren Code verstehen.
Auch wenn ich viele Features aus neuen Sprachen schätze, so kann man nicht
alle Probleme lösen, indem man stets neue Programmiersprachen erfindet, 
die Bandbreiten nur durch Verbote einschränken.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Die Welt braucht mehr CONST</title>
   <link href="https://www.opengate.at/blog/2023/12/more-const/"/>
   <published>2023-12-16T12:00:00+01:00</published>
   <updated>2023-12-16T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2023/12/more-const</id>
   <category term="devel" />
   <summary type="text">Wenn ich von RUST 
und vor allem von ZIG 
eines gelernt habe, dann die Notwendigkeit const häufiger einzusetzen.

Denn moderne Sprachen meckern sofort, wenn wir Variablen deklarieren,
die dann nur wie Konstanten benutzt werden.
</summary>
   <content type="html">&lt;p&gt;Wenn ich von &lt;a href=&quot;https://de.wikipedia.org/wiki/Rust_(Programmiersprache)&quot;&gt;RUST&lt;/a&gt; 
und vor allem von &lt;a href=&quot;https://de.wikipedia.org/wiki/Zig_(Programmiersprache)&quot;&gt;ZIG&lt;/a&gt; 
eines gelernt habe, dann die Notwendigkeit &lt;code&gt;const&lt;/code&gt; häufiger einzusetzen.&lt;/p&gt;

&lt;p&gt;Denn moderne Sprachen meckern sofort, wenn wir Variablen deklarieren,
die dann nur wie Konstanten benutzt werden.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;variablen-die-nicht-variieren&quot;&gt;Variablen, die nicht variieren&lt;/h3&gt;

&lt;p&gt;Wenn wir vom Compiler eine Variable verlangen, dann sollten wir das nur tun,
weil wir in dessen “Lagerraum” unterschiedliche Dinge aufbewahren wollen.&lt;br /&gt;
Wir erhalten den notwendigen Platz und auch “Logistik”, die den Platz 
verwaltet und an unsere Bedürfnisse anpasst.&lt;/p&gt;

&lt;p&gt;Konstanten hingegen sind wie Verkehrsschilder. Sie werden einmal produziert und
aufgestellt und brauchen danach keine “Wartung” mehr.&lt;/p&gt;

&lt;p&gt;Ein effizientes Programm weiß also genau, wo es veränderbare Informationen
braucht, und wo fixe Daten ausreichen.&lt;/p&gt;

&lt;p&gt;In der Praxis sieht das aber anders aus, und so liegt fast alles in Variablen,
die dann auch noch “versehentlich” verändert werden und der Grund für 
Fehlverhalten sind.&lt;/p&gt;

&lt;h3 id=&quot;zig-sagt-konstante-variablen-sind-ein-fehler&quot;&gt;ZIG sagt: Konstante Variablen sind ein Fehler&lt;/h3&gt;

&lt;p&gt;Der ZIG Code&lt;/p&gt;

&lt;div class=&quot;language-zig highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;const std = @import(&amp;quot;std&amp;quot;); 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;const builtin = @import(&amp;quot;builtin&amp;quot;);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;pub fn main() void { 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  var v = 42;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;  std.debug.print(&amp;quot;Hello, {}!&amp;quot;, .{ v }); 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;führt zum Fehler:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;error: variable of type ‘comptime_int’ must be const or comptime&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Unser &lt;code&gt;v&lt;/code&gt; ist keine Variable und ändert sich nie. Es ist eigentlich eine
Konstante und ZIG lässt uns den Code nur durchgehen, wenn wir daraus ein&lt;br /&gt;
&lt;code&gt;const v = 42;&lt;/code&gt; machen.&lt;/p&gt;

&lt;p&gt;Jetzt kann der Compiler den Zielcode perfekt optimieren, denn er braucht keinen
Speicher für &lt;code&gt;v&lt;/code&gt; reservieren und kann somit die CPU Register ausreizen.&lt;/p&gt;

&lt;p&gt;In C würden viele Entwickler folgendes hintippen:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; main() {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; v = &lt;span style=&quot;color:#00D&quot;&gt;42&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  printf(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Hello, %d&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, v);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Aber auch hier würde ein&lt;br /&gt;
&lt;code&gt;const int v = 42&lt;/code&gt; oder noch besser ein&lt;br /&gt;
&lt;code&gt;static const int v = 42;&lt;/code&gt; zu mehr Optimierungen führen.&lt;br /&gt;
Doch da uns der Compiler dazu nicht zwingt, bleibt die Variable bestehen.&lt;/p&gt;

&lt;h4 id=&quot;wieso-behaupten-rust-und-zig-teils-besser-als-c-zu-sein&quot;&gt;Wieso behaupten RUST und ZIG teils besser als C zu sein?&lt;/h4&gt;

&lt;p&gt;Tja … es ist nicht die Sprache, sondern der Programmierstil, der gut- oder
schlecht-optimierten Code zur Folge hat.&lt;/p&gt;

&lt;p&gt;Die Unterscheidung von Variablen und Konstanten sollte also auch in C Code
von hoher Priorität sein. So erhalten wir dann nämlich Ergebnisse, die keine
andere Sprache mehr übertreffen kann.&lt;br /&gt;
Es ist natürlich nur ein erster Schritt, auf den viele andere wohlüberlegt
folgen müssen.&lt;/p&gt;

&lt;h3 id=&quot;fazit-weitere-sprachen-lernen-hilft&quot;&gt;Fazit: Weitere Sprachen lernen hilft!&lt;/h3&gt;

&lt;p&gt;Je mehr Sprachen man sich ansieht, um so mehr lernt man auch über die 
“Muttersprache” (also C).&lt;/p&gt;

&lt;p&gt;Ich würde mir wünschen, dass wir mehrere Level der Codeverifizierung in C
Compilern hätten. Die Feststellung, dass Variablen als Konstanten genutzt
werden, wäre ein solches Feature.&lt;/p&gt;

&lt;p&gt;Natürlich könnte man das über “Warnings-as-Errors” Optionen auch umsetzen,
aber es ist eben nicht das gleiche, wie eine zwingend per Standard 
vorgeschrieben Var-Konstanten-Prüfung.&lt;/p&gt;

&lt;p&gt;Doch im Gegensatz zu &lt;code&gt;ZIG&lt;/code&gt; und &lt;code&gt;RUST&lt;/code&gt; sollte &lt;code&gt;C&lt;/code&gt; sich immer die Option 
vorbehalten, dass man ein solches Feature auch abschalten können muss.&lt;/p&gt;

&lt;p&gt;Oder wie man gerne sagt:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ein Feature, das man nicht abschalten kann, ist ein Bug.&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>Das Ende von 32-bits</title>
   <link href="https://www.opengate.at/blog/2023/12/end-of-32/"/>
   <published>2023-12-09T12:00:00+01:00</published>
   <updated>2023-12-09T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2023/12/end-of-32</id>
   <category term="hardware" /><category term="software" />
   <summary type="text">Mit Windows 95 wurde
das 32-bit Zeitalter im PC Bereich eingeläutet, obwohl es schon länger da war.
Und mit Windows 11 wird diese 
Glocke nun schrittweise abmontiert.

Solche Schritte sind logisch, haben aber dennoch einige Konsequenzen.
</summary>
   <content type="html">&lt;p&gt;Mit &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_95&quot;&gt;Windows 95&lt;/a&gt; wurde
das 32-bit Zeitalter im PC Bereich eingeläutet, obwohl es schon länger da war.
Und mit &lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_11&quot;&gt;Windows 11&lt;/a&gt; wird diese 
Glocke nun schrittweise abmontiert.&lt;/p&gt;

&lt;p&gt;Solche Schritte sind logisch, haben aber dennoch einige Konsequenzen.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Der Übergang von 16-bit zu 32-bit war eigentlich relativ schnell 
abgeschlossen. Während im Jahr 1995 noch weiter Software für die 16-bit Welt
entwickelt wurde, war im Jahr 2000 bereits so gut wie alles verschwunden.
Außerdem fand in unseren Breiten die Büro-Digitalisierung gefühlt erst
kurz vor dem Jahr 2000 statt.&lt;/p&gt;

&lt;p&gt;Linux war nie auf 16-bit Systemen lauffähig und musste sich daher auch nie 
um einen solchen Migrationspfad kümmern.&lt;br /&gt;
Und was Windows anbelangt, so war die 16-Bit API eher ein Alptraum und wurde
mit dem Wechsel zu 32-Bit besser und stabiler … wenn gleich auch nicht 
gerade übersichtlicher.&lt;/p&gt;

&lt;p&gt;Doch bereits in den Jahren 2003/2004 kam mit AMD64 die echte 64-bit Einführung,
die Intel mit IA64 (Itanium) schwer verbockt hatte.&lt;br /&gt;
Das war übrigens die große Chance für Linux, dessen Entwicklerteam sofort an
der 64-Bit Portierung arbeitete und zügig erste Demos anbot.&lt;br /&gt;
Microsoft braucht bis ins Jahr 2005 um mit Windows Server 2003-x64 ein 
alltagstaugliches Produkt einzuführen und Visual Studio 2005 für die 
Entwicklung bereitzustellen.&lt;/p&gt;

&lt;h3 id=&quot;glaube-64-bit-braucht-keiner&quot;&gt;Glaube: 64-Bit braucht keiner&lt;/h3&gt;

&lt;p&gt;Wenn man von Server-Anwendungen wie großen Datenbanken ansieht, lohnte es sich
für Entwickler überhaupt nicht, 64-Bit Kompilate herzustellen.&lt;br /&gt;
Denn etwa bis ins Jahr 2014 wurden reine Intel-32 Prozessoren hergestellt, 
die den 64-Bit-Befehlssatz nicht ausführen konnten und daher zwingend mit 
32-Bit Software betrieben werden mussten.&lt;/p&gt;

&lt;p&gt;Man musste also entweder zwei Varianten der eigenen Software bereitstellen 
und pflegen, oder man blieb bei 32-Bits und vertraute auf Microsofts
Kompatibilität, die allen 32-Bit Programmen gestattete, auch auf allen
X64 Betriebssystemen zu laufen.&lt;br /&gt;
Selbst die Tatsache, dass Windows Server seit 2008R2 gar keine 64-bit Variante
mehr besaß, konnte den Desktop Markt nur langsam beeinflussen.&lt;/p&gt;

&lt;p&gt;Auch alle Linux Distributionen lieferten 32-Bit Bibliotheken in den 64-Bit 
Varianten mit aus, um die Ausführung älterer Software zu gewährleisten.
Gleichsam war Linux durch die Distributoren meist von Anfang an auf dem
neuen X64 Stand, da hier nicht die originalen Entwickler, sondern die 
Distributoren die finalen Programme zusammen kompilierten.&lt;/p&gt;

&lt;p&gt;Ich glaube sowohl bei Debian wie auch OpenSuse damals gelesen zu haben,
dass man 32-bit Varianten nur dann nehmen soll, wenn man nicht weiß,
was die eigene CPU kann … was bei Linux-Fans selten der fall war.&lt;/p&gt;

&lt;h3 id=&quot;das-ende-der-x86-netbooks-und-tablets&quot;&gt;Das Ende der X86 Netbooks und Tablets&lt;/h3&gt;

&lt;p&gt;Die ersten Windows Tablets nach 2010 waren meist 32-bittig und kamen mit 
1 GB RAM auf den Markt, stiegen dann auf 2 GB. Jetzt kann man zwar ein 
Windows (8 oder 10) noch mit 2 GB RAM betreiben, aber effektiv nutzen kann 
man es nicht. Besonders Webanwendungen sind  dafür heute viel zu komplex.&lt;br /&gt;
Und als Intel aufhörte, 32-bit-only-Prozessoren zu bauen, und jedes System 
mit einem 64-Bit OS ausgestattet war, begann langsam die Erkenntnis 
umzugreifen, dass neue Apps nur noch 64-Bit sein müssen.&lt;/p&gt;

&lt;p&gt;Am Ende war und ist es Windows 11, dass uns jetzt gar keine Möglichkeit mehr
lässt, auf einer only-32-bit Plattform laufen zu können.&lt;/p&gt;

&lt;h3 id=&quot;32-bit-kompatibilität-schwindet&quot;&gt;32-Bit Kompatibilität schwindet.&lt;/h3&gt;

&lt;p&gt;Windows wird vermutlich noch lange den 32-Bit Layer mitführen und alle 
alten Programme damit betreiben können, doch bereits seit Windows Embedded 7 
kann man das 32-bit WOW (Windows on Windows) Subsystem entfernen. Auch WinPE
kennt keine Kompatibilität und führt nur “sein” Binary-Format aus.&lt;/p&gt;

&lt;p&gt;Unter Linux sieht die Sache ähnlich aus, wenn man an Docker denkt.&lt;br /&gt;
Niemand stellt hier ein 32-Bit Image bereit (außer es ist ein ARM-32-bit Image
für den Raspberry PI).&lt;/p&gt;

&lt;p&gt;Das führt nun dazu, dass neue Software generell nur noch für 64-Bit Systeme
kompiliert wird.&lt;br /&gt;
Im Fall von Windows finden wir heute zwar immer noch 32-bit Kompilate vor,
doch auch hier setzte die Trendumkehr schon vor Jahren ein.&lt;br /&gt;
Bitcoin-Core ist seit 8 Jahren 64-bit-only und Ähnliches ist auch 
für andere Produkte wahr.&lt;/p&gt;

&lt;p&gt;Am Extremsten war das aber bei den Treibern zu beobachten. Die aktuellen
Treiber für Intel-Grafik-Chips liegen auch seit 2018 nur noch als 64-Bit
Varianten vor. Man könnte die zwar auf 32-Bit portieren, doch das tut 
einfach niemand mehr.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ich verbinde mit 32-Bits einfach viel Nostalgie und finde es Schade, dass 
nicht beide Bitbreiten parallel weiterexistieren können. 
Doch rein rational war der Schritt weg von 32-Bits hin zu 64-bits mehr
als überfällig.&lt;/p&gt;

&lt;p&gt;Hier haben &lt;a href=&quot;https://de.wikipedia.org/wiki/.NET_(Plattform)&quot;&gt;dotNET&lt;/a&gt; und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Java_(Programmiersprache)&quot;&gt;JAVA&lt;/a&gt; Entwickler 
einen riesigen Vorteil, denn dort kümmern sich ihre Laufzeitumgebungen 
darum, dass Code automatisch zur neuersten Variante hochkompiliert wird.&lt;/p&gt;

&lt;p&gt;Doch für die native Entwicklung bedeutet das, dass wir entweder schon 
umgestellt sind, oder sofort mit der 64-Bit Umstellung starten müssen.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>ZIG als C/C++ Toolchain</title>
   <link href="https://www.opengate.at/blog/2023/12/zig-toolchain/"/>
   <published>2023-12-03T12:00:00+01:00</published>
   <updated>2023-12-03T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2023/12/zig-toolchain</id>
   <category term="devel" />
   <summary type="text">Das beste an der Programmiersprache ZIG 
ist, dass sein Compiler Toolkit gleichzeitig auch ein C Compiler ist. Das 
bedeutet, man kann ZIG auch dazu nutzen, das eigene C Projekt vollständig 
zu kompilieren.

Und mit einer kleinen Toolchain Datei für CMake 
wird daraus der beste und plattform-unabhängigste Compiler überhaupt.

</summary>
   <content type="html">&lt;p&gt;Das beste an der &lt;a href=&quot;https://de.wikipedia.org/wiki/Zig_(Programmiersprache)&quot;&gt;Programmiersprache ZIG&lt;/a&gt; 
ist, dass sein Compiler Toolkit gleichzeitig auch ein C Compiler ist. Das 
bedeutet, man kann &lt;code&gt;ZIG&lt;/code&gt; auch dazu nutzen, das eigene C Projekt vollständig 
zu kompilieren.&lt;/p&gt;

&lt;p&gt;Und mit einer kleinen Toolchain Datei für &lt;a href=&quot;https://de.wikipedia.org/wiki/CMake&quot;&gt;CMake&lt;/a&gt; 
wird daraus der beste und plattform-unabhängigste Compiler überhaupt.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Machen wir es kurz.&lt;br /&gt;
Hier ist sie, meine Toolchain-Datei für ZIG:&lt;/p&gt;

&lt;div class=&quot;language-cmake highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;set(target_id x86_64-linux-gnu)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;set(CMAKE_C_COMPILER zig cc)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;set(CMAKE_C_COMPILER_AR zig ar)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;set(CMAKE_C_COMPILER_RANLIB zig ranlib)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;set(CMAKE_C_COMPILER_TARGET ${target_id})
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;set(CMAKE_CXX_COMPILER zig c++)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;set(CMAKE_CXX_COMPILER_AR zig ar)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;set(CMAKE_CXX_COMPILER_RANLIB zig ranlib)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;set(CMAKE_CXX_COMPILER_TARGET ${target_id})
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Es bedeutet einfach, dass wenn man die &lt;code&gt;zig&lt;/code&gt; EXE mit dem Parameter
&lt;code&gt;cc&lt;/code&gt; oder &lt;code&gt;c++&lt;/code&gt; aufruft, hat man den C bzw. C++ Compiler-Teil vor sich,
und das ist aktuellen eine LLVM (CLang) Variante, die zusammen mit Zig
und inklusive vieler Runtime-Implementierungen für alle gängigen 
Betriebssysteme geliefert wird.&lt;/p&gt;

&lt;p&gt;Man braucht also CMake nur beizubringen, dass &lt;code&gt;zig cc&lt;/code&gt; der C Compiler ist,
und sämtliche anderen Compiler Flags werden dann wie für Clang üblich
ermittelt.&lt;/p&gt;

&lt;p&gt;Die &lt;code&gt;target-id&lt;/code&gt; konfiguriert dann noch die gewünschte Zielplattform und
schon läuft der Build durch.&lt;/p&gt;

&lt;h3 id=&quot;problem-bibliotheken&quot;&gt;Problem: Bibliotheken&lt;/h3&gt;

&lt;p&gt;Naja … ganz so perfekt läuft es vielleicht doch nicht immer. 
Denn wenn man viele Fremdbibliotheken benötigt, dann sind die nicht zwingend
an der richtigen Stelle (aus Sicht des &lt;code&gt;ZIG&lt;/code&gt; Compilers).&lt;/p&gt;

&lt;p&gt;Soll heißen: Wenn ich z.B.: systemweit in Debian einen Cross-Compile Umgebung 
eingerichtet habe&lt;br /&gt;
(z.B. mit &lt;code&gt;dpkg --add-architecture armhf&lt;/code&gt; und &lt;code&gt;apt install XXX:armhf&lt;/code&gt;),
dann findet mein Compiler die Bibliotheken von selbst.&lt;br /&gt;
Bei einer lokalen &lt;code&gt;ZIG&lt;/code&gt;-Installation sind diese Libs nicht vorhanden, und selbst
wenn sie im System vorhanden sind, dann muss man deren Pfade erst mal dem
Compiler bzw. Linker explizit mitteilen.&lt;/p&gt;

&lt;p&gt;Hier könnten andere Build- und Paketmanager durchaus hilfreich sein, aber
da stehe ich selbst auch noch am Anfang.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;ZIG rulez!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;hätte man früher unaufgefordert in jedes Forum gepostet.&lt;/p&gt;

&lt;p&gt;Ich bin dezent beeindruckt, dass den ZIGlings gelungen ist, was den anderen
Compilerherstellern bisher nicht geglückt ist:&lt;br /&gt;
Nämlich einen C Compiler samt Cross-Umgebung für alle Plattform auf allen
Plattformen bereitzustellen.&lt;/p&gt;

&lt;p&gt;Hier zahlt sich die 100MB+ Installation echt aus, weil eben alle Targets
samt unterschiedlichen C-Runtimes enthalten sind.&lt;/p&gt;

&lt;p&gt;Wer also im klassischen Unix-Stil kleine effiziente Tools schreiben will, 
hat paradoxerweise mit &lt;code&gt;ZIG&lt;/code&gt; den besten C-Compiler in seinen Händen.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Externer Stack in Watcom</title>
   <link href="https://www.opengate.at/blog/2023/12/external-stack/"/>
   <published>2023-12-02T12:00:00+01:00</published>
   <updated>2023-12-02T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2023/12/external-stack</id>
   <category term="devel" />
   <summary type="text">Während Windows und Linux interne Funktionen für das Zusammenstellen von
Koroutinen anbieten, lässt uns DOS 
diese Arbeit selber machen.

Zumindest dachte ich das, doch meine Assembler-Künste versagten stets und 
ließen meine DOSBox Sitzungen sofort einfrieren.

Spoiler: Ich war gar nicht schuld!
</summary>
   <content type="html">&lt;p&gt;Während Windows und Linux interne Funktionen für das Zusammenstellen von
Koroutinen anbieten, lässt uns &lt;a href=&quot;https://de.wikipedia.org/wiki/MS-DOS&quot;&gt;DOS&lt;/a&gt; 
diese Arbeit selber machen.&lt;/p&gt;

&lt;p&gt;Zumindest dachte ich das, doch meine Assembler-Künste versagten stets und 
ließen meine DOSBox Sitzungen sofort einfrieren.&lt;/p&gt;

&lt;p&gt;Spoiler: Ich war gar nicht schuld!
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Während in einer 64 KByte &lt;code&gt;.com&lt;/code&gt; Datei alle 3 Segmente (Code, Data, Stack) in
einem zusammenfallen, können &lt;code&gt;.exe&lt;/code&gt; Programme im Large-Modus Code und
Daten auf mehrere Segmente verteilt werden und die Aufrufe und Zugriffe 
erfolgen über &lt;code&gt;FAR&lt;/code&gt; Calls.&lt;/p&gt;

&lt;p&gt;Nur das Stack-Segment bleibt ein und das selbe, weil man sich ohnehin nicht
vorstellen konnte, dass jemand mehr als 64 KByte auf den Stack packen wollen
würde.&lt;/p&gt;

&lt;p&gt;Will ich nun aber ein bisschen kooperatives Multitasking etablieren, so dachte 
ich, brauche ich einfach nur ein neues Segment von DOS allokieren lassen und
über ein paar Assemblerzeilen die Ausführung dort weiterlaufen zu lassen.&lt;/p&gt;

&lt;p&gt;Zwar ist es schon etwas schwieriger mit den wenigen 16-bit Registern die 
notwendigen Daten im Prozessor zu halten um alles korrekt wechseln zu können,
doch ich dachte, ich hätte es schon gelöst.&lt;br /&gt;
Trotzdem schlugen alle meine Tests mit eingefrorenen Bildschirmen oder
Stack-Korruptionen fehl.&lt;/p&gt;

&lt;h3 id=&quot;der-compiler-muss-bescheid-wissen&quot;&gt;Der Compiler muss Bescheid wissen!&lt;/h3&gt;

&lt;p&gt;Nach langem hin und her suchen, fand ich zum Glück den entscheidenden 
Eintrag in der OpenWatcom Compiler-Doku.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;code&gt;zu&lt;/code&gt;: do not assume that &lt;code&gt;SS&lt;/code&gt; contains segment of &lt;code&gt;DGROUP&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Im Langtext heißt es:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The &lt;code&gt;zu&lt;/code&gt; option relaxes the restriction that the SS register contains the 
base address of the default data segment, “DGROUP”. Normally, all data 
items are placed into the group “DGROUP” and the SS register contains the 
base address of this group. When the “zu” option is selected, the SS 
register is volatile (assumed to point to another segment) and any global
data references require loading a segment register such as DS with the base
address of “DGROUP”.&lt;br /&gt;
(16-bit only) This option is useful when compiling routines that are to be 
placed in a Dynamic Link Library (DLL) since the SS register points to the 
stack segment of the calling application upon entry to the function.&lt;br /&gt;
The macro __SW_ZU will be predefined if “zu” is selected.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Das Stack-Segment, das wir vom Compiler am Anfang aufgesetzt bekommen, enthält
also “mehr” als nur den Stack und wenn wir uns eigene Stacks schaffen, fehlt
das und führt zu Folgefehlern.&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;CMake&lt;/code&gt; musste ich also noch etwas wie:&lt;/p&gt;

&lt;div class=&quot;language-cmake highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;set(CMAKE_C_FLAGS &amp;quot;${CMAKE_C_FLAGS} -zu&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;set(CMAKE_CXX_FLAGS &amp;quot;${CMAKE_CXX_FLAGS} -zu&amp;quot;)
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;oder moderner&lt;/p&gt;

&lt;div class=&quot;language-cmake highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;add_compile_options(&amp;quot;-zu&amp;quot;)
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;einfügen und schon funktionierten meine Callstack-Manipulationen wie erwartet.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;zu&lt;/code&gt; verbessert vermutlich nicht gerade die Performance, aber wenn man dafür
ein bisschen Koroutinen-Flair abbekommen kann, bin ich bereit da etwas 
Leistung herzuschenken.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Tja, nicht mal C-Compiler kommen ohne Magie aus.&lt;br /&gt;
Man würde sich erwarten, dass C Code unabhängig von der Umgebung arbeitet
und einfach seine Daten auf den oder vom Callstack schaufelt ohne zu 
hinterfragen, wo der Stack genau herkommt.&lt;br /&gt;
Doch wenn Optimierungen oder versteckte Werte an bestimmten Stellen liegen,
können die nicht so leicht “nachgebaut” werden.&lt;/p&gt;

&lt;p&gt;Wie man aber sieht, haben die Macher diesen Spezialfall vorgesehen und
durch das genannte Compiler-Flag steuerbar gemacht.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ein hoch auf OpenWatcom&lt;br /&gt;
… wenn auch heute teils mit gekreuzten Fingern.&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>Das InuYasha-FanProjekt</title>
   <link href="https://www.opengate.at/blog/2023/11/inuyasha/"/>
   <published>2023-11-26T12:00:00+01:00</published>
   <updated>2023-11-26T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2023/11/inuyasha</id>
   <category term="general" /><category term="entertainment" />
   <summary type="text">Es war purer Zufall, als ich einen alten Schatz im DVD-Regal wiederfand, den 
ich vor knapp 20 Jahren erworben hatte.
Zwischen 2006 und 2007 kamen die InuYasha 
Anime Filme in unseren Breiten auf den Markt und schlossen für mich die 
damals unvollendete Serie ab, die Anfang der 2000er Jahre auf RTL2 im 
Nachmittagsprogramm lief.

Und dann erinnerte ich mich an noch etwas …
</summary>
   <content type="html">&lt;p&gt;Es war purer Zufall, als ich einen alten Schatz im DVD-Regal wiederfand, den 
ich vor knapp 20 Jahren erworben hatte.&lt;br /&gt;
Zwischen 2006 und 2007 kamen die &lt;a href=&quot;https://de.wikipedia.org/wiki/Inu_Yasha&quot;&gt;InuYasha&lt;/a&gt; 
Anime Filme in unseren Breiten auf den Markt und schlossen für mich die 
damals unvollendete Serie ab, die Anfang der 2000er Jahre auf RTL2 im 
Nachmittagsprogramm lief.&lt;/p&gt;

&lt;p&gt;Und dann erinnerte ich mich an noch etwas …
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Aus irgend welchen Gründen hatte ich in jenen Jahren ein gesteigertes 
Interesse an allen typischen japanischen Rollenspielcharakteren, wie sie mir
die Final Fantasy Spiele von SNES bis Playstation vorsetzten.&lt;/p&gt;

&lt;p&gt;Fast immer ging es um einen jungen männlichen Helden, der ritterlich umher
reiste, Monster besiegte und das Herz von mindestens einer Jungfrau eroberte,
die ihn dann zumeist als mächtige Magierin begleitete.&lt;/p&gt;

&lt;p&gt;Die InuYasha Animeserie setzte dem ganzen dann die Krone auf, und war für mich
der Inbegriff einer Teenage-Hero-Story. Bis heute spreche ich bei ähnlichen
Produktionen vom “Cooler-Junge-mit-Schwert-Anime”.&lt;/p&gt;

&lt;h3 id=&quot;dvds-mit-qualität&quot;&gt;DVDs mit Qualität&lt;/h3&gt;

&lt;p&gt;Von den 4 Filmen sind die ersten 3 super und den vierten hätte man sich sparen
können. Die Nummer 3 mit dem Thema “Höllenschwert” ist für mich zweifellos das 
beste Anime-Kino aller Zeiten.&lt;/p&gt;

&lt;p&gt;Doch ein besonderes Highlight sind neben den stylischen Aluboxen die Booklets,
die einem japanische Begriffe, Namen und Eigenheiten beschreiben.&lt;br /&gt;
Hier hat offenbar jemand mal Zeit in die Qualität gesteckt und nicht einfach
nur Werbematerial für andere DVDs eingestreut.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/anime-inuyasha-dvds.jpg&quot; alt=&quot;Anime Inuyasha DVDs&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Und so fand ich auch den Hinweis, dass die InuYasha Movie DVDs für den 
deutschen Markt durch die inzwischen nicht mehr existierende Firma &lt;code&gt;RedPlanet&lt;/code&gt;
in Zusammenarbeit mit dem &lt;code&gt;InuYasha FanProjekt&lt;/code&gt; produziert wurden.&lt;/p&gt;

&lt;h3 id=&quot;das-inuyasha-fanprojekt&quot;&gt;Das InuYasha FanProjekt&lt;/h3&gt;

&lt;p&gt;Da haben sich offenbar vor über 20 Jahren ein paar Jungs und Mädchen 
zusammengefunden, die Fans der Mangas und der nachfolgenden Anime-Serie waren.
Und irgendwie kam diese Gruppe auf die Idee, an der Übersetzung des 
japanischen Materials mitzuwirken und … das wurde dann auch offiziell.&lt;/p&gt;

&lt;p&gt;Viele Anime-Serien wurden “kindgerecht” ins Nachmittagsprogramm eingestreut.
Und da man dort Tötungen nicht all zu gerne sah, wurde viel Material bis zur 
Unkenntlichkeit geschnitten und auch der Text inhaltsverändernd entschärft.&lt;/p&gt;

&lt;p&gt;Doch für die Filme, die auch fürs Kino geeignet waren, konnte man endlich die
Originale heranziehen und dass damals vor 20 Jahren eine Privatinitiative 
erstmals so direkt und positiv auf eine Produktion einwirkten konnte finde ich
einfach nur genial.&lt;/p&gt;

&lt;p&gt;Das alte Web-Forum, in welchem sich die Mitglieder des FanProjekts austauschten
existiert immer noch und bewahrt somit wie ein alter griechischer Tempel das
Andenken an die erbrachten Leistungen vieler freiwilliger Helfer.
&lt;a href=&quot;https://iyfp.eu/&quot;&gt;https://iyfp.eu/&lt;/a&gt;&lt;/p&gt;

&lt;h3 id=&quot;wie-die-zeit-vergeht-&quot;&gt;Wie die Zeit vergeht …&lt;/h3&gt;

&lt;p&gt;Der Titel des Beitrags &lt;a href=&quot;https://iyfp.eu/viewtopic.php?t=1076&quot;&gt;Wir trauern um unseren guten Freund Olaf blue Boos&lt;/a&gt;
im Forum ließ mich schon vor 10 Jahren und auch heute wieder nachdenken, wie
schnell das Leben an einem vorbeiziehen kann. Der genannte Mann war ein 
Organisator des IYFP und ich erinnere mich, dass er auch in einigen Podcasts
mitwirkte, die sich damals mit der Anime-Szene auseinander setzten.
(Ich glaube, das war auf &lt;a href=&quot;http://otakutimes.de/&quot;&gt;otakutimes.de&lt;/a&gt; und bei der 
heute ebenso obsoleten “Anime-Copyright-Allianz”.)&lt;/p&gt;

&lt;p&gt;Ich hatte keine Anknüpfungspunkte zum IYFP, kannt dort auch niemanden und las
nur gelegentlich mal ein paar Artikel der Gruppe mit. Dennoch berührt es
mich persönlich, dass hier mindestens ein wichtiges Mitglied inzwischen nicht
mehr unter uns weilt.&lt;br /&gt;
Und gleichsam halte ich immer noch einen Teil seines Werkes in meinen Händen,
und freue mich, dass es bei mir und vielen anderen Fans überdauert hat und 
auch weiter überdauern wird.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Das InuYasha FanProjekt ist nur eines von vielen kleineren und größeren 
Umsetzungen, welches durch viel freiwillige Arbeit etwas bewirkt hat.&lt;br /&gt;
Doch für mich ist es ein Ankerpunkt, ein Funke voller Freude, der mich an 
eine unbeschwerte Zeit zurückdenken lässt, die viel Spaß gemacht hat.&lt;/p&gt;

&lt;p&gt;Und diesen Spaß haben mir natürlich die japanische Autorin und ihr 
Produktionsteam ermöglicht, aber auch die Mitglieder des IYFP.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Eine echt geniale Leistung!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In meinen DVD Booklets stehen die Namen einiger Teammitglieder, die aktiv an
den DVDs mitgearbeitet haben:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Olaf “blue” Boos&lt;/li&gt;
  &lt;li&gt;Lukas “EVA-01” Ruffing&lt;/li&gt;
  &lt;li&gt;Pierre “pbsaffran” Bancov&lt;/li&gt;
  &lt;li&gt;Katarina “pekopeko” Conrath&lt;/li&gt;
  &lt;li&gt;Björn “Liferipper” Schmid&lt;/li&gt;
  &lt;li&gt;Marcio “Gogeta-X” Fragoso&lt;/li&gt;
  &lt;li&gt;Christian “Shiero-sensei” Linke&lt;/li&gt;
  &lt;li&gt;Michael “mi-Ka” Ebersberger&lt;/li&gt;
  &lt;li&gt;Andreas “Knuckles” Müller&lt;/li&gt;
  &lt;li&gt;Dennis “Shugana” Felske&lt;/li&gt;
  &lt;li&gt;Matthias “Kogoro” Helm&lt;/li&gt;
  &lt;li&gt;Michael “MagDragon” Paff&lt;/li&gt;
  &lt;li&gt;Kevin “Phytagoras” Wrobel”&lt;/li&gt;
  &lt;li&gt;Sabina “StephWingSab” Schneider&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Und es waren bestimmt noch viele mehr beteiligt.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Euch allen da draußen: &lt;strong&gt;DANKE!&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>SQLITE für Windows 95</title>
   <link href="https://www.opengate.at/blog/2023/11/old-sqlite/"/>
   <published>2023-11-19T12:00:00+01:00</published>
   <updated>2023-11-19T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2023/11/old-sqlite</id>
   <category term="devel" />
   <summary type="text">
  SQLite ist schon eine tolle Software 
… weil sie so “kompatibel” ist.


Wenn es darum geht ein Datenformat zu haben, das man über Zeiten hinweg
nutzen kann, denkt man nicht gleich an eine SQL-Datenbank.
Aber wie sich zeigt, lässt sich diese Software auch auf 25 Jahre alten
Systemen einsetzen.
</summary>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/SQLite&quot;&gt;SQLite&lt;/a&gt; ist schon eine tolle Software 
… weil sie so “kompatibel” ist.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Wenn es darum geht ein Datenformat zu haben, das man über Zeiten hinweg
nutzen kann, denkt man nicht gleich an eine SQL-Datenbank.&lt;br /&gt;
Aber wie sich zeigt, lässt sich diese Software auch auf 25 Jahre alten
Systemen einsetzen.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;code&gt;SQLite&lt;/code&gt; ist schon lange ins &lt;code&gt;GATE&lt;/code&gt; Framework integriert und von Zeit zu 
Zeit aktualisiere ich meinen Fork mit dem “latest-greatest” Abkömmling.&lt;/p&gt;

&lt;p&gt;Dabei habe ich mir wieder die Frage gestellt, wie weit ich mit SQLite in 
die Vergangheit reisen könnte. Und zumindest für die Windows Welt, konnte
ich das schnell austesten.&lt;/p&gt;

&lt;h3 id=&quot;sqlite-unter-nt4-und-win98&quot;&gt;SQLite unter NT4 und Win98&lt;/h3&gt;

&lt;p&gt;Wenn man ein paar Compiler-Flags richtig einstellt, lässt sich SQLite mit
Visual Studio 2005 kompilieren und dessen Output läuft dann unter NT4 wie
auch unter Windows 98.&lt;/p&gt;

&lt;p&gt;Natürlich muss man für Win98 mit der ANSI API arbeiten und auf einige 
erweiterte Datenzugriffsmöglichkeiten verzichten, doch diesen Weg kann man
leicht aus den Originalquellen beschreiten.&lt;/p&gt;

&lt;h3 id=&quot;windows-95-ist-anders&quot;&gt;Windows 95 ist anders&lt;/h3&gt;

&lt;p&gt;Wer denkt zwischen Win95 und 98 gäbe es keine funktionalen Unterschiede, 
der irrt.&lt;br /&gt;
Denn eine Funktion fehlt an vielen Enden: &lt;code&gt;InterlockedCompareExchange()&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Das Thema hatte ich im GATE-Framework intern schon und leitete damals einen
Workaround bei mir ein … doch in Fremdcode geht das nicht so einfach.&lt;/p&gt;

&lt;p&gt;Ich konnte jedoch das Ergebnis von &lt;code&gt;InterlockedCompareExchange&lt;/code&gt; in einer 
eigenen Funktion provisorisch nachbauen (mit &lt;code&gt;InterlockedExchange&lt;/code&gt;) und 
dann (per Makro von &lt;code&gt;CMake&lt;/code&gt; aus) die originalen Aufrufe von 
&lt;code&gt;InterlockedCompareExchange&lt;/code&gt; auf meine Funktion umleiten.&lt;/p&gt;

&lt;p&gt;Zum Kompilieren war Studio 2003 notwendig, wofür auch noch eine kleine 
Änderung am Buildscript notwendig war … doch am Ende konnte SQLite
auch für Windows 95 kompiliert und dort auch ausgeführt werden.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Wenn es also ein Datenformat gibt, das ich heute im Jahr 2023 genau so nutzen
kann, wie damals im Jahr 1995, dann ist das &lt;code&gt;SQLite&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Ich bin sicher, dass es keine andere freie Datenbanksoftware gibt, die ihr
Datenformat und auch ihren Programmcode so gestaltet hat, dass man Jahrzehnte
damit überbrücken kann. Im besten Fall bekommt man kompatible Upgrades auf die 
neueste Version, die nur unter der neuesten Umgebung läuft.&lt;/p&gt;

&lt;p&gt;Daher erneut: &lt;strong&gt;Ein Hoch auf SQLite!&lt;/strong&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Hirnlos glücklich</title>
   <link href="https://www.opengate.at/blog/2023/11/stroke/"/>
   <published>2023-11-18T12:00:00+01:00</published>
   <updated>2023-11-18T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2023/11/stroke</id>
   <category term="general" />
   <summary type="text">
  Was meinen Schlaganfall von letzter Woche anbelangt …
… es war eh keiner … glaube/hoffe ich.


</summary>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;Was meinen Schlaganfall von letzter Woche anbelangt …
… es war eh keiner … glaube/hoffe ich.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Soooo lustig war das anfangs natürlich nicht.&lt;/p&gt;

&lt;p&gt;Denn ich sitze wie fast jeden Abend vor dem Rechner und tippe herum, als ich
merke, dass mir das Drücken der Tasten mit der linken Hand immer schwerer
fällt.&lt;/p&gt;

&lt;p&gt;Gut, das kommt vor, schnell hat man sich einen Nerv wo eingeklämmt oder saß
eben blöd schief am Stuhl.&lt;br /&gt;
Also einmal aufstehen eine Runde durchs Zimmer laufen und alles ist wieder
gut.&lt;/p&gt;

&lt;p&gt;Doch an jenem Abend neulich leider nicht. Es fiel mir immer schwerer die 
linke Hand zu bewegen. Es ging zwar, war aber anstrengend und langsam.&lt;/p&gt;

&lt;p&gt;Dann wird man nervös … es könnte ja doch was Ernstes sein … aber wenn nicht,
dann blamiert man sich wegen einem eingeschlafenem Arm.&lt;/p&gt;

&lt;p&gt;Es dauerte jedenfalls recht lange, bis sich mein Arm wieder normal anfühlte.
Eine Stunde war ich auf und abgelaufen, stets in Versuchung vielleicht doch 
den Notarzt zu rufen.&lt;/p&gt;

&lt;p&gt;Letztendlich tat ich es nicht und ging “ganz normal” schlafen. Der Arm war
da wieder halbwegs normal.&lt;/p&gt;

&lt;h3 id=&quot;nachbehandlung&quot;&gt;Nachbehandlung&lt;/h3&gt;

&lt;p&gt;Am Folgetag war man erster Weg zum Hausarzt … der erst am nächsten Tag
für mich Zeit hatte. Nach Schilderung des Vorfalles gab es mehrere 
Möglichkeiten, die von harmlosen Verspannungen bis zum Schlaganfall reichten
und alle ausgeschlossen werden sollten.&lt;/p&gt;

&lt;p&gt;So bekam ich jede Menge Überweisungen und Tests zugeordnet. Bluttests, EKG,
Ultraschall und Neurologe waren tatsächlich binnen zwei Wochen vereinbar.
Nur die wichtigste Sache: ein MRT zum Check, ob mein Hirn noch richtig
läuft, da ist der nächste Termin erst im Februar frei.&lt;/p&gt;

&lt;p&gt;Ich hätte, wie ich nun weiß, sofort den Notarzt rufen sollen, denn in
Notfällen wird sofort ein Gerät für einen frei gemacht.&lt;br /&gt;
… aber … bei verabredeten Terminen für einen quasi Vorsorgecheck,
da dauert es schon gerne mal 3-4 Monate.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Die beste Erklärung für meinen “toten Arm” ist wohl meine verschobene
Wirbelsäule, die einige Nerven eingeklemmt hatte … und an dem
Abend war es vielleicht die Armsteuerung. Auf einen Schlaganfall deutet
nichts hin, auch ein inzwischen ebenfalls gemachtes normales CT nicht 
… aber wirklich ausschließen kann es offenbar nur ein MRT … 
und auf diesen Termin bin ich schon gespannt.&lt;/p&gt;

&lt;p&gt;Wie auch immer … wenn ich bei einem Kundenproblem mit einer Software 
den nächsten Diagnosetermin in 3 Monaten einplane, dann kann man den
Aufschrei noch am Südpol sehr deutlich hören.&lt;/p&gt;

&lt;p&gt;Heißt also:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Unsere medizinischen Einrichtungen bräuchten da auch mal
ein System-Update.&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>Debian UI ein/ausschalten</title>
   <link href="https://www.opengate.at/blog/2023/11/debian-ui/"/>
   <published>2023-11-12T12:00:00+01:00</published>
   <updated>2023-11-12T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2023/11/debian-ui</id>
   <category term="software" />
   <summary type="text">
  X11 und ein UI Desktop 
gehören einfachen zu jedem Linux dazu. 
Warum auch nicht, selbst wenn man sie nicht immer braucht.


… dachte ich, bis ich mir die Speicherauslastung ansah.
Jetzt heißt es: Abschalten!
</summary>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/X_Window_System&quot;&gt;X11&lt;/a&gt; und ein UI Desktop 
gehören einfachen zu jedem Linux dazu. 
Warum auch nicht, selbst wenn man sie nicht immer braucht.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;… dachte ich, bis ich mir die Speicherauslastung ansah.&lt;br /&gt;
Jetzt heißt es: &lt;em&gt;Abschalten!&lt;/em&gt;
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Am &lt;a href=&quot;https://de.wikipedia.org/wiki/Hyper-V&quot;&gt;Hyper-V&lt;/a&gt; Server gibt es das tolle 
Feature: Dynamischer Speicher.&lt;br /&gt;
Man ordnet dem System ein Minimum garantiert zu, lässt aber einen
Spielraum für die maximale Nutzung offen.&lt;br /&gt;
Wenn VMs jetzt nicht den vollen Speicher brauchen, bleibt dieser für andere
Aufgaben oder andere VMs übrig.&lt;br /&gt;
Und genau so kann ich wesentlich mehr VMs gleichzeitig starten.&lt;/p&gt;

&lt;p&gt;Meine Debian Server zum Bauen von Software starten daher mit 1 GB RAM,
dürfen sich aber bis zu 4 GB krallen, wenn noch so viel frei ist.&lt;/p&gt;

&lt;p&gt;Jetzt braucht ein Buildserver natürlich kein UI, doch ich installiere
es trotzdem manchmal mit, damit ich im Notfall auch dort ein paar Dinge
komfortabler durchführen kann, oder weil ich meine eigenen X11-Apps 
schnell testen möchte.&lt;/p&gt;

&lt;p&gt;Mit aktivierter X11 Desktop Session schwillt der Speicherbedarf aber schnell
auf die erlaubten 4 GB an, ohne dass ich die UI überhaupt nutze.&lt;br /&gt;
Es macht also durchaus Sinn die grafische Benutzerschnittstelle erst gar nicht
zu starten, wenn ich sie nicht brauche.&lt;/p&gt;

&lt;h3 id=&quot;x11-unter-debian-ein-und-ausschalten&quot;&gt;X11 unter Debian ein und ausschalten&lt;/h3&gt;

&lt;p&gt;Vor über 20 Jahren lernte ich noch etwas über “Runlevel”:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;init 3&lt;/code&gt; startet den Mehrbenutzer-Modus ohne UI (also nur die Text-Konsole)&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;init 5&lt;/code&gt; startet die volle grafische Oberfläche unter Linux.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Heute hat &lt;code&gt;systemd&lt;/code&gt; diese Funktion übernommen und benennt die Runlevels in
“Targets” um.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;multi-user.target&lt;/code&gt; bezeichnet den Konsolenmodus&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;graphical.target&lt;/code&gt; stellt die volle grafische Oberfläche bereit.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Und um beim Start eben nur die Konsole zu starten und auf die UI zu
verzichten reicht ein einfaches:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;sudo systemctl set-default multi-user.target
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Umgekehrt kann der automatische Start der GUI mit&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;sudo systemctl set-default graphical.target
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;wieder aktiviert werden.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Das witzige ist, dass ich mich selten direkt auf solchen Maschinen im UI 
einlogge, sondern eher &lt;code&gt;xrdp&lt;/code&gt; nutze. Auch hier ist der automatische Start 
der GUI eine reine Speicherverschwendung, den &lt;code&gt;xrdp&lt;/code&gt; startet erst dann 
die grafische Umgebung, wenn die erste Remote-Verbindung angenommen wird.&lt;/p&gt;

&lt;p&gt;Das Installieren einer GUI kann also auch auf Servern Sinn machen, doch es 
lohnt sich dieses “Target” nicht automatisch hochziehen zu lassen.&lt;/p&gt;

&lt;p&gt;Mit dem &lt;code&gt;multi-user.target&lt;/code&gt; fährt man also am besten und schont vor allem
die Ressourcen der Hardware oder des VM-Hosts.&lt;/p&gt;

&lt;p&gt;Und wenn man direkt zur GUI wechseln möchte, erledigt das&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;systemctl isolate graphical.target
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;was dem früheren &lt;code&gt;init 5&lt;/code&gt; entsprechen würde.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>The Marvels und Loki Season 2</title>
   <link href="https://www.opengate.at/blog/2023/11/loki-marvel/"/>
   <published>2023-11-11T12:00:00+01:00</published>
   <updated>2023-11-11T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2023/11/loki-marvel</id>
   <category term="entertainment" />
   <summary type="text">Wow! Was für eine Woche. Zum einen endete die zweite Loki Staffel mit einem
spektakulärem Ende und zum anderen kam mit The Marvels ein weiterer Film in
die Kinos, dessen Ausrichtung schon lange diskutiert wird.

Soll heißen, dieses Woche war eine Medien Woche.
</summary>
   <content type="html">&lt;p&gt;Wow! Was für eine Woche. Zum einen endete die zweite &lt;code&gt;Loki&lt;/code&gt; Staffel mit einem
spektakulärem Ende und zum anderen kam mit &lt;code&gt;The Marvels&lt;/code&gt; ein weiterer Film in
die Kinos, dessen Ausrichtung schon lange diskutiert wird.&lt;/p&gt;

&lt;p&gt;Soll heißen, dieses Woche war eine Medien Woche.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;the-marvels&quot;&gt;The Marvels&lt;/h3&gt;

&lt;p&gt;Es ist wirklich zum verrückt werden. Ich liebe jede der drei Frauen, die mit 
the “Marvels” im großen Kinoformat ankamen … und trotzdem schmerzt es mich,
wie wenig mit den Figuren gemacht wurde.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Brie_Larson&quot;&gt;Brie Larson&lt;/a&gt; hatte ja bereits ihren
Marvel-Soloauftritt im ersten “Captain Marvel” Film. Doch wir alle wissen, 
dass dieser Film nur “nachgereicht” wurde, um im nahenden Endgame Titel eine
geheime Superwaffe zu haben. Genau das war damals das Problem. Man sah den 
Szenen an, dass sie in größere Handlung  “hineinkonstruiert” wurden. Man hätte
ähnlich wie bei Ironman, Captain America oder Thor etwa 2 bis 3 Filme für die 
Charakterentwicklung gebraucht um die Figur zu etablieren.&lt;/p&gt;

&lt;p&gt;Und was passiert im zweiten Film … leider wieder das gleiche.
Mit &lt;code&gt;Monica Ramow&lt;/code&gt; und &lt;code&gt;Kamala Kahn&lt;/code&gt; hatte man zwei tolle Protagonisten
hinzugewonnen, die Sympathien trugen und besonders Kamala spielte 
(wie Tom Holland in Spiderman) die Rolle eines Teenagers hervorragen in ihrer
&lt;a href=&quot;https://de.wikipedia.org/wiki/Ms._Marvel_(Fernsehserie)&quot;&gt;Ms. Marvel&lt;/a&gt; Serie.&lt;/p&gt;

&lt;p&gt;“The Marvels” war lustig, humorvoll und mit gutem Schauspiel vorgetragen, doch
die Handlung und der herbeigeschriebene Bösewicht war farb- und konturlos.
Wieder einmal findet man ein Artefakt, das Welten zerstören kann, 
die böse “Dar-Benn”, Anführerin der Kree setzt es ein um ihr Volk zu retten,
und ignoriert den Genozid und die Auslöschung anderer.&lt;/p&gt;

&lt;p&gt;Am Ende läuft der Frauen-Fight-Club durch, die guten gewinnen, die Böse 
verliert.&lt;br /&gt;
Ja … da hätte ich mehr erwartet.&lt;/p&gt;

&lt;p&gt;Und trotzdem wirkt &lt;a href=&quot;https://de.wikipedia.org/wiki/Iman_Vellani&quot;&gt;Iman Vellani&lt;/a&gt; 
als Kamala so bezaubernd nett in ihrer Rolle, dass ich dem Film seinen 
simplen Plott verzeihe. Vielmehr sehe ich den Film als eine Komödie, in der 
eine Raumstation von “frisch geschlüpften Katzen” 
(&lt;a href=&quot;https://en.wikipedia.org/wiki/List_of_alien_races_in_Marvel_Comics#F&quot;&gt;Flerken&lt;/a&gt; )
gerettet wird und Brie Larson als Prinzessin vortanzen kann.&lt;/p&gt;

&lt;p&gt;Ein Highlight wird für viele die Mid- und Endcredit-Szene sein, den dort werden
einerseits die Young Avangers angekündigt und Monica Rambeau hat es inzwischen
in die Dimension der X-Men verschlagen … heißt also, die kommen auch bald ins
Kino.&lt;/p&gt;

&lt;p&gt;Na und so geht man dann mit einem breiten Grinsen aus dem Kinosaal.&lt;/p&gt;

&lt;h3 id=&quot;loki-season-2&quot;&gt;Loki Season 2&lt;/h3&gt;

&lt;p&gt;Ich liebe alles, was mit Zeitreisen zu tun hat, von daher stand die Loki Serie
automatisch bei mir auf einem Podest.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Aber - W-T-F - war das ein geniales Finale!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Dass Loki als einer der besten Bösewichte im Marvel Universum bekannt ist, 
ist einfach erklärt: Er hat einen Grund!&lt;br /&gt;
Stets wird er von seinem Bruder Thor daran erinnert, dass er nicht zum 
herrschen bestimmt ist und selbst wenn er sich mit Gewalt “einen Thron” nimmt,
wird ihm der schnell wieder genommen.&lt;/p&gt;

&lt;p&gt;Und dann verschlägt es eine Loki-Variante in Time-Variance-Authority und
schon in Folge 1 von Staffel 1 lernt Loki, dass es da draußen noch viel mehr
gibt, als sein kindisches Wetteifern um Untertanen.&lt;/p&gt;

&lt;p&gt;Staffel 2 startet genau dort wo uns das Ende von Staffel 1 mit Fragezeichen
zurückgelassen hat. Doch schnell wird klar, dass Loki jetzt ein neues Ziel
gefunden hat. Während seine weibliche Variante Sylvi die Zeitstrahlen von 
der Kontrolle der TVA befreit hat, wandelt sich 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Tom_Hiddleston&quot;&gt;Tom Hiddleston&lt;/a&gt;’s Loki nun
zum Beschützer der Zeitlinien um.&lt;/p&gt;

&lt;p&gt;Und dann gingen die Gerüchte mit uns allen durch, wer wohl der “wahre” 
Bösewicht der Staffel sein wird, wenn Loki nun zum Retter wird.
Aber Marvels brillianter Schachzug in Sachen Storytelling hat uns alle
überrascht und uns ein Ende beschert, dass man sich immer wieder und
wieder ansehen kann und sich einfach freuen kann, wie Loki endlich eine
Bestimmung (&lt;code&gt;Ein Glorreiches Ansinnen&lt;/code&gt;) findet.&lt;/p&gt;

&lt;p&gt;Eigentlich wollte er immer schon der Gute sein, er konnte es nur nicht 
verkraften damit nicht alleine zu sein. Alleine der Gesichtsausdruck
in Thor 3 nach seinen Worten “Euer Retter ist hier” sprach Bände, als
wiederum Thor auftrat und ihm die Show stahl.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Am Ende von Folge 6 konnten weder Maschinen noch verbesserte Technik 
das Absterben der Zeitlinien verhindern. Hier konnte nur “ein Gott” 
einschreiten und sein Leben für alle anderen aufopfern, und so 
entstand ein neuer Lebensbaum.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/marvel-loki-yggdrasil.jpg&quot; alt=&quot;Marvel-Loki2-Yggdrasil&quot; /&gt;&lt;/p&gt;

&lt;p&gt;So kann man das hervorragende Ende der Loki Serie umschreiben und wenn
dann Soundtrack einsetzt, während sich die Mobius quasi von uns
verabschiedet, dann ist man gleichsam glücklich wie auch traurig über
die Reise, das Schicksal und die Bestimmung des neuen:&lt;br /&gt;
Loki, Gott der Geschichten.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Wenn man mal von kleinen Begehrlichkeiten absieht, war diese Woche für
Marvel Fans ein Fest. &lt;code&gt;The Marvels&lt;/code&gt; hat mir “nur” einen empfehlenswerten 
Kinoabend beschehrt, aber &lt;code&gt;Loki&lt;/code&gt; hat unsere Welt gerettet.&lt;/p&gt;

&lt;p&gt;Und wenn das Storywriting so weitergeht, wie es Loki gezeigt hat, 
nämlich unvorhersehbar und trotzdem gut und schlüssig, dann steht
Marvel nicht der aktuell gerne herbeigeredete Untergang, sondern ein
gutes Comeback bevor.&lt;/p&gt;

&lt;p&gt;Die letzten Filme konnten nicht mehr an die Erfolge der Phase 3 und
Endgame anschließen … aber es heißt nicht, dass es in den kommenden
Jahren nicht wieder solche Titel geben kann.&lt;/p&gt;

&lt;p&gt;Ich freue mich jetzt auf jeden Fall schon darauf.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Watcom im Docker</title>
   <link href="https://www.opengate.at/blog/2023/11/watcom-docker/"/>
   <published>2023-11-05T12:00:00+01:00</published>
   <updated>2023-11-05T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2023/11/watcom-docker</id>
   <category term="devel" /><category term="software" />
   <summary type="text">Dass wir heute unsere Linux und Windows Binaries auf Buildservern bauen
lassen, ist Standard. Doch zu DOS 
Zeiten war es immer nur der eigene Computer, der das finale Release eine 
Software anfertigte.

Wäre es nicht faszinierend, wenn wir auch DOS Programme heute im Docker
Container bauen lassen könnten?
</summary>
   <content type="html">&lt;p&gt;Dass wir heute unsere Linux und Windows Binaries auf Buildservern bauen
lassen, ist Standard. Doch zu &lt;a href=&quot;https://de.wikipedia.org/wiki/MS-DOS&quot;&gt;DOS&lt;/a&gt; 
Zeiten war es immer nur der eigene Computer, der das finale Release eine 
Software anfertigte.&lt;/p&gt;

&lt;p&gt;Wäre es nicht faszinierend, wenn wir auch DOS Programme heute im Docker
Container bauen lassen könnten?
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Und tatsächlich wurden die &lt;a href=&quot;https://de.wikipedia.org/wiki/Watcom&quot;&gt;Open Watcom&lt;/a&gt;
Compiler für C, C++ und Fortran inzwischen auch auf Linux portiert, womit
DOS Programme unter Linux kompiliert werden können.&lt;/p&gt;

&lt;p&gt;Bei der&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Frage: Läuft das auch in Docker?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;wird es leider etwas komplizierter als es sein müsste, und so lautet die&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Antwort: Watcom läuft, nur das Setup leider nicht.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Das Watcom Projekt liefert seine Ergebnisse in alter DOS/Win3x Manier als
Installer-EXEn aus. In einer solchen über 100 MB großen Programmdatei ist
das ganze Setup enthalten und ein UI lässt einen auswählen, was man alles
haben möchte.&lt;/p&gt;

&lt;p&gt;Das ist super für Benutzer vor dem Bildschirm, aber schlecht für jemanden,
der die Installation automatisiert durchlaufen lassen will, und genau das 
brauchen wir für Docker.&lt;br /&gt;
Theoretisch könnte man das interne Script für die Installation zwar
abändern, doch mir hat sich nicht erschlossen, wie man das schnell 
hinbekommen könnte.&lt;/p&gt;

&lt;p&gt;Mein nächster Versuch lief dann über &lt;a href=&quot;https://linux.die.net/man/1/expect&quot;&gt;expect(1)&lt;/a&gt;,
mit dem man Eingaben an ein laufendes Programm hätte schicken können.&lt;br /&gt;
Das funktionierte sogar halbwegs auf der echten Konsole, und ich konnte die
nötigen &lt;code&gt;ENTER&lt;/code&gt; + &lt;code&gt;Pfeiltasten&lt;/code&gt; an das Setup schicken, um bis zur Installation
zu kommen … doch leider klappte es wieder nicht im Docker Container.&lt;/p&gt;

&lt;h3 id=&quot;lösung-real-installieren-und-kopieren&quot;&gt;Lösung: Real installieren und kopieren&lt;/h3&gt;

&lt;p&gt;Am Ende ging ich den “einfachsten” Weg und war erstaunt, wie erfolgreich das
war: Ich installierte OpenWatcom auf einer frischen Linuxumgebung und 
kopierte einfach alle installierten Dateien dann in ein 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Tar_(Packprogramm)&quot;&gt;TAR&lt;/a&gt;-Archiv.&lt;br /&gt;
Und eben dieses Archiv wurde dann in ein neues Docker-Image importiert.
Das war es auch schon.&lt;/p&gt;

&lt;p&gt;Das Watcom Setup installiert nämlich seine Dateien in &lt;code&gt;/usr/bin/watcom&lt;/code&gt;
und verändert sonst nichts am System.&lt;br /&gt;
Um die nötigen Environment-Variablen zu setzen, wird im Build-Script einfach 
der Inhalt von&lt;br /&gt;
&lt;code&gt;/usr/bin/watcom/owsetenv.sh&lt;/code&gt; importiert:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;#!/bin/sh
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;. /usr/bin/watcom/owsetenv.sh
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;...
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;cmake -G &amp;quot;Watcom WMake&amp;quot; ...
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;wmake
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Schon läuft der DOS Build in Linux und auch innerhalb eines Docker Containers.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Vor 25 Jahren startete ich meine erste Linux-Distro noch von DOS aus (falls 
sich noch wer an &lt;a href=&quot;https://tldp.org/HOWTO/UMSDOS-HOWTO.html&quot;&gt;UMSDOS&lt;/a&gt; erinnert …).&lt;/p&gt;

&lt;p&gt;Und heute starte ich Buildprozesse für DOS aus Linux Docker Containern heraus.&lt;/p&gt;

&lt;p&gt;… wer hätte das gedacht, aber es bereitet mir immer wieder Spaß solche 
scheinbar entfernten Systemgrenzen abzuschreiten.&lt;/p&gt;

&lt;p&gt;Am Ende heißt es also:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Frage: Laufen Watcom DOS Builds auch in Docker?&lt;br /&gt;
Antwort: Ja natürlich!&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>Forgejo Runner</title>
   <link href="https://www.opengate.at/blog/2023/11/forgejo/"/>
   <published>2023-11-04T12:00:00+01:00</published>
   <updated>2023-11-04T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2023/11/forgejo</id>
   <category term="software" />
   <summary type="text">Wäre es nicht schön zu wissen, ob der zuletzt hochgeladene Code auch korrekt
gebaut werden kann?
Dafür haben wir CI/CD Features und 
Build-Agents auf unterschiedlichen Plattformen.

Codeberg bietet dafür sein 
Woodpecker CI an … doch etwas versteckt 
findet man auch Github Actions als 
forgejo Workflows.
</summary>
   <content type="html">&lt;p&gt;Wäre es nicht schön zu wissen, ob der zuletzt hochgeladene Code auch korrekt
gebaut werden kann?&lt;br /&gt;
Dafür haben wir &lt;a href=&quot;https://de.wikipedia.org/wiki/CI/CD&quot;&gt;CI/CD&lt;/a&gt; Features und 
Build-Agents auf unterschiedlichen Plattformen.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://codeberg.org/&quot;&gt;Codeberg&lt;/a&gt; bietet dafür sein 
&lt;a href=&quot;https://woodpecker-ci.org/&quot;&gt;Woodpecker CI&lt;/a&gt; an … doch etwas versteckt 
findet man auch &lt;a href=&quot;https://de.wikipedia.org/wiki/GitHub&quot;&gt;Github&lt;/a&gt; Actions als 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Forgejo&quot;&gt;forgejo&lt;/a&gt; Workflows.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Über &lt;code&gt;Github actions&lt;/code&gt; kann der Server bei einem Ereignis (wie: 
“Neuer Code eingecheckt.”) einem registrierten “Runner” auftragen, ein 
Script auszuführen.&lt;/p&gt;

&lt;p&gt;Und wenn dieses Script dann den neuen Code kompiliert, dann haben wir 
bereits einen Buildserver aufgesetzt.&lt;/p&gt;

&lt;h3 id=&quot;wieder-ein-neues-yaml&quot;&gt;Wieder ein neues YAML&lt;/h3&gt;

&lt;p&gt;Was mich an allen CI/CD Lösungen ankotzt sind deren Uneinigkeit, wie man einen
Vorgang einheitlich abbilden kann. Jede f*cking Lösung erkennt, dass YAML
super geeignet ist für diesen Job … und jede f*cking Lösung löst es ein
bisschen anders.&lt;br /&gt;
Gerade so, dass man noch abstrakt erkennt, dass alle Lösungen eigentlich gleich
aufgebaut sind, aber unterschiedlich genug, dass man jede Variante separat
implementieren muss und ja kein Zeichen von A nach B kopieren kann.&lt;/p&gt;

&lt;p&gt;… aber gut … genug gelästert.&lt;/p&gt;

&lt;p&gt;Meine action-workflows liegen in der Datei &lt;code&gt;/.gitea/workflows/build-platform.yml&lt;/code&gt;
und sind etwa so aufgebaut:&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#606&quot;&gt;on&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#D20&quot;&gt;[push]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#606&quot;&gt;jobs&lt;/span&gt;:
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#606&quot;&gt;build-linux-x64&lt;/span&gt;:
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#606&quot;&gt;runs-on&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#D20&quot;&gt;docker&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#606&quot;&gt;container&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#D20&quot;&gt;opendockergate/gate-build-env:deb.10.gcc.8.1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#606&quot;&gt;steps&lt;/span&gt;:
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;      - &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#D20&quot;&gt;name: checkout sources&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;        &lt;span style=&quot;color:#606&quot;&gt;uses&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#D20&quot;&gt;actions/checkout@v3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;        &lt;span style=&quot;color:#606&quot;&gt;with&lt;/span&gt;:
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;          &lt;span style=&quot;color:#606&quot;&gt;submodules&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#D20&quot;&gt;true&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;      - &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#D20&quot;&gt;name: run linux GCC X64 build scripts&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;        &lt;span style=&quot;color:#606&quot;&gt;run&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;|&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#D20&quot;&gt;          env | sort&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#D20&quot;&gt;          cd scripts&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#D20&quot;&gt;          ./build-make.sh&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#D20&quot;&gt;          cd ..&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#D20&quot;&gt;          mkdir -p ./dist/linux_x64&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#D20&quot;&gt;          cp -r ./build/make/deploy/bin/* ./dist/linux_x64&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#D20&quot;&gt;          ls -l ./dist/linux_x64&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;      - &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#D20&quot;&gt;name: compress artifacts&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n21&quot; name=&quot;n21&quot;&gt;21&lt;/a&gt;&lt;/span&gt;        &lt;span style=&quot;color:#606&quot;&gt;run&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;|&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n22&quot; name=&quot;n22&quot;&gt;22&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#D20&quot;&gt;          tar -cJvf artifacts-linux-x64.tar.xz -C ./dist/ .&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n23&quot; name=&quot;n23&quot;&gt;23&lt;/a&gt;&lt;/span&gt;      - &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#D20&quot;&gt;name: upload artifacts&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n24&quot; name=&quot;n24&quot;&gt;24&lt;/a&gt;&lt;/span&gt;        &lt;span style=&quot;color:#606&quot;&gt;uses&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#D20&quot;&gt;actions/upload-artifact@v3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n25&quot; name=&quot;n25&quot;&gt;25&lt;/a&gt;&lt;/span&gt;        &lt;span style=&quot;color:#606&quot;&gt;with&lt;/span&gt;:
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n26&quot; name=&quot;n26&quot;&gt;26&lt;/a&gt;&lt;/span&gt;          &lt;span style=&quot;color:#606&quot;&gt;name&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#D20&quot;&gt;artifacts-linux-x64.tar.xz&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n27&quot; name=&quot;n27&quot;&gt;27&lt;/a&gt;&lt;/span&gt;          &lt;span style=&quot;color:#606&quot;&gt;path&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#D20&quot;&gt;artifacts-linux-x64.tar.xz&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n28&quot; name=&quot;n28&quot;&gt;28&lt;/a&gt;&lt;/span&gt;          &lt;span style=&quot;color:#606&quot;&gt;retention-days&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#D20&quot;&gt;7&lt;/span&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Man definiert also, dass bei einem &lt;code&gt;push&lt;/code&gt; was passieren soll, und zwar wird der
Job &lt;code&gt;build-linux-x64&lt;/code&gt; gestartet, der auf einem Runner läuft, den man unter dem Tag
&lt;code&gt;docker&lt;/code&gt; findet, und der soll den Container 
&lt;code&gt;opendockergate/gate-build-env:deb.10.gcc.8.1&lt;/code&gt; benutzen (also mein Dockerhub Repo).&lt;/p&gt;

&lt;p&gt;Jetzt braucht man etwas Detailwissen. Man könnte sich jetzt gleich ein Shell-Script
schreiben, das per GIT alles auscheckt und dann baut, doch dafür gibt es bereits
fertigen Code, der das fehlertolerant abwickelt.&lt;br /&gt;
Man muss nur wissen, dass unter dem Namen &lt;code&gt;actions/checkout@v3&lt;/code&gt; ein GIT-Clone 
implementiert ist, und dass sich hinter &lt;code&gt;actions/upload-artifact@v3&lt;/code&gt; die HTTP 
API zum Hochladen von Build-Ergebnissen zum Forgejo/Codeberg Server verbirgt.&lt;/p&gt;

&lt;p&gt;Denn diese Codes werten das Gewirr von Umgebungsvariablen aus und setzen die 
notwendigen Aktionen um mit wenig Einstellung zum Ziel zu kommen.&lt;/p&gt;

&lt;p&gt;In der Mitte befindet sich dann unter &lt;code&gt;run&lt;/code&gt; “mein Buildcode”, der im geklonten
Repository die nötigen Schritte setzt, damit die Sourcen gebaut werden.&lt;/p&gt;

&lt;h3 id=&quot;docker-image-brauch-nodejs&quot;&gt;Docker Image brauch nodejs&lt;/h3&gt;

&lt;p&gt;Damit &lt;code&gt;actions&lt;/code&gt; scripts wie &lt;code&gt;checkout&lt;/code&gt; oder &lt;code&gt;upload-artifact&lt;/code&gt; funktionieren,
brauch das Docker image zwingend &lt;code&gt;nodejs&lt;/code&gt; installiert.&lt;/p&gt;

&lt;p&gt;Ein Basis Build-Image für C++ unter Codeberg Actions fängt bei mir also so
im &lt;code&gt;Dockerfile&lt;/code&gt; an:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;apt-get install build-essential cmake git nodejs apt-transport-https ca-certificates
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Ohne &lt;code&gt;nodejs&lt;/code&gt; treten jede Menge Fehler auf, die nicht unmittelbar auf die 
fehlende Node-Installation hinweisen.&lt;/p&gt;

&lt;h3 id=&quot;einen-runner-braucht-man-auch&quot;&gt;Einen Runner braucht man auch&lt;/h3&gt;

&lt;p&gt;Der &lt;code&gt;forgejo-runner&lt;/code&gt; ist ein kleiner Dienst, den man sich von der Github 
Release-Seite herunterladen und auf einer gängigen Linux-Distro mit 
Docker-Setup installieren kann.&lt;/p&gt;

&lt;p&gt;Zuerst setze ich also eine neue &lt;code&gt;Debian&lt;/code&gt; Maschine auf und installiere 
&lt;code&gt;Docker&lt;/code&gt; darauf:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;sudo apt update
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;sudo apt upgrade -y
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;sudo apt install -y ca-certificates curl
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;sudo install -m 0755 -d /etc/apt/keyrings
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;sudo curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;sudo chmod a+r /etc/apt/keyrings/docker.asc
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;echo &amp;quot;deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian $(. /etc/os-release &amp;amp;&amp;amp; echo $VERSION_CODENAME) stable&amp;quot; | sudo tee /etc/apt/sources.list.d/docker.list &amp;gt; /dev/null
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;sudo apt update
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;sudo systemctl start docker
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Den &lt;code&gt;forgejo-runner&lt;/code&gt; installiere ich dann in &lt;code&gt;/opt/forgejo&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;sudo mkdir /opt/forgejo
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;sudo chown $USER /opt/forgejo
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;cd /opt/forgejo
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;wget https://code.forgejo.org/forgejo/runner/releases/download/v3.3.0/forgejo-runner-3.3.0-linux-amd64
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;chmod +x ./forgejo-runner-3.3.0-linux-amd64
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;ln -s ./forgejo-runner-3.3.0-linux-amd64 ./forgejo-runner
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Auf Codeberg.org erhält man in den “Actions/Runners” Einstellungen einen 
Registration-Token.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/codeberg-new-runner.gif&quot; alt=&quot;codeberg.org new runner screenshot&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Diesen &lt;code&gt;TOKEN&lt;/code&gt; nutzt man dann auf der Runner Maschine mit dem  &lt;code&gt;register&lt;/code&gt; 
Kommando und danach erzeugt man noch eine Standard-Konfiguration:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;./forgejo-runner register --no-interactive --token TOKEN --name my_runner_name --instance https://codeberg.org
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;./forgejo-runner generate-config &amp;gt; config.yml
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Nun hat man die versteckte Registrierungsdatei &lt;code&gt;.runner&lt;/code&gt; und eine 
einsatzbereite Konfigurationsdatei &lt;code&gt;config.yml&lt;/code&gt; im Verzeichnis und kann den 
neuen Runner auch schon im WebUI auf codeberg.org sehen.&lt;br /&gt;
Weitere Infos findet man dann unter 
&lt;a href=&quot;https://docs.codeberg.org/ci/actions/&quot;&gt;docs.codeberg.org/ci/actions/&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Damit der Dienst bei jedem Systemstart ausgeführt wird, hilft einem
bei &lt;code&gt;systemd&lt;/code&gt; ein Eintrag wie in&lt;br /&gt;
&lt;code&gt;/etc/systemd/system/forgejo-runner.service&lt;/code&gt;&lt;/p&gt;

&lt;div class=&quot;language-ini highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;[Unit]
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;Description=forgejo runner
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;After=network.target
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;[Service]
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;ExecStart=/opt/forgejo/forgejo-runner daemon
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;WorkingDirectory=/opt/forgejo
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;Type=simple
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;User=mybuilduser
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;Group=mybuildgroup
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Die Kommandos:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;sudo systemctl enable forgejo-runner
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;sudo systemctl start forgejo-runner
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;lassen den neuen &lt;code&gt;forgejo-runner&lt;/code&gt; Dienst dann im Hintergrund ausführen.&lt;/p&gt;

&lt;p&gt;Mein Runner läuft in einer kleinen VM auf meinem Server zu Hause und dieser 
fragt stets den Codeberg Server, ob neue Jobs anstehen.&lt;br /&gt;
Wenn neuer Code per git &lt;code&gt;commit&lt;/code&gt;ed und ge&lt;code&gt;push&lt;/code&gt;t wird, springt der Runner an,
baut alles und lädt das Ergebnis zum Codeberg Server hoch, wo man es für 
einige Tage direkt wieder herunterladen kann.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Hinweis: Es dürfte ein Limit von 10 MB pro Upload gesetzt sein, wer 
mehr hochlädt bekommt HTTP Fehler zurück.&lt;br /&gt;
Ich habe meine Binaries vor dem Upload per&lt;br /&gt;
&lt;code&gt;tar -cJvf artifacts.tar.xz -C ./output-dir/ .&lt;/code&gt; komprimieren lassen, um
nicht zu schnell in das Limit hineinzulaufen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;CI/CD kostenlos und alles mit Open-Source Software.&lt;/strong&gt;&lt;br /&gt;
Wer hätte sich das vor 15 Jahren gedacht?&lt;/p&gt;

&lt;p&gt;Zwar weist das Forgejo-Projekt immer auf seinen Alpha-Status hin und dass noch
einige Fixes fehlen, bis man sich traut “produktiv” genannt zu werden, doch
seitdem ich verstanden habe, wie das Ding funktioniert, liebe ich es.&lt;/p&gt;

&lt;p&gt;Ja … es wäre mir lieber, wenn &lt;a href=&quot;https://de.wikipedia.org/wiki/GitLab&quot;&gt;Gitlab&lt;/a&gt;, 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Bitbucket&quot;&gt;Bitbucket&lt;/a&gt; und Github sich auf ein
YAML Format hätten einigen können, doch da das Setup so einfach umzusetzen ist,
kann jedes GIT-Projekt schnell in ein CI-Projekt umgewandelt werden.&lt;/p&gt;

&lt;p&gt;Codeberg und Forgejo beweisen, dass sie es trotz ihres vergleichsweise kleinen 
Team mit den großen Anbietern aufnehmen können und alle notwendigen modernen 
Features für ein Softwareprojekt bereitstellen können.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Monochrome Bitmaps</title>
   <link href="https://www.opengate.at/blog/2023/10/mono-bitmaps/"/>
   <published>2023-10-29T12:00:00+01:00</published>
   <updated>2023-10-29T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2023/10/mono-bitmaps</id>
   <category term="devel" />
   <summary type="text">Die ersten Bilder, die ich Mitte der 90er auf Disketten speicherte mussten
klein sein. 24-bit Bitmaps waren ein No-Go, weil viel zu groß.
16 Farben mit 4-Bits war aber gerade noch möglich und daher quasi ein Standard.

Und als ich heute mit meiner Eigenimplementierung Probleme feststellte,
lag es an einem noch älteren “besseren” Format, nämlich 1-Bit Schwarz-Weiß
Bitmaps.
</summary>
   <content type="html">&lt;p&gt;Die ersten Bilder, die ich Mitte der 90er auf Disketten speicherte mussten
klein sein. 24-bit Bitmaps waren ein No-Go, weil viel zu groß.
16 Farben mit 4-Bits war aber gerade noch möglich und daher quasi ein Standard.&lt;/p&gt;

&lt;p&gt;Und als ich heute mit meiner Eigenimplementierung Probleme feststellte,
lag es an einem noch älteren “besseren” Format, nämlich 1-Bit Schwarz-Weiß
&lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_Bitmap&quot;&gt;Bitmaps&lt;/a&gt;.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_95&quot;&gt;Windows 95&lt;/a&gt; Setup lädt 
bei der Installation ein blaues Hintergrundbild mit einer den Schirm 
füllenden Tastatur in den Speicher und eben dieses Bild existiert auch weiter
in &lt;code&gt;c:\\Windows&lt;/code&gt;.&lt;br /&gt;
Als ich die Datei mit meinem eigenen Bildbetrachter öffnen wollte, startete
eine längere Debugging Session.&lt;/p&gt;

&lt;p&gt;Denn das “blaue” Windows-95 Setup-Bild ist nämlich eine Schwarz/weiß-Grafik.
Oder besser gesagt eine 1-Bit Grafik mit einer Farbpalette für die Farben
Schwarz und Blau. Das ganze wurde so 
hinge-&lt;a href=&quot;https://de.wikipedia.org/wiki/Dithering_(Bildbearbeitung)&quot;&gt;dither&lt;/a&gt;-t, 
dass es wie ein Farbverlauf aussieht aber keiner ist.&lt;br /&gt;
Und wenn in einem Byte 8 Pixel gespeichert werden können, verringert sich
die sonst unkomprimierte Bildgröße auf ein viertel von dem, was eine 4-Bit
16-Farben Grafik brauchen würde.&lt;/p&gt;

&lt;p&gt;Mein erstes Problem war, dass ich in meinem Code gar nicht auf die richtige
Implementierung umleitete, wenn “1” Bit pro Pixel im Header vermerkt war …
denn solche Bilder gibt es heute überhaupt nicht mehr.&lt;/p&gt;

&lt;p&gt;Doch dieser Bug war schnell behoben, und erst dann wurde zum ersten Mal 
sichtbar, dass meine Mono-Bitmap-Implementierung schon immer falsch
waren.&lt;/p&gt;

&lt;p&gt;Ich ging nämlich davon aus, dass das erste (niederste) Bit im Pixel-Byte auch
gleich dem ersten Pixel selbst entsprach. Doch es ist genau umgekehrt:
Das höherwertige Bit entspricht dem 1. Pixel, und würde etwa so adressiert 
werden:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;unsigned&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt;* line_bytes;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;for&lt;/span&gt;(x = &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;; x &amp;lt; width; ++x)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  pixel_bit = line_bytes[x / &lt;span style=&quot;color:#00D&quot;&gt;8&lt;/span&gt;] &amp;amp; &lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt; &amp;lt;&amp;lt; (&lt;span style=&quot;color:#00D&quot;&gt;7&lt;/span&gt; - (x % &lt;span style=&quot;color:#00D&quot;&gt;8&lt;/span&gt;));
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Ich hatte leider nur ein &lt;code&gt;x % 8&lt;/code&gt; anstatt von das &lt;code&gt;7 - (x % 8)&lt;/code&gt; im Code.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Nun gut, wieder wurde ein kleiner Bug gefixt, und ich habe gelernt, wie
Schwarz/Weiß Grafiken in der Regel im Speicher ausgerichtet sind.&lt;/p&gt;

&lt;p&gt;Tatsächlich sind solche Formate ein wahrere Segen, wenn man wenig
Speicher zur Verfügung hat. Echte Kompression würde oft auch noch
mehr Speicher sparen doch am Ende muss immer alles einmal im
RAM stehen, das wäre dann bei 640x480 Pixel:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;24-Bit Bitmap: 921600 Bytes&lt;/li&gt;
  &lt;li&gt;8-Bit Bitmap:  307200 Bytes&lt;/li&gt;
  &lt;li&gt;4-Bit Bitmap:  153600 Bytes&lt;/li&gt;
  &lt;li&gt;1-Bit Bitmaps:  38400 Bytes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Man sieht also, wie viel Platz man verschwendet, wenn man nur 2 echte
benutzte Farben auf 24-Bit aufblähen würde.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Windows mit libcrypto</title>
   <link href="https://www.opengate.at/blog/2023/10/libcrypto/"/>
   <published>2023-10-28T13:00:00+02:00</published>
   <updated>2023-10-28T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2023/10/libcrypto</id>
   <category term="devel" />
   <summary type="text">Wenn man vergisst die SSL/TSL
Bibliotheken ins Zielverzeichnis zu kopieren, sollte das Laden eines davon 
abhängigen Programms fehlschlagen.
Doch so “zur Hälfte” konnte doch was geladen werden … und das war für mich
ein intessantes Rätsel.

Wie sich herausgestellt hat liefert Microsoft sein Windows seit 2018 offenbar
mit einer libcrypto Variante aus.
</summary>
   <content type="html">&lt;p&gt;Wenn man vergisst die &lt;a href=&quot;https://de.wikipedia.org/wiki/Transport_Layer_Security&quot;&gt;SSL/TSL&lt;/a&gt;
Bibliotheken ins Zielverzeichnis zu kopieren, sollte das Laden eines davon 
abhängigen Programms fehlschlagen.&lt;br /&gt;
Doch so “zur Hälfte” konnte doch was geladen werden … und das war für mich
ein intessantes Rätsel.&lt;/p&gt;

&lt;p&gt;Wie sich herausgestellt hat liefert Microsoft sein Windows seit 2018 offenbar
mit einer &lt;code&gt;libcrypto&lt;/code&gt; Variante aus.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Wer SSL/TLS Features benötigt, ist grundsätzlich von Fremdbibliotheken 
abhängig. Unter Linux war das schon immer so und Windows … naja dort 
eigentlich auch. Die alte (&lt;code&gt;wincrypt&lt;/code&gt;) und neue (&lt;code&gt;bcrypt&lt;/code&gt;) Implementierung
in der WinAPI ist immer auf dem Stand, als die Windows Version auf den
Markt kam … also immer veraltet.&lt;/p&gt;

&lt;p&gt;Zum Glück stehen mit OpenSSL und libreSSL zwei hervorragende Kandidaten
parat, die die Lücke problemlos füllen … wenn man sie eingebunden bekommt.&lt;/p&gt;

&lt;p&gt;Linkt man die beiden Teilbibliotheken &lt;code&gt;libcrypto&lt;/code&gt; und &lt;code&gt;libssl&lt;/code&gt; dynamisch, 
darf man sich beim Deployment ärgern, wenn sie nicht vorhanden sind oder in 
der falschen Version vorliegen.&lt;br /&gt;
Link man sie statisch, hat man garantiert das Richtige dabei, bekommt aber 
eine 2 MB+ große EXE, die sonst nur 200 KB groß gewesen wäre.&lt;/p&gt;

&lt;p&gt;Ich habe daher wie so oft eine duale Strategie für SSL vorgesehen und kann
entweder mit der statischen Variante arbeiten, oder lade zur Laufzeit die
notwendigen Funktionspointer per Hand nach, womit ich ebenso nicht gegen
SSL-Libs linken muss und beim Start einfach die “nächst-greifbare” Variante
geladen wird.&lt;/p&gt;

&lt;h3 id=&quot;windows-10-and-server-2019-mit-libcrypto&quot;&gt;Windows 10 and Server 2019 mit libcrypto&lt;/h3&gt;

&lt;p&gt;Microsoft hat interessanterweise im Jahr 2018 erstmals eine ältere Version
der &lt;code&gt;libcrypto.dll&lt;/code&gt; aus dem libreSSL Projekt ins &lt;code&gt;Windows\\System32&lt;/code&gt; 
Verzeichnis gelegt, jedoch nicht den SSL/TLS Teil.&lt;br /&gt;
Im Server 2016 und älteren Windows-10 IOT Versionen von 2016 ist die DLL noch
nicht vorhanden.&lt;/p&gt;

&lt;p&gt;Genau das führte bei mir zu einigen Problemchen beim “dynamischen” Nachladen
der Funktionalität. Denn statt wie erwartet nichts zu finden, wenn keine
DLLs von mir ausgeliefert werden, wurde plötzlich &lt;code&gt;libcrypto&lt;/code&gt; geladen und
die nachfolgenden &lt;code&gt;libssl&lt;/code&gt; schlug fehl.&lt;/p&gt;

&lt;p&gt;Auf diesen Halbstand war ich nicht vorbereitet und somit musste ich die 
Fehlerbehandlung anpassen.&lt;br /&gt;
… doch aus dieser interessanten Erkenntnis leitet sich ein anderer Vorteil
ab.&lt;/p&gt;

&lt;h3 id=&quot;libssh2-mit-boardmitteln-betreiben&quot;&gt;libssh2 mit Boardmitteln betreiben&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;libssh2&lt;/code&gt; nutzt für den Aufbau von SSH Sitzungen ausschließlich Funktionen der
&lt;code&gt;libcrypto&lt;/code&gt; aber braucht keinen SSL/TLS Support. Bisher musste ich immer eine
vollständige libreSSL oder OpenSSL Schnittstelle bereitstellen, wenn ich SSH
einsetzen wollte … doch mit einem aktuellen Windows kann man diese 
Funktionalität auch vom OS Kern beziehen.&lt;/p&gt;

&lt;p&gt;Da Import-Bibliotheken für die &lt;code&gt;libcrypto&lt;/code&gt; fehlen, habe ich einfach statische
Wrapper um die notwendigen APIs erstellt und nun kann &lt;code&gt;libssh2&lt;/code&gt; gegen meinen
statischen Wrapper linken, der im Hintergrund dann nur die &lt;code&gt;libcrypto&lt;/code&gt; lädt
und die Funktionspointer importiert.&lt;/p&gt;

&lt;p&gt;So entsteht dann eine schlanke SSH Implementierung, die vom OS mitverwaltet 
wird und fette Crypto/SSL Kopien entfallen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;Windows wird langsam OpenSource-tauglich.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ich kann wieder mal nicht nachvollziehen, warum diese freie Bibliothek erst
so spät in Windows Einzug gehalten hat und verstehe schon gar nicht, warum 
der SSL/TLS Teil wieder fehlt.&lt;/p&gt;

&lt;p&gt;Im allgemeinen Fall ist es weiter sicher besser die ganze Crypto/SSL 
Implementierung selbst bereitzustellen … aber für neu entwickelte Tools
ist das Vorhandensein von OpenSource-Kryptographie zumindest mal ein guter
Start.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>NetBSD mit X11</title>
   <link href="https://www.opengate.at/blog/2023/10/netbsd-x11/"/>
   <published>2023-10-22T13:00:00+02:00</published>
   <updated>2023-10-22T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2023/10/netbsd-x11</id>
   <category term="software" />
   <summary type="text">Da installiert man sich ein “kleines und feines” 
NetBSD mit 
SSH Zugang, damit man schnell
mal was drauf kompilieren kann, und dann bekommt man nichts durch den 
Compiler, was X11 benötigt.

Wieso kann man das nicht nachinstallieren?
</summary>
   <content type="html">&lt;p&gt;Da installiert man sich ein “kleines und feines” 
&lt;a href=&quot;https://de.wikipedia.org/wiki/NetBSD&quot;&gt;NetBSD&lt;/a&gt; mit 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Secure_Shell&quot;&gt;SSH&lt;/a&gt; Zugang, damit man schnell
mal was drauf kompilieren kann, und dann bekommt man nichts durch den 
Compiler, was &lt;a href=&quot;https://de.wikipedia.org/wiki/X_Window_System&quot;&gt;X11&lt;/a&gt; benötigt.&lt;/p&gt;

&lt;p&gt;Wieso kann man das nicht nachinstallieren?
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;netbsd-ohne-x11&quot;&gt;NetBSD ohne X11&lt;/h3&gt;

&lt;p&gt;Nach einer minimalen Installation beginnt bei mir meist das “Nachinstallieren”
von Dingen, die man zum Kompilieren und Linken braucht.&lt;br /&gt;
Im Fall des GATE Frameworks gehören da auch UI-Bibliotheken wie X11 dazu.&lt;/p&gt;

&lt;p&gt;Und für gewöhnlich liefert der Paketmanager des Betriebssystems die gewünschten
Binärdateien und Sourcecodes nach.&lt;/p&gt;

&lt;p&gt;Startet man unter NetBSD mit
&lt;code&gt;pkgin install motif&lt;/code&gt; wird ein entsprechendes Paket gefunden … und an der
Stelle beachtete ich nicht weiter, was sonst noch auf der Konsole stand.&lt;/p&gt;

&lt;p&gt;Doch beim Kompilieren erreichte mich sofort die Meldung &lt;code&gt;Xm/Xm.h&lt;/code&gt; würde nicht
gefunden werden, gefolgt von allen möglichen anderen &lt;code&gt;X11/*&lt;/code&gt; Includes.&lt;br /&gt;
&lt;code&gt;Motif&lt;/code&gt; und &lt;code&gt;X11&lt;/code&gt; wurden also nicht installiert.&lt;/p&gt;

&lt;p&gt;Beim erneuten Aufruf von &lt;code&gt;pkgin&lt;/code&gt; sah ich dann schnell, dass “Warnungen” 
ausgegeben wurden, dass &lt;code&gt;/usr/X11R7&lt;/code&gt; nicht existiert, was eine Voraussetzung
für die Installation von Paketen der X11 Familie ist.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;/usr/X11R7/lib/libX11.so.7, needed by libXft-2.3.8nb1 is not present in this system.  
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;0 to remove, 0 to refresh, 0 to upgrade, 0 to install
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;0B to download, 0B of additional disk space will be used
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;the following packages have unmet requirements:   libXft-2.3.8nb1 motif-2.3.8nb3 emwm-1.1nb1
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h3 id=&quot;lösung-upgrade-installation-mit-x11&quot;&gt;Lösung: Upgrade Installation mit X11&lt;/h3&gt;

&lt;p&gt;Unter &lt;code&gt;NetBSD&lt;/code&gt; ist &lt;code&gt;X11&lt;/code&gt; eine Kernkomponente, die nur bei der OS 
Installation auf dem System ausgerollt wird. Man kann sie nicht nachträglich 
über den Paketmanager installieren lassen.&lt;/p&gt;

&lt;p&gt;Man muss also &lt;code&gt;sysinst&lt;/code&gt; aufrufen um die lokale Installation zu erneuern und
dabei können auch X11 und sämtlichen Sourcen installiert werden.&lt;br /&gt;
Das Text-UI lässt einem alles notwendige auswählen und startet danach den
Download und die Integration der neuen Komponenten.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ich bin inzwischen schon so an den (Debian-) Linux Ablauf gewöhnt, immer nur
das Basissystem zu installieren und UI nur bei Bedarf nachzuladen, dass ich 
mir gar nicht mehr vorstellen konnte, dass das auch noch anders ablaufen kann.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;NetBSD&lt;/code&gt; ist eben so ein Fall … und es ist gut, dass ich auch mal
wieder “eine andere Sichtweise” wahrnehmen durfte.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Jekyll update</title>
   <link href="https://www.opengate.at/blog/2023/10/jekyll-update/"/>
   <published>2023-10-21T13:00:00+02:00</published>
   <updated>2023-10-21T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2023/10/jekyll-update</id>
   <category term="software" /><category term="projects" />
   <summary type="text">Als ich 2018 mit der Blog Software Jekyll anfing und damals mit Ubuntu 18.04
und dem Vorgänger 16.04 arbeitete, sah das Setup komplizierter aus, als es 
hätte sein müssen.

Auf heutigen Debian Varianten sind die damaligen Kunstgriffe nicht mehr 
notwendig, teilweise stören sie eher.

Es ist also Zeit, die Doku zu überarbeiten.
</summary>
   <content type="html">&lt;p&gt;Als ich 2018 mit der Blog Software Jekyll anfing und damals mit Ubuntu 18.04
und dem Vorgänger 16.04 arbeitete, sah das Setup komplizierter aus, als es 
hätte sein müssen.&lt;/p&gt;

&lt;p&gt;Auf heutigen Debian Varianten sind die damaligen Kunstgriffe nicht mehr 
notwendig, teilweise stören sie eher.&lt;/p&gt;

&lt;p&gt;Es ist also Zeit, die Doku zu überarbeiten.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;jekyll-ohne-root-rechte-und-systeminstallation&quot;&gt;Jekyll ohne root-Rechte und Systeminstallation&lt;/h3&gt;

&lt;p&gt;Wenn man die &lt;code&gt;Ruby&lt;/code&gt; GEM-Module mittels &lt;code&gt;sudo&lt;/code&gt; installiert, landen sie
in Verzeichnissen, wo sie von normalen Accounts zwar gelesen, aber nicht
editiert werden können.&lt;/p&gt;

&lt;p&gt;Die aktuelle Empfehlung für eine Jekyll Installation sieht also so aus,
dass man die GEMs im &lt;code&gt;HOME&lt;/code&gt; Verzeichnis ablegt.&lt;br /&gt;
Hierfür nutzt man am besten die Umgebungsvariable &lt;code&gt;GEM_HOME&lt;/code&gt;, und fügt den
&lt;code&gt;bin&lt;/code&gt;-Pfad der GEMs der &lt;code&gt;PATH&lt;/code&gt; Variable hinzu.&lt;/p&gt;

&lt;p&gt;Die Installation sieht dann so aus&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;sudo apt-get install ruby-full build-essential zlib1g-dev -y
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;echo &apos;# Install Ruby Gems to ~/gems&apos; &amp;gt;&amp;gt; ~/.bashrc
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;echo &apos;export GEM_HOME=&amp;quot;$HOME/gems&amp;quot;&apos; &amp;gt;&amp;gt; ~/.bashrc
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;echo &apos;export PATH=&amp;quot;$HOME/gems/bin:$PATH&amp;quot;&apos; &amp;gt;&amp;gt; ~/.bashrc
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;source ~/.bashrc
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Ist der Pfad-Export erst in &lt;code&gt;.bashrc&lt;/code&gt; angefügt, stehen die aktualisierten
Variablen in jeder neuen Shell-Sitzung zur Verfügung.&lt;/p&gt;

&lt;p&gt;Nun reicht ein einfaches&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;cd /path/to/my-jekyll-project
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;bundler install
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;bundler update
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;um alle notwendigen Abhängigkeiten zu erhalten.&lt;/p&gt;

&lt;p&gt;Am Ende kann &lt;code&gt;bundler exec jekyll build&lt;/code&gt; oder &lt;code&gt;... serve&lt;/code&gt; beweisen, dass die 
Webseite neu generiert werden kann.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Langsam wird es Zeit, dass ich alle meine Dokus mal verifiziere und schaue, 
ob sie noch funktionieren. Denn mit jeder neuen OS-Version gibt es Änderungen
und schon funktionieren beschriebene Scripts des Vorgängers nicht mehr oder
zumindest nicht mehr vollständig.&lt;/p&gt;

&lt;p&gt;In Sachen Jekyll hat sich die Prozedur sehr vereinfacht.&lt;br /&gt;
Und während damals noch Jekyll v3 im Einsatz war, läuft heute v4 und bringt
einige Verbesserungen mit sich.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>ZLIB ohne Level 9</title>
   <link href="https://www.opengate.at/blog/2023/10/zlib-level-9/"/>
   <published>2023-10-15T13:00:00+02:00</published>
   <updated>2023-10-15T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2023/10/zlib-level-9</id>
   <category term="devel" />
   <summary type="text">Viele Probleme meiner Arbeit am GATE Projekt liegen bei den Compilern.
Man würde glauben, wenn dieses gelöst sind, also alles kompiliert, wäre man
fertig.

Leider nicht ganz, denn plötzlich schlägt z.B.: die Initialisierung der 
ZLIB zur Laufzeit fehl.
</summary>
   <content type="html">&lt;p&gt;Viele Probleme meiner Arbeit am GATE Projekt liegen bei den Compilern.
Man würde glauben, wenn dieses gelöst sind, also alles kompiliert, wäre man
fertig.&lt;/p&gt;

&lt;p&gt;Leider nicht ganz, denn plötzlich schlägt z.B.: die Initialisierung der 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Zlib&quot;&gt;ZLIB&lt;/a&gt; zur Laufzeit fehl.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Die ZLIB nutzt beim Komprimieren einige Parameter wie etwas
Compression-Level, Memory-Level und Window-Bits.
Hierfür existieren Konstanten wie&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;compression-level: &lt;code&gt;Z_BEST_COMPRESSION&lt;/code&gt; (==&lt;code&gt;9&lt;/code&gt;)&lt;/li&gt;
  &lt;li&gt;memory-level: &lt;code&gt;MAX_MEM_LEVEL&lt;/code&gt; (==&lt;code&gt;9&lt;/code&gt;)&lt;/li&gt;
  &lt;li&gt;window-bits: &lt;code&gt;MAX_WBITS&lt;/code&gt; (==&lt;code&gt;15&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Da ich die besten Ergebnisse haben möchte, nutzte ich diese Werte als Standard
in meine Codes, nur das Compression-Level war von außen einstellbar.&lt;/p&gt;

&lt;p&gt;Unter DOS kompiliert dieser Code zwar, kann jedoch dann nicht ausgeführt 
werden, es kommt zum Abbruch der Initialisierung in &lt;code&gt;deflateInit2_()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Mit jeder Menge &lt;code&gt;printf()&lt;/code&gt; Debugging kam ich dann zu den Zeilen, die die
Parameter umsetzen und hier findet die Allokation eines Puffers statt,
die vereinfacht so aussieht:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;Byte* window = malloc((&lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt; &amp;lt;&amp;lt; window_size) * &lt;span style=&quot;color:#00D&quot;&gt;2&lt;/span&gt; * &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;sizeof&lt;/span&gt;(Byte));
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Bei &lt;code&gt;2^15 * 2&lt;/code&gt; landen wir bei &lt;code&gt;2^16&lt;/code&gt; bytes, also 65536. Theoretisch würde das
ein vollständiges DOS Segment sein, doch mit malloc können wir kein ganzes 
Segment in einem kapern.&lt;/p&gt;

&lt;p&gt;Etwas ähnliches passiert dann auch noch beim Memory-Level, denn da wird zum
Level &lt;code&gt;7&lt;/code&gt; addiert, womit man auch wieder auf 16 Bits kommt.&lt;/p&gt;

&lt;h3 id=&quot;lösung-kleinere-parameter&quot;&gt;Lösung: Kleinere Parameter&lt;/h3&gt;

&lt;p&gt;Meine Lösung war dann denkbar einfach (und wurde zusätzlich auch gleich auf
Windows CE angewendet):&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#if&lt;/span&gt; defined(GATE_SYS_WINCE) || defined(GATE_SYS_DOS)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;        &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; memlevel = MAX_MEM_LEVEL - &lt;span style=&quot;color:#00D&quot;&gt;2&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;        &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; window_bits = MAX_WBITS - &lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#else&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;        &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; memlevel = MAX_MEM_LEVEL;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;        &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; window_bits = MAX_WBITS;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#endif&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Mit den gepatchten Parameter läuft die ZLib brav weiter und generiert mit
&lt;code&gt;deflate&lt;/code&gt; komprimierte Ergebnisse, allerdings sind die jetzt potentiell
etwas schlechter, weil die Wörterbücher kleiner sind. Aber damit kann
man auf diesen Plattformen leben.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ab sofort kann das &lt;code&gt;arch&lt;/code&gt; Tool &lt;code&gt;.gz&lt;/code&gt; und &lt;code&gt;.zip&lt;/code&gt; Archive erzeugen und auch
wieder unter DOS auspacken.&lt;br /&gt;
Damit bin ich schon zufrieden.&lt;/p&gt;

&lt;p&gt;Ich müsste jetzt noch Tests mit Archiven machen, die unter Windows oder Linux
erzeugt wurden und größere Window-Bits hatten und ob die beim Entpacken
Probleme machen. Allerdings sehe ich im &lt;code&gt;inflate()&lt;/code&gt; Code keine Allokationen,
die davon abhängen, zumindest nicht bei der Initialisierung.&lt;/p&gt;

&lt;p&gt;DOS ist inzwischen eine wichtige Plattform für mich geworden, um zu
verifizieren, ob Code wirklich plattformunabhängig läuft.
Die Window-Bits sind ein schönes Beispiel für Einschränkungen, die man 
einfach nur wissen muss, um sie mit wenig Code überwinden zu können.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>AD Server Transfer auf N100</title>
   <link href="https://www.opengate.at/blog/2023/10/ad-fsmo/"/>
   <published>2023-10-14T13:00:00+02:00</published>
   <updated>2023-10-14T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2023/10/ad-fsmo</id>
   <category term="software" /><category term="hardware" />
   <summary type="text">Mit meinem neuen N100 
basiertem Board, das als neuer Domain-Controller arbeiten darf, 
endet die 5-Jahres-Mission meines E3940 Systems.

Ein kritischer Punkt ist immer die korrekte Übertragung der 
Active Directory
Rolle, und diesmal geschah das “geordnet” und nicht einfach durch hartes
Umschalten.

</summary>
   <content type="html">&lt;p&gt;Mit meinem neuen &lt;a href=&quot;https://www.intel.de/content/www/de/de/products/sku/231803/intel-processor-n100-6m-cache-up-to-3-40-ghz/specifications.html&quot;&gt;N100&lt;/a&gt; 
basiertem Board, das als neuer Domain-Controller arbeiten darf, 
endet die 5-Jahres-Mission meines E3940 Systems.&lt;/p&gt;

&lt;p&gt;Ein kritischer Punkt ist immer die korrekte Übertragung der 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Active_Directory&quot;&gt;Active Directory&lt;/a&gt;
Rolle, und diesmal geschah das “geordnet” und nicht einfach durch hartes
Umschalten.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Ein neuer N100 4-Kern max-3.4 GHz Prozessor löst nun den max-1.8 GHz 
Intel Atom x5 in meinem Wohn/arbeitszimmer ab. Ich erwarte mir vom Sprung von 
14 auf 7nm und von dder Verdoppelung der Maximalleistung schon einiges an 
Geschwindigkeitzugewinn.&lt;br /&gt;
Auch darf der neue Knecht mit 16 GB RAM werken, während sein Vorgänger nur 8 GB
vertrug.&lt;/p&gt;

&lt;h3 id=&quot;active-directory-server-umbenennen&quot;&gt;Active Directory Server umbenennen&lt;/h3&gt;

&lt;p&gt;Unter dem Namen &lt;code&gt;SVR01&lt;/code&gt; spreche ich schon lange mein “Primärsystem” an, das
rund um die Uhr läuft. Blöd ist nur, wenn man einem neuen System diesen Namen
geben will und daher war mein Idee, das alte Gerät im AD Verband umzubenennen,
und das neue System mit dem somit wieder freiem Namen frisch als Server aufzunehmen.&lt;/p&gt;

&lt;p&gt;Der alte Server &lt;code&gt;SVR01&lt;/code&gt; sollte auf &lt;code&gt;SVR99&lt;/code&gt; umgenannt werden, während mein
zweiter Domaincontroller &lt;code&gt;SVR02&lt;/code&gt; “zur Sicherheit” mitlief.&lt;/p&gt;

&lt;p&gt;Die vorgeschlagene Prozedur war einen “zusätzlichen” Namen dem Server
hinzuzufügen mit:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;netdom computername oldname.domain.tld /add:newname.domain.tld
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Dann einen Reboot durchführen und den neuen Namen als Primärnamen zu 
deklarieren mit:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;netdom computername oldname.domain.tld /makeprimary:newname.domain.tld
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Und nach einem weiteren Reboot kann man den alten Namen per:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;netdom computername newname.domain.tld /remove:oldname.domain.tld
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;entfernen.&lt;/p&gt;

&lt;p&gt;Tatsächlich funktionierte das auch so. Allerdings traten gleich nach der
&lt;code&gt;netdom&lt;/code&gt; Ausführung mehrere Fehler in diversen MMC Modulen auf, die dann ihren
Server nicht mehr finden konnten.&lt;/p&gt;

&lt;p&gt;Doch aus diese Probleme lassen sich per Reboot “gesundstreicheln”.&lt;/p&gt;

&lt;h3 id=&quot;fsmo-rollentransfer&quot;&gt;FSMO Rollentransfer&lt;/h3&gt;

&lt;p&gt;Die 5 FSMO-Rollen (Flexible Single Master Operation) können jeweils nur von
einem Server ausgeübt werden, alle anderen leiten die Anfragen an den “Master”
weiter.&lt;br /&gt;
In meinem Fall liegen alle gemeinsam auf einem Server, da alle andere Maschinen
nur bei Bedarf eingeschaltet werden.&lt;/p&gt;

&lt;p&gt;Ich fand es schon vor 20 Jahren seltsam, dass Microsoft die UIs zur Übertragung
einer Rolle an so unterschiedlichen Orten versteckt hat:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Die Rollen für den “RID”, “PDC” und “Infrastructure” Master findet man unter
“Users and Computers”
&lt;img src=&quot;/blog/assets/img/ad-domain-roles.png&quot; alt=&quot;FSMO Domain Roles&quot; /&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Die “Domain Naming” Rolle ist unter “Domains and Trusts” versteckt.
&lt;img src=&quot;/blog/assets/img/ad-name-role.png&quot; alt=&quot;FSMO Naming Roles&quot; /&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Und der “Schema” Master Dialog befindet sich im MMC Snap-in 
“Active Directory Schema”
&lt;img src=&quot;/blog/assets/img/ad-schema-role.png&quot; alt=&quot;FSMO Schema Role&quot; /&gt;&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Doch dieses Schema-Snap-In ist auf Standard-Installationen gar nicht zugänglich.
Man muss erst &lt;code&gt;regsvr32 schmmgmt.dll&lt;/code&gt; zur Registrierung aufrufen und kann dann
in einer leeren &lt;code&gt;mmc.exe&lt;/code&gt; Sitzung unter “Add/Remove Snap-in” das Schema-Snap-in
einfügen.&lt;/p&gt;

&lt;p&gt;Man hätte das auch &lt;a href=&quot;/blog/2021/10/server-2022/&quot;&gt;per ADSI-Edit manuell setzten&lt;/a&gt;
können, doch wenn möglich, sollte man immer den “offiziellen” Weg gehen. Wer
weiß schon, was Microsoft im Hintergrund mit jeder neuen Version verändert.&lt;/p&gt;

&lt;h3 id=&quot;workfolder-neu-einrichten&quot;&gt;Workfolder neu einrichten&lt;/h3&gt;

&lt;p&gt;Mit dem neuen Server waren natürlich auch meine Workfolder weg. Sie waren natürlich
noch da, und zwar am alten Server, und als Kopie auf meiner lokalen Maschine, doch
eben nicht mehr “synchronisiert”.&lt;/p&gt;

&lt;p&gt;Beim Aufsetzen der Workfolder fing wieder das elende Spiel mit den Zertifikaten an.
Man musste eines mit dem richtigen Namen erstellen, dann für das HTTPS Protokoll für
die Workfolders freigeben und sicherstellen, dass ihm auch am Client vertraut wird.&lt;/p&gt;

&lt;p&gt;Meine Umstellung fiel zufällig genau auf die Woche, wo mein altes Zertifikat 
ausgelaufen war und ich mich wirklich lange wunderte, warum alle Verbindungen
abgebrochen wurden.&lt;/p&gt;

&lt;p&gt;Wie toll wäre es hierfür ein Testprogramm zu haben, dass einem genau sagt, warum
die Synchronisation nicht funktioniert. So musste ich zwei Stunden herumraten,
doch am Ende klappte auch das wieder.&lt;/p&gt;

&lt;h3 id=&quot;server-backup&quot;&gt;Server Backup&lt;/h3&gt;

&lt;p&gt;Der letzte Schritt war die Neueinrichtung des Server Backups.
Das war auf der bestehenden Platte nur möglich, wenn die alten Backups gelöscht
wurden, doch da ich ohnehin alles doppelt gesichert hatte, war das auch noch
zu verkraften.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Mein neuer kleiner ITX Server ist erstmals kein originaler Intel Atom mehr,
denn von denen gibt es keinen leistbaren in der neuen Fertigungstechnik.
Dennoch überzeugt der N100 auf Anhieb und rechnet dann auch wirklich
doppelt so schnell die Windows-Update Hashes durch.&lt;/p&gt;

&lt;p&gt;Größter Pluspunkt ist, dass ich jetzt endlich einen funktionierenden
Grafikkartentreiber am Server habe.&lt;br /&gt;
Ich brauche am Domaincontroller zwar keine UI-Power, aber die Fixierung 
auf den Microsoft-Basic VGA-Treiber, weil ansonsten Blue-Screens flogen,
war schon ziemlich nervig.&lt;/p&gt;

&lt;p&gt;Ich bin jedenfalls mit dem Update zufrieden und freue mich, dass der
Active Directory Transfer diesmal so problemlos funktioniert hat.&lt;/p&gt;

&lt;p&gt;Mal sehen, ob ich in 5 Jahren dann wieder einen solchen Hardwarewechsel
durchführe, oder ob das dann schon ein Roboter für mich erledigt.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Serien: Loki 2, Ahsoka, Ragnarök</title>
   <link href="https://www.opengate.at/blog/2023/10/loki/"/>
   <published>2023-10-08T13:00:00+02:00</published>
   <updated>2023-10-08T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2023/10/loki</id>
   <category term="entertainment" />
   <summary type="text">Während ich gespannt auf die neue Loki Serie auf Disney+ gewartet habe,
kamen auch andere Titel heraus, in die ich hineinschnuppern wollte.
Das Star Wars Franchise kann mit “Ahsoka” aufwarten und bei Netflix entdeckte
ich zufällig eine andere “Loki-Variante” in der norwegisch-dänischen 
Serie Ragnarök

Die Abendunterhaltung ist also gesichert.
</summary>
   <content type="html">&lt;p&gt;Während ich gespannt auf die neue &lt;code&gt;Loki&lt;/code&gt; Serie auf Disney+ gewartet habe,
kamen auch andere Titel heraus, in die ich hineinschnuppern wollte.
Das Star Wars Franchise kann mit “Ahsoka” aufwarten und bei Netflix entdeckte
ich zufällig eine andere “Loki-Variante” in der norwegisch-dänischen 
Serie &lt;a href=&quot;https://de.wikipedia.org/wiki/Ragnar%C3%B6k_(Fernsehserie)&quot;&gt;Ragnarök&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Die Abendunterhaltung ist also gesichert.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;marvels-loki-staffel-2&quot;&gt;Marvels Loki Staffel 2&lt;/h3&gt;

&lt;p&gt;Es geht weiter mit &lt;code&gt;Loki Laufeyson&lt;/code&gt;, dem aus der Zeit gefallenen Variante des
Gottes des Schabernaks, und wie er nun mit der neuen TVA 
umgehen soll.&lt;/p&gt;

&lt;p&gt;Am Ende der ersten Staffel sollte eine Entscheidung getroffen werden.
Zwei Lokis am Ende der Zeit. 
“Die eine” (&lt;a href=&quot;https://de.wikipedia.org/wiki/Sophia_Di_Martino&quot;&gt;Sophia Di Martino&lt;/a&gt;)
wild entschlossen die Zeitstrahlen vom Diktat der Time Variance Authority zu 
befreien und “unser” Loki &lt;a href=&quot;https://de.wikipedia.org/wiki/Tom_Hiddleston&quot;&gt;Tom Hiddleston&lt;/a&gt;,
der den seltsamen Verwaltungsapparat, der die Zeitstrahlen kontrolliert, 
zunehmend als notwendiges Übel ansieht.&lt;/p&gt;

&lt;p&gt;Ich bin wirklich verdammt gespannt, wie dieses Geschichte nun weitergesponnen
wird. Loki selbst springt jetzt offenbar unkontrolliert durch die Zeit und
lernt daher jede Situation aus einem anderen Blickwinkel kennen.
Dieser Handlungsstrang hat klar meine volle Aufmerksamkeit.&lt;/p&gt;

&lt;p&gt;Ich bin also gespannt, wie die Serie am Ende aussehen wird.&lt;/p&gt;

&lt;h3 id=&quot;ragnarök&quot;&gt;Ragnarök&lt;/h3&gt;

&lt;p&gt;Näher am Original der nordischen Mythologie bewegt sich die Serie
&lt;a href=&quot;https://de.wikipedia.org/wiki/Ragnar%C3%B6k_(Fernsehserie)&quot;&gt;Ragnarök&lt;/a&gt;, 
die aktuell auf &lt;a href=&quot;https://de.wikipedia.org/wiki/Netflix&quot;&gt;Netflix&lt;/a&gt; ausgestrahlt
wird.&lt;/p&gt;

&lt;p&gt;Hier findet ein Art Reinkarnation der Götter Thor und Loki in zwei
Teenagerbrüdern statt, die in den Mitgliedern eines lokalen 
Familienunternehmens ihre Feinde finden, nämlich die unsterblichen Riesen 
(Jötun), gegen welche die Götter früher bereits antreten mussten.&lt;/p&gt;

&lt;p&gt;Während die sehr menschlich aussehenden “Riesen” die Welt mit 
Umweltverschmutzung bedrohen, müssen die Teenager erst ihre göttlichen
Kräfte entdecken. Beide Seiten bekommen Hilfe von diversen anderen
mythischen Personen und Ritualen, bis es dann immer wieder mal zum
Kampf kommt.&lt;/p&gt;

&lt;p&gt;Ein bisschen erinnert es mich an die Twilight-Story. Sie hat dem
Vampirmythos nicht immer gut getan … aber hat ihn trotzdem auch 
wieder aufblühen lassen.&lt;br /&gt;
Ragnarök könnte das Gleiche auch mit der nordischen Mythologie durchmachen.&lt;/p&gt;

&lt;p&gt;Es ist zwar mehr als seltsam, wenn sich ein junger Thor primär über die
Chatnachrichten einer Schulkollegin den Kopf zerbricht, und wenn Loki
als Transvestit neue Persönlichkeitsformen durchlebt … aber, so ist
die Welt heute nun mal.&lt;/p&gt;

&lt;p&gt;Und es fällt positiv auf, dass sich die Produzenten viele Gedanken darüber
gemacht haben, wie sie Stücke aus den alten Überlieferungen detailreich
ins 21. Jahrhundert übersetzen können.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ab in den Norden!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ich finde, dass wir über die Götter des Nordens vergleichsweise wenig wissen.
Griechenland und Rom wie auch alle Stationen des Christen- und Judentums 
wurden tausendfach verfilmt und neu erzählt.&lt;/p&gt;

&lt;p&gt;Jeder kennt die alten Propheten und wer mit Zeus im Bett war, weil wir es 
schon im Fernsehen gesehen haben.
Thor und Loki kennen wir nur in sehr verfremdeter Art aus den 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Marvel_Studios&quot;&gt;Marvel&lt;/a&gt; Universum,
aber sonst wissen wir recht wenig darüber.&lt;/p&gt;

&lt;p&gt;Ich freue mich also, dass nun auch nicht-Marvel-Serien diesen Themenbereich 
aufgreifen.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Das 5. Blog-Jahr</title>
   <link href="https://www.opengate.at/blog/2023/10/blog-v5/"/>
   <published>2023-10-07T13:00:00+02:00</published>
   <updated>2023-10-07T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2023/10/blog-v5</id>
   <category term="projects" />
   <summary type="text">Ich mag ja meine Beiträge hier recht unstet veröffentlichen, aber es sieht
so aus, als bleibt mir die Motivation weiter erhalten.

Seit Oktober 2018 sammle ich meine Lebenseindrücke als Entwickler und ich
glaube, das bringt auch was.
</summary>
   <content type="html">&lt;p&gt;Ich mag ja meine Beiträge hier recht unstet veröffentlichen, aber es sieht
so aus, als bleibt mir die Motivation weiter erhalten.&lt;/p&gt;

&lt;p&gt;Seit Oktober 2018 sammle ich meine Lebenseindrücke als Entwickler und ich
glaube, das bringt auch was.
&lt;!--more--&gt;&lt;/p&gt;

&lt;p&gt;2018 es mir daran gelegen, einiges niederzuschreiben, was mir 
“schon lange unter den Nägeln brannte”.&lt;br /&gt;
Inzwischen hat sich der Brand gelegt und nun sind es aktuelle Themen wie
auch Erinnerungen an manche Ereignisse, die den Blog vorantreiben.&lt;/p&gt;

&lt;p&gt;Ich lerne aktuell viel aus der Vergangenheit, wenn ich z.B. für DOS
Codes umschreiben muss, damit sie stückweise in 64 KB Segmente passen.
Genau das macht dann aber auch Windows und Linux Code besser, wenn nicht
immer gleich ein Gigabyte RAM aquiriert wird und dann das Paging anspringt.&lt;/p&gt;

&lt;p&gt;Gleichzeitig treiben mich Neuentwicklungen im Web oder auch aus dem Beruf zu
Sprachen wie Python, Rust oder 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Zig_(Programmiersprache)&quot;&gt;ZIG&lt;/a&gt;, was mich auch
wieder Codes und Interfaces überdenken lässt.&lt;/p&gt;

&lt;p&gt;Manchmal denke ich mir, ich könnte nach 20 Jahren eigentlich schon die Nase 
voll haben von der Softwareentwicklung … doch diese Welt ist so unglaublich
groß, unterschiedlich und fordernd, dass ich mir tatsächlich vorstellen kann, 
dass mich das weitere 20 Jahre voll ausfüllt.&lt;/p&gt;

&lt;p&gt;Und in diesem Sinne darf auch der Blog noch möglichst lange hier mitlaufen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;Also auf geht’s in die nächste Runde!&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>Kreta</title>
   <link href="https://www.opengate.at/blog/2023/10/crete/"/>
   <published>2023-10-01T13:00:00+02:00</published>
   <updated>2023-10-01T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2023/10/crete</id>
   <category term="general" />
   <summary type="text">Zuletzt hatte ich mich vor 10 Jahren in ein Flugzeug gesetzt. Nun war es
wieder so weit um eine Woche auf der südlichen griechischen Insel 
Kreta zu verbringen.
</summary>
   <content type="html">&lt;p&gt;Zuletzt hatte ich mich vor 10 Jahren in ein Flugzeug gesetzt. Nun war es
wieder so weit um eine Woche auf der südlichen griechischen Insel 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Kreta&quot;&gt;Kreta&lt;/a&gt; zu verbringen.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Es war nicht nur ein Geburtstagsgeschenk an meine Mutter, sondern auch eine
Erinnerung an die 90er. Damals flogen Großmutter, Mutter und ich fast jedes
Jahr in den Ferien an irgend einen Strand um dort auszuspannen.&lt;/p&gt;

&lt;p&gt;Nach vielen Jahren beschlossen somit meine Mutter und ich, dieser Tradition 
gedenkend, ebenso nochmal eine Reise gemeinsam anzutreten.&lt;/p&gt;

&lt;h3 id=&quot;von-der-buchung-zum-flug&quot;&gt;Von der Buchung zum Flug&lt;/h3&gt;

&lt;p&gt;Nachdem uns täglich Werbeangebote der BILLA Supermarktkette ins Haus fliegen
und diese ebenso Urlaubsreisen anbieten, war unser Anbieter schnell gefunden.
Schließlich wollten wir keine Action-reiches Programm, sondern einfach nur 
eine Woche “chillen”, wie man heute sagt.&lt;/p&gt;

&lt;p&gt;Vor dem Jahr 2000 fuhren wir entweder 30 km in eine andere Stadt um ein
Reisebüro zu finden, oder wir konnten im “Reiseangebot”, des hiesigen
Bankschalters etwas finden.&lt;/p&gt;

&lt;p&gt;Heute erledigt das der Webshop ganz genau so wie er das für alle anderen
Alltagsprodukte abdeckt. Das Reisepaket wird für X Personen gewählt und
die Kontaktdaten werden übergeben. 10 Minuten später erhält man die 
Zahlingsinformationen für die Online-Überweisung.&lt;/p&gt;

&lt;p&gt;Ein bisschen Zeit vergeht zwischen der Zahlung und der Bestätigung. 
Heute erwartet man die Fertigstellung binnen Minuten automatisch, doch bei
einer Reise, sitzt noch ein Mensch am anderen Ende und gibt die Bestellung
erst 2-3 Tage später frei, wenn die Zahlung eingegangen ist.&lt;/p&gt;

&lt;p&gt;Nicht inkludiert war unser Transport zum Flughafen Wien-Schwechat. Eine
günstige Option ist entweder mit der Bahn hinzufahren oder das Auto zu
nehmen und dort eine Woche am Parkplatz abzustellen.&lt;br /&gt;
Interessant waren die Kosten, die beim Flughafenparkplatz selbst bei 120
Euro für eine Woche starteten.
Der neben dem Flughafen liegende 
&lt;a href=&quot;https://www.mazur-parken.at/&quot;&gt;Mazur Parkplatz&lt;/a&gt; kostet nur 75 Euro pro Woche
und bietet einen Shuttledienst alle 20 Minuten zum Flughafeneingang.
Für dieses günstige Angebot entschieden wir uns dann.&lt;/p&gt;

&lt;p&gt;Der Online-Checkin des Fluges war erst genau 24 Stunden vor Abreise 
durchführbar. Letztendlich tippt man dort nur Namen, Mailadresse und Alter ein
und kann dann “Zusatzdienste” wie “mehr Gepäck”, Sitzplatzwahl oder Snacks 
während des Flugs wählen.&lt;br /&gt;
Diese Dienste lassen sich bei der Bestellung nur per Kreditkarte abwickeln,
und nachdem ich meine zurückgegeben hatte, konnte ich keine dieser Optionen
nutzen.&lt;/p&gt;

&lt;p&gt;Meine Befürchtung, wir würden jetzt irgendwo im Flugzeug verteilt sitzen, trat
aber nicht ein, und wir bekamen zwei Plätze nebeneinander automatisch zugewiesen.&lt;/p&gt;

&lt;p&gt;Da bei den Online-Boardtickets extra dabei stand, man solle sie ausdrucken, tat
ich das auch und kam “klassisch” mit Klemmbrett zum Flughafen.&lt;br /&gt;
Aber wie erwartet wäre das nicht notwendig gewesen, denn das Scannen des 
Bar-Codes der digitalen Karte funktionierte auch einfach per Smartphone
und so kann man auch papierlos abreisen.&lt;br /&gt;
Per Mail geschickt bekommen hatten wir auch PDFs mit Transfer- und Hotel 
“Voucher”, die ich zur Sicherheit ebenfalls im Handgepäck hatte.&lt;/p&gt;

&lt;h3 id=&quot;reif-für-die-insel&quot;&gt;Reif für die Insel&lt;/h3&gt;

&lt;p&gt;Auch am Zielflughafen in Heraklion klappte alles problemlos. Wir trotteten vom
Flugzeug zu den Gepäcksbändern und danach aus dem Flughafengebäude, wo direkt
gegenüber kleine Kabinen mit allen möglichen Touristik-Unternehmen aufgestellt
waren. Die für uns zuständige Reisehelferin, fand unsere Namen auf ihrer Liste
und verwies uns zum nächsten Bus mit Nummer X, der das Gepäck verlud und uns 
zum Zielhotel brachte.&lt;/p&gt;

&lt;p&gt;Auch dort füllten wir nur noch unsere Daten im Hotelformular aus und schon 
ging es ab auf die Zimmer.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Also kurz gesagt: Alles war unkompliziert und einfach.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In den folgenden Tagen genossen wir schönes Wetter, lange Spaziergänge
und vor allem das üppige köstliche Essen.&lt;br /&gt;
Nur das Meer war uns schon zu reißerisch. Kretas Küste ist sehr felsenreich
und in unserer Gegend in Chersonissos Stadt waren Standstrände eher klein 
gehalten und immer wieder von scharfen Felsen und Gestein unterbrochen.&lt;/p&gt;

&lt;p&gt;Der Wellengang war Ende September/Anfang Oktober zwar noch nicht extrem,
doch die mutigen Gäste, die sich ins Wasser wagten, wurden schon ganz schön
gefordert. Und als wir dann noch eine ältere Dame sahen, die im Wasser 
unglücklich gestürzt war, sich eine Krampfader aufgeschlagen hatte und
das Blut nur so sprizte, meinten wir:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Hey, wir müssen eigentlich gar nicht zwingend ins Wasser!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Die griechische Touristenkultur ist nett und aufgeschlossen … manchmal
vielleicht auch ein bisschen zu sehr aufgeschlossen, wenn einem ein
Kleidungsstück 5 mal versucht wird zum Kauf anzutragen, aber in Summe 
war an jeder Ecke was zu entdecken und sowohl das äußere wie auch das
persönliche Klima perfekt.&lt;/p&gt;

&lt;p&gt;Dass im August hier bis zu 50 Grad geherrscht haben sollen, will ich mir 
nicht vorstellen, denn das wäre die Hölle gewesen. Doch Ende September
mit 23 bis 28 hat es für uns genau gepasst.&lt;/p&gt;

&lt;p&gt;Lediglich die Nächte waren für uns ungewohnt warm, was aber mit
der Klimaanlage ausgeglichen werden konnte.
Und auch die Verbindung zur Heimat riss nie ab, denn Internet gab es - 
zu meiner Freude - mit voller Bandbreite kostenlos.&lt;br /&gt;
(Das war vor 10 Jahren noch kein Standard in Hotels).&lt;/p&gt;

&lt;h3 id=&quot;rückreise&quot;&gt;Rückreise&lt;/h3&gt;

&lt;p&gt;Genau wie vor dem Hinflug war auch der Online-Checkin für die Rückreise
24 Stunden vor dem Flug möglich und wieder genau so unkompliziert.
Die Rezeption half beim Ausdrucken von Formularen und bei der Planung
von Frühstück und der Busabholung.&lt;/p&gt;

&lt;p&gt;Letztlich kamen wir wieder am Flughafen an, mussten nur die Nummer
unseres Gepäck-Checkins an einem der Monitore ablesen, das Gepäck aufgeben
und hatten noch etwas Zeit bis der Flug nach Wien zum Boarding fertig war.&lt;/p&gt;

&lt;p&gt;Und während unsere Reise wirklich perfekt einfach war, taten mir zahlreiche
andere Fluggäste leid, die dort seit Stunden auf ihren Flug warteten und 
einfach nicht wegkamen. Eine andere Perversion war dann, die Ausrufung eines
Fluggastes über 90 Minuten hinweg, der immer mit den Worten
“Last call for …” eingeleitet wurde.&lt;br /&gt;
Ich meine, da sitzen 100e Leute in einem Flieger, warten dass er startet und
dann tut sich nichts, weil ein Typ fehlt.&lt;/p&gt;

&lt;p&gt;Naja … hier kann ich nur sagen: Was für ein Glück, dass bei uns alles
so reibungslos verlief.&lt;/p&gt;

&lt;p&gt;In Wien angekommen fiel uns nur eines deutlich auf: der Flughafen muss 10 mal
größer sein, als der auf Kreta. Alleine die Gehwege waren der Wahnsinn und
offen gesagt für ältere Personen durchaus herausfordernd.&lt;/p&gt;

&lt;p&gt;Dennoch bekamen wir unser Gepäck, fanden zur Shuttledienst-Haltestelle, wo
uns der Bus zum Auto brachte … und dann … tja dann war die schöne
Woche auch leider schon wieder vorbei.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ich bin ja eigentlich ein Flugmuffel und stets besorgt, was da alles schief
gehen kann. Doch hier muss ich ganz klar sagen:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Gerne wieder!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Das einzige, was nicht funktioniert hat, war die Zubuchung per Kreditkarte,
da ich ja keine hatte. Hier frage ich mich schon, warum alle Shops, und die
Reise selbst mehrere Zahlungsoptionen inklusive PayPal bieten, und nur die
Fluglinie selbst für die Sitzplatzwahl auf Kreditkarte besteht.
Aber naja … notwendig war’s ja nicht, ist also auch egal.&lt;/p&gt;

&lt;p&gt;In diesem Sinne geht man Dank an Kreta und die schöne Woche, die wir dort
verbringen durften.
Und wenn es möglich wäre, dann hätte ich gerne einen 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Souvlaki&quot;&gt;Souvlaki&lt;/a&gt; Koch hier bei mir.
Verdammt, ich vermisse es am Abend im Buffet alles durchprobieren zu können,
und am Ende dann noch so einen leckeren Spieß zu verzehren.&lt;/p&gt;

&lt;p&gt;Das Essen war echt großartig (wie mein Bauch auch immer noch anzeigt).&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>GIT Migration</title>
   <link href="https://www.opengate.at/blog/2023/09/git-migration/"/>
   <published>2023-09-30T13:00:00+02:00</published>
   <updated>2023-09-30T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2023/09/git-migration</id>
   <category term="devel" />
   <summary type="text">Bei einer Migration stellt sich immer die Frage:

  Was nehme ich mit? Was lasse ich zurück?


Die GIT History ist so ein Thema, denn 
die will man meistens behalten, um Entwicklungsschritte nachvollziehen zu 
können. Aber andere Dinge möchte man gerne vergessen lassen.
</summary>
   <content type="html">&lt;p&gt;Bei einer Migration stellt sich immer die Frage:&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;Was nehme ich mit? Was lasse ich zurück?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Die &lt;a href=&quot;https://de.wikipedia.org/wiki/Git&quot;&gt;GIT&lt;/a&gt; History ist so ein Thema, denn 
die will man meistens behalten, um Entwicklungsschritte nachvollziehen zu 
können. Aber andere Dinge möchte man gerne vergessen lassen.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Mit meiner geplanten Migration von &lt;a href=&quot;https://bitbucket.org&quot;&gt;Bitbucket&lt;/a&gt; zu 
&lt;a href=&quot;https://codeberg.org&quot;&gt;Codeberg&lt;/a&gt; kam ich zu dem Schluss, dass ich die History 
nicht übernehme … oder anders gesagt, ich kopiere einfach die aktuellen 
Sourcen in ein neues GIT Repository.&lt;/p&gt;

&lt;p&gt;Die primäre Grund dafür:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ich Idiot hatte fette Binärdateien ins alte Repo aufgenommen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Unter den “externen Bibliotheken” war bekanntlich auch &lt;code&gt;GTK&lt;/code&gt;, welches ich
eigens für Windows kompiliert hatte. Diese Bibliotheken umfassten viele
Megabytes an Binärdateien, die das Repo extrem aufgebläht hatten.&lt;/p&gt;

&lt;p&gt;Deshalb erfolgte zuerst die Abspaltung des &lt;code&gt;extlibs&lt;/code&gt; Repositories für 
Fremdbibliotheken und diese durften nur in reiner Source-Form commited werden.&lt;br /&gt;
Und dann wurde das &lt;code&gt;gate&lt;/code&gt; Projekt nur mit dessen Sourcen separat angelegt.&lt;/p&gt;

&lt;p&gt;Anders sieht es beim &lt;code&gt;opengate&lt;/code&gt; Repository aus, in dem die Quellen der
Webseiten von &lt;code&gt;opengate.at&lt;/code&gt; liegen.&lt;br /&gt;
Hier klonte ich zuerst das neue leere Repo, fügte dann den Pfad zum alten
Repo hinzu, holte die alten Inhalte auf die lokale Maschine und führt dann
einen Merge durch, der die alten Inhalte in den Branch des neuen Repos
integrierte.&lt;/p&gt;

&lt;p&gt;Das sieht dann etwa so aus:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;git clone https://new-server.tld/path_to/my_new_project.git
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;cd my_new_project
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;git remote add old_stuff https://old-server.tld/path_to/my_old_project.git
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;git fetch old_stuff
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;git merge old_stuff/master
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;git push
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Nun kann ich jede Änderung bis zur Erstellung des ersten Blog-Eintrages in
GIT zurückverfolgen.&lt;/p&gt;

&lt;p&gt;Im Fall vom &lt;code&gt;gate&lt;/code&gt; Projekt wäre das vielleicht auch nicht schlecht gewesen,
doch hier war mein Ziel mit einem schlanken Repo zu beginnen.&lt;/p&gt;

&lt;p&gt;Außerdem bin ich inzwischen ein Fan von &lt;code&gt;squash&lt;/code&gt; Mergerequests geworden,
bei denen mehrere Commits zu einem zusammengefasst werden.&lt;br /&gt;
Mein künftiger &lt;code&gt;main&lt;/code&gt; Branch soll nicht jede kleine Änderung erhalten, 
sondern nur noch gesammelte fertige Features (oder fertige Blogposts).&lt;br /&gt;
Schließlich bringt es nichts, 1000 einzelne Commits zu speichern, bei
denen immer nur ein Zeilchen angepasste wurde.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Die GIT Migration zu Codeberg geht gut voran, obwohl ich jetzt auch noch
viele weitere Kleinigkeiten fixen muss, damit das Gesamtsystem wieder so
bauen kann wie vorher … und das auf allen gewünschten Plattformen.&lt;/p&gt;

&lt;p&gt;Migrationen sind mühsam, aber bieten immer auch eine gute Gelegenheit um
aufzuräumen, denn:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Nur saubere GIT Repos sind gute GIT Repos.&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>Externe Bibliotheken</title>
   <link href="https://www.opengate.at/blog/2023/09/extlibs/"/>
   <published>2023-09-24T13:00:00+02:00</published>
   <updated>2023-09-24T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2023/09/extlibs</id>
   <category term="devel" />
   <summary type="text">Wenn es um die Enwicklung von Basis-Strukturen und OS-Anbindungen geht, mache
ich natürlich alles selbst. Aber heute braucht man auch Kompression, 
Verschlüsselung und jede Menge Datenformate um mit der Welt “reden” zu können.

Dies alles erledigen “externe Bibliotheken”, die ich bisher immer im 
Schlepptau dabei hatte. Nun bekommen sie ihr eigenes Vehikel.
</summary>
   <content type="html">&lt;p&gt;Wenn es um die Enwicklung von Basis-Strukturen und OS-Anbindungen geht, mache
ich natürlich alles selbst. Aber heute braucht man auch Kompression, 
Verschlüsselung und jede Menge Datenformate um mit der Welt “reden” zu können.&lt;/p&gt;

&lt;p&gt;Dies alles erledigen “externe Bibliotheken”, die ich bisher immer im 
Schlepptau dabei hatte. Nun bekommen sie ihr eigenes Vehikel.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Die Verwaltung von Abhängigkeiten ist in C und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B&quot;&gt;C++&lt;/a&gt; leider immer noch ein 
ungutes Thema. Gleich vorab würde ich sagen: Nutzt &lt;a href=&quot;https://conan.io/&quot;&gt;CONAN&lt;/a&gt;!&lt;br /&gt;
Ja, CONAN ist mühsam zu erlernen, aber es bietet tatsächlich genau die 
Infrastruktur, mit der wirklich jedes Kompilat mit jeder möglichen Einstellung
abgebildet wird.&lt;/p&gt;

&lt;p&gt;An der Stelle wäre das Thema “Externe Bibliotheken” eigentlich auch schon
beendet und das GATE Framework unterstützt auch einen CONAN-basierten
Build für alle Abhängigkeiten.&lt;/p&gt;

&lt;h3 id=&quot;aber&quot;&gt;Aber:&lt;/h3&gt;

&lt;p&gt;Leider erfüllen viele Bibliotheken heute nicht “meine” Anforderungen.
Und die handeln alle von Kompatibilität hin zu sehr alten Systemen.
Für &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_95&quot;&gt;Windows 95&lt;/a&gt; 
brauche ich einen MSVC 2003 und für 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Haiku_(Betriebssystem)&quot;&gt;Haiku&lt;/a&gt; einen GCC 2.&lt;/p&gt;

&lt;p&gt;Daran scheitert vieles … doch meistens nur an wenigen Zeilen.&lt;/p&gt;

&lt;p&gt;Und aus diesem Grund pflege ich gepatchte Varianten von Bibliotheken wie 
&lt;a href=&quot;https://de.wikipedia.org/wiki/OpenSSL&quot;&gt;OpenSSL&lt;/a&gt;, 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Zlib&quot;&gt;ZLIB&lt;/a&gt;, 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Lempel-Ziv-Markow-Algorithmus&quot;&gt;LZMA&lt;/a&gt;, 
&lt;a href=&quot;https://de.wikipedia.org/wiki/JPEG&quot;&gt;JPEG&lt;/a&gt;, 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Portable_Network_Graphics&quot;&gt;PNG&lt;/a&gt;, 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Graphics_Interchange_Format&quot;&gt;GIF&lt;/a&gt; oder 
&lt;a href=&quot;https://de.wikipedia.org/wiki/SQLite&quot;&gt;SQLITE&lt;/a&gt; in einem zusätzlichen
Repository namens &lt;a href=&quot;https://codeberg.org/GateNetwork/extlibs&quot;&gt;extlibs&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Gleichzeitig führen einige Bibliotheken eine Vielzahl von Einstellungen mit
sich, die ich nicht benötige. Hier kann ein angepasstes und verschlanktes
Buildsystem die Nutzung erheblich verbessern.&lt;/p&gt;

&lt;h3 id=&quot;notwendige-anpassungen&quot;&gt;Notwendige Anpassungen&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;OpenSSL nutzt heute die moderne &lt;code&gt;BCRYPT&lt;/code&gt; API unter Windows um Zufallszahlen
zu erzeugen. Damit läuft ganz OpenSSL erst ab Windows Vista.
Mit der Abänderung von genauer einer Funktion auf die frühere OpenSSL
Implementierung mit &lt;code&gt;WinCrypt&lt;/code&gt; läuft OpenSSL auch auf Windows 9X und NT 4.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;_s&lt;/code&gt; und &lt;code&gt;_r&lt;/code&gt; sind tolle neue Erweiterungen für bestehende &lt;code&gt;POSIX&lt;/code&gt; 
Funktionen, die ältere Compiler und deren Standard-Libs nicht kennen.
Hier hilft meist ein &lt;code&gt;CMAKE&lt;/code&gt; Patch, der auf den alten Compilern ein Makro
einspeist, welches ein&lt;br /&gt;
&lt;code&gt;sprintf_s(buf, sz, fmt, ...)&lt;/code&gt; auf &lt;code&gt;sprintf(buf, fmt, ...)&lt;/code&gt; umleitet.&lt;br /&gt;
Ein &lt;code&gt;gmtime_r&lt;/code&gt; kann man aber auch in einer eigenen Funktion implementieren,
die ein Mutex-geschütztes &lt;code&gt;gmtime&lt;/code&gt; nutzt. Und eine solche Patch-Funktion 
wird dann einfach mitkompiliert.&lt;/li&gt;
  &lt;li&gt;Fehlende Platformen wie &lt;code&gt;WINCE&lt;/code&gt; oder &lt;code&gt;HAIKU&lt;/code&gt; landen gerne mal in einem
&lt;code&gt;#error&lt;/code&gt; Block. Meist braucht man nur an die &lt;code&gt;#ifdef WIN32  ... #else&lt;/code&gt;
Zeilen ein weiteres &lt;code&gt;#ifdef&lt;/code&gt; anfügen und schon läuft die ganze Lib auf
einer offiziell nicht unterstützten Plattform.&lt;/li&gt;
  &lt;li&gt;Unvollständige Spezialitäten wie Assembler-Support deaktiviere ich gerne
im Ganzen. LZMA kommt mit jeder Menge &lt;code&gt;#if&lt;/code&gt; Spielereien um auf schnellere
Assemblermodule umzuleiten. Das funktioniert aber oft nicht korrekt, und
so helfe ich gerne nach, dass immer der &lt;code&gt;#else&lt;/code&gt; Block mit der generischen
C Implementierung aktiv wird.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;WINCE&lt;/code&gt; und &lt;code&gt;UEFI&lt;/code&gt; Dummies für unbenutzte Features: Die ZLIB ist genial, aber
warum sind dort direkte POSIX-Aufrufe für Dateien drinnen? WinCE hat
das alles nicht implementiert, und obwohl ich keine Datei-basierte ZLIB
Funktionen nutze, werden diese zum Requirement. Also muss ich Dummy-Funktionen
für die exotischen Plattformen belegen, die einfach nur da sind, um nicht
aufgerufen zu werden.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Es gibt sicher noch ein paar andere Spielereien, aber die genannten Punkte 
decken die meisten Änderungen ab, die ich bei externen Bibliotheken einfach
brauche.&lt;/p&gt;

&lt;p&gt;All das ist nun in den &lt;code&gt;extlibs&lt;/code&gt; implementiert.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Dass ein C++ Projekt seine externen Abhängigkeiten selbst mitführt, war viele
Jahre “normal” … und ist heute der Grund warum C++ abgehängt wirkt, weil
kein einheitliches Verwaltungssystem hierfür existierte.&lt;/p&gt;

&lt;p&gt;Mit der Einführung von &lt;code&gt;CONAN&lt;/code&gt; kann jedoch auch jedes C++ Projekt mit jedem
Compiler und jedem erdenklichen Buildsystem darauf vertrauen, dass notwendige
Sourcen heruntergeladen und passen kompiliert werden.&lt;/p&gt;

&lt;p&gt;Und dennoch wird es besonders im C und C++ Bereich immer Nischen geben, die
für exotische Aufgaben Anpassungen vornehmen müssen, die einer zentralen
Paketverwaltung widersprechen.&lt;/p&gt;

&lt;p&gt;Meine “historischen” Plattformen wären ein solchen Beispiel, doch in
der Mikrokonroller-Welt lassen sich bestimmt auch ähnliche Nischen finden.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Migration zu Codeberg</title>
   <link href="https://www.opengate.at/blog/2023/09/codeberg-migration/"/>
   <published>2023-09-23T13:00:00+02:00</published>
   <updated>2023-09-23T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2023/09/codeberg-migration</id>
   <category term="devel" /><category term="software" /><category term="projects" />
   <summary type="text">Es wird Zeit sich voll und ganz der 
Open Source Welt zu öffnen.
Mein bisheriger Git Hoster 
Bitbucket ist ja ganz toll, 
aber gehört der Firma Atlassian. Und 
Github ist in fester Hand von Microsoft.

Alle sitzen in den USA und niemand weiß, wie die morgen so drauf sein werden.

Es ist beschlossen, ich übersiedle “code-technisch” nach Berlin, und zwar
nach codeberg.org
</summary>
   <content type="html">&lt;p&gt;Es wird Zeit sich voll und ganz der 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Open_Source&quot;&gt;Open Source&lt;/a&gt; Welt zu öffnen.
Mein bisheriger &lt;a href=&quot;https://de.wikipedia.org/wiki/Git&quot;&gt;Git&lt;/a&gt; Hoster 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Bitbucket&quot;&gt;Bitbucket&lt;/a&gt; ist ja ganz toll, 
aber gehört der Firma Atlassian. Und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/GitHub&quot;&gt;Github&lt;/a&gt; ist in fester Hand von Microsoft.&lt;/p&gt;

&lt;p&gt;Alle sitzen in den USA und niemand weiß, wie die morgen so drauf sein werden.&lt;/p&gt;

&lt;p&gt;Es ist beschlossen, ich übersiedle “code-technisch” nach Berlin, und zwar
nach &lt;a href=&quot;https://www.codeberg.org/&quot;&gt;codeberg.org&lt;/a&gt;
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;codeberg&quot;&gt;Codeberg&lt;/h3&gt;

&lt;p&gt;Warum ich Codeberg super finde, 
&lt;a href=&quot;/blog/2023/03/codeberg/&quot;&gt;hatte ich schon mal beschrieben&lt;/a&gt;.
Jetzt geht es auch darum ein Zeichen zu setzen, und deshalb zahle ich gerne
den jährlichen Mitgliedsbeitrag um diesen Dienst zusätzlich auch finanziell
zu unterstützen.&lt;/p&gt;

&lt;p&gt;Wenn wir der Jugend an den Schulen die Softwareentwicklung näher bringen, dann
sollten wir das nicht im Schatten von Konzernen tun, die sich heute als 
kostenlose Freunde anbieten und morgen unsere Daten an “andere” verfüttern.&lt;/p&gt;

&lt;p&gt;Und natürlich freue auch ich mich, wenn ich meinen Code an einer Stelle ablegen
kann, die von der Community, also von Enthusiasten verwaltet wird, und nicht 
von profitgetriebenen Managern.&lt;/p&gt;

&lt;p&gt;Kurz gesagt:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Codeberg rulez!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;migration&quot;&gt;Migration&lt;/h3&gt;

&lt;p&gt;Das GATE Projekt besteht inzwischen aus mehrere Repositories:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;In &lt;code&gt;gate&lt;/code&gt; liegt C/C++ Framework&lt;/li&gt;
  &lt;li&gt;In &lt;code&gt;opengate&lt;/code&gt; liegen die Quellen der Webseite(n)&lt;/li&gt;
  &lt;li&gt;Der &lt;code&gt;gate-blog-classroom&lt;/code&gt; sammelt zusätzliche Sourcecodes für den Blog&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;cpp-build-env&lt;/code&gt; enthält die Docker Bauanleitungen&lt;/li&gt;
  &lt;li&gt;und dann gibt es noch ein paar private Spielereien für Arduino und Co.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Das &lt;code&gt;gate&lt;/code&gt; Repository wird bei der Codeberg Migration wieder bei Null anfangen
und keine History von Bitbucket übernehmen. Grund dafür ist meine Dummheit,
da ich Binaries für &lt;a href=&quot;https://de.wikipedia.org/wiki/GTK_(Programmbibliothek)&quot;&gt;GTK3&lt;/a&gt; 
und EFI miteingecheckt habe, die das Repository nur unnötig aufblähen.&lt;/p&gt;

&lt;p&gt;Doch die Blog- und Webquellen sind relativ frei von solchen Geschwüren, 
also macht es durchaus Sinn, deren History 1:1 zu übernehmen.&lt;/p&gt;

&lt;p&gt;Wie das mit CI Funktionen und Buildservices aussieht, weiß ich noch nicht.
Im Zweifelsfall läuft das eben bei mir zu Hause. Am wichtigsten ist mir das 
GIT-Repo selbst, alles andere ist optional.&lt;/p&gt;

&lt;h3 id=&quot;pages&quot;&gt;Pages&lt;/h3&gt;

&lt;p&gt;Außerdem ist mir das “Pages” Feature ins Auge gefallen. Inhalte solcher
Pages-Repos sollen direkt als statische Webseite per URL erreichbar sein.&lt;br /&gt;
Oh … das freut mich … und könnte zukünftig das Bauen des Blogs 
“optimieren”.&lt;/p&gt;

&lt;p&gt;Schließlich brauche ich ja immer Monate, bis alles korrigiert und in einem
Schwung neu hochgeladen ist. Aber so könnte ich auch die Entwürfe als
“Voransicht” automatisiert generieren lassen.&lt;br /&gt;
Denn das war mir auf meinem Webspace mit FTP-Passwörtern immer viel zu heikel.&lt;/p&gt;

&lt;p&gt;Na mal sehen, was daraus wird.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;Die nächsten Wochen werden ein Spaß.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ohne einige Umstellungen in der Projektstruktur wird es wohl nicht gehen, aber
früher oder später wird das ganze GATE Projekt auf Codeberg einsehbar sein.&lt;/p&gt;

&lt;p&gt;Die ersten Vorbereitungen wurden gesetzt und ich bin total beeindruckt, dass 
Codeberg ein &lt;code&gt;git-clone&lt;/code&gt; 3 mal schneller hinbekommt als ein gleich großes Bitbucket Projekt.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Defekte M2 SSD gerettet</title>
   <link href="https://www.opengate.at/blog/2023/09/restore/"/>
   <published>2023-09-17T13:00:00+02:00</published>
   <updated>2023-09-17T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2023/09/restore</id>
   <category term="software" /><category term="hardware" />
   <summary type="text">Alarmstufe Rot am Server!

Der reagiert einfach nicht mehr … bzw. nur noch seltsam
langsam per Ping, aber das UI hängt nur noch.

Und Schuld war die verbaute M2 SSD.
</summary>
   <content type="html">&lt;p&gt;Alarmstufe Rot am Server!&lt;/p&gt;

&lt;p&gt;Der reagiert einfach nicht mehr … bzw. nur noch seltsam
langsam per Ping, aber das UI hängt nur noch.&lt;/p&gt;

&lt;p&gt;Und Schuld war die verbaute &lt;a href=&quot;https://de.wikipedia.org/wiki/M.2&quot;&gt;M2 SSD&lt;/a&gt;.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Mein seit 2019 durchgehend zu Hause laufender &lt;a href=&quot;https://de.wikipedia.org/wiki/Intel_Atom&quot;&gt;Intel-Atom&lt;/a&gt;
Server, hat mir bisher nie wirklich Probleme bereitet (OK, der Grafiktreiber schon …).&lt;br /&gt;
Gut, er war nicht schnell, aber was erwartet man von einem mit 13 Watt 
betriebenem System.&lt;/p&gt;

&lt;p&gt;Ich hatte damals auch einige Billig-SSDs aus China bestellt und als Bootplatten
verbaut. Bei den Daten setzte ich meist auf die teureren Markenprodukte aus 
dem lokalen Handel.&lt;/p&gt;

&lt;p&gt;Zwar müssen meine Server nicht wirklich viele Daten herumschieben, aber im 
Laufe der Zeit sammelt sich vieles an und vor allem duplizieren sich oft
Videos und Audiodateien in mehreren Verzeichnissen versehentlich, wenn ich mal
nicht aufpasse.&lt;/p&gt;

&lt;p&gt;Dennoch waren stets mindestens 50% der Laufwerke frei, manchmal auch mehr.
Und dann passierte es …&lt;/p&gt;

&lt;h3 id=&quot;disketten-waren-schneller-als-volle-ssd&quot;&gt;Disketten waren schneller als volle SSD&lt;/h3&gt;

&lt;p&gt;Es war nicht das erste mal, dass sich eine “günstige” SSD seltsam langsam
verhielt. In manchen Testsystemen konnte ich das schonmal beobachten, doch
diese werden wieder geplättet und bei der Neuinstallation war wieder alles
gut.&lt;/p&gt;

&lt;p&gt;Nun hatte es meinen &lt;a href=&quot;https://de.wikipedia.org/wiki/Active_Directory&quot;&gt;Active Directory&lt;/a&gt;
Domain Controller getroffen und den wollte ich nicht grundlos wegwerfen.&lt;/p&gt;

&lt;p&gt;Offenbar schaltete die SSD in einen extrem langsamen Zugriffsmodus und lieferte
nur wenige Kilobytes pro Sekunde aus. Das war früher mal verkraftbar, ist
aber auf einem heutigen Windows untragbar, weil da permanent etwas gelesen
oder geschrieben wird und sich das System so selbst blockiert.&lt;/p&gt;

&lt;p&gt;Ich kaufte sofort ein Ersatzsystem und eine Ersatzplatte, wollte aber das 
Original Byte für Byte kopieren, damit das neue System mit dem bestehenden
AD-Stand hochfahren konnte.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;W-T-F! Mehr als 24 Stunden!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ich konnte die beiden SSDs (512 GB) zwar problemlos in meinem Rechner starten
und die Sektor-Direktkopie starten, aber die Lesegeschwindigkeit fiel immer
wieder dramatisch ab und so dauerte die Aktion über das Wochenende.&lt;br /&gt;
Die Hoffnung, ich könnte schnell Auslesen, nur das Schreiben wäre langsam 
gewesen, erfüllte sich nicht.&lt;/p&gt;

&lt;p&gt;Am Ende ging aber dennoch alles gut und ich hatte keine Daten verloren, doch
so wirklich sicher war ich mir da anfangs nicht.&lt;br /&gt;
Zwar waren auch meine Backups mitgelaufen, doch auch hier fand ich heraus,
dass Backupversuche einige Tage vorher immer wieder fehlgeschlagen waren.
Mit einem Restore wäre zwar auch nicht viel verloren gewesen … aber man
weiß ja nie, ob das Backup dann korrekt war.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Billige SSDs speichern 2, 3 oder mehrere Bits in einer Zelle. Damit ist alles
superschnell, wenn nur kleine Teile des Mediums ausgefüllt sind.&lt;br /&gt;
Irgendwann findet dann aber das große Umspeichern statt und ich glaube, dass
ich in so eine Aktion hineingeraten bin, die alles schlimmer gemacht hat.&lt;/p&gt;

&lt;p&gt;Zwar gingen keine Daten verloren, so weit ich weiß … doch womöglich
stand ich kurz davor.&lt;/p&gt;

&lt;p&gt;Das erinnert mich dann wieder an das Big-Box-Mart Video, in dem es am 
Ende heißt:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Your every-day low prices have a price, they are not free.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Und das gilt bei SSDs eben auch. Denn meine Markenprodukte haben so ein
Verhalten noch nicht gezeigt, obwohl sie viel stärker beschrieben werden. 
(Und hoffentlich tun sie das auch nicht.)&lt;/p&gt;

&lt;iframe width=&quot;640&quot; height=&quot;360&quot; src=&quot;/blog/redirect.html?https%3A%2F%2Fwww.youtube-nocookie.com%2Fembed%2FpKv6RcXa2UI&quot; frameborder=&quot;1&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
</content>
 </entry>
 
 <entry>
   <title>Docker Windows abgeschaltet</title>
   <link href="https://www.opengate.at/blog/2023/09/docker-windows/"/>
   <published>2023-09-16T13:00:00+02:00</published>
   <updated>2023-09-16T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2023/09/docker-windows</id>
   <category term="software" />
   <summary type="text">Ich wollte einfach nur einen Windows Build Server
mit Docker neu aufsetzen.
Doch Microsoft hat ihren offiziellen MsftDockerProvider vom Netz genommen.

An dieser Stelle war man Aufschrei in ganz Wien zu hören. Zum Glück ist die
Alternative das Moby Projekt, welches Docker für Windows Server weiter unterstützt.
</summary>
   <content type="html">&lt;p&gt;Ich wollte einfach nur einen Windows Build &lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_Server_2022&quot;&gt;Server&lt;/a&gt;
mit &lt;a href=&quot;https://de.wikipedia.org/wiki/Docker_(Software)&quot;&gt;Docker&lt;/a&gt; neu aufsetzen.
Doch Microsoft hat ihren offiziellen &lt;code&gt;MsftDockerProvider&lt;/code&gt; vom Netz genommen.&lt;/p&gt;

&lt;p&gt;An dieser Stelle war man Aufschrei in ganz Wien zu hören. Zum Glück ist die
Alternative das &lt;code&gt;Moby&lt;/code&gt; Projekt, welches Docker für Windows Server weiter unterstützt.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;bisherige-installation-von-docker&quot;&gt;Bisherige Installation von Docker&lt;/h3&gt;

&lt;p&gt;Bisher wurde Docker auf Windows Servern mit&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;Install-Module -Name DockerMsftProvider -Repository PSGallery -Force
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;Install-Package -Name docker -ProviderName DockerMsftProvider
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;eingerichtet. Die Prozedur lud die entsprechenden Pakete aus dem Netz und 
installierte den Docker Dienst im Windows System. 
Doch nun sehen wir Fehler wie:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;WARNING: MSG:UnableToDownload https://go.microsoft.com/fwlink/?LinkID=627338&amp;amp;clcid=0x409  
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;WARNING: Unable to download the list of available providers. Check your internet connection.  
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;WARNING: Cannot find path  
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;&apos;C:\Users\ADMINI~1\AppData\Local\Temp\2\DockerMsftProvider\DockerDefault_DockerSearchIndex.json&apos; 
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;because it does not exist.
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;WARNING: Cannot bind argument to parameter &apos;downloadURL&apos; because it is an empty string.
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;WARNING: The property &apos;AbsoluteUri&apos; cannot be found on this object. Verify that the property exists.
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;WARNING: The property &apos;RequestMessage&apos; cannot be found on this object. Verify that the property exists.
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;Install-Package : No match was found for the specified search criteria and package name &apos;docker&apos;. 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;Try Get-PackageSource to see all available registered package sources.
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Früher lag offenbar unter 
&lt;code&gt;https://dockermsft.azureedge.net/dockercontainer/DockerMsftIndex.json&lt;/code&gt; 
die notwendige Information, wo die Daten heruntergeladen werden konnte, 
doch das ist nun abgeschaltet, wie man auf 
&lt;a href=&quot;https://github.com/OneGet/MicrosoftDockerProvider&quot;&gt;GitHub von MicrosoftDockerProvider&lt;/a&gt;
nachlesen kann.&lt;/p&gt;

&lt;p&gt;Das bedeutet: Ab sofort kann man Docker Enterprise für Windows Server nicht mehr
regulär installieren.&lt;/p&gt;

&lt;h3 id=&quot;alternative-das-moby-projekt&quot;&gt;Alternative: Das Moby Projekt&lt;/h3&gt;

&lt;p&gt;Wer Enterprise-Support braucht, kann die &lt;a href=&quot;https://www.mirantis.com/&quot;&gt;Mirantis&lt;/a&gt;
Container Runtime nutzen … und darf dafür auch extra zahlen.&lt;/p&gt;

&lt;p&gt;Und wer einfach nur seine Buildumgebung wieder zum Laufen bekommen will, kann
das &lt;a href=&quot;https://mobyproject.org/&quot;&gt;OpenSource Projekt Moby&lt;/a&gt; nutzen, welches die
Docker Dienste ohne den Unternehmens-Support zum Download zur Verfügung stellt.&lt;/p&gt;

&lt;p&gt;Man hat dann zwar nur eine &lt;code&gt;AS IS&lt;/code&gt; Software ohne Garantien, kann sich aber 
die Quellen sichern und im Notfall den Dienst auch selbst bauen.&lt;/p&gt;

&lt;p&gt;Die Sourcen und Releases liegen auf 
&lt;a href=&quot;https://github.com/moby/moby&quot;&gt;github.com/moby/moby&lt;/a&gt;&lt;/p&gt;

&lt;h3 id=&quot;installation-der-moby-docker-container-runtime&quot;&gt;Installation der Moby Docker Container Runtime&lt;/h3&gt;

&lt;p&gt;Nachdem das Windows &lt;code&gt;Container&lt;/code&gt; Feature aktiviert ist, lädt man sich am
einfachsten ein Installationsscript für die Powershell herunter, das
die aktuellen Binärdateien herunterlädt und in &lt;code&gt;C:\Windows\System32\&lt;/code&gt;
installiert.&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;(new-object System.Net.WebClient).DownloadFile(&amp;quot;https://raw.githubusercontent.com/microsoft/Windows-Containers/Main/helpful_tools/Install-DockerCE/install-docker-ce.ps1&amp;quot;, &amp;quot;install-docker-ce.ps1&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;.\install-docker-ce.ps1
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h3 id=&quot;sonderfall-windows-server-2016&quot;&gt;Sonderfall Windows Server 2016&lt;/h3&gt;

&lt;p&gt;Die aktuellen Moby Builds funktionieren erst ab Server 2019. Unter älteren
Windows Version verweigert der aktuelle &lt;code&gt;dockerd.exe&lt;/code&gt; seinen Dienst.&lt;/p&gt;

&lt;p&gt;Man kann sich allerdings auch unter 
&lt;a href=&quot;https://download.docker.com/win/static/stable/x86_64/&quot;&gt;download.docker.com/win/static/stable/x86_64/&lt;/a&gt;
eine ältere Version der Runtime herunterladen, z.B.: v20.10.24.
Danach muss man die beiden Programme &lt;code&gt;docker.exe&lt;/code&gt; und &lt;code&gt;dockerd.exe&lt;/code&gt; aus der 
ZIP Datei einfach nach &lt;code&gt;C:\Windows\System32&lt;/code&gt; kopieren und hat danach auch unter
Server 2016 wieder einen funktionalen Docker Dienst.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;Pfui Microsoft! Das konntet ihr schon mal besser!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Wenn ich an Windows eines geschätzt habe, dann war das seine zuverlässige
Kompatibilität und der lange Support von Software.
Selbst heute erhalte ich noch über &lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_Server_Update_Services&quot;&gt;WSUS&lt;/a&gt; 
alle Windows XP und Windows 2000 Updates, was für Industriemaschinen immer 
noch notwendig sein kann.&lt;/p&gt;

&lt;p&gt;Dass gerade Docker einfach mal so abgedreht wird, ist nicht akzeptabel.
Man hätte die alten Binaries liegen lassen können und nur für
Neuinstallationen auf die Alternativen verweisen können.&lt;/p&gt;

&lt;p&gt;Wenn gleich das Moby Projekt sicher toll ist, so ist der mit dem
Server mitgekaufte Enterprise-Support plötzlich weg … und was 
passiert jetzt, wenn ein Kunde hierfür ein Anliegen hat?&lt;br /&gt;
Dann wird es unerwartet teuer.&lt;/p&gt;

&lt;p&gt;Ich überlege jetzt trotzdem, ob ich nicht meine laufenden
Windows Server mit der “alten” Docker Installation jetzt dupliziere
und per SysPrep für spätere Neuinstallationen konserviere.&lt;/p&gt;

&lt;p&gt;In jedem Fall kostet mich dieser Umstand jetzt sowohl in der Firma
wie auch privat jede Menge wertvolle Zeit.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>STAR64: ein RISC-V von PINE64</title>
   <link href="https://www.opengate.at/blog/2023/09/star64/"/>
   <published>2023-09-09T13:00:00+02:00</published>
   <updated>2023-09-09T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2023/09/star64</id>
   <category term="hardware" />
   <summary type="text">Ein neuer Stern ist am Himmel erschienen. Mit dem STAR64
habe ich nun ein Raspberry-PI 4
ähnliches RISC-V System in meine 
Familie aufgenommen und freue mich, dass diese CPU Architektur langsam im
Endanwendermarkt angekommen ist.
</summary>
   <content type="html">&lt;p&gt;Ein neuer Stern ist am Himmel erschienen. Mit dem &lt;a href=&quot;https://pine64.com/product-category/star64/&quot;&gt;STAR64&lt;/a&gt;
habe ich nun ein &lt;a href=&quot;https://de.wikipedia.org/wiki/Raspberry_Pi&quot;&gt;Raspberry-PI&lt;/a&gt; 4
ähnliches &lt;a href=&quot;https://de.wikipedia.org/wiki/RISC-V&quot;&gt;RISC-V&lt;/a&gt; System in meine 
Familie aufgenommen und freue mich, dass diese CPU Architektur langsam im
Endanwendermarkt angekommen ist.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Vor 20 Jahren war es für mich unvorstellbar, dass es noch etwas anderes als
X86 PCs zum digitalen Arbeiten geben kann. Exotische Taschenrechner und 
wenige &lt;a href=&quot;https://de.wikipedia.org/wiki/Personal_Digital_Assistant&quot;&gt;PDA&lt;/a&gt;s 
mal ausgenommen.&lt;/p&gt;

&lt;p&gt;Vor 10 Jahren sah ich, dass &lt;a href=&quot;https://de.wikipedia.org/wiki/Arm-Architektur&quot;&gt;ARM&lt;/a&gt;
Geräte den klassischen X86 PC langsam verdrängten.&lt;/p&gt;

&lt;p&gt;Und heute sehe ich, dass mit RISC-V auch ARM einen wachsenden Konkurrenten bekommt.&lt;/p&gt;

&lt;h3 id=&quot;star64-hardware&quot;&gt;STAR64 Hardware&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/star64-riscv-1.jpg&quot; alt=&quot;STAR64&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Das Star64 Model-A baut auf einer 64-bit RISC-V Quad-Core CPU auf, die es auf 
1.5 GHz bringen kann. Ich habe mir das Modell mit 8 GB RAM gegönnt.
Bestromt wird das 13x8 cm Board offiziell mit einem 12 V Netzteil über einen
üblichen Hohlstecker, wie er auch bei einigen ITX Mainboards zur Anwendung
kommt.&lt;/p&gt;

&lt;p&gt;Ein solches 12 V Netzteil hatte ich ohnehin zu Hause und musste daher keines 
mitbestellen. Die geforderten 3.5 Ampere würden somit 45 Watt ergeben.
Doch selbst bei CPU Volllast beim Kompilieren, kam das Gerät bei meiner
Messung nicht über 8 bis 9 Watt hinaus … also ein echter Stromsparer.
Ich habe allerdings auch keine Erweiterungskarten angeschlossen oder
USB belastet … von daher sind die 8 Watt also dennoch eine untere Grenze.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/star64-riscv-2.jpg&quot; alt=&quot;STAR64-USB&quot; /&gt;&lt;/p&gt;

&lt;p&gt;WLAN, 2x LAN, HDMI, 3x USB2, 1x USB3 sind vorhanden, allerdings an 
gegenüberliegenden Enden verbaut.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/star64-riscv-3.jpg&quot; alt=&quot;STAR64-LAN&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Für einen Desktop mit “Hinten-Strom” und “Vorne-USB” passt das gut,
bei meiner Verkabelung am KVM-Switch war es etwas ungünstig.
Cool wäre gewesen, wenn es neben HDMI und LAN Buchse noch einmal
USB für Tastatur und Maus gegeben hätte.&lt;/p&gt;

&lt;h3 id=&quot;software&quot;&gt;Software&lt;/h3&gt;

&lt;p&gt;Das System kann entweder von SD-Karte oder &lt;a href=&quot;https://de.wikipedia.org/wiki/Multimedia_Card#eMMC&quot;&gt;eMMC&lt;/a&gt;
Karte booten, was man über kleine Schalter konfigurieren kann:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/star64-riscv-4.jpg&quot; alt=&quot;STAR64-LAN&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Ich kopierte ein fertiges Desktop-Linuximage basierend auf dem 
&lt;a href=&quot;https://en.wikipedia.org/wiki/Yocto_Project&quot;&gt;Yocto Projekt&lt;/a&gt; einfach auf eine
SD-Karte und schon konnte das Gerät starten.&lt;/p&gt;

&lt;p&gt;Ein &lt;a href=&quot;https://en.wikipedia.org/wiki/Armbian&quot;&gt;Armbian&lt;/a&gt; Image hätte ich auch 
ausprobieren wollen, doch dieses wurde nicht erkannt. Nach Anschluss eines 
seriellen Adapters an den Pins 6, 8 und 10 konnte ich eine Fehlermeldung am 
COM-Port abfangen.&lt;/p&gt;

&lt;p&gt;Was man ebenso am COM-Port bei einem erfolgreichen Boot sehen kann, ist:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;U-Boot 2021.10 (Jun 05 2023 - 16:23:55 +0000)05062023
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;CPU:   rv64imacu_zba_zbb
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;Model: Pine64 Star64
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;DRAM:  Not a StarFive EEPROM data format - magic error
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;4 GiB
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;MMC:   sdio0@16010000: 0, sdio1@16020000: 1
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;Loading Environment from SPIFlash... SF: Detected gd25lq128 with page size 256 Bytes, erase size 4 KiB, total 16 MiB
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;*** Warning - bad CRC, using default environment
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;Not a StarFive EEPROM data format - magic error
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Da wurde also einiges vom StarFive Modell übernommen.
Ärgerlich ist dabei allerdings, dass mein 8GB Modell nur mit 4 GB
angesprochen wird … und das ändert sich auch später nach dem Laden
des Linux Kernels nicht mehr.&lt;/p&gt;

&lt;p&gt;Ich vermute mal, ich muss irgendwann den Bootloader ersetzen, damit
die vollen 8 GB nutzbar werden … aber vorläufig werde ich damit leben
können.&lt;/p&gt;

&lt;p&gt;Beim ersten Start wird die Partition auf die gesamte Größe der SD Karte
ausgeweitet und dann nochmal neu gestartet.&lt;/p&gt;

&lt;p&gt;Am Ende landete ich in einer KDE-Login Maske, die mich mit Benutzer- und
Passworteingabe (beide lautend auf &lt;code&gt;pine64&lt;/code&gt;) zum üblichen Linux Desktop
weiterleitete.&lt;/p&gt;

&lt;p&gt;Von dort konnte ich grafisch meinen WLAN-Router einbuchen und schon war das
Gerät im Netz. Dort wurden dann zahlreiche Updates nachgeladen und nach 
einem finalen Reboot war mein STAR64 voll nutzbar.&lt;/p&gt;

&lt;h4 id=&quot;performance-und-stabilität&quot;&gt;Performance und Stabilität&lt;/h4&gt;

&lt;p&gt;Dass ein RISC-V System aktuelle ARM Kerne nicht überholen wird, war mir im
Vorfeld klar. Am besten vergleichbar war die Performance mit einem 
Raspberry-PI 4. Dieser mag vielleicht beim booten etwas schneller sein,
doch wenn ich einen Kompiliervorgang startete, dann war die 
Fortschrittsgeschwindigkeit gefühlt sehr nahe am RPI-4.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Für mich also absolut OK für die Softwareentwicklung.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Die Nutzung des Internet ist … wie auch beim PI … etwas schwierig.
Mein Blog lädt natürlich super schnell, doch alleine der Login bei
diversen Diensten wie &lt;code&gt;outlook.com&lt;/code&gt; oder &lt;code&gt;Bitbucket&lt;/code&gt;, sind auf dem STAR64
ähnlich träge wie auch auf dem RPI4. Zwar tauchen die Seitenteile am Ende 
meist immer auf, aber die Wartezeiten erinnern dann leider doch wieder an 
die Telefonmodem-Zeiten der späten 90er.&lt;/p&gt;

&lt;p&gt;Ein Problem hatte ich konkret mit dem HDMI Anschluss beim Umschalten
des KVM-Switches. Eine verlorene Verbindung zum Monitor wird später
nicht wiederhergestellt, wenn man zum Gerät zurückschaltet.&lt;br /&gt;
Ich musste also per serieller Konsole ein &lt;code&gt;reboot&lt;/code&gt; Kommando absetzen,
um dann wieder ein schönes Monitorbild zu bekommen.&lt;br /&gt;
Tja … so ist das mit brandneuer Hardware. Doch auch hier werden die
Patches - so hoffe ich - nicht all zu lange auf sich warten lassen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ich liebe meinen STAR64 trotz seiner kleinen Fehler, denn mein erster
Kontakt mit dem &lt;a href=&quot;/blog/2022/08/risc-v/&quot;&gt;Lichee RV Allwinner D1&lt;/a&gt;
war zwar super aus technischer Sicht, doch für die täglich Arbeit tauglich
war dieses Gerät nicht.&lt;/p&gt;

&lt;p&gt;Der STAR64 kommt da schon eher in Frage und ich gehe davon aus, dass
die nächsten RISC-V Varianten noch näher an die ARM-Leistungen herankommen
werden.&lt;/p&gt;

&lt;p&gt;Und so können wir heute live miterleben, wie die nächste CPU Architektur 
ihren Platz in der Welt bekommt.&lt;/p&gt;

&lt;p&gt;Ich denke nun jedenfalls darüber nach, einen RISC-V Linux Build aller
meiner GATE Tools per Cross-Compiling ausgeben zu lassen, denn bald wird
das ebenso notwendig sein, so wie wir heute X86, X86_64, ARM und ARM64 Builds
von allem Programmen anlegen.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>WINGET unter Windows IOT</title>
   <link href="https://www.opengate.at/blog/2023/09/winget-iot/"/>
   <published>2023-09-03T13:00:00+02:00</published>
   <updated>2023-09-03T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2023/09/winget-iot</id>
   <category term="software" />
   <summary type="text">Mit dem kommenden “Aus” für Windows 10 
im Jahr 2025, frage ich mich, wie lange ich dieses Plattform weiter 
nutzen wollen werde.

Windows 10 IOT erhält noch bis 2030 Support, also werde ich wohl darauf
wechseln … doch dort fehlt jede Menge Software.
</summary>
   <content type="html">&lt;p&gt;Mit dem kommenden “Aus” für &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_10&quot;&gt;Windows 10&lt;/a&gt; 
im Jahr 2025, frage ich mich, wie lange ich dieses Plattform weiter 
nutzen wollen werde.&lt;/p&gt;

&lt;p&gt;Windows 10 IOT erhält noch bis 2030 Support, also werde ich wohl darauf
wechseln … doch dort fehlt jede Menge Software.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;blockquote&gt;
  &lt;p&gt;Hinweis: Windows-10-IOT kann man nicht im nächsten Laden kaufen, 
sondern erhält es durch ein MSDN-ABO oder andere Lizenzvereinbarungen
für Unternehmen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Meine Laptops von 2014 und 2016 laufen noch brav, sind aber nicht 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_11&quot;&gt;Windows 11&lt;/a&gt; tauglich (und würden 
wohl auch ziemlich lahm damit starten.)&lt;/p&gt;

&lt;p&gt;Meine Windows 10 IOT Alternative ist für die Softwareentwicklung super.
Win10-IOT unterstützt Win32/64 vollständig und damit auch jede 
Entwicklungsumgebung.&lt;/p&gt;

&lt;p&gt;Was dem Teil aber fehlt ist der &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Store&quot;&gt;Windows Store&lt;/a&gt; 
und auch sonst alle Standard-Apps wie Mail und Kalender, auf die ich nicht
verzichten will.&lt;/p&gt;

&lt;p&gt;Natürlich kann man die Pakete manuell aus dem Netz extrahieren und 
nachinstallieren, aber sehr benutzerfreundlich ist das nicht.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Wie cool wäre es, wenn &lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_Package_Manager&quot;&gt;winget&lt;/a&gt;
verfügbar wäre, das alles einfach nachinstallieren kann?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Doch leider fehlt &lt;code&gt;winget&lt;/code&gt; ebenfalls.&lt;/p&gt;

&lt;h3 id=&quot;winget-installation-unter-windows-10-iot&quot;&gt;winget Installation unter Windows 10 IOT&lt;/h3&gt;

&lt;p&gt;Zu meiner großen Freude hat Microsoft inzwischen eine 
&lt;a href=&quot;https://learn.microsoft.com/en-us/windows/iot/iot-enterprise/deployment/install-winget-windows-iot&quot;&gt;Anleitung online gestellt&lt;/a&gt;, 
wie man den modernen App-Installer auf Win10 IOT einrichten kann.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Man holt sich von &lt;a href=&quot;https://github.com/microsoft/winget-cli/releases&quot;&gt;github.com&lt;/a&gt;
das neueste &lt;code&gt;.msixbundle&lt;/code&gt; und die License &lt;code&gt;.xml&lt;/code&gt; Datei&lt;/li&gt;
  &lt;li&gt;Dann lädt man sich die &lt;a href=&quot;https://aka.ms/Microsoft.VCLibs.x64.14.00.Desktop.appx&quot;&gt;VCLibs&lt;/a&gt;
auf die Platte&lt;/li&gt;
  &lt;li&gt;Und muss noch &lt;a href=&quot;https://www.nuget.org/packages/Microsoft.UI.Xaml/2.7.0&quot;&gt;Microsoft.UI.Xaml.nupkg&lt;/a&gt; aus
dem Netz gesogen werden.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;nupkg&lt;/code&gt; ist in Wahrheit eine &lt;code&gt;.zip&lt;/code&gt; Datei, und aus dieser muss man sich die 
Datei &lt;code&gt;Microsoft.UI.XAML.2.7.appx&lt;/code&gt; herausziehen.&lt;/li&gt;
  &lt;li&gt;Jetzt öffnet man die Powershell und führt aus:
    &lt;ul&gt;
      &lt;li&gt;Add-AppxPackage -Path &amp;lt;path to VCLibs .appx file&amp;gt;&lt;/li&gt;
      &lt;li&gt;Add-AppxPackage -Path &lt;path to=&quot;&quot; UI=&quot;&quot; xaml.appx=&quot;&quot; file=&quot;&quot;&gt;&lt;/path&gt;&lt;/li&gt;
      &lt;li&gt;Add-AppxPackage -Path &amp;lt;path to .msixbundle file&amp;gt;&lt;/li&gt;
      &lt;li&gt;Add-AppxProvisionedPackage -Online -PackagePath &amp;lt;path to .msixbundle file&amp;gt; -LicensePath &lt;path to=&quot;&quot; xml=&quot;&quot; file=&quot;&quot;&gt;&lt;/path&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nun ist &lt;code&gt;winget&lt;/code&gt; unter &lt;code&gt;%LOCALAPPDATA%\Microsoft\WindowsApps&lt;/code&gt; verlinkt und kann 
zur Installation weiterer Software genutzt werden.&lt;/p&gt;

&lt;h3 id=&quot;windows-store-apps-per-winget-installieren&quot;&gt;Windows Store Apps per &lt;code&gt;winget&lt;/code&gt; installieren.&lt;/h3&gt;

&lt;p&gt;Ein &lt;code&gt;winget search something&lt;/code&gt; lässt einen recht schnell auch die üblichen 
Apps wie &lt;em&gt;Mail&lt;/em&gt; oder &lt;em&gt;News&lt;/em&gt; finden. Installieren kann man die Apps dann
über &lt;code&gt;winget install --id appid&lt;/code&gt;.
Die Microsoft Apps sind oft nur über ihre kryptischen Hash-IDs erreichbar.&lt;/p&gt;

&lt;p&gt;Meine üblichen Verdächtigen sind:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Mail: &lt;code&gt;winget install --id 9WZDNCRFHVQM&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Kamera-App: &lt;code&gt;winget install --id 9WZDNCRFJBBG&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;OneDrive: &lt;code&gt;winget install --id Microsoft.OneDrive&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;News: &lt;code&gt;winget install --id 9WZDNCRFHVFW&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Wetter-App: &lt;code&gt;winget install --id 9WZDNCRFJ3Q2&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Movies-und-TV-App: &lt;code&gt;winget install --id 9WZDNCRFJ3P2&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Und als Entwickler brauch man dann noch mindestens:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;winget install --id &quot;Notepad++.Notepad++&quot;&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;winget install --id Git.Git&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;winget install --id Kitware.Cmake&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;winget install --id Microsoft.VisualStudioCode&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;winget&lt;/code&gt; ist und bleibt die sinnvollste Erfindung der letzten 5 Jahre.
Und immer noch verstehe ich nicht, warum das so lange gedauert hat, dieses
Tool bereitzustellen.&lt;/p&gt;

&lt;p&gt;Mit der Installationsprozedur kann man jedenfalls sein profanes Windows IOT
in eine lebendige Umgebung verwandeln, die dem üblichen Benutzer-Windows um
nichts nachsteht … nur dass es eben 5 Jahre länger supportet wird.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Nochmal ein EOS Update</title>
   <link href="https://www.opengate.at/blog/2023/09/eos-update/"/>
   <published>2023-09-02T13:00:00+02:00</published>
   <updated>2023-09-02T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2023/09/eos-update</id>
   <category term="software" />
   <summary type="text">Aus gegebenem Anlass habe ich nochmal mein Sony Xperia mit dem neuesten 
/e/OS Betriebssystem aktualisiert.

Ich hatte es vor einem Jahr aufgesetzt
und dachte, die Prozedur würde sich leicht wiederholen lassen.
Naja … nicht ganz.
</summary>
   <content type="html">&lt;p&gt;Aus gegebenem Anlass habe ich nochmal mein Sony Xperia mit dem neuesten 
&lt;a href=&quot;https://de.wikipedia.org/wiki//e/OS&quot;&gt;/e/OS&lt;/a&gt; Betriebssystem aktualisiert.&lt;/p&gt;

&lt;p&gt;Ich hatte es &lt;a href=&quot;/blog/2022/11/eos/&quot;&gt;vor einem Jahr aufgesetzt&lt;/a&gt;
und dachte, die Prozedur würde sich leicht wiederholen lassen.&lt;br /&gt;
Naja … nicht ganz.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Da wir für &lt;a href=&quot;https://de.wikipedia.org/wiki/Android_(Betriebssystem)&quot;&gt;Android&lt;/a&gt; 
Updates einen Treiber benötigen und dies älteren davon leider nicht immer
offiziell auffindbar sind oder nicht signiert sind, ist der übelste Teil
Windows dazu zu bekommen, die INF-Treiber zu akzeptieren, damit die 
Android-Tools auch mit dem Zielgerät kommunizieren können.&lt;/p&gt;

&lt;p&gt;Ich verzichte ja nach Möglichkeit auf den Secure-Boot für Windows, doch da
dieser Standard ist, sollte dieser zuerst mal im BIOS Setup ausgeschaltet
werden. Auf Test-Laptops brachte ich die Treiber nämlich mit aktiviertem 
Secure-Boot nie zum Laufen.&lt;/p&gt;

&lt;p&gt;Danach kann man mit dem Aufruf von&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;bcdedit /set testsigning on
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;als Administrator ab dem nächsten Boot das Laden von nicht-signierten Treibern
gestatten. Alternativ lässt sich das auch in den &lt;code&gt;Einstellungen&lt;/code&gt; unter 
&lt;code&gt;Wiederherstellen&lt;/code&gt; und &lt;code&gt;Erweiterter Start&lt;/code&gt; aktivieren.&lt;/p&gt;

&lt;p&gt;Meine alten Links zur Sony Seite funktionieren leider inzwischen nicht mehr.
Ich konnte aber im Netz ein paar andere Varianten aufspüren, eine davon lag
unter &lt;a href=&quot;https://xperiausbdriver.com/sony-xperia-xa2-h3113&quot;&gt;xperiausbdriver.com/sony-xperia-xa2-h3113&lt;/a&gt;.&lt;br /&gt;
Mit etwas Glück sollte sich dieser Treiber dann installieren lassen, wenn das
Smartphone per USB verbunden ist, neu startet und die Tasten &lt;code&gt;+&lt;/code&gt; und &lt;code&gt;Power&lt;/code&gt;
gleichzeitig drückt werden.&lt;/p&gt;

&lt;p&gt;Ist das Rufzeichen oder Fragezeichen im Geräte-Manager neben dem Android ADB
Gerät verschwunden, kann man (hoffentlich) problemlos das Update durchführen.&lt;/p&gt;

&lt;p&gt;Inzwischen können die Android-Tools auch leicht per &lt;code&gt;winget&lt;/code&gt; installiert werden,
allerdings funktionieren sie nur, wenn man sie im Installationsverzeichnis ausführt:&lt;/p&gt;

&lt;div class=&quot;language-batch highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;winget install Google.PlatformTools
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;cd C:\Users\%USERNAME%\AppData\Local\Microsoft\WinGet\Packages\Google.PlatformTools_Microsoft.Winget.Source_8wekyb3d8bbwe\platform-tools
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Nun konnte ich das von der &lt;code&gt;/e/os&lt;/code&gt; Seite geholte Image auf das Smartphone
aufspielen. Und nach einem erfolgreich ausgeführtem &lt;code&gt;adb sideload ...&lt;/code&gt; und 
dem Abwarten der Installationsprozedur, startete am Ende mein Xperia 
problemlos mit der neuesten Version von &lt;code&gt;/e/os&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Das tolle am aktuellen Stand ist, dass &lt;code&gt;/e/os&lt;/code&gt; sich nun offenbar besser selbst
“on-the-fly” aktualisieren lässt. Weitere manuelle &lt;code&gt;adb&lt;/code&gt; Einsätze sollten damit
nicht mehr notwendig sein … hoffe ich.&lt;/p&gt;

&lt;p&gt;Doch es zeigt sich, dass die Setup Prozedur wegen verschwindender Treiber 
und immer wieder neueren Sicherheits-Spielereien in Windows einfach nur 
mühsam ist.&lt;br /&gt;
Hier heißt es dann:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Durchhalten und erneut probieren.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Irgendwann findet man schon die richtige Treiber- und Setup-Konstellation, 
die erfolgreich durchläuft.&lt;/p&gt;

&lt;p&gt;Und zum Glück konnten alle meine gescheiterten Image-Installation immer wieder
per Neustart des Smartphones von Vorne begonnen werden.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Python-Gitlab</title>
   <link href="https://www.opengate.at/blog/2023/08/python-gitlab/"/>
   <published>2023-08-27T13:00:00+02:00</published>
   <updated>2023-08-27T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2023/08/python-gitlab</id>
   <category term="software" />
   <summary type="text">Build- und Softwaresysteme wie Gitlab 
lassen sich durch beliebig viel Geld um beliebig viele Features erweitern.
Und dann sitzt man lange vor dem “Super-duper-Plugin” und weiß erst recht
wieder nicht, wie man das bekommt, was man haben möchte.

“Selber machen” ist dann immer die beste Lösung.
</summary>
   <content type="html">&lt;p&gt;Build- und Softwaresysteme wie &lt;a href=&quot;https://de.wikipedia.org/wiki/GitLab&quot;&gt;Gitlab&lt;/a&gt; 
lassen sich durch beliebig viel Geld um beliebig viele Features erweitern.&lt;br /&gt;
Und dann sitzt man lange vor dem “Super-duper-Plugin” und weiß erst recht
wieder nicht, wie man das bekommt, was man haben möchte.&lt;/p&gt;

&lt;p&gt;“Selber machen” ist dann immer die beste Lösung.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Ich bin durch meine Firma mit Gitlab gesegnet und nutze es daher fast täglich.&lt;/p&gt;

&lt;p&gt;Neben Quellcode- und Buildagent-Verwaltung existieren rudimentäre 
Auswertungen für Testfälle und andere Statistiken, die jedoch für jedes 
Projekt einzeln ermittelt und auch nur separat angezeigt werden können.&lt;/p&gt;

&lt;p&gt;Oft sind aber projektübergreifende Details interessant und hier muss man
je nach Anwendungsfall entweder zu externen Plugins greifen, oder
Auswertungsjobs von kompletten Fremdsystemen durchführen lassen.&lt;/p&gt;

&lt;p&gt;Was oft übersehen wird ist:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Gitlab hat für fast alles eine &lt;a href=&quot;https://de.wikipedia.org/wiki/Representational_State_Transfer&quot;&gt;REST&lt;/a&gt;
oder zumindest RESTartige Webschnittstelle.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Alles, was das Web-UI anzeigt, kann auch separat als 
&lt;a href=&quot;https://de.wikipedia.org/wiki/JavaScript_Object_Notation&quot;&gt;JSON&lt;/a&gt; Datensatz
heruntergeladen werden. Und wenn die Daten schon als &lt;code&gt;JSON&lt;/code&gt; da sind, kann man 
sie in weiteren Scriptsprachen wie etwa &lt;a href=&quot;https://de.wikipedia.org/wiki/Python_(Programmiersprache)&quot;&gt;Python&lt;/a&gt; 
relativ leicht kombinieren, auswerten oder in andere Formate übertragen.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://python-gitlab.readthedocs.io/en/stable/&quot;&gt;python-gitlab&lt;/a&gt; ist ein Modul,
welches die HTTP-Webrequests in einfache Python Objekte verpackt, die ziemlich
selbsterklärend benutzt werden können.&lt;/p&gt;

&lt;h3 id=&quot;auf-zum-script&quot;&gt;Auf zum Script!&lt;/h3&gt;

&lt;p&gt;Man braucht zuerst mal einen Access-Token zu den Projekten, den man sich im
Gitlab WebUI unter seinem Benutzerprofil anlegen kann. Dort wird festgelegt,
ob der Token nur Leserechte hat, oder auch etwas verändern darf.&lt;/p&gt;

&lt;p&gt;Dann installiert man sich das &lt;code&gt;python-gitlab&lt;/code&gt; Modul per &lt;code&gt;pip&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;pip install python-gitlab
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;und kann mit dem Scripten anfangen.&lt;/p&gt;

&lt;p&gt;Ich nutze fixe Gruppen in Gitlab, in denen meine Projekte liegen.
Da sich die nie ändern, kann man sie einfach über ihre IDs ansprechen.
Die IDs von Gruppen oder Projekten findet man auch in der Gitlab Web-UI 
im Untertitel, wenn man eine Gruppe oder Projekt öffnet.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;import&lt;/span&gt; &lt;span style=&quot;color:#B44;font-weight:bold&quot;&gt;gitlab&lt;/span&gt; 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;gl = gitlab.Gitlab(url=&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;https://my.gitlab.server&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;, private_token=&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;abcdefg&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;mygroup = gl.groups.get(&lt;span style=&quot;color:#00D&quot;&gt;12345&lt;/span&gt;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;myprojects = mygroup.projects.list()
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;for&lt;/span&gt; entry &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;in&lt;/span&gt; myprojects:
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  print(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;ID#{} {}: {}&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;.format(entry.id, entry.name, entry.http_url_to_repo))
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Und schon finde ich eine Liste aller Projekte in meiner Gruppe vor. Mit dem
&lt;code&gt;http_url_to_repo&lt;/code&gt; Feld könnte man sich jetzt gleich ein &lt;code&gt;git clone&lt;/code&gt; basteln,
das alle Projekte lokal herunterlädt.&lt;/p&gt;

&lt;p&gt;Spannender wird es dann aber, wenn man auf die Pipelines der Projekte zugreift
und dort den Status der Ausführung ausliest, und die Statistik der 
&lt;a href=&quot;https://de.wikipedia.org/wiki/JUnit&quot;&gt;JUnit&lt;/a&gt; Tests erhält.&lt;br /&gt;
Denn so kann man sich als Entwickler mit wenigen Zeilen einen Übersichtsmonitor
bauen, der anzeigt, was gerade gut und eher schlecht gelaufen ist und 
Nacharbeitung benötigt.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Mit der Gitlab-Web-API kann man die Buildumgebung automatisieren, überwachen
und auswerten lassen.&lt;br /&gt;
Zwar langweilen mich solche Scriptereien im Job oft, aber ich habe es zu 
schätzen gelernt, wie man sich seinen Alltag mit ein paar Zeilen vereinfachen 
kann.&lt;/p&gt;

&lt;p&gt;Das Arbeiten mit Buildsystem gehört heute vor allem in Großprojekten zum 
Standard, und die Zeiten, wo der Entwickler-Rechner auch gleich die Releases 
erzeugte sind (leider) lange vorbei.&lt;/p&gt;

&lt;p&gt;Folglich sollte “Buildserver-Scripting” in jeder Schule unterrichtet werden, 
denn wer weiß … bald braucht jeder Handwerker einen Buildserver um seine
Maschinen auf den neuesten Stand zu bekommen.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>std::unique_ptr</title>
   <link href="https://www.opengate.at/blog/2023/08/unique_ptr/"/>
   <published>2023-08-26T13:00:00+02:00</published>
   <updated>2023-08-26T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2023/08/unique_ptr</id>
   <category term="devel" />
   <summary type="text">Als ich neulich freudig folgendes vor Kollegen verkündete:


  Wir können problemlos native Pointer mit unique_ptr ersetzen,
da das Layout der Objekte gleich ist.


wurde dagegen argumentiert.
Grund genug, das nochmal aufzurollen.
</summary>
   <content type="html">&lt;p&gt;Als ich neulich freudig folgendes vor Kollegen verkündete:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Wir können problemlos native Pointer mit &lt;code&gt;unique_ptr&lt;/code&gt; ersetzen,
da das Layout der Objekte gleich ist.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;wurde dagegen argumentiert.&lt;br /&gt;
Grund genug, das nochmal aufzurollen.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Memory-Leaks fühlen sich besonders dort wohl, wo 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Ressourcenbelegung_ist_Initialisierung&quot;&gt;RAII&lt;/a&gt; 
nicht angewendet wird. Genau das geschieht auch in Projekten, die ich 
mitbetreuen darf.&lt;/p&gt;

&lt;p&gt;Jetzt herrscht dort leider die Meinung, dass alle erkannten Memory-Leaks
nur einmalige Allokierungen sind, weil vieles aus globalen Singletons 
hervorgeht.&lt;/p&gt;

&lt;p&gt;Das stimmt streng genommen auch, und man kann globale Variablen gerne
formal ausnehmen … doch Leak-Detektoren tun das nicht von selbst.&lt;br /&gt;
Und wenn man dann zahlreiche Unit-Tests ausführt, die alle unzählige 
Leaks aus solchen Singletons melden, bringt die Erkennung genau gar nichts,
weil sie keiner mehr ernst nimmt.&lt;/p&gt;

&lt;p&gt;Die Devise sollte also lauten:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Wir beheben diese Leaks so gut wie möglich, damit wir im Bericht am Ende
die relevanten Leaks angezeigt bekommen, die wir weiterverfolgen sollen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Tja und tatsächlich hilft einem da ein Smart-Pointer, der am Prozessende
automatisch zerstört wird. &lt;code&gt;std::unique_ptr&lt;/code&gt; ist ein perfekter Kandidat 
solche nativen Pointer zu ersetzen und das Cleanup so dem Compiler zu 
überlassen.&lt;/p&gt;

&lt;p&gt;Spätestens hier meldet sich dann das Deployment Team und fragt, ob eine 
solche Codeänderung die Binärkompatibilität bricht und ob Patches dann
noch möglich sind.&lt;/p&gt;

&lt;h3 id=&quot;auto_ptr-vs-unique_ptr&quot;&gt;auto_ptr vs unique_ptr&lt;/h3&gt;

&lt;p&gt;Ein &lt;code&gt;std::auto_ptr&lt;/code&gt; besteht genau aus einem Member, nämlich aus dem Pointer
zum verwalteten Objekt. Und seine &lt;code&gt;reset()&lt;/code&gt; und Destruktorfunktionen führen ein
&lt;code&gt;delete&lt;/code&gt; auf eben diesen Pointer aus.&lt;br /&gt;
Das bedeutet eine &lt;code&gt;int*&lt;/code&gt; Variable und ein &lt;code&gt;auto_ptr&amp;lt;int&amp;gt;&lt;/code&gt; haben in der Regel 
das gleiche Speicherlayout.&lt;/p&gt;

&lt;p&gt;Diese Behauptung wird zwar nicht durch den Standard gedeckt, aber auf allen 
unseren üblichen Plattformen ist das durch die Compiler de facto garantiert.&lt;/p&gt;

&lt;p&gt;Man kann also durchaus eine &lt;code&gt;.dll&lt;/code&gt; oder &lt;code&gt;.so&lt;/code&gt; patchen, die original ein Objekt
mit einem &lt;code&gt;T*&lt;/code&gt; definiert, welches durch einen &lt;code&gt;auto_ptr&amp;lt;T&amp;gt;&lt;/code&gt; ersetzt wird.
Die Datengröße und das Layout bleiben gleich, nur Codes führen jetzt ein
automatisches Cleanup durch.&lt;/p&gt;

&lt;p&gt;Bei &lt;code&gt;std::unique_ptr&lt;/code&gt; hatte ich anfangs meine Zweifel, ob man hier auch so
vorgehen kann. Schließlich bietet unique_ptr an, eine Freigabefunktion
dem Objekt beizulegen, die das referenzierte Objekt zerstören können soll.
Das ist im Normalfall dann auch wieder ein &lt;code&gt;delete ptr&lt;/code&gt;, kann aber durch
etwas anderes abgewandelt werden.&lt;/p&gt;

&lt;p&gt;Meine Befürchtung war, dass weitere Funktionszeiger in &lt;code&gt;unique_ptr&lt;/code&gt; integriert
werden und womit das &lt;code&gt;unique_ptr&lt;/code&gt; Objekt dann mehr als nur den zu verwaltenden
Pointer mitführt.&lt;/p&gt;

&lt;h3 id=&quot;compressed-pair&quot;&gt;Compressed Pair&lt;/h3&gt;

&lt;p&gt;Wie so oft hat &lt;a href=&quot;https://devblogs.microsoft.com/oldnewthing/20230801-00/?p=108509&quot;&gt;Raymond Chen bereits die Lösung publiziert&lt;/a&gt;
und beschreibt die &lt;code&gt;MSVC&lt;/code&gt; Lösung, die auch in anderen 
STL-Implementierungen angewendet wird:&lt;/p&gt;

&lt;p&gt;Der Deleter-Funktor (dessen Default Typ einfach &lt;code&gt;std::default_delete&lt;/code&gt; heißt) 
wird nicht als Member dem &lt;code&gt;unique_ptr&lt;/code&gt; angehängt, sonder &lt;code&gt;unique_ptr&lt;/code&gt; erbt
von diesem Typ. Und so lange dieser Typ selbst keine Datenmember besitzt
(was bei &lt;code&gt;std::default_delete&lt;/code&gt; der Fall ist), wächst &lt;code&gt;unique_ptr&lt;/code&gt; nicht,
sondern definiert seine Größe nur nach dem bekannten Pointer zum Objekt.&lt;/p&gt;

&lt;p&gt;Beim MSVC gibt es dafür den Typ &lt;code&gt;compressed_pair&amp;lt;K, V&amp;gt;&lt;/code&gt; welcher von &lt;code&gt;K&lt;/code&gt; erbt
und nur &lt;code&gt;V&lt;/code&gt; als echten Value-member anhängt.&lt;/p&gt;

&lt;h3 id=&quot;konstruktion-von-objekten&quot;&gt;Konstruktion von Objekten&lt;/h3&gt;

&lt;p&gt;Die Größen von Klassen und ihren Unterobjekten sind essentiell für das
Erzeugen und den Zugriff auf instanziierte Objekte. Wenn also ein Typ
in einem Modul (DLL/SO) eingesetzt wird und ich dessen Code neu 
kompilieren und ausrollen möchte, darf sich das Objektlayout um kein
einziges Bit ändern, denn sonst stimmt es mit früheren Kompilaten nicht
mehr überein. Code hingegen wird über Namenstabellen beim dynamischen
Einbinden neu aufgelöst.&lt;/p&gt;

&lt;p&gt;Um also eine Plugin-SO/DLL gefahrlos patchen zu können, muss sichergestellt 
sein, dass alle Datenstrukturen exakt gleich groß sind und mit identischen 
Offsets herauskommen.&lt;/p&gt;

&lt;p&gt;Und eben genau das ist bei &lt;code&gt;std::unique_ptr&lt;/code&gt; dann der Fall, wenn man die 
Default-Implementierung nutzt.&lt;/p&gt;

&lt;h3 id=&quot;beispiel&quot;&gt;Beispiel&lt;/h3&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;my_worker_impl&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;my_worker&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;public&lt;/span&gt;:
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;  my_worker()
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  : ptr(&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;new&lt;/span&gt; my_worker_impl())
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;  {
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;  }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;private&lt;/span&gt;:
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;//my_worker_impl* ptr;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;// PATCH: replace raw ptr with unique_ptr&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;  std::unique_ptr&amp;lt;my_worker_impl&amp;gt; ptr;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;};
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;my_worker singleton_instance;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Durch die Änderung bleiben die Daten exakt an der gleichen Stelle, doch 
&lt;code&gt;unique_ptr&lt;/code&gt; generiert automatisch einen Destruktor-Aufruf, der am Ende des
Prozesses das allokierte Objekt wieder freigibt.&lt;/p&gt;

&lt;p&gt;Und wenn &lt;code&gt;my_worker&lt;/code&gt; jetzt ein Member in einem anderen Objekt sein sollte,
das in einem Modul liegt, welches mit dem alten Header kompiliert wurde,
so ist ein binärkompatibler Patch ebenso möglich.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Man muss natürlich klar darauf hinweisen, dass Binärkompatibilität nicht
durch Standards gedeckt wird. Eigentlich handelt es sich hierbei um
“undefinied behavior”. Das bedeutet aber nicht, dass auf bestimmten 
Plattformen das Verhalten dann trotzdem vom Hersteller garantiert ist.&lt;/p&gt;

&lt;p&gt;Der Wechsel von raw-Pointern zu &lt;code&gt;unique_ptr&lt;/code&gt; wäre also so ein Fall,
der unter Windows und Linux durchführbar ist und die Codequalität
erhöht, ohne dass man manuell neue Destruktoren oder Ähnliches
schreiben müsste.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>IBM PS/2 30 Floppy Adapter</title>
   <link href="https://www.opengate.at/blog/2023/08/floppy-adapter/"/>
   <published>2023-08-19T13:00:00+02:00</published>
   <updated>2023-08-19T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2023/08/floppy-adapter</id>
   <category term="hardware" />
   <summary type="text">Bei meinem PS/2 30 sind die originalen 
Diskettenlaufwerke 
eingegangen und leider passen neue Floppy-Drives nicht mit den alten 
Anschlüssen zusammen.

Doch zum Glück bietet die Firma texELEC einen Adapter an, der übliche
PC-Diskettenlaufwerke mit dem alten 
IBM PS/2 verheiraten kann.
</summary>
   <content type="html">&lt;p&gt;Bei &lt;a href=&quot;/blog/2022/08/ps2-30/&quot;&gt;meinem PS/2 30&lt;/a&gt; sind die originalen 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Diskettenlaufwerk&quot;&gt;Diskettenlaufwerke&lt;/a&gt; 
eingegangen und leider passen neue Floppy-Drives nicht mit den alten 
Anschlüssen zusammen.&lt;/p&gt;

&lt;p&gt;Doch zum Glück bietet die Firma &lt;code&gt;texELEC&lt;/code&gt; einen Adapter an, der übliche
PC-Diskettenlaufwerke mit dem alten 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Personal_System/2&quot;&gt;IBM PS/2&lt;/a&gt; verheiraten kann.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Disketten und ihre Laufwerke sind eine kritische Sache. Sie werden etwa seit 
dem Jahr 2000 nicht mehr produziert, und das heißt, alle Medien und Geräte,
die es aktuell gibt, sind die letzten.&lt;br /&gt;
Im Falle meines IBM PS/2 aus dem Jahre 1987 sprechen wir von 35 Jahre alter
Hardware und der Tod der “beweglichen” Teile ist da ganz natürlich.&lt;/p&gt;

&lt;p&gt;Vermutlich könnte man die Laufwerke noch reparieren, wenn nur ein Gummiriemen
defekt ist. Bei einem kaputtem Motor, wird es schon komplizierter.&lt;/p&gt;

&lt;p&gt;Doch aus den späten 90ern liegen bei mir noch einige handelsübliche 3.5 Zoll
Laufwerke herum, warum also nicht diese nutzen?&lt;/p&gt;

&lt;p&gt;Die üblichen 34-PIN Flachbandkabel passen jedoch nicht zu den alten 
Steckanschlüssen des IBM PS/2 M30&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/ibm-ps2-floppy-adapter-4.jpg&quot; alt=&quot;IBM PS/2 M30 Floppy Adapter 4&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;ein-adapter-für-neue-laufwerke&quot;&gt;Ein Adapter für neue Laufwerke&lt;/h3&gt;

&lt;p&gt;Und dann fand ich zufällig ein Produkt, das eine Brücke zwischen den Laufwerken der
90er und der 80er Jahre bauen kann:&lt;br /&gt;
Den &lt;code&gt;IBM PS/2 to Standard Floppy adapter&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/ibm-ps2-floppy-adapter-1.jpg&quot; alt=&quot;IBM PS/2 M30 Floppy Adapter 1&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Bestellung, Zahlung und Versand funktionierten unkompliziert und schon bald erreicht
mich die Sendung mit der begehrten Hardware.&lt;/p&gt;

&lt;p&gt;Ich verbaute diese im Gerät und schloss es auf Position von Laufwerk A: an,
legte eine alte 720 KB (Double-Density) DOS-Diskette ein und startete das System.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/ibm-ps2-floppy-adapter-2.jpg&quot; alt=&quot;IBM PS/2 M30 Floppy Adapter 2&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Ich war beeindruckt, als ich am Lesegeräusch des Laufwerks das Laden des 
Betriebssystem feststellen konnte. Parallel zeigte der Monitor die ersten DOS
Zeilen an.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/ibm-ps2-floppy-adapter-3.jpg&quot; alt=&quot;IBM PS/2 M30 Floppy Adapter 3&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;Es ist geschafft!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Im Jahr 2023 darf das Gerät das erst Mal seit über 20 Jahren wieder ein 
Betriebssystem starten, denn seit damals konnte ich das Gerät mangels 
funktionierender Laufwerke nicht mehr starten.&lt;/p&gt;

&lt;p&gt;Ich erinnere mich, dass auch MS-DOS 6.22 auf dem 8088 Prozessor erfolgreich
lief. Als nächstes brauche ich also ein größeres Speichermedium als eine
3.5 Diskette.&lt;br /&gt;
… mal sehen ob sich da was auftreiben lässt.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Das Ende der &apos;.sln&apos;</title>
   <link href="https://www.opengate.at/blog/2023/08/end-solution/"/>
   <published>2023-08-13T13:00:00+02:00</published>
   <updated>2023-08-13T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2023/08/end-solution</id>
   <category term="devel" /><category term="software" />
   <summary type="text">Seit meinen ersten Entwicklungs-Experimenten in Visual Basic sind sie fix
dabei: Die Verwaltungsdateien von Visual Studio.
Sie fassen die eigentlichen Source-Code-Dateien zusammen und heißen
“Projekte” im Einzelfall (.vcproj, .vcxproj) oder “Solution” (.sln)
als Sammlungen.

Jetzt ist Schluss damit. Ab jetzt kümmert sich ausschließlich 
CMake um diese Details.
</summary>
   <content type="html">&lt;p&gt;Seit meinen ersten Entwicklungs-Experimenten in Visual Basic sind sie fix
dabei: &lt;em&gt;Die Verwaltungsdateien von Visual Studio&lt;/em&gt;.
Sie fassen die eigentlichen Source-Code-Dateien zusammen und heißen
“Projekte” im Einzelfall (&lt;code&gt;.vcproj&lt;/code&gt;, &lt;code&gt;.vcxproj&lt;/code&gt;) oder “Solution” (&lt;code&gt;.sln&lt;/code&gt;)
als Sammlungen.&lt;/p&gt;

&lt;p&gt;Jetzt ist Schluss damit. Ab jetzt kümmert sich ausschließlich 
&lt;a href=&quot;https://de.wikipedia.org/wiki/CMake&quot;&gt;CMake&lt;/a&gt; um diese Details.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;die-geschichte-eines-fehlers&quot;&gt;Die Geschichte eines Fehlers&lt;/h3&gt;

&lt;p&gt;Da ich mit Windows aufgewachsen bin, habe ich das “grafische” Hinzufügen und
Entfernen von Quellcodes zu einem “Projekt” immer als die beste und stabilste
Form angesehen.&lt;br /&gt;
Ein neues Projekt wurde damit immer in der IDE erstellt und dann vollständig
in das Versionsverwaltungssystem eingespielt.&lt;/p&gt;

&lt;p&gt;Und früher war das auch überlegen, denn ein Visual Studio 2005 Solution 
funktionierte bei rein nativem Code überall ohne Kunstgriffe.&lt;/p&gt;

&lt;p&gt;Bei Linux hingegen funktionierte alles grundsätzlich nur auf dem 
Originalsystem. Wer also unter &lt;a href=&quot;https://de.wikipedia.org/wiki/OpenSUSE&quot;&gt;SUSE&lt;/a&gt;
gegen 3 Bibliotheken per Makefile linkte konnte nicht wissen, ob die unter 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Ubuntu_(Betriebssystem)&quot;&gt;Ubuntu&lt;/a&gt; auch so heißen 
und durfte dann das Buildscript anpassen, oder lange aus-if-en, wie die 
Komponenten heißen.&lt;/p&gt;

&lt;p&gt;Und um das “grafisch” besser kontrollieren zu können, nutzte ich lange Zeit
Code::Blocks um auch Linux solche Projektdateien aufzuzwingen.&lt;/p&gt;

&lt;p&gt;Ich generierte also “irgendwie” für jede Bibliothek ein Visual Studio und
ein Code::Blocks Projekt und verwaltete diese dann für unterschiedlichen
Plattformen.&lt;/p&gt;

&lt;p&gt;Unter Linux war das … naja … immer schon blöd, es funktionierte aber 
unter Windows super, bis mit Studio 2012 neue Plattformtypen hinzukamen, 
die man nicht mehr in einer Solution unterbringen konnte.&lt;/p&gt;

&lt;p&gt;Windows Phone und die Universal Windows Plattform brauchten eigene Solutions
für sich, und so erzeugte ich eine Win32-Solution, eine UWP-Solution und 
später dann mit VS 2017 eine Android-Solution um immer die gleichen Sourcen
zu einem Projekt zusammenzubinden.&lt;/p&gt;

&lt;h3 id=&quot;cmake-löst-heute-alles&quot;&gt;CMake löst heute alles&lt;/h3&gt;

&lt;p&gt;Ich kann es heute ja immer noch nicht nachvollziehen, warum ich CMake so
lange verweigert hatte. Grund dafür waren “komplizierte” Querschläger wie
OpenSSL, die zwar für Win32 und Linux toll waren, bei WinCE oder UWP aber
versagten. Doch das hätte ich auch damals schon angehen können.&lt;/p&gt;

&lt;p&gt;Inzwischen hat CMake viele Tricks drauf um wirklich alle meine Wünsche zu 
erfüllen und daher habe ich nun auch im GATE Projekt mit der Entfernung 
aller Solution- und Projekt-Dateien begonnen.&lt;br /&gt;
Es ist heute auch gar nicht mehr möglich die Buildkonfiguration hart 
festzulegen, denn jede Studio-Installation kommt mit einem anderen SDK und
mit jedem Update ändert sich dann auch noch der Minimum-Support der 
Zielplattform. Man müsste also in jedem Studio mit der Hin- und 
Herkonvertierung starten und das ist erst recht wieder Fehleranfällig.&lt;/p&gt;

&lt;p&gt;CMake erkennt brav, was auf dem System vorhanden ist und erzeugt die 
Solutions und Projekte automatisch genau so, damit sie alles Vorhandene
finden und nutzen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;Good Bye SLN!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Es erzeugt in mir immer ein gewisses Retro-Feeling, wenn in einem Sourcepaket
eine &lt;code&gt;.sln&lt;/code&gt; Datei oder was Ähnliches drinnen ist. Besonders auf 
&lt;a href=&quot;https://www.codeproject.com/&quot;&gt;codeproject.com&lt;/a&gt; findet man noch viele solcher
alten C++ Projekte.&lt;/p&gt;

&lt;p&gt;Heute erwarte ich von jedem C/C++ Projekt, dass eine &lt;code&gt;CMakeLists.txt&lt;/code&gt; Datei
enthalten ist. Denn mit dieser lässt sich dann für wesentlich mehr Plattformen
eine Buildprozedur einrichten.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Android mit CMake</title>
   <link href="https://www.opengate.at/blog/2023/08/android-cmake/"/>
   <published>2023-08-12T13:00:00+02:00</published>
   <updated>2023-08-12T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2023/08/android-cmake</id>
   <category term="devel" />
   <summary type="text">Mit der Migration zu Visual Studio 
2022 gingen mir meine Android 
Builds verloren. Nun müssen diese neu erdacht werden.

Und eben dafür soll mir nun CMake
aus der Patsche helfen.
</summary>
   <content type="html">&lt;p&gt;Mit der Migration zu &lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_Studio&quot;&gt;Visual Studio&lt;/a&gt; 
2022 gingen mir meine &lt;a href=&quot;https://de.wikipedia.org/wiki/Android_(Betriebssystem)&quot;&gt;Android&lt;/a&gt; 
Builds verloren. Nun müssen diese neu erdacht werden.&lt;/p&gt;

&lt;p&gt;Und eben dafür soll mir nun &lt;a href=&quot;https://de.wikipedia.org/wiki/CMake&quot;&gt;CMake&lt;/a&gt;
aus der Patsche helfen.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Als ich das GATE Projekt mit dem Studio 2017 damals startete, legte ich auch
eine parallel Solution für Android an, um mit den Standard-Toolkits, die beim
Studio dabei waren, Android Apps bauen zu können.&lt;/p&gt;

&lt;p&gt;Das funktionierte zwar recht gut, doch so musste ich jede neue Codedatei von
Hand in mehrere Solutionzweige aufnehmen und diverse Build-Flags immer doppelt
und dreifach warten.&lt;/p&gt;

&lt;p&gt;Folglich soll auch diese Konfiguration von CMake übernommen werden:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;cmake -DCMAKE_SYSTEM_NAME=Android -A x64 path_to_src
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;reicht bei einem heutigen &lt;code&gt;CMake&lt;/code&gt; aus, um Visual Studio automatisch zu finden
und dort dessen installierte Android Features zu aktivieren.&lt;br /&gt;
Das Ergebnis ist eine generierte Visual Studio Solution (&lt;code&gt;.sln&lt;/code&gt;), deren 
Projekte gegen das “Standard” Android NDK kompiliert und linkt.&lt;/p&gt;

&lt;h3 id=&quot;fehlende-paketierung&quot;&gt;Fehlende Paketierung&lt;/h3&gt;

&lt;p&gt;Während also meine Binärdateien schon brav generiert werden können, fehlt
leider ein entscheidendes Detail: Das APK Paket.&lt;/p&gt;

&lt;p&gt;Im alten VS 2017 wurde das vom Projekt-Template miterzeugt und baute ein 
&lt;code&gt;APK&lt;/code&gt; Paket mit dem &lt;code&gt;NativeActivity&lt;/code&gt; Modul aus der C++ Buildtoolchain.&lt;br /&gt;
So konnte man die neue App auch gleich im Emulator testen und sogar debuggen.&lt;/p&gt;

&lt;p&gt;Noch weiß ich nicht, wie man das in &lt;code&gt;CMake&lt;/code&gt; erzeugen lassen kann, also wird
das wohl meine nächste Aufgabe werden.&lt;br /&gt;
Parallel stellt sich heraus, dass VS 2022 offenbar auch das 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Apache_Ant&quot;&gt;Buildsystem Ant&lt;/a&gt; nicht mehr
unterstützt, welches in VS 2017 noch Standard war.&lt;br /&gt;
Also ist auch hier noch eine Baustelle offen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Die Umstellung von VS-Solutions auf &lt;code&gt;CMake&lt;/code&gt; ist bestimmt der richtige Schritt
für die Zukunft. Aktuell ist das aber leider ein Rückschritt, da ich vorerst
keine Android-Pakete mehr erstellen und testen kann.&lt;/p&gt;

&lt;p&gt;Das ist zwar jetzt keine großes Drama … aber ich fand es schon toll, dass
ich meine &lt;a href=&quot;https://de.wikipedia.org/wiki/OpenGL&quot;&gt;OpenGL&lt;/a&gt; GATE-Programme direkt
auch als Android-App am Smartphone sehen konnte.&lt;br /&gt;
… aber das wird ja hoffentlich bald auch wieder funktionieren.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Audio am Raspberry PI</title>
   <link href="https://www.opengate.at/blog/2023/08/raspberry-audio/"/>
   <published>2023-08-06T13:00:00+02:00</published>
   <updated>2023-08-06T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2023/08/raspberry-audio</id>
   <category term="hardware" />
   <summary type="text">Da stecke ich mal einen passiven Lautsprecher in die Buchse eines
Raspberry PI 2 und erschrecke 
bei den erklingenden Kratz- und Störgeräuschen.

Der RPI überträgt nämlich auch Videodaten über diesen Stecker … und ich
dachte, ich muss diese wegfiltern.
</summary>
   <content type="html">&lt;p&gt;Da stecke ich mal einen passiven Lautsprecher in die Buchse eines
&lt;a href=&quot;https://de.wikipedia.org/wiki/Raspberry_Pi&quot;&gt;Raspberry PI&lt;/a&gt; 2 und erschrecke 
bei den erklingenden Kratz- und Störgeräuschen.&lt;/p&gt;

&lt;p&gt;Der RPI überträgt nämlich auch Videodaten über diesen Stecker … und ich
dachte, ich muss diese wegfiltern.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;blockquote&gt;
  &lt;p&gt;Spoiler: Es lag am Stecker.&lt;br /&gt;
Und eigentlich war meine ganze Aktion nur eine Spaßübung.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Unsere &lt;a href=&quot;https://de.wikipedia.org/wiki/Klinkenstecker&quot;&gt;3.5mm Audiostecker&lt;/a&gt; sind
zwar “meistens” einheitlich aufgebaut wenn es um Audio geht, es gibt aber 
auch ein paar Ausnahmen.&lt;/p&gt;

&lt;p&gt;In der simpelsten Variante gibt es nur zwei Kontakte, wobei die Hälfte der 
Spitze den Mono-Ton überträgt und am restlichen Schaftkontakt die Masse 
(Ground) liegt.&lt;br /&gt;
Also: &lt;code&gt;&amp;lt;=====mono=====|=====ground=====####------------Device&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Dann kann man die Spitze in linken und rechten Kanal unterteilen (links ist 
ganz vorne) gefolgt vom Ground.&lt;br /&gt;
Also: &lt;code&gt;&amp;lt;=left=|=right=|=====ground=====####------------Device&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Und schließlich kann man auch einen Ring vom Ground abschotten und 
“was anderes” wie das Mikrofon oder eben Video darüber übertragen.&lt;/p&gt;

&lt;p&gt;Das heißt also vom Steckerplastik bis zur Spitze liegen 4 Ringe, nämlich:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Links (Spitze)&lt;/li&gt;
  &lt;li&gt;Rechts&lt;/li&gt;
  &lt;li&gt;Ground&lt;/li&gt;
  &lt;li&gt;Mikrofon/Video&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Also: &lt;code&gt;&amp;lt;=left=|=right=|=ground=|=micro=####------------Device&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Wenn man jetzt einen Stecker mit 3 Kontakten (L,R und Ground) hat und dieser
in eine 4-polige Buchse gesteckt wird, sollte der Chip die Überbrückung 
zwischen den beiden Kontaktringen feststellen und die optionale Übertragung
ausschalten (bzw. ist die dann sowieso kurzgeschlossen).&lt;/p&gt;

&lt;p&gt;Doch da bei meinem alten Lautsprecher furchtbares Kratzen auftrat, dachte
ich, dass da was nicht korrekt funktionierte und so beschloss ich, aus ein 
paar alten Teilen einen “modularen” Stecker zu basteln um ausprobieren zu 
können, welcher Kontakt was überträgt.&lt;/p&gt;

&lt;p&gt;Und somit verlötete ich 4 Litzen mit einem 4-poligen 3.5mm Stecker und am 
anderen Ende mit Pinsteckern. Dann packte ich noch eine 3-polige Audiobuchse
auf eine Protoplatine zusammen mit einer Doppelpinbuchsenreihe.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/audiojack-rpi.jpg&quot; alt=&quot;RPI audio adapter&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Die 3.5mm Buchse passte nur verdreht auf die Platine … aber zum Ausprobieren 
ist das OK.&lt;/p&gt;

&lt;p&gt;Kaum hatte ich meinen Adapter zwischen Raspberry PI und Lautsprecher geschaltet
und nur die 3 relevanten Pins verbunden, kamen klare Töne aus dem Gerät und
meine Mission war damit erfüllt.&lt;/p&gt;

&lt;p&gt;Mit den Steckern konnte ich noch ein bisschen herumspielen und feststellen,
was ich alles “verdrehen” konnte.&lt;/p&gt;

&lt;p&gt;Am Ende stellte ich jedoch mit anderen Kopfhörern und Lautsprechern fest,
dass ich diese auch direkt am Raspberry PI nutzen konnte, ohne dass Störungen
hörbar wurden.&lt;br /&gt;
Der Grund war denkbar einfach: Der Stecker passte offenbar nicht ganz genau
in die Buchse und so kam es offenbar auch zu anderen Überbrückungen.
(Auch das 3D-gedruckte Gehäuse war daran etwas beteiligt.)&lt;br /&gt;
Mit etwas Gewalt konnte ich den Stecker temporär so fest einschieben, dass
er auch ohne Adapter direkt klangrein arbeitete.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Auch wenn es Alternativen gibt, so ist das kleine Adapterchen gar nicht mal 
so unpraktisch. Ich fände es generell super, wenn man bei allen Kabeln die 
einzelnen Kanäle aus- und einschalten bzw. auch umstecken könnte.&lt;/p&gt;

&lt;p&gt;Zumindest habe ich gelernt, dass die Audio Pin-Belegung des Raspberry PI 
doch nicht vom Standard abweicht, was ich anfangs fälschlich annahm.&lt;br /&gt;
Nun könnte ich den RPi auch “lautstark” mitteilen lassen, woran er gerade
arbeitet.&lt;br /&gt;
… doch das ist eine andere Geschichte.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>M2 SSD Varianten</title>
   <link href="https://www.opengate.at/blog/2023/08/m2-ssd/"/>
   <published>2023-08-05T13:00:00+02:00</published>
   <updated>2023-08-05T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2023/08/m2-ssd</id>
   <category term="hardware" />
   <summary type="text">Als 10 Jahre lang alles über IDE 
angeschlossen wurde (also zwischen 1995 und 2005), war meine kleine Welt 
noch in Ordnung.
Ja, es gab dann die 40 und 80 poligen Kabel, aber alles war abwärts kompatibel.

SATA hätte diese Tradition als 
“ein” universeller Steckerstandardübernehmen sollen. Doch dann kamen MSATA
und M.2 mit ihren “Keys” …
</summary>
   <content type="html">&lt;p&gt;Als 10 Jahre lang alles über &lt;a href=&quot;https://de.wikipedia.org/wiki/ATA/ATAPI&quot;&gt;IDE&lt;/a&gt; 
angeschlossen wurde (also zwischen 1995 und 2005), war meine kleine Welt 
noch in Ordnung.
Ja, es gab dann die 40 und 80 poligen Kabel, aber alles war abwärts kompatibel.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Serial_ATA&quot;&gt;SATA&lt;/a&gt; hätte diese Tradition als 
“ein” universeller Steckerstandardübernehmen sollen. Doch dann kamen &lt;code&gt;MSATA&lt;/code&gt;
und &lt;code&gt;M.2&lt;/code&gt; mit ihren “Keys” …
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;sata-festplatten-anschlüsse&quot;&gt;SATA Festplatten Anschlüsse&lt;/h3&gt;

&lt;p&gt;Serial-ATA definiert unter anderem auch die Steckkontakte zwischen Festplatten,
Verkabelung und dem PC.&lt;br /&gt;
Da wäre der etwa 1cm breite Datenkontakt mit 7 Pins und der etwa 2 cm breite
Stromkontakt mit 15 Pins. Beide Steckkontakte sind an einer Seite mit einer
Erhebung ausgestattet, damit man Stecker nicht falsch einstöpseln kann.&lt;/p&gt;

&lt;p&gt;Diese Teil war ein großer Vorsprung zum früheren IDE/ATAPI 40-Pin 
Flachbandstecker mit dem 4-Pin Molex-Stromanschluss. Denn dort waren zwar
die beiden Steckkontakte definiert, nicht aber deren genaue Position auf 
dem Datenträger. Und so müssen bis heute Festplatten-Docking-Stations mit
verschiebbaren Kontakten ausgestattet sein, die man an die Platte anpassen
muss.&lt;/p&gt;

&lt;p&gt;SATA definiert aber, dass die beiden SATA-Kontakte nebeneinander mit einem
festen Abstand liegen müssen.&lt;br /&gt;
Und somit kann man de facto alle SATA Platten überall problemlos anhängen,
und SATA Controller auf Mainboard und Datenträger einigen sich über die
möglichen Geschwindigkeiten.&lt;/p&gt;

&lt;p&gt;Doch leider liegt hier das Maximum bei 6 GBit/s mit SATA 3, die Vorgänger
SATA 2 und 1 schaffen nur 3 und 1.5 GBit/s, allerdings besteht in der
Regel Kompatibilität zwischen allen dreien.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/ssd-sata-25.jpg&quot; alt=&quot;SSD SATA 2.5&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;msata-direkt-am-mainboard&quot;&gt;mSATA direkt am Mainboard&lt;/h3&gt;

&lt;p&gt;Die 2.5 Zoll SSD Festplatten bestehen zu 2/3 aus Luft, tatsächlich wird nur
ein kleiner Teil des Gehäuses für die Speicherchips benutzt.&lt;br /&gt;
Somit könnte man doch noch kleiner Chips direkt am Mainboard unterbringen;
und genau das erreicht mSATA (mini-SATA).&lt;/p&gt;

&lt;p&gt;Meine Baytrail &lt;a href=&quot;https://de.wikipedia.org/wiki/Intel_Atom&quot;&gt;Intel-Atom&lt;/a&gt; Boards 
aus um das Jahr 2013 hatten solche Slots verbaut und auch im Embedded und 
Industriebereich hat der kleinere Formfaktor seine Vorteile.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/ssd-msata.jpg&quot; alt=&quot;SSD MSATA&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;m2-als-neuer-formfaktor&quot;&gt;M.2 als neuer Formfaktor&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;M.2&lt;/code&gt; definiert einen Form-Faktor, also die Größe einer Steckkarte, damit 
man diese und die Buchsen genau auf diesen Standard abstimmen kann.&lt;br /&gt;
Allerdings können neben Speicherkarten auch andere Geräte wie Modems und WLAN 
oder beliebige PCIe-Karten über das M.2 Format angebunden werden.&lt;/p&gt;

&lt;p&gt;Um was es sich handelt, erkannt man an den Einkerbungen der Buchse bzw. der
Steckkarte.&lt;br /&gt;
Und hier wird es bei dem inzwischen sehr klein gewordenem Steckkontakt mühsam,
denn man erkennt nicht immer mit dem freien Auge, um welches Format es sich 
handelt. Hier muss man stets nachlesen, welche Buchse man hat und welches
Medium dafür erwerben muss.&lt;/p&gt;

&lt;h4 id=&quot;m2-sata-ssds-mit-zwei-einkerbungen&quot;&gt;M.2 SATA SSDs mit zwei Einkerbungen&lt;/h4&gt;

&lt;p&gt;Die älteren und langsameren M.2 SSDs mit SATA Technologie erkennt man an den
zwei Einkerbungen (M-Key und B-Key). Sie schaffen wie SATA-3 etwa 600 MB/s.
In eine Buchse mit 2 Einkerbungen passen also nur SATA SSDs und nicht die
folgenden NVMe-SSDs mit nur einer Einkerbung.&lt;/p&gt;

&lt;p&gt;Umgekehrt kann eine SATA M.2 SSD meist auch in einer NVMe-Buchse betrieben
werden.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/ssd-sata-m2.jpg&quot; alt=&quot;SSD-SATA-M2&quot; /&gt;&lt;/p&gt;

&lt;h4 id=&quot;m2-nvme-ssds-mit-einer-einkerbung&quot;&gt;M.2 NVMe SSDs mit einer Einkerbung&lt;/h4&gt;

&lt;p&gt;Hat eine M.2 SSD nur eine Einkerbung (nur M-Key), handelt es sich um eine
schnellere NVMe SSD (Non-Volatile-Memory-Express) die je nach Modell biss
zu 7000 MB/s Daten umschaufeln kann und damit 10x schneller als SATA M.2 SSDs
sein können.&lt;/p&gt;

&lt;p&gt;Eine NVMe M.2 SSD passt natürlich nicht in eine SATA M.2 Buchse, die für 
2 Kerben vorgesehen ist.&lt;/p&gt;

&lt;h3 id=&quot;adapter-für-sata-und-usb&quot;&gt;Adapter für SATA und USB&lt;/h3&gt;

&lt;p&gt;Da ich ursprünglich nur ein Mainboard hatte, das NVMe SSDs unterstützte 
und ich sonst nur SATA-M2 Adapter gekauft hatte, lief ich in ein Problem beim
Datenbackup nach einem Crash.&lt;/p&gt;

&lt;p&gt;Ich hatte mich nie mit den Details zu M.2 SSDs befasst und dachte immer, dass
die Formate ohnehin alle zueinander kompatibel sind. Doch das gilt eben nicht
für NVMe bei SATA-Adaptern.&lt;/p&gt;

&lt;p&gt;Ich musste mir also einen separaten USB3-NVMe-M2 Adapter besorgen um auch 
solche Speichermedien extern anzapfen zu können.&lt;br /&gt;
Seither liegen in meinem Hardware-Notfallkoffer immer beide Adapter,
einer für M.2-SATA nach SATA oder USB und dann noch einer für M.2-NVMe nach USB3.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/ssd-m2-adapter.jpg&quot; alt=&quot;M2-NVME-SATA USB-Adapter&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Dass es zwei SSD Format gibt, die optisch ziemlich gleich aussehen, finde ich
nach wie vor ungut … aber so ist das eben manchmal.&lt;/p&gt;

&lt;p&gt;Auf lange Sicht werden SATA-M.2-SSDs vermutlich durch NVMe ersetzt werden.
Das führt bereits zu niedrigen Preisen für die älteren Modelle und ist der 
Grund, warum ich mit denen recht gut eingedeckt bin.&lt;/p&gt;

&lt;p&gt;Dass man aber auf der Fläche eines Daumen oder Zeigefingers heute Datenmengen
von mehreren Terabyte unterbringen kann, die mit N-100 MB/s bearbeiten kann,
ist eine Meisterleistung unserer Zeit.&lt;br /&gt;
Kaum zu glauben, dass ich vor 20 Jahren mit sauschweren 3.5 Zoll-Brocken 
hantieren musste, um 2 GB mühsamst ans Mainboard anschließen zu können.&lt;/p&gt;

&lt;p&gt;Früher war eben doch nicht alles besser …&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Marvel&apos;s Secret Invasion</title>
   <link href="https://www.opengate.at/blog/2023/07/secret-invasion/"/>
   <published>2023-07-30T13:00:00+02:00</published>
   <updated>2023-07-30T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2023/07/secret-invasion</id>
   <category term="entertainment" />
   <summary type="text">Nick Fury 
war mal “echt cool”. Aber ihm fehlte es an Hintergrund.
Seinen eigenen Film hat er nie bekommen, doch nun hat ihn Marvel mit einer
6-teiligen Disney+ Serie in den Vordergrund geholt.

Und so habe ich 6 Wochen lang jeden Mittwoch darauf gewartet, 
wie der Erfinder der Avengers sein Stück vom Kuchen in
Secret Invasion abbekommt.
</summary>
   <content type="html">&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Nick_Fury_(Marvel_Cinematic_Universe)&quot;&gt;Nick Fury&lt;/a&gt; 
war mal “echt cool”. Aber ihm fehlte es an Hintergrund.
Seinen eigenen Film hat er nie bekommen, doch nun hat ihn Marvel mit einer
6-teiligen &lt;a href=&quot;https://de.wikipedia.org/wiki/Disney%2B&quot;&gt;Disney+&lt;/a&gt; Serie in den Vordergrund geholt.&lt;/p&gt;

&lt;p&gt;Und so habe ich 6 Wochen lang jeden Mittwoch darauf gewartet, 
wie der Erfinder der Avengers sein Stück vom Kuchen in
&lt;a href=&quot;https://de.wikipedia.org/wiki/Secret_Invasion&quot;&gt;Secret Invasion&lt;/a&gt; abbekommt.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Naja … und … ich weiß nicht.&lt;br /&gt;
Da fängt eine Serie so gut an, und endet dann genau wie 
&lt;a href=&quot;https://de.wikipedia.org/wiki/She-Hulk:_Die_Anw%C3%A4ltin&quot;&gt;She-Hulk&lt;/a&gt; mit 
der Intension ein &lt;code&gt;W-T-F?&lt;/code&gt; auf die Stirn der Zuseher zu ritzen.&lt;/p&gt;

&lt;h3 id=&quot;der-held-ohne-superkraft&quot;&gt;Der Held ohne Superkraft&lt;/h3&gt;

&lt;p&gt;Der Großteil der Marvel-Helden verfügt über eine übermenschliche Kraft, die
er entweder durch Spinnenbiss, ein Wundermittel, kosmische Strahlen, Technik 
oder durch göttliche Abstammung erlangt hat.&lt;/p&gt;

&lt;p&gt;Andere Figuren (die durchaus interessanter sein können) haben sich eine 
übermenschliche Technik antrainiert. Sei es ein perfektes Bogenschießen,
maschinelle Unterstützung oder perfekt athletische Beinarbeit (wobei ich
wieder bei “meiner” &lt;a href=&quot;https://de.wikipedia.org/wiki/Scarlett_Johansson&quot;&gt;Scarlett Johansson&lt;/a&gt;
angekommen wäre).&lt;/p&gt;

&lt;p&gt;Nick Fury hingegen war nichts weiter als ein Ermittler, ein Agent, mit einem
scharfen Verstand eines überlegenen Schachspielers.&lt;br /&gt;
Er brauchte keine Superkräfte, sondern versammelte und überzeugte nur die
richtigen Leute zum richtigen Zeitpunkt für “seine Sache” zu kämpfen.&lt;/p&gt;

&lt;p&gt;Genau das macht ihn eigentlich zum interessantesten 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Marvel_Cinematic_Universe&quot;&gt;MCU&lt;/a&gt; Helden …
nämliche seine “überlegene” Normalität.&lt;/p&gt;

&lt;h3 id=&quot;secret-invasion&quot;&gt;Secret Invasion&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;Da kamen also in den 90ern Aliens auf die Erde, die ein Zuhause suchten.
Nick Fury wollte ihnen helfen … doch bis 2020 passierte nicht wirklich viel.&lt;br /&gt;
Die Lösung der Aliens: Terrorismus und die Erde für sich erobern.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So könnte man den Handlungsbeginn von Secret Invasion kurz zusammenfassen.
Und jeder errät auch den Ausgang:&lt;br /&gt;
Nick Fury wird diese dunklen Pläne vereiteln.&lt;/p&gt;

&lt;p&gt;Die spannende Frage war während der Serie also das &lt;em&gt;“Wie”&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Und hier beginnt das Ganze auch echt gut. Wir sehen einen gealterten
gebrochenen Fury, dem man nicht mehr viel zutraut.
Man merkt, dass erst langsam wieder Leben in seine scheinbar müden
Knochen kommt.&lt;br /&gt;
Wir sehen in Rückblenden, wie Hoffnung geschürt wurde, die an der
Realität zerbrach und sich fast nachvollziehbar in Hass und Ablehnung
auf der Gegenseite wandelte.&lt;/p&gt;

&lt;p&gt;Und ich hatte meinen Spaß mitzuverfolgen, wie hin und her intrigiert
wurde, falsche Freunde enttarnt und Feinde zu Verbündeten wurden.&lt;/p&gt;

&lt;h3 id=&quot;die-verfluchte-letzte-folge&quot;&gt;Die verfluchte letzte Folge&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Vorsicht Spoiler!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Und dann kam der Faustschlag mitten in mein Gesicht, als die 
vorletzte Folge von einer DNA-Mischung aller Superhelden sprach, die
sich in der letzten Folge der Bösewicht einverleibte und quasi zum
stärksten Superhelden aller Zeiten werden wollte.&lt;/p&gt;

&lt;p&gt;W-T-F? Jetzt kann man sich also Superkräfte einfach einimpfen lassen?
Diese Erzählung stört mich derart, dass ich es mir auch bei noch so gutem
Willen einfach nicht schönreden kann.&lt;/p&gt;

&lt;p&gt;Mit solche Stories gleitet Marvel auf das Niveau von DC’s Justice League
hinab. Denn wo dort in den letzten 5 Minuten immer Superman alles 
wegfegt, weil er eben der Stärkste ist, kommt jetzt Marvel’s Avengers-Spritze.
Dann gibt es einen 5 Minuten Boxkampf und “die Gute” gewinnt.&lt;/p&gt;

&lt;p&gt;Für dieses Ende hätten wir nicht 6 Folgen gebraucht; das hätten 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Tom_und_Jerry&quot;&gt;Tom und Jerry&lt;/a&gt; auch in 
5 Minuten vorspielen können.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Es war schön Nick Fury und einige andere Charaktere noch mal in einer 
Serie zu sehen und auch die Darstellung eines gealterten und deplatzierten 
Helden war eigentlich gut angedacht.&lt;/p&gt;

&lt;p&gt;Aber das Ende hat dem Ansehen der Figuren geschadet, und das ist schade.&lt;/p&gt;

&lt;p&gt;Als nächstes werden wir Nick Fury wohl in 
&lt;a href=&quot;https://de.wikipedia.org/wiki/The_Marvels&quot;&gt;The Marvels&lt;/a&gt; erleben dürfen, und 
ich hoffe, dass sich bis dahin der Charakter und sein Umfeld von 
“Secret Invasion” erholt haben werden.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Kurpark Oberlaa</title>
   <link href="https://www.opengate.at/blog/2023/07/kurpark-oberlaa/"/>
   <published>2023-07-29T13:00:00+02:00</published>
   <updated>2023-07-29T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2023/07/kurpark-oberlaa</id>
   <category term="general" />
   <summary type="text">Meine Sommerspaziergänge führen mich jedes Jahr einmal durch den 
Kurpark Oberlaa. 
Es ist jetzt knapp 20 Jahre her, dass ich dieses kleine Idyll am Rande von 
Wien zum ersten Mal betreten habe.

Und immer wieder erfreut es einen, dass es in der grauen Stadt auch solche
grünen Oasen gibt.

</summary>
   <content type="html">&lt;p&gt;Meine Sommerspaziergänge führen mich jedes Jahr einmal durch den 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Kurpark_Oberlaa&quot;&gt;Kurpark Oberlaa&lt;/a&gt;. 
Es ist jetzt knapp 20 Jahre her, dass ich dieses kleine Idyll am Rande von 
Wien zum ersten Mal betreten habe.&lt;/p&gt;

&lt;p&gt;Und immer wieder erfreut es einen, dass es in der grauen Stadt auch solche
grünen Oasen gibt.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Wenn man vom Reumannplatz aus der Laaer-Berg-Straße nach Süden folgt, kommt 
man zwangsläufig am Kurpark Oberlaa vorbei.
Diese 600 km² große Grünfläche bietet allen Besuchern kostenfrei mehrere
Naturbereiche von Teichen, Wiesen, Waldstücken und Gartenanlagen in 
unterschiedlichsten Varianten.&lt;/p&gt;

&lt;p&gt;Es ist also gar nicht notwendig aus der Stadt “raus” zu fahren, wenn man die
Natur genießen willen, sondern man fährt einfach zur südlichen Endstation der
U-Bahn Linie U1, wandert über einen der vielen Pfade und rastet und genießt
die Umgebung auf einer der Bänke.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/kurpark-oberlaa-01.jpg&quot; alt=&quot;Kurpark Oberlaa 01&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Und während in den städtischen Betonbauten im Sommer die Temperaturen klettern, 
spenden die Bäume im Kurpark angenehmen Schatten.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/kurpark-oberlaa-02.jpg&quot; alt=&quot;Kurpark Oberlaa 01&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Bereits am Eingang von der Straße aus bekommt man einen Vorgeschmack auf die
Pflanzenwelt, die einen erwartet.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/kurpark-oberlaa-03.jpg&quot; alt=&quot;Kurpark Oberlaa 01&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Die Hauptwege durch das Areal sind alle asphaltiert und damit auch für 
ältere Menschen und jene mit Gehbehinderungen leicht nutzbar.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/kurpark-oberlaa-04.jpg&quot; alt=&quot;Kurpark Oberlaa 01&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Mehrere Teiche können umrundet werden, und mir ist auch schon der eine
oder andere Fischer aufgefallen, der geduldig seine Angel über das blaue 
Nass hielt.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/kurpark-oberlaa-05.jpg&quot; alt=&quot;Kurpark Oberlaa 01&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Seitenpfade führen zu Beeten mit unterschiedlichsten Blumen und Grünanlagen.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/kurpark-oberlaa-06.jpg&quot; alt=&quot;Kurpark Oberlaa 01&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Einige Wegstrecken sind grün “überdacht” und trennen so schattige Pfade von
sonnigeren Raststätten.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/kurpark-oberlaa-07.jpg&quot; alt=&quot;Kurpark Oberlaa 01&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Um die Sommerhitze überstehen zu können werden einige Bereiche immer wieder
bewässert. So bleiben die Wiesen auch im Hochsommer grün.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/kurpark-oberlaa-08.jpg&quot; alt=&quot;Kurpark Oberlaa 01&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Auch erheben sich immer wieder diverse Kunstwerke aus den Beeten und
Terrassen.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/kurpark-oberlaa-09.jpg&quot; alt=&quot;Kurpark Oberlaa 01&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Sonnenliege nur am Strand? Nein, auch auf den Wiesen des Kurparks sind
verstreut Sonnenliegen aufgestellt um Urlaubsstimmung aufkommen zu lassen.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/kurpark-oberlaa-10.jpg&quot; alt=&quot;Kurpark Oberlaa 01&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Platz ist im Grünen jedenfalls genug, und so kann sich jeder einen
freien Picknickplatz aussuchen, während sich die Kinder nebenan mit 
Ballspielen beschäftigen.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/kurpark-oberlaa-11.jpg&quot; alt=&quot;Kurpark Oberlaa 01&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Bäume spenden fast auf allen Wegen den begehrten Schatten …&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/kurpark-oberlaa-12.jpg&quot; alt=&quot;Kurpark Oberlaa 01&quot; /&gt;&lt;/p&gt;

&lt;p&gt;… und runden die Landschaft um die Teiche ab.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/kurpark-oberlaa-13.jpg&quot; alt=&quot;Kurpark Oberlaa 01&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Wie man sieht, sind die Anlagen nicht nur für das Naturgefühl sondern
auch für das Auge erdacht worden.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/kurpark-oberlaa-14.jpg&quot; alt=&quot;Kurpark Oberlaa 01&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Und Enten fühlen sich in den Teichen sichtlich pudelwohl.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Kurz gesagt: Er ist einfach schön, unser Kurpark.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>X11 mit Motif</title>
   <link href="https://www.opengate.at/blog/2023/07/motif/"/>
   <published>2023-07-23T13:00:00+02:00</published>
   <updated>2023-07-23T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2023/07/motif</id>
   <category term="devel" />
   <summary type="text">Mit GTK+ hatte ich ein portables UI 
Framework gefunden, welches ich sowohl in Windows als auch in Linux zur 
Entwicklung nutzen konnte.

Doch … wenn es um kleine UIs geht, ist dieses Riesenframework schon ein
ziemlicher Overhead.

Und dann fiel mir wieder ein: X11 
hat ja seine 30 Jahre alten X-Toolkits integriert.
</summary>
   <content type="html">&lt;p&gt;Mit &lt;a href=&quot;https://en.wikipedia.org/wiki/GTK&quot;&gt;GTK+&lt;/a&gt; hatte ich ein portables UI 
Framework gefunden, welches ich sowohl in Windows als auch in Linux zur 
Entwicklung nutzen konnte.&lt;/p&gt;

&lt;p&gt;Doch … wenn es um kleine UIs geht, ist dieses Riesenframework schon ein
ziemlicher Overhead.&lt;/p&gt;

&lt;p&gt;Und dann fiel mir wieder ein: &lt;a href=&quot;https://de.wikipedia.org/wiki/X_Window_System&quot;&gt;X11&lt;/a&gt; 
hat ja seine 30 Jahre alten X-Toolkits integriert.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;vorgeschichte&quot;&gt;Vorgeschichte&lt;/h3&gt;

&lt;p&gt;Es war Ende 2007 als ich mich zum ersten Mal mit UIs unter Linux und X11 
auseinandersetzte. Schon damals wollte ich ein Äquivalent zur nativen
WinAPI für UIs haben, die auf jedem System vorhanden sind und keine 
fetten Runtimes brauchten.&lt;/p&gt;

&lt;p&gt;Die üblichen Vertreter GTK und &lt;a href=&quot;https://de.wikipedia.org/wiki/Qt_(Bibliothek)&quot;&gt;QT&lt;/a&gt; 
waren mir damals schon unsympathisch, weil sie viel Eigenaufwand erforderten 
um kompiliert werden zu können und Tools wie 
&lt;a href=&quot;https://de.wikipedia.org/wiki/CMake&quot;&gt;CMake&lt;/a&gt; kannte ich damals noch nicht.&lt;/p&gt;

&lt;p&gt;Hängen geblieben bin ich bei beim X-Toolkit mit seinen &lt;code&gt;Xt*&lt;/code&gt; APIs, welches
die Erstellung von “Widgets” ermöglicht, also Usercontrols wie Buttons,
Labels und andere übliche UI Elemente.&lt;/p&gt;

&lt;p&gt;Schon damals listete Wikipedia &lt;a href=&quot;https://de.wikipedia.org/wiki/X_Athena_Widgets&quot;&gt;Athena&lt;/a&gt;, 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Motif&quot;&gt;Motif&lt;/a&gt; und &lt;code&gt;XView&lt;/code&gt; als klassische
Implementierungen von solchen UI Widgets auf, doch da die letzten beiden
zu dem Zeitpunkt noch nicht Open-Source verträglich waren, versuchte ich
mein Glück mit Athena und seinen &lt;code&gt;Xaw*&lt;/code&gt; APIs.&lt;/p&gt;

&lt;p&gt;Athena’s Widgets sind mit Abstand die altbackensten, schwarz-weiß und mit
teils unbenutzbaren UI Verhalten, wie z.B. dass man nur dann in eine
Textbox schreiben konnte, wenn der Mauszeiger über dieser thronte.
Auch die Scrollbars verdienten ihren Namen nicht.&lt;br /&gt;
Und somit war das UI-Experiment schnell beendet.&lt;/p&gt;

&lt;h3 id=&quot;heute&quot;&gt;Heute&lt;/h3&gt;

&lt;p&gt;Wie gesagt: Ich hätte gerne eine UI Framework, dass möglichst leichtgewichtig
ist und welches man leicht in eigene Projekte integrieren kann. Komplexe
Sachen brauche ich nicht, ich will nur Buttons, Labels und Textboxen für 
primitive UI-Dialoge.&lt;/p&gt;

&lt;p&gt;Und nachdem &lt;code&gt;Motif&lt;/code&gt; gegen 2013 als &lt;a href=&quot;https://de.wikipedia.org/wiki/Open_Source&quot;&gt;Open Source&lt;/a&gt;
Bibliothek neu veröffentlicht wurde und heute in jeder Linux und BSD Distro 
zu finden ist, dachte ich mir:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Implementieren wir doch einfach mal Motif Apps!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;motif&quot;&gt;Motif&lt;/h3&gt;

&lt;p&gt;Bei Motif muss man zwischen den Xt (X-Toolkit) und den Motif Widgets 
unterscheiden. Man erkennt die Toolkit Funktionen am &lt;code&gt;Xt&lt;/code&gt; Prefix, 
während die Motif Funktionen mit &lt;code&gt;Xm&lt;/code&gt; beginnen. Widget-Klassen sind eigentlich
nur String-Konstanten (beginnend mit &lt;code&gt;xm&lt;/code&gt;) und identifizieren das zu ladende
UI Control, bzw. dessen Layout und Verhalten.&lt;/p&gt;

&lt;p&gt;Wie oft in UI Frameworks läuft alles in einer Event-Loop, die Benutzerereignisse
an die Controls (Widgets) weiterleitet.&lt;br /&gt;
Das UI selbst beginnt mit einem Hauptfenster, in dem einer von mehreren 
Layout-Containern als Kind eingefügt wird.&lt;br /&gt;
Innerhalb des Containers werden dann die UI-Controls wie Buttons erzeugt und
der Container übernimmt dann deren Ausrichtung und Positionierung.&lt;/p&gt;

&lt;script src=&quot;/blog/assets/mermaid/mermaid.min.js&quot;&gt;&lt;/script&gt;
&lt;div class=&quot;mermaid&quot;&gt;
flowchart LR
    subgraph XToolkit
      XTLOOP[[Event Loop]]
      SHELL[Application&lt;br /&gt;Main&lt;br /&gt;Window]
    end

    subgraph Motif Widgets
      CONTAINER(Control&lt;br /&gt;Layout&lt;br /&gt;Container)
      CONTROL1([UI Button A])
      CONTROL2([UI Textbox B])
    end

    subgraph User/Logic
      CALLBACK1[[button_pushed&lt;br /&gt;Callback]]
      CALLBACK2[[text_changed&lt;br /&gt;Callback]]
    end

    XTLOOP --- SHELL
    SHELL --- CONTAINER
    CONTAINER --- CONTROL1
    CONTAINER --- CONTROL2

    CONTROL1 --- CALLBACK1
    CONTROL2 --- CALLBACK2
&lt;/div&gt;

&lt;p&gt;An die Widgets können Callbacks angehängt werden, damit ein “Button-Click” zum
Aufruf einer Funktion führt.&lt;/p&gt;

&lt;p&gt;In Code sieht das etwas so aus:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color:#B44;font-weight:bold&quot;&gt;&amp;lt;X11/Intrinsic.h&amp;gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color:#B44;font-weight:bold&quot;&gt;&amp;lt;Xm/Xm.h&amp;gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color:#B44;font-weight:bold&quot;&gt;&amp;lt;Xm/Primitive.h&amp;gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color:#B44;font-weight:bold&quot;&gt;&amp;lt;Xm/BulletinB.h&amp;gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color:#B44;font-weight:bold&quot;&gt;&amp;lt;Xm/PushB.h&amp;gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;static&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt; button_pushed_callback(Widget widget, XtPointer client_data, XtPointer call_data)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;  XtAppContext app = (XtAppContext)client_data;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  XtAppSetExitFlag(app);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;}
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt; create_ui_widgets(XtAppContext app, Display* disp)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;  Widget main_window = XtAppCreateShell(&lt;span style=&quot;color:#069&quot;&gt;NULL&lt;/span&gt;, &lt;span style=&quot;color:#069&quot;&gt;NULL&lt;/span&gt;, applicationShellWidgetClass, disp, &lt;span style=&quot;color:#069&quot;&gt;NULL&lt;/span&gt;, &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;  XtManageChild(main_window);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;  XtRealizeWidget(main_window);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;    
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;  Widget control_container = XtCreateWidget(&lt;span style=&quot;color:#069&quot;&gt;NULL&lt;/span&gt;, xmBulletinBoardWidgetClass, main_window, &lt;span style=&quot;color:#069&quot;&gt;NULL&lt;/span&gt;, &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  XtManageChild(control_container);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n21&quot; name=&quot;n21&quot;&gt;21&lt;/a&gt;&lt;/span&gt;  XtRealizeWidget(control_container);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n22&quot; name=&quot;n22&quot;&gt;22&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n23&quot; name=&quot;n23&quot;&gt;23&lt;/a&gt;&lt;/span&gt;  Widget motif_button = XtCreateWidget(&lt;span style=&quot;color:#069&quot;&gt;NULL&lt;/span&gt;, xmPushButtonWidgetClass, control_container, &lt;span style=&quot;color:#069&quot;&gt;NULL&lt;/span&gt;, &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n24&quot; name=&quot;n24&quot;&gt;24&lt;/a&gt;&lt;/span&gt;  XtManageChild(motif_button);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n25&quot; name=&quot;n25&quot;&gt;25&lt;/a&gt;&lt;/span&gt;  XtRealizeWidget(motif_button);    
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n26&quot; name=&quot;n26&quot;&gt;26&lt;/a&gt;&lt;/span&gt;  XtAddCallback(motif_button, XmNactivateCallback, &amp;amp;button_pushed_callback, (XtPointer)app);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n27&quot; name=&quot;n27&quot;&gt;27&lt;/a&gt;&lt;/span&gt;}
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n28&quot; name=&quot;n28&quot;&gt;28&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n29&quot; name=&quot;n29&quot;&gt;29&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; main(&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; argc, &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt; **argv) 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n30&quot; name=&quot;n30&quot;&gt;30&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n31&quot; name=&quot;n31&quot;&gt;31&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt;* display_name = &lt;span style=&quot;color:#069&quot;&gt;NULL&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n32&quot; name=&quot;n32&quot;&gt;32&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt; my_app_name[] = &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;MyMotifApp&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n33&quot; name=&quot;n33&quot;&gt;33&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt; my_app_class[]= &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;MyMotifClass&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n34&quot; name=&quot;n34&quot;&gt;34&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n35&quot; name=&quot;n35&quot;&gt;35&lt;/a&gt;&lt;/span&gt;  XtToolkitInitialize();
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n36&quot; name=&quot;n36&quot;&gt;36&lt;/a&gt;&lt;/span&gt;  XtAppContext app = XtCreateApplicationContext();
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n37&quot; name=&quot;n37&quot;&gt;37&lt;/a&gt;&lt;/span&gt;  Display* disp = XtOpenDisplay(app, display_name, my_app_name, my_app_class, &lt;span style=&quot;color:#069&quot;&gt;NULL&lt;/span&gt;, &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;, &amp;amp;argc, argv);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n38&quot; name=&quot;n38&quot;&gt;38&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n39&quot; name=&quot;n39&quot;&gt;39&lt;/a&gt;&lt;/span&gt;  create_ui_widgets(app);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n40&quot; name=&quot;n40&quot;&gt;40&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n41&quot; name=&quot;n41&quot;&gt;41&lt;/a&gt;&lt;/span&gt;  XEvent xevt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n42&quot; name=&quot;n42&quot;&gt;42&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;while&lt;/span&gt;(!XtAppGetExitFlag(ctx))
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n43&quot; name=&quot;n43&quot;&gt;43&lt;/a&gt;&lt;/span&gt;  {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n44&quot; name=&quot;n44&quot;&gt;44&lt;/a&gt;&lt;/span&gt;    XtAppNextEvent(app, &amp;amp;xevt);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n45&quot; name=&quot;n45&quot;&gt;45&lt;/a&gt;&lt;/span&gt;    XtDispatchEvent(&amp;amp;xevt);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n46&quot; name=&quot;n46&quot;&gt;46&lt;/a&gt;&lt;/span&gt;  }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n47&quot; name=&quot;n47&quot;&gt;47&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n48&quot; name=&quot;n48&quot;&gt;48&lt;/a&gt;&lt;/span&gt;  XtCloseDisplay(disp);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n49&quot; name=&quot;n49&quot;&gt;49&lt;/a&gt;&lt;/span&gt;  XtDestroyApplicationContext(app);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n50&quot; name=&quot;n50&quot;&gt;50&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n51&quot; name=&quot;n51&quot;&gt;51&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Meine Herausforderung ist es nun, für alle bereits existierenden GATE UI 
Controls eine Entsprechung in den Motif Widgets zu finden. Buttons und Labels
sind wie üblich leicht. Schwieriger wird es dann vermutlich mit Treeviews und 
Listviews werden, die viele Daten verwalten müssen.&lt;/p&gt;

&lt;p&gt;Aber nachdem mir das mit der WinAPI und GTK gelungen ist, ist es nur eine 
Frage der Zeit, bis ich das auch auf Motif portiert haben werden.&lt;/p&gt;

&lt;p&gt;Das Problem ist heute eher die Dokumentation und Beispiele. Die Technik 
stammt aus den 90ern und früher und wird heute in neuen Projekten kaum mehr
genutzt. Kein Wunder also, dass auch die Dokumentation dünner geworden ist.&lt;/p&gt;

&lt;p&gt;In sofern also gut, dass das wieder einmal alles ausgegraben wird.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>WinAPI: Win16</title>
   <link href="https://www.opengate.at/blog/2023/07/win16/"/>
   <published>2023-07-22T13:00:00+02:00</published>
   <updated>2023-07-22T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2023/07/win16</id>
   <category term="devel" />
   <summary type="text">
  Windows ist abwärtskompatibel.
Alte APIs bleiben bestehen, es kommen nur neue dazu.


So heißt es. Also ist Win95 
einfach ein Win3x +
Erweiterungen.
… zumindest glaubte ich das bisher.
</summary>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;Windows ist abwärtskompatibel.
Alte APIs bleiben bestehen, es kommen nur neue dazu.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So heißt es. Also ist &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_95&quot;&gt;Win95&lt;/a&gt; 
einfach ein &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_3.1&quot;&gt;Win3x&lt;/a&gt; +
Erweiterungen.
… zumindest glaubte ich das bisher.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Obwohl mein erstes Windows noch zur 3.x Generation gehörte, habe ich
nur ein bisschen &lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_Basic_Classic&quot;&gt;Visual Basic&lt;/a&gt; 
darauf ausprogrammiert.&lt;br /&gt;
C und C++ programmierte ich erst später und nur gegen das Win32 API.&lt;/p&gt;

&lt;p&gt;Doch mein Glaube war stark, dass ich somit auch “Win16” beherrschen würde,
weil dieses in Win32 aufgegangen ist, quasi nach der Formel:&lt;br /&gt;
&lt;code&gt;Win32&lt;/code&gt; = &lt;code&gt;Win16&lt;/code&gt; + &lt;code&gt;Threads&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Ich hätte gar nicht falscher liegen können, wenn man von einigen wenigen
Details zur Fenstergestaltung absieht.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Watcom&quot;&gt;OpenWATCOM&lt;/a&gt;, “der Compiler” des 20. 
Jahrhunderts kann auch heute noch Win16 Binaries erzeugen.&lt;br /&gt;
Und somit wandert auch diese Plattform langsam ins GATE Projekt&lt;/p&gt;

&lt;h3 id=&quot;andere-apis&quot;&gt;Andere APIs&lt;/h3&gt;

&lt;p&gt;So wie im POSIX Code häufig ein &lt;code&gt;open()&lt;/code&gt; der Anfang von allem ist, so sieht
man im WinAPI Code stets ein &lt;code&gt;CreateFile()&lt;/code&gt;. Doch Win16 hatte eine solche
Funktion nicht, auch kein &lt;code&gt;ReadFile()&lt;/code&gt; oder &lt;code&gt;WriteFile()&lt;/code&gt; und so stand ich
vor der ersten großen Frage:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Soll ich jetzt alle Codestellen per &lt;code&gt;#ifdef WIN16&lt;/code&gt; mit einer zweiten 
Implementierung beglücken, wenn die Win32 Funktion nicht in Win16
verfügbar ist.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;Jein&lt;/em&gt; ist die Antwort.&lt;/p&gt;

&lt;p&gt;Es gibt schon solche Stellen, die vollständig neu geschrieben werden müssen.
Ein Beispiel wären “Prozesse”, die in Win16 nur “Tasks” mit Task-ID waren 
und technisch mit Win32 Prozessen nichts zu tun haben.&lt;/p&gt;

&lt;p&gt;Doch bei häufig genutzten APIs wie beim Dateisystem wählte ich einen anderen
Ansatz: Die Win32 API wird einfach mit Win16 Funktionen emuliert.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Win32&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Win16&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;CreateFile&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;OpenFile&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;ReadFile&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;_lread&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;WriteFile&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;_lwrite&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;CloseHandle&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;_lclose&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;DeleteFile&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;OpenFile(OF_DELETE)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;FindFirstFile&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;opendir&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;SetFilePointer&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;_llseek&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;GetFileSize&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;_llseek&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;und so weiter.&lt;/p&gt;

&lt;p&gt;Dadurch lassen sich dann bereits fertige Codes sofort kompilieren, einzige
Herausforderung ist, dass ich das Verhalten auch ausreichend genau nachbauen 
muss.&lt;/p&gt;

&lt;h3 id=&quot;keine-fehler&quot;&gt;Keine Fehler&lt;/h3&gt;

&lt;p&gt;Viele Win16 APIs haben keine Rückgabewerte, während ihre Win32 Nachfolger
diese sehr wohl nutzen um Erfolg von Misserfolg zu unterscheiden. Hier 
bleibt mir dann doch nur ein &lt;code&gt;#ifdef&lt;/code&gt; um den Rückgabewerte in Win16 zu 
ignorieren.&lt;/p&gt;

&lt;p&gt;Außerdem gab es kein &lt;a href=&quot;https://learn.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-getlasterror&quot;&gt;GetLastError()&lt;/a&gt; 
und &lt;a href=&quot;https://learn.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-setlasterror&quot;&gt;SetLastError()&lt;/a&gt;.&lt;br /&gt;
Zumindest das kann man mit einer globalen Variable selbst leicht nachbauen.&lt;/p&gt;

&lt;h3 id=&quot;keine-dibsection&quot;&gt;Keine DIBSection&lt;/h3&gt;

&lt;p&gt;Interessant ist, wie häufig ich in Win32 DIBSections eingesetzt habe um
dann direkt auf dem Grafikpuffer Pixel nachzubearbeiten.&lt;br /&gt;
Tja, da macht einem Win16 auch einen Strich durch die Rechnung: Man kann
dort nicht selbst einen Puffer allokieren und an eine Bitmap ausleihen.&lt;/p&gt;

&lt;p&gt;Einzige Alternative ist, einen Pixelpuffer zu befüllen und dann an &lt;code&gt;CreateDIBitmap&lt;/code&gt;
zu übergeben. Dann kann man zwar nicht mehr direkt auf die Pixel in der Bitmap
zugreifen, aber man kann zumindest immer wieder neue Bitmaps mit fertigen Bildern 
erstellen.&lt;/p&gt;

&lt;h3 id=&quot;ui-flags&quot;&gt;UI Flags&lt;/h3&gt;

&lt;p&gt;Doch das schlimmste sind fehlende Features bei UI Controls. Das Konzept von
Fenstern, Buttons, Labels und Textfeldern ist von Win16 direkt auf Win32 
übernommen worden. Doch Win32 hat zahlreiche Flags und Details angefügt, die
ich inzwischen aktiv eingesetzt hatte.&lt;/p&gt;

&lt;p&gt;Um jetzt daraus wieder Win16-kompatiblen Code machen zu können, muss ich 
entweder auf einige Features verzichten, oder das Control im Win32 Stil
unter Win16 nachimplementieren.&lt;/p&gt;

&lt;p&gt;Bei erweiterten Controls wie Treeview und Listview ist das ohnehin notwendig,
da es die unter Win16 nicht gab.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Alles in allem ist das zwar eine interessante Erfahrung, aber ich habe
total unterschätzt wie unterschiedlich Win16 von Win32 war und ist.&lt;/p&gt;

&lt;p&gt;Umgekehrt kann man auch sagen, wie sehr ausgereift Win32 im Gegensatz zu Win16
ist, denn hier zeigt sich erst, mit wie wenig seltsamen APIs damals Anfang der 
90er gearbeitet werden musste.&lt;br /&gt;
(Und trotzdem kamen einige große Apps dabei heraus.)&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>DOS Framebuffer</title>
   <link href="https://www.opengate.at/blog/2023/07/dos-framebuffer/"/>
   <published>2023-07-16T13:00:00+02:00</published>
   <updated>2023-07-16T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2023/07/dos-framebuffer</id>
   <category term="devel" />
   <summary type="text">Das Tool DOSBox startet mit Standard 
Einstellungen seine Emulation mit nur wenigen CPU Zyklen, und trotzdem lässt 
sich darin Prince of Persia 
flüssig spielen.

Warum also läuft mein Code so grottig darin?
</summary>
   <content type="html">&lt;p&gt;Das Tool &lt;a href=&quot;https://de.wikipedia.org/wiki/DOSBox&quot;&gt;DOSBox&lt;/a&gt; startet mit Standard 
Einstellungen seine Emulation mit nur wenigen CPU Zyklen, und trotzdem lässt 
sich darin &lt;a href=&quot;https://de.wikipedia.org/wiki/Prince_of_Persia&quot;&gt;Prince of Persia&lt;/a&gt; 
flüssig spielen.&lt;/p&gt;

&lt;p&gt;Warum also läuft mein Code so grottig darin?
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;blockquote&gt;
  &lt;p&gt;Wenn man Code wie ein Anfänger schreibt, dann darf man sich nicht wundern,
wenn die CPU den Code auch wie ein Anfänger ausführt.&lt;br /&gt;
Also schlecht.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In meiner generischen Implementierung für den Zugriff auf Rastergrafiken
werden die Pixel per &lt;code&gt;(x,y)&lt;/code&gt; Koordinaten durchgelaufen um die Farben auf
die einzelnen Pixel zu übertragen.&lt;br /&gt;
Das ist natürlich höchst ineffizient, denn bei jeder Pixel-Operation wird
&lt;code&gt;y&lt;/code&gt; mit der Bildlänge ausmultipliziert und &lt;code&gt;x&lt;/code&gt; addiert um zur richtigen
Speicherstelle zu gelangen.&lt;br /&gt;
Es ist ineffizient, dafür aber generisch und läuft überall.&lt;/p&gt;

&lt;p&gt;Um jetzt aber ordentliche Frame-Raten zu erzielen, habe ich optimierte 
Funktionen geschrieben, um diverse Operationen direkt per Zeigerarithmetik 
ohne lange Rechnungen auszuführen.&lt;/p&gt;

&lt;p&gt;Vergessen hatte ich das aber bei einer nicht ganz unwichtigen Routine:
nämlich &lt;code&gt;clear()&lt;/code&gt;, die da Bild löscht, bzw. mit einer bestimmten
Hintergrundfarbe vollständig übermalt.&lt;/p&gt;

&lt;p&gt;Tja, am Windows PC mit 3 GHz+ fällt der Fehler natürlich nicht auf, denn auch
das langsamste &lt;code&gt;clear&lt;/code&gt; wird dort in Sekundenbruchteilen umgesetzt.&lt;/p&gt;

&lt;p&gt;Startet man das ganze aber im &lt;a href=&quot;https://de.wikipedia.org/wiki/MS-DOS&quot;&gt;DOS&lt;/a&gt; 
Emulator mit den simulierten Geschwindigkeiten
eines &lt;a href=&quot;https://de.wikipedia.org/wiki/Intel_80286&quot;&gt;80286&lt;/a&gt; / 80386 dauert es 
plötzlich mehrere Sekunden, bis der Schirm “frei”
wird, wenn der Bildpuffer mit der ineffizienten Codevariante gelöscht wird.&lt;/p&gt;

&lt;h3 id=&quot;beste-lösung-memset&quot;&gt;Beste Lösung: memset()&lt;/h3&gt;

&lt;p&gt;Ich änderte also die Löschroutine von einem&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt; clear_image(&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;unsigned&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt; back_color) {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;for&lt;/span&gt;(&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; y = &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;; y &amp;lt; height; ++y) {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;for&lt;/span&gt;(&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; x = &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;; x &amp;lt; width; ++x) {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;      set_pixel(x, y, back_color);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;    }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;  }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;in etwa in ein:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt; clear_image(&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;unsigned&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt; back_color) {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;unsigned&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt;* pixel_ptr = get_pixel_ptr(&lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;, &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  size_t length = width * height;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  memset(pixel_ptr, back_color, length);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;und schon war “das Spiel” 10 mal schneller.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Vor 25 Jahren waren solche Optimierungen für mich ein absolutes Muss
und auch ein riesigen Spaß bei der Implementierung.&lt;br /&gt;
Ich bin heute fast etwas entsetzt, dass mir so eine generische Routine 
“durchgerutscht” ist, und ich es nicht sofort bemerkt hatte.&lt;/p&gt;

&lt;p&gt;In diesem Sinne wieder mal “ein Hoch auf DOS” und den Emulator &lt;code&gt;DOSBox&lt;/code&gt;.&lt;br /&gt;
Dort lernt man nämlich wirklich gutes Ressourcenmanagement …&lt;br /&gt;
… weil man nur so wenig hat.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>CONAN 2</title>
   <link href="https://www.opengate.at/blog/2023/07/conan2/"/>
   <published>2023-07-15T13:00:00+02:00</published>
   <updated>2023-07-15T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2023/07/conan2</id>
   <category term="software" />
   <summary type="text">Das Buildsystem CONAN 
hatte einige Fehlerchen in seinem Konzept.
Doch schon seit Jahren läuft parallel die Entwicklung von CONAN 2.
Und dieses Projekt wälzt jetzt quasi alles um.

</summary>
   <content type="html">&lt;p&gt;Das Buildsystem &lt;a href=&quot;https://de.wikipedia.org/wiki/Conan_(Software)&quot;&gt;CONAN&lt;/a&gt; 
hatte einige Fehlerchen in seinem Konzept.
Doch schon seit Jahren läuft parallel die Entwicklung von CONAN 2.
Und dieses Projekt wälzt jetzt quasi alles um.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;vorgeschichte&quot;&gt;Vorgeschichte&lt;/h3&gt;

&lt;p&gt;Ich wurde vor 4 Jahren eigentlich durch ein Migrationsprojekt in der Firma auf
CONAN aufmerksam. Ein bestehendes &lt;a href=&quot;https://de.wikipedia.org/wiki/CMake&quot;&gt;CMake&lt;/a&gt; 
Projekt sollte in CONAN Packages aufgeteilt werden, damit diese versioniert im
dortigen &lt;code&gt;jfrog&lt;/code&gt; Repository abgelegt werden können.&lt;/p&gt;

&lt;p&gt;Der Vorteil von CONAN liegt vor allem im Dependency-Management, wenn es um die
Bereitstellung aller notwendigen Drittkomponenten geht.&lt;/p&gt;

&lt;p&gt;Niemand befasste sich damals mit den unterschiedlichen “Generatoren” innerhalb
von CONAN v1, sondern man nahm den offensichtlich passenden, nämlich den 
&lt;code&gt;cmake&lt;/code&gt; Generator.&lt;/p&gt;

&lt;p&gt;Dieser erzeugt aus den aufgelösten Abhängigkeiten eine cmake-include Datei,
welche vom Projekt &lt;code&gt;CMakeLists.txt&lt;/code&gt; inkludiert wird. Und alle Details der
Abhängigkeiten liegen im Form von CMake Variablen vor, die das Projekt nun
integrieren kann, also z.B mit:&lt;/p&gt;

&lt;div class=&quot;language-cmake highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;include_directories(${CONAN_INCLUDE_DIRS})
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;target_link_libraries(${PROJECT_NAME} ${CONAN_LIBS})
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Daraus ergibt sich leider das Problem, dass diese “magischen” CONAN-CMake
Variablen dann nur noch innerhalb einer von CONAN erstellten Umgebung
korrekt funktionieren.&lt;br /&gt;
CMake hingegen würde normalerweise ohne CONAN per &lt;code&gt;find_package(dependency)&lt;/code&gt; 
Abhängigkeiten suchen …&lt;/p&gt;

&lt;p&gt;Und so wurde eine Entscheidung getroffen:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Der CMake-Generator aus CONAN v1.x wurde in CONAN v2 entfernt.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;migration-nach-conan-v2&quot;&gt;Migration nach CONAN v2&lt;/h3&gt;

&lt;h4 id=&quot;neue-generatoren&quot;&gt;Neue Generatoren&lt;/h4&gt;

&lt;p&gt;Anstatt also eine zirkuläre Abhängigkeit zwischen CONAN und CMake zu erzeugen,
arbeitet CONAN v2 also “Zulieferer” für CMake.&lt;/p&gt;

&lt;p&gt;Der &lt;code&gt;CMakeDeps&lt;/code&gt; Generator erzeugt nun alle erforderlichen &lt;code&gt;.cmake&lt;/code&gt; Dateien,
die per &lt;code&gt;find_package&lt;/code&gt; dann die Abhängigkeiten im korrekten CMake-Stil in ein
Projekt integrieren. Man nutzt also keine CONAN-CMake-Variablen, sondern schreibt
die &lt;code&gt;CMakeLists.txt&lt;/code&gt; so, als ob CONAN nicht involviert wäre.&lt;br /&gt;
Der &lt;code&gt;CMakeDeps&lt;/code&gt; Generator aus v2 ähnelt sehr dem &lt;code&gt;cmake_find_package&lt;/code&gt; Generator
aus v1.&lt;/p&gt;

&lt;p&gt;Der &lt;code&gt;CMakeToolchain&lt;/code&gt; generator hingegen erzeugt eine Toolchain-Datei, die 
notwendige Informationen über den zu nutzenden Compiler und die Zielplattform
enthält. Man startet also CMake mit dem Verweis zu Toolchain-Datei um den
CMake-Build einzurichten. Auch hier haben wir keine magischen Variablen mehr
im Hintergrund.&lt;/p&gt;

&lt;p&gt;Diese beiden neuen Generatoren sind also der Nachfolger des abgekündigten
v1 cmake-Generators.&lt;br /&gt;
Das wäre ja alles super, wenn es nicht bedeuten würde, dass jedes Projekt
und vor allem alle CMake-Dateien jetzt umgeschrieben werden müssen.&lt;/p&gt;

&lt;h4 id=&quot;änderungen-in-conanfilepy&quot;&gt;Änderungen in conanfile.py&lt;/h4&gt;

&lt;p&gt;Eine weitere gravierende Änderung ist, dass CONAN’s Python Framework ebenso
geändert wurde. Befanden sich bisher alle Klassen und Hilfswerkzeuge im 
Python Modul &lt;code&gt;conans&lt;/code&gt;, so ist man jetzt zum Namen &lt;code&gt;conan&lt;/code&gt; zurückgekehrt.
Aus&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;from&lt;/span&gt; &lt;span style=&quot;color:#B44;font-weight:bold&quot;&gt;conans&lt;/span&gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;import&lt;/span&gt; &lt;span style=&quot;color:#B44;font-weight:bold&quot;&gt;ConanFile&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;wird&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;from&lt;/span&gt; &lt;span style=&quot;color:#B44;font-weight:bold&quot;&gt;conan&lt;/span&gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;import&lt;/span&gt; &lt;span style=&quot;color:#B44;font-weight:bold&quot;&gt;ConanFile&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Auch andere neue Methoden in einer Conan Klasse wurden geändert.
So werden Generatoren nun in der neuen Method &lt;code&gt;generate()&lt;/code&gt; geladen und angewendet
und die &lt;code&gt;layout()&lt;/code&gt; Methode gestattet Änderungen von Attributen, wo Pfade für
Quellcodes und Ausgabedateien hinzeigen sollen.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;imports()&lt;/code&gt; wurde vollständig entfernt, an dessen Stelle treten die neue 
“Deployer”, mit denen Dateien aus Abhängigkeiten extrahiert werden können.
Damit ändert sich auch die Funktion der bestehenden &lt;code&gt;deploy()&lt;/code&gt; Methode, die
nun mit dem eingesetzten Deployer zusammenspielen muss.&lt;/p&gt;

&lt;p&gt;… und vieles mehr.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;CONAN v2 macht technisch vieles richtig. Es gestattet einem Projekt vor 
allem nach einer einmaligen Konfiguration durch CONAN, selbständig zu
laufen. In v1 waren die engen internen Verflechtungen zwischen CONAN und
CMake häufig die Ursache von Problemen, die damit behoben sein sollten.&lt;/p&gt;

&lt;p&gt;Doch leider macht dieses Neudesign die Migration von großen Projekten mehr
als schwierig.&lt;/p&gt;

&lt;p&gt;Ich bin gespannt, wie wir jetzt in der Firma mit dem Thema umgehen.
Es steht jedenfalls fest, dass eine Migration auch viele Vorteile und 
vor allem Zukunftssicherheit bringen wird.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>C++ Result T, E</title>
   <link href="https://www.opengate.at/blog/2023/07/results/"/>
   <published>2023-07-09T13:00:00+02:00</published>
   <updated>2023-07-09T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2023/07/results</id>
   <category term="devel" />
   <summary type="text">Es gibt da diese eine Sache, die von Rust und ZigLang herüberzieht, die
mir keine Ruhe mehr lässt: Nämlich die Rückgabe von Ergebnissen und 
Fehlern in einer eigenen Datenstruktur ohne 
Exceptions.

Tja … und da C++23 mit std::expected einfach noch zu weit weg ist,
habe ich kurzerhand Result&amp;lt;T, E&amp;gt; in mein Framework aufgenommen.
</summary>
   <content type="html">&lt;p&gt;Es gibt da diese eine Sache, die von Rust und ZigLang herüberzieht, die
mir keine Ruhe mehr lässt: Nämlich die Rückgabe von Ergebnissen und 
Fehlern in einer eigenen Datenstruktur ohne 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Ausnahmebehandlung&quot;&gt;Exceptions&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Tja … und da C++23 mit &lt;code&gt;std::expected&lt;/code&gt; einfach noch zu weit weg ist,
habe ich kurzerhand &lt;code&gt;Result&amp;lt;T, E&amp;gt;&lt;/code&gt; in mein Framework aufgenommen.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Das Problem mit C++ Exceptions ist nicht das Konzept, sondern dessen
Implementierungen in &lt;a href=&quot;https://de.wikipedia.org/wiki/GNU_Compiler_Collection&quot;&gt;GCC&lt;/a&gt; 
und &lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_C%2B%2B&quot;&gt;MSVC&lt;/a&gt;, die immer nur 
eine Ausprägung zulassen. Man könnte Exception auf unterschiedliche Weisen 
in Binärcode abbilden, doch um modul-übergreifend kompatibel zu sein, muss 
man bei einer Variante bleiben.&lt;/p&gt;

&lt;p&gt;Und somit verhindern C++ Exceptions weiter, dass ich “lesbaren” Code
für EFI-Applications schreiben kann, weil ich nur reine C Routinen
dort verarbeiten kann.&lt;/p&gt;

&lt;p&gt;Andere (EFI-) Projekte haben das auch durchgemacht und propagieren C++ 
ohne Exceptions und &lt;code&gt;RTTI&lt;/code&gt;, womit sie erfolgreich sind.&lt;br /&gt;
Doch wie werden dort Fehler behandelt?&lt;/p&gt;

&lt;h3 id=&quot;return-value-codes&quot;&gt;Return-value Codes&lt;/h3&gt;

&lt;p&gt;Tja, man brauch Return-Typen, die sowohl Fehler als auch Erfolgsresultate
erhalten können. Rust und ZIG tragen dieses Konzept in der Kernsprache und
können es dort (hoffentlich) gut optimieren.&lt;/p&gt;

&lt;p&gt;In C++ kann man natürlich ein Template schreiben, dass wie ein &lt;code&gt;std::variant&lt;/code&gt;
einen von zwei möglichen Typen enthalten kann.&lt;br /&gt;
Ein solcher &lt;code&gt;std::expected&amp;lt;succes_type, error_type&amp;gt;&lt;/code&gt; Typ wird entweder mit
dem einen oder anderen Typen konstruiert und gibt ihn so gekapselt an den
Aufrufer zurück.&lt;/p&gt;

&lt;p&gt;Dieser kann dann aus-if-en, ob er einen Fehler oder einen Erfolg erhalten hat.&lt;/p&gt;

&lt;p&gt;Ein Code sagt mehr als 1000 Worte:&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;struct&lt;/span&gt; division_error {};
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; devide_classic(&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; a, &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; b) {
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt;(b == &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;) {
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;throw&lt;/span&gt; division_error();
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  }
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; a / b;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;}
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt; do_devide_classic() {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;try&lt;/span&gt; {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; result = devide_classic(&lt;span style=&quot;color:#00D&quot;&gt;4&lt;/span&gt;, &lt;span style=&quot;color:#00D&quot;&gt;2&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;    std::cout &amp;lt;&amp;lt; &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Result=&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &amp;lt;&amp;lt; result &amp;lt;&amp;lt; std::endl; 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;  }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;catch&lt;/span&gt;(devision_error &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt;&amp;amp;) {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;    std::cout &amp;lt;&amp;lt; &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Error&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &amp;lt;&amp;lt; std::endl;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;  }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;}
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n21&quot; name=&quot;n21&quot;&gt;21&lt;/a&gt;&lt;/span&gt;std::expected&amp;lt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt;, division_error&amp;gt; devide_new(&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; a, &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; b) {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n22&quot; name=&quot;n22&quot;&gt;22&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt;(b == &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;) {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n23&quot; name=&quot;n23&quot;&gt;23&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; division_error();
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n24&quot; name=&quot;n24&quot;&gt;24&lt;/a&gt;&lt;/span&gt;  }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n25&quot; name=&quot;n25&quot;&gt;25&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; a / b;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n26&quot; name=&quot;n26&quot;&gt;26&lt;/a&gt;&lt;/span&gt;}
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n27&quot; name=&quot;n27&quot;&gt;27&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n28&quot; name=&quot;n28&quot;&gt;28&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt; do_devide_new() {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n29&quot; name=&quot;n29&quot;&gt;29&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;auto&lt;/span&gt; result = devide_new(&lt;span style=&quot;color:#00D&quot;&gt;4&lt;/span&gt;, &lt;span style=&quot;color:#00D&quot;&gt;2&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n30&quot; name=&quot;n30&quot;&gt;30&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt;(result) {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n31&quot; name=&quot;n31&quot;&gt;31&lt;/a&gt;&lt;/span&gt;    std::cout &amp;lt;&amp;lt; &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Result=&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &amp;lt;&amp;lt; *result &amp;lt;&amp;lt; std::endl; 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n32&quot; name=&quot;n32&quot;&gt;32&lt;/a&gt;&lt;/span&gt;  }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n33&quot; name=&quot;n33&quot;&gt;33&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;else&lt;/span&gt; {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n34&quot; name=&quot;n34&quot;&gt;34&lt;/a&gt;&lt;/span&gt;    std::cout &amp;lt;&amp;lt; &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Error&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &amp;lt;&amp;lt; std::endl;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n35&quot; name=&quot;n35&quot;&gt;35&lt;/a&gt;&lt;/span&gt;  }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n36&quot; name=&quot;n36&quot;&gt;36&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h3 id=&quot;umsetzung-im-gate-projekt&quot;&gt;Umsetzung im GATE Projekt&lt;/h3&gt;

&lt;p&gt;Eigentlich sind Exception ein zentraler Bestandteil der C++ Implementierung 
des GATE Projektes. Ich kann jetzt nicht auf ein anderes Error-Modell umsteigen
ohne alles neu schreiben zu müssen.&lt;/p&gt;

&lt;p&gt;Allerdings möchte ich schrittweise die bestehenden C++ Klassen erweitern.
Neben den normalen Methoden mit Exception-Support, soll es alternative
Funktionen mit dem Präfix &lt;code&gt;try&lt;/code&gt; geben die ein &lt;code&gt;gate::Result&amp;lt;T, E&amp;gt;&lt;/code&gt; zurückliefern
und eben keine Exceptions auslösen.&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;Foo&lt;/span&gt; {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;public&lt;/span&gt;:
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt;         doSomething();
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  Result&amp;lt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt;&amp;gt; tryDoSomething() &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;noexcept&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;};
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Meine Hoffnung liegt beim C++ Optimizer, der die als statische Bibliotheken
erzeugten C++ Klassen scannt und dann nur die Methoden übersetzt, die 
tatsächlich benutzt werden.&lt;/p&gt;

&lt;p&gt;So kann man Apps schreiben, die nur die Exception-freien C++ Methoden nutzen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;Andere Länder - andere Sitten.&lt;br /&gt;
Andere Sprachen - andere Fehlerbehandlungen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Dieser Ansatz ist ungewöhnlich und ich bin mir noch nicht sicher, was ich
am Ende davon halten soll. Trotzdem denke ich, dass Exception-frei Apps
eine Existenzberechtigung haben und somit werde ich mal sehen, wo mich
dieser Weg hinführt.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Szenen, die das Leben schreibt</title>
   <link href="https://www.opengate.at/blog/2023/07/innkeeper/"/>
   <published>2023-07-08T13:00:00+02:00</published>
   <updated>2023-07-08T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2023/07/innkeeper</id>
   <category term="general" />
   <summary type="text">Ich bin ja keiner von diesen geselligen Leuten, die abends mit der Gruppe
in ‘ner Kneipe sitzen und saufen. Wenn 10+ Personen kreuz und quer 
quasseln, nervt mich das eher.

Aber ein gemütliches Abendessen mit ein paar wenigen Freunden oder Kollegen
kann schon sehr nett sein.

Und genau an solchen Orten erlebt man dann die lustigsten Dinge.
</summary>
   <content type="html">&lt;p&gt;Ich bin ja keiner von diesen geselligen Leuten, die abends mit der Gruppe
in ‘ner Kneipe sitzen und saufen. Wenn 10+ Personen kreuz und quer 
quasseln, nervt mich das eher.&lt;/p&gt;

&lt;p&gt;Aber ein gemütliches Abendessen mit ein paar wenigen Freunden oder Kollegen
kann schon sehr nett sein.&lt;/p&gt;

&lt;p&gt;Und genau an solchen Orten erlebt man dann die lustigsten Dinge.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Im Sommer läuft die Wiener Gastronomie auf Hochtouren, jeder Hof und 
jeder Gehsteig wird mit Tischen und Bänken zugepflastert.&lt;/p&gt;

&lt;p&gt;Man denkt, dass im 21. Jahrhundert die Klischees der Vergangenheit 
und die eigenartigen Figuren der Wiener Straßen verschwunden sind, 
und alles nur noch generisch pseudo-professionelle Bedienung ist.&lt;/p&gt;

&lt;p&gt;Doch nein, sie sind nicht auszurotten und dafür bin ich dankbar.
In 3 Stunden in einem Gasthof konnte ich mehr Sketches für eine
Comedy-Show sammeln als im mehrjährigen Studium des Programms des
&lt;a href=&quot;https://simpl.at/&quot;&gt;Kabarett Simpl&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;der-schwule-kellner&quot;&gt;Der schwule Kellner&lt;/h3&gt;

&lt;p&gt;Ich dachte erst: &lt;em&gt;Der spielt das doch nur&lt;/em&gt;.
Denn ich sah vor mir ein Bild von Winnitouch aus 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Der_Schuh_des_Manitu&quot;&gt;Der Schuh des Manitu&lt;/a&gt;,
doch das war es nicht ganz. Die Bewegungen waren nicht so plump hopsig, aber
hatten trotzdem immer einen Hauch von Balletttanz mit einer Brise 
Aufmüpfigkeit unterfüttert.&lt;/p&gt;

&lt;p&gt;Die beste Szene war ohnehin gleich am Anfang nach der Bestellung als sein 
Smartphone bimmelte und er genervt meinte:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Huch, das ist wieder der Chef von der SPÖ.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Dann hob er ab und trillerte ein so typisches “Haaaaaallooo” in das Mikro,
wie ich es nur von &lt;a href=&quot;https://de.wikipedia.org/wiki/Hape_Kerkeling&quot;&gt;Hape Kerkeling&lt;/a&gt;
kenne.&lt;/p&gt;

&lt;p&gt;Am schlimmsten war, das wir im Unklaren blieben, ob er mit dem SPÖ Chef
jetzt Ludwig, Babler oder Doskozil gemeint hat.&lt;/p&gt;

&lt;p&gt;Aber auch weitere Gespräche, vor allem bei seiner Alkoholempfehlung waren
wie aus dem Bilderbuch.&lt;/p&gt;

&lt;h3 id=&quot;der-obdachlose&quot;&gt;Der Obdachlose?&lt;/h3&gt;

&lt;p&gt;Wenn sich jemand plötzlich selbstbewusst an den Tisch setzt und mitdiskutiert,
bin ich erst mal verwirrt.&lt;br /&gt;
Ich gehe dann meine optische Datenbank durch und stelle fest:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Etwas dicklich, Hipsterbart, oben vier Zähne, unten Drei und
schnauzt im Vorbeigehen immer wieder die anderen Kellner an.
… hmm, der will hier einfach mitschmarotzen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Er redet stets von “seinen Köchen” und wie schlecht die Qualität in dem Laden
geworden sein, was er auf die Inflation, die Politik und den Preisdruck in der
Lebensmittelindustrie zurückführt.&lt;br /&gt;
Mit der Zeit denke ich: Naja, vielleicht ist der hier sogar angestellt um die
Leute zu unterhalten, denn er schiebt Kommentare, wie ich sie früher nur von
&lt;a href=&quot;https://de.wikipedia.org/wiki/Hermes_Phettberg&quot;&gt;Hermes Phettberg&lt;/a&gt; kannte.&lt;/p&gt;

&lt;p&gt;Als ich nach dem Abendessen nachfragte, stellte sich heraus, es handelte sich
um einen der Chefköche des Restaurants, der nur gerade frei hatte.&lt;br /&gt;
Alter Schwede … der hat unser Essen gekocht … und das arge war, es war
unglaublich gut.&lt;/p&gt;

&lt;h3 id=&quot;der-nachbar&quot;&gt;Der Nachbar&lt;/h3&gt;

&lt;p&gt;Wochentags sind sie am häufigsten am Abend beim Wirt: Die Einzelpersonen.
Sie sitzen alleine an den Tischen jeweils links und rechts von Pärchen und
Gruppen umgeben.&lt;br /&gt;
Zuerst nehmen sie Witterung auf, blicken zaghaft in die Richtung eines Tisches
und schnappen ein paar Worte auf. Sind die richtigen Passwörter gefallen, 
werden die Tischgäste mit den Augen fixiert und wie eine Gazellenherde 
beobachtet.&lt;/p&gt;

&lt;p&gt;Nun ist es nur noch eine Frage der Zeit bis der Einzelkämpfer ins Gespräch
einfällt:&lt;br /&gt;
Das beste Album von 1985, das letzte Tor beim gestrigen Spiel … schon 
fliegt das erste Argument und der Dialog am Nachbartisch wird zum Trialog
aufgestockt.&lt;/p&gt;

&lt;p&gt;Der Wortwechsel dauert dann wie ein kurzer kräftiger Regen, verschwindet
dann aber genau so schnell, wie er begonnen hat. Denn der Jäger bereitet
sich schon auf den Tisch auf der anderen Seite vor.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;Weitere Details erfahren Sie von ihrem Wirt!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Es ist schon verrückt, welche Personen man ungeplant in einem Gasthof 
auffindet, und jede einzelne kann bereichernd wirken.
Entweder durch ihre lockere (schwule) Art, durch ihre scheinbar 
kümmerliches Auftreten oder durch ihre Direktheit.&lt;/p&gt;

&lt;p&gt;Diesen Charm haben McDonalds und Burgerking noch nie gehabt und leider auch 
ein Stück weit vertrieben. Doch an den richtigen Stellen blüht der alte
Wiener Schmäh weiter auf und da kann freilich auch jeder Heurige am Land 
mithalten.&lt;/p&gt;

&lt;p&gt;Ich werde zwar nie zum Kneipengeher werden und nie mit einem Wirt befreundet 
sein, aber von Zeit zu Zeit genieße ich ein solches Spektakel neben einem 
guten Essen sehr. Und offen gesagt ist das auch günstiger. Für meine 20 bis 
40 Euro bekomme ich je nach Ausstattung ein ordentliches Abendessen und ein 
improvisiertes Liveprogramm dazu. Im Theatersaal mag die Unterhaltung sicher
auch stimmen, doch da kommt man mit so wenig Geld nicht hinein.&lt;/p&gt;

&lt;p&gt;Hinweis: Und wer gerne weitere Live-Reality-Dokus sehen will, der nimmt den 
Platz zwischen Küche und Toilette. Dort geht sprichwörtlich alles vorbei, was 
man gerade noch so verdauen kann.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Haiku OS als Plattform</title>
   <link href="https://www.opengate.at/blog/2023/07/haiku-os/"/>
   <published>2023-07-02T13:00:00+02:00</published>
   <updated>2023-07-02T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2023/07/haiku-os</id>
   <category term="projects" />
   <summary type="text">Ein neues Mitglied wird provisorisch in die Familie aufgenommen:
Haiku, die 
OpenSource-Variante des früheren BeOS 
Betriebssystems.

Das GATE Projekt wird nun um einen Platform-Support-Layer für
BeOS erweitert.

</summary>
   <content type="html">&lt;p&gt;Ein neues Mitglied wird provisorisch in die Familie aufgenommen:&lt;br /&gt;
&lt;a href=&quot;https://de.wikipedia.org/wiki/Haiku_(Betriebssystem)&quot;&gt;Haiku&lt;/a&gt;, die 
OpenSource-Variante des früheren &lt;a href=&quot;https://de.wikipedia.org/wiki/BeOS&quot;&gt;BeOS&lt;/a&gt; 
Betriebssystems.&lt;/p&gt;

&lt;p&gt;Das GATE Projekt wird nun um einen Platform-Support-Layer für
BeOS erweitert.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;kompilieren-für-haikubeos&quot;&gt;Kompilieren für Haiku/BeOS&lt;/h3&gt;

&lt;p&gt;BeOS und Haiku basieren (zumindest in der 32-bit Version) auf 
&lt;a href=&quot;https://de.wikipedia.org/wiki/GNU_Compiler_Collection&quot;&gt;GCC&lt;/a&gt; Kompilaten.
Von daher ist die Toolchain dem Linux Build im GATE Projekt ziemlich ähnlich …&lt;br /&gt;
… dachte ich.&lt;/p&gt;

&lt;p&gt;Und tatsächlich stimmt das auch, denn unter einem frisch installierten Haiku
lässt sich der Build-Prozess mit &lt;code&gt;cmake&lt;/code&gt; und &lt;code&gt;make&lt;/code&gt; ganz regulär starten.&lt;/p&gt;

&lt;p&gt;Im ersten Test erstellte ich so Konsolenprogramme, die unter Haiku ausgeführt
werden konnten.&lt;/p&gt;

&lt;p&gt;Alternativ werden auch &lt;a href=&quot;https://de.wikipedia.org/wiki/Docker_(Software)&quot;&gt;Docker&lt;/a&gt;
Images für Linux angeboten, in denen ein Cross-Compiler für Haiku enthalten ist.&lt;br /&gt;
Hier bedurfte es einer CMake-Toolchain Datei um die nötigen Pfade zu setzen.
Der Build klappte zwar, doch die Binärdateien waren im Anschluss nicht in
Haiku ausführbar.&lt;/p&gt;

&lt;p&gt;Das wirft mich jetzt etwas zurück, da die Docker-Entwicklung effizient 
abgelaufen wäre. So muss ich in der VM mit UIs arbeiten, die sich anders 
verhalten als gewohnt, was leider immer Zeit kostet.&lt;/p&gt;

&lt;p&gt;Aber hey … wir stehen noch ganz am Anfang … das wird schon noch werden.&lt;/p&gt;

&lt;h3 id=&quot;die-kernel-api&quot;&gt;Die Kernel API&lt;/h3&gt;

&lt;p&gt;Da das GATE Projekt direkt mit dem OS reden soll, müssen einige GATE-APIs
für Prozesse, Threads, Atomics, Zeit und Dateien neu implementiert werden.&lt;/p&gt;

&lt;p&gt;Die BeOS APIs basieren großteils auf C++ Klassen, was im GATE Projekt mit 
meinen C-Vorgaben kollidieren würde. Doch die Kernel-Schnittstellen für die 
genannten Basisdienste sind zum Glück reine &lt;code&gt;extern C&lt;/code&gt; Funktionen und können
somit direkt aufgerufen werden:&lt;/p&gt;

&lt;p&gt;Bisher kam ich mit folgenden BeOS-spezifischen Headern in Berührung:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color:#B44;font-weight:bold&quot;&gt;&amp;lt;kernel/OS.h&amp;gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color:#B44;font-weight:bold&quot;&gt;&amp;lt;support/SupportDefs.h&amp;gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color:#B44;font-weight:bold&quot;&gt;&amp;lt;support/TLS.h&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Interessant finde ich, wie “einfach” die Schnittstellen gehalten sind.
Natürlich fehlen auch einige Konstrukte, die ich aus den POSIX-Threads
kenne, doch diese werden sich alle mit dem bestehenden Grundstock 
nachbilden lassen.&lt;/p&gt;

&lt;p&gt;Beschrieben ist alles im &lt;a href=&quot;https://www.haiku-os.org/legacy-docs/bebook/TheKernelKit_Overview.html&quot;&gt;Be Book - Kernel Kit&lt;/a&gt;&lt;/p&gt;

&lt;h3 id=&quot;offene-frage-c&quot;&gt;Offene Frage: C++&lt;/h3&gt;

&lt;p&gt;Sobald es zu den höheren Funktionen wie IPC oder UIs kommt, ist 
C++ zwingend erforderlich. Hier käme ich dann in die ungewöhnliche
Situation, dass ich einen C-Wrapper um die C++ Klassen schreiben
müsste, um sie in die C Bibliotheken integrieren zu können.&lt;br /&gt;
Und am Ende würde der GATE C++ Layer wieder C++ daraus machen.&lt;/p&gt;

&lt;p&gt;Das ist natürlich reiner Overhead, aber vorerst sehe ich keine
Alternative … doch wer weiß, was ich noch alles von dem
neuen alten OS lernen kann.&lt;/p&gt;

&lt;p&gt;Es wird allerdings noch einiges an Zeit vergehen, bis ich an diese
Decke stoßen werde.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;BeOS/Haiku Interna zu lernen mag mancher als Zeitverschwendung abtun.&lt;br /&gt;
Ich sehe es anders.&lt;br /&gt;
Jede neue Plattform hat ihre Eigenheiten, die in Ihrer Umgebung absolut
legitim sind. Nur durch das “Erleben” aller Facetten lässt sich Code so
erarbeiten, dass er wirklich universell einsetzbar wird.&lt;/p&gt;

&lt;p&gt;So wie ich von Windows gutes und schlechtes API-Design erlernte,&lt;br /&gt;
von Linux gutes Streaming und schlechtes Service-Management,&lt;br /&gt;
und von DOS enge Limits und direkte Zugriffe,&lt;br /&gt;
so erwarte ich mir auch von BeOS/Haiku eine neue Sicht auf die Welt,
aus der ich Gutes übernehmen und Schlechtes umgehen kann.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Services für Win9x</title>
   <link href="https://www.opengate.at/blog/2023/07/win9x-service/"/>
   <published>2023-07-01T13:00:00+02:00</published>
   <updated>2023-07-01T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2023/07/win9x-service</id>
   <category term="devel" />
   <summary type="text">Während der Windows 98 
und ME Support im Jahr 2003 ablief, hatte ich noch 2008 den Auftrag, Software 
so zu schreiben, dass sie unter Windows 9x ausführbar ist.

Dabei ging es “nur” um normale UIs.

Dienste wie unter NT 
gab es nicht … oder vielleicht doch …?
</summary>
   <content type="html">&lt;p&gt;Während der &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_98&quot;&gt;Windows 98&lt;/a&gt; 
und ME Support im Jahr 2003 ablief, hatte ich noch 2008 den Auftrag, Software 
so zu schreiben, dass sie unter Windows 9x ausführbar ist.&lt;/p&gt;

&lt;p&gt;Dabei ging es “nur” um normale UIs.&lt;/p&gt;

&lt;p&gt;Dienste wie unter &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_NT_4.0&quot;&gt;NT&lt;/a&gt; 
gab es nicht … oder vielleicht doch …?
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Es ist schon ein bisschen ironisch, dass sich die damals junge 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt; Community zu Recht über 
“das schlechte Windows” aufregte, und dabei fast ausschließlich Probleme mit 
Windows 95 und 98 nannte.&lt;br /&gt;
NT4 und 2000 konnte man dann nur als zu aufgebläht bezeichnen.&lt;/p&gt;

&lt;p&gt;Die strukturierte Verwaltung von “Diensten” (Daemons unter Linux) hatte aber 
nur NT wirklich drauf, während sich das junge Linux mit init-Scripten plagte
und interessanterweise nicht viel mehr hinbekam, als eben Windows 9x.&lt;/p&gt;

&lt;h3 id=&quot;kein-service-manager&quot;&gt;Kein Service Manager&lt;/h3&gt;

&lt;p&gt;Der Service Control Manager (SCM) definiert unter NT die Infrastruktur eines
Dienstes. Eine EXE startet und registriert sich selbst per API als Dienst 
inklusive Callbacks für diverse Statusänderungen und die Service-Runtime führt 
diese Callbacks als RPCs dann “kontrolliert” aus.&lt;/p&gt;

&lt;p&gt;Win9X kannte einen solchen Dienst nicht, hatte aber einen für damals typischen
billigen Trick, um so etwas Ähnliches wie Hintergrunddienste anzustarten.&lt;/p&gt;

&lt;h3 id=&quot;registry--registration--service&quot;&gt;Registry + Registration = Service&lt;/h3&gt;

&lt;p&gt;Viele Leute kennen den Registry-Key&lt;br /&gt;
&lt;code&gt;HKEY_LOCAL_MACHINE\Software\Microsoft\CurrentVersion\Run&lt;/code&gt;, dessen Einträge 
beim Login durchgelaufen werden und die String-Values einfach als Prozesse
gestartet werden.&lt;/p&gt;

&lt;p&gt;Für Dienste gab es &lt;code&gt;HKEY_LOCAL_MACHINE\Software\Microsoft\CurrentVersion\RunServices&lt;/code&gt;,
dessen Einträge schon beim Start des Windows-UI abgearbeitet wurden.
So konnte man per Key-Namen jedem Dienst einen Namen zuordnen und der 
String-Wert war einfach die Kommandozeile, die den Dienst starten sollte.&lt;/p&gt;

&lt;p&gt;Da bei der Abmeldung eines Benutzers auch alle laufenden Prozesse gekillt 
wurden, musste man noch einen Möglichkeit schaffen, die Dienst-Prozesse als
ebensolche zu markieren. Und das geschah mit folgender &lt;code&gt;kernel32&lt;/code&gt; API:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;DWORD WINAPI RegisterServiceProcess(DWORD dwProcessId, DWORD dwType);
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Diese Funktion existierte nur in Windows 9x und nicht NT, doch man konnte sie 
per &lt;code&gt;GetProcAddress()&lt;/code&gt; laden um zu beiden OS-Typen kompatibel zu bleiben.&lt;br /&gt;
Ein Aufruf von &lt;code&gt;RegisterServiceProcess(GetCurrentProcessId(), 1)&lt;/code&gt; registrierte
einen Prozess als Dienst, und schon wurde er nicht mehr beim Logout beendet.&lt;/p&gt;

&lt;h3 id=&quot;anwendung&quot;&gt;Anwendung&lt;/h3&gt;

&lt;p&gt;Manche Netzwerkserver für Windows wie FTP, HTTP oder NTP nutzten diese 
Methode um im Hintergrund ihre Dienste durchzuführen.&lt;br /&gt;
Doch da Windows 9x selten für solche “Dienste” genutzt wurde, ging diese 
Methode wieder in Vergessenheit.&lt;br /&gt;
Man findet sie noch in sehr alten Code-Repositories in Softwareständen vor
2003, doch danach wurde der Win9x-Service Support systematisch überall 
entfernt.&lt;/p&gt;

&lt;p&gt;Die Funktion &lt;code&gt;RegisterServiceProcess&lt;/code&gt; selbst findet man “leider” in 
zahlreichen alten Foren als “Hacker-Funktion” um das eigene Programm
vor dem Task-Manager zu verstecken.&lt;br /&gt;
Wer also Böses vor hatte und nicht wollte, dass das eigene Programm
leicht gekillt werden konnte, registrierte es fälschlich als Dienst.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Auch diese Technik wandert nun ins GATE Projekt und tut dort seinen
Dienst, wenn die NT-APIs nicht geladen werden können … sprich, wenn
ein Prozess unter Windows 9x gestartet wird.&lt;/p&gt;

&lt;p&gt;Da diese Funktion aber nur in ANSI-Kompilaten Sinn macht, ist dieser Teil 
in Unicode- oder x64- Varianten generell per &lt;code&gt;#ifdef&lt;/code&gt; deaktiviert.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>C++ Erbschafts-Steuer</title>
   <link href="https://www.opengate.at/blog/2023/06/cpp-inherit/"/>
   <published>2023-06-25T13:00:00+02:00</published>
   <updated>2023-06-25T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2023/06/cpp-inherit</id>
   <category term="devel" />
   <summary type="text">Politisch kann ich mich mit der Idee der Erbschaftssteuer gut identifizieren,
vermutlich deshalb weil mich kein Millionenerbe erwartet.

In Sachen C++ sollte jedenfalls jede 
unnötige Form von Erbschaft rigoros weggesteuert werden. Und im Gegensatz zur 
Politik mache ich gerne Nägel mit Köpfen und setze diese Ziel einfach um.
</summary>
   <content type="html">&lt;p&gt;Politisch kann ich mich mit der Idee der Erbschaftssteuer gut identifizieren,
vermutlich deshalb weil mich kein Millionenerbe erwartet.&lt;/p&gt;

&lt;p&gt;In Sachen &lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B&quot;&gt;C++&lt;/a&gt; sollte jedenfalls jede 
unnötige Form von Erbschaft rigoros weggesteuert werden. Und im Gegensatz zur 
Politik mache ich gerne Nägel mit Köpfen und setze diese Ziel einfach um.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Und wieder einmal hat mich der ehrwürdige alte Zen-Meister 
&lt;a href=&quot;https://en.wikipedia.org/wiki/Watcom_C/C%2B%2B&quot;&gt;OpenWatcom&lt;/a&gt; 
auf eine Lebensweisheit aufmerksam gemacht:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;code_bloat = exceptions * inheritance&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;vorgeschichte-welche-ausnahmen-gibt-es-überhaupt&quot;&gt;Vorgeschichte: Welche Ausnahmen gibt es überhaupt?&lt;/h3&gt;

&lt;p&gt;Anfangs dachte ich, dass Exceptions im Java-Style “übersichtlich” wären.
Es gibt im GATE Framework daher eine abstrakte &lt;code&gt;Throwable&lt;/code&gt; Klasse, von der
eine &lt;code&gt;Exception&lt;/code&gt; Basisklasse erbt, und dann gibt es im Namensraum &lt;code&gt;exceptions&lt;/code&gt;
noch für jeden Result-Code eine Template-Variante, wie z.B.:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;exceptions::NotImplemented&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;exceptions::NullPointer&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;exceptions::Timeout&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;exceptions::OutOfBounds&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;usw.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In Wahrheit sind die &lt;code&gt;exceptions::&lt;/code&gt; Varianten nur mit einem Result-Code 
konstruierte &lt;code&gt;Exception(results::ErrorCode)&lt;/code&gt; Instanzen.&lt;/p&gt;

&lt;p&gt;Zwar habe ich schon häufiger die “Endknoten” per &lt;code&gt;throw&lt;/code&gt; geworfen, doch in
den &lt;code&gt;catch&lt;/code&gt; Blöcken reagiere ich in erste Linie auf Instanzen der 
&lt;code&gt;Exception&lt;/code&gt; Basisklasse.&lt;/p&gt;

&lt;p&gt;Der Grund ist einfach: In fast allen Fällen ist es egal, ob z.B.: 
ein Dateizugriff, wegen eines &lt;code&gt;AccessDenied&lt;/code&gt; oder &lt;code&gt;NotAvailable&lt;/code&gt; Fehlers 
abbricht. Man loggt den Fehler und beendet die Operation. Es bringt mir 
also im Normalfall nichts zwischen den Fehlern zu unterscheiden und falls 
doch, tut das ein einfaches &lt;code&gt;if&lt;/code&gt; ebenso.&lt;/p&gt;

&lt;h3 id=&quot;die-eine-exception-die-viele-ist&quot;&gt;Die eine Exception, die viele ist…&lt;/h3&gt;

&lt;p&gt;Ich könnte also gleich die Basisklasse mit dem entsprechenden Fehlercode werfen.
Und um das umzusetzen, nutze ich eine Funktion namens&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt; raiseException(result_t resultCode, &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt;* msg = &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;, &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt;* src = &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;, int32_t errCode = &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;);
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Die machte bisher nichts anderes als den &lt;code&gt;resultCode&lt;/code&gt; Parameter auszuwerten und daraus ein&lt;br /&gt;
&lt;code&gt;throw exceptions::Something(msg, src, errCode);&lt;/code&gt; auszulösen.&lt;/p&gt;

&lt;p&gt;Und seit neuem macht sie nur noch:&lt;br /&gt;
&lt;code&gt;throw Exception(resultCode, msg, src, errCode);&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Und das alleine reichte, um die &lt;a href=&quot;https://de.wikipedia.org/wiki/MS-DOS&quot;&gt;DOS&lt;/a&gt; 
Varianten meiner GATE Tools um 70 bis 80 KByte zu verkleinern. So wurden 
aus 290 KB wieder 215 KB, ohne dass sich funktional was änderte.&lt;/p&gt;

&lt;h3 id=&quot;rtti-und-catch-blöcke&quot;&gt;RTTI und Catch-Blöcke&lt;/h3&gt;

&lt;p&gt;Mit jeder neuen abgeleiteten Klasse einer abstrakten Basis, wird ein 
unsichtbares Netz von Typenverknüpfungen um Hintergrund gesponnen, das dann
zum Einsatz kommt, wenn zur Laufzeit eine Exception geworfen und schrittweise
als ihr Basistyp zum Catch-Block überführt werden muss.&lt;/p&gt;

&lt;p&gt;Je mehr Klassen es gibt um so größer wird der generierte Hintergrundcode, der
dann am Ende vielleicht nie benutzt wird, aber trotzdem vorhanden sein muss.&lt;/p&gt;

&lt;p&gt;Jetzt könnte man natürlich hoffen, dass ein guter Optimizer den Großteil 
davon wegbekommt, doch wie sich zeigt, passiert das nicht (bzw. nicht immer).&lt;/p&gt;

&lt;p&gt;Am einfachsten kann man den Müllberg also dadurch klein halten, dass man 
im Vorfeld gar keinen Müll mehr produziert.
Und dieser Ansatz funktioniert offenbar zu meiner großen Freude.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ich habe die früheren &lt;code&gt;exceptions::Something&lt;/code&gt; Klassen per &lt;code&gt;#ifdef&lt;/code&gt; deaktiviert,
denn vielleicht finde ich in Zukunft doch noch Verwendung für sie.
Aber das DOS Beispiel hat mich bereits davon überzeugt, dass 
“eine” gute Exceptionklasse viel Effizienter ist, als 20 individuelle.&lt;/p&gt;

&lt;p&gt;Ich belasse daher die vereinfache Variante und freue mich, dass der ohnehin 
große Exceptionoverhead wieder ein Stück erträglicher geworden ist.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>CONAN CPUs</title>
   <link href="https://www.opengate.at/blog/2023/06/conan-cpu/"/>
   <published>2023-06-24T13:00:00+02:00</published>
   <updated>2023-06-24T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2023/06/conan-cpu</id>
   <category term="software" />
   <summary type="text">Buildsysteme wie CMake, 
XMake oder CONAN 
sorgen unter anderem auch dafür, dass die Builds so schnell wie möglich 
durchlaufen.
Und auf unseren heutigen Multikern-CPUs bedeutet das, dass sie so viele
CPU Kerne wie möglich parallel einsetzen.

Problematisch wird es nur, wenn das eben “zu viel” ist.
</summary>
   <content type="html">&lt;p&gt;Buildsysteme wie &lt;a href=&quot;https://de.wikipedia.org/wiki/CMake&quot;&gt;CMake&lt;/a&gt;, 
&lt;a href=&quot;https://xmake.io/&quot;&gt;XMake&lt;/a&gt; oder &lt;a href=&quot;https://de.wikipedia.org/wiki/Conan_(Software)&quot;&gt;CONAN&lt;/a&gt; 
sorgen unter anderem auch dafür, dass die Builds so schnell wie möglich 
durchlaufen.&lt;br /&gt;
Und auf unseren heutigen Multikern-CPUs bedeutet das, dass sie so viele
CPU Kerne wie möglich parallel einsetzen.&lt;/p&gt;

&lt;p&gt;Problematisch wird es nur, wenn das eben “zu viel” ist.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;neulich-in-der-firma-&quot;&gt;Neulich in der Firma …&lt;/h3&gt;

&lt;p&gt;Plötzlich schlägt eine Vielzahl an Builds fehl. Der 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_C%2B%2B&quot;&gt;MSVC&lt;/a&gt; meldet&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Internal compiler errors&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;und der &lt;a href=&quot;https://de.wikipedia.org/wiki/GNU_Compiler_Collection&quot;&gt;GCC&lt;/a&gt; schreibt:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Out of memory: Kill process (cc1plus)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;auf die Konsole.&lt;/p&gt;

&lt;p&gt;Die Meldung kannte ich, sie deutete darauf hin, dass ein Compilerprozess
vom System terminiert wurde und dahinter steckt oft fehlender RAM 
(bzw. fehlender virtueller Speicher im Allgemeinen).&lt;/p&gt;

&lt;p&gt;Bei der Meldung des Problems an die Buildserver Admins kam zurück,
dass wir zu viele Kerne parallel nutzen und das herunter limitieren sollen.&lt;/p&gt;

&lt;p&gt;Und das hat mir dann die Woche versaut …&lt;/p&gt;

&lt;h3 id=&quot;rechenformeln&quot;&gt;Rechenformeln&lt;/h3&gt;

&lt;p&gt;Für mich zählte die alte Formeln: &lt;code&gt;RAM = CPU-cores * 2GB&lt;/code&gt;&lt;br /&gt;
(Das absolute Minimum wäre &lt;code&gt;RAM = CPU-cores * 1GB&lt;/code&gt;)
Wird sie eingehalten, kann jeder Kern einen Compiler-Prozess erhalten und
parallel daran werkeln.&lt;/p&gt;

&lt;p&gt;Beim &lt;a href=&quot;https://de.wikipedia.org/wiki/Raspberry_Pi&quot;&gt;Raspberry PI&lt;/a&gt; 2 mit 4 Kernen 
und 1 GB wird die Regel verletzt, weshalb mir dort öfter der Build abbricht. 
Vor allem wenn Monster wie 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Boost_(C%2B%2B-Bibliothek)&quot;&gt;BOOST&lt;/a&gt; oder 
&lt;a href=&quot;https://de.wikipedia.org/wiki/SQLite&quot;&gt;SQLite&lt;/a&gt; gebaut werden sollen.&lt;/p&gt;

&lt;p&gt;Von einem offiziellen Buildserver in der Cloud erwarte ich allerdings, dass
diese einfachen Regeln eingehalten werden, denn unser benutztes CONAN
ermittelt die Anzahl der CPUs und startet dann eben genau so viele Prozesse
wie möglich.&lt;/p&gt;

&lt;p&gt;Nun wurde uns aber mitgeteilt, dass im Hintergrund
&lt;a href=&quot;https://de.wikipedia.org/wiki/Kubernetes&quot;&gt;Kubernetes&lt;/a&gt; für die 
Ressourcenverwaltung eingesetzt wird und dieses unsere Dockersitzungen 
verwaltet. Hier wird dann im virtualisierten Container die reale Anzahl
an Kernen des Hosts ausgegeben, nur der nutzbare RAM wurde auf 16 GB 
reduziert. Das bedeutet laut Formel, dass man nur 8 Kerne und damit 8
Compilerjobs parallel nutzen sollte, CONAN ermittelte jedoch 32 Kerne und 
überforderte somit das System.&lt;/p&gt;

&lt;h3 id=&quot;workarounds-als-lösung&quot;&gt;Workarounds als Lösung&lt;/h3&gt;

&lt;p&gt;Nachdem mir mitgeteilt wurde, dass es nicht möglich sei die aufgezählten 
CPU-Kerne im virtualisierten OS herunterzusetzen, blieb mir nur der Ausweg
eine Methode zu finden, wie man CONAN dazu bringt weniger parallele Jobs
zu starten.&lt;/p&gt;

&lt;p&gt;Zum Glück wurde mit &lt;code&gt;CONAN_CPU_COUNT&lt;/code&gt; bereits eine Umgebungsvariable 
eingeführt, mit der man exakt definieren kann, wie viele CPUs und damit
parallele Jobs ausgeführt werden sollen.&lt;/p&gt;

&lt;p&gt;Alternativ kann man auch in &lt;code&gt;conanfile.py&lt;/code&gt; beeinflussen, damit nicht 
automatisch ein &lt;code&gt;-j N&lt;/code&gt; an CMake geschickt wird, und anschließend lässt sich 
ein zusätzlicher Kommandozeilenparameter an &lt;code&gt;CMake&lt;/code&gt; senden, der die 
gewünschte Anzahl an Jobs erzeugt.&lt;br /&gt;
Das sieht dann etwa so aus:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color:#06B;font-weight:bold&quot;&gt;build&lt;/span&gt;(&lt;span style=&quot;color:#069&quot;&gt;self&lt;/span&gt;):
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;  job_count = &lt;span style=&quot;color:#00D&quot;&gt;4&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  cmake = CMake(&lt;span style=&quot;color:#069&quot;&gt;self&lt;/span&gt;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  cmake.configure()
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  cmake.parallel = &lt;span style=&quot;color:#069&quot;&gt;False&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;  cmake.build(args=[&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;-j&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span style=&quot;color:#369;font-weight:bold&quot;&gt;str&lt;/span&gt;(job_count)])
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h3 id=&quot;hartkodierte-limits-sind-falsch&quot;&gt;Hartkodierte Limits sind falsch!&lt;/h3&gt;

&lt;p&gt;Jetzt kann man zwar mit &lt;code&gt;CONAN_CPU_COUNT=8&lt;/code&gt; das Limit hart setzen, womit der
Build auf genau diesem Server läuft. Soll der Build aber auch auf anderen
Servern laufen, kommt es dort sofort zu Problemen, wenn dieser mit weniger 
CPUs und RAM ausgestattet ist. Und genau das passierte auch bei uns.&lt;/p&gt;

&lt;p&gt;Am Ende wurde eine neue Variable auf den Buildserven etabliert, die die 
maximal nutzbare Anzahl an CPUs definiert. Die Idee war, dass wir diese
Variable dann im CI-Script an &lt;code&gt;CONAN_CPU_COUNT&lt;/code&gt; zuweisen.&lt;br /&gt;
Auch dieser Schritt führte wieder ein Problem ein, nämlich dass
CONAN den Dienst verweigerte, wenn diese externe Variable nicht definiert
war. Dann wurde nämlich &lt;code&gt;CONAN_CPU_COUNT&lt;/code&gt; auf einen Leerstring gesetzt,
was zum Abbruch wegen einer Fehlkonfiguration führte.&lt;/p&gt;

&lt;h3 id=&quot;und-der-wahre-hintergrund-war&quot;&gt;Und der wahre Hintergrund war:&lt;/h3&gt;

&lt;p&gt;Tatsächlich war das Problem auf die Umstellung von CGROUPS v1 auf CGROUPS v2
zurückzuführen, die auf den Kubernetes Servern durchgeführt wurde.&lt;br /&gt;
Und wir nutzen die CONAN Version 1.50, welche nur CGROUPS v1 unterstützt.&lt;/p&gt;

&lt;p&gt;Das Geheimnis liegt in &lt;code&gt;cpu.py&lt;/code&gt;, welches bis v1.50 die beiden Pfade&lt;br /&gt;
&lt;code&gt;/sys/fs/cgroup/cpu/cpu.cfs_quota_us&lt;/code&gt; und&lt;br /&gt;
&lt;code&gt;/sys/fs/cgroup/cpu/cpu.cfs_period_us&lt;/code&gt; auslas und das CPU-Limit daraus
errechnete, was nur unter CGROUPS v1 funktioniert.&lt;/p&gt;

&lt;p&gt;Neuere Versionen von CONAN testen zuerst die CGROUPS v2 Pfade&lt;br /&gt;
&lt;code&gt;/sys/fs/cgroup/cgroup.controllers&lt;/code&gt; und&lt;br /&gt;
&lt;code&gt;/sys/fs/cgroup/cpu.max&lt;/code&gt; bevor sie auf die beiden V1 Pfade zurückgreifen.&lt;/p&gt;

&lt;p&gt;Tja … nur leider lässt sich das Build-Image erst wieder mit dem
nächsten größeren Software-Release auf CONAN 1.51+ upgraden.&lt;/p&gt;

&lt;p&gt;Somit bleibt leider vorerst nur der hässliche Workaround mit 
&lt;code&gt;CONAN_CPU_COUNT&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ich kotz’ gleich im Strahl …&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Buildsysteme sollen ihre Umgebung korrekt erkennen können und sich darauf
best-möglich einrichten. Und Hostsysteme sollen ihren Containern von außen
nur die Ressourcen anzeigen, die sie nutzen dürfen.&lt;/p&gt;

&lt;p&gt;Ich verstehe nicht, warum mit CGROUPS v2 die Kompatibilität der &lt;code&gt;sysfs&lt;/code&gt; Pfade
gebrochen wird, und ich verstehe auch nicht, warum Docker überhaupt erst die 
reale CPU-Anzahl an Prozesse im Container zurückliefert.&lt;/p&gt;

&lt;p&gt;In jedem Fall hat diese unnötige Panne unzählige Stunden gekostet und wird
in Zukunft noch weitere Zeit einnehmen.&lt;/p&gt;

&lt;p&gt;Ich für meinen Teil habe daraus allerdings gelernt, dass Docker ganz 
unschöne Seiteneffekte produzieren kann, denn auch meine Codes würden nicht 
im &lt;code&gt;sysfs&lt;/code&gt; nach Dateien suchen, wenn sie die CPU-Anzahl wissen wollen.&lt;/p&gt;

&lt;p&gt;Und ganz nebenbei:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Auf meinem Azure Buildserver läuft eine VM mit einer CPU und 512 MB RAM.
Eigentlich würden darauf alle Builds fehlschlagen, doch ich habe dort
&lt;a href=&quot;/blog/2021/03/azure-vm/&quot;&gt;den Swapspace&lt;/a&gt; aktiviert.
Und schon führt die Verletzung der obigen Formel nicht mehr zum Crash,
es dauert nur länger, wenn die Platte rattert.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Soll heißen: Man kann die CPU/RAM/Job Überlastung auch noch anders abfangen.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Laptop mit FreeDOS</title>
   <link href="https://www.opengate.at/blog/2023/06/freedos-laptop/"/>
   <published>2023-06-18T13:00:00+02:00</published>
   <updated>2023-06-18T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2023/06/freedos-laptop</id>
   <category term="hardware" /><category term="software" />
   <summary type="text">
  PCs und Laptops dürfen nicht ohne OS verkauft werden.


So steht das irgendwo.
Und eben deshalb werden auch heute noch Computer mit 
FreeDOS verkauft.
</summary>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;PCs und Laptops dürfen nicht ohne OS verkauft werden.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So steht das irgendwo.&lt;br /&gt;
Und eben deshalb werden auch heute noch Computer mit 
&lt;a href=&quot;https://de.wikipedia.org/wiki/FreeDOS&quot;&gt;FreeDOS&lt;/a&gt; verkauft.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;2005 erwarb ich erstmals einen verbilligten Laptop, der kein
Windows, kein Linux, sondern nur DOS installiert hatte.&lt;/p&gt;

&lt;p&gt;Dass ich heute im Jahr 2023 wieder auf so ein Gerät stoße, 
verwunderte mich sehr … denn heutige PCs und Laptops unterstützen
den Boot von 32 bit Software eigentlich gar nicht mehr.&lt;/p&gt;

&lt;p&gt;Wie soll das also funktionieren?&lt;/p&gt;

&lt;h3 id=&quot;freedos-am-x86-64-laptop&quot;&gt;FreeDOS am X86-64 Laptop&lt;/h3&gt;

&lt;p&gt;Nach dem Einschalten des HP Laptops erscheint ein Boot Menü, das entweder
zu FreeDOS oder zum “Handbuch” umleitet.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/freedos-laptop-3.jpg&quot; alt=&quot;Laptop-FreeDOS-3&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Und tatsächlich scheint dann ein FreeDOS zu starten.
Warum es sich dabei um eine veraltete Version aus dem Jahr 2006 handelt,
erschließt sich mir nicht, denn inzwischen ist v1.3 verfügbar.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/freedos-laptop-1.jpg&quot; alt=&quot;Laptop-FreeDOS-1&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Doch außer den Standard-DOS Programmen findet man nichts, womit man 
arbeiten könnte.&lt;/p&gt;

&lt;h3 id=&quot;betriebsanleitung-in-browserform&quot;&gt;Betriebsanleitung in Browserform&lt;/h3&gt;

&lt;p&gt;Parallel dazu startet der zweite Eintrag im Bootmenü einen Browser
im Vollbild und lässt einen per Maus über Links zu den einzelnen
Seiten des Benutzerhandbuches wechseln.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/freedos-laptop-5.jpg&quot; alt=&quot;Laptop-FreeDOS-5&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Man hätte auch sagen können: Eine Art PDF-Viewer.
Menüs und andere Funktionen konnte ich dort auf die Schnelle nicht
entdecken.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/freedos-laptop-4.jpg&quot; alt=&quot;Laptop-FreeDOS-4&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;verstecktes-linux&quot;&gt;Verstecktes Linux&lt;/h3&gt;

&lt;p&gt;Gelegentlich blitzte beim Starten (egal ob DOS oder Handbuch) dann die 
Wahrheit durch:&lt;br /&gt;
Im Hintergrund wird eine kleine Linux Installation gestartet, die FreeDOS 
offenbar im Emulator ausführt.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/freedos-laptop-2.jpg&quot; alt=&quot;Laptop-FreeDOS-2&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Und das ist auch die einzige Möglichkeit, die mir einfallen würde, um in
vertretbarer Zeit DOS auf so einem Gerät auszuführen.&lt;/p&gt;

&lt;p&gt;So lange PCs und Laptops mit dem EFI-CSM (Compatibility-Support-Module) 
ausgestattet waren, konnte man den X86-Prozessor wieder den Real-Mode 
zurückschalten und im Speicher das klassische BIOS ablegen, mit dem DOS
dann die Hardware anspricht.&lt;/p&gt;

&lt;p&gt;Das CSM war auch für ein 32-bit Windows notwendig, doch nachdem es heute
kaum noch reine 32-bit Prozessoren gibt (die letzten waren alte Intel-Atoms “Z”)
und auch Microsoft mit Windows 11 gar kein 32-bit System mehr liefert, 
entfällt diese Brücke in die 80er Jahr endgültig und es können nur noch 
Systeme gebootet werden, die native x64-EFI-Bootloader bereitstellen.&lt;/p&gt;

&lt;p&gt;FreeDOS gehört nicht dazu.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Es wäre ja interessant einen Emulator oder Hyper-Visor als reine EFI
App zu schreiben und FreeDOS darüber ausführen zu lassen.&lt;br /&gt;
Doch so lange das nicht fertig ist, hat man das Ziel mit Linux am schnellsten 
erreicht.&lt;/p&gt;

&lt;p&gt;Doch hiermit komme ich nicht klar:&lt;br /&gt;
Warum installiert man ein lauffähiges Linux um dann DOS anzuzeigen, mit dem
man nichts machen kann?&lt;br /&gt;
Man hätte dann doch gleich eine rudimentäres Linux mit Kommandozeile einsetzen
können und dort wäre ein Support für Netzwerk und Updates gleich inkludiert
gewesen.&lt;/p&gt;

&lt;p&gt;Naja … wieder so eine Dummheit aus der Vergangenheit. Nur weil man
Nicht-Windows-System im Jahr 2005 mit FreeDOS herausbrachte, muss man 
dieses Verfahren doch nicht künstlich im Jahr 2023 immer noch am Leben
erhalten …&lt;/p&gt;

&lt;p&gt;Aber 15 Minuten später lief “mein” Windows 11 auf dem Gerät und alles war gut.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Luftfeuchtigkeit abbauen</title>
   <link href="https://www.opengate.at/blog/2023/06/dehumidifier/"/>
   <published>2023-06-17T13:00:00+02:00</published>
   <updated>2023-06-17T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2023/06/dehumidifier</id>
   <category term="hardware" /><category term="projects" />
   <summary type="text">Dicke Luft hat man auch, wenn zu viel Wasser in ihr steckt, was gerne in alten
Kellern passieren kann.

Und nachdem ich neulich wieder ein Video sah, wie man sich so einen
Luftentfeuchter (auch Dehumidifier genannt) selber basteln kann, 
dachte ich: OK, das will ich auch!
</summary>
   <content type="html">&lt;p&gt;Dicke Luft hat man auch, wenn zu viel Wasser in ihr steckt, was gerne in alten
Kellern passieren kann.&lt;/p&gt;

&lt;p&gt;Und nachdem ich neulich wieder ein Video sah, wie man sich so einen
Luftentfeuchter (auch Dehumidifier genannt) selber basteln kann, 
dachte ich: &lt;em&gt;OK, das will ich auch!&lt;/em&gt;
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Peltier-Element&quot;&gt;Peltier Elemente&lt;/a&gt; heißen die 
kleinen Zauberdinger, die entweder aus Wärmeunterschieden Strom erzeugen, oder
aus Strom Wärmeunterschiede herstellen.
Fließt durch ein solches Element Strom, wird die eine Seite heiß und die 
andere kalt.&lt;/p&gt;

&lt;p&gt;Aus diesem Prinzip entsteht die Idee, dass an der kalten Stelle die 
Wasseranteile der Luft kondensieren und dort langsam abtropfen.
Man braucht also nur zwei Kühlkörper, die die Oberfläche vergrößern
und zwei Ventilatoren, die die warme Luft auf der einen Seite zur Kühlung 
abführen und auf der anderen Seite Umgebungsluft durch den Kühlkörper
strömen um dort das Wasser kondensieren zu lassen.&lt;/p&gt;

&lt;h3 id=&quot;idee&quot;&gt;Idee&lt;/h3&gt;

&lt;p&gt;Die Plastik-Box, in der meine Waschmaschinen Waschmittel-Tabs verkauft werden,
erschien mir passend, um am Deckel das Peltier Element mit den beiden 
Kühlkörpern anzubringen.&lt;/p&gt;

&lt;p&gt;Die warme Seite zeigt nach oben, also außerhalb der Box um Wärme abzuleiten.
Die kalte nach unten innerhalb der Box.&lt;/p&gt;

&lt;p&gt;Durch Löcher in der Seitenwand soll Luft durch die Box strömen können.
Und das kondensierte Wasser kann auf den Boden der Box abtropfen.&lt;/p&gt;

&lt;h3 id=&quot;auf-zur-klebepistole&quot;&gt;Auf zur Klebepistole&lt;/h3&gt;

&lt;p&gt;Ich hatte einige alte CPU und Chipset-Kühlkörper mit und ohne Lüfter 
herumliegen und von denen nahm ich mir zwei.
Aus einer PVC-Platte schnitt ich mir eine Schablone heraus, die den
äußeren Umriss des Peltier-Elements vergrößerte.&lt;br /&gt;
So konnte ich dann die Kühlkörper, die viel größer als das Peltier-Element
waren fest mit der PVC-Schablone verkleben, die das Element in seiner
Mitte umschloss.&lt;/p&gt;

&lt;p&gt;Aus dem Deckel der Box schnitt ich dann nur die Größe des kleiner Kühlkörpers (oben)
aus, verklebte den größeren Kühler mit dem größeren PVC-Teil unten. Hier musste
ja mehr Klebefläche herhalten, damit es auch am Deckel befestigt blieb.
Oben schob ich dann noch eine dünnere Kartonschablone um den oberen Kühler
herum ein, um auch dessen Auflagefläche zu vergrößern und verklebte sie mit
dem Deckel.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/diy-dehumidifier-3.jpg&quot; alt=&quot;DIY-Dehumidifier-3&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Nun saßen beiden Kühlkörper direkt am Peltier-Element anliegend in der Mitte
umgeben von PVC und viel Klebstoff.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/diy-dehumidifier-2.jpg&quot; alt=&quot;DIY-Dehumidifier-2&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Das Kind in mir hatte viel Spaß mit der Kleberei. Aber so war die Sache auch
in wenigen Minuten fertig.&lt;/p&gt;

&lt;h3 id=&quot;durchzug-mit-ventilation&quot;&gt;Durchzug mit Ventilation&lt;/h3&gt;

&lt;p&gt;Damit genug Luft durch die Box durchfegen sollte, verschraubte ich einen 
weiteren kleinen PC-Lüfter an der Wand, wo ich zuvor ein Loch 
eingeschnitten hatte.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/diy-dehumidifier-4.jpg&quot; alt=&quot;DIY-Dehumidifier-4&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Hier zeigte sich wieder, dass auf dem dünnen Plastik Schrauben nicht die
beste Lösung waren. Doch mit Klebstoff bei den Lüfterblättern 
herumzuwerken erschien mir genau so falsch.&lt;/p&gt;

&lt;h3 id=&quot;erster-testbetrieb&quot;&gt;Erster Testbetrieb&lt;/h3&gt;

&lt;p&gt;Jetzt wurden die Lüfter und das Element mit dem Labornetzteil verbunden
und die Box damit eingeschaltet.&lt;/p&gt;

&lt;p&gt;Das Element verhielt sich korrekt und die Rippen des unteren Kühlkörpers
fingen langsam an keine Wassertröpfchen einzufangen.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Hier lag mein Fehler:&lt;br /&gt;
Ich hätte statt einem langen niedrigen Kühlkörper eher einen kürzeren
höheren nutzen sollen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Die kleinen Wassertropfen sollen sich schließlich zu größeren verbinden
und dann abtropfen, doch auf den niedrigen Rippen können keinen besonders
großen Tropfen entstehen.&lt;/p&gt;

&lt;h3 id=&quot;schieflage&quot;&gt;Schieflage&lt;/h3&gt;

&lt;p&gt;Mein Workaround-Fix war nun, dass ich die Box an einer Seite aufsockelte,
damit sie schief dastand.&lt;/p&gt;

&lt;p&gt;Das hat ein wenig geholfen, dass die Tröpfchen zur Kannte wanderten, größer
wurden und besser abtropften.&lt;/p&gt;

&lt;p&gt;Hätte ich nochmals von vorne angefangen, wäre die Wahl auf einen anderen
Kühler gefallen, doch so blieb ich bei dem, was ich bereits zusammengeklebt
hatte.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/diy-dehumidifier-1.jpg&quot; alt=&quot;DIY-Dehumidifier-1&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Nun… es sieht aus wie der Bastelversuch eines Kindes … aber aus eben
solchen Erfahrungen lernt man.&lt;/p&gt;

&lt;p&gt;Und funktional erfüllt das Teil zumindest die Minimalanforderungen und so
war nach einiger Zeit auch der Boden der Box “bewässert”.&lt;/p&gt;

&lt;p&gt;Für mich ist damit der Beweis erbracht, dass ich mit Müll und Schrott aus
der Kiste, einem Peltier-Element und viele Klebstoff einen Luft-Entfeuchter
bauen kann.&lt;br /&gt;
Und das geht fast schneller, als den Bestellprozess in einem Webshop 
abzuschließen … von der Wartezeit der Lieferung ganz zu schweigen.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Ziglang</title>
   <link href="https://www.opengate.at/blog/2023/06/ziglang/"/>
   <published>2023-06-11T13:00:00+02:00</published>
   <updated>2023-06-11T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2023/06/ziglang</id>
   <category term="devel" />
   <summary type="text">Vergesst RUST!

Die Programmiersprache ZIG
(auch als ZIGlang bekannt) wäre die einzige Sprache, die vielleicht mal C 
ersetzen könnte … weil sie C beinhaltet.
</summary>
   <content type="html">&lt;p&gt;Vergesst RUST!&lt;/p&gt;

&lt;p&gt;Die Programmiersprache &lt;a href=&quot;https://de.wikipedia.org/wiki/Zig_(Programmiersprache)&quot;&gt;ZIG&lt;/a&gt;
(auch als ZIGlang bekannt) wäre die einzige Sprache, die vielleicht mal C 
ersetzen könnte … weil sie C beinhaltet.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Seit meiner &lt;a href=&quot;/blog/2023/02/rust/&quot;&gt;ersten Bekanntschaft mit RUST&lt;/a&gt;,
stelle ich mir häufiger die Frage, welche Techniken eine Sprache besser oder
schlechter für Betriebssysteme geeignet sind.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B&quot;&gt;C++&lt;/a&gt; stellt für mich nach wie vor ein 
Optimum dar, da es vollständig auf C aufsetzt. Dennoch stehen Exceptions und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Runtime_Type_Information&quot;&gt;RTTI&lt;/a&gt; als genutzte 
Features in der &lt;a href=&quot;https://de.wikipedia.org/wiki/Standard_Template_Library&quot;&gt;STL&lt;/a&gt; 
dem Ziel OSDev leider sehr im Wege.&lt;/p&gt;

&lt;p&gt;An RUST hingegen stört mich sehr, dass es C als Fremdkörper behandelt und den
zentralen Fehler vieler Sprachen wiederholt: Es bildet kein stabiles ABI ab
und integriert das C-ABI nicht direkt sondern nur über foreign-function-calls.&lt;/p&gt;

&lt;p&gt;Und dann entdeckte ich &lt;code&gt;ZIG&lt;/code&gt;`.&lt;/p&gt;

&lt;p&gt;Als Sprache ist ZIG für mich “leider” ähnlich wie RUST zur Visual-Basic Syntax
zurückgerutscht und liest sich neben C Code schwer, weil alles verkehrt 
deklariert wird. Eine C Funktion wie&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;int32_t foo(int32_t x, int32_t y) {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; x + y;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;sieht in ZIG so aus:&lt;/p&gt;

&lt;div class=&quot;language-zig highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;pub fn foo(x: i32, y: i32) i32 {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;  return x + y;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Konkret fehlt eigentlich nur der &lt;code&gt;-&amp;gt;&lt;/code&gt; Pfeil zwischen Funktionsparameter und 
Return-Type, um aus der ZIG-Funktion eine RUST-Funktion zu machen.&lt;/p&gt;

&lt;p&gt;In Summe kann ZIG auch um einiges weniger als RUST, es unterstützt keine
Klassen, keine Traits und keine Polymorphismen für Objekte.&lt;/p&gt;

&lt;p&gt;Doch ZIG kann etwas, woran andere Sprachen scheitern:&lt;/p&gt;

&lt;p&gt;Es integriert einen C Compiler, kann selbst als C-Compiler auftreten
und C-Code zusammen mit dem eigenen ZIG-Format in einem Programm zusammenfassen.&lt;/p&gt;

&lt;p&gt;Diese Eigenschaft hatte bisher nur C++, ab nun gibt es Konkurrenz.&lt;/p&gt;

&lt;h3 id=&quot;hochsprache-ohne-exceptions&quot;&gt;Hochsprache ohne Exceptions&lt;/h3&gt;

&lt;p&gt;Fehlerbehandlung ist ein großes Thema und Exception sind häufig der Grund
warum C++ im Embedded, OS und Hardwarebereich verworfen wird.
(Dabei vergisst man leider, dass man C++ auch ohne Exceptions nutzen kann!).&lt;/p&gt;

&lt;p&gt;ZIG bietet mit seinen integrierten Optionals und Error-Typen ein Feature auf
unterster Sprachebene an, was C++ erst mit C++17 durch &lt;code&gt;std::optional&lt;/code&gt; und
&lt;code&gt;std::variant&lt;/code&gt; nachliefert und dort leider nicht so elegant geschrieben werden
kann.&lt;/p&gt;

&lt;p&gt;Zusätzlich dürfen ZIG-Pointer nicht NULL werden, an diese Stellen treten leere
Optionals oder Error-Types.
Man kann dann auf den Inhalt des Pointers gar nicht zugreifen, wenn man ihn
nicht prüft oder den Error-Type per &lt;code&gt;try&lt;/code&gt; oder &lt;code&gt;catch&lt;/code&gt; behandelt.&lt;br /&gt;
Der Compiler lässt daher unsicheren Code (ähnlich wie in RUST) erst gar nicht
entstehen.&lt;/p&gt;

&lt;h3 id=&quot;comptime-vs-makros&quot;&gt;Comptime vs. Makros&lt;/h3&gt;

&lt;p&gt;ZIG unterstützt keine Makros (außer man kompiliert reinen C Code).
Als Alternative erlaubt einem die Sprache aber jede Funktion, Variable
oder jeden Parameter als &lt;code&gt;comptime&lt;/code&gt; zu markieren.&lt;br /&gt;
Das bedeutet, dass das Element schon zur Übersetzungszeit bekannt sein
muss und der Code teilweise oder vollständig vom Compiler ausgeführt
wird, womit eine neue Form der dynamischen Code-Generierung entstehen
kann.&lt;/p&gt;

&lt;p&gt;Vergleichbar ist dieses Feature noch am ehesten mit C++ &lt;code&gt;constexpr&lt;/code&gt;,
welches mit jedem neuen Sprachstandard tiefer in die Sprache vordringt.&lt;/p&gt;

&lt;p&gt;Durch &lt;code&gt;comptime&lt;/code&gt; lassen sich Typen auswerten und Generics-Features
entwerfen, wie auch ganze Datenstrukturen während des Kompilierens
zusammengesetzt werden können.&lt;/p&gt;

&lt;p&gt;Kurz gesagt: &lt;em&gt;Voll geil!&lt;/em&gt;&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;ZIG ist für mich Neuland, jedoch eine Gegend, die ich gerne betrete.
Ich weiß nicht, wie lange es dauern wird, bis ich ausreichend darüber
weiß, doch jetzt muss ein Schritt nach dem anderen gesetzt werden.&lt;/p&gt;

&lt;p&gt;Fall es möglich ist, würde ich gerne ZIG als weitere Anbindung neben
C++ in mein GATE Projekt aufnehmen.&lt;br /&gt;
… aber ob das so leicht umsetzbar sein wird, das steht noch in 
den Sternen.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>DOS WATCOM Stackoverflow</title>
   <link href="https://www.opengate.at/blog/2023/06/stack-overflow/"/>
   <published>2023-06-10T13:00:00+02:00</published>
   <updated>2023-06-10T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2023/06/stack-overflow</id>
   <category term="devel" />
   <summary type="text">Auf die Frage, warum meine Grafikdemo funktioniert und meine
Commandline-Tools auf der DOS 
Plattform häufig crashen, gibt es eine Antwort:


  Der Command Line Parser löst Stack-Overflows aus.


Aber warum?
</summary>
   <content type="html">&lt;p&gt;Auf die Frage, warum meine Grafikdemo funktioniert und meine
Commandline-Tools auf der &lt;a href=&quot;https://de.wikipedia.org/wiki/MS-DOS&quot;&gt;DOS&lt;/a&gt; 
Plattform häufig crashen, gibt es eine Antwort:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Der Command Line Parser löst Stack-Overflows aus.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Aber warum?
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Das beste am Umstieg von DOS auf 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_NT&quot;&gt;Windows NT&lt;/a&gt; war, dass man 
bei Crashes nicht mehr dauernd den Reset-Knopf drücken musste. Ich nannte 
solche DOS Programme damals einfach: Schlecht programmiert.&lt;br /&gt;
Denn sie funktionierten und scheiterten abhängig vom verfügbaren
konventionellen Arbeitsspeicher … und der war mit seinem 640 KB Maximum
nicht gerade groß.&lt;/p&gt;

&lt;p&gt;Als meine eigenen DOS Kompilate scheiterten, obwohl sie unter 
Windows und Linux durch alle Tests kamen, stürzte mich das fast in
eine Krise. Denn was bringt mir die Portierung von Code auf die
DOS Plattform, wenn dann am Ende nichts läuft?&lt;/p&gt;

&lt;p&gt;Doch ein zufälliger Blick in die von &lt;a href=&quot;https://de.wikipedia.org/wiki/Watcom&quot;&gt;Watcom&lt;/a&gt; 
generierten &lt;code&gt;.map&lt;/code&gt; Dateien zeigten auf, dass nur 2 KB Stack im Programm reserviert werden.
Und da am gleichen Datensegment auch noch andere Dinge wie globale Variablen 
liegen können führt es zwangsläufig zu Überschneidungen, wenn der Stack seine 
engen Grenzen sprengt.&lt;/p&gt;

&lt;h3 id=&quot;lösung-stack-vergrößern&quot;&gt;Lösung: Stack vergrößern&lt;/h3&gt;

&lt;p&gt;Die notwendige Anpassung der Linkerflags war schnell gefunden, als ich 
wusste, wo das Problem herkam:&lt;br /&gt;
&lt;code&gt;opt stack=32768&lt;/code&gt; vergrößert den reservierten Stackbereich auf 32 KB,
was im Endeffekt ausreichte.&lt;/p&gt;

&lt;p&gt;In &lt;a href=&quot;https://de.wikipedia.org/wiki/CMake&quot;&gt;CMake&lt;/a&gt; hängt man das einfach 
an die Variable &lt;code&gt;CMAKE_EXE_LINKER_FLAGS&lt;/code&gt;an:&lt;/p&gt;

&lt;div class=&quot;language-cmake highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;set(CMAKE_EXE_LINKER_FLAGS &amp;quot;${CMAKE_EXE_LINKER_FLAGS} opt stack=32768&amp;quot;)
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;Kleiner Fix, große Wirkung.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Da im GATE Projekt Strings bzw. Stringausschnitte nicht zwingend &lt;code&gt;NUL&lt;/code&gt;-
terminiert sind, müssen Inhalte vor der Übergabe an externe C-Funktionen
(zB. Dateipfade) in einen Puffer kopiert werden, der dann mit einem &lt;code&gt;\0&lt;/code&gt; 
endet, und das passiert meist auf dem Stack, der somit schnell über 2K 
anwachsen kann.&lt;/p&gt;

&lt;p&gt;Ich muss aber eingestehen, dass mir mit diesen Crashes vor Augen geführt
wurde, dass einige Design-Entscheidungen nicht ideal für bestimmte
Plattformen sind. Denn klassische DOS Anwendungen kamen mit wenigen
Bytes auf dem Stack aus.&lt;/p&gt;

&lt;p&gt;Ob gleich das Problem nun gelöst ist, werde ich im Hinterkopf mal 
durchdenken, ob ich nicht vielleicht ganz allgemein zu viel auf dem
Stack arbeite.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>WinCE Hardware</title>
   <link href="https://www.opengate.at/blog/2023/06/wince/"/>
   <published>2023-06-04T13:00:00+02:00</published>
   <updated>2023-06-04T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2023/06/wince</id>
   <category term="hardware" /><category term="retro" />
   <summary type="text">Programme für Windows CE 
zu bauen ist und bleibt eines meiner Hobbies.
Doch Hardware bekommt man für dieses OS nicht einfach so im Laden.

Doch zwei (Nicht-Smartphone-) Geräte mit diesem OS kann ich dennoch mein
Eigen nennen.
</summary>
   <content type="html">&lt;p&gt;Programme für &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_CE&quot;&gt;Windows CE&lt;/a&gt; 
zu bauen ist und bleibt eines meiner Hobbies.
Doch Hardware bekommt man für dieses OS nicht einfach so im Laden.&lt;/p&gt;

&lt;p&gt;Doch zwei (Nicht-Smartphone-) Geräte mit diesem OS kann ich dennoch mein
Eigen nennen.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;wondermedia-laptop&quot;&gt;WonderMedia Laptop&lt;/h3&gt;

&lt;p&gt;Vor etwas über 10 Jahren startete ich meine erste zaghafte Bestellung aus 
China.
Damals gab es noch kein &lt;a href=&quot;https://de.wikipedia.org/wiki/AliExpress&quot;&gt;AliExpress&lt;/a&gt;, 
dafür aber einige schlecht zusammengeschusterte Webseiten mit Angeboten für 
Laptops und Tablets um die 100 Euro.&lt;/p&gt;

&lt;p&gt;Als ich dort meine Bestellung in ein Webformular eintrug und per 
&lt;a href=&quot;https://de.wikipedia.org/wiki/PayPal&quot;&gt;PayPal&lt;/a&gt; bezahlte, rechnete ich mit einer 
50:50 Chance, dass mein Geld weg sein konnte, doch ich wollte eben unbedingt 
ein ARM Gerät mit Windows CE haben und war risikofreudig.&lt;/p&gt;

&lt;p&gt;Und es ging gut aus:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/wince-laptop-01.jpg&quot; alt=&quot;WinCE-Laptop-1&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Ein Laptop mit WM8650 CPU, 256 MB RAM, 4 GB FlashDrive und einem 7 Zoll LCD 
Screen kam einige Wochen später per Paketdienst in Wien an.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/wince-laptop-02.jpg&quot; alt=&quot;WinCE-Laptop-2&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Die CPU ist mit 800 MHz getaktet und die Bildauflösung schafft 800 x 480 Pixel.
Ein kleines Netzteil versorgte das Gerät mit 9V und ~1.5A mit Strom und der 
eingebaute Akku sorgte für ein bisschen “Freiheit” von der Steckdose.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/wince-laptop-03.jpg&quot; alt=&quot;WinCE-Laptop-3&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Ins Netzwerk gelangte man über den 100 MBit LAN Anschluss an der Rückseite
oder das integrierte WLAN-Modul. Allerdings war die WLAN-Verbindung mit dem 
Gerät immer so schlecht, dass ich sie nie produktiv nutzte und immer ein
Kabel anschloss.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/wince-laptop-04.jpg&quot; alt=&quot;WinCE-Laptop-4&quot; /&gt;&lt;/p&gt;

&lt;p&gt;3 USB Ports (2 rechts, einer hinten) erlaubten den Anschluss von Maus, 
Tastatur und weiteren Speichermedien.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/wince-laptop-05.jpg&quot; alt=&quot;WinCE-Laptop-5&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Während das integrierte Keyboard zwar sehr klein aber dennoch “nutzbar” war,
ist eine separate Maus ein absolutes Muss für diesen Laptop. Das integrierte
Touchpad gleicht einem Zufallsgenerator, der willkürlich Berührungen ignoriert
und dann doch wieder weitergibt. Auch die beiden unsensiblen Maustasten 
verdienen ihren Namen nicht.&lt;/p&gt;

&lt;p&gt;Mit Windows CE 6.0 war dieses Gerät mein erstes vollwertiges CE-Windows, mit 
dem ich selbstgeschriebene Programme testen konnte. Auf meinen Windows Mobile
Telefonen war das theoretisch zwar auch möglich, doch wegen der unguten 
Bedienung verlor ich stets die Lust nach wenigen Minuten.&lt;/p&gt;

&lt;p&gt;Trotz der an Windows 98 angelehnten Oberfläche reichten die 800 MHz der CPU
nicht im entferntesten an die Performance eines Intel Pentium mit 300 MHz
Ende der 90er heran.
Die Bedienung wirkte schwerfällig und so wundert es mich nicht, dass dieses
Gerät keine guten Kritiken erhielt und schnell wieder verschwand.&lt;/p&gt;

&lt;p&gt;Für mich war es jedoch die perfekte Gelegenheit, Windows-CE mal live 
auszuprobieren um mit seinen Eigenheiten jenseits von Smartphones vertraut
zu werden.&lt;/p&gt;

&lt;h3 id=&quot;gps-navi-fürs-auto&quot;&gt;GPS Navi fürs Auto&lt;/h3&gt;

&lt;p&gt;Vor 2 Jahren fiel mir eines der letzten mit Windows-CE betriebenen Geräte auf,
und zwar ein GPS-Navi fürs Auto auf AliExpress.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/wince-navi-01.jpg&quot; alt=&quot;WinCE-Navi-1&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Solche Modelle gibt es bis heute auf der China-Plattform als billige Navis und
Video-Abspieler und sie alle bauen offenbar auf einem alten modifizierten
Windows CE 6.0 auf.&lt;br /&gt;
Mein Gerät startet ein eigenes UI, dass man aber beenden kann und dann in der
normalen Windows-CE-Desktop-Shell landet.&lt;/p&gt;

&lt;p&gt;Die Preise variieren von 40 bis 100 Euro je nach Ausstattung.&lt;br /&gt;
Und somit leistete ich mir auch eines dieses Billigteile.&lt;/p&gt;

&lt;p&gt;Viel Informationen erhält man leider nicht über die verbaute Hardware, 
aber ich weiß zumindest, dass ich mit 128 MB RAM auf einem 5 Zoll Screen 
arbeiten kann. Ein einziger USB-Port versorgt das Gerät mit Strom 
(im Auto über den Zigarettenanzünder) und dieser zieht laut Messung nur
350 Milliampere bei 5V.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/wince-navi-02.jpg&quot; alt=&quot;WinCE-Navi-2&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Mit der Außenwelt kann das Gerät nur über die Touchscreen kommunizieren.
WLAN oder LAN-Anschlüsse fehlen, was bei einem Gerät fürs Auto auch OK ist.&lt;/p&gt;

&lt;p&gt;Mitgeliefert wurde auch eine eingelegte SD Karte, auf der offenbar die 
Navigationskartendaten abgelegt sind, wie auch einige andere Strukturen
für den enthaltenen MP3- und Video-Player.&lt;/p&gt;

&lt;p&gt;Über den USB Port kann das Navi auch mit dem PC verbunden werden, 
wo es sich als zwei Laufwerke meldet.
Ein Laufwerk stellt den leeren internen Flash Speicher dar, das zweite
bildet die eingesteckte SD-Karte ab.&lt;br /&gt;
Alternativ kann man die USB-Verbindung auch per Einstellung für das 
alte &lt;a href=&quot;https://de.wikipedia.org/wiki/ActiveSync&quot;&gt;ActiveSync&lt;/a&gt; Protokoll zur 
Wartung und Installation von Software nutzen.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/wince-navi-03.jpg&quot; alt=&quot;WinCE-Navi-3&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Das Navi kann zwar bei weitem nicht so flexibel eingesetzt werden wie der
Laptop, aber im Notfall ist es eben auch ein typisches Windows-CE Gerät,
dass dafür entwickelte Software hosten kann.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Für den Laptop hatte auch einmal ein angepasstes 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Arch_Linux&quot;&gt;Arch-Linux&lt;/a&gt; gefunden, das
von der SD-Karte gebootet werden konnte. Es ist also auch möglich, das 
Gerät auf Linux umzustellen, doch das vermag aus der Hardware auch nicht
mehr herauszuholen. Ich erinnere mich auch dort an eine extrem zähe
UI-Erfahrung, die dem Alltag nicht gerecht wird.&lt;/p&gt;

&lt;p&gt;Und so bleiben meine beiden WinCE-Geräte eben WinCE-Geräte und verifizieren,
dass Software, die im Emulator lief, auch in der realen Welt lauffähig ist.&lt;/p&gt;

&lt;p&gt;Da diese Hardware heute nicht mehr produziert wird, bin ich froh sie noch
rechtzeitig gekauft zu haben. Und obwohl es sich um keine Rennpferde 
handelt bin ich dennoch beeindruckt, wie das ganze OS fix im RAM laufend
mit so wenig Ressourcen auskommt und dennoch ein vollständiges Windows UI
darstellen kann.&lt;/p&gt;

&lt;h3 id=&quot;nachtrag&quot;&gt;Nachtrag:&lt;/h3&gt;

&lt;p&gt;Und wie mein Laptop von Innen aussieht, hat bereits jemand auf YouTube 
ausgebreitet:&lt;/p&gt;

&lt;iframe width=&quot;640&quot; height=&quot;360&quot; src=&quot;/blog/redirect.html?https%3A%2F%2Fwww.youtube-nocookie.com%2Fembed%2Fj29pCTWkEVE&quot; frameborder=&quot;1&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
</content>
 </entry>
 
 <entry>
   <title>DIY: Crimp</title>
   <link href="https://www.opengate.at/blog/2023/06/crimp/"/>
   <published>2023-06-03T13:00:00+02:00</published>
   <updated>2023-06-03T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2023/06/crimp</id>
   <category term="hardware" />
   <summary type="text">So manches Board hat Anschlüsse für diverse Leiterplattensteckverbinder 
für die Stromzufuhr oder eine serielle Verbindung, doch es gibt kein 
Gegenstück, das da reinpasst.

An der Stelle muss man zur Crimpzange 
greifen und sich für die nötige Sockelgröße den richtigen Stecker selbst 
hinbiegen.
</summary>
   <content type="html">&lt;p&gt;So manches Board hat Anschlüsse für diverse Leiterplattensteckverbinder 
für die Stromzufuhr oder eine serielle Verbindung, doch es gibt kein 
Gegenstück, das da reinpasst.&lt;/p&gt;

&lt;p&gt;An der Stelle muss man zur &lt;a href=&quot;https://de.wikipedia.org/wiki/Crimpen&quot;&gt;Crimpzange&lt;/a&gt; 
greifen und sich für die nötige Sockelgröße den richtigen Stecker selbst 
hinbiegen.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Als ich mir damals vor 4 Jahren die Box mit den Steckkontakten zugelegt hatte,
dachte ich noch, ich könnte das mit meiner Adernendhülsenzange hinmurxen.
Im Endeffekt habe ich aber nur einige Stücke so verhundst, dass ich sie 
wegwerfen musste.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/crimp01.jpg&quot; alt=&quot;Crimp 1&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Man braucht also eine ordentliche Crimpzange, die mechanisch einrastet, damit
man die kleinen Hülsen einspannen kann, um die Ader einführen und fixieren zu
können.&lt;/p&gt;

&lt;p&gt;Die Rundhülsen, haben an einer Seite zwei Krallenstückpaare, die beim 
Crimpen die Ader und die Isolation festhalten.&lt;br /&gt;
Auf der anderen Seite befindet sich neben dem Pin-Kontakt ein kleiner
Zinken, der in dem Plastikstecker einrasten soll.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/crimp02.jpg&quot; alt=&quot;Crimp 2&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Die Kunst ist es also, die Hülse so in die Crimpzange einzuspannen, dass
nur die beiden Krallen umgebogen werden und das untere Steckteil unverändert
bleibt.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/crimp03.jpg&quot; alt=&quot;Crimp 3&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Hat man die Hülse korrekt in der Zange, muss nun die Ader genau so tief
eingeführt werden, dass die äußere Kralle die Isolierung zu fassen bekommt
und die innere Kralle mit den Litzen in Berührung kommt.&lt;br /&gt;
Stopft man die Ader zu tief hinein, stören die Litzen den Pin-Kontakt.&lt;br /&gt;
Hier gilt:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Übung macht den Meister … und mir fehlt noch viel Übung.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/crimp04.jpg&quot; alt=&quot;Crimp 4&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Doch nach ein paar Versuchen hat man zumindest eine brauchbare Verbindung
zwischen Ader und Hülse.&lt;br /&gt;
Und somit kann diese in den Stecker eingefügt werden.&lt;/p&gt;

&lt;p&gt;Sobald der keine Widerhaken am Ende eingerastet ist, sollte der Stecker
einigermaßen zugfest sitzen und kann als Stecker seinen Dienst aufnehmen.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/crimp05.jpg&quot; alt=&quot;Crimp 5&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Nachdem der Akku meines alten &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_CE&quot;&gt;Windows-CE&lt;/a&gt; 
Laptops schon vor Jahren kaputtgegangen ist und seither das Board einen unguten
Pfeifton abgibt, wenn kein Akku angeschlossen ist, wollte ich mal probieren, 
ob man den Lademechanismus durch einen Widerstand “zähmen” kann.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/crimpplug.jpg&quot; alt=&quot;Crimp Plug&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Und eben genau dafür brauchte ich nach langem wieder mal einen solche
Platinensteckverbindung.&lt;/p&gt;

&lt;p&gt;Früher hatte ich extra dafür Stecker und Kabel von Elektroschrott abgetrennt.
Doch es ist wesentlich “eleganter”, wenn man sich seinen Stecker selbst
zusammenbaut.&lt;/p&gt;

&lt;p&gt;Die Box mit je 10 mal 2 bis 5 Pin-Steckern kostete damals in Fernost nur 
wenige Euro. Heute wird das wohl mehr sein, ist aber immer noch günstig, denn 
man kann so eine Vielzahl an Steckern herstellen.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/crimpbox.jpg&quot; alt=&quot;Crimpbox&quot; /&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>getaddrinfo</title>
   <link href="https://www.opengate.at/blog/2023/05/getaddrinfo/"/>
   <published>2023-05-28T13:00:00+02:00</published>
   <updated>2023-05-28T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2023/05/getaddrinfo</id>
   <category term="devel" />
   <summary type="text">Die Funktion getaddrinfo() löst Funktionen wie gethostbyname()
oder gethostbyaddr() ab und ist quasi “die” Schnittstelle zur DNS
Auflösung eines Systems im Netzwerk.

Blöd nur, dass Windows 95 davon nichts wusste…
</summary>
   <content type="html">&lt;p&gt;Die Funktion &lt;code&gt;getaddrinfo()&lt;/code&gt; löst Funktionen wie &lt;code&gt;gethostbyname()&lt;/code&gt;
oder &lt;code&gt;gethostbyaddr()&lt;/code&gt; ab und ist quasi “die” Schnittstelle zur DNS
Auflösung eines Systems im Netzwerk.&lt;/p&gt;

&lt;p&gt;Blöd nur, dass Windows 95 davon nichts wusste…
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;fehlkonstruktion-gethostbyname&quot;&gt;Fehlkonstruktion gethostbyname&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;gethostbyname()&lt;/code&gt; ist auch eine von diesen dummen Funktionen, die C 
Programmen ihren schlechten Ruf beschert hat.
Hier wird nämlich das Ergebnis in einen Puffer im Hintergrund geschrieben,
den man nicht unter Kontrolle hat.&lt;br /&gt;
Im schlimmsten Fall ist es ein globaler Puffer, was bedeutet, dass nicht
zwei Threads die Funktion nicht gleichzeitig benutzen dürfen.&lt;/p&gt;

&lt;p&gt;Das kann man jetzt gerne über einen Mutex lösen, durch niemand weiß, ob
nicht eine Fremdbibliothek ebenso die Funktion aufruft und dort ohne
Mutex den Puffer bearbeitet.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;getaddrinfo()&lt;/code&gt; ist die flexibler Nachfolger-Funktion und allokiert 
separaten Speicher für jeden Aufruf. Außerdem erlaubt sie wesentlich 
mehr Optionen für die Hostnamen-Auflösung.&lt;/p&gt;

&lt;h3 id=&quot;warum-als-nicht-immer-getaddrinfo&quot;&gt;Warum als nicht immer getaddrinfo?&lt;/h3&gt;

&lt;p&gt;Tja, heute kein Thema. Jedes OS hat die Funktion integriert. Doch meine
(Support-)Welt beginnt in den 90ern, wo &lt;code&gt;getaddrinfo&lt;/code&gt; weder in Windows 
noch in den damaligen Unix-Derivaten garantiert vorhanden war.&lt;/p&gt;

&lt;p&gt;Aus diesem Grund findet man in meinen älteren Projekten nur Mutex-geschützte
&lt;code&gt;gethostbyname&lt;/code&gt; Aufrufe.&lt;/p&gt;

&lt;p&gt;Unter Windows wurde &lt;code&gt;getaddrinfo()&lt;/code&gt; mit Windows XP in die &lt;code&gt;ws2_32.dll&lt;/code&gt; integriert.
Windows 2000 und ältere Vertreter meldeten somit immer einen fehlenden 
Einsprungpunkt, wenn man sein Projekt gegen die Funktion linken ließ.&lt;/p&gt;

&lt;p&gt;Es gibt zwar den dokumentierten Verweis zur inline Funktion &lt;code&gt;WspiapiGetAddrInfo&lt;/code&gt;,
die &lt;code&gt;getaddrinfo&lt;/code&gt; dann über andere DLLs zu laden versucht, doch auch die sind
nur unter Windows 2000 mit bestimmten Preview-Updates vorhanden und nicht in
Standard-Installationen.&lt;br /&gt;
Windows 9x fällt übrigens generell flach bei dem Thema.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Heute baue ich in der Regel auf ein dynamisch geladenes &lt;code&gt;getaddrinfo()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Ist die Funktion im OS enthalten (also &lt;code&gt;LoadLibrary(&quot;ws2_32&quot;)&lt;/code&gt; oder 
&lt;code&gt;dlopen(NULL, RTLD_GLOBAL)&lt;/code&gt;), wird sie benutzt.&lt;br /&gt;
Wenn nicht, dann implementiere ich sie mit &lt;code&gt;gethostbyname&lt;/code&gt; provisorisch 
inklusive Mutex nach.&lt;/p&gt;

&lt;p&gt;Auf diese Weise kommen Binaries heraus, die überall gestartet werden können
und dann eben das heranziehen, was vorhanden ist.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Windows 2000 Update</title>
   <link href="https://www.opengate.at/blog/2023/05/win2k-update/"/>
   <published>2023-05-27T13:00:00+02:00</published>
   <updated>2023-05-27T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2023/05/win2k-update</id>
   <category term="software" /><category term="retro" />
   <summary type="text">Dass man Windows 2000 
auch noch mit dem aktuellen 
Windows Server Update Service 
 (WSUS) aktualisieren kann, hatte ich aus der Auflistung des Betriebssystems 
 im WSUS-Menü erschlossen.

Korrekt funktioniert hatte das dann aber nicht, sondern brach ab.

Tatsächlich liegt die Lösung nahe … wenn man sie kennt.
</summary>
   <content type="html">&lt;p&gt;Dass man &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_2000&quot;&gt;Windows 2000&lt;/a&gt; 
auch noch mit dem aktuellen 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_Server_Update_Services&quot;&gt;Windows Server Update Service&lt;/a&gt; 
 (WSUS) aktualisieren kann, hatte ich aus der Auflistung des Betriebssystems 
 im WSUS-Menü erschlossen.&lt;/p&gt;

&lt;p&gt;Korrekt funktioniert hatte das dann aber nicht, sondern brach ab.&lt;/p&gt;

&lt;p&gt;Tatsächlich liegt die Lösung nahe … wenn man sie kennt.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Das einzige was &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft&quot;&gt;Microsoft&lt;/a&gt; heute 
wirklich noch ein Alleinstellungsmerkmal beschert, ist sein langer Support 
und die meist vorhandene Abwärtskompatibilität.&lt;br /&gt;
Soll heißen:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Was gestern funktioniert hat, soll auch morgen noch funktionieren.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In Sachen Windows-Updates endet das Vergnügen meist nach dem Extended-Support 
nach 10 Jahren. Doch wer sich einen Windows Server leistet bekommt &lt;code&gt;WSUS&lt;/code&gt; 
gratis dazu, und der synchronisiert sich dann mit den MS-Fileservern, wo 
Updates für alle Ewigkeiten liegenbleiben … zumindest seit Windows 2000.&lt;/p&gt;

&lt;p&gt;Der erste Updateversuch eines älteren OS streikt meist und man muss manuell
einen neueren Windows Update Agent einspielen, doch danach finden 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_7&quot;&gt;Windows 7&lt;/a&gt; und 8 brav 
wieder ihre Aktualisierungen.&lt;/p&gt;

&lt;p&gt;Bei &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_XP&quot;&gt;Windows XP&lt;/a&gt; und 
Windows 2000 ist das nun aber leider nicht mehr so.
Bei XP fiel mir das nicht auf, weil ich ein aktualisiertes Image von 2020
nutze, in dem alles korrekt integriert war, aber meine Windows 2000 ISOs 
verweilten auf dem Stand von 2010 und da rührte sich nichts mehr.&lt;/p&gt;

&lt;p&gt;Jedenfalls benötigte ich für Windows 2000 die Version &lt;code&gt;6.1.22.4&lt;/code&gt; des Agents 
(&lt;code&gt;WindowsUpdateAgent30-x86.exe&lt;/code&gt;), denn die neueren Varianten verweigerten
bei der Erstinstallation die Durchführung des Setups.&lt;/p&gt;

&lt;p&gt;Man kann zwar per Registry manuell die Policy zum eigenen WSUS Server 
setzen:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;code&gt;WUServer&lt;/code&gt; = &lt;code&gt;http://my-wsus.domain:8530&lt;/code&gt; (string)&lt;/li&gt;
      &lt;li&gt;&lt;code&gt;WUStatusServer&lt;/code&gt; = &lt;code&gt;http://my-wsus.domain:8530&lt;/code&gt; (string)&lt;/li&gt;
      &lt;li&gt;&lt;code&gt;ElevateNonAdmins&lt;/code&gt; = &lt;code&gt;0x00000001&lt;/code&gt; (DWORD)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code&gt;HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;code&gt;UseWUServer&lt;/code&gt; = &lt;code&gt;0x00000001&lt;/code&gt; (DWORD)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Und danach meldet sich der Dienst sogar beim WSUS an (wird also in der UI
als Client sichtbar), kann aber keine Daten mit ihm austauschen.&lt;br /&gt;
Den Fehler findet man im Update-Agent Log&lt;br /&gt;
&lt;code&gt;C:\WINNT\SoftwareDistribution\ReportingEvents.log&lt;/code&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;800b0109	SelfUpdate	Failure	Software Synchronization	
Windows Update Client failed to detect with error 0x800b0109.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Das Problem liegt an den Root-Zertifikaten die der Verifizierung dienen.
Die sind nämlich schon lange abgelaufen und somit ist keine Aktualisierung
mehr möglich.&lt;/p&gt;

&lt;h3 id=&quot;lösung-neue-zertifikate-einspielen&quot;&gt;Lösung: Neue Zertifikate einspielen&lt;/h3&gt;

&lt;p&gt;Was für ein Glück, dass sich ein paar findige Leute im Netz die Mühe gemacht
haben und die notwendigen Zertifikatsteile zusammengesucht und erneuert haben.
Diese sind auf 
&lt;a href=&quot;https://github.com/JohnTHaller/RootCertificateUpdatesForLegacyWindows&quot;&gt;github.com/JohnTHaller&lt;/a&gt;
veröffentlicht und müssen am Zielsystem nur noch importiert werden.
Also &lt;code&gt;mmc.exe&lt;/code&gt; ← Snap-in &lt;code&gt;Certificates&lt;/code&gt; ← &lt;code&gt;Computer Account&lt;/code&gt; ←&lt;br /&gt;
&lt;code&gt;Trusted Root Certification Authorities/Certificates&lt;/code&gt; öffnen und die beiden 
&lt;code&gt;.sst&lt;/code&gt; Dateien importieren.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/win2k_import_certificates.png&quot; alt=&quot;Win2K-import-certificates&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Am Ende wird noch am besten der Update Dienst beendet.
Und ein &lt;code&gt;wuauclt /detectnow&lt;/code&gt; beginnt nun mit den neuen Zertifikaten mit der
WSUS-Kommunikation und dem Self-Update.&lt;/p&gt;

&lt;p&gt;Kurze Zeit später poppt auch schon das Update-Symbol in der Taskleiste auf
und dann ist die Welt wieder in Ordnung.&lt;/p&gt;

&lt;p&gt;Falls das nicht sofort funktioniert, helfen die Kommandos&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;wuauclt /resetauthentication&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;wuauclt /reportnow&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;und auch das Löschen des Ordners &lt;code&gt;c:\WINNT\SoftwareDistribution&lt;/code&gt; bei beendetem
Update-Dienst kann helfen, damit sich alles neue einrichtet.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;vorsicht-update-rollup-bluescreens&quot;&gt;Vorsicht: Update-Rollup Bluescreens!&lt;/h3&gt;

&lt;p&gt;Nach dem SP4 kamen für Windows 2000 noch über 100 weitere Updates heraus, die sich
alle per WSUS einspielen lassen.
Darunter ist auch das Update &lt;code&gt;KB891861&lt;/code&gt; mit dem Titel&lt;br /&gt;
“Update Rollup 1 for Windows 2000 Service Pack 4”.
Diese Teil zerstörte mir jede Installation, nachdem es einen Reboot-Bluescreen
Zyklus eingerichtet hatte.&lt;/p&gt;

&lt;p&gt;Aus eben diesem Grund habe ich das Update KB891861 in WSUS auf “Declined” 
gesetzt, damit ich es hoffentlich nie wieder sehen muss.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Zertifikate hatten für mich immer schon den Nachteil, dass sie ablaufen
(und ja ich weiß … das sollte eigentlich ein Vorteil sein).&lt;/p&gt;

&lt;p&gt;Denn egal wo man hinkommt, man findet immer nur Software-Scherbenhaufen vor,
wenn eine Firma oder ein Projekt aufgegeben wird und keiner mehr neue Zertifikate
für die Software anlegen will/kann/darf.&lt;/p&gt;

&lt;p&gt;Was meine “Windows-Kindheit” anbelangt freue ich mich, dass es zumindest noch
per Workaround eine Möglichkeit gibt, die Zertifikate zu aktualisieren und 
danach das OS auf den bestmöglichen Letztstand zu bringen.&lt;/p&gt;

&lt;p&gt;Ich hoffe, dass diese Möglichkeit noch einige Jahre bestehen bleibt, aber
nachdem Windows Server 2022 das Windows 2000 Produkt immer noch im WSUS listet,
erwarte ich, dass zumindest bis zum Ende des Standard-Supports so bleiben wird.&lt;/p&gt;

&lt;p&gt;Zumindest kann ich nun wieder behaupten, “ein aktuelles Windows 2000” in
Betrieb genommen zu haben.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Mutters Reise zum Rudolfsturm</title>
   <link href="https://www.opengate.at/blog/2023/05/hallstatt/"/>
   <published>2023-05-21T13:00:00+02:00</published>
   <updated>2023-05-21T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2023/05/hallstatt</id>
   <category term="general" />
   <summary type="text">In den letzten Jahren wandere ich gerne zu “Orten meiner Vergangenheit”, wo
ich vor 10 bis 15 Jahren wohnte oder arbeitete.

Dieses Wochenende durfte ich miterleben, wie es ist nach 50 Jahren einen
bekannten Ort wieder zu erleben.
Ich durfte Einblick nehmen, wo meine Mutter einen Teil ihrer Jugend 
verbrachte.
</summary>
   <content type="html">&lt;p&gt;In den letzten Jahren wandere ich gerne zu “Orten meiner Vergangenheit”, wo
ich vor 10 bis 15 Jahren wohnte oder arbeitete.&lt;/p&gt;

&lt;p&gt;Dieses Wochenende durfte ich miterleben, wie es ist nach 50 Jahren einen
bekannten Ort wieder zu erleben.&lt;br /&gt;
Ich durfte Einblick nehmen, wo meine Mutter einen Teil ihrer Jugend 
verbrachte.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Durch ein Ferialjob verschlug es meine Mutter vor 50 Jahren nach 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Hallstatt&quot;&gt;Hallstatt&lt;/a&gt; in den Gastbetrieb
am &lt;a href=&quot;https://de.wikipedia.org/wiki/Rudolfsturm&quot;&gt;Rudolfsturm&lt;/a&gt;. Und seit vielen
Jahren hörte ich sie von dieser schönen Jugenderfahrung schwärmen.&lt;br /&gt;
Es wurde also höchste Zeit, dass wir dem Turm am Berg hoch über dem 
Hallstätter See einen Besuch abstatten.&lt;/p&gt;

&lt;p&gt;Als Reisemuffel fürchtete ich vor allem die Anfahrt mit dem Auto und mein
Talent mich heillos zu verfahren. Doch wenn man es auf die A1 schafft 
(und zu der findet man in Niederösterreich immer), dann kann man die Abfahrt
bei Regau nach Gmunden, Bad Ischl, Bad Goisern und Hallstatt eigentlich gar
nicht verfehlen.&lt;br /&gt;
Und so gelang die Anreise zielgenau auf Anhieb und ohne Einsatz eines 
Navigationsgerätes oder Smartphones (und auf so etwas bin ich heutzutage 
stolz!).&lt;/p&gt;

&lt;p&gt;Der geplante Kurzurlaub sollte nur zwei Tage (also eine Übernachtung) 
dauern. Eine wirklich preiswerte und schöne Unterkunft fanden wir 
Bad Goisern, das nur wenige Kilometer vor Hallstatt entfernt liegt.&lt;/p&gt;

&lt;h3 id=&quot;auf-nach-bad-goisern-und-hallstatt&quot;&gt;Auf nach Bad Goisern und Hallstatt&lt;/h3&gt;

&lt;p&gt;Als wir uns nach dem Mittagessen in Bad Goisern gleich zum Ziel aufmachten, 
konnten wir live miterleben wie unglaublich überlaufen Hallstatt inzwischen ist. 
Alle großen Parkplätze war voll und gesperrt. Nur gelegentlich wenn 
andere Touristen aufbrachen und ein Stellplatz frei wurde, öffnete sich kurz
die Pforte um den einen freien Platz gleich wieder auszufüllen.&lt;/p&gt;

&lt;p&gt;Das Gerücht: &lt;em&gt;“Hallstatt sei in Asien bliebt”&lt;/em&gt; ist eine Untertreibung.&lt;br /&gt;
Man hatte eher den Eindruck: “In China kann es jetzt keine Chinesen mehr geben”.
Tatsächlich waren die Straßen und Gassen voll mit Touristen aus Asien und
jede halbe Stunde kam ein neuer Bus an, der weitere Besucher brachte.
Doch eines steht auch fest: So fließt jede Menge Geld in die kleine Stadt.&lt;/p&gt;

&lt;p&gt;Mutter erkannte den Ort Hallstatt kaum wieder, da (wie in solchen
Touristenhochburgen üblich) ein Souveniergeschäft dem anderen folgte.
Das war vor 50 Jahren noch ganz anders.&lt;/p&gt;

&lt;p&gt;Doch in einer hinteren Seitengasse trafen wir dann auf zwei einheimische
ältere Damen und ich konnte mitverfolgen, wie Mutter im Gespräch mit den
beiden wieder jung wurde.&lt;br /&gt;
Ja … vieles hat sich verändert seit damals und aus der keinen 
Dorfgemeinschaft wurde ein Tourismuszentrum. Doch auch wenn die
Anwohner den extremen Ansturm nicht immer genießen, so haben sie besonders
in der Pandemie festgestellt, wie wichtig dieser Zustrom ist und folglich
schätzen sie die Gäste auch.&lt;/p&gt;

&lt;p&gt;Stets im Blickfeld war die Bergbahn, die zum Rudolfsturm führte, doch
diesen wollten wir erst am zweiten Tag besuchen.&lt;br /&gt;
So streiften wir noch kurz durch die Straßen und machten uns am Abend
auf zur Herberge, wo wir mit Blick auf die umgebenden Berge am Balkon über
das Gesehene diskutierten.&lt;/p&gt;

&lt;h3 id=&quot;der-rudolfsturm&quot;&gt;Der Rudolfsturm&lt;/h3&gt;

&lt;p&gt;Nach einem köstlichen Frühstück um 8:00 fuhren wir sogleich von Bad Goisern
nach Hallstatt um pünktlich um 9:00 Uhr bei der ersten Bergfahrt dabei zu sein.
Die Strategie war gut, denn am Morgen waren noch die Hälfte der Parkplätze frei.&lt;/p&gt;

&lt;p&gt;Mutter erzählte von einer Seilbahn mit 4 Plätzen, die permanent gegengleich
zwei Kabinen zwischen Berg und Tal hin und herbewegte. Täglich musste sie so
mit anderen Dienstmädchen Verpflegung zum hoch gelegenen Rudolfsturm bringen.&lt;/p&gt;

&lt;p&gt;Heute fahren zwei Bergbahn-Gondeln auf Schienen den gleichen Weg, können aber
wesentlich mehr Personen transportieren. Es finden etwa 15 Personen darin 
Platz und alle 15 Minuten beginnt eine neue Fahrt.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/hallstatt-salzbergbahn.jpg&quot; alt=&quot;Hallstatt-Salzbergbahn&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Direkt neben der Bergbahnstation liegt auch der Rudolfsturm, doch
diesen hoben wir uns fürs Mittagessen auf.&lt;/p&gt;

&lt;p&gt;Wir folgten dem Wanderweg bergauf, der zur Salzmine führte. Im dortigen Haus
(damals als Salinenhaus bekannt) war nämlich das Personal des Rudolfturms 
untergebracht und so gingen wir genau den Weg entlang, den Mutter mit ihren
Kolleginnen täglich hin und herlaufen mussten. &lt;br /&gt;
Man merkt, dass die steile Strecke im Alter anstrengender ist … doch die
Umgebung mit den blühenden Wiesen und der kühlen Bergluft machten diesen
Spaziergang zu einem schönen Nostalgieerlebnis.&lt;/p&gt;

&lt;p&gt;Beim Salinenhaus angekommen rasteten wir auf einer der Bänke. 
Und während andere Touristen in die Salzmine drängten, erfuhr ich manch
lustige Geschichte von damals, als diese Gegend nur von einigen Arbeitern
aufgesucht wurde.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/hallstatt-salinenhaus.jpg&quot; alt=&quot;Hallstatt-Salinenhaus&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Beim Rückweg zum Rudolfsturm trafen wir dann unverhofft auf das Highlight
des Tages: Einen Archäologen.&lt;br /&gt;
Der “Kerl” war mit seinem Team in einem der dort angrenzenden Häusern 
untergebracht und in einem zufällig gestarteten Gespräch, erzählte er uns,
wie er mit seinen Kollegen Grabungen vornahm und welche Schätze im reichen
Ort Hallstatt bereits gefunden wurden.&lt;/p&gt;

&lt;p&gt;Es war beeindruckend einem Fachmann gegenüberzustehen, dem man die 
Bewunderung für die Hallstätter Kultur und deren Geschichte in jedem
Satz anmerken konnte. Und es ist auch beeindruckend zu erfahren, wie
bereits Menschen in der Steinzeit die Orte bewohnten und bebauten,
die wir heute zur Sommerfrische nutzen.&lt;/p&gt;

&lt;p&gt;Pünktlich zur Mittagszeit waren wir wieder zurück beim Rudolfsturm
und nachdem Mutter damals unzählige Gäste dort hatte bewirten
dürfen, so wurden wir an diesem Tag ebenso hervorragend verköstigt.&lt;/p&gt;

&lt;p&gt;Mutter bemerkte schnell, dass dem Turm ein Gebäudeteil fehlte und
so fanden wir im Internet den Bericht, dass um 2007 der hintere 
Teil unter Schneedruck eingestürzt war und das Anwesen umgebaut wurde. 
Die heutige hintere offene Terrasse, auf der wir zu Tisch saßen war früher 
ein geschlossener Speisesaal.&lt;/p&gt;

&lt;p&gt;Ein besonderes Highlight war außerdem, dass wir die Erlaubnis erhielten,
kurz einen Blick in die oberen Räume werfen zu dürfen.&lt;br /&gt;
Damals waren dort Gästezimmer für Besucher vorhanden, heute sind diese
offen und eine Erweiterung des Gastronomiebereiches.&lt;/p&gt;

&lt;p&gt;Die Möblierung hat sich vollständig geändert … und doch sind einige
Teile wie die Holzverkleidung an den Wänden und Ecken offenbar noch
im Original erhalten.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/hallstatt-rudolfsturm.jpg&quot; alt=&quot;Hallstatt-Rudolfsturm&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;eine-schöne-erinnerung&quot;&gt;Eine schöne Erinnerung&lt;/h3&gt;

&lt;p&gt;Zu meinen größten Freuden dieses Jahr wird ganz bestimmt dieser Besuch
in Hallstatt zählen, denn ich habe meine Mutter schon lange nicht mehr
so “jung” lachen gesehen.&lt;br /&gt;
Ich konnte in ihren Augen sehen, wie wichtig solche Fixpunkte im Leben
sind und wie unglaublich schön es ist, wenn solche alte Erinnerungen wieder
lebendig werden.&lt;/p&gt;

&lt;p&gt;Aus einem:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Naja, warum nicht mal dorthin, wo du früher schon mal warst.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;wurde unerwartet ein Besuch einer der schönsten Flecken unseres Landes
und gleichzeitig eine Erinnerung voller Freuden, die ich selbst zwar nicht
erlebt habe, aber trotzdem habe ich sie nun gespürt.&lt;/p&gt;

&lt;p&gt;Die Heimreise wurde bereichert von einem sonnigen Panorama zwischen Ober-
und Niederöstereich und wurde untermalt von einem langen Gespräch über
Gott, die Welt, Liebe und Leben … und der schönen Zeit in Hallstatt.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Auslöser für diese Reise war eine Mappe mit Erinnerungsfotos und Zeichnungen,
die meine Mutter vor 50 Jahren angelegt hat.&lt;br /&gt;
Diese Mappe lag die ganze Zeit in einer Lade im Wohnzimmer.&lt;/p&gt;

&lt;p&gt;Und vor einigen Wochen, als sie zufällig geöffnet wurde, bildete sie plötzlich
einen Anker in die Vergangenheit, die Mutter und mich an diesen Ort und in 
diese Zeit zurückgeführt hat.&lt;/p&gt;

&lt;p&gt;Ich habe daraus gelernt, dass es solche “kleinen Dinge” sind, die später 
eine ungeahnt große Wirkung haben können.
Ein “gutes Foto” kann die Erinnerungen an einen Ort, ein Ereignis, einen 
Freund aufleben lassen, auch wenn das Original inzwischen verblasst ist.&lt;/p&gt;

&lt;p&gt;Wir hätten die teuersten Konzert- oder Theaterkarten haben können, im
luxoriösesten Palast dinieren können … aber nichts wäre so schön
gewesen, wie auf der Bergbank zu sitzen und einfach nur über die 
Vergangenheit zu reden.&lt;/p&gt;

&lt;p&gt;Und am Ende war es ein Blatt Papier, das ein Portal in diese andere Zeit
geöffnet hat, ganz ohne Technik, Kabel und Spezialeffekte.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Windows Downgrade</title>
   <link href="https://www.opengate.at/blog/2023/05/win-downgrade/"/>
   <published>2023-05-14T13:00:00+02:00</published>
   <updated>2023-05-14T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2023/05/win-downgrade</id>
   <category term="software" />
   <summary type="text">Auf meinen Intel-Atom Boards 
fällt es mir leider ganz deutlich auf:


  Man kann mit Windows 10 einfach nicht arbeiten 
… alles ist so verdammt langsam.


Doch … komisch … das war vor ein paar Jahren noch ganz anders.

</summary>
   <content type="html">&lt;p&gt;Auf meinen &lt;a href=&quot;https://de.wikipedia.org/wiki/Intel_Atom&quot;&gt;Intel-Atom&lt;/a&gt; Boards 
fällt es mir leider ganz deutlich auf:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Man kann mit Windows 10 einfach nicht arbeiten 
… alles ist so verdammt langsam.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Doch … komisch … das war vor ein paar Jahren noch ganz anders.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Seit seinem ersten Release im Jahr 2015 hat sich 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_10&quot;&gt;Windows 10&lt;/a&gt; ordentlich 
weiterentwickelt. Das betrifft auch seine Größe. Anfangs kam man mit 
einer 2,5 bis max. 3 GB &lt;code&gt;install.wim&lt;/code&gt; aus, 
heute ist das auf 3,9 GB gestiegen und mit den letzten Updates kommt
man auch schon über die magische 4 GB Grenze drüber (und muss die &lt;code&gt;.wim&lt;/code&gt;
aufsplitten).&lt;/p&gt;

&lt;p&gt;Ein größeres OS bedeutet längere Ladezeiten, denn Standard-DLLs haben ebenso
an Speck zugelegt. Neue Features, die automatisch aktiviert sind fressen 
ebenso Platz auf Disk und RAM auf.&lt;br /&gt;
&lt;strong&gt;Und genau das macht meine kleinen Intel-Atom Maschinen träge.&lt;/strong&gt;&lt;/p&gt;

&lt;h3 id=&quot;windows-8-&quot;&gt;Windows 8 ?&lt;/h3&gt;

&lt;p&gt;Teilweise habe ich auch wieder die originalen 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_8&quot;&gt;Windows 8/8.1&lt;/a&gt; Installationen
ausprobiert, mit denen die Baytrail Boards von 2013 bis 2016 ausgeliefert
wurden. Der größte Haken sind die inzwischen defekten Online-Tools wie
die Mail-App, ein nicht mehr funktionierender Store und der nicht mehr
korrekt laufende Windows-Update-Mechanismus.&lt;/p&gt;

&lt;p&gt;Zwar kann man mit &lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_Server_Update_Services&quot;&gt;WSUS&lt;/a&gt;,
Offline-Integration und viel Geduld ein Image teilweise hochpatchen, doch da
z.B.: keine Zertifikatsupdates mehr durchgeführt werden, degeneriert das
System leider mehr und mehr.&lt;/p&gt;

&lt;h3 id=&quot;lösung-windows-10-enterprise-1607&quot;&gt;Lösung: Windows 10 Enterprise 1607&lt;/h3&gt;

&lt;p&gt;Als MSDN Abonnent bekommt man auch die Enterprise Versionen beigelegt, die
einen relevanten Vorteil haben: Sie werden 10 Jahre voll unterstützt.&lt;br /&gt;
Soll heißen, das OS von 2016 bekommt bis 2026 garantiert Support und danach
werden vermutlich die Updateserver auch noch (hoffentlich) etwas weiterlaufen.&lt;/p&gt;

&lt;p&gt;Ein Nachteil sind fehlende Store-Apps … doch dafür kenne ich ja bereits 
&lt;a href=&quot;/blog/2021/06/ltsb-store/&quot;&gt;eine Lösung&lt;/a&gt;.&lt;/p&gt;

&lt;h4 id=&quot;update-integration&quot;&gt;Update Integration&lt;/h4&gt;

&lt;p&gt;Meine Vorgehensweise ist wie immer:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;OS in VM installieren&lt;/li&gt;
  &lt;li&gt;Standard Windows Update durchführen&lt;/li&gt;
  &lt;li&gt;KB - Nummern der Updates heraussuchen und diese manuell herunterladen&lt;/li&gt;
  &lt;li&gt;Updates ins Windows &lt;code&gt;.wim&lt;/code&gt; Installationsimage integrieren&lt;/li&gt;
  &lt;li&gt;Fertig&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Natürlich funktioniert das nicht … denn Microsoft schafft es immer
mit ihren “späten” Updates, den Integrationsprozess zu versauen.&lt;/p&gt;

&lt;p&gt;Soll heißen: Von 5 großen Updates bricht das letzte (nämlich das Rollup 2023)
ab und hinterlässt ein defektes Image.&lt;/p&gt;

&lt;p&gt;Folglich habe ich eben dieses letzte Update nicht integriert sondern dem
Setup-Image separat als &lt;code&gt;.msu&lt;/code&gt; beigelegt.&lt;br /&gt;
Wird Windows installiert, muss man dieses letzte Update eben am Ende manuell
ausführen.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Klingt komisch … ist aber so … und funktioniert dann auch.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4 id=&quot;apps-und-konfiguration&quot;&gt;Apps und Konfiguration&lt;/h4&gt;

&lt;p&gt;Windows Update holt am Ende noch die neuesten Defender-Updates und somit hat 
man ein halbwegs “gepatchtes” Windows, aber eben mit dem API Stand von 2016.&lt;/p&gt;

&lt;p&gt;Einen weiteren Performance-Boost bekomme ich dann noch auf einigen Maschinen
durch das Deaktivieren des Defender-Dienstes.&lt;br /&gt;
(Powershell: &lt;code&gt;Uninstall-WindowsFeature Windows-Defender&lt;/code&gt;)&lt;/p&gt;

&lt;p&gt;Das tue ich natürlich nur auf Geräten, die mit dem Internet nur spärlich in
Berührung kommen, wie z.B.: auf einem alten Tablet, dass sich einfach über
der Lötstation an die Wand genagelt habe.&lt;br /&gt;
Dort kann mir das Teil Pläne anzeigen, Widerstand-Farbringe aufschlüsseln
oder Podcasts abspielen.&lt;/p&gt;

&lt;p&gt;Auf solchen Geräten ist ein permanenter Scan der Dateien nach Viren nicht
notwendig … und nachdem einige ältere Hardware bei mir solche 
Teiljobs im “gesicherten Wohnzimmer” ableistet, gestatte ich mir auf eben
solchen Geräten die Entfernung einiger Web-Kondome.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ja … das ältere Windows ist schneller, braucht etwas weniger RAM und
zuckelt nicht ewig herum, wenn man einfach nur den Explorer öffnen will.&lt;/p&gt;

&lt;p&gt;Mein “gefühlter” Eindruck ist also weiter “gefühlt” richtig:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Man sollte Geräte mit dem OS-Stand betreiben, mit dem es ausgeliefert wurde.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ein Windows 10 22H2 trägt de facto schon ein halbes Windows 11 in sich,
dass laut Hardwareanforderungen auf alten Atom-System nicht lauffähig ist.
Man kann also nur sagen: Windows funktioniert, aber “laufen” tut es nicht.&lt;/p&gt;

&lt;p&gt;Mit dem alten Enterprise 1607 habe ich also für die nächsten 3 Jahre ein
Image, mit dem&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Kleinigkeiten erledigt werden können,&lt;/li&gt;
  &lt;li&gt;einige modernere Apps unterstützt sind,&lt;/li&gt;
  &lt;li&gt;und die Performance trotzdem noch akzeptabel ist.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Kurz gesagt: &lt;em&gt;“Genau, was ich wollte.”&lt;/em&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>HAIKU, früher ZETA, früher BeOS</title>
   <link href="https://www.opengate.at/blog/2023/05/haiku/"/>
   <published>2023-05-13T13:00:00+02:00</published>
   <updated>2023-05-13T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2023/05/haiku</id>
   <category term="retro" />
   <summary type="text">Ich trauere einem Projekt der 90er sehr hinterher, nämlich dem alternativen
Betriebssystem BeOS.

Da wir heute nur noch Windows 
und Unix Derivate im freien Feld finden
(und gelegentlich mal ein RTOS 
auf ‘ner MCU), ist das kreative Potential bei der OS Entwicklung auf 
Null gefallen.
</summary>
   <content type="html">&lt;p&gt;Ich trauere einem Projekt der 90er sehr hinterher, nämlich dem alternativen
Betriebssystem &lt;a href=&quot;https://de.wikipedia.org/wiki/BeOS&quot;&gt;BeOS&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Da wir heute nur noch &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows&quot;&gt;Windows&lt;/a&gt; 
und &lt;a href=&quot;https://de.wikipedia.org/wiki/Unix&quot;&gt;Unix&lt;/a&gt; Derivate im freien Feld finden
(und gelegentlich mal ein &lt;a href=&quot;https://de.wikipedia.org/wiki/Echtzeitbetriebssystem&quot;&gt;RTOS&lt;/a&gt; 
auf ‘ner MCU), ist das kreative Potential bei der OS Entwicklung auf 
Null gefallen.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Da es um das Jahr 2000 noch kein Internet in meinen Breiten gab (oder nur ein 
nicht-leistbares), waren Beilage-CDs diverser Computer-Magazine, die einzige 
Möglichkeit an neue Software zu gelangen.&lt;br /&gt;
Neben gefühlt 1000 Varianten von Geld- und Terminplanern, wie diversen
Office-Zusätzen erhielt man so primär auch noch Updates für die aktuellen
Windows Versionen.&lt;/p&gt;

&lt;p&gt;Nach und nach schaffte es dann auch noch Linux auf diese Weise publiziert
zu werden, aber dann war auch schon Schluss.&lt;/p&gt;

&lt;p&gt;Ein Perle habe ich jedoch neulich wieder gefunden, nämlich eine CD
mit dem damals neuen Betriebssystem BeOS.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/beos_cd1999.jpg&quot; alt=&quot;BeOS CD&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;das-multimedia-os-beos&quot;&gt;Das Multimedia-OS BeOS&lt;/h3&gt;

&lt;p&gt;Mir wurde BeOS von einem Schulkollegen damals so präsentiert:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Das ist wie Windows nur viel besser für Multimedia.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Obgleich ich das Attribut “besser” sofort anzweifelte, musste ich
nach der ersten Test-Installation zugestehen, dass in mehreren
Fenstern Videodateien abgespielt werden konnten, was unter 
Windows 98 “gerade mal so” möglich war auf der damaligen 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Intel_Pentium&quot;&gt;Pentium-1&lt;/a&gt; Hardware.&lt;/p&gt;

&lt;p&gt;BeOS ist ähnlich wie Windows ein primär grafisches Betriebssystem und 
optimiert daher seine Schnittstellen auf die Darstellung von UI Elementen. 
Es ist damit das genaue Gegenteil von Unix und Linux, die primär Datenströme
verwalten und wo UIs erst als Beiwagen im Usermode nachgereicht wird.&lt;/p&gt;

&lt;p&gt;Doch im Gegensatz von Windows zog BeOS auch schon damals nicht
den fetten Rattenschwanz von DOS und Win3x Kompatibilität 
hinterher, sondern kümmerte sich nur um seine Kernkompetenz.&lt;/p&gt;

&lt;p&gt;Da auch damals schon eine &lt;a href=&quot;https://de.wikipedia.org/wiki/Transmission_Control_Protocol&quot;&gt;TCP/IP&lt;/a&gt; 
Anbindung ans Netz und Tools wie Mailclient und Browser dabei waren, sah es 
so aus, als könnte sich das neue OS tatsächlich gegen die bestehende 
Schar beweisen.&lt;/p&gt;

&lt;p&gt;Eine Eigenschaft die heute als Nachteil ausgelegt wird, war die 
Single-User-Strategie. BeOS kannte keine Benutzeraccounts und verzichtete
auf ein Berechtigungsmodell für Zugriffe auf Ressourcen und Dateien.
Das macht das System natürlich (ähnlich wie DOS) schnell, verhinderte aber
den Einsatz im Unternehmensbereich, wo unterschiedliche Nutzerprofile eine
wichtige Anforderung darstellen.&lt;/p&gt;

&lt;h3 id=&quot;c-als-kernsprache&quot;&gt;C++ als Kernsprache&lt;/h3&gt;

&lt;p&gt;Damals war es revolutionär: BeOS nutzt &lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B&quot;&gt;C++&lt;/a&gt; 
als Primärsprache, und nicht reines C. Während Windows und Linux bis heute auf
C Funktionen als Schnittstellen aufsetzen, wählte BeOS den rein 
objektorientierten Ansatz und baute sein UI Framework nur auf C++ Klassen auf.&lt;/p&gt;

&lt;p&gt;Daraus ergibt sich einerseits ein wesentlich eleganteres Codedesign, aber
leider auch eine Abhängigkeit zum C++ ABI des eingesetzten Compilers.
Somit war der Stand des GCC v2.x fix mit BeOS verdrahtet, was damals OK 
war, im Nachhinein aber Erweiterungen schwer machte.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;BeOS endete mit dem Ende des Unternehmens, welches es anfangs entwickelt
hatte. Und da auch die Stärke einer Linux-Community fehlte, verschwand
BeOS wieder von den Heft-CDs und geriet in Vergessenheit.&lt;/p&gt;

&lt;p&gt;Ich erinnere mich, dass Anfang der 2000er noch Shopping-Kanäle im 
Kabelfernsehen den Nachfolger “Zeta-OS” zum Kauf anboten, was dem 
Ansehen meines Erachtens eher schadete.&lt;/p&gt;

&lt;p&gt;Heute existiert zum Glück as &lt;a href=&quot;https://de.wikipedia.org/wiki/Haiku_(Betriebssystem)&quot;&gt;HaikuOS&lt;/a&gt; 
Projekt, welches BeOS als Open Source Software nachbaut und bis heute aktiv ist.&lt;/p&gt;

&lt;p&gt;Ich würde mir sehr wünschen, dass BeOS bzw. Haiku wieder zu den aktuellen
Systemen aufschließt und somit eine Alternative zu unseren Windows und
Linux-Monokulturen bereitstellt.&lt;/p&gt;

&lt;p&gt;Das Schnittstellendesign ist gut obwohl bzw. weil es sich von der WinAPI
und &lt;a href=&quot;https://de.wikipedia.org/wiki/POSIX&quot;&gt;POSIX&lt;/a&gt; unterscheidet. Trotzdem 
existieren viele Portierung von POSIX APIs auf BeOS/Haiku, womit zahlreiche 
moderne Softwarepakte auch unter BeOS/Haiku angeboten werden können.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Also Leute: Nutzt BeOS!&lt;br /&gt;
Wir brauchen mehr Diversität im Betriebssystembereich!&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>Optionale V-Tables</title>
   <link href="https://www.opengate.at/blog/2023/05/opt-vtbl/"/>
   <published>2023-05-07T13:00:00+02:00</published>
   <updated>2023-05-07T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2023/05/opt-vtbl</id>
   <category term="devel" />
   <summary type="text">Microsoft führte vor langer Zeit 
mit __declspec(novtable) eine interessante Erweiterung in den 
MSVC ein, um dem Problem 
der aufgeblasenen COM
DLLs zu begegnen.

Andere Compiler kennen und brauchen das nicht …
… außer man baut sich seine eigenen COM-artigen Objekte und deren
V-Tables zusammen.
</summary>
   <content type="html">&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft&quot;&gt;Microsoft&lt;/a&gt; führte vor langer Zeit 
mit &lt;code&gt;__declspec(novtable)&lt;/code&gt; eine interessante Erweiterung in den 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_C%2B%2B&quot;&gt;MSVC&lt;/a&gt; ein, um dem Problem 
der aufgeblasenen &lt;a href=&quot;https://de.wikipedia.org/wiki/Component_Object_Model&quot;&gt;COM&lt;/a&gt;
DLLs zu begegnen.&lt;/p&gt;

&lt;p&gt;Andere Compiler kennen und brauchen das nicht …&lt;br /&gt;
… außer man baut sich seine eigenen COM-artigen Objekte und deren
&lt;a href=&quot;https://de.wikipedia.org/wiki/Tabelle_virtueller_Methoden&quot;&gt;V-Tables&lt;/a&gt; zusammen.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Selbst bei bester Optimierung fallen mir in den &lt;code&gt;.map&lt;/code&gt; Dateien von Builds
viele Funktionen auf, die in einem statische Programm nicht 
enthalten sein dürften.&lt;br /&gt;
Bei genauerem Hinsehen entpuppten sich Aufrufe dieser Funktionen als Teil 
von C-V-Table-Objekt-Methoden, die selbst nie benutzt wurden.&lt;/p&gt;

&lt;p&gt;Besonders in &lt;code&gt;watcom&lt;/code&gt; unter &lt;code&gt;DOS&lt;/code&gt; ist das lästig, wenn mehrere Kilobytes
an Code in der EXE landen, die gar nicht gebraucht werden.&lt;/p&gt;

&lt;h3 id=&quot;v-table-initialisierung&quot;&gt;V-Table Initialisierung&lt;/h3&gt;

&lt;p&gt;C Objekte sahen bei mir (ganz ähnlich zu COM) etwa so aus:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;static&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; method_1_impl(&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;* self, &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; param);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;static&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; method_2_impl(&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;* self, &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; param1, &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; param2);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;typedef&lt;/span&gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;struct&lt;/span&gt; 
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; (*method_1)(&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;* self, &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; param);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; (*method_2)(&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;* self, &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; param1, &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; param2);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;} my_vtbl_t;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;static&lt;/span&gt; my_vtbl_t &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt; my_vtbl = 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;  &amp;amp;method_1_impl,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;  &amp;amp;method_2_impl
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;}; &lt;span style=&quot;color:#777&quot;&gt;/* init V-Table in global scope */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;typedef&lt;/span&gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;struct&lt;/span&gt; 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;  my_vtbl_t &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt;* vtbl;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n21&quot; name=&quot;n21&quot;&gt;21&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; private_member_1;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n22&quot; name=&quot;n22&quot;&gt;22&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; private_member_2;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n23&quot; name=&quot;n23&quot;&gt;23&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n24&quot; name=&quot;n24&quot;&gt;24&lt;/a&gt;&lt;/span&gt;} my_object_t;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n25&quot; name=&quot;n25&quot;&gt;25&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n26&quot; name=&quot;n26&quot;&gt;26&lt;/a&gt;&lt;/span&gt;my_object_t* my_object_constructor()
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n27&quot; name=&quot;n27&quot;&gt;27&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n28&quot; name=&quot;n28&quot;&gt;28&lt;/a&gt;&lt;/span&gt;  my_object_t* obj = malloc(&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;sizeof&lt;/span&gt;(my_object_t));
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n29&quot; name=&quot;n29&quot;&gt;29&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n30&quot; name=&quot;n30&quot;&gt;30&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  obj-&amp;gt;vtbl = &amp;amp;my_vtbl;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n31&quot; name=&quot;n31&quot;&gt;31&lt;/a&gt;&lt;/span&gt;  obj-&amp;gt;private_member_1 = &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n32&quot; name=&quot;n32&quot;&gt;32&lt;/a&gt;&lt;/span&gt;  obj-&amp;gt;private_member_2 = &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n33&quot; name=&quot;n33&quot;&gt;33&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n34&quot; name=&quot;n34&quot;&gt;34&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; obj;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n35&quot; name=&quot;n35&quot;&gt;35&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Nachdem die statische &lt;code&gt;my_vtbl&lt;/code&gt; Variable mit den beiden 
Methodenimplementierungen &lt;code&gt;method_1_impl&lt;/code&gt; und &lt;code&gt;method_2_impl&lt;/code&gt; initialisiert
wurde, ist deren Code und Aufruf-Baum vollständig im Programm integriert, auch
wenn &lt;code&gt;my_object_constructor&lt;/code&gt; nicht aufgerufen wird.&lt;/p&gt;

&lt;p&gt;Dieses Problem löste ich nun über einen neuen Ansatz der Initialisierung.&lt;/p&gt;

&lt;h3 id=&quot;v-table-konstruktor-funktion&quot;&gt;V-Table Konstruktor-Funktion&lt;/h3&gt;

&lt;p&gt;Anstatt die V-Table statisch initialisieren zu lassen, wird im Konstruktor
geprüft, ob der anfangs ausgenullte Speicher schon befüllt ist.&lt;br /&gt;
Falls nicht, wird die V-Table auf dem Stack erzeugt und dann in die globale
V-Table kopiert:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;static&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; method_1_impl(&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;* self, &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; param);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;static&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; method_2_impl(&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;* self, &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; param1, &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; param2);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;typedef&lt;/span&gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;struct&lt;/span&gt; 
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; (*method_1)(&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;* self, &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; param);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; (*method_2)(&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;* self, &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; param1, &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; param2);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;} my_vtbl_t;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;static&lt;/span&gt; my_vtbl_t &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt; my_vtbl = 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;  &amp;amp;method_1_impl,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;  &amp;amp;method_2_impl
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;};
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;static&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt; init_my_vtbl()
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt;(my_vtbl.method_1 == &lt;span style=&quot;color:#069&quot;&gt;NULL&lt;/span&gt;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n21&quot; name=&quot;n21&quot;&gt;21&lt;/a&gt;&lt;/span&gt;    my_vtbl_t local_vtbl = 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n22&quot; name=&quot;n22&quot;&gt;22&lt;/a&gt;&lt;/span&gt;    {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n23&quot; name=&quot;n23&quot;&gt;23&lt;/a&gt;&lt;/span&gt;      &amp;amp;method_1_impl,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n24&quot; name=&quot;n24&quot;&gt;24&lt;/a&gt;&lt;/span&gt;      &amp;amp;method_2_impl
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n25&quot; name=&quot;n25&quot;&gt;25&lt;/a&gt;&lt;/span&gt;    };
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n26&quot; name=&quot;n26&quot;&gt;26&lt;/a&gt;&lt;/span&gt;    my_vtbl = local_vtbl;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n27&quot; name=&quot;n27&quot;&gt;27&lt;/a&gt;&lt;/span&gt;  }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n28&quot; name=&quot;n28&quot;&gt;28&lt;/a&gt;&lt;/span&gt;}
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n29&quot; name=&quot;n29&quot;&gt;29&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n30&quot; name=&quot;n30&quot;&gt;30&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;typedef&lt;/span&gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;struct&lt;/span&gt; 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n31&quot; name=&quot;n31&quot;&gt;31&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n32&quot; name=&quot;n32&quot;&gt;32&lt;/a&gt;&lt;/span&gt;  my_vtbl_t &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt;* vtbl;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n33&quot; name=&quot;n33&quot;&gt;33&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n34&quot; name=&quot;n34&quot;&gt;34&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; private_member_1;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n35&quot; name=&quot;n35&quot;&gt;35&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; private_member_2;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n36&quot; name=&quot;n36&quot;&gt;36&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n37&quot; name=&quot;n37&quot;&gt;37&lt;/a&gt;&lt;/span&gt;} my_object_t;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n38&quot; name=&quot;n38&quot;&gt;38&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n39&quot; name=&quot;n39&quot;&gt;39&lt;/a&gt;&lt;/span&gt;my_object_t* my_object_constructor()
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n40&quot; name=&quot;n40&quot;&gt;40&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n41&quot; name=&quot;n41&quot;&gt;41&lt;/a&gt;&lt;/span&gt;  my_object_t* obj = malloc(&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;sizeof&lt;/span&gt;(my_object_t));
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n42&quot; name=&quot;n42&quot;&gt;42&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n43&quot; name=&quot;n43&quot;&gt;43&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;/* init V-Table in first constructor call: */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n44&quot; name=&quot;n44&quot;&gt;44&lt;/a&gt;&lt;/span&gt;  init_my_vtbl(); 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n45&quot; name=&quot;n45&quot;&gt;45&lt;/a&gt;&lt;/span&gt;  obj-&amp;gt;vtbl = &amp;amp;my_vtbl;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n46&quot; name=&quot;n46&quot;&gt;46&lt;/a&gt;&lt;/span&gt;  obj-&amp;gt;private_member_1 = &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n47&quot; name=&quot;n47&quot;&gt;47&lt;/a&gt;&lt;/span&gt;  obj-&amp;gt;private_member_2 = &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n48&quot; name=&quot;n48&quot;&gt;48&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n49&quot; name=&quot;n49&quot;&gt;49&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; obj;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n50&quot; name=&quot;n50&quot;&gt;50&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Da die Verknüpfung der V-Table mit den Methoden jetzt in einer Funktion
stattfindet und nicht mehr statisch auf globaler Ebene, schaffen es nun alle
Compiler, den ganzen Aufrufbaum wegzuoptimieren, wenn 
&lt;code&gt;my_object_constructor()&lt;/code&gt; nie aufgerufen wird.&lt;/p&gt;

&lt;h3 id=&quot;optimierungspotential&quot;&gt;Optimierungspotential&lt;/h3&gt;

&lt;p&gt;V-Tables kommen im GATE Projekt vor allem bei Streams und “Runnables” für
Threads vor. Jeder Kompressionsalgorithmus ist als Encoder-/Decoder-Stream
verfügbar und das bedeutet, dass automatisch immer alle einkompiliert werden,
sobald gegen die &lt;code&gt;gateencode&lt;/code&gt; Bibliothek gelinkt wird.&lt;/p&gt;

&lt;p&gt;Tatsächlich hat sich hier aber keine große Optimierung ergeben, da ich meist
immer alle Formen von Features einer Bibliothek nutze.
&lt;code&gt;ZLIB&lt;/code&gt;, &lt;code&gt;BZIP2&lt;/code&gt; und &lt;code&gt;LZMA&lt;/code&gt; treten immer gemeinsam auf, oder gar nicht.&lt;/p&gt;

&lt;p&gt;Doch die kleineren Helferchen wie &lt;code&gt;stringstream&lt;/code&gt;, &lt;code&gt;memorystream&lt;/code&gt; und 
&lt;code&gt;nullstream&lt;/code&gt; fallen jetzt sofort weg, wenn sie nicht benutzt werden und das
führte bei DOS-Programmen gleich zu einer Verringerung um 5 bis 10 KByte.&lt;/p&gt;

&lt;p&gt;Hätte ich SSL-Streams bisher “optional” im Code drinnen gehabt, würde die 
Codereduktion im Megabytes-Bereich liegen.&lt;/p&gt;

&lt;h3 id=&quot;gcc-negativ-optimierung&quot;&gt;GCC Negativ-Optimierung&lt;/h3&gt;

&lt;p&gt;Tatsächlich sind mir auch ein paar “Negativ-Optimierungen” mit meiner neuen
Initialisierungsstrategie aufgefallen. Denn in einigen Formationen hat der
GCC offenbar die V-Tables schon vorher perfekt wegoptimiert.&lt;br /&gt;
Mit meiner Umstellung kam also bei den benutzten Objekten jetzt eine
Initialisierungsfunktion hinzu, die größer war als die alte statische
Initialisierung.&lt;/p&gt;

&lt;p&gt;Während also WATCOM und MSVC Binaries zwischen 2 und 10 KB kleiner wurden,
wurden einige Outputbinaries des GCC um 1 KByte größer.&lt;/p&gt;

&lt;p&gt;Doch da hier der Kosten/Nutzeneffekt bei der DOS Plattform groß und bei
Linux vernachlässigbar war, bin ich bei den neuen Funktionen geblieben.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Tja … Microsoft hat schon vor über 20 Jahren das V-Table Problem zumindest
im C++ Codegenerator angegangen.&lt;br /&gt;
Heute komme ich also im C-Nachbau auch dorthin.&lt;/p&gt;

&lt;p&gt;Es ist schon spannend zu lernen, wie und vor allem wann Compiler ihre 
Optimierungen anwenden können und wann nicht.&lt;/p&gt;

&lt;p&gt;Ich überlege noch, ob man die Initialisierung mit Makros “besser” abdecken
kann, aber vorerst bleibe ich bei der direkten Umsetzung.&lt;br /&gt;
Der V-Table Code wird schließlich nur einmal geschrieben bzw. heute
eben genau einmal angepasst.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Guardians of the Galaxy - 3</title>
   <link href="https://www.opengate.at/blog/2023/05/guardians-3/"/>
   <published>2023-05-06T13:00:00+02:00</published>
   <updated>2023-05-06T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2023/05/guardians-3</id>
   <category term="entertainment" />
   <summary type="text">Mitte der 90er hatten wir 
Als die Tiere den Wald verließen,
denn diese Serie trieb jedes Kind zum nächsten Tierschutzverein.

Heute setzt 
Guardians of the Galaxy Vol 3
bei diesem Thema an und zeigt uns ein würdiges Ende der Guardians 
(und deren möglichen Neubeginn).
</summary>
   <content type="html">&lt;p&gt;Mitte der 90er hatten wir 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Als_die_Tiere_den_Wald_verlie%C3%9Fen_(Fernsehserie)&quot;&gt;Als die Tiere den Wald verließen&lt;/a&gt;,
denn diese Serie trieb jedes Kind zum nächsten Tierschutzverein.&lt;/p&gt;

&lt;p&gt;Heute setzt 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Guardians_of_the_Galaxy_Vol._3&quot;&gt;Guardians of the Galaxy Vol 3&lt;/a&gt;
bei diesem Thema an und zeigt uns ein würdiges Ende der Guardians 
(und deren möglichen Neubeginn).
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Diverse Trailer haben es uns schon ahnen lassen, dass der sprechende&lt;br /&gt;
&lt;a href=&quot;https://en.wikipedia.org/wiki/Rocket_Raccoon&quot;&gt;Waschbär Rocket&lt;/a&gt; eine zentrale
Rolle einnehmen wird.&lt;/p&gt;

&lt;p&gt;Wir wussten aus den Filmen bisher nur, dass es sich bei diesem Wesen um ein
Experiment an Tieren handelte, welches diese intelligenter und damit auch
“menschlicher” werden ließ (… was für ein Widerspruch).&lt;/p&gt;

&lt;p&gt;Und tatsächlich spielt ein Drittel des Filmes als Rückblenden in der 
Vergangenheit und zeigt wie Rocket unter unmenschlichsten Bedingungen
zu dem wurde, was er heute ist.&lt;/p&gt;

&lt;h3 id=&quot;rettet-die-tiere&quot;&gt;Rettet die Tiere&lt;/h3&gt;

&lt;p&gt;** Achtung: Spoiler voraus! **&lt;/p&gt;

&lt;p&gt;Dieser Marvel Film ist ein einziger Fingerzeig darauf, wie schlecht wir
Menschen mit Tieren umgehen. Dass hier auch Marvels Guardians of the
Galaxy vorkommen, ist eigentlich belanglos … und trotzdem unglaublich
gelungen umgesetzt worden.&lt;/p&gt;

&lt;p&gt;In den ersten 10 Minuten wird Rocket lebensgefährlich verletzt und der
Film handelt davon, wie seine Freunde, die Guardians, um dessen Leben
kämpfen. Und diese Aufgabe führt sie zu Rockets ehemaligen Peiniger,
der ihn einst “erschuf”.&lt;br /&gt;
Das war es auch schon … und hier könnte man sofort die Kritik loslassen
und von einer fehlenden Story sprechen.&lt;/p&gt;

&lt;p&gt;Doch auf diesem simplen Handlungsstrang sehen wir einerseits einen 
Freundeskreis, der ungewohnt ernst die eigenen Fehler eingesteht und 
andererseits erblicken wir in einer hochmodernen technisierten Zukunft
dreckige Käfige, in denen Tiere gequält und ihre Leben nur einen reinen 
Materialwert hat.&lt;/p&gt;

&lt;p&gt;Die Bilder wirken zugegeben oft kitschig, wenn wir Waschbären, Otter oder
Hasen mit menschlichen Gesichtszügen leiden oder sich freuen sehen.&lt;br /&gt;
Das kennt man nur noch aus dem “Kinderfernsehen”.&lt;br /&gt;
Aber vielleicht brauchen wir mal einen “erwachsenen” Unterhaltungsfilm,
der uns wieder daran erinnert, dass WIR oft für das Leid auf dieser
Welt verantwortlich sind.&lt;/p&gt;

&lt;h3 id=&quot;neue-und-alte-gesichter&quot;&gt;Neue und alte Gesichter&lt;/h3&gt;

&lt;p&gt;Der ehemalige &lt;a href=&quot;https://de.wikipedia.org/wiki/Maze_Runner_%E2%80%93_Die_Auserw%C3%A4hlten_im_Labyrinth&quot;&gt;Maze Runner&lt;/a&gt;
Verlierer &lt;a href=&quot;https://de.wikipedia.org/wiki/Will_Poulter&quot;&gt;Will Poulter&lt;/a&gt; hat 
ordentlich Muskeln antrainiert, damit er zu 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Figuren_aus_dem_Marvel-Universum#Adam_Warlock&quot;&gt;Adam Warlock&lt;/a&gt;
werden konnte um die “junge Variante” einer lebendigen Waffen zu spielen.&lt;br /&gt;
Bedauerlich ist eher, dass er zur Nebenfigur verkommen ist und nun vermutlich 
auf seinen großen Auftritt in den kommenden Avengers Filmen warten muss.&lt;/p&gt;

&lt;p&gt;Ansonsten laufen viele Figuren der vergangenen Filme einmal vorbei, spielen
aber keine Rolle. Es wirkt eher so, als hätte man sie in die Story hinein 
geschrieben, damit man eben das ganze Guardians-Universum nochmal auflisten
kann.&lt;/p&gt;

&lt;h3 id=&quot;ende-und-neuanfang&quot;&gt;Ende und Neuanfang&lt;/h3&gt;

&lt;p&gt;Für das Ende sollte man ausreichend Wasser trinken, denn ohne Tränen geht 
es nicht. Die Guardians trennen sich, und versuchen (so wie Thor in 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Thor:_Love_and_Thunder&quot;&gt;Thor 4&lt;/a&gt; ) einen neuen
Sinn im Leben zu finden.&lt;br /&gt;
Doch gleichzeitig sammeln sich junge Azubis rund um Rocket und Adam, 
um ein neues Guardians-Team zu gründen.&lt;/p&gt;

&lt;p&gt;Wir haben also das Ende einer Trilogie erreicht, die im Abspann einfach
“ausläuft”.&lt;br /&gt;
Dennoch lautet der letzte Schriftzug:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The legendary Star-Lord will return.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Als Marvel Fan kann ich gar nicht anders, als diesen Film zu empfehlen.
Die Guardians sind eine “komische Bande” und produzieren zuverlässig 
Lacher im Kinosaal.&lt;br /&gt;
Diesmal wurde es aber gleichzeitig ernst bei vielen Szenen und der
in &lt;em&gt;Infinity Wars&lt;/em&gt; zur “Star-Lusche” verkommene Star-Lord hat sich 
(ähnlich zu Thor) seinen Heldenstatus zurückerkämpft.&lt;/p&gt;

&lt;p&gt;Ein Funkfeuer von Comic-haften Kämpfen wechselt sich mit ruhigen wie auch 
düsteren Rückblenden ab und zeigt alle Charaktere von ihre lustigen, 
ernsten und heldenhaften Seite.&lt;/p&gt;

&lt;p&gt;Tja und alle, die Guardians of the Galaxy vorher noch nicht kannten,
die sehen sich am besten den Christmas-Song aus dem Weihnachts-Special
an, das ziemlich gut zeigt, was für ein “seltsamer” Haufen die 
Guardians-Charaktere sind und wie selbstironisch sie mit sich umgehen:&lt;/p&gt;

&lt;iframe width=&quot;640&quot; height=&quot;360&quot; src=&quot;/blog/redirect.html?https%3A%2F%2Fwww.youtube-nocookie.com%2Fembed%2F-E1ULv6LcOk&quot; frameborder=&quot;1&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
</content>
 </entry>
 
 <entry>
   <title>Major&apos;s Problem</title>
   <link href="https://www.opengate.at/blog/2023/04/majors-problem/"/>
   <published>2023-04-30T13:00:00+02:00</published>
   <updated>2023-04-30T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2023/04/majors-problem</id>
   <category term="general" />
   <summary type="text">Skandale, Verbrechen und Betrug geschehen rund um die Uhr. Auch die Welt der
Stars und Sternchen ist damit konfrontiert.
Bisher ging das stets an mir vorbei, weil mich das wenig interessiert hat.

Mit der Anzeige wegen häuslicher Gewalt gegen Jonathan Majors 
ändert sich das allerdings. Hier kann man nicht so einfach Partei ergreifen 
und weitermachen.
</summary>
   <content type="html">&lt;p&gt;Skandale, Verbrechen und Betrug geschehen rund um die Uhr. Auch die Welt der
Stars und Sternchen ist damit konfrontiert.&lt;br /&gt;
Bisher ging das stets an mir vorbei, weil mich das wenig interessiert hat.&lt;/p&gt;

&lt;p&gt;Mit der Anzeige wegen häuslicher Gewalt gegen &lt;a href=&quot;https://de.wikipedia.org/wiki/Jonathan_Majors&quot;&gt;Jonathan Majors&lt;/a&gt; 
ändert sich das allerdings. Hier kann man nicht so einfach Partei ergreifen 
und weitermachen.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Es war allgemeiner Konsens, dass Jonathan Majors eine hervorragende Besetzung
als “He-who-remains” und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Figuren_aus_dem_Marvel-Universum#Kang_der_Eroberer&quot;&gt;Kang the Conqueror&lt;/a&gt; 
im &lt;a href=&quot;https://de.wikipedia.org/wiki/Marvel_Cinematic_Universe&quot;&gt;Marvel Cinematic Universe&lt;/a&gt; 
ist.&lt;/p&gt;

&lt;p&gt;Der Schauspieler konnte realistisch die Figur eines Mastermind wie auch eines 
Bösewichtes der ersten Klasse darstellen. Für 2025 war mit Avengers 
“Kang-Dynasty” das nächste große Marvel-Kinospektakel geplant, und bis dahin 
sind noch einige Zwischenprojekte mit dieser Figur eingeplant.&lt;/p&gt;

&lt;p&gt;Und dann … im März 2023 … kommt die Meldung von der Verhaftung des 
Schauspielers in die Medien. Er soll eine Frau geschlagen und verletzt haben.&lt;/p&gt;

&lt;p&gt;Wie auch immer sich die Geschichte fortsetzt, können “wir” nicht wissen.
Die Verteidigung des Opfers bringt Verletzungen und medizinische Details vor,
der Angeklagte liefert Videoaufzeichnungen und Chatprotokolle, dass die
Verletzungen nicht von ihm stammen können.&lt;/p&gt;

&lt;p&gt;Jetzt ergeben sich folgende Szenarien:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Dem Kläger wurde ein Unrecht angetan:
    &lt;ul&gt;
      &lt;li&gt;Der Beschuldigte legt manipulierte Beweise vor um die Schuld von sich zu weisen.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Der Angeklagte wurde zu Unrecht beschuldigt:
    &lt;ul&gt;
      &lt;li&gt;Der Kläger legt manipulierte Beweise vor um die Schuld auf den Kläger zu legen.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Kläger und Angeklagter legen zum Teil manipulierte Beweise vor
    &lt;ul&gt;
      &lt;li&gt;Jetzt wird es verdammt kompliziert.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Interessant sind jedoch jetzt bereits die Konsequenzen, denn mit 
Veröffentlichung der Anklage wurden sämtliche Projekte und 
Partnerschaften mit dem Schauspieler unmittelbar beendet. Nur Marvel hat 
für seine Projekte bisher noch kein Statement abgegeben … doch im 
Hintergrund, so munkelt man, wird eine Neubesetzung zumindest angedacht.&lt;/p&gt;

&lt;p&gt;Das Schlimme an dieser Dynamik ist, dass egal wie es ausgeht, der Schaden 
bereits angerichtet ist.&lt;/p&gt;

&lt;p&gt;Jonathan Major’s steile Karriere ist aktuell beendet und für ihn geht es nun 
um die Frage, ob er verurteilt werden wird oder ob er mit beschädigtem Image 
weiter in der Filmbranche arbeiten können wird.&lt;/p&gt;

&lt;p&gt;Das Opfer ist mit einem Prozess konfrontiert, der ebenfalls keine große 
Karriere mehr zulässt. Stimmen die Vorwürfe, muss gegen eine Horde von 
Majors-Fans angekämpft werden und man steht für immer als Opfer im 
Rampenlicht. Handelt es sich um eine böswillige Unterstellung, 
folgt eine unbezahlbare Wiedergutmachungsforderung und ein Leben 
in Schande.&lt;/p&gt;

&lt;p&gt;Das Schlimme daran ist, dass sich in unserer medialen Welt die Fronten schon
gebildet haben und so wird munter darüber diskutiert:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;dass Superstars glauben, sich alles ungestraft erlauben zu können.&lt;/li&gt;
  &lt;li&gt;dass einsame Freaks gerne Superstars die Karriere zerstören wollen.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Auf Youtube treten bereits Verteidiger für beide Seiten auf und Astrologen
legen die Karten um den Ausgang vorhersehen zu können.&lt;/p&gt;

&lt;p&gt;… &lt;strong&gt;und all das ist Schwachsinn.&lt;/strong&gt;&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ich wünsche mir natürlich, dass der charismatische Schauspieler von den
Anschuldigungen reingewaschen werden kann … und gleichzeitig will ich,
dass Gewalt gerade bei solchen Personen auf gar keinen Fall geduldet werden
kann.&lt;/p&gt;

&lt;p&gt;Jetzt heißt es mal Klappe halten und die Justiz arbeiten lassen … und 
das dauert eben. Die Beweise beider Seiten müssen geprüft und vorgetragen
werden und am Ende soll ein Richter entscheiden, was weiter geschehen soll.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Hardware und Software in Filmen</title>
   <link href="https://www.opengate.at/blog/2023/04/movie-hardware/"/>
   <published>2023-04-29T13:00:00+02:00</published>
   <updated>2023-04-29T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2023/04/movie-hardware</id>
   <category term="general" /><category term="entertainment" />
   <summary type="text">Es gibt für Insider nichts komischeres, als wenn Outsider so tun, als würden 
sie sich auskennen.

Und zu den lustigsten Dingen zählen dabei die Darstellung von Hardware
und Software in Film und Fernsehen.

</summary>
   <content type="html">&lt;p&gt;Es gibt für Insider nichts komischeres, als wenn Outsider so tun, als würden 
sie sich auskennen.&lt;/p&gt;

&lt;p&gt;Und zu den lustigsten Dingen zählen dabei die Darstellung von Hardware
und Software in Film und Fernsehen.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;armageddon-1998&quot;&gt;Armageddon 1998&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/movie-armageddon-cpu-m3.jpg&quot; alt=&quot;PC-Mainboard in Space&quot; /&gt;&lt;/p&gt;

&lt;p&gt;In den ersten Minuten 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Armageddon_%E2%80%93_Das_j%C3%BCngste_Gericht&quot;&gt;des Films&lt;/a&gt;
schwebt ein Astronaut im Orbit und repariert einen Satelliten.&lt;br /&gt;
Spannend ist, dass es ein Intel-Mainboard für Sockel-2 Prozessoren ist, auf
dem er mit einem tollen Greifwerkzeug den Prozessor (vermutlich ein Pentium)
entfernt.&lt;/p&gt;

&lt;p&gt;Ich bin mir nicht sicher, ob man ein PC Mainboard einfach so dem Weltraum aussetzen sollte.
(… die überhitzen doch ohne Luftkühlung!)&lt;/p&gt;

&lt;h3 id=&quot;the-core-minute-79&quot;&gt;The Core (Minute 79)&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/movie-thecore-breadboard-m79.jpg&quot; alt=&quot;Breadboard in earth&apos;s core&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/The_Core_%E2%80%93_Der_innere_Kern&quot;&gt;Der innere Kern&lt;/a&gt;
ist pure SciFi-Comedy, nur wussten das die Macher nicht.&lt;/p&gt;

&lt;p&gt;Wenn man schon ein Magma-festes Schiff hat, mit dem man sich zum Mittelpunkt 
der Erde graben kann, dann hat es auch die beste Technik an Board.&lt;br /&gt;
Als der Computer dann einen beschädigten Schiffsteil mit einem Kollegen 
abtrennen will, versucht der Techniker den Vorgang aufzuhalten.&lt;br /&gt;
Dafür muss man einfach schnell viele Kabel umstecken.&lt;br /&gt;
Gut das überall Breadboards mit jeder Menge Kabel und Kurzschlüssen in den
Wänden verbaut sind, so kann man hoch energisch Kontakte herausziehen und 
wieder reinstecken.&lt;/p&gt;

&lt;h3 id=&quot;batman-vs-superman-minute-38&quot;&gt;Batman vs Superman (Minute 38)&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/movie-batmanvsuperman-lumia-m38.jpg&quot; alt=&quot;Batmans Lumia Phone&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Das einzige, was mich in 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Batman_v_Superman:_Dawn_of_Justice&quot;&gt;dem Film&lt;/a&gt;
voll und ganz überzeugt hat, war, als Bruce Wayn mit einem 
Lumia Windows Phone die Hardware der Lexx-Corp gehackt hat.&lt;/p&gt;

&lt;p&gt;Das verstehe ich … diese Smartphone war perfekt und konnte alles.
Schade dass die Hacker-App nie im Store erhältlich war.&lt;/p&gt;

&lt;h3 id=&quot;der-tag-an-dem-die-erde-stillstand-minute-30&quot;&gt;Der Tag, an dem die Erde stillstand (Minute 30)&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/movie-earthstoodstill-wintable-m30.jpg&quot; alt=&quot;WinVista Table&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Ja, Microsoft hat mal einen Tisch namens 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_PixelSense&quot;&gt;Surface bzw. PixelSense&lt;/a&gt;
entwickelt, den niemand haben wollte. 
Es war ein übergroßer Touchscreen mit Windows Vista.&lt;/p&gt;

&lt;p&gt;Im &lt;a href=&quot;https://de.wikipedia.org/wiki/Der_Tag,_an_dem_die_Erde_stillstand_(2008)&quot;&gt;Film&lt;/a&gt;
hat des Teil für 10 Sekunden den Zweck ein paar Farbpatzer und virtuelles
Papierblatt für die Entscheidungsträger anzuzeigen.
Tja … die Regierung kann sich sowas leisten.&lt;/p&gt;

&lt;h3 id=&quot;matrix-2-minute-103&quot;&gt;Matrix 2 (Minute 103)&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/movie-matrix2-ssh-m103.jpg&quot; alt=&quot;SSH Hack&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Ist doch klar, dass alle, die &lt;a href=&quot;https://de.wikipedia.org/wiki/Matrix_Reloaded&quot;&gt;die Matrix&lt;/a&gt;
verstehen, absolute Hacker sind.
Und Trinity nutzt auch eine bekannte SSH Lücke für ihren Hack aus.
… aber … warum sollte bei der Eingabe des &lt;code&gt;root&lt;/code&gt; Passworts auf der 
Konsole nochmal ein eigenes Fenster aufgehen, wo genau die 8 Stellen des
zuvor gesetzt Passworts &lt;code&gt;Z10N0101&lt;/code&gt; perfekt für die Kamera ausgerichtet 
nochmal eingegeben werden müssen.&lt;br /&gt;
Da wird es unglaubwürdig, Freunde.&lt;br /&gt;
Die 3 Assembler-Zeilen im Hintergrund lassen wir mal als optische Bereichung
einfach so stehen.&lt;/p&gt;

&lt;h3 id=&quot;digimon-movie&quot;&gt;Digimon Movie&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/movie-digimon-windows.jpg&quot; alt=&quot;Digimon Movie&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Dass Digimon in zwei überlappenden Windows 98 Fenstern “live” mit Animationen
digitieren können und dass alles über eine Modem-Verbindung übertragen wird,
ist schon ein bisschen weit hergeholt.&lt;/p&gt;

&lt;p&gt;Aber mir gefällt am besten, wie es dort “im Internet” aussieht:&lt;br /&gt;
Ein leerer Raum mit Wänden, auf denen Karusselpferde und andere Ringelspiele
ihre Runden ziehen.&lt;/p&gt;

&lt;p&gt;In Summe enthält der &lt;a href=&quot;https://de.wikipedia.org/wiki/Digimon_Adventure_(Film)&quot;&gt;Digimon-Film&lt;/a&gt;
(leider) mehr Windows 9x-Screenshots als gute Handlung. 
Aber als Werbefilm hätte Microsoft es nicht besser machen können.&lt;/p&gt;

&lt;h3 id=&quot;star-trek-discovery-s1e3-minute-20&quot;&gt;Star Trek Discovery (S1E3 Minute 20)&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/movie-discovery1x3-ntkernel-m20.jpg&quot; alt=&quot;Star Trek Discovery with WinNT&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Im 23. Jahrhundert ist der Windows Kernel immer noch fleißig im Einsatz
um die Systeme der &lt;a href=&quot;https://de.wikipedia.org/wiki/Star_Trek:_Discovery&quot;&gt;U.S.S. Discovery&lt;/a&gt;
zu betreiben.&lt;br /&gt;
Nur manchmal muss Micheal Burnham diesen Patchen um eine Biologie
Aufgabe lösen zu können.
Auch nicht schlecht. Wer auch immer sich das hat einfallen lassen, wusste nicht,
dass LCARS für “Linux CAn Run Starships” steht.&lt;/p&gt;

&lt;h3 id=&quot;frequency-minute-69&quot;&gt;Frequency (Minute 69)&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/movie-frequency-yahoo-m69.jpg&quot; alt=&quot;Yahoo-Stock-Secrets&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Anlagetipps in die Vergangenheit schicken … das machte sonst nur Biff in 
Zurück in die Zukunft. 
Doch &lt;a href=&quot;https://de.wikipedia.org/wiki/Frequency_(Film)&quot;&gt;Frequency&lt;/a&gt; greift das
Thema “Daten in die Vergangenheit schicken” ebenso auf.&lt;/p&gt;

&lt;p&gt;Die Info, man solle in der Vergangenheit in “Yahoo” Aktien investieren, war
im Jahr 1999/2000 vielleicht noch richtig. 
Und der Nachbarsjunge fuhr dann als Erwachsener ein schönes Auto.
Es fehlte aber die Info, dass man die Aktien im neuen Jahrtausend
ganz schnell wieder verkaufen sollte.&lt;/p&gt;

&lt;h3 id=&quot;antitrust-bzw-startup&quot;&gt;AntiTrust bzw. “Startup”&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/movie-antitrust-bash-m51.jpg&quot; alt=&quot;HTML and bash tools&quot; /&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ist es nicht lustig, dass der 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Startup_(Film)&quot;&gt;Film Antitrust&lt;/a&gt;
bei uns unter dem Titel “Startup” herauskam?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ich liebe es, wenn sich Programmierer über die genialsten Algorithmen 
unterhalten und dann Java Code angezeigt wird, der die HTTP-Verben
&lt;code&gt;GET&lt;/code&gt; und &lt;code&gt;HEAD&lt;/code&gt; aus einem Byte-Array zeichenweise heraus-IF-t.
Genau so fasziniert wäre wohl auch Bill Gates gewesen.
Doch die Sache hatte ihren Preis. Diese Zeilen wurden einem anderen
Coder geklaut, der seine Erfindung nicht lange überlebt hat.&lt;/p&gt;

&lt;p&gt;Gut, dass unser Hacker-Held das Überwachungssystem findet und auslesen kann.
Am Ende werden die Firmensatelliten mit &lt;code&gt;10.x.x.x&lt;/code&gt; IP Addressen einfach
heruntergefahren und der Sourcecode im Netz veröffentlicht.
Ob die gezeigte Seite &lt;code&gt;skullbocks.com&lt;/code&gt; immer noch den Code zeigt?&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Es gäbe sicher noch viel viel mehr, aber diese Filme (bzw. Serien) kommen
mir immer in den Sinn.&lt;br /&gt;
Leider nicht mehr gefunden habe ich die 
&lt;a href=&quot;https://de.wikipedia.org/wiki/SeaQuest_DSV&quot;&gt;Seaquest DSV&lt;/a&gt; Folge, 
wo ich mich an ein “Watchdog-Programm” erinnere und ein digitaler Hund 
immer “Wau-wau” am Lautsprecher ausgab.&lt;/p&gt;

&lt;p&gt;Es ist einfach lustig, was sich Filmemacher alles einfallen lassen um
digitale Ereignisse und “Hacken” zu visualisieren.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>WSL Special: Debian und Server 2019</title>
   <link href="https://www.opengate.at/blog/2023/04/wsl-special/"/>
   <published>2023-04-23T13:00:00+02:00</published>
   <updated>2023-04-23T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2023/04/wsl-special</id>
   <category term="software" />
   <summary type="text">Für WSL ist 
Ubuntu die beste Distribution, denn 
hier hat jede Distro-Version eine eigene ID, und man kann sie alle parallel
installieren, z.B.: Ubuntu-18.04, Ubuntu-20.04 usw.

Debian heißt immer nur Debian und man bekommt offiziell immer nur die 
neueste Variante.
Doch wie kann man auf einem älteren Stand seine Software testen?
</summary>
   <content type="html">&lt;p&gt;Für &lt;a href=&quot;https://de.wikipedia.org/wiki/Windows-Subsystem_f%C3%BCr_Linux&quot;&gt;WSL&lt;/a&gt; ist 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Ubuntu&quot;&gt;Ubuntu&lt;/a&gt; die beste Distribution, denn 
hier hat jede Distro-Version eine eigene ID, und man kann sie alle parallel
installieren, z.B.: &lt;code&gt;Ubuntu-18.04&lt;/code&gt;, &lt;code&gt;Ubuntu-20.04&lt;/code&gt; usw.&lt;/p&gt;

&lt;p&gt;Debian heißt immer nur &lt;code&gt;Debian&lt;/code&gt; und man bekommt offiziell immer nur die 
neueste Variante.
Doch wie kann man auf einem älteren Stand seine Software testen?
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Microsoft bietet offiziell nur einen Download Link für Debian auf 
&lt;a href=&quot;https://learn.microsoft.com/en-us/windows/wsl/install-manual&quot;&gt;learn.microsoft.com&lt;/a&gt; an,
und zwar: &lt;a href=&quot;https://aka.ms/wsl-debian-gnulinux&quot;&gt;aka.ms/wsl-debian-gnulinux&lt;/a&gt;&lt;br /&gt;
Heute erhält man damit nur Debian 11, vor einem Jahr war es Debian 10 und
bis vor 2 Jahren war es noch Debian 9.&lt;/p&gt;

&lt;p&gt;Die älteren Varianten sind quasi weg.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ein Hoch auf die fleißigen Bienchen im Internet und auf Github!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Zum Glück hat ein &lt;a href=&quot;http://github.com/MicrosoftDocs/WSL/issues/563&quot;&gt;User auf GitHub&lt;/a&gt; 
die früheren Links gepostet:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Download &lt;a href=&quot;https://wsldownload.azureedge.net/DebianGNULinux_1-1-3-0_x64__76v4gfsz19hv4.Appx&quot;&gt;WSL Debian  9&lt;/a&gt;
    &lt;ul&gt;
      &lt;li&gt;Für Updates muss man in &lt;code&gt;/etc/apt/sources.list&lt;/code&gt; die URLs auf 
&lt;code&gt;http://archive.debian.org/...&lt;/code&gt; umstellen.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Download &lt;a href=&quot;https://wsldownload.azureedge.net/TheDebianProject.DebianGNULinux_1.12.2.0_neutral___76v4gfsz19hv4.AppxBundle&quot;&gt;WSL Debian 11&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Download &lt;a href=&quot;https://wsldownload.azureedge.net/kali-linux-08-06-2019.appx&quot;&gt;WSL Kali Linux 2019.2&lt;/a&gt;
    &lt;ul&gt;
      &lt;li&gt;Für Update müssen neue Keys eingespielt werden mit:&lt;br /&gt;
&lt;code&gt;sudo wget --no-check-certificate https://archive.kali.org/archive-key.asc -O /etc/apt/trusted.gpg.d/kali-archive-keyring.asc&lt;/code&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Download &lt;a href=&quot;https://wsldownload.azureedge.net/KaliLinux_1.13.1.0.AppxBundle&quot;&gt;WSL Kali Linux 2022.3&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Download &lt;a href=&quot;https://wsldownload.azureedge.net/14.04.5.3-server-cloudimg-amd64-root.tar.gz&quot;&gt;WSL Ubuntu 14.04&lt;/a&gt;
    &lt;ul&gt;
      &lt;li&gt;Nur root filesystem&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Download &lt;a href=&quot;https://wsldownload.azureedge.net/Ubuntu_1604.2019.523.0_x64.appx&quot;&gt;WSL Ubuntu-16.04&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Download &lt;a href=&quot;https://wsldownload.azureedge.net/Ubuntu_1804.2019.522.0_x64.appx&quot;&gt;WSL Ubuntu-18.04 X+5&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Download &lt;a href=&quot;https://wsldownload.azureedge.net/Ubuntu_1804.2019.522.0_ARM64.appx&quot;&gt;WSL Ubuntu-18.04 ARM64&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Download &lt;a href=&quot;https://wsldownload.azureedge.net/Ubuntu_2004.2020.424.0_x64.appx&quot;&gt;WSL Ubuntu-20.04 X64&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Download &lt;a href=&quot;https://wsldownload.azureedge.net/Ubuntu_2004.2020.424.0_ARM64.appx&quot;&gt;WSL Ubuntu-20.04 ARM64&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Download &lt;a href=&quot;https://wslstorestorage.blob.core.windows.net/wslblob/Ubuntu2204LTS-230418_x64.appx&quot;&gt;WSL Ubuntu-22.04 X64&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Download &lt;a href=&quot;https://wslstorestorage.blob.core.windows.net/wslblob/Ubuntu2204LTS-230418_ARM64.appx&quot;&gt;WSL Ubuntu-22.04 ARM64&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Download &lt;a href=&quot;https://wsldownload.azureedge.net/openSUSE-42_v1.appx&quot;&gt;WSL OpenSUSE Leap 42.2&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Download &lt;a href=&quot;https://wslstorestorage.blob.core.windows.net/wslblob/openSUSELeap15_4-230130_x64.Appx&quot;&gt;WSL openSUSE Leap 15.4&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Download &lt;a href=&quot;https://wslstorestorage.blob.core.windows.net/wslblob/openSUSETumbleweed-230130_x64.Appx&quot;&gt;WSL openSUSE Tumbleweed&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Download &lt;a href=&quot;https://wsldownload.azureedge.net/SLES-12_v1.appx&quot;&gt;WSL SUSE Linux Enterprise Server 12&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Download &lt;a href=&quot;https://wslstorestorage.blob.core.windows.net/wslblob/SUSELinuxEnterpriseServer15_SP4-230130_x64.Appx&quot;&gt;WSL SUSE Linux Enterprise Server 15-SP4&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Download &lt;a href=&quot;https://wslstorestorage.blob.core.windows.net/wslblob/OracleLinux8.5_8.5.1.0.Appx&quot;&gt;WSL OracleLinux 8.5&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Download &lt;a href=&quot;https://wslstorestorage.blob.core.windows.net/wslblob/OracleLinux7.9_7.9.1.0.Appx&quot;&gt;WSL OracleLinux 7.9&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Die &lt;code&gt;.appx&lt;/code&gt; Dateien sind &lt;code&gt;.zip&lt;/code&gt; Dateien und lassen sich mit Tools wie 7zip öffnen.
Unter den extrahierten Dateien befindet sich meist eine &lt;code&gt;.exe&lt;/code&gt;, die die 
Distribution automatisch einrichtet.&lt;/p&gt;

&lt;p&gt;Alternativ kann man auch das enthaltene Dateisystem in der &lt;code&gt;.tar.gz&lt;/code&gt; Datei per&lt;br /&gt;
&lt;code&gt;wsl --import MyDistroName &quot;C:\WSL\my_distro_storage&quot; &quot;path\to\install.tar&quot;&lt;/code&gt;&lt;br /&gt;
in die WSL Installation integrieren und mit&lt;br /&gt;
&lt;code&gt;wsl -d MyDistroName&lt;/code&gt; starten.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ich brauche immer wieder mal alte Linux Distributionen, um mit deren Standard
Compiler Debug-Builds anzustoßen, die dann auf gleichartigen Zielsystemen
getestet werden sollen.&lt;/p&gt;

&lt;p&gt;Parallel dazu sind einige Tools und Bibliotheken aufwärts-kompatibel.
Baut ein Programm also auf Ubuntu 16.04, wird es mit hoher Wahrscheinlichkeit
auf einem Ubuntu 22.04 laufen. Umgekehrt ist das aber nicht so.&lt;/p&gt;

&lt;p&gt;Es bringt also Vorteile, wenn schnell und effizient über unterschiedliche
Linux Distributionen verfügt werden kann … und da sind alte WSL-Images 
echt hilfreich.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>RDP klaut ALT-GR</title>
   <link href="https://www.opengate.at/blog/2023/04/rdp-alt-gr/"/>
   <published>2023-04-22T13:00:00+02:00</published>
   <updated>2023-04-22T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2023/04/rdp-alt-gr</id>
   <category term="software" />
   <summary type="text">
  Und nun zu den aktuellen Nachrichten:

  Während der interaktiven Sitzung zwischen 
Windows 10 und 
Server 2019
kam es heute zu einem Unfall im ALT-GR 
Tastenbereich.

  Mehrere Codes wurden korrumpiert, als sämtliche Tastenanschläge für
Backslash \ und Pipe | durch scharfe-S ß und Kleinerzeichen &amp;lt;
ersetzt wurden.

  Die zuständigen Behörden wurden umgehend informiert und erarbeiteten
vor Ort eine Lösung.


</summary>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;Und nun zu den aktuellen Nachrichten:&lt;/p&gt;

  &lt;p&gt;Während der interaktiven Sitzung zwischen 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_10&quot;&gt;Windows 10&lt;/a&gt; und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_Server_2019&quot;&gt;Server 2019&lt;/a&gt;
kam es heute zu einem Unfall im &lt;a href=&quot;https://de.wikipedia.org/wiki/Alt_Gr&quot;&gt;ALT-GR&lt;/a&gt; 
Tastenbereich.&lt;/p&gt;

  &lt;p&gt;Mehrere Codes wurden korrumpiert, als sämtliche Tastenanschläge für
Backslash &lt;code&gt;\&lt;/code&gt; und Pipe &lt;code&gt;|&lt;/code&gt; durch scharfe-S ß und Kleinerzeichen &lt;code&gt;&amp;lt;&lt;/code&gt;
ersetzt wurden.&lt;/p&gt;

  &lt;p&gt;Die zuständigen Behörden wurden umgehend informiert und erarbeiteten
vor Ort eine Lösung.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Der Spruch:&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;Das Leben ist wie eine Hühnerleiter.&lt;br /&gt;
Kurz und beschissen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;hat sich heute wieder bewahrheitet … denn ich hasse es, wenn ich wegen
Blödsinn so viel Lebenszeit verliere.&lt;/p&gt;

&lt;p&gt;Daher die Lösung zuerst:&lt;/p&gt;

&lt;p&gt;Falls plötzlich die &lt;code&gt;ALT-GR&lt;/code&gt; Taste nicht mehr die üblichen Zeichen auf einer 
deutschen Tastatur produziert und parallel eine 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Remote_Desktop_Protocol&quot;&gt;RDP&lt;/a&gt; Sitzung offen ist:&lt;br /&gt;
&lt;strong&gt;Einfach die RDP-Verbindung trennen!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Ich kenne schon länger das Phänomen, dass RDP-Sessions zu veralteten Clients 
(&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_XP&quot;&gt;Windows XP&lt;/a&gt;, 2000) die 
&lt;code&gt;ALT-GR&lt;/code&gt; Taste nicht verstehen. Bei &lt;a href=&quot;https://de.wikipedia.org/wiki/Xrdp&quot;&gt;xrdp&lt;/a&gt; 
unter &lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt; passiert das übrigens auch 
immer wieder.&lt;/p&gt;

&lt;p&gt;Die Lösung ist dann meistens:&lt;br /&gt;
&lt;code&gt;AltGr&lt;/code&gt; + &lt;code&gt;Taste&lt;/code&gt; == &lt;code&gt;Strg&lt;/code&gt; + &lt;code&gt;Alt&lt;/code&gt; + &lt;code&gt;Taste&lt;/code&gt;&lt;br /&gt;
Soll heißen: Ein Backslash ist nicht nur mit &lt;code&gt;Alt-Gr&lt;/code&gt; + &lt;code&gt;&amp;amp;szlig;&lt;/code&gt;, 
sondern auch &lt;code&gt;Strg&lt;/code&gt; + &lt;code&gt;Alt&lt;/code&gt; + &lt;code&gt;&amp;amp;szlig;&lt;/code&gt; möglich.&lt;/p&gt;

&lt;p&gt;Das kümmert mich sonst nicht, weil ich das bestenfalls zur Eingabe von 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Uniform_Naming_Convention&quot;&gt;UNC&lt;/a&gt; Pfaden brauche.&lt;/p&gt;

&lt;p&gt;Heute hatte ich aber eine ungute “Rückkopplung”, dass nämlich die &lt;code&gt;ALT-GR&lt;/code&gt; 
Taste auch in lokalen Programmen nicht mehr funktionierte, unter anderem
auch nicht in &lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_Studio&quot;&gt;Visual Studio&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Und so saß ich mit 3 Programmen vor mir: RDP, Netflix und Visual Studio und 
wechselte ohne genau hinzusehen zwischen den 3 Fenstern und tippt weiter 
meine Codekorrekturen ein.&lt;br /&gt;
Der Compiler verweigerte jedoch diese nach zahlreichen Änderungen und erst
da bemerkte ich die häufigen &lt;code&gt;&amp;amp;szlig;&lt;/code&gt; und &lt;code&gt;&amp;lt;&lt;/code&gt; Zeichen.&lt;/p&gt;

&lt;p&gt;Die Tastatureinstellungen waren korrekt (Deutsch) auch ein erneutes 
Verbinden der USB-Tastatur half nicht.&lt;/p&gt;

&lt;p&gt;Als ich den Rechner neu starten wollte und das RDP-Fenster schloss
funktionierte plötzlich auch &lt;code&gt;ALT-GR&lt;/code&gt; wieder korrekt … W-T-F !&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ja … auch so ein Blödsinn kostet Zeit … und erst recht die Spielerei
mit der Tastatur, denn ich dachte anfangs, die Taste sei kaputt.&lt;/p&gt;

&lt;p&gt;Naja … nun ist es hiermit dokumentiert:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Bei Tastaturfehlern beenden Sie umgehend ihre RDP Sitzungen.&lt;br /&gt;
Und bei Risiken und Nebenwirkungen tragen sie ihren Arzt zum Apotheker.&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>Offline Installationen mit Linux</title>
   <link href="https://www.opengate.at/blog/2023/04/offline-install/"/>
   <published>2023-04-21T13:00:00+02:00</published>
   <updated>2023-04-21T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2023/04/offline-install</id>
   <category term="software" />
   <summary type="text">Bei Produktinstallationen für Kunden melden diese oft:


  Wir haben ein XYZ Linux Version 9.8.7 ohne Internetanbindung.
Senden Sie uns alle notwendigen Installationspakete zu.


Und dann fängt das große Weinen an, wenn man bei 
Python3
angefangen eine halbe Linux-Distribution “nachliefern” soll.
</summary>
   <content type="html">&lt;p&gt;Bei Produktinstallationen für Kunden melden diese oft:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Wir haben ein XYZ Linux Version 9.8.7 ohne Internetanbindung.
Senden Sie uns alle notwendigen Installationspakete zu.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Und dann fängt das große Weinen an, wenn man bei 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Python_(Programmiersprache)&quot;&gt;Python3&lt;/a&gt;
angefangen eine halbe Linux-Distribution “nachliefern” soll.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Windows stammt aus der Offline-Zeit weshalb alles als einzelne 
Installationsdatei (&lt;code&gt;.msi&lt;/code&gt;, &lt;code&gt;.msu&lt;/code&gt;, &lt;code&gt;.cab&lt;/code&gt; und andere) ausgeliefert werden 
kann. Heute ist das ein unguter Fluch, weil man die Fülle an Dateifragmenten
nicht mehr verwaltet bekommt und erst seit kurzem wird versucht mit
&lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_Package_Manager&quot;&gt;winget&lt;/a&gt; 
verspätet ins 21. Jahrhundert zu wechseln.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt; Distributionen hatten früh 
erkannt, wie wichtig ein einheitliches Paket-Management ist und nutzten 
es. Allerdings spalteten sich schnell verfeindete Sekten ab und gründeten 
ihre eigene Paket-Religion.&lt;/p&gt;

&lt;p&gt;Im Embedded-Bereich schmerzt das sehr, wenn man neben dem eigenen Produkt
auch noch auf viele Geschmacksrichtungen von Linux-Varianten eingehen
muss, denn dort ist ein System “offline” und stets veraltet für 10 Jahre
in Betrieb.&lt;/p&gt;

&lt;p&gt;Wenn wir Entwickler also ein tolles Feature implementieren, das auf der
&lt;code&gt;lib_superduper&lt;/code&gt; aufbaut, müssen wir dann auch einen Weg finden, 
wie diese fehlende &lt;code&gt;lib_superduper&lt;/code&gt; beim Kunden integriert wird.&lt;/p&gt;

&lt;p&gt;Aber wie findet man jetzt heraus, welche Pakete sonst noch fehlen, und
wo kann man die dann herunterladen?&lt;/p&gt;

&lt;h3 id=&quot;debian-kali-ubuntu-raspbian&quot;&gt;Debian (Kali, Ubuntu, Raspbian)&lt;/h3&gt;

&lt;p&gt;Wir brauchen also eine Liste der fehlenden &lt;code&gt;.deb&lt;/code&gt; Dateien, die &lt;code&gt;apt&lt;/code&gt; 
für uns herunterladen und dann installieren würde.&lt;/p&gt;

&lt;p&gt;Folgender Trick hat da bei mir funktioniert:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Eine VM (oder ein Docker Container) wird so aufgesetzt wie das Zielsystem.&lt;/li&gt;
  &lt;li&gt;Man löscht die Inhalte von Verzeichnis &lt;code&gt;/var/cache/apt/archives&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Anschließend startet man &lt;code&gt;sudo apt install --download-only PACKNAME&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Und schon liegen alle notwendigen &lt;code&gt;.deb&lt;/code&gt; Dateien in &lt;code&gt;/var/cache/apt/archives&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Von dort kopiert man sie dann zum Zielsystem und führt folgendes Kommando aus:&lt;br /&gt;
&lt;code&gt;sudo dpkg -i *.deb&lt;/code&gt;, welches die &lt;code&gt;.deb&lt;/code&gt; Dateien installiert.
Nachdem die Reihenfolge der Installation nicht definiert ist, kann es aber auch
zu Problemen oder Scriptfehler kommen, die man dann mit&lt;br /&gt;
&lt;code&gt;sudo apt-get install --fix-broken&lt;/code&gt; wieder hinbekommen kann.&lt;/p&gt;

&lt;h3 id=&quot;redhat-alma-centos&quot;&gt;RedHat, Alma, CentOS&lt;/h3&gt;

&lt;p&gt;Distributionen, die mit dem &lt;code&gt;dnf&lt;/code&gt; Tool ihre &lt;code&gt;.rpm&lt;/code&gt; Pakete verwalten, benötigen
das Kommando:&lt;br /&gt;
&lt;code&gt;dnf download PACKNAME --resolve&lt;/code&gt;&lt;br /&gt;
und schon liegen alle korrekt aufgelösten Abhängigkeiten als &lt;code&gt;.rpm&lt;/code&gt; Dateien im
aktuellen Verzeichnis.&lt;/p&gt;

&lt;p&gt;Installieren kann man die Softwarepakete aus dem Verzeichnis dann mit&lt;br /&gt;
&lt;code&gt;sudo rpm -ihv *.rpm&lt;/code&gt;&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ich als Entwickler brauche immer wieder mal einen &lt;code&gt;gdb&lt;/code&gt; auf einer 
Zielmaschine. Und wenn ich weiß, dass mein Kunde eine Debian 9 oder Alma 8
Variante im Einsatz hat, dann kann ich bei mir lokal genau die Bibliotheken
vorbereiten und dann per SSH installieren, die zur Distribution passen.&lt;/p&gt;

&lt;p&gt;Schwerer haben es da meine Dev-Ops Kollegen, die Datenbanken, Monitoring-Tools
und Deployment-Werkzeuge auf unterschiedliche Kundenhardware verteilen müssen.&lt;/p&gt;

&lt;p&gt;Zumindest gibt es für die gängigen Linux Varianten Hilfsmittel um solche
Offline-Updates vorzubereiten.&lt;/p&gt;

&lt;p&gt;Mein gutes (Update-) Werk ist für heute getan und somit kann ich beruhigt 
auf der Konsole &lt;code&gt;exit&lt;/code&gt; eintippen.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Keyboard- und Tastencodes</title>
   <link href="https://www.opengate.at/blog/2023/04/console-keys/"/>
   <published>2023-04-15T13:00:00+02:00</published>
   <updated>2023-04-15T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2023/04/console-keys</id>
   <category term="devel" />
   <summary type="text">A bis Z und 0 bis 9 wird von jedem OS auf 
ASCII 
bzw. Unicodezeichen abgebildet. 
Das gilt auch für die Konsole.

Aber wie bekommt man z.B. Pfeiltasten per read(stdin) geliefert?
</summary>
   <content type="html">&lt;p&gt;&lt;code&gt;A&lt;/code&gt; bis &lt;code&gt;Z&lt;/code&gt; und &lt;code&gt;0&lt;/code&gt; bis &lt;code&gt;9&lt;/code&gt; wird von jedem OS auf 
&lt;a href=&quot;https://de.wikipedia.org/wiki/American_Standard_Code_for_Information_Interchange&quot;&gt;ASCII&lt;/a&gt; 
bzw. &lt;a href=&quot;https://de.wikipedia.org/wiki/Unicode&quot;&gt;Unicodezeichen&lt;/a&gt; abgebildet. 
Das gilt auch für die Konsole.&lt;/p&gt;

&lt;p&gt;Aber wie bekommt man z.B. Pfeiltasten per &lt;code&gt;read(stdin)&lt;/code&gt; geliefert?
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Meine uralten Basic-Beispiele machten sich die Sache für kleine Spielchen 
leicht: Man ging vom Zahlenblock aus und nutzte die Tasten&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;2&lt;/code&gt; herunter&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;4&lt;/code&gt; links&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;6&lt;/code&gt; rechts&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;8&lt;/code&gt; hinauf&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So umging man schon unter &lt;a href=&quot;https://de.wikipedia.org/wiki/MS-DOS&quot;&gt;DOS&lt;/a&gt; die 
interessante Frage, wie man eigentlich an die “richtigen” Pfeiltasten kommt.&lt;/p&gt;

&lt;p&gt;Leider ist das alles andere als einfach … oder anders gesagt, es hängt vom
OS ab. Im &lt;a href=&quot;https://de.wikipedia.org/wiki/C_(Programmiersprache)&quot;&gt;C Standard&lt;/a&gt; 
sind solche Tastenübersetzungen jedenfalls nicht definiert.&lt;/p&gt;

&lt;h3 id=&quot;bios-und-dos&quot;&gt;BIOS und DOS&lt;/h3&gt;

&lt;p&gt;Im PC &lt;a href=&quot;https://de.wikipedia.org/wiki/BIOS&quot;&gt;BIOS&lt;/a&gt; und nachfolgend auch unter 
DOS wurden solche Tastenanschläge in zwei-Bytes-Sequenzen kodiert.&lt;br /&gt;
Das erste Byte zeigte an, dass das nachfolgende Byte eine Spezialtaste war.&lt;/p&gt;

&lt;p&gt;Und so ergeben sich z.B.: für die Pfeiltasten:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Up: &lt;code&gt;00&lt;/code&gt; und &lt;code&gt;72&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Down: &lt;code&gt;00&lt;/code&gt; und &lt;code&gt;80&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Left: &lt;code&gt;00&lt;/code&gt; und &lt;code&gt;75&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Right: &lt;code&gt;00&lt;/code&gt; und &lt;code&gt;77&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;windows&quot;&gt;Windows&lt;/h3&gt;

&lt;p&gt;Die Windows Konsole reagiert hier “eigen”, denn ein normales &lt;code&gt;ReadFile(STDIN)&lt;/code&gt;
interpretiert die Tasten nicht, das Konsolenfenster jedoch schon und 
“verbessert” eigenmächtig das UI, indem es eine History der letzten Eingaben
über die Pfeiltasten auslesen lässt.&lt;/p&gt;

&lt;p&gt;Man kann jedoch über die Konsolen-API 
&lt;a href=&quot;https://learn.microsoft.com/en-us/windows/console/readconsoleinput&quot;&gt;ReadConsoleInput&lt;/a&gt; 
alle Tastenereignisse abfangen und selbst interpretieren. Was sich nach 
Unicode abbilden lässt, erledigt Windows für uns, doch Sondertasten 
bekommen den Wert &lt;code&gt;0&lt;/code&gt;.&lt;br /&gt;
In dem Fall muss man den &lt;code&gt;VKEY&lt;/code&gt;-Code interpretieren, der mitgeliefert wird und
dort haben so gut wie alle üblichen Tasten eine Entsprechung.&lt;/p&gt;

&lt;h3 id=&quot;posix-linux&quot;&gt;POSIX (Linux)&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Unix&quot;&gt;Unix&lt;/a&gt; Varianten treten das Erbe von 
&lt;a href=&quot;https://de.wikipedia.org/wiki/VT100&quot;&gt;VT-100&lt;/a&gt; an und kodieren Sondertasten 
mit Escape-Sequenzen&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Up: &lt;code&gt;0x1b 0x5b 0x41&lt;/code&gt; = &lt;code&gt;^[[A&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Down: &lt;code&gt;0x1b 0x5b 0x42&lt;/code&gt; =  &lt;code&gt;^[[B&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Right: &lt;code&gt;0x1b 0x5b 0x43&lt;/code&gt; = &lt;code&gt;^[[C&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Left: &lt;code&gt;0x1b 0x5b 0x44&lt;/code&gt; = &lt;code&gt;^[[D&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Schlimmer ist hier, dass die Standard-Konsole auf &lt;code&gt;ENTER&lt;/code&gt; wartet, bevor ein
&lt;code&gt;read(STDIN)&lt;/code&gt; Eingaben lasen kann.
Um also einzelne Tasten direkt lesen zu können, muss man über &lt;code&gt;termios.h&lt;/code&gt; und
&lt;a href=&quot;https://linux.die.net/man/3/tcsetattr&quot;&gt;tcsetattr()&lt;/a&gt; die “Line-Discipline” 
ausschalten. Das wichtigste auszuschaltende Flag heißt &lt;code&gt;ICANON&lt;/code&gt;.
Danach kann man die Escape-Sequenzen selbst abprüfen.&lt;/p&gt;

&lt;h3 id=&quot;gate-implementierung&quot;&gt;GATE Implementierung&lt;/h3&gt;

&lt;p&gt;Einerseits sollte die Konsolen-API genau die Zeichen zurückgeben, die das
System liefert. Andererseits sind abstrakte Symbole für z.B. die Pfeiltasten
aber sehr notwendig um portable Programme zu schreiben.&lt;/p&gt;

&lt;p&gt;Der Kompromiss sieht also so aus, dass es eine native Schnittstelle zum
Lesen einzelner Zeichen gibt und einen “Input-Parser”, der aus den nativen
Zeichen wieder Tastenanschläge zusammensetzt.&lt;/p&gt;

&lt;p&gt;Für DOS und Linux war das relative einfach, weil man direkte Mapping-Tabellen
für die Zeichenübersetzung erstellen kann.&lt;/p&gt;

&lt;p&gt;Windows hingegen verdoppelte den Aufwand, denn zuerst musste ich mal die
&lt;code&gt;VKEYS&lt;/code&gt; in Unicode-Zeichen umwandeln, bevor diese dann per Mapping-Tabelle
in abstrakte Tasten konvertiert werden können.&lt;br /&gt;
Ich entschied mich für die neuen Icon-Zeichen in Unicode, wo die
Pfeiltasten-VKeys auf grafische Pfeile abgebildet werden, denn ich glaube
nicht, dass es in naher Zukunft Tastaturen geben wird, die diese Zeichencodes
direkt antippbar bereitstellen werden.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Der kleinste gemeinsame Nenner zwischen mehreren Systemen wird bei solchen
Aufgaben unerwartet groß, soll heißen: Die Unterschiede sind sehr groß.&lt;/p&gt;

&lt;p&gt;Meine Erwartung, dass es einen übergreifenden Standard gibt, hat sich nicht
erfüllt.&lt;/p&gt;

&lt;p&gt;Aber mit etwas Aufwand und 4 separaten Implementierungen 
(Windows, POSIX, DOS und &lt;a href=&quot;https://de.wikipedia.org/wiki/Unified_Extensible_Firmware_Interface&quot;&gt;EFI&lt;/a&gt;) 
habe ich nun meine eigene Konsolen- und Tastaturschnittstelle geschaffen, 
die für mein Vorhaben ausreicht.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Altes Debian für alte Hardware</title>
   <link href="https://www.opengate.at/blog/2023/04/old-debian/"/>
   <published>2023-04-09T13:00:00+02:00</published>
   <updated>2023-04-09T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2023/04/old-debian</id>
   <category term="software" /><category term="hardware" />
   <summary type="text">Mein aus dem Jahr 2005 stammende HP 
NX6310 Laptop lebt noch immer,
fristet aber sein Dasein auf der Reservebank.

Und ich dachte mir: Nachdem man nicht mal mit einem 
Raspberry PI 3 heute vernünftig 
“ins Internet” gehen kann, klappt das mit einem 1.4 GHz Single-Core 
Celeron erst recht nicht.

Doch man staune: Debian 
macht es möglich.

</summary>
   <content type="html">&lt;p&gt;Mein aus dem Jahr 2005 stammende &lt;a href=&quot;https://de.wikipedia.org/wiki/HP_Inc.&quot;&gt;HP&lt;/a&gt; 
NX6310 &lt;a href=&quot;https://de.wikipedia.org/wiki/Notebook&quot;&gt;Laptop&lt;/a&gt; lebt noch immer,
fristet aber sein Dasein auf der Reservebank.&lt;/p&gt;

&lt;p&gt;Und ich dachte mir: Nachdem man nicht mal mit einem 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Raspberry_Pi&quot;&gt;Raspberry PI&lt;/a&gt; 3 heute vernünftig 
“ins Internet” gehen kann, klappt das mit einem 1.4 GHz Single-Core 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Intel_Celeron&quot;&gt;Celeron&lt;/a&gt; erst recht nicht.&lt;/p&gt;

&lt;p&gt;Doch man staune: &lt;a href=&quot;https://de.wikipedia.org/wiki/Debian&quot;&gt;Debian&lt;/a&gt; 
macht es möglich.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Debian 7.0 (Wheezy) aus dem Jahr 2013 war damals mein erstes 
Debian &lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt; für den Raspberry PI, 
und mich beeindruckte schon damals, wie schnell die X86-Desktop-Variante 
bei mir auf meinen &lt;a href=&quot;https://de.wikipedia.org/wiki/Intel_Atom&quot;&gt;Intel Atom&lt;/a&gt; 
Maschinen lief.&lt;/p&gt;

&lt;p&gt;Zwar ist Debian auch heute noch ein flinkes System, aber dennoch wurde
es (wie alle seine Verwandten) mit jedem neuen Kernel und Userland größer 
und damit schwerfälliger.&lt;/p&gt;

&lt;p&gt;Deshalb wollte ich bewusst eine alte Distribution auf dem HP Laptop
einsetzen.&lt;/p&gt;

&lt;p&gt;Die Standard-Netzwerkinstallation erkannte auch sofort meine Hardware und 
den verbundenen Ethernet-Port, konnte aber keine Pakete finden.&lt;br /&gt;
Die Mirror-URLs, die damals gültig waren, existieren heute nicht mehr.&lt;/p&gt;

&lt;p&gt;Mit &lt;code&gt;archive.debian.org&lt;/code&gt; hat man jedoch immer noch ein Online
Repository, welches die ältesten Distributionsversionen bereitstellt.&lt;/p&gt;

&lt;p&gt;Sobald die neue URL manuell eingetragen ist, startet auch schon der
Download der gewünschten Software und richtet Debian auf der Festplatte
ein.&lt;/p&gt;

&lt;h3 id=&quot;verblüffend-schnell&quot;&gt;Verblüffend schnell&lt;/h3&gt;

&lt;p&gt;Ich gebe zu, ich habe die originale Festplatte durch eine 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Solid-State-Drive&quot;&gt;SSD&lt;/a&gt; ersetzt, aber nie 
hätte ich erwartet, wie verdammt schnell das Altgerät hochfahren kann.&lt;/p&gt;

&lt;p&gt;In 5 Sekunden ist das OS geladen und wartet auf die 
Benutzeranmeldung. Die von &lt;a href=&quot;https://de.wikipedia.org/wiki/Xfce&quot;&gt;XFCE&lt;/a&gt; 
verwalteten Fenster reagieren ebenfalls prompt auf Klicks und anderen Aktionen.&lt;/p&gt;

&lt;p&gt;Als Webbrowser stehen &lt;a href=&quot;https://de.wikipedia.org/wiki/Chromium_(Browser)&quot;&gt;Chromium&lt;/a&gt; 
37 und &lt;a href=&quot;https://de.wikipedia.org/wiki/Namensstreit_zwischen_Debian_und_Mozilla&quot;&gt;Iceweasel&lt;/a&gt;
38 (Ein Debian-fork von Firefox) zur Verfügung. 
“Meine Seiten” laden beide Browser deutlich schneller als das der
aktuelle Chromium am Raspberry PI 4 mit Debian 11 hinbekommt.
Hier hilft der kleinere Fußabdruck der Software deutlich die 
Ausführung zu optimieren.&lt;/p&gt;

&lt;p&gt;Andere Seiten wie &lt;code&gt;youtube.com&lt;/code&gt; funktionieren leider nicht, was aber an 
der Darstellung der Seiten liegt. Interessanterweise kann ich aber
problemlos Youtube-Videos abspielen, die über den
&lt;a href=&quot;/blog/2019/01/no-cookie/&quot;&gt;youtube-nocookie.com&lt;/a&gt; `` 
Link aufrufbar sind.&lt;/p&gt;

&lt;p&gt;Es ist also sogar “einfaches Multimedia” mit dem Veteran möglich.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;Hut ab vor Debian!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Erstens bin ich beeindruckt, dass die Installation einer 10 Jahre alten
Distro überhaupt noch funktioniert und erst recht “Hut ab” vor der 
unglaublichen Leistung, die das OS aus einem Celeron von 2005 herausholen
kann.&lt;/p&gt;

&lt;p&gt;Ein parallel installiertes &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_2000&quot;&gt;Windows 2000&lt;/a&gt; 
und XP kommen da in Sachen Reaktionszeit auf der Hardware bei weitem nicht 
mit.&lt;/p&gt;

&lt;p&gt;Die alte Regel, dass Debian einen hervorragenden Support für ältere Hardware
bietet, kann ich hiermit nur bestätigen.&lt;/p&gt;

&lt;p&gt;Auch in Sachen Nachhaltigkeit ist diese Erkenntnis wertvoll, denn wir lernen
hiermit, wie gut man auch heute noch mit alter Hardware arbeiten kann.
Für reine Office-Tätigkeit, wie auch die Programmierung ist das Gerät nämlich
immer noch gut geeignet.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Fail: Timeout NEVER = ?</title>
   <link href="https://www.opengate.at/blog/2023/04/timeout-never/"/>
   <published>2023-04-08T13:00:00+02:00</published>
   <updated>2023-04-08T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2023/04/timeout-never</id>
   <category term="devel" />
   <summary type="text">Ich mag Funktionen mit Timeouts, denn mit denen kann man “kalkulieren”,
während andere ewig blockieren können.

Folglich baue ich auch selbst gerne solche ein.
Doch … was ist, wenn man unendlich auf ein Ereignis warten will?
</summary>
   <content type="html">&lt;p&gt;Ich mag Funktionen mit Timeouts, denn mit denen kann man “kalkulieren”,
während andere ewig blockieren können.&lt;/p&gt;

&lt;p&gt;Folglich baue ich auch selbst gerne solche ein.&lt;br /&gt;
Doch … was ist, wenn man unendlich auf ein Ereignis warten will?
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Die kurze Antwort: Man kann zwei Funktionen für ein Feature implementieren.
Eine mit Timeout und eine ohne. Aber das ist lästig.&lt;/p&gt;

&lt;p&gt;An der Stelle tauchen dann (in vielen Frameworks) Konstanten auf, die die
Unendlichkeit repräsentieren.&lt;br /&gt;
Titel wie &lt;code&gt;NOTIMEOUT&lt;/code&gt;, &lt;code&gt;INFINITE&lt;/code&gt;, &lt;code&gt;NEVER&lt;/code&gt; und viele mehr sollen ausdrücken,
dass man nicht eine bestimmte Anzahl von Sekunden oder Millisekunden warten
soll, sondern so lange “blockieren” darf, bis die gewünschte Operation fertig
ist.&lt;/p&gt;

&lt;p&gt;Solche Timeout-Konstanten können aber Wertebereiche repräsentieren, 
die sich mit anderen Zeitangaben überlappen können.&lt;/p&gt;

&lt;p&gt;Ein Klassiker unter Windows ist &lt;code&gt;INFINITE&lt;/code&gt; welches als &lt;code&gt;DWORD&lt;/code&gt; Typ den
Wert &lt;code&gt;0xffffffff&lt;/code&gt; trägt.&lt;br /&gt;
Die meisten Warteroutinen akzeptieren einen &lt;code&gt;DWORD&lt;/code&gt; als Millisekundenwert,
somit man maximal maximal &lt;code&gt;4 294 967 295&lt;/code&gt; Millisekunden (50 Tage) auf ein
Ereignis warten kann.&lt;br /&gt;
Der &lt;code&gt;INFINITE&lt;/code&gt; Wert lässt das System allerdings ewig warten.&lt;/p&gt;

&lt;p&gt;Hier kann man dann den Fehler machen und das unendliche Timeout durch eine 
Subtraktion per Überlauf auf diesen Wert bringen.&lt;/p&gt;

&lt;p&gt;Ein anderer Klassiker ist die falsche Portierung dieses Wertes (z.B. auf Linux).&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;unsigned&lt;/span&gt; wait_infinite_ms = (&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;unsigned&lt;/span&gt;)-&lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;struct&lt;/span&gt; timespec timeout = { wait_infinite_ms / &lt;span style=&quot;color:#00D&quot;&gt;1000&lt;/span&gt;, wait_infinite_ms * &lt;span style=&quot;color:#00D&quot;&gt;1000000&lt;/span&gt; };
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;select(... &amp;amp;timeout);
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Es ist übrigens nicht lustig solche Fehler in anderen Programmen zu suchen, 
wenn die einzige Info ist:&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;Das Programm bleibt hängen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;-1--never&quot;&gt;-1 != NEVER&lt;/h3&gt;

&lt;p&gt;Ich bin dabei in meine eigene Falle getappt, als ich die DOS Keyboard
Warteroutinen erstellt habe. Ein leichtfertiges&lt;br /&gt;
&lt;code&gt;await_and_read_kbd(ptr_char, -1)&lt;/code&gt;&lt;br /&gt;
ließ genau &lt;code&gt;(unsigned int)-1&lt;/code&gt; Millisekunden Zeit verstreichen.
Und auf einem 16-Bit System sind das 65 Sekunden.&lt;/p&gt;

&lt;p&gt;Mein Problem lag in der Erwartungshaltung:&lt;br /&gt;
Warte unendlich lange auf Ereignis, brich bei Fehlern ab.
“Unendlich” bedeutet ohne Timeout, und der Timeout-Fehler nach
65 Sekunden brach dann unerwartet die Funktion ab.&lt;/p&gt;

&lt;p&gt;Wenn man also schon ein &lt;code&gt;NEVER&lt;/code&gt; als Zeiteinheit zulässt, dann muss man
diesen Spezialfall auch ausprogrammieren.&lt;/p&gt;

&lt;h3 id=&quot;wait-wait_for-wait_until&quot;&gt;wait, wait_for, wait_until&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B&quot;&gt;C++&lt;/a&gt; löst dieses Problem aus meiner 
Sicht sehr schön, indem es nicht auf eine API mit magischen Konstanten setzt, 
sondern in vielen Bereichen 3 Warte-Varianten anbietet.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;wait()&lt;/code&gt; wartet unendlich&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;wait_for()&lt;/code&gt; wartet eine fixe Zeitspanne ab&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;wait_until()&lt;/code&gt; wartet bis ein übergebener Zeitpunkt erreicht ist.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Eine solche Lösung schwebt mir daher in meinem C++-Layer auch vor.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;Man spielt nicht mit der Zeit, schon gar nicht mit der Unendlichkeit.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Tatsächlich sind mir Endlosschleifen wegen falscher Zeit und Warteroutinen
schon öfter untergekommen. Die Fixes sind dann in wenigen Zeilen durchgeführt,
aber das Auffinden solcher Schwachstellen ist mühsam.&lt;/p&gt;

&lt;p&gt;Es macht also Sinn, sich vorher über eine “gute API” den Kopf zu
zerbrechen und dieses Schema einheitlich projektweit umzusetzen, 
als auf Bugs und Inkonsistenzen zu warten.&lt;/p&gt;

&lt;p&gt;Leider spielen da auch viele Hilfsbibliotheken nicht gut mit, die 
Warteroutinen auch alle etwas anders ausgestalten.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Parameter per Kommandozeile</title>
   <link href="https://www.opengate.at/blog/2023/04/process-args/"/>
   <published>2023-04-02T13:00:00+02:00</published>
   <updated>2023-04-02T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2023/04/process-args</id>
   <category term="devel" />
   <summary type="text">Wenn Programme andere Programme starten sollen, stellt sich die Frage:

  Wie?


Die C Standard Bibliothek 
beantwortet das leider sehr unzufriedenstellend, doch trotzdem basieren 
viele Lösungen auf dem alten
system(&quot;myprog arg1 arg2&quot;) Schema.

Und da kann man leider auch viel falsch machen.
</summary>
   <content type="html">&lt;p&gt;Wenn Programme andere Programme starten sollen, stellt sich die Frage:&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;Wie?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Die &lt;a href=&quot;https://cplusplus.com/reference/cstdlib/&quot;&gt;C Standard Bibliothek&lt;/a&gt; 
beantwortet das leider sehr unzufriedenstellend, doch trotzdem basieren 
viele Lösungen auf dem alten&lt;br /&gt;
&lt;code&gt;system(&quot;myprog arg1 arg2&quot;)&lt;/code&gt; Schema.&lt;/p&gt;

&lt;p&gt;Und da kann man leider auch viel falsch machen.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;windows-vs-unix-vs-c&quot;&gt;Windows vs. Unix vs. C&lt;/h3&gt;

&lt;p&gt;Das aus &lt;a href=&quot;https://de.wikipedia.org/wiki/CP/M&quot;&gt;CP/M&lt;/a&gt; und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/MS-DOS&quot;&gt;DOS&lt;/a&gt; geborene 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows&quot;&gt;Windows&lt;/a&gt; verfolgt einen vom 
C-Standard abweichenden Weg mit “Befehlszeilenargumenten” umzugehen.&lt;br /&gt;
Denn während &lt;a href=&quot;https://de.wikipedia.org/wiki/Unix&quot;&gt;Unix&lt;/a&gt; Programme für 
erfahrene Profis gemacht wurden, die alles über eine Vielzahl von Parameter 
konfigurieren wollten, waren DOS und Windows Programme für Anfänger 
in Büros gedacht.&lt;/p&gt;

&lt;p&gt;Ein DOS/Windows Programm braucht keine Argumente, sondern startet ein UI,
in welchem der Benutzer seine Daten über eine “schöne” Maske findet.&lt;br /&gt;
Die “Profis” unter diesen Anfängern lernten dann, dass man den Start und
das Laden eines Programmes vereinen konnte, in dem man nach der Programmdatei
noch den Pfad zur Datendatei angab, wie:&lt;br /&gt;
&lt;code&gt;edit c:\my_diary.txt&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Hier unterscheiden sich DOS/Windows und Unix gewaltig, denn Windows leitet
diesen String einfach an das Programm weiter, während das Unix Programm von 
seinem Elternprozess ein Array von Strings für jeden Parameter erhält.&lt;br /&gt;
Man könnte auch sagen:&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;Windows ist auf genau einen Parameter optimiert bzw. eingeschränkt.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Bei DOS/Windows Programmen müssen also die Parameter im Prozess selbst 
auseinanderdividiert werden, während auf Unix-Systemen bereits der 
Elternprozess festlegt, wie viele Parameter übergeben werden.&lt;/p&gt;

&lt;p&gt;Problematisch wird das dann bei Leerzeichen, die es in DOS ursprünglich in
Dateinamen nicht gab, womit man den einen Befehlszeilen-String einfach
durch seine Leerzeichen aufspalten konnte.&lt;br /&gt;
Im Nachhinein wurde dann mit 
&lt;a href=&quot;https://learn.microsoft.com/en-us/windows/win32/api/shellapi/nf-shellapi-commandlinetoargvw&quot;&gt;CommandLineToArgv()&lt;/a&gt; 
eine API eingeführt, damit dieses Parsen auch unter Windows einheitlich 
wurde und C-Runtime darauf aufsetzen konnte. 
Hier werden nun nämlich Anführungszeichen (double quotes) benutzt, um einen
zusammengehörenden Parameter zu markieren.&lt;br /&gt;
z.B.: &lt;code&gt;my_app first_arg &quot;seconds arg&quot; &quot;and a third arg&quot;&lt;/code&gt;&lt;/p&gt;

&lt;h3 id=&quot;einfaches-und-doppeltes-anführungszeichen&quot;&gt;Einfaches und doppeltes Anführungszeichen&lt;/h3&gt;

&lt;p&gt;Die C Funktion &lt;code&gt;system(command_string)&lt;/code&gt; ruft die OS-Shell mit dem übergebenen Kommando 
auf, was unter Windows zu einen &lt;code&gt;CreateProcess()&lt;/code&gt; mit &lt;code&gt;cmd.exe /c &lt;/code&gt; + &lt;code&gt;command_string&lt;/code&gt; 
wird.
Die Linux C-Runtime nutzt ein &lt;code&gt;fork()&lt;/code&gt; / &lt;code&gt;exec()&lt;/code&gt; Paar mit dem Array&lt;br /&gt;
&lt;code&gt;[ &quot;/bin/sh&quot;, &quot;-c&quot;, command_string ]&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Das bedeutet also, wenn man Leerzeichen in Argumenten eines Zielprogramms
braucht (z.B.: für das Auflisten des Ordners &lt;code&gt;my folder&lt;/code&gt;), dann muss der
Aufruf den Leerzeichen-Parameter auch unter Anführungszeichen setzen.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;system(&amp;quot;dir \&amp;quot;my folder\&amp;quot;&amp;quot;);
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;wird am Ende zu:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Windows: &lt;code&gt;CreateProcess(&quot;cmd.exe /c dir \&quot;my folder\&quot;&quot;)&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Linux: &lt;code&gt;exec([ &quot;/bin/sh&quot;, &quot;-c&quot; &quot;dir \&quot;my folder\&quot;&quot; ] )&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Man könnte glauben, doppelte Anführungszeichen lösen somit alle Probleme und 
sind plattformunabhängig.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Leider falsch!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Jede Shell hat die Eigenschaft, dass sie Umgebungsvariablen expandieren
und Escapezeichen umwanden kann. Das trifft sowohl unter Windows wie auch 
unter Linux zu (wenn auch ganz unterschiedlich).&lt;/p&gt;

&lt;p&gt;Linux führte daher die einfachen Anführungszeichen ein (Hochkomma, single quotes), 
mit denen die Variablen und Zeichenauswertung verhindert wird.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;dir &quot;my folder&quot;&lt;/code&gt; und  &lt;code&gt;dir &apos;my folder&apos;&lt;/code&gt; liefern beide unter Linux das
gleiche Ergebnis, doch unter Windows wird der zweite Aufruf fehlschlagen, 
da die Hochkommata nicht interpretiert werden können.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;echo $HOME&lt;/code&gt; und &lt;code&gt;echo &quot;$HOME&quot;&lt;/code&gt; liefern unter Linux beide Male das 
tatsächliche Verzeichnis, das in der &lt;code&gt;HOME&lt;/code&gt; Variable gespeichert wird.&lt;br /&gt;
Doch der Aufruf &lt;code&gt;echo &apos;$HOME&apos;&lt;/code&gt; führt zur Ausgabe &lt;code&gt;$HOME&lt;/code&gt;, da der
Variablenverweis nicht durch den Inhalt ersetzt wird.&lt;/p&gt;

&lt;p&gt;An dieser Stelle unterscheidet sich also zusätzlich das Verhalten der Shells 
von Windows und Linux deutlich, denn um zu verhindern, dass in manche 
Argumente versehentlich Umgebungsvariablen eingeschleust werden, wird das 
Hochkomma &lt;code&gt;&apos;&lt;/code&gt; in vielen Anwendungen bevorzugt.&lt;/p&gt;

&lt;h3 id=&quot;beispielprogramm-system_cmd&quot;&gt;Beispielprogramm &lt;code&gt;system_cmd&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;Ich habe im BLOG Classroom das Beispielprogramm &lt;code&gt;system_cmd&lt;/code&gt; hinzugefügt, mit 
dem &lt;code&gt;system()&lt;/code&gt; Aufrufe per Kommandozeile ausgeführt werden können.
Hier kann man mitverfolgen, welche Kommandos wie im Prozess ankommen,
und was der Prozess selbst wieder an die Shell weitergibt, und was diese 
am Ende daraus macht.&lt;/p&gt;

&lt;p&gt;Hintergrund dieser Analyse war ein Bug in einer Software, wo es um die 
Weitergabe von Passwort-Token ging. Hier ist die Abschaltung der
Variablen- und Sonderzeichenauflösung sehr sinnvoll, denn ein einzelnes 
Dollarzeichen kann schnell zu falschen Daten führen.&lt;/p&gt;

&lt;p&gt;Ich sehe im Besonderen die Notwendigkeit, dass die Parameterverwaltung
für Windows und Linux unterschiedlich durchgeführt werden muss und 
Sonderzeichen manuell so umgestaltet werden müssen, dass die Shell daraus 
nichts Ungewolltes macht.&lt;/p&gt;

&lt;p&gt;Der Aufruf von Programmen, die sowohl unter Windows also auch unter Linux
verfügbar sind (z.B.: &lt;code&gt;curl&lt;/code&gt;), liefern beim Start durch &lt;code&gt;system()&lt;/code&gt; nicht 
immer die gleichen Ergebnisse.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;Oh Mann! Lieber nicht &lt;code&gt;system()&lt;/code&gt; benutzen!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Es gab schon früher einige Meldungen, dass &lt;code&gt;system()&lt;/code&gt; zum Hacken missbraucht
werden konnte. Hat man die Möglichkeit Teile des Strings zu manipulieren, 
kann man Schlimmste Sachen damit anstellen.&lt;/p&gt;

&lt;p&gt;Dass aber die Art der Anführungszeichen zu unterschiedlichem Handling in
der Shell führen können, hatte ich so deutlich bisher aber auch nicht auf 
dem Zeiger.&lt;/p&gt;

&lt;p&gt;Generell nutze ich selbst wenn möglich direkt die APIs des OS, 
also &lt;code&gt;exec()&lt;/code&gt; oder &lt;code&gt;CreateProcess()&lt;/code&gt; und nie &lt;code&gt;system()&lt;/code&gt;.&lt;br /&gt;
Damit bleiben mir “Interpretationsspielräume” der Shell erspart.
Leider machen es sich viele Projekte leicht und bauen “mal schnell” 
einen String zusammen. Der Grund liegt in der Einfachheit des Aufrufs …
sicher ist das aber nicht.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Das Gleiche gilt natürlich auch für&lt;/strong&gt; &lt;a href=&quot;https://www.man7.org/linux/man-pages/man3/popen.3.html&quot;&gt;popen()&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Nun geht für mich die Analyse weiter, in welchen anderen Projekten ich noch
solche &lt;code&gt;system()&lt;/code&gt; Zeitbomben finde.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Defragmentierung</title>
   <link href="https://www.opengate.at/blog/2023/04/defrag/"/>
   <published>2023-04-01T13:00:00+02:00</published>
   <updated>2023-04-01T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2023/04/defrag</id>
   <category term="software" />
   <summary type="text">Die Defragmentierung
von Festplatten war früher eines der schönsten Schauspiele, die ein 
DOS oder 
Windows PC mit sich brachte.

Heute ist sie in Vergessenheit geraten, obwohl im Hintergrund immer noch
stückweise “optimiert” wird.
</summary>
   <content type="html">&lt;p&gt;Die &lt;a href=&quot;https://de.wikipedia.org/wiki/Fragmentierung_(Dateisystem)#Defragmentierung&quot;&gt;Defragmentierung&lt;/a&gt;
von Festplatten war früher eines der schönsten Schauspiele, die ein 
&lt;a href=&quot;https://de.wikipedia.org/wiki/MS-DOS&quot;&gt;DOS&lt;/a&gt; oder 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows&quot;&gt;Windows&lt;/a&gt; PC mit sich brachte.&lt;/p&gt;

&lt;p&gt;Heute ist sie in Vergessenheit geraten, obwohl im Hintergrund immer noch
stückweise “optimiert” wird.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;geschichte&quot;&gt;Geschichte&lt;/h3&gt;

&lt;p&gt;Datenträger werden unordentlich, wenn ständig Daten gespeichert und wieder
gelöscht werden. Im Idealfall ist eine Datei nämlich in einem 
zusammenhängenden Block gespeichert, womit das Lesen linear in einem Stück 
erfolgen kann. Doch beim Löschen von Daten entstehen unregelmäßige Lücken, 
die nicht mehr von ganzen Dateien befüllt werden können, und somit müssen 
zusammenhängende Daten quer über den Datenträger verteilt gespeichert werden.&lt;/p&gt;

&lt;p&gt;Und weil das damals auf mechanischen Festplatten viel Zeit kostete, wurde
mit der “Defragmentierung” ein Werkzeug erschaffen, dass Dateien so lange
hin und her verschob, bis wieder alle Stücke lückenlos hintereinander 
angeordnet waren.&lt;/p&gt;

&lt;h3 id=&quot;dos&quot;&gt;DOS&lt;/h3&gt;

&lt;p&gt;DOS 6 lieferte das erste grafische &lt;code&gt;defrag.exe&lt;/code&gt; Programm mit, welches die
Festplatte als Blockmenge am Textbildschirm darstellte und man förmlich
zusehen konnte, wie die verstreuten Blöcke wieder zusammengesetzt wurden.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/dos-defrag.png&quot; alt=&quot;DOS defrag.exe&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Ein toller Nebeneffekt war übrigens, dass Verzeichnisse alphabetisch sortiert
wurden. Der Aufruf von &lt;code&gt;dir&lt;/code&gt; lieferte vor der Defragmentierung die Einträge
in der Reihe ihre Anlegung, danach konnte man schön von A-Z durchblättern.&lt;/p&gt;

&lt;h3 id=&quot;windows-9x&quot;&gt;Windows 9x&lt;/h3&gt;

&lt;p&gt;Ähnlich sah die Defragmentierung unter &lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_9x&quot;&gt;Windows 95/98&lt;/a&gt;
aus. Hier konnte man bereits scrollen und sah für jeden logischen 
Speicherblock ein Kästchen und je größer die Platte wurde um so länger
wurde die Liste.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/win95-defrag.gif&quot; alt=&quot;Win95 Defrag&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Windows 98 fügte dann noch Optimierungen hinzu, dass häufig genutzte Dateien
an den Anfang der Festplatte verschoben wurden, was mit 
Geschwindigkeitsgewinnen beworben wurde.&lt;/p&gt;

&lt;h3 id=&quot;windows-nt-4&quot;&gt;Windows NT 4&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_NT&quot;&gt;NT4&lt;/a&gt; hatte kein 
Defragmentierung-Tool dabei, weil man bereits verkündet hatte, dass das neue 
&lt;a href=&quot;https://de.wikipedia.org/wiki/NTFS&quot;&gt;NTFS&lt;/a&gt; Dateisystem so effizient sei, dass 
es zu keinen Fragmenten mehr kommen sollte (bzw. dass diese dann egal wären).&lt;/p&gt;

&lt;p&gt;Doch so ganz stimmte das auch nicht, und so lieferten Dritthersteller solche
Tools nach.&lt;br /&gt;
&lt;code&gt;oodefrag&lt;/code&gt; war eine kostenlose Variante, die ich damals einsetzte. Sie setzte
den &lt;a href=&quot;https://de.wikipedia.org/wiki/Internet_Explorer&quot;&gt;Internet-Explorer&lt;/a&gt; 5.0 
und die &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Management_Console&quot;&gt;MMC&lt;/a&gt;
voraus, was beides kein Grundbestandteil von NT war und nachinstalliert 
werden musste.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/app-mmc-1.gif&quot; alt=&quot;MMC 1.2 for NT 4&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/app-oodefrag.gif&quot; alt=&quot;O&amp;amp;O Defrag 2000 Freeware Edition&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;windows-2000xp&quot;&gt;Windows 2000/XP&lt;/h3&gt;

&lt;p&gt;Mit NT 5 (also &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_2000&quot;&gt;Windows 2000&lt;/a&gt;) 
lieferte Microsoft wieder selbst ein Defragmentierung-Tool mit und ließ es
auch automatisch von Zeit zu Zeit im Hintergrund durchlaufen.
Die Anzeige wurde stark vereinfacht und zeigte nur noch einen Querbalken an,
der ein Laufwerk und seine Daten repräsentierte.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/win2k-defrag.gif&quot; alt=&quot;Win2000 Defrag&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Die Darstellung von einzelnen Blöcken wurde durch die stark gewachsene 
Speichergröße unmöglich gemacht. Startete man zu Windows NT Zeiten noch mit 
Festplatten im 1 GB Bereich, musste ein Windows Server 2003 schon mit 100 GB 
und mehr umgehen können.&lt;br /&gt;
Diese Datenmengen kann man nicht mehr sinnvoll durch einzelne Kästchen oder 
Bildpunkte darstellen.&lt;/p&gt;

&lt;h3 id=&quot;ab-vista-und-windows-7&quot;&gt;Ab Vista und Windows 7&lt;/h3&gt;

&lt;p&gt;Ab NT 6 (&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_Vista&quot;&gt;Windows Vista&lt;/a&gt;) 
erreicht die Defragmentierung quasi ihr endgültiges Aussehen.
Nun sehen wir nur noch eine Prozentzahl in einer Listview, die während der
Defragmentierung hochzählt.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/app-defrag-win7.gif&quot; alt=&quot;Win7 Defrag&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Diese Optik wurde leicht angepasst auch in 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_8&quot;&gt;Windows 8&lt;/a&gt;, 10 und 11 sowie 
den entsprechenden Server Varianten übernommen.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/app-defrag-win10.gif&quot; alt=&quot;Win10 Defrag&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Windows unterscheidet seit dieser Zeit aktiv zwischen 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Festplattenlaufwerk&quot;&gt;klassischen Festplatten&lt;/a&gt;
und neuen &lt;a href=&quot;https://de.wikipedia.org/wiki/Solid-State-Drive&quot;&gt;SSDs&lt;/a&gt; und führt 
auf der moderneren Hardware keine übliche Defragmentierung mehr durch.&lt;/p&gt;

&lt;p&gt;Der als “Optimierung” bezeichnete Vorgang sendet nun das 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Solid-State-Drive#Leistungsverlust_bei_Verwendung_(TRIM_und_Garbage_Collection)&quot;&gt;TRIM&lt;/a&gt; 
Kommando an die SSD um freie Sektoren dem SSD-Controller zu melden. 
Dieser kann deren Speicherzellen dann intelligent wiederverwenden und 
braucht den Inhalt nicht bewahren.&lt;/p&gt;

&lt;p&gt;Mit SSDs ist es egal, ob Dateistücke hintereinander liegen, denn
der Zugriff auf die einzelnen Sektoren erfolgt durch den Controller
annähernd gleich schnell und außerdem organisiert dieser die Daten intern
nach anderen Kriterien. Die Daten des logischen Sektor 2 müssen in der SSD
nicht “direkt hinter” dem logischen Sektor 1 liegen.&lt;br /&gt;
Eine klassische Defragmentierung ist hier also unnötig und nutzt durch das 
Umschreiben lediglich die Speicherzellen sinnlos ab.&lt;/p&gt;

&lt;h3 id=&quot;ssds-trotzdem-defragmentieren&quot;&gt;SSDs trotzdem defragmentieren&lt;/h3&gt;

&lt;p&gt;Will man aber dennoch alle seine Dateien defragmentiert Sektor für Sektor
hintereinander vorliegen haben, lässt sich Windows über das Konsolenkommando&lt;br /&gt;
&lt;code&gt;defrag C: /PrintProgress /FreespaceConsolidate&lt;/code&gt; dazu bewegen.&lt;/p&gt;

&lt;p&gt;Das hilft vor allem, wenn man ein Laufwerk verkleinern möchte und freien
Platz am Ende des Datenträgers sicherstellen will.
Die “Konsolidierung des freien Speicherplatzes” ist auch sinnvoll, wenn man 
ein Low-level &lt;a href=&quot;https://de.wikipedia.org/wiki/Speicherabbild&quot;&gt;Image&lt;/a&gt; eines 
Datenträgers anlegt, denn dann liegen die Dateien auch dort in einem Stück 
hintereinander in der Image Datei.&lt;br /&gt;
Ich würde jedoch ein &lt;a href=&quot;https://learn.microsoft.com/en-us/windows-hardware/manufacture/desktop/capture-and-apply-windows-using-a-single-wim&quot;&gt;WIM Image&lt;/a&gt;
einem Sektor-für-Sektor Image vorziehen, und für 
&lt;a href=&quot;https://learn.microsoft.com/de-de/windows-hardware/manufacture/desktop/what-is-dism&quot;&gt;dism&lt;/a&gt; 
und &lt;code&gt;.wim&lt;/code&gt; Dateien ist die Fragmentierung wiederum gleichgültig.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Das Defragmentieren der Festplatte gehörte um das Jahr 2000 herum zu den 
üblichen “Wartungsvorgängen”, die man unwissenden Kunden als notwendigen
Service aufschwatzen konnte, und was auch immer eindrucksvoll präsentierbar 
war.&lt;/p&gt;

&lt;p&gt;Heute klicke ich eher zufällig jedes halbe Jahr auf den “Optimieren” Knopf,
meist nach einem größeren Cleanup oder Backup.&lt;br /&gt;
Geschwindigkeitsvorteile bringt einem das keine mehr ein … doch es 
bewirkt immer noch den &lt;a href=&quot;https://de.wikipedia.org/wiki/Placebo&quot;&gt;Placebo-Effekt&lt;/a&gt;, 
dass man glaubt, man hätte danach einen saubereren Datenträger vor sich.&lt;/p&gt;

&lt;p&gt;In diesem Sinne:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Defragmentiert immer brav eure Festplatten!&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>QBasic: CALL ABSOLUTE</title>
   <link href="https://www.opengate.at/blog/2023/03/call-absolute/"/>
   <published>2023-03-26T13:00:00+02:00</published>
   <updated>2023-03-26T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2023/03/call-absolute</id>
   <category term="devel" /><category term="retro" />
   <summary type="text">Als ich in den 90ern meine DOS und 
QBASIC-Babyschritte machte, lernte ich,
dass “Systemroutinen” (auch als “Software-Interrupts” bekannt) mit QBasic 
nicht möglich waren, jedoch in QuickBasic 4.5+ unterstützt wurden.

Es gab jedoch einen dunklen Hack, mit dem auch das kostenlose QBasic
“mächtiger” werden konnte … doch mir war das damals leider nicht bewusst.
</summary>
   <content type="html">&lt;p&gt;Als ich in den 90ern meine &lt;a href=&quot;https://de.wikipedia.org/wiki/MS-DOS&quot;&gt;DOS&lt;/a&gt; und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/QBasic&quot;&gt;QBASIC&lt;/a&gt;-Babyschritte machte, lernte ich,
dass “Systemroutinen” (auch als “Software-Interrupts” bekannt) mit &lt;code&gt;QBasic&lt;/code&gt; 
nicht möglich waren, jedoch in &lt;code&gt;QuickBasic&lt;/code&gt; 4.5+ unterstützt wurden.&lt;/p&gt;

&lt;p&gt;Es gab jedoch einen dunklen Hack, mit dem auch das kostenlose &lt;code&gt;QBasic&lt;/code&gt;
“mächtiger” werden konnte … doch mir war das damals leider nicht bewusst.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Die Compiler-Sprachen von damals (wie Turbo-C oder 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Turbo_Pascal&quot;&gt;Turbo-Pascal&lt;/a&gt;)
ließen sowohl inline-&lt;a href=&quot;https://de.wikipedia.org/wiki/Assemblersprache&quot;&gt;Assembler&lt;/a&gt;
wie auch Interrupt-Aufrufe zu.
Doch dem &lt;code&gt;QBasic&lt;/code&gt;-Interpreter fehlten solche Mechanismen.
Nur das kommerzielle QuickBasic bot eine Interrupt-Bibliothek an, 
um Systemroutinen aufrufen zu können.&lt;/p&gt;

&lt;p&gt;Doch &lt;code&gt;QBasic&lt;/code&gt; und mache seiner Vorfahren gestatteten es, Bytes im Speicher
direkt zu setzen. Und so konnten kleine Programmteile manuell in den
Speicher geschrieben werden.&lt;br /&gt;
Und mit der Anweisung &lt;code&gt;CALL ABSOLUTE&lt;/code&gt; konnte man eine beliebige 
Speicheradresse einfach anspringen um den dortigen Code auszuführen.&lt;/p&gt;

&lt;h3 id=&quot;x86-assembly-code-dynamisch-mit-qbasic-kompilieren&quot;&gt;X86-Assembly Code dynamisch mit QBASIC kompilieren&lt;/h3&gt;

&lt;p&gt;Wenn man weiß wie, ist es einfach:&lt;br /&gt;
Man allokiert ein Array in QBASIC, schreibt den korrektn Maschinencode 
mit &lt;code&gt;POKE&lt;/code&gt; Aufrufen in das Array, holt sich dan mit &lt;code&gt;VARPTR&lt;/code&gt; und 
&lt;code&gt;VARSEG&lt;/code&gt; die Adresse und lässt &lt;code&gt;CALL ABSOUTE&lt;/code&gt; den Code ausführen.&lt;/p&gt;

&lt;p&gt;In meinem Beispiel im Classroom unter&lt;br /&gt;
&lt;a href=&quot;https://codeberg.org/GateNetwork/gate-blog-classroom/src/branch/main/basic/call_absolute/callabs.bas&quot;&gt;basic/call_absolute/callabs.bas&lt;/a&gt;
sieht man aber, dass das in &lt;code&gt;QBASIC&lt;/code&gt; recht mühsam sein kann.&lt;/p&gt;

&lt;p&gt;In Assembler würde das Unterprogramm etwa so aussehen:&lt;/p&gt;

&lt;div class=&quot;language-asm highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;push bp         ; prolog
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;mov bp, sp
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;mov ax, ds      ; DS segment auf stack sichern
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;push ax
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;mov ax, es      ; ES segment auf stack sichern
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;push ax
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;mov ax, [my_ds] ; neues DS segment laden
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;mov ds, ax
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;mov ax, [my_es] ; neues ES segment laden
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;mov es, ax
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;mov ax, [my_ax] ; gewünschtes AX laden
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;mov bx, [my_bx] ; gewünschtes BX laden
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;mov cx, [my_cx] ; gewünschtes CX laden
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;mov dx, [my_dx] ; gewünschtes DX laden
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;mov si, [my_si] ; gewünschtes SI laden
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;mov di, [my_di] ; gewünschtes DI laden
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;int intNum      ; interrupt aufrufen
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n21&quot; name=&quot;n21&quot;&gt;21&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n22&quot; name=&quot;n22&quot;&gt;22&lt;/a&gt;&lt;/span&gt;pop ax          ; gesichertes ES segment zurückholen
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n23&quot; name=&quot;n23&quot;&gt;23&lt;/a&gt;&lt;/span&gt;mov es, ax
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n24&quot; name=&quot;n24&quot;&gt;24&lt;/a&gt;&lt;/span&gt;pop ax          ; gesichertes DS segment zurückholen
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n25&quot; name=&quot;n25&quot;&gt;25&lt;/a&gt;&lt;/span&gt;mov ds, ax
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n26&quot; name=&quot;n26&quot;&gt;26&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n27&quot; name=&quot;n27&quot;&gt;27&lt;/a&gt;&lt;/span&gt;pop bp          ; epilog
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n28&quot; name=&quot;n28&quot;&gt;28&lt;/a&gt;&lt;/span&gt;ret
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Doch in QBASIC ist das Befüllen eines Arrays mit Byte-Werten ein Krampf:&lt;/p&gt;

&lt;div class=&quot;language-basic highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;DIM op(1 TO 64) AS INTEGER
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;DIM i AS INTEGER
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;i = 1
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;REM ---- jeder Menge Code davor ----
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;REM ---- MOV AX, (regs.ax)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;op(i) = &amp;amp;HB8: i = i + 1
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;op(i) = regs.ax AND &amp;amp;HFF: i = i + 1
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;op(i) = (regs.ax \ 256) AND &amp;amp;HFF: i = i + 1
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;REM ---- MOV BX, (regs.bx)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;op(i) = &amp;amp;HBB: i = i + 1
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;op(i) = regs.bx AND &amp;amp;HFF: i = i + 1
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;op(i) = (regs.bx \ 256) AND &amp;amp;HFF: i = i + 1
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;REM ---- MOV CX, (regs.cx)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;op(i) = &amp;amp;HB9: i = i + 1
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;op(i) = regs.bx AND &amp;amp;HFF: i = i + 1
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;op(i) = (regs.bx \ 256) AND &amp;amp;HFF: i = i + 1
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n21&quot; name=&quot;n21&quot;&gt;21&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n22&quot; name=&quot;n22&quot;&gt;22&lt;/a&gt;&lt;/span&gt;REM ---- MOV DX, (regs.dx)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n23&quot; name=&quot;n23&quot;&gt;23&lt;/a&gt;&lt;/span&gt;op(i) = &amp;amp;HBA: i = i + 1
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n24&quot; name=&quot;n24&quot;&gt;24&lt;/a&gt;&lt;/span&gt;op(i) = regs.dx AND &amp;amp;HFF: i = i + 1
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n25&quot; name=&quot;n25&quot;&gt;25&lt;/a&gt;&lt;/span&gt;op(i) = (regs.dx \ 256) AND &amp;amp;HFF: i = i + 1
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n26&quot; name=&quot;n26&quot;&gt;26&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n27&quot; name=&quot;n27&quot;&gt;27&lt;/a&gt;&lt;/span&gt;REM ---- INT num
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n28&quot; name=&quot;n28&quot;&gt;28&lt;/a&gt;&lt;/span&gt;op(i) = &amp;amp;HCD: i = i + 1
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n29&quot; name=&quot;n29&quot;&gt;29&lt;/a&gt;&lt;/span&gt;op(i) = intNum: i = i + 1
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n30&quot; name=&quot;n30&quot;&gt;30&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n31&quot; name=&quot;n31&quot;&gt;31&lt;/a&gt;&lt;/span&gt;REM ---- jede Menge Code danach ----
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n32&quot; name=&quot;n32&quot;&gt;32&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n33&quot; name=&quot;n33&quot;&gt;33&lt;/a&gt;&lt;/span&gt;DIM asmFunc(1 TO 64) AS INTEGER
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n34&quot; name=&quot;n34&quot;&gt;34&lt;/a&gt;&lt;/span&gt;asmFuncAddr = VARPTR(asmFunc(1))
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n35&quot; name=&quot;n35&quot;&gt;35&lt;/a&gt;&lt;/span&gt;DEF SEG = VARSEG(asmFunc(1))
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n36&quot; name=&quot;n36&quot;&gt;36&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n37&quot; name=&quot;n37&quot;&gt;37&lt;/a&gt;&lt;/span&gt;REM ---- INT-Array-Werte zu echtem Bytecode übertragen
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n38&quot; name=&quot;n38&quot;&gt;38&lt;/a&gt;&lt;/span&gt;FOR n = 0 TO i - 1
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n39&quot; name=&quot;n39&quot;&gt;39&lt;/a&gt;&lt;/span&gt;    POKE (asmFuncAddr + n), op(n + 1)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n40&quot; name=&quot;n40&quot;&gt;40&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;NEXT n
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n41&quot; name=&quot;n41&quot;&gt;41&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n42&quot; name=&quot;n42&quot;&gt;42&lt;/a&gt;&lt;/span&gt;CALL ABSOLUTE(VARPTR(asmFunc(1)))
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Ich setze also einen Eintrag von &lt;code&gt;op(i)&lt;/code&gt; auf eine CPU-Instruktion, und
dann folgt immer ein &lt;code&gt;i = i + 1&lt;/code&gt; …&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Oh Mann, da lernt an C echt wieder lieben, wo es einfach heißt:&lt;br /&gt;
&lt;code&gt;op[i++] = 0xab;&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;vorsicht-beim-hin--und-rücksprung&quot;&gt;Vorsicht beim Hin- und Rücksprung&lt;/h3&gt;

&lt;p&gt;Es gibt ja mehrere &lt;code&gt;ret&lt;/code&gt; Varianten, wir brauchen hier Opcode &lt;code&gt;CB&lt;/code&gt; für 
einen &lt;code&gt;far&lt;/code&gt;-return.&lt;br /&gt;
Und auch &lt;code&gt;CALL ABSOLUTE&lt;/code&gt; funktioniert nur dann, wenn in der Zeile
das ganze&lt;br /&gt;
&lt;code&gt;CALL ABSOLUTE(VARPTR(asmFunc(1)))&lt;/code&gt; steht.
Mit dem vorherigen &lt;code&gt;asmFuncAddr&lt;/code&gt; klappt es nicht.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Genau so eine Funktion hatte mir damals gefehlt, um per DOS das Dateisystem
zu durchforsten oder per &lt;code&gt;INT 10h&lt;/code&gt; und &lt;code&gt;INT 13h&lt;/code&gt; Grafikkarten und
Disketten zu kontrollieren.&lt;/p&gt;

&lt;p&gt;All das gelang mir am Ende mit &lt;code&gt;Turbo Pascal&lt;/code&gt; etwas später.&lt;br /&gt;
Aber Schade, dass mir diese Welt nicht gleich in &lt;code&gt;QBASIC&lt;/code&gt; offen stand.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Faszinierend:&lt;br /&gt;
Eine Programmidee von mir nach über 30 Jahren fertiggestellt.&lt;br /&gt;
Das kann nicht mal
&lt;a href=&quot;https://de.wikipedia.org/wiki/Duke_Nukem&quot;&gt;Duke Nukem&lt;/a&gt; toppen.&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>Spezialfälle in Windows 95</title>
   <link href="https://www.opengate.at/blog/2023/03/missing-win95/"/>
   <published>2023-03-25T12:00:00+01:00</published>
   <updated>2023-03-25T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2023/03/missing-win95</id>
   <category term="devel" /><category term="software" /><category term="retro" />
   <summary type="text">Aus API Sicht waren 
Windows 95, 98 und ME für mich so 
ziemlich das gleiche, nämlich ein reduziertes Set von 
NT4. 
Die Frage war damals also:


  Ist etwas kompatibel mit “NT4” oder “nur 9x”.


Doch … Windows 95 war stets “weniger”, der Support wurde schnell fallen
gelassen als 98 auf den Markt kam … und heute verstehe ich erst, 
warum das so war.
</summary>
   <content type="html">&lt;p&gt;Aus &lt;a href=&quot;https://de.wikipedia.org/wiki/Programmierschnittstelle&quot;&gt;API&lt;/a&gt; Sicht waren 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_9x&quot;&gt;Windows 95, 98 und ME&lt;/a&gt; für mich so 
ziemlich das gleiche, nämlich ein reduziertes Set von 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_NT_4.0&quot;&gt;NT4&lt;/a&gt;. 
Die Frage war damals also:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ist etwas kompatibel mit “NT4” oder “nur 9x”.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Doch … Windows 95 war stets “weniger”, der Support wurde schnell fallen
gelassen als 98 auf den Markt kam … und heute verstehe ich erst, 
warum das so war.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Das schöne an &lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_Basic_Classic&quot;&gt;Visual Basic 6&lt;/a&gt; 
Code war: Er lief überall, da er nur Windows 95 als Minimum voraussetzte und 
selbst dort nur Teile der 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_Application_Programming_Interface&quot;&gt;Windows API&lt;/a&gt;
nutzte.&lt;/p&gt;

&lt;p&gt;In &lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B&quot;&gt;C/C++&lt;/a&gt; musst man sich über diverse 
Makros entscheiden, ob man bei NT4 startete, oder nur:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;das 95er Subset&lt;/li&gt;
  &lt;li&gt;95 + IE4&lt;/li&gt;
  &lt;li&gt;98&lt;/li&gt;
  &lt;li&gt;98 + IE5&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;usw. einsetzen wollte. Je nach Wahl wurden mehr APIs freigeschaltet, bzw. neue Flags und
&lt;code&gt;struct&lt;/code&gt;s für diese APIs.&lt;/p&gt;

&lt;p&gt;Windows 95 (auch als v4.0 bekannt) war das erste 32-bit OS mit “neuem” Design 
und man mag denken, es wäre der kleine Bruder von NT4 (auch v4.0), doch es
liegt in Wahrheit irgendwo zwischen NT 3.5 und NT 4.0.&lt;/p&gt;

&lt;h3 id=&quot;fehlende-komponenten&quot;&gt;Fehlende Komponenten&lt;/h3&gt;

&lt;p&gt;Meine neulichen Compiler-Experimente mit
&lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_Studio&quot;&gt;Visual Studio&lt;/a&gt; 2003 deckten auf,
dass GATE Code zwar auf Windows 98 liefen, unter 95 jedoch mit fehlenden 
Einsprungpunkten abbrachen.&lt;/p&gt;

&lt;h4 id=&quot;interlocked-compare-exchange&quot;&gt;Interlocked Compare Exchange&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;InterlockedIncrement()&lt;/code&gt;, &lt;code&gt;...Decrement&lt;/code&gt; und &lt;code&gt;...Exchange&lt;/code&gt; gab es bereits, 
doch &lt;code&gt;InterlockedAdd()&lt;/code&gt; und &lt;code&gt;InterlockedCompareExchange()&lt;/code&gt; fehlten. Das 
bedeutet: Reference-Counting-Support ist da, State-Machine-Support nicht.&lt;/p&gt;

&lt;p&gt;Ich nutze &lt;code&gt;CompareExchange&lt;/code&gt; häufig zum sicheren Umschalten zwischen Zuständen
und das tun auch andere Bibliotheken.&lt;/p&gt;

&lt;h4 id=&quot;winsock-1&quot;&gt;Winsock 1&lt;/h4&gt;

&lt;p&gt;Es gibt de facto keine Software, die nicht gegen &lt;code&gt;ws2_32.dll&lt;/code&gt;, also Winsock-2
linkt, wenn sie 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Transmission_Control_Protocol/Internet_Protocol&quot;&gt;TCP/IP&lt;/a&gt;
braucht, doch eben diese DLL fehlte im originalen Win95.
Sie wurde zwar mit dem Internet Explorer nachgeliefert … doch der war damals
eben noch kein Standard.&lt;br /&gt;
Während NT4 und 98 somit “jede” Netzwerk Software ausführen konnte, wurde 95
meist ausgeschlossen.&lt;/p&gt;

&lt;h4 id=&quot;utf-8&quot;&gt;UTF-8&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;WideCharToMultiByte()&lt;/code&gt; und &lt;code&gt;MultiByteToWideChar()&lt;/code&gt; sind die beiden wichtigsten
Funktionen, um zwischen NT’s Unicode Strings und alten Win9x ANSI Strings hin
und her zu konvertieren. Mit dem Flag &lt;code&gt;CP_UTF8&lt;/code&gt; war auch UTF-8 als &lt;code&gt;char&lt;/code&gt;-Output
möglich … doch erst ab 98.&lt;/p&gt;

&lt;p&gt;Mir flog das als “unerklärbarer” Fehler um die Ohren, denn im GATE Projekt
sind alle Strings UTF-8 und müssen entweder nach UTF-16 oder ANSI konvertiert
werden, wenn Windows-APIs aufgerufen werden.&lt;/p&gt;

&lt;h4 id=&quot;fibers&quot;&gt;Fibers&lt;/h4&gt;

&lt;p&gt;Die Fiber-APIs kommen ebenso erst mit Windows 98, obwohl sie schon in NT 3.51
implementiert waren.&lt;br /&gt;
Zwar sind Fibers im GATE Projekt optional, doch nun weiß ich: 
&lt;a href=&quot;https://de.wikipedia.org/wiki/OpenSSL&quot;&gt;OpenSSL&lt;/a&gt; und andere Hilfsbibliotheken 
nutzen ebenso Fibers oder fragen zumindest ab, ob die Ausführung auf einem 
Thread oder einem Fiber läuft.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Meine Lösung zur Umgehung dieser Probleme ist: im ANSI-Modus werden die
fehlenden APIs durch Fallbacks ersetzt.
Unicode Varianten laufen daher ab NT4 mit Standard APIs, ANSI Varianten
implementieren Fallbacks für Windows 95.&lt;/p&gt;

&lt;p&gt;Mein größtes Problem sind Fremdbibliotheken, für die habe ich aktuell
keine richtige Lösung. Zwar wäre es möglich per Makros die Aufrufe von
Fiber- und Interlocked-Code auf selbst implementierte Hilfsfunktionen
umzuleiten … aber wer weiß, ob das Ergebnis dann korrekt ist.&lt;/p&gt;

&lt;p&gt;Vorerst muss ich leider Tools mit SSL und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/SQLite&quot;&gt;SQLite&lt;/a&gt; von Windows 95 ausschließen.
Und das ist deshalb ärgerlich, weil es nur 2 oder 3 Aufrufe innerhalb 
dieser Bibliotheken gibt.&lt;/p&gt;

&lt;p&gt;Doch ich habe nun (20 Jahre zu spät) endlich gelernt, warum einige 
Projekte damals einfach nicht Win95-kompatibel waren.&lt;br /&gt;
Ich dachte damals, dass UI-Spezialitäten daran Schuld wären, doch die
Ursache lag teilweise viel tiefer.&lt;/p&gt;

&lt;p&gt;Relevanz hat diese Erkenntnis heute keine mehr.
Doch sie zeigt die historische Entwicklung und Integration von Funktionen
bzw. deren Prioritäten recht gut auf.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Codeberg: das bessere Github</title>
   <link href="https://www.opengate.at/blog/2023/03/codeberg/"/>
   <published>2023-03-19T12:00:00+01:00</published>
   <updated>2023-03-19T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2023/03/codeberg</id>
   <category term="software" />
   <summary type="text">Ich bin 2018 nur deshalb zu Bitbucket 
gegangen, weil man dort kostenlose private 
Repos 
anlegen konnte.
Erst ein Jahr später zogen Github 
und andere nach, doch einen Grund zur Migration gab es für mich keinen.

Mit Codeberg ist in Deutschland ein offener und 
kostenloser Git-Hoster aufgetaucht, 
der mich aber über einen Umzug nachdenken lässt:


  Der Code liegt auf Servern in der EU … also “bei Freunden”.


</summary>
   <content type="html">&lt;p&gt;Ich bin 2018 nur deshalb zu &lt;a href=&quot;https://de.wikipedia.org/wiki/Bitbucket&quot;&gt;Bitbucket&lt;/a&gt; 
gegangen, weil man dort kostenlose private 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Repository#Software-Repository&quot;&gt;Repos&lt;/a&gt; 
anlegen konnte.&lt;br /&gt;
Erst ein Jahr später zogen &lt;a href=&quot;https://de.wikipedia.org/wiki/GitHub&quot;&gt;Github&lt;/a&gt; 
und andere nach, doch einen Grund zur Migration gab es für mich keinen.&lt;/p&gt;

&lt;p&gt;Mit &lt;a href=&quot;http://codeberg.org/&quot;&gt;Codeberg&lt;/a&gt; ist in Deutschland ein offener und 
kostenloser &lt;a href=&quot;https://de.wikipedia.org/wiki/Git&quot;&gt;Git&lt;/a&gt;-Hoster aufgetaucht, 
der mich aber über einen Umzug nachdenken lässt:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Der Code liegt auf Servern in der EU … also “bei Freunden”.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;server-politik&quot;&gt;Server-Politik&lt;/h3&gt;

&lt;p&gt;Ich habe bereits im Jahr 2005 gelernt, dass Software auf Servern innerhalb 
der &lt;a href=&quot;https://de.wikipedia.org/wiki/Vereinigte_Staaten&quot;&gt;USA&lt;/a&gt; durchaus 
“problematisch” sein können. Denn wer auch immer es sich mit der US-Regierung
verscherzt, bekommt den Zorn in allen Geschäftsbereichen zu spüren.&lt;/p&gt;

&lt;p&gt;Und so wird allen US-Unternehmen untersagt in irgend einer Form Handel mit
Staaten zu betreiben, die nicht genehm sind. Und das betraf damals viele
Länder, die in irgend einer Form mit Afghanistan oder dem Irak zu tun hatten.&lt;/p&gt;

&lt;p&gt;Und heute trifft das vor allem die Umgebung von Russland.&lt;/p&gt;

&lt;p&gt;Jetzt kann ich das durchaus nachvollziehen, dass ein Staat seinem 
Kriegsgegner kein “Ressourcen schenken” will, doch leider sind von solchen
Sanktionen auch &lt;a href=&quot;https://de.wikipedia.org/wiki/Open_Source&quot;&gt;Open Source&lt;/a&gt;
Projekte betroffen.&lt;br /&gt;
Das bedeutet, da wird gerade den Jungs und Mädels, die für eine 
fortschrittliche freie Gesellschaft stehen und die sich dort beteiligen 
wollen, der Zugang zu Wissen und der Zugang zur Beteiligungsmöglichkeit
entzogen.&lt;br /&gt;
Und das darf eigentlich nicht sein.&lt;/p&gt;

&lt;h3 id=&quot;codeberg&quot;&gt;Codeberg&lt;/h3&gt;

&lt;p&gt;Der Berliner Verein Codeberg e.V. hat vor ein paar Jahren ein 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Gitea&quot;&gt;gitea&lt;/a&gt; basiertes GIT Hosting gestartet, 
welches ähnlich zu &lt;code&gt;Github&lt;/code&gt; und Konsorten ist, jedoch seinen Sitz innerhalb 
der EU hat und somit von den üblichen Spielen der “Großmächte” vorerst 
verschont ist.&lt;/p&gt;

&lt;p&gt;Ich will jetzt nicht schlecht über Projekte auf Servern in anderen Staaten
sprechen, aber wenn es um Rechtssicherheit und Eigenständigkeit geht, dann
kann man sich aktuell auf die EU am ehesten verlassen, dass sie die Rechte
der Bürger schützt.&lt;/p&gt;

&lt;p&gt;Die Gesinnung des Projektes kann man auch nur positiv hervorheben, denn 
sie stellt die “Bewahrung freier Inhalte” in den Mittelpunkt.
Und da das Projekt nun schon ein paar Jahre online ist, kann man davon 
ausgehen, dass die Starthürden bezwungen wurden.&lt;/p&gt;

&lt;p&gt;Im Netz findet man eine stetig wachsende Gruppe von Anwendern, die mit
den Diensten zufrieden sind.&lt;br /&gt;
Stand heute: 66000 Projekte von 52000 Benutzern.&lt;/p&gt;

&lt;h4 id=&quot;woodpecker-ci&quot;&gt;Woodpecker CI&lt;/h4&gt;

&lt;p&gt;GIT ist nicht genug … heute braucht jeder 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Kontinuierliche_Integration&quot;&gt;CI (Continuous Integration)&lt;/a&gt;.
Soll heißen: Wird Code commited, muss ein Buildserver anspringen und das
Projekt durchbauen.&lt;/p&gt;

&lt;p&gt;Codeberg setzt hier auf &lt;a href=&quot;https://woodpecker-ci.org/&quot;&gt;Woodpecker-CI&lt;/a&gt;, welches
&lt;a href=&quot;https://de.wikipedia.org/wiki/Docker_(Software)&quot;&gt;Docker&lt;/a&gt; basierte Agents für 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt;, 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Mac_OS_(Apple)&quot;&gt;MacOS&lt;/a&gt; und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows&quot;&gt;Windows&lt;/a&gt; anbietet.&lt;/p&gt;

&lt;p&gt;Das ganze funktioniert genau so, wie in den meisten anderen CI-Systemen
nur eben wieder mal mit einer etwas anderen Syntax:
Man legt eine &lt;a href=&quot;https://de.wikipedia.org/wiki/YAML&quot;&gt;YAML&lt;/a&gt; Datei an, die eine 
Pipeline von Aufgaben definiert, wo man einen Docker-Image Pfad hinterlegt 
und dann die Build-Kommandos in Script-Form anfügt. Und am Ende kann das 
Ergebnis per Suchfilter gefunden und als Artefakt hochgeladen werden.&lt;/p&gt;

&lt;p&gt;Also eigentlich super … nur eben wieder “ein bisschen” anders, als
es Github, &lt;a href=&quot;https://de.wikipedia.org/wiki/GitLab&quot;&gt;Gitlab&lt;/a&gt; oder Bitbucket tun.&lt;/p&gt;

&lt;h4 id=&quot;weitere-infos&quot;&gt;Weitere Infos&lt;/h4&gt;

&lt;p&gt;Damit die Community verbunden bleibt, erhält man allgemeine Infos im
&lt;a href=&quot;http://blog.codeberg.org/&quot;&gt;Projekt-Blog&lt;/a&gt;. 
Oder man folgt dem Newsfeed auf &lt;a href=&quot;https://social.anoxinon.de/@Codeberg&quot;&gt;Mastodon&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Einer aktiven Diskussion zu Funktionen oder Problemen kann man auf
&lt;a href=&quot;http://matrix.to/#/#codeberg-space:matrix.org&quot;&gt;matrix.org&lt;/a&gt; beiwohnen.&lt;/p&gt;

&lt;p&gt;Es ist also alles da, was ein modernes Community-basiertes Hosting-Projekt
benötigt.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ich habe nun begonnen ein paar Test-Projekte auf der Plattform anzulegen.
Ich bin mir noch nicht sicher, ob ich das GATE Projekt von Bitbucket zu
Codeberg verschieben sollte, denn eigentlich bin ich mit Bitbucket zufrieden
und habe keine “technischen” Grund, von dort abzuziehen.&lt;/p&gt;

&lt;p&gt;Dennoch lege ich “mein Lebenswerk” lieber in die Hände der Community,
als in die Schatulle eines kommerziellen Software Hauses, wie es bei 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Atlassian&quot;&gt;Atlassian&lt;/a&gt; der Fall ist.&lt;/p&gt;

&lt;p&gt;Naja … mal sehen, was die Zukunft bringen mag.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Weiter kein Versand mit Aliexpress</title>
   <link href="https://www.opengate.at/blog/2023/03/no-aliexpress/"/>
   <published>2023-03-18T12:00:00+01:00</published>
   <updated>2023-03-18T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2023/03/no-aliexpress</id>
   <category term="general" />
   <summary type="text">Aliexpress wurde für mich 
“attraktiv”, als es von Kreditkartenzahlungen zu 
PayPal wechselte. 
(Das muss Ende 2019 passiert sein.)

Doch seit dem 1. Januar 2023 ist Österreich von der größten Handelsplattform
für Bauteile für Baster ausgeschlossen … und es wird einfach nicht besser.
</summary>
   <content type="html">&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/AliExpress&quot;&gt;Aliexpress&lt;/a&gt; wurde für mich 
“attraktiv”, als es von Kreditkartenzahlungen zu 
&lt;a href=&quot;https://de.wikipedia.org/wiki/PayPal&quot;&gt;PayPal&lt;/a&gt; wechselte. 
(Das muss Ende 2019 passiert sein.)&lt;/p&gt;

&lt;p&gt;Doch seit dem 1. Januar 2023 ist Österreich von der größten Handelsplattform
für Bauteile für Baster ausgeschlossen … und es wird einfach nicht besser.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Das Thema Verpackung und Umweltschutz ist wichtig, und deshalb wurde ein 
&lt;a href=&quot;https://www.wko.at/service/umwelt-energie/information-verpackungsverordnung.html#verpflichtungen_2023&quot;&gt;Gesetzt beschlossen&lt;/a&gt;,
dass alle Händler im Ausland, die ihre Ware nach Österreich versenden,
einige weitere Auflagen erfüllen müssen.&lt;/p&gt;

&lt;p&gt;AliExpress hat daher seine Onlineplattform angepasst und lässt Suchanfragen 
mit Lieferort Österreich nur noch mit jenen Händlern zu, die die neuen 
Bedingungen erfüllen.&lt;br /&gt;
Das heißt also:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Man kann de facto nichts mehr bestellen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Bei Suchanfragen nach “Arduino” oder “Raspberry PI” erhielt ich vor einigen
Monaten noch 10000e Angebote.&lt;br /&gt;
Nun sind es wenige dutzend, doch selbst diese melden beim Öffnen des Links 
sofort:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Dieses Produkt kann nicht an Ihre Adresse versendet werden.
Wählen Sie ein anderes Produkt oder eine andere Adresse aus.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Betroffen ist jede Art von Bauteilen oder Werkzeuge, also genau das alles,
wofür ich mich interessiere.&lt;/p&gt;

&lt;p&gt;Interessanterweise haben z.B. Textil-Anbieter bereits eine Lieferform 
ausgehandelt und versenden fleißig ihre Artikel.&lt;br /&gt;
Produkte wie Unterhosen, Militärjacken oder Sexspielzeug werden also
problemlos nach Östereich geliefert … doch beim 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Arduino_(Plattform)#Hardware&quot;&gt;Atmega328&lt;/a&gt; ist 
die Lieferkette unterbrochen.&lt;/p&gt;

&lt;p&gt;Ich weiß jetzt offen gesagt nicht, was meine Landsleute sonst noch für Sachen
in China bestellen, doch die Aufträge der Maker-Szene dürften aktuell
alle wegbrechen … und ich glaube nicht, dass das durch Unterhosenkäufe
ausgeglichen wird.&lt;/p&gt;

&lt;p&gt;In den Statements, die bisher im Netz diskutiert wurden, heißt es, dass
AliExpress hier nur als Plattform auftritt und jeder einzelne Shop die
Verpackungsbestimmungen selbst umsetzen muss.&lt;br /&gt;
Aber das verstehe ich nicht so ganz, denn schließlich bietet AliExpress
seine eigenen Versandtarife an und da wäre es doch möglich, dass AliExpress
als Dachverband auftritt und für Österreich ein Schema für alle Shops
aushandelt.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Aktuell habe ich keinen zwingenden Bedarf an neuer Hardware aus China,
mir fehlt nur der Zugang zu weiteren 
&lt;a href=&quot;https://de.wikipedia.org/wiki/RISC-V&quot;&gt;RISC-V&lt;/a&gt; Dev-Boards.
Doch in den vergangenen Jahren habe ich häufig “Spielzeug” mitgekauft,
und damit ist nun leider Schluss.&lt;/p&gt;

&lt;p&gt;Ich frage mich, ob sich AliExpress doch noch dazu durchringt, uns den
Versand wieder zu eröffnen, oder ob sich eine Alternative am Markt
breit machen wird.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.banggood.com/&quot;&gt;Banggood&lt;/a&gt; bietet zwar mit einem wesentlich 
geringerem Angebot auch viele Elektronik-Produkte an, doch die Preise 
und die Auswahl sind mit AliExpress nicht vergleichbar.
Hier starten die Preise für RISC-V Boards bei 200 €, welche ich früher
schon um 100 € entdeckt hatte … und nun ärgere ich mich, damals nicht
sofort zugegriffen zu haben.&lt;/p&gt;

&lt;p&gt;In Sachen Verpackung muss man allerdings eines festhalten:&lt;br /&gt;
Wer in China Sachen kauft bekommt alles in einem einfach Plastiksäckchen 
zugestellt, das meistens problemlos in den Briefkasten passt.&lt;/p&gt;

&lt;p&gt;Bestelle ich die gleiche Hardware innerhalb der EU (wenn überhaupt möglich), 
bezahle ich etwa den 5-fachen Preis und bekomme dafür eine Schachtel mit 
Füllmaterial, eine mit Plastik umspannte Produktbox, in der das Produkt dann
nochmals in Plastik versiegelt ist.&lt;br /&gt;
… anders gesagt: Der Verpackungsmüll ist nachweislich wesentlich größer.&lt;/p&gt;

&lt;p&gt;Ich bin mir also nicht sicher, ob die neue Verordnung das Müllproblem
besser behandelt …&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Strategiewechsel</title>
   <link href="https://www.opengate.at/blog/2023/03/new-strategy/"/>
   <published>2023-03-12T12:00:00+01:00</published>
   <updated>2023-03-12T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2023/03/new-strategy</id>
   <category term="projects" />
   <summary type="text">Bisher habe ich im GATE Projekt versucht, die herauskommenden Programme
als größere “Universalwerkzeuge” anzulegen.
Doch das war falsch … oder sagen wir mal: Es ist nicht der beste Weg.

Denn jenseits der Windows 
und Linux Welt gelten teilweise 
andere Regeln und die möchte ich auch gerne einhalten.
</summary>
   <content type="html">&lt;p&gt;Bisher habe ich im GATE Projekt versucht, die herauskommenden Programme
als größere “Universalwerkzeuge” anzulegen.&lt;br /&gt;
Doch das war falsch … oder sagen wir mal: Es ist nicht der beste Weg.&lt;/p&gt;

&lt;p&gt;Denn jenseits der &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows&quot;&gt;Windows&lt;/a&gt; 
und &lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt; Welt gelten teilweise 
andere Regeln und die möchte ich auch gerne einhalten.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;code&gt;gatecli&lt;/code&gt; ist ein solches Werkzeug, in dem schon viele Funktionen eingefügt 
wurden. Wann immer ich neue Features implementiere, erhält das Programm ein 
neues Modul, mit dem man das neue Feature per Konsole ausführen kann.&lt;/p&gt;

&lt;p&gt;Doch … nun zeigt sich, dass dieser Ansatz ein Bremsklotz ist.
Und dieser manifestiert sich am deutlichsten unter 
&lt;a href=&quot;https://de.wikipedia.org/wiki/MS-DOS&quot;&gt;DOS&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;auf-die-größe-kommt-es-an&quot;&gt;Auf die Größe kommt es an&lt;/h3&gt;

&lt;p&gt;Wenn man Kompression, Grafikformate, Streams und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Socket_(Software)&quot;&gt;Sockets&lt;/a&gt; in eine EXE
statisch zusammenkompiliert, so wird diese verständlicherweise immer größer.&lt;/p&gt;

&lt;p&gt;Zusammen mit &lt;a href=&quot;https://de.wikipedia.org/wiki/SQLite&quot;&gt;SQLite&lt;/a&gt; und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/LibreSSL&quot;&gt;libreSSL&lt;/a&gt; kommt man da schnell auf 
4 MB, was eigentlich klein ist, wenn man es mit DLLs aller Teilkomponenten 
vergleicht.&lt;br /&gt;
Unter DOS ließe sich eine solch große EXE aber gar nicht mehr laden, doch da 
auf dieser Platform SSL und Datenbanken fehlen, sinkt die Größe drastisch.&lt;/p&gt;

&lt;p&gt;Trotzdem bricht der Übersetzungsvorgang seit einiger Zeit ab, da manche 
Datenstrukturen das 64-KByte Limit brechen.&lt;br /&gt;
Da hilft auch das größte Speichermodell nicht mehr weiter.&lt;/p&gt;

&lt;p&gt;Mit über 700 KByte sprengt man nämlich deutlich die 640 KByte des 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Konventioneller_Speicher&quot;&gt;konventionellen Speichers&lt;/a&gt;
und damit ist an der Stelle Schluss.&lt;/p&gt;

&lt;p&gt;Erkenntnis:&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;Wenn man alles in ein Programm packt, 
wird das für manche Plattformen einfach zu groß.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;aufspaltung-in-kleinprogramme&quot;&gt;Aufspaltung in Kleinprogramme&lt;/h3&gt;

&lt;p&gt;Die Lösung ist der alte &lt;a href=&quot;https://de.wikipedia.org/wiki/Unix&quot;&gt;Unix&lt;/a&gt;-Ansatz, 
nämlich je ein kleines Programm für genau je ein Feature (oder maximal
eine Feature-Familie).&lt;br /&gt;
In Summe vergrößert das zwar den Gesamtspeicherverbrauch, weil nun einige
Dinge redundant implementiert werden müssen, doch die kleineren Programme
können dann auf jeder Plattform geladen werden.&lt;/p&gt;

&lt;p&gt;In der Theorie sollte auch die Optimierung von unnötigen Codes besser
funktionieren, da der Compiler nun weniger Ausführungspfade nachverfolgen
muss.&lt;/p&gt;

&lt;p&gt;Es gibt nun aber eine andere Plattform, wo ich bisher mit “einem großen
Programm” besser gefahren bin, und das ist 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Unified_Extensible_Firmware_Interface&quot;&gt;UEFI&lt;/a&gt;.&lt;br /&gt;
Denn mit &lt;code&gt;gatecli&lt;/code&gt; hatte ich ein Werkzeug, das wie eine eigene Shell
alles verfügbar machte. 
Ich musste daher nur eine Binärdatei auf einen virtuellen Datenträger packen
um Tests unter &lt;code&gt;QEMU&lt;/code&gt; zu starten.&lt;/p&gt;

&lt;h3 id=&quot;umstellungsplan&quot;&gt;Umstellungsplan&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;gatecli&lt;/code&gt; wird nicht aufgelöst, doch ich plane mehrere Funktionen auszulagern.
Es soll also eigene Binaries für Kompression und Dateioperationen geben und
die bestehenden Features werden dann teilweise aus &lt;code&gt;gatecli&lt;/code&gt; verschwinden.&lt;/p&gt;

&lt;p&gt;Am Ende wird vermutlich etwas wie eine Mikro 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Shell_(Betriebssystem)&quot;&gt;Shell&lt;/a&gt; zurückbleiben, 
die andere Prozesse starten können soll.&lt;/p&gt;

&lt;p&gt;Ein offene Frage ist für mich der Umgang mit 
&lt;a href=&quot;https://de.wikipedia.org/wiki/WebAssembly&quot;&gt;WASM&lt;/a&gt;, denn dort gibt es keine
Prozesse so wie auf anderen Systemen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;Umstellungen sind der letzte Dreck.
Aber es ist das beste, was mir passieren konnte.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Wie bei jeder Umstellungen werde ich neue Details darüber lernen, ob 
Schnittstellen gut oder schlecht (also flexibel oder zu starr) ausdefiniert
wurden, und das ist positiv.&lt;br /&gt;
Allerdings wird das auch wieder einiges an Zeit auffressen … aber so ist
das Leben nun mal.&lt;/p&gt;

&lt;p&gt;Die DOS Plattform ist außerdem eine herrliche Vorbereitung für den Einsatz
von GATE Code auf Mikrocontrollern oder 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Echtzeitbetriebssystem&quot;&gt;RTOS&lt;/a&gt;
Plattformen.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>__near, __far, wherever you are</title>
   <link href="https://www.opengate.at/blog/2023/03/near-far/"/>
   <published>2023-03-11T12:00:00+01:00</published>
   <updated>2023-03-11T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2023/03/near-far</id>
   <category term="devel" />
   <summary type="text">Während Kate rebelliert, 
Leo stirbt und 
Céline von “near” und “far” 
singt (siehe Titanic), 
überlege ich gerade, wo ich überall “spezielle” Pointer-Attribute unterbringen 
muss.

Na … da blutet fast das Herz des Ozeans …
</summary>
   <content type="html">&lt;p&gt;Während &lt;a href=&quot;https://de.wikipedia.org/wiki/Kate_Winslet&quot;&gt;Kate&lt;/a&gt; rebelliert, 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Leonardo_DiCaprio&quot;&gt;Leo&lt;/a&gt; stirbt und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/C%C3%A9line_Dion&quot;&gt;Céline&lt;/a&gt; von “near” und “far” 
singt (siehe &lt;a href=&quot;https://de.wikipedia.org/wiki/Titanic_(1997)&quot;&gt;Titanic&lt;/a&gt;), 
überlege ich gerade, wo ich überall “spezielle” Pointer-Attribute unterbringen 
muss.&lt;/p&gt;

&lt;p&gt;Na … da blutet fast das Herz des Ozeans …
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;vorgeschichte&quot;&gt;Vorgeschichte&lt;/h3&gt;

&lt;p&gt;Nachdem alle modernen Systeme mit &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows&quot;&gt;Windows&lt;/a&gt;
oder &lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt; ausgestattet sind und 
mit einem Flat-Memory-Modell arbeiten, versteht heute keiner mehr, wenn ich
mich zu folgender Aussage hinreißen lasse:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Pointer ist nicht gleich Pointer.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In &lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B&quot;&gt;C++&lt;/a&gt; finden viele &lt;code&gt;typedef&lt;/code&gt;s statt, 
um Pointer zu kapseln. z.B.: &lt;code&gt;typedef X* X_ptr;&lt;/code&gt;&lt;br /&gt;
Das ist eigentlich ineffizient, weil &lt;code&gt;X*&lt;/code&gt; viel kürzer als &lt;code&gt;X_ptr&lt;/code&gt; zu schreiben
ist.&lt;/p&gt;

&lt;p&gt;Doch früher … viel früher gab es mal mehrere Implementierungen der gleichen
Sache abhängig von gewünschten Datenmodell, nämlich:
&lt;code&gt;typedef X __near* X_ptr;&lt;/code&gt; oder &lt;code&gt;typedef X __far* X_ptr;&lt;/code&gt;&lt;br /&gt;
Und schon macht es wieder total Sinn, dass man mit dem richtigen &lt;code&gt;X_ptr&lt;/code&gt;
arbeitet.&lt;/p&gt;

&lt;h3 id=&quot;segmentierung&quot;&gt;Segmentierung&lt;/h3&gt;

&lt;p&gt;X86-16-bit und &lt;a href=&quot;https://de.wikipedia.org/wiki/MS-DOS&quot;&gt;DOS&lt;/a&gt; arbeiteten mit 
Segment:Offset Adressierung. Das Datensegment-Register wurde auf einen 
64-KByte großen Block gesetzt
und man adressierte die Daten über einen relativen Offset.&lt;/p&gt;

&lt;p&gt;Wenn ein Programm mit 64 KByte auskam, konnte man ein “kleineres”
Speichermodell wählen. Das Segment-Register wurde einmal global gesetzt
und alle Adressierung liefen nur über den Offset.&lt;br /&gt;
Das nennt man dann einen &lt;code&gt;near&lt;/code&gt; Pointer, und der ist nur 16-Bit groß,
also klein und damit effizient.&lt;/p&gt;

&lt;p&gt;Kommt man 64 KByte nicht aus, kann man weitere 64-KByte Blöcke allokieren
und das Datensegment einfach auf den Block zeigen lassen, den man haben
möchte. Solche Pointer sind dann 32-Bit breit (weil Segment + Offset) 
und die werden eben als &lt;code&gt;far&lt;/code&gt; Pointer bezeichnet.&lt;/p&gt;

&lt;p&gt;Das gewählte Speichermodell entscheidet also, ob&lt;br /&gt;
&lt;code&gt;sizeof(void*) == 2&lt;/code&gt; oder &lt;code&gt;sizeof(void*) == 4&lt;/code&gt; gilt. Das könnte dem 
Programmierer jetzt theoretisch egal sein und er könnte mit dem &lt;code&gt;far&lt;/code&gt;
Modell immer alles erreichen, doch wenn stets das Segment-Register bei
Datenzugriffen neu ausgerichtet werden muss, dann läuft das Programm
plötzlich nur noch halb so schnell.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Also Augen auf bei der Wahl des Speichermodells!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;ausnahmen-von-der-regel&quot;&gt;Ausnahmen von der Regel&lt;/h3&gt;

&lt;p&gt;Das GATE Projekt ist leider zu groß, als dass es mit &lt;code&gt;near&lt;/code&gt; recht weit
kommen würde. Kleine Konsolen-Apps würden sich zwar ausgehen, aber ich
mache eben nichts kleines.&lt;br /&gt;
Ich nutze daher das &lt;code&gt;large&lt;/code&gt; Modell, in dem Code und Daten mehrere Segmente
nutzen dürfen, damit sind sowohl Code, als auch Daten-Pointer vom Typ &lt;code&gt;far&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Schließlich geht es mir bei der DOS-Portierung des Projektes nicht um
Hocheffizienz sondern um den Beweis, dass man auch heutige Programme
noch für DOS kompilieren kann, wenn man sie “richtig” aufsetzt.&lt;/p&gt;

&lt;p&gt;Allerdings sind mir einige gebrochene Unit-Tests im Projekt aufgefallen,
bei denen ich Pointer für andere Zwecke einsetze, und einer davon heißt
“Alignment”.&lt;/p&gt;

&lt;p&gt;Weder der C noch C++ Standard garantieren, dass Pointer einem bestimmten
Alignment folgen, doch die Praxis lehrte mich:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;All Datentypen haben im Zweifelsfall mindestens die Ausrichtung des
Pointer-Typs, weil der “am besten” an das Speichermodell angepasst ist.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Soll heißen,&lt;br /&gt;
&lt;code&gt;void func(char x, int y);&lt;/code&gt;&lt;br /&gt;
hat die gleiche ABI-Signatur wie:
&lt;code&gt;void func(void* x, void* y);&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Denn alle Datentypen kleiner &lt;code&gt;void*&lt;/code&gt; werden auf die Größe von &lt;code&gt;void*&lt;/code&gt; 
aufgepumpt, weil &lt;code&gt;void*&lt;/code&gt; mit hoher Wahrscheinlichkeit genau die
Größe eines normalen CPU Allzweckregisters hat.&lt;/p&gt;

&lt;h3 id=&quot;generische-funktionsaufrufe&quot;&gt;Generische Funktionsaufrufe&lt;/h3&gt;

&lt;p&gt;Im &lt;code&gt;gate/functions&lt;/code&gt; Modul werden beliebige C-Funktionsaufrufe über einen
Dispatcher geleitet und der arbeitete bisher nach der Idee, dass alle 
Parameter einer Funktion durch &lt;code&gt;void*&lt;/code&gt; repräsentierbar sind (mit ein 
paar Sonderfällen, die aus mehreren &lt;code&gt;void*&lt;/code&gt; Typen zusammengesetzt
sein können.)&lt;/p&gt;

&lt;p&gt;Das Problem ist, dass &lt;code&gt;void*&lt;/code&gt; im Large-Modell 4 Bytes breit ist, doch das
Default-Alignment ist auf 16-bit Systemen eben nur 16-bit breit.&lt;br /&gt;
Ein &lt;code&gt;void foo(int, int)&lt;/code&gt; belegt 4 Bytes (2x int16) am Stack, doch ein&lt;br /&gt;
&lt;code&gt;void bar(void*, void*)&lt;/code&gt; hätte wegen &lt;code&gt;far&lt;/code&gt; bereits 8 Bytes (2x int32) belegt
und stimmt nicht mehr mit dem Original überein.&lt;/p&gt;

&lt;p&gt;Mein Unit-Test Fehler entstand also durch eine Verschiebung des Speichers.&lt;/p&gt;

&lt;h3 id=&quot;lösung-16-bit-parameter-nutzen-anstatt-von-void-&quot;&gt;Lösung: 16-bit Parameter nutzen, anstatt von &lt;code&gt;void *&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;Nun musste also auch ich ein &lt;code&gt;typedef&lt;/code&gt; für generische Parameter einsetzen und
eben dieses &lt;code&gt;typedef&lt;/code&gt; sieht unter DOS nun anders aus, als unter anderen
Betriebssystemen.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#if&lt;/span&gt; defined(GATE_COMPILER_WATCOM)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;typedef&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;short&lt;/span&gt; fparam_t;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#else&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;typedef&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;* fparam_t;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#endif&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Kaum war die Anpassung vorgenommen, funktionierten auch die Tests wieder 
erfolgreich.&lt;/p&gt;

&lt;h3 id=&quot;andere-nearfar-pointer-erzeugen&quot;&gt;Andere near/far Pointer erzeugen&lt;/h3&gt;

&lt;p&gt;Wenn man unter DOS direkt auf die Hardware zugreifen möchte, dann funktioniert
das unter anderem auch über feste Speicheradressen.&lt;br /&gt;
Ein Beispiel wäre &lt;code&gt;A0000&lt;/code&gt; des VGA Standards.&lt;/p&gt;

&lt;p&gt;Pointer zu solchen Segmenten sind ebenso als &lt;code&gt;__far&lt;/code&gt; Pointer deklariert.
Sie werden über Hilfsmakros wie &lt;code&gt;MK_FP&lt;/code&gt; explizit erzeugt:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;static&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;unsigned&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt; __far * vga_screen; 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;vga_screen = (&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;unsigned&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt; __far*)MK_FP(&lt;span style=&quot;color:#02b&quot;&gt;0xA000&lt;/span&gt;,&lt;span style=&quot;color:#02b&quot;&gt;0x0000&lt;/span&gt;); 
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ein weiteres Mysterium ist gelöst und eine notwendige Codeanpassung wurde
vorgenommen. Anstatt vieler &lt;code&gt;void*&lt;/code&gt; Parameter wurde nun ein neuer Typ angelegt,
den man an einer Stelle ändern kann.&lt;br /&gt;
So kann man auf jeder Plattform den passenden nativen Datentypen über 
Compiler-spezifische Makros ermitteln.&lt;/p&gt;

&lt;p&gt;Ich werde vorerst mit dem &lt;code&gt;LARGE&lt;/code&gt; Modell weiterarbeiten, doch es tut sich nun
die Frage auf, ob es auch möglich wäre die kleineren Modelle einzusetzen.
Spätestens dann müsste ich weitere Anpassungen in vermutlich vielen Modulen
vornehmen, denn dann wird die Unterscheidung zwischen &lt;code&gt;near&lt;/code&gt; und &lt;code&gt;far&lt;/code&gt; 
explizit umgesetzt werden müssen.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Windows 95 Update ohne Windows 3.x</title>
   <link href="https://www.opengate.at/blog/2023/03/win95-update-hack/"/>
   <published>2023-03-05T12:00:00+01:00</published>
   <updated>2023-03-05T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2023/03/win95-update-hack</id>
   <category term="retro" />
   <summary type="text">Retro-Time!
Beim Aufräumen meiner Backups ist mir wieder ein altes 
NT-4 ISO-Image 
untergekommen, welches neben Windows NT Varianten auch 
Windows 95 enthielt, 
und zwar eine englische Version.

Da ich aus meiner Vergangenheit nur deutsche Versionen aufgehoben hatte,
startete ich spaßhalber das Setup in einer VM … 
Doch das brach mit einer Upgrade-Fehlermeldung ab.
</summary>
   <content type="html">&lt;p&gt;&lt;strong&gt;Retro-Time!&lt;/strong&gt;&lt;br /&gt;
Beim Aufräumen meiner Backups ist mir wieder ein altes 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_NT_4.0&quot;&gt;NT-4&lt;/a&gt; ISO-Image 
untergekommen, welches neben Windows NT Varianten auch 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_95&quot;&gt;Windows 95&lt;/a&gt; enthielt, 
und zwar eine englische Version.&lt;/p&gt;

&lt;p&gt;Da ich aus meiner Vergangenheit nur deutsche Versionen aufgehoben hatte,
startete ich spaßhalber das Setup in einer VM … 
Doch das brach mit einer Upgrade-Fehlermeldung ab.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Als Windows 95 herauskam, war ich noch lange nicht bereit dafür, und als es
so weit war … naja, &lt;a href=&quot;/blog/2018/11/win95-update/&quot;&gt;die Story ist dokumentiert&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Es gab:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;die Vollversion “für PCs ohne Windows”&lt;/li&gt;
  &lt;li&gt;und eine Upgrade Version “für PCs mit &lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_3.x&quot;&gt;Windows 3.x&lt;/a&gt;”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Meine gefundene Variante war die originale Upgrade Version und brauchte 
somit eine Windows 3.x Installation um ausgerollt werden zu können.&lt;/p&gt;

&lt;p&gt;Früher nutzte ich eine umständliche Methode und entpackte die Datei 
&lt;code&gt;mini.cab&lt;/code&gt; mit dem &lt;code&gt;extract.exe&lt;/code&gt; Tool und editierte die Datei &lt;code&gt;system.ini&lt;/code&gt;,
von &lt;code&gt;shell=winsetup.bin&lt;/code&gt; zu &lt;code&gt;shell=c:\w95setup\path\setup.exe&lt;/code&gt;.
Danach startete ich &lt;code&gt;dosx&lt;/code&gt; und genoss den Start des Windows-Setups ohne
3.x Prüfung.&lt;br /&gt;
Der Scherz war, dass Windows 95 sein eigenes kleines Windows 3.x Fragment
in &lt;code&gt;mini.cab&lt;/code&gt; mitlieferte, welches den grafischen Teil des Setups anzeigte
und wenn man &lt;code&gt;setup.exe&lt;/code&gt; nicht von DOS sondern von einer laufenden
Windows Sitzung aus startete, fand keine weitere Prüfung mehr statt.&lt;/p&gt;

&lt;p&gt;Es geht aber auch einfacher…&lt;/p&gt;

&lt;h3 id=&quot;win-3x-fake-anlegen&quot;&gt;Win 3.x Fake anlegen&lt;/h3&gt;

&lt;p&gt;Hacker haben folgendes herausgefunden:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Das Setup prüft nur, ob die Dateien &lt;code&gt;win.com&lt;/code&gt; und &lt;code&gt;win386.exe&lt;/code&gt; existieren.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Man führt also folgende Zeilen aus:&lt;/p&gt;

&lt;div class=&quot;language-batch highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;mkdir c:\winfake
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;dir /s c: &amp;gt; c:\winfake\win.com
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;dir /s c: &amp;gt; c:\winfake\win386.exe
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;und startet das Windows 95 Setup ganz normal, dann werden die Dateien entweder
automatisch gefunden, oder man darf sie in einem Laufwerksdialog auch auf
anderen Laufwerken manuell auswählen.&lt;/p&gt;

&lt;p&gt;Sind die beiden Dateien vorhanden, wird Windows 95 vollständig installiert,
denn der Inhalt es identisch zur Vollversion.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Tja … ich konnte mich noch dunkel erinnern, dass man nur bestimmte Dateien
brauchte und zum Glück konnte ich noch uralte Foreneinträge vom Jahr 2000 
finden, wo das dokumentiert war.&lt;/p&gt;

&lt;p&gt;Nun ist es auch hier schriftlich festgehalten, damit ich auch in 10 Jahren
noch Windows 95 installieren kann. 
… es mag vielleicht keinen Grund dafür geben, dieses OS zu installieren,
aber hey … es ist ein Stück Kindheitserinnerung.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>dll_import für Templates</title>
   <link href="https://www.opengate.at/blog/2023/03/import-template/"/>
   <published>2023-03-04T12:00:00+01:00</published>
   <updated>2023-03-04T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2023/03/import-template</id>
   <category term="devel" />
   <summary type="text">Sind in für DLLs 
exportierten C++ Klassen unter 
Windows Datentypen 
enthalten, die auf Templates aufbauen, sieht man schnell den Fehler:


  1warning C4251: ... needs to have dll-interface ...




Doch den bekommt man gar nicht so leicht weg, wenn man portabel bleiben 
möchte.

</summary>
   <content type="html">&lt;p&gt;Sind in für &lt;a href=&quot;https://de.wikipedia.org/wiki/Dynamic_Link_Library&quot;&gt;DLL&lt;/a&gt;s 
exportierten &lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B&quot;&gt;C++ Klassen&lt;/a&gt; unter 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows&quot;&gt;Windows&lt;/a&gt; Datentypen 
enthalten, die auf Templates aufbauen, sieht man schnell den Fehler:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;warning C4251: ... needs to have dll-interface ...
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Doch den bekommt man gar nicht so leicht weg, wenn man portabel bleiben 
möchte.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;vorgeschichte-c-templates&quot;&gt;Vorgeschichte: C++ Templates&lt;/h3&gt;

&lt;p&gt;C++ Templates kann man nicht exportieren, sie sind in der Regel vollständig
im Header implementiert und daher “einfach da”. Wenn sie aber benutzt und 
damit “instanziiert” werden, erzeugt der Compiler eine Implementierung, gegen 
die dann gelinkt wird.&lt;br /&gt;
Nachdem mehrere Module Templates instanziieren können stellt das eigentlich 
eine Verletzung der One-Definition-Rule (ODR) dar … doch für Templates wird 
eine Ausnahme gemacht und der Linker fügt die mehrfachen Varianten entweder 
in eine zusammen, oder behandelt sie wie private Inline-Codes.&lt;/p&gt;

&lt;p&gt;Das Spiel endet aber an der Grenze der erzeugten Ausgabedatei.&lt;br /&gt;
Und wenn jetzt ein Projekt eine Bibliothek in ein Programm einbindet und 
eine Template-basierte Instanz zwischen beiden ausgetauscht werden soll,
tja dann müssen wir hoffen und vertrauen, dass es “irgendwie” funktioniert.&lt;/p&gt;

&lt;p&gt;Die C++ Sprache kennt keine Windows &lt;code&gt;.dll&lt;/code&gt; oder
&lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt; &lt;code&gt;.so&lt;/code&gt; Bibliotheken,
und somit sind es die Compiler-Hersteller, die den Austausch von Daten
zwischen Bibliotheken implementieren, doch einen Standard gibt es nicht.&lt;/p&gt;

&lt;p&gt;Aus diesem Grund können auch ein &lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_C%2B%2B&quot;&gt;MSVC&lt;/a&gt;
und ein &lt;a href=&quot;https://de.wikipedia.org/wiki/MinGW&quot;&gt;MinGW GCC&lt;/a&gt; problemlos über
C-Schnittstellen kommunizieren, denn diese Schnittstelle ist spezifiziert.
C++ Codes funktionieren bibliotheksübergreifend jedoch nur mit genau ein und
der selben Compiler-Version, ein Compiler-Mischbetrieb ist nicht möglich.&lt;/p&gt;

&lt;h3 id=&quot;idee-template-instanzen-exportieren&quot;&gt;Idee: Template Instanzen exportieren&lt;/h3&gt;

&lt;p&gt;Will man einen &lt;code&gt;std::vector&amp;lt;int&amp;gt;&lt;/code&gt; von einer Bibliothek zum Hauptprogramm
weiterreichen, meldet uns die genannte Warnung, dass &lt;code&gt;std::vector&amp;lt;int&amp;gt;&lt;/code&gt; kein
DLL-Interface eingerichtet hat. Es funktioniert dann aber “magisch” trotzdem,
weil der gleiche &lt;code&gt;&amp;lt;vector&amp;gt;&lt;/code&gt; Header in beiden Komponenten vorhanden ist,
und damit das Binäre Layout auf beiden Seiten identisch bestimmt wird.&lt;/p&gt;

&lt;p&gt;Soll heißen, der Inhalt von &lt;code&gt;std::vector&amp;lt;int&amp;gt;&lt;/code&gt; wird auf der Zielseite genau
so “verstanden”, wie er auf der Erstellerseite angelegt wurde, weil beide
Seiten eine Kopie des gleichen Codes enthalten.&lt;/p&gt;

&lt;p&gt;Man kann jedoch aus diesem “Zufall” auch einen Standard machen, indem man
die explizite Template-Instanziierung mit einem DLL-Interface exportiert
und auf der Zielseite importiert.&lt;br /&gt;
Nun existiert der Code auf genau einer Seite und die zweite Seite nutzt
ihn. Wir haben dann einen binären Standard und können Bugfixes an exakt
einer Stelle vornehmen, anstatt sich sorgen zu müssen, dass Templates
an jedem Ort anders interpretiert werden.&lt;/p&gt;

&lt;h3 id=&quot;beispiel-code&quot;&gt;Beispiel Code&lt;/h3&gt;

&lt;p&gt;Code sagt mehr als 1000 Worte&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#777&quot;&gt;// mylib.h&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color:#B44;font-weight:bold&quot;&gt;&amp;lt;utility&amp;gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#if&lt;/span&gt; defined(mylib_EXPORTS)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#  if&lt;/span&gt; defined(_MSC_VER)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#    define&lt;/span&gt; MYLIB_API __declspec(dllexport)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#    define&lt;/span&gt; MYLIB_EXTERN
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#  else&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#    define&lt;/span&gt; MYLIB_API __attribute__((visibility (&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;default&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)))
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#    define&lt;/span&gt; MYLIB_EXTERN &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;extern&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#  endif&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#else&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#  if&lt;/span&gt; defined(_MSC_VER)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#    define&lt;/span&gt; MYLIB_API  __declspec(dllimport)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#    define&lt;/span&gt; MYLIB_EXTERN &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;extern&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#  else&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#    define&lt;/span&gt; MYLIB_API
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#    define&lt;/span&gt; MYLIB_EXTERN &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;extern&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#  endif&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#endif&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n21&quot; name=&quot;n21&quot;&gt;21&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n22&quot; name=&quot;n22&quot;&gt;22&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#777&quot;&gt;// declare export of some std::pair instances&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n23&quot; name=&quot;n23&quot;&gt;23&lt;/a&gt;&lt;/span&gt;LIB_EXTERN &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;template&lt;/span&gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;struct&lt;/span&gt; LIB_API std::pair&amp;lt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt;, &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt;&amp;gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n24&quot; name=&quot;n24&quot;&gt;24&lt;/a&gt;&lt;/span&gt;LIB_EXTERN &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;template&lt;/span&gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;struct&lt;/span&gt; LIB_API std::pair&amp;lt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;double&lt;/span&gt;, &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;double&lt;/span&gt;&amp;gt;;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#777&quot;&gt;// mylib.cpp&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color:#B44;font-weight:bold&quot;&gt;&amp;quot;mylib.h&amp;quot;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;template&lt;/span&gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;struct&lt;/span&gt; std::pair&amp;lt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt;, &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt;&amp;gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;template&lt;/span&gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;struct&lt;/span&gt; std::pair&amp;lt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;double&lt;/span&gt;, &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;double&lt;/span&gt;&amp;gt;;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Im Header wird jede gewollte Template-Spezialisierung deklariert, 
und in der &lt;code&gt;.cpp&lt;/code&gt; Datei findet dann die explizite Instanziierung statt.&lt;/p&gt;

&lt;p&gt;Der besondere Unterschied zwischen &lt;code&gt;MSVC&lt;/code&gt; und GCC ist, dass unter Windows
ein mit &lt;code&gt;dllexport&lt;/code&gt; exportiertes Symbol nicht zusätzlich noch &lt;code&gt;extern&lt;/code&gt;
sein darf, während der GCC &lt;code&gt;extern&lt;/code&gt; gestattet.&lt;/p&gt;

&lt;p&gt;Wir brauchen daher ein zusätzliches “extern” - Makro, welches im Fall von 
&lt;code&gt;dllexpoprt&lt;/code&gt; im Header einfach leer ist.&lt;br /&gt;
Unter Linux darf dieses &lt;code&gt;extern&lt;/code&gt; nicht fehlen, ansonsten wird die 
Spezialisierung schon im Header generiert.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Für eigene Datentypen ist die Methode also durchaus geeignet, um Templates
in der Bibliothek für einige Typen in konkrete Datentypen umzuwandeln.&lt;/p&gt;

&lt;p&gt;Die Sache hat nur einen Haken: &lt;code&gt;std::string&lt;/code&gt; und alle Container nutzen intern
jede Menge weitere private Hilfstypen, die selbst wieder Templates sein 
können. Und das Problem ist, dass man alle “exportieren” müsste, um alle
bekannten &lt;code&gt;MSVC&lt;/code&gt; Warnungen wegzubekommen.&lt;/p&gt;

&lt;p&gt;Doch dieses Unterfangen ist nicht portabel, und aus diesem Grund setze
ich die explizite Instanziierung nur selten für eigene Typen ein.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Trampolin-Springen</title>
   <link href="https://www.opengate.at/blog/2023/02/trampoline/"/>
   <published>2023-02-26T12:00:00+01:00</published>
   <updated>2023-02-26T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2023/02/trampoline</id>
   <category term="devel" />
   <summary type="text">Bei meinem Rust-Kurs hat mich eine 
Aussage während des Vortrages gestört:


  C++ erzeugt oft schlechten 
Maschinen-Code mit Trampolines.


Das ist etwas weit hergeholt.
</summary>
   <content type="html">&lt;p&gt;Bei meinem &lt;a href=&quot;/blog/2023/02/rust/&quot;&gt;Rust-Kurs&lt;/a&gt; hat mich eine 
Aussage während des Vortrages gestört:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B&quot;&gt;C++&lt;/a&gt; erzeugt oft schlechten 
Maschinen-Code mit Trampolines.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Das ist etwas weit hergeholt.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;sprungbretter-damals-und-heute&quot;&gt;Sprungbretter damals und heute&lt;/h3&gt;

&lt;p&gt;Wer unter &lt;a href=&quot;https://de.wikipedia.org/wiki/Disk_Operating_System&quot;&gt;DOS&lt;/a&gt; mit 
X86 16 bit &lt;a href=&quot;https://de.wikipedia.org/wiki/Assemblersprache&quot;&gt;Assembler&lt;/a&gt; 
gearbeitet hat, der kannte das Problem, dass “Conditional-Jumps” 
(also IF Sprünge) nur +/- 127 Bytes weit reisen konnten.&lt;br /&gt;
Oft erhielt man die Fehlermeldung, dass das Ziel für den Sprung zu 
weit entfernt war.&lt;/p&gt;

&lt;p&gt;Jetzt konnte man entweder selbst mitten im Code eine “Zwischensprungstation”
einrichten, die zuerst angesprungen wurde um von dort zum richtigen Ziel
weiterzuspringen … oder man ließ diese Arbeit dem Assembler selbst per
Direktive erledigen.&lt;/p&gt;

&lt;p&gt;Dank 32 (und mehr)-Bit Codes sind diese Trampoline weitgehend ausgestorben.&lt;/p&gt;

&lt;p&gt;C++ generiert heute jedoch manchmal eigene Hilfsfunktionen, die sich 
ebenfalls Trampoline nennen, die zuerst “angesprungen” werden und zum 
eigentlichen Ziel umleiten.&lt;/p&gt;

&lt;h3 id=&quot;warum-passiert-das&quot;&gt;Warum passiert das?&lt;/h3&gt;

&lt;h4 id=&quot;funktoren&quot;&gt;Funktoren&lt;/h4&gt;

&lt;p&gt;Funktoren und &lt;a href=&quot;https://en.cppreference.com/w/cpp/utility/functional/function&quot;&gt;std::function&lt;/a&gt; 
Bindings sind solche “gewollten” Umschlagplätze. Schließlich kapselt man hier
einen Funktionsaufruf bewusst in ein “Interface” um es später generisch 
aufrufen zu können.&lt;/p&gt;

&lt;script src=&quot;/blog/assets/mermaid/mermaid.min.js&quot;&gt;&lt;/script&gt;
&lt;div class=&quot;mermaid&quot;&gt;
flowchart LR
  STD(std::function&lt;br /&gt;void&amp;amp;#40int,char&amp;amp;#41)
  F[[function: void target&amp;amp;#40int,char&amp;amp;#41]]
  O[[method: void obj::target&amp;amp;#40int,char&amp;amp;#41]]
  L[[lambda: &amp;amp;#91&amp;amp;#93&amp;amp;#40int,char&amp;amp;#41]]
  STD --trampoline&lt;br /&gt;C call--&amp;gt; F
  STD --trampoline&lt;br /&gt;this call--&amp;gt; O
  STD --trampoline&lt;br /&gt;lambda call/inline--&amp;gt; L
&lt;/div&gt;

&lt;h4 id=&quot;mehrfachvererbung-mit-virtuellen-methoden&quot;&gt;Mehrfachvererbung mit virtuellen Methoden&lt;/h4&gt;

&lt;p&gt;Wenn eine Klasse von einer Basisklasse erbt, dann setzt C++ bei der neuen
Klasse die Basis an den Anfang und fügt dahinter die neuen Elemente an.
Das gilt auch für die &lt;a href=&quot;https://de.wikipedia.org/wiki/Tabelle_virtueller_Methoden&quot;&gt;V-Table&lt;/a&gt;
und man kann immer sagen, dass ein &lt;code&gt;this&lt;/code&gt; Pointer gleich dem &lt;code&gt;base-class&lt;/code&gt; 
Pointer ist.&lt;/p&gt;

&lt;p&gt;Erbt eine Klasse aber von zwei Basen, dann hat die zweite Basis, das Problem,
dass sie nicht am “Anfang” der neuen Klasse stehen kann, weil dort schon die
erste steht.&lt;br /&gt;
Doch ein von außen kommender Aufruf über einen Pointer zur zweiten Basis 
würde eben auf den B-Teil von C zeigen.&lt;br /&gt;
Hier generiert jetzt der Compiler das B-Interface, das zum C-Interface
weiterspringt, wo aber vorher noch der &lt;code&gt;this&lt;/code&gt; Pointer angepasst wird, um
wieder auf C zu zeigen.&lt;/p&gt;

&lt;p&gt;Und das kann man leider auf der Ebene nicht besser machen.&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;struct&lt;/span&gt; A
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;virtual&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt; foo() { }
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; a;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;};
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;struct&lt;/span&gt; B
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;virtual&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt; bar() { }
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; b;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;};
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;struct&lt;/span&gt; C : A, B 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;virtual&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt; foo() &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;override&lt;/span&gt; { }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;virtual&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt; bar() &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;override&lt;/span&gt; { }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;};
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; main()
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;  C c;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  C* ptr_c = &amp;amp;c;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n21&quot; name=&quot;n21&quot;&gt;21&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n22&quot; name=&quot;n22&quot;&gt;22&lt;/a&gt;&lt;/span&gt;  A* ptr_a = &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;static_cast&lt;/span&gt;&amp;lt;A*&amp;gt;(ptr_c);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n23&quot; name=&quot;n23&quot;&gt;23&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;// result: ptr_a == ptr_c&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n24&quot; name=&quot;n24&quot;&gt;24&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n25&quot; name=&quot;n25&quot;&gt;25&lt;/a&gt;&lt;/span&gt;  B* ptr_b = &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;static_cast&lt;/span&gt;&amp;lt;B*&amp;gt;(ptr_c);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n26&quot; name=&quot;n26&quot;&gt;26&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;// result: ptr_b == ptr_c + sizeof(A)&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n27&quot; name=&quot;n27&quot;&gt;27&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n28&quot; name=&quot;n28&quot;&gt;28&lt;/a&gt;&lt;/span&gt;  ptr_a-&amp;gt;foo();
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n29&quot; name=&quot;n29&quot;&gt;29&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;// no trampoline required, directly call C::foo&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n30&quot; name=&quot;n30&quot;&gt;30&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n31&quot; name=&quot;n31&quot;&gt;31&lt;/a&gt;&lt;/span&gt;  ptr_b-&amp;gt;bar();
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n32&quot; name=&quot;n32&quot;&gt;32&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;// invokes trampoline, this_ptr = ptr_b - sizeof(A)&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n33&quot; name=&quot;n33&quot;&gt;33&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n34&quot; name=&quot;n34&quot;&gt;34&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n35&quot; name=&quot;n35&quot;&gt;35&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;script src=&quot;/blog/assets/mermaid/mermaid.min.js&quot;&gt;&lt;/script&gt;
&lt;div class=&quot;mermaid&quot;&gt;
flowchart TB
  subgraph class C : public A, B
    Aimpl(C impl of foo)
    Bimpl(C impl of bar)

    subgraph V-Table class A
      Afoo[[A::foo]]
    end

    subgraph V-Table class B
      Bbar[[B::bar]]
    end

    subgraph V-Table class C
      Cfoo[[C::foo]]
      Cbar[[C::bar]]
    end

    T[/B to C&lt;br /&gt;trampoline/]
  end

  Cfoo --&amp;gt; Aimpl
  Cbar --&amp;gt; Bimpl

  Afoo --direct call&lt;br /&gt;A* == C*---&amp;gt; Cfoo
  Bbar --call&lt;br /&gt;B* --&amp;gt; T --new C*&lt;br /&gt;pointer--&amp;gt; Cbar
&lt;/div&gt;

&lt;h3 id=&quot;optimierungen-des-compilers&quot;&gt;Optimierungen des Compilers&lt;/h3&gt;

&lt;p&gt;Es ist aber ein Irrtum zu glauben, dass wir deshalb immer über
Trampolines zur Implementierung springen, denn wenn wir mal
beim richtigen Interface-Pointer sind, springen wir stets zum
endgültigen Ziel ohne Umwege.&lt;/p&gt;

&lt;p&gt;Aus diesem Grund wird Vererbung in C++ immer häufiger über Templates
gelöst und virtuelle Funktionen samt Trampolines kommen nicht mehr
zum Einsatz.&lt;/p&gt;

&lt;p&gt;Zusätzlich haben die Compiler immer weitere Verbesserungen erhalten,
um Typeninformationen an Variablen zu binden.&lt;br /&gt;
Selbst wenn jemand ein &lt;code&gt;B* ptr = &amp;amp;c&lt;/code&gt; ausführt und danach &lt;code&gt;B&lt;/code&gt; Aufrufe
macht, kann der Compiler sich merken, dass es in Wahrheit ein &lt;code&gt;C*&lt;/code&gt; ist
und statisch das richtige Ziel ohne Trampolin aufrufen.&lt;br /&gt;
Ähnliches gilt für Dispatcher in Functor und Lambda Codes.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ja, Trampoline existieren in C++ als ABI-Sicherheitsgarantie, und der 
Compiler mag sie als 10-Byte große Bröckchen einstreuen, doch das bedeutet
nicht, dass sie immer genutzt werden.&lt;/p&gt;

&lt;p&gt;Rust kennt keine Mehrfachvererbung und kompiliert alle Codes statisch, womit
das höchste Maß an Optimierung möglich ist. Gleiches passiert, wenn man in
C++ ebenso vorgeht. Man kann daher nicht behaupten, Rust wäre hier von 
Grund auf besser bei der Codegenerierung.&lt;/p&gt;

&lt;p&gt;Einen Punkt muss man allerdings Rust zuschreiben: C++ nutzt virtuelle 
Methoden leider schon häufig in Klassen der Standard-Bibliothek wie 
&lt;code&gt;iostreams&lt;/code&gt; und das bedeutet, dass es hier schon zu Trampolines kommen 
kann (nicht muss!).&lt;br /&gt;
In Rust hingegen sind alle Aufrufe direkt, bis man explizit &lt;code&gt;dyn&lt;/code&gt; 
einsetzt, was von Grund auf Trampoline-frei ist.&lt;/p&gt;

&lt;p&gt;Der Nachteil ist jedoch: Wenn man in Rust z.B. 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Component_Object_Model&quot;&gt;COM&lt;/a&gt; Interfaces 
implementieren will oder muss, dann muss man das über unsafe-C-Codes selbst 
machen …&lt;br /&gt;
und das heißt, man darf sich dann quasi Trampolines selbst zusammenschrauben.&lt;br /&gt;
Und auf der Ebene verlasse ich mich lieber auf Compiler-generierte 
Trampolines mit best möglicher Optimierung.&lt;/p&gt;

&lt;p&gt;Also bitte keine Anschuldigungen, wenn man Worst-Cases von Sprache A mit
Best-Cases von Sprache B vergleicht. Ich weiß, das macht man im Marketing
häufig … seriös ist das aber nicht.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Linux auditd und CRLF</title>
   <link href="https://www.opengate.at/blog/2023/02/auditd-crlf/"/>
   <published>2023-02-25T12:00:00+01:00</published>
   <updated>2023-02-25T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2023/02/auditd-crlf</id>
   <category term="software" />
   <summary type="text">Bei mir lagen heute zwei Dateien in /etc/audit/rules.d.
Wenn in der zweiten alle Regeln auskommentiert wurden, funktionierte 
auditd zumindest mit den Regeln 
der ersten Datei.
Kaum wurden die Regeln in der zweiten Datei aktiviert, funktionierte gar 
nichts mehr.

Und wieder einmal habe ich einen Tag Lebenszeit verloren …
</summary>
   <content type="html">&lt;p&gt;Bei mir lagen heute zwei Dateien in &lt;code&gt;/etc/audit/rules.d&lt;/code&gt;.
Wenn in der zweiten alle Regeln auskommentiert wurden, funktionierte 
&lt;a href=&quot;https://linux.die.net/man/8/auditd&quot;&gt;auditd&lt;/a&gt; zumindest mit den Regeln 
der ersten Datei.&lt;br /&gt;
Kaum wurden die Regeln in der zweiten Datei aktiviert, funktionierte gar 
nichts mehr.&lt;/p&gt;

&lt;p&gt;Und wieder einmal habe ich einen Tag Lebenszeit verloren …
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;der-linux-wächter-auditd&quot;&gt;Der Linux-Wächter: auditd&lt;/h3&gt;

&lt;p&gt;Ich durfte für ein Projekt in der Firma den Einsatz des Linux Daemons &lt;code&gt;auditd&lt;/code&gt;
ausprobieren. Dieser lädt seine Konfiguration aus &lt;code&gt;.rules&lt;/code&gt; Dateien, die
in &lt;code&gt;/etc/audit/rules.d&lt;/code&gt; liegen.&lt;br /&gt;
&lt;code&gt;auditd&lt;/code&gt; loggt dann Zugriffe auf Dateien, Programme oder Systemcalls,
die man dann für Sicherheitsprüfungen nutzen kann.&lt;/p&gt;

&lt;p&gt;So weit, so gut.&lt;/p&gt;

&lt;h3 id=&quot;crlf--error&quot;&gt;CRLF == Error&lt;/h3&gt;

&lt;p&gt;Natürlich habe ich logische Unterteilungen dieser “Rules” in mehrere Dateien
gemacht, die man dann über das selektive Kopieren von Dateien verteilen kann.&lt;br /&gt;
Und plötzlich funktionierte nichts mehr.&lt;/p&gt;

&lt;p&gt;Ein Aufruf von &lt;code&gt;auditctl -l&lt;/code&gt; zeigte, dass keine einzige Regel geladen wurde,
obwohl alle Regeln zuvor in einer einzigen Datei perfekt funktioniert hatten.&lt;/p&gt;

&lt;p&gt;Immer wieder kopierte ich die Dateien per &lt;a href=&quot;https://de.wikipedia.org/wiki/Secure_Shell&quot;&gt;SSH&lt;/a&gt;
zwischen meinem Windows System und dem Linux-Testsystem hin und her. 
Wurden alle Rules in der Datei per &lt;code&gt;#&lt;/code&gt; Präfix auskommentiert und die Rules 
in einer anderen Datei eingebunden, wurden sie geladen und funktionierten.&lt;/p&gt;

&lt;p&gt;Nach mehreren Zweifeln an meiner Gesundheit, erkannte ich ganz unten rechts 
in der Statuszeile von &lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_Studio_Code&quot;&gt;Visual Studio Code&lt;/a&gt;
den Unterschied zwischen den Dateien:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Die Originale waren mit typischen Linux &lt;code&gt;LF&lt;/code&gt; Zeilenenden versehen,
nur die eine störrische, die ich unter Windows neu angelegt hatte,
zeigte: &lt;code&gt;CRLF&lt;/code&gt; an.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;So ein Fu**!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Naja … ich hätte da auch schon schneller darauf kommen können, aber wenn man
die ersten Dateien “zufällig” auf dem richtigen System erstellt hat und einem
nur die letzte in die Suppe spuckt, wird man eben blind für die Frage aus
der Schreibmaschinenwelt.&lt;/p&gt;

&lt;p&gt;Mich ärgert das deshalb, weil ich jetzt seit 20 Jahren in meinen Codes immer
beide Line-Ending Fälle brav behandle.&lt;br /&gt;
Das hätten die Macher von &lt;code&gt;auditd&lt;/code&gt; auch tun können, schließlich braucht man 
nur das &lt;code&gt;CR&lt;/code&gt; vor einem &lt;code&gt;LF&lt;/code&gt; wegkürzen und alles ist gut.&lt;/p&gt;

&lt;p&gt;However … Gefahr erkannt, Gefahr gebannt.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>_bios_disk()</title>
   <link href="https://www.opengate.at/blog/2023/02/bios_disk/"/>
   <published>2023-02-19T12:00:00+01:00</published>
   <updated>2023-02-19T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2023/02/bios_disk</id>
   <category term="devel" /><category term="retro" />
   <summary type="text">Der Zugriff auf Disketten 
(und die ersten Festplatten) war bereits mit dem originalen IBM 
BIOS möglich, denn der 
INT 13h bot einige Dienste, 
wie etwas das Lesen und Schreiben einzelner Sektoren.
Das brauchte das BIOS auch selbst, um das OS booten zu können.

Watcom (und andere historische Compiler)
stellen für diesen Systemaufruf die C-Funktion _bios_disk() zur Verfügung.
</summary>
   <content type="html">&lt;p&gt;Der Zugriff auf &lt;a href=&quot;https://de.wikipedia.org/wiki/Diskette&quot;&gt;Disketten&lt;/a&gt; 
(und die ersten Festplatten) war bereits mit dem originalen IBM 
&lt;a href=&quot;https://de.wikipedia.org/wiki/BIOS&quot;&gt;BIOS&lt;/a&gt; möglich, denn der 
&lt;a href=&quot;https://stanislavs.org/helppc/int_13.html&quot;&gt;INT 13h&lt;/a&gt; bot einige Dienste, 
wie etwas das Lesen und Schreiben einzelner Sektoren.&lt;br /&gt;
Das brauchte das BIOS auch selbst, um das OS booten zu können.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Watcom&quot;&gt;Watcom&lt;/a&gt; (und andere historische Compiler)
stellen für diesen Systemaufruf die C-Funktion &lt;code&gt;_bios_disk()&lt;/code&gt; zur Verfügung.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Grundsätzlich funktionieren alle BIOS und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/MS-DOS&quot;&gt;DOS&lt;/a&gt; Systemaufrufe recht ähnlich.
Man schreibt in das &lt;code&gt;A&lt;/code&gt; Register (&lt;code&gt;AH&lt;/code&gt;, &lt;code&gt;AL&lt;/code&gt; oder &lt;code&gt;AX&lt;/code&gt;) eine Aufrufnummer,
setzt weitere Register auf diverse Parameter und springt zu einem der 
Interrupts:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;int 10h&lt;/code&gt; für Text- und Grafik&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;int 13h&lt;/code&gt; für Disketten und Festplattenzugriffe&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;int 21h&lt;/code&gt; für MS-DOS Funktionen&lt;/li&gt;
  &lt;li&gt;und viele mehr&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;(Hmm … an welchen &lt;a href=&quot;https://de.wikipedia.org/wiki/Unix&quot;&gt;Unix&lt;/a&gt; Klon erinnert 
uns das jetzt?)&lt;/p&gt;

&lt;p&gt;Um das zu vereinfachen, haben die Compiler von damals einige häufig benutzte
&lt;a href=&quot;https://de.wikipedia.org/wiki/Assemblersprache&quot;&gt;Assembler&lt;/a&gt; Interrupt-Aufrufe 
in &lt;a href=&quot;https://de.wikipedia.org/wiki/C_(Programmiersprache)&quot;&gt;C Funktionen&lt;/a&gt; gekapselt.&lt;br /&gt;
Watcom stellt auch heute noch in &lt;code&gt;dos.h&lt;/code&gt; viele DOS-Aufrufe direkt als&lt;br /&gt;
&lt;code&gt;unsigend _dos_*(...);&lt;/code&gt; zur Verfügung.&lt;/p&gt;

&lt;p&gt;Tatsächlich gibt es auch den Header &lt;code&gt;bios.h&lt;/code&gt;, der einige häufig genutzte 
BIOS Funktionen kapselt:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;_bios_disk&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;_bios_equiplist&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;_bios_keybrd&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;_bios_memsize&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;_bios_printer&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;_bios_serialcom&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;_bios_timeofday&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;disketten-auslesen&quot;&gt;Disketten auslesen&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;Wozu sollte man heute Disketten per BIOS-Aufruf auslesen?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Tja, wenn man einen &lt;a href=&quot;/blog/2019/09/toshiba-t300/&quot;&gt;Toshiba T300&lt;/a&gt;
hat, der ein 640 KB-Spezialdiskettenformat unterstützt, das kein anderes 
5.25 Zoll Laufwerk lesen kann, und wenn man von einer solchen Diskette ein 
Image ziehen will … dann braucht man das.&lt;/p&gt;

&lt;p&gt;Der T300 kann zum Glück auch normale IBM/DOS 360 KB Diskettenformate lesen
und schreiben. Doch Booten kann er offenbar nur von seinem Spezialformat.&lt;/p&gt;

&lt;p&gt;Meine Idee war daher die Sektoren der Spuren auszulesen und in Dateien
auf dem zweiten Laufwerk zu schreiben. So kann man eine “große” Diskette
in zwei kleine teilen, die dann ein neuerer PC wieder lesen kann.&lt;/p&gt;

&lt;p&gt;Man befüllt also eine &lt;code&gt;struct _ibm_diskinfo_t&lt;/code&gt; mit den Laufwerksparametern
und ruft&lt;br /&gt;
&lt;code&gt;_bios_disk(_DISK_READ, &amp;amp;diskinfo);&lt;/code&gt; auf.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;struct&lt;/span&gt; _ibm_diskinfo_t 
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;unsigned&lt;/span&gt; drive;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;unsigned&lt;/span&gt; head;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;unsigned&lt;/span&gt; track;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;unsigned&lt;/span&gt; sector;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;unsigned&lt;/span&gt; nsectors;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;* buffer;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;};
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Ein paar Details über den Aufruf musste ich mir von den alten Interrupt-Listen
zusammensuchen, die ich zum Glück online finden konnte.&lt;/p&gt;

&lt;p&gt;Dass &lt;code&gt;drive&lt;/code&gt; mit &lt;code&gt;0&lt;/code&gt; Laufwerk &lt;code&gt;A&lt;/code&gt; und mit &lt;code&gt;1&lt;/code&gt; dann &lt;code&gt;B&lt;/code&gt; meint, ist logisch.&lt;br /&gt;
Der Kopf kann mit &lt;code&gt;0&lt;/code&gt; und &lt;code&gt;1&lt;/code&gt; die obere untere Seite ansprechen.&lt;br /&gt;
&lt;code&gt;track&lt;/code&gt; geht von &lt;code&gt;0&lt;/code&gt; bis einschließlich &lt;code&gt;79&lt;/code&gt; auf meiner Spezialdiskette.&lt;br /&gt;
Und &lt;code&gt;sector&lt;/code&gt;, tja der tanzt mit der Nummerierung von &lt;code&gt;1&lt;/code&gt; bis &lt;code&gt;8&lt;/code&gt; aus der Reihe.&lt;/p&gt;

&lt;p&gt;Doch so konnte ich dann den ersten 512-Bytes Puffer befüllen und freute mich,
dass die Daten auch tatsächlich einem 
&lt;a href=&quot;https://de.wikipedia.org/wiki/File_Allocation_Table#FAT12&quot;&gt;FAT12&lt;/a&gt; 
Format entsprachen. Zumindest einige der Felder konnte ich klar zuordnen und 
sie stimmten mit den Laufwerksparametern überein.&lt;/p&gt;

&lt;p&gt;Leider schlug mein erster Versuch die Sektoren in einer Schleife auszulesen
fehl, denn ich erhielt von den Folgesektoren immer leere Puffer zurück.&lt;br /&gt;
Vielleicht hat DOS auch etwas dagegen, wenn man im Hintergrund per 
&lt;code&gt;int 13h&lt;/code&gt; das Laufwerk fernsteuert, oder der Aufruf in der Schleife klappt
nicht wie erwartet.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Zumindest kann ich eines feststellen:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;OpenWATCOM erstellt 16-Bit DOS-EXE Programme, die auch auf dem 
Toshiba T300 lauffähig sind.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ich war leider zu kurz am Zweitwohnsitz und konnte keine weiteren Tests
machen, warum das weitere Auslesen fehlschlug.&lt;/p&gt;

&lt;p&gt;Leider ist von vielen BIOS-Varianten bekannt, dass sie Bugs haben und z.B.
Registerwerte zerstören. Wann das hier der Fall ist und die &lt;code&gt;_bios_disk&lt;/code&gt;
Funktion nicht ausreichend abgesichert ist, dann müsste man den Aufruf
in Assembler neu schreiben und alles doppelt und dreifach absichern.&lt;/p&gt;

&lt;p&gt;Wie dem auch sei … zumindest ein Teilschritt ist erreicht und beim
nächsten Mal komme ich hoffentlich wieder ein Stück weiter.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Ant man 3 - Quantumania</title>
   <link href="https://www.opengate.at/blog/2023/02/quantumania/"/>
   <published>2023-02-18T12:00:00+01:00</published>
   <updated>2023-02-18T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2023/02/quantumania</id>
   <category term="entertainment" />
   <summary type="text">Phase 5 ist da!
Mit Ant-Man and the Wasp - Quantumania
hat das Marvel Cinematic Universe 
seine 5. Phase erreicht und deren Prämisse lautet:
Das Multiversum.

</summary>
   <content type="html">&lt;p&gt;Phase 5 ist da!&lt;br /&gt;
Mit &lt;a href=&quot;https://de.wikipedia.org/wiki/Ant-Man_and_the_Wasp:_Quantumania&quot;&gt;Ant-Man and the Wasp - Quantumania&lt;/a&gt;
hat das &lt;a href=&quot;https://de.wikipedia.org/wiki/Marvel_Cinematic_Universe&quot;&gt;Marvel Cinematic Universe&lt;/a&gt; 
seine 5. Phase erreicht und deren Prämisse lautet:&lt;br /&gt;
Das Multiversum.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Es begann mit der &lt;a href=&quot;https://de.wikipedia.org/wiki/Loki_(Fernsehserie)&quot;&gt;Loki-Serie&lt;/a&gt;, 
an deren Ende der neue Bösewicht &lt;a href=&quot;https://en.wikipedia.org/wiki/Kang_the_Conqueror&quot;&gt;Kang&lt;/a&gt; 
angedeutet wurde, doch dann kamen die andere Filme und Serien, die fern ab 
von der Idee des Multiversums spielten.&lt;br /&gt;
In &lt;a href=&quot;https://de.wikipedia.org/wiki/Doctor_Strange_in_the_Multiverse_of_Madness&quot;&gt;Doctor Strange in the Multiverse of Madness&lt;/a&gt;
wurde das Multiversum als nebeneinanderliegende Universen dargestellt, die
von einander isoliert und völlig unterschiedlich sind … außer man hat 
die besondere Fähigkeit Tore zwischen diesen Universen zu öffnen.&lt;/p&gt;

&lt;p&gt;Doch in der Loki Serie drang eines durch:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Was ist, wenn in einem Universum jemand sitzt, 
der die anderen Universen kontrollieren möchte.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Hier startet nun Phase 5 durch, die am Ende in einem Multiverse Avengers
Film &lt;a href=&quot;https://en.wikipedia.org/wiki/Avengers_The_Kang_Dynasty&quot;&gt;The Kang Dynasty&lt;/a&gt; 
in Phase 6 enden soll.&lt;/p&gt;

&lt;h3 id=&quot;achtung-spoiler&quot;&gt;Achtung Spoiler&lt;/h3&gt;

&lt;p&gt;Ich hatte es schon befürchtet, als ich die Trailer zum neuen Film sah und es
hat sich leider bestätigt:&lt;/p&gt;

&lt;p&gt;Janet von Dyne (Michelle Pfeiffer) wurde im zweiten Teil aus der Quantenebene
gerettet, in der sie 30 Jahre lange gelebt hat, und es wurde so dargestellt,
als wäre das ein öder Raum, in dem nur hausgroße Amöben und Bärtierchen 
herumschwimmen.&lt;br /&gt;
Doch im Quantumania-Film wird der Figur “angedichtet”, sie wolle nicht 
erzählen, was sie in Wirklichkeit dort unten erlebt hat.&lt;br /&gt;
Dort lebt nämlich eine ganze Zivilisation von Menschen und außerirdischen 
Kreaturen gemeinsam mit (W-T-F) 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Bill_Murray&quot;&gt;Bill Murray&lt;/a&gt;, und alle treffen 
sich dort in Bars, wo sich sonst nur Luke Skywalker betrinken würde.&lt;/p&gt;

&lt;p&gt;Es sah wirklich sehr nach Star Wars aus, nur eben ohne Lichtschwerter.&lt;/p&gt;

&lt;p&gt;Aber das eigentlich Schlimme war: Janet hatte dort einen gestrandeten 
“Kang the Conqueror” getroffen und seine dunklen Pläne gesehen, wie er
alle anderen Universen entweder erobern oder zerstören wollte.&lt;/p&gt;

&lt;p&gt;Diese Geschehnisse hatte sie einfach verschwiegen, bis es sie nun erneut
gemeinsam mit Ant-Man alt (Michael Douglas) und neu (Paul Rudd), der
Wespe (Evangeline Lilly) und der rebellischen Tochter Cassie (Kathryn Newton)
wieder in die Quantenwelt verschlug.&lt;/p&gt;

&lt;p&gt;Diese herbei konstruierte Story ist mein größter Kritikpunkt am ganzen Film.&lt;/p&gt;

&lt;p&gt;Denn wenn ein Frau 30 Jahre gegen einen Weltenzerstörer kämpft und eine 
Rebellengruppe anführt, es dann aber dem Ehemann der Tochter einfach so 
verschweigt, dann ist das schon recht unglaubwürdig.&lt;/p&gt;

&lt;h3 id=&quot;action-im-mikrokosmos&quot;&gt;Action im Mikrokosmos&lt;/h3&gt;

&lt;p&gt;Ein verbannter Weltenherrscher, eine Gruppe “Weltenreisende” … na, die
Story konnte man sich denken. 
Es geht nur darum, dass Kang wieder aus der Quantenebene hinaus will und als
Leute auftauchen, die das schon mal hinbekommen haben, beginnt das Spiel
nach Schema F: Ich entführe/kidnappe, dafür gibst du mir den Schlüssel zum
Fluchtwagen, am Ende ruft Gandalf die Adler und Harry Potter entwaffnet
Magneto.&lt;/p&gt;

&lt;p&gt;So in etwa war Quantumania und es hat Spaß gemacht.&lt;br /&gt;
Schließlich sind wir in einer Comic-Welt voller Comic-Superhelden und Schurken,
also warum nicht.&lt;/p&gt;

&lt;p&gt;Mit &lt;a href=&quot;https://de.wikipedia.org/wiki/Jonathan_Majors&quot;&gt;Jonathan Majors&lt;/a&gt; als 
Kang hat Marvel eine brilliante Besetzung gefunden, denn während alle anderen
Figuren Comic-haft herumalberten, gelang es dem Haudegen sowohl das brutale 
wie auch das etwas wahnsinnige eines Eroberers glaubhaft darzustellen.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/marvel-quantumania.jpg&quot; alt=&quot;Marvel Quantumania&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;auch-mit-streichelzoo-für-kleinkinder&quot;&gt;Auch mit Streichelzoo für Kleinkinder&lt;/h3&gt;

&lt;p&gt;Wenn etwas übertrieben war, dann waren es die kindlichen Pipi-Kacka-Witze.
“Humpty Dumpty” Modok bekommt zuerst tödliche Waffen, doch es reicht, dass 
ihm Cassy gut zuredet, dass er kein Arsch mehr sein soll, und schon kämpft 
er für das Gute.&lt;br /&gt;
Das hätte auch aus einer Folge &lt;a href=&quot;https://de.wikipedia.org/wiki/Doctor_Snuggles&quot;&gt;Doctor Snuggles&lt;/a&gt;
stammen können. In einem Marvel-Action-Film fand ich es unpassend, aber wenn
die Teenies was draus lernen, dann kann ich damit auch leben.&lt;/p&gt;

&lt;h3 id=&quot;und-das-beste-die-x-credit-szenen&quot;&gt;Und das Beste: Die X-Credit Szenen&lt;/h3&gt;

&lt;p&gt;Es ist für den Film etwas traurig, aber ich gebe zu, dass mich von Anfang an 
am meisten die Mid- und End-Credit Szenen interessiert haben.&lt;br /&gt;
Ich wusste, dass im ersten Film der Phase 5 nicht schon alles “erledigt” sein 
konnte, und dass wir jetzt wieder 3 Jahre auf “den großen Avengers-Film” 
hinarbeiten werden.&lt;/p&gt;

&lt;p&gt;Und es war so unglaublich geil, als nach dem Ende von Ant-Man und dem Tod
“unseres Kangs” in der Quantenwelt, plötzlich ein ganzes Stadion voller
Kangs zu sehen war, die sich der neuen Bedrohung widmen mussten, nachdem
“einer der ihren” getötet wurde.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/marvel-quantumania-mid-credit.jpg&quot; alt=&quot;Marvel Quantumania Mid Credit&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Getoppt wurde das dann nur noch durch die End-Credit Szene, die dann
Loki Staffel 2 ankündigte. Loki und Mobius lauschten einem “frühen”
Kang im 18. Jahrhundert alias Victor Timely, der über die Zeit und ihre 
Manipulation vor Publikum sprach.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/marvel-quantumania-end-credit.jpg&quot; alt=&quot;Marvel Quantumania End Credit&quot; /&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Victor Timely and his Astounding Temporal Marvels.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;WOW. Phase 5 hat eingeschlagen.&lt;br /&gt;
Ich tue dem Film sicher unrecht, wenn ich ihn nur auf sein Ende und die beiden
Credit-Szenen reduziere … aber darum ging es doch. Eine typische Comic-Story
als Vorspiel für die kommenden Filme.&lt;br /&gt;
Quantumania hat es geschafft, dass ich mich total auf die kommenden Filme und
die “Entwicklung von Kang” freue.&lt;/p&gt;

&lt;p&gt;Denn während uns Phase 4 mit vielen Fragezeichen und ohne Thanos-Ersatz hat
stehen lassen, knallt uns Phase 5 einen noch krasseren Bad-Ass hin, dem
sprichwörtlich alles zuzutrauen ist.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>3 Tage Rust</title>
   <link href="https://www.opengate.at/blog/2023/02/rust/"/>
   <published>2023-02-11T12:00:00+01:00</published>
   <updated>2023-02-11T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2023/02/rust</id>
   <category term="devel" />
   <summary type="text">In der Nachbarabteilung meiner Firma wurde festgestellt, dass 
dotNet Software 
“nicht ganz so gut performt” und deshalb musste eine schnellere Sprache her.
Das wurde dann nicht C++, 
weil das angeblich zu kompliziert ist, sondern 
Rust.

Und weil in der bestellten Rust-Schulung für Mitarbeiter noch ein Platz frei
war, durfte ich mich da auch hineinsetzen.
</summary>
   <content type="html">&lt;p&gt;In der Nachbarabteilung meiner Firma wurde festgestellt, dass 
&lt;a href=&quot;https://de.wikipedia.org/wiki/.NET_(Plattform)&quot;&gt;dotNet&lt;/a&gt; Software 
“nicht ganz so gut performt” und deshalb musste eine schnellere Sprache her.
Das wurde dann nicht &lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B&quot;&gt;C++&lt;/a&gt;, 
weil das angeblich zu kompliziert ist, sondern 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Rust_(Programmiersprache)&quot;&gt;Rust&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Und weil in der bestellten Rust-Schulung für Mitarbeiter noch ein Platz frei
war, durfte ich mich da auch hineinsetzen.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Als C und C++ Entwickler sehe ich da eine “Konkurrenz” aufkommen, deren 
Notwendigkeit sich mir eigentlich nicht erschließt. … aber das ist nicht
verwunderlich, genau so ging es mir vor über 10 Jahren schon mit 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Objective-C&quot;&gt;Objective-C&lt;/a&gt;.&lt;br /&gt;
Wenn man sein Handwerk beherrscht, sieht man nicht die Notwendigkeit es 
durch etwas anderes zu ersetzen.&lt;/p&gt;

&lt;p&gt;Und so fiel mir intensiv auf, dass (wie immer) alles nur anders benannt ist
um sich zu unterscheiden, und im Endeffekt auch “nur programmiert” wird.&lt;/p&gt;

&lt;p&gt;Beim Längeren Nachdenken versteht man dann aber doch einige Dinge besser
und kann ihren (wenn auch seltsam wirkenden) Ursprung nachvollziehen.&lt;/p&gt;

&lt;h3 id=&quot;die-vorteile&quot;&gt;Die Vorteile&lt;/h3&gt;

&lt;h4 id=&quot;formzwang&quot;&gt;Formzwang&lt;/h4&gt;

&lt;p&gt;Als C/C++ Mensch liebt und hasst man die völlige Freiheit im Code 
gleichzeitig, denn man selbst kann sich frei entfalten, und weil das
alle so machen, versteht man den Code des Nachbar nicht mehr.&lt;/p&gt;

&lt;p&gt;Der Rust Compiler geht hier so weit, dass er Verletzungen des Codingstyles
als Warnung anzeigt. Wer also&lt;br /&gt;
&lt;code&gt;fn saySomething()&lt;/code&gt; schreibt, bekommt sofort mitgeteilt, dass es besser
&lt;code&gt;fn say_something()&lt;/code&gt; heißen sollte.&lt;/p&gt;

&lt;p&gt;Und ich gebe zu, dass auch ich an mir selbst inzwischen leide, dass ich mich
mal darauf festgelegt habe, in C anders zu arbeiten als in C++, damit man die
Ebenen besser unterscheiden kann … aber lesbarer wird die Sache im Ganzen
dadurch nicht.&lt;/p&gt;

&lt;h4 id=&quot;lebensdauer-und-konstanten&quot;&gt;Lebensdauer und Konstanten&lt;/h4&gt;

&lt;p&gt;Dass Instanzen von Variablen eine begrenzte Lebensdauer haben, ist üblich, 
doch Rust verfolgt jede Variable und Referenz und vermag daher dem Anwender
gleich zu melden, wenn dieser auf etwas zugreift, was nicht mehr existiert.&lt;/p&gt;

&lt;p&gt;In C++ hingegen dürfen wir sogar lokale Variablen als Referenz aus einer
Funktion zurückgeben, was selten eine gute Idee ist.&lt;/p&gt;

&lt;p&gt;Auch das transferieren einer Variable in eine andere folgt festen Spielregeln,
womit es erst einmal ausgeschlossen ist, dass zwei Threads auf die 
gleiche Speicherzelle zugreifen dürfen. Erst mit zusätzlichem Aufwand werden
solche Zugriffe möglich, was in C++ ohne Warnung oft “als Unfall” passiert.&lt;/p&gt;

&lt;p&gt;Dass außerdem erst einmal alles “konstant” ist und explizit als “veränderbar”
(&lt;code&gt;mut&lt;/code&gt;) markiert werden muss, ist entgegen der Norm. Doch wenn man auch hier
wieder an Multithreading denkt, ergeben sich damit enorme Sicherheiten, die
man in anderen Sprachen schnell und oft leichtsinnig verliert.&lt;/p&gt;

&lt;h4 id=&quot;fehlerbehandlung&quot;&gt;Fehlerbehandlung&lt;/h4&gt;

&lt;p&gt;Und wer ein Fan von C-Returncodes ist und C++ 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Ausnahmebehandlung&quot;&gt;Exceptions&lt;/a&gt; hasst, der wird
Rusts &lt;code&gt;enum Result&amp;lt;T, E&amp;gt;&lt;/code&gt; richtig lieben.&lt;br /&gt;
Mit dem &lt;code&gt;?&lt;/code&gt;-Operator wird nämlich das&lt;br /&gt;
&lt;code&gt;if(!ok) return error;&lt;/code&gt; in ein Zeichen am Ende eines Aufrufs hineinkodiert.
Man programmiert also den Erfolgsfall weiter und darf sich darauf verlassen,
dass Rust den Fehler automatisch zurückgibt, bis er irgendwo explizit 
behandelt wird … und das alles ohne Exception-Overhead.&lt;/p&gt;

&lt;h4 id=&quot;-und-vieles-mehr&quot;&gt;… und vieles mehr&lt;/h4&gt;

&lt;p&gt;Natürlich kann man jetzt nicht alle Vorzüge auflisten, die lernt man in 
jedem Rust-Tutorial. Doch die 3 genannten Punkte gefallen mir persönlich
sehr.&lt;/p&gt;

&lt;h3 id=&quot;die-andere-seite&quot;&gt;Die andere Seite&lt;/h3&gt;

&lt;p&gt;Wenn eine Sprache aber so andersartig und seltsam ist, dass sie mit wenig
vergleichbar ist, dann stellt sich einem schon die Frage, ob das gut,
und vor allem ob das sinnvoll ist.&lt;/p&gt;

&lt;h4 id=&quot;traits-vs-klassen&quot;&gt;Traits vs. Klassen&lt;/h4&gt;

&lt;p&gt;Ein Mathematiker mag es anders sehen, doch ich als Embedded-Programmierer 
schätze das Interface- Objekt- und Vererbungsmodell der Sprachen C++, C#,
und Java wirklich sehr.&lt;/p&gt;

&lt;p&gt;Rust kennt dieses Konzept nicht, sondern lässt uns &lt;code&gt;Traits&lt;/code&gt; für jedes
neue Element implementieren. Parallel dazu werden Attribute eingesetzt
um “ähnliche” Eigenschaften magisch hinzuzufügen.&lt;/p&gt;

&lt;p&gt;Während mir in C++ eine Klasse ganz genau sagt, von wem sie Eigenschaften
bekommen (geerbt) hat, kann in Rust jeder Typ im Nachhinein durch ein
Trait “erweitert” werden. Übersichtlich ist das nicht.&lt;/p&gt;

&lt;h4 id=&quot;keine-trennung-von-kernsprache-und-bibliothek&quot;&gt;Keine Trennung von Kernsprache und Bibliothek&lt;/h4&gt;

&lt;p&gt;Während in C++ Operatoren als Teil der Kernsprache überladen werden können,
nutzt Rust (für mich willkürlich definierte) Traits.&lt;br /&gt;
Wer für eine Struktur das Trait &lt;code&gt;std::ops::Add&lt;/code&gt; implementiert, der kann dann
seine Instanzen mit &lt;code&gt;obj1 + obj2&lt;/code&gt; addieren, was ja schön und gut ist.&lt;/p&gt;

&lt;p&gt;Doch dass dafür von der Kernsprache in einen Bibliotheksnamensraum 
hineingegriffen werden muss um das Operatorsymbol &lt;code&gt;+&lt;/code&gt; zu “überladen”,
ist meiner Erfahrung nach kein guter Designansatz.&lt;/p&gt;

&lt;h4 id=&quot;uneinheitliche-typenbestimmung&quot;&gt;Uneinheitliche Typenbestimmung&lt;/h4&gt;

&lt;p&gt;Der Rust-Compiler rät sehr geschickt herum um den Typ einer Variablen
festzustellen. Man könnte diesen explizit festlegen, doch das macht
man nur, wenn es sein muss.&lt;br /&gt;
Wann man was definieren muss scheint mir recht kompliziert definiert 
zu sein. Manchmal reicht ein &lt;code&gt;_&lt;/code&gt; als Platzhalter, dass der Compiler 
später den Typen einfügt, manchmal nicht.&lt;/p&gt;

&lt;p&gt;Manchmal braucht man den “Turbofish” (mit Ähnlichkeit zu expliziten 
C++ Template Instanziierungen, z.B.: &lt;code&gt;foo().bar::&amp;lt;Vec&amp;lt;i32&amp;gt;&amp;gt;::()&lt;/code&gt;), 
um Typen festzulegen, weil es nicht anders geht, und manchmal errät der 
Compiler alles ohne Typenangaben.&lt;/p&gt;

&lt;p&gt;Selbst unser Trainer im Kurs konnte das nicht immer so genau sagen.&lt;/p&gt;

&lt;h4 id=&quot;-und-vieles-mehr-&quot;&gt;… und vieles mehr …&lt;/h4&gt;

&lt;p&gt;Ich will jetzt gar nicht von der hässlichen Lifetime-Syntax wie &lt;br /&gt;
&lt;code&gt;fn foo&amp;lt;&apos;a&amp;gt;(x: &amp;amp;&apos;a i32)&lt;/code&gt; anfangen, kurz gesagt: Rust ist so 
fremdartig, dass es wenig Anknüpfpunkte (und Zusammenarbeit) mit
anderen Sprachen gibt.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Der für mich größte Nachteil von Rust ist: Es hat kein standardisiertes
&lt;a href=&quot;https://de.wikipedia.org/wiki/Bin%C3%A4rschnittstelle&quot;&gt;ABI&lt;/a&gt; um seine Features
ins System exportieren zu können, schlimmer noch, es will auch gar keines.&lt;br /&gt;
Rust kann Bibliotheken und Sourcen nur in ein großes Binary 
zusammenkompilieren.&lt;/p&gt;

&lt;p&gt;Das entspricht reinen statischen Bibliotheken in C++. Und das fände ich
eigentlich sogar ganz gut … doch dass man eben gar keine nativen
Rust DLLs oder SOs (ohne Kunstgriffe) erzeugen kann, ist eine kritische
Einschränkung.&lt;/p&gt;

&lt;p&gt;Einzige Option: eine C-API. Man kann Rust Code in C-Funktionen kapseln,
damit sie von anderen Modulen benutzt werden können. Doch genau hier gehen
dann alle Sicherheitsfeatures von Rust wieder verloren und man muss die
sicheren Rust-Strings in Null-terminierte-C-Strings umwandeln, usw.&lt;/p&gt;

&lt;p&gt;Als Sprache finde ich Rust allerdings sehr interessant und ich hoffe,
dass C++ noch einiges daraus lernen wird.&lt;br /&gt;
Für mich wird es jedoch über eine “einfache” C-Anbindung vermutlich 
wenig Gründe geben, irgend etwas in Rust zu machen.&lt;/p&gt;

&lt;p&gt;Dafür habe ich in C/C++ einfach schon 15 Jahre Vorsprung.&lt;/p&gt;

&lt;p&gt;Außerdem … inzwischen gibt es ja mit &lt;a href=&quot;https://ziglang.org/&quot;&gt;ZIG&lt;/a&gt; die nächste
Programmiersprache, die besser und performanter als Rust sein soll.
Und wenn immer alle von vorne anfangen “ihre eigene” Sprache neu zu entwickeln,
gibt es auf lange Sicht auch keinen Fortschritt.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>GCC: Statische Optimierungen</title>
   <link href="https://www.opengate.at/blog/2023/02/static-optimized/"/>
   <published>2023-02-05T12:00:00+01:00</published>
   <updated>2023-02-05T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2023/02/static-optimized</id>
   <category term="devel" />
   <summary type="text">Statische Bibliotheken gehören bekanntlich zu meinen Lieblingen, und auf
Plattformen wie DOS sind sie sowieso 
eine Notwendigkeit.

Doch trotz Link-Time-Optimization und anderem Schnickschnack sind die
fertigen Programme meist größer als unter Windows.
Und teilweise sogar verdammt übergroß.
</summary>
   <content type="html">&lt;p&gt;Statische Bibliotheken gehören bekanntlich zu meinen Lieblingen, und auf
Plattformen wie &lt;a href=&quot;https://de.wikipedia.org/wiki/MS-DOS&quot;&gt;DOS&lt;/a&gt; sind sie sowieso 
eine Notwendigkeit.&lt;/p&gt;

&lt;p&gt;Doch trotz Link-Time-Optimization und anderem Schnickschnack sind die
fertigen Programme meist größer als unter Windows.
Und teilweise sogar verdammt übergroß.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Ein moderner &lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_C%2B%2B&quot;&gt;MSVC&lt;/a&gt; erzeugt 
gerne eine 100 KB große EXE für ein einfaches &lt;code&gt;hello_world&lt;/code&gt; Programm, wenn 
die C-Runtime statisch gelinkt wird.
Der &lt;a href=&quot;https://de.wikipedia.org/wiki/GNU_Compiler_Collection&quot;&gt;GCC&lt;/a&gt; unter 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt; oder &lt;a href=&quot;https://de.wikipedia.org/wiki/Watcom&quot;&gt;OpenWatcom&lt;/a&gt; 
für DOS sind da schon kompakter mit 10 bis 40 KB.&lt;br /&gt;
Das ist auch halbwegs “OK”, wenn man an die vielen Patches und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Systemaufruf&quot;&gt;System-Call&lt;/a&gt; Wrapper denkt.&lt;/p&gt;

&lt;p&gt;Trotzdem fällt mir auf, dass &lt;code&gt;MSVC&lt;/code&gt; Binaries gerade beim GATE Projekt
nicht so rasant anwachsen, wie auf anderen Plattformen.&lt;br /&gt;
Sowohl der GCC wie auch OpenWatcom produzieren gleich 200 KB große
Binaries, wenn sie gegen die statische GATE-Core Bibliothek linken.&lt;/p&gt;

&lt;p&gt;Ein Blick in die Binaries erklärt das auch:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Da waren alle Funktionen der GATE Bibliotheken enthalten.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Während der &lt;code&gt;MSVC&lt;/code&gt; nur die benutzten Funktionen in die EXE packt, 
legen GCC und Watcom auch alle unbenutzten Funktionen bei.&lt;/p&gt;

&lt;p&gt;Es wird also Zeit für ein Build-Update.&lt;/p&gt;

&lt;h3 id=&quot;gcc&quot;&gt;GCC&lt;/h3&gt;

&lt;p&gt;Jede nicht statische (also &lt;code&gt;extern&lt;/code&gt;) Funktion wird im GCC als “öffentlich”
markiert. Das bedeutet in &lt;code&gt;.so&lt;/code&gt;
&lt;a href=&quot;https://de.wikipedia.org/wiki/Programmbibliothek#Dynamische_Bibliotheken&quot;&gt;Shared Objects&lt;/a&gt;, 
dass sie exportiert wird.&lt;br /&gt;
Programme exportieren jedoch nichts, sondern rufen nur jene Ketten von
Funktionen auf, die irgendwo in &lt;code&gt;main()&lt;/code&gt; anfangen.&lt;br /&gt;
Doch da der GCC auch alles unbenutzte beilegt, werden Programme unnötig
groß.&lt;/p&gt;

&lt;h4 id=&quot;lösung-attribute-visibility-hidden&quot;&gt;Lösung: &lt;strong&gt;attribute&lt;/strong&gt; ((visibility (“hidden”)))&lt;/h4&gt;

&lt;p&gt;Ich baue Shared-Libs grundsätzlich mit der default-Visibility &lt;code&gt;hidden&lt;/code&gt;, doch
bei Programmen habe ich das bisher nie benutzt.&lt;br /&gt;
Die Alternative ist natürlich, dass man das “Exportier-Makro” aller Funktionen
explizit auf &lt;code&gt;__attribute__ ((visibility (&quot;hidden&quot;)))&lt;/code&gt; schaltet.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#if&lt;/span&gt; defined(GATE_COMPILER_GCC)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#  define&lt;/span&gt; GATE_API_EXPORT __attribute__((visibility (&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;default&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)))
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#  define&lt;/span&gt; GATE_API_IMPORT
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#  define&lt;/span&gt; GATE_API_LOCAL __attribute__ ((visibility (&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;hidden&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)))
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#endif&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#if&lt;/span&gt; defined(GATE_SHARED_LIBS)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#  if&lt;/span&gt; defined(GATE_CORE_EXPORTS)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#    define&lt;/span&gt; GATE_CORE_API GATE_API_EXPORT
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#  else&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#    define&lt;/span&gt; GATE_CORE_API GATE_API_IMPORT
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#  endif&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#else&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#  define&lt;/span&gt; GATE_CORE_API GATE_API_LOCAL
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#endif&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;GATE_CORE_API &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; gate_foo(&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; something);
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h3 id=&quot;watcom&quot;&gt;Watcom&lt;/h3&gt;

&lt;p&gt;Unter DOS war die Sache noch viel auffälliger. Ich musste das Speicher-Modell
auf &lt;code&gt;Medium&lt;/code&gt; erhöhen, damit alle Daten in einer GATE-Hello-World EXE Platz 
hatten.
Auch hier zeigte die erstellte &lt;code&gt;.map&lt;/code&gt; Datei, dass alle Funktionen der 
Bibliothek samt Daten und &lt;code&gt;VTBL&lt;/code&gt; Strukturen in die EXE gewandert waren.&lt;/p&gt;

&lt;h4 id=&quot;lösung--zm-und-opt-el&quot;&gt;Lösung: &lt;code&gt;-zm&lt;/code&gt; und &lt;code&gt;opt el&lt;/code&gt;&lt;/h4&gt;

&lt;p&gt;Wenn man das Compiler-Flag &lt;code&gt;-zm&lt;/code&gt; anhängt, werden Funktionen in eigene Segmente
ausgelagert. Und die Linker-Option &lt;code&gt;ELIMINATE&lt;/code&gt;, löscht dann alle diese 
Fragmente, die nicht vom Programm aus aufgerufen werden.&lt;/p&gt;

&lt;p&gt;In &lt;a href=&quot;https://de.wikipedia.org/wiki/CMake&quot;&gt;CMake&lt;/a&gt; für Watcom sieht dass 
dann so aus:&lt;/p&gt;

&lt;div class=&quot;language-cmake highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;set(CMAKE_C_FLAGS_RELEASE &amp;quot;${CMAKE_C_FLAGS_RELEASE} -zm&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;set(CMAKE_CXX_FLAGS_RELEASE &amp;quot;${CMAKE_CXX_FLAGS_RELEASE} -zm&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;set(CMAKE_EXE_LINKER_FLAGS_RELEASE &amp;quot;${CMAKE_EXE_LINKER_FLAGS_RELEASE} opt el&amp;quot;)
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;Kleine EXE, große Wirkung!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Gerade, wenn man &lt;a href=&quot;https://de.wikipedia.org/wiki/OpenSSL&quot;&gt;OpenSSL&lt;/a&gt; oder 
&lt;a href=&quot;https://www.libssh2.org/&quot;&gt;libSSH2&lt;/a&gt; statisch in sein Programm mit aufnimmt, 
kommen hunderte wenn nicht tausende Funktionen hinzu, die man nie braucht.
Alle bekommt man leider nie weg, weil sie oft in Strukturen zusammengefasst 
werden, aber wenn man zumindest einige “eliminieren” kann, schrumpft das 
finale Programm dann schon ordentlich.&lt;/p&gt;

&lt;p&gt;So wurde meine DOS-EXE von 135 KB auf 35 KB reduziert.&lt;br /&gt;
Und der GCC verbuchte für das alte 200 KB Binary nach der Kur nur noch 25 KB.&lt;/p&gt;

&lt;p&gt;Damit wurde der &lt;code&gt;MSVC&lt;/code&gt; mit seinen 100 KB Babyspeck deutlich geschlagen und die
großen 4-MB Programme sind jetzt auf Windows und Linux ziemlich gleich groß.&lt;/p&gt;

&lt;p&gt;Wenn also etwas unnatürlich groß aus der Compiler-Fertigung herauskommt, gilt:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Nicht verzagen, Compiler-Handbuch fragen!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Denn dort findet man (nach langem Suchen) meist den Grund und die Lösung.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Nachtrag: Wakanda forever</title>
   <link href="https://www.opengate.at/blog/2023/02/wakanda-4ever/"/>
   <published>2023-02-04T12:00:00+01:00</published>
   <updated>2023-02-04T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2023/02/wakanda-4ever</id>
   <category term="entertainment" />
   <summary type="text">Im November hatte ich 
Black Panther - Wakanda forever
im Kino gesehen.
Ich wusste damals nicht so recht, was ich darüber schreiben soll.
Nun ist der Film auf Disney+ erschienen und ich weiß es immer noch nicht.

Aber weglassen darf man den Film auch nicht!
</summary>
   <content type="html">&lt;p&gt;Im November hatte ich 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Black_Panther:_Wakanda_Forever&quot;&gt;Black Panther - Wakanda forever&lt;/a&gt;
im Kino gesehen.&lt;br /&gt;
Ich wusste damals nicht so recht, was ich darüber schreiben soll.
Nun ist der Film auf Disney+ erschienen und ich weiß es immer noch nicht.&lt;/p&gt;

&lt;p&gt;Aber weglassen darf man den Film auch nicht!
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Das schlimmste, was einem in einer Fernsehserie passieren kann, ist, wenn 
einem der Hauptdarsteller abhanden kommt.&lt;br /&gt;
Und da die Marvel-Filme eigentlich eine Langzeit-Serie sind, trifft das 
dort auch zu.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Chadwick_Boseman&quot;&gt;Chadwick Boseman&lt;/a&gt; der 
Darsteller des Black Panther ist 2020 verstorben … und so wie es mit vielen
ikonischen Rollen der Fall ist, wird es meiner Meinung nach nie wieder einen
so guten Black Panther geben können.&lt;/p&gt;

&lt;h3 id=&quot;trauer-und-neustart&quot;&gt;Trauer und Neustart&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Achtung Spoiler!&lt;/strong&gt;&lt;br /&gt;
Ich denke, kein Marvel-Film hatte es so schwer geschaffen zu werden wie dieser.
Die gesamte Story musste an die Realität angepasst werden, nämlich an den
Tod des Darstellers.&lt;br /&gt;
Und somit ist es nicht verwunderlich, dass das Ergebnis irgendwie 
zusammengewürfelt wirkt, und dass &lt;a href=&quot;https://de.wikipedia.org/wiki/Letitia_Wright&quot;&gt;Letitia Wright&lt;/a&gt;
als Shuri weder als Schauspielerin noch als Filmfigur in die Rolle des neuen
Black Panther passt.&lt;/p&gt;

&lt;p&gt;“Das Mädchen” war super als kleine Schwester des Black Panther gecastet und
wirkte als ein “Geschmacksverstärker” für den Erfolg des ersten Teils.&lt;br /&gt;
Doch als neue Superheldin, konnte mich Shuri leider nicht überzeugen, und
vielleicht gab ihr auch der beschleunigte Film nicht die notwendige Zeit dafür.&lt;/p&gt;

&lt;p&gt;Ich ignoriere mal, dass wieder aus dem Nichts heraus eine neue übermächtige 
Partei eingeführt wurde, die seit Jahrhunderten unter dem Meeresboden lebt
und erst jetzt auf einmal Herrschaftsansprüche stellt und Wakanda vernichten
will.&lt;/p&gt;

&lt;p&gt;Nein, das schlimme war eigentlich die End-Credit-Szene.&lt;br /&gt;
Da wird mit Mühe und Not eine weibliche Black-Panther aufgebaut, die dann 
doch noch alles gebacken bekommt, doch dann wird ein Geheimnis gelüftet:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Der Black-Panther hatte bereits einen Sohn gezeugt und vor der Welt 
versteckt, damit ist “der Geist” des Vaters noch in der Welt
und alles wird gut.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ich weiß, die Szene war so nicht gemeint … aber trotzdem bleibt für mich
jetzt übrig, dass Frauen es einfach nicht bringen, doch der nächste Mann ist 
schon da und wird wieder übernehmen, damit alles wieder in Ordnung kommt.&lt;/p&gt;

&lt;p&gt;Zugegeben fällt mir auch nichts besseres ein, wie man mit der Ausgangslage
den Film noch hätte retten können, doch … hätten wir am Ende eine Tochter 
und nicht einen Sohn gesehen, wäre die Blutlinie auch bewahrt worden und
wir hätten die erste weibliche Superheldin von Wakanda nicht gleich wieder
auf die Wartebank geschickt.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/marvel-wakanda-forever.jpg&quot; alt=&quot;Wakanda Forever&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Wakanda Forever gehört definit ins MCU und jeder sollte ihn gesehen haben.
Aber vielleicht nicht wegen seines Inhalts, sondern als Beweis dafür, dass 
auch unter schwierigsten Bedingungen das Team weitergearbeitet hat um diese
Werk fertigzustellen.&lt;/p&gt;

&lt;p&gt;Wir lernen daraus, dass man nicht aufgeben darf, sondern stets in Richtung
Ziel wandern muss. Manchmal kann man hinsprinten … und manchmal muss man
sich hinschleppen. Aufgeben gilt nicht!&lt;/p&gt;

&lt;p&gt;Und diese Message war gerade während der Corona-Pandemie (in der der Film
entstanden ist) wichtiger als alles andere.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Sound-Karten</title>
   <link href="https://www.opengate.at/blog/2023/01/soundblaster/"/>
   <published>2023-01-29T12:00:00+01:00</published>
   <updated>2023-01-29T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2023/01/soundblaster</id>
   <category term="hardware" /><category term="retro" />
   <summary type="text">Verblüffenderweise wäre ich eigentlich “zu jung” für 
Soundkarten, denn etwa ab
dem Jahr 1997 wanderte die Audiofunktion eines PCs auf das Mainboard und 
war “Standard”.

Doch da ich bis nach 2000 immer 5 Jahre alte Gebrauchtgeräte besaß, durfte ich
dieses Phänomen auch noch miterleben.
</summary>
   <content type="html">&lt;p&gt;Verblüffenderweise wäre ich eigentlich “zu jung” für 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Soundkarte&quot;&gt;Soundkarten&lt;/a&gt;, denn etwa ab
dem Jahr 1997 wanderte die Audiofunktion eines PCs auf das Mainboard und 
war “Standard”.&lt;/p&gt;

&lt;p&gt;Doch da ich bis nach 2000 immer 5 Jahre alte Gebrauchtgeräte besaß, durfte ich
dieses Phänomen auch noch miterleben.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Naja … stimmt nicht ganz, 1995 erhielt ich meine erste Soundkarte als 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Industry_Standard_Architecture&quot;&gt;ISA Erweiterungskarte&lt;/a&gt; 
für meinen &lt;a href=&quot;https://de.wikipedia.org/wiki/Intel_80486&quot;&gt;80486&lt;/a&gt;. Die Story war 
eine typisch komische:&lt;br /&gt;
Mein Vater kaufte mir gönnerhaft “PC-Lautsprecher” mit der netten Info der
Verkäuferin im Discounter:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Die steckt man hinten am Monitor an.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ja … beim Mac vielleicht, aber nicht an einen PC Monitor von damals.&lt;br /&gt;
Und weil ich dann meiner Mutter so leid tat, die mich traurig mit den
nutzlosen Boxen herumsitzen sah, wurde dank der Beratung im 
“Computer-Geschäft” eine Soundkarte nachgekauft.&lt;/p&gt;

&lt;p&gt;Die damaligen Preise habe ich nicht mehr im Kopf, doch die Soundkarte
war etwa 3x teurer als die Boxen.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/sound-card-01.jpg&quot; alt=&quot;Soundcard 01&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;wav-avi-und-midi&quot;&gt;WAV, AVI und MIDI&lt;/h3&gt;

&lt;p&gt;Zwischen 95 und 2000 lief eine heute nicht mehr nachvollziehbare Revolution.
PCs waren seit 15 Jahren eigentlich primär Schreibmaschinen mit Monitor und
verwalteten Bürodokumente, Listen und einige wenige Bilder.&lt;br /&gt;
Doch mit dem &lt;a href=&quot;https://de.wikipedia.org/wiki/Intel_Pentium&quot;&gt;Pentium&lt;/a&gt; und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_95&quot;&gt;Windows 95&lt;/a&gt; kam der 
Wechsel von 16 Farben auf 256, 65000 und 16 Mio. Farben auf den Bildschirmen
und langsam verbreiteten sich immer mehr “Videoclips” auf den Heft-CDs 
von Zeitschriften.&lt;/p&gt;

&lt;p&gt;Kleine unkomprimierte &lt;a href=&quot;https://de.wikipedia.org/wiki/Audio_Video_Interleave&quot;&gt;AVI&lt;/a&gt;
Dateien mit anfangs 180 x 120 Pixel zeigten Ausschnitte von Fußballspielen 
und anderen Ereignissen.&lt;br /&gt;
Und ich sah diese vorher immer als Stummfilm.&lt;/p&gt;

&lt;p&gt;Mit der neu installierten Soundkarte wurde der PC zum Videoplayer und ich
fühlte mich damals wie in einer neuen Welt, in der ich am Schaltpult saß
und per Maus “den Film” in Sekundenschnelle vor und rückspulen konnte.&lt;br /&gt;
(Wer weiß noch wie lange das Hin- und Herspulen auf 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Video_Home_System&quot;&gt;VHS&lt;/a&gt;-Videorekordern dauerte…)&lt;/p&gt;

&lt;p&gt;Doch Ton war teuer, da &lt;a href=&quot;https://de.wikipedia.org/wiki/MP3&quot;&gt;MP3&lt;/a&gt; noch nicht 
erfunden und die Hardware gar nicht schnell genug für die Dekompression war.&lt;br /&gt;
Um dennoch “Musik” anhören zu können, sammelten Menschen wie ich die
wenige Kilobyte große &lt;a href=&quot;https://de.wikipedia.org/wiki/MIDI&quot;&gt;MIDI&lt;/a&gt; Dateien, 
die auf genannten Heft-CDs und Spiele Demos enthalten waren.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;MIDI&lt;/code&gt; speichert quasi die Notenblätter einer Musikstückes für eine bestimmte
Anzahl vordefinierter Instrumente.&lt;br /&gt;
Zwar klang ein “Piano” in &lt;code&gt;MIDI&lt;/code&gt; nicht immer wie ein Piano, doch die digitalen
Instrumentennachahmungen hatten auch ihren eigenen Charm und prägten das
“IT Gefühl” der damaligen Zeit.&lt;/p&gt;

&lt;p&gt;Das Besondere (ob gut oder schlecht sei dahingestellt) an &lt;code&gt;MIDI&lt;/code&gt; Dateien war,
dass sie auf jeder Soundkarte etwas anders klangen. Vermutlich war alles am
original Soundblaster ausgelegt, und die Nachbauprodukte versagten teils 
die Töne identisch nachzubilden.&lt;br /&gt;
Erst einige Jahre später mit höheren &lt;a href=&quot;https://de.wikipedia.org/wiki/DirectX&quot;&gt;DirectX&lt;/a&gt; 
Versionen hat zumindest Microsoft den Software-Synthesizer eingeführt, 
womit MIDI-Klänge wieder PC-übergreifend einheitlich waren.&lt;/p&gt;

&lt;h3 id=&quot;varianten-wie-ac97&quot;&gt;Varianten wie AC’97&lt;/h3&gt;

&lt;p&gt;In Sachen Programmierung kam ich erst nach 2007 mit “Audio” in Berührung.
Damals war die Welt schon durchstandardisiert, wobei Windows bis heute seine
klassische Audio-Codec-API mitliefert und in Linux 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Advanced_Linux_Sound_Architecture&quot;&gt;ALSA&lt;/a&gt; weite 
Verbreitung findet.&lt;/p&gt;

&lt;p&gt;Einen PCM-Output-Puffer zu den Lautsprechern und einen PCM-Input-Puffer für 
das Mikrofon gibt es auf beiden Systemen und sie lassen sich damit “ähnlich”
programmieren.&lt;br /&gt;
Damit der Ton nicht kurz unterbrochen wird und ein Knacken hörbar wird, 
nutzt man mehrere Puffer, wo immer einer dem System verarbeitet wird, während
die anderen vorbereitet werden. Ringpuffer sind da eine Möglichkeit.&lt;/p&gt;

&lt;p&gt;Ein interessanter Aspekt war unter Windows der “Mixer”, über den Lautstärken
auf der Soundkarte geregelt werden konnten.&lt;br /&gt;
Bei der Ausgabe konnte man entweder die einzelnen Ausgabeverbindungen 
manuell regeln, oder man konnte nur alles gemeinsam lauter oder leiser 
stellen. Das hing von der Hardware bzw. vom Treiber der Soundkarte ab.&lt;/p&gt;

&lt;p&gt;Und so musste man im Code durchprobieren, welche Variante hier wirksam war.
Am Ende musste der Code auf mehreren Soundkarten und Treibern getestet
werden, damit ein scheinbar so einfaches Feature wie “laut-leise” 
überall funktionierte.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;In der heutigen Streaming-Zeit ist es unvorstellbar, dass PCs von sich aus
nicht mit Sound umgehen konnten. Und selbst die kleinsten SOCs wagen es
nicht, ohne eine 3,5 Klinkenbuchse für den Audioausgange ausgeliefert zu
werden.&lt;/p&gt;

&lt;p&gt;Im professionellen Bereich gibt es auch heute noch Soundkarten, wenn man 
zig Ein- und Ausgänge für die Tonabmischung benötigt … doch für das einfach 
Volk bringt wirklich jedes Gerät vom 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Raspberry_Pi&quot;&gt;Rasperry PI&lt;/a&gt;
bis zum Gaming-PC den Ton bereits mit … im Zweifelsfall wird er dann 
noch über USB veredelt. &lt;br /&gt;
Soll heißen, man steckt einen USB-Soundchip an, der die Ein/Ausgabe regelt
oder direkt per Funk an die Kopfhörer sendet.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/sound-card-03.jpg&quot; alt=&quot;Soundcard 03&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Irgendwie ist es schade, dass man heute nicht mehr “Herr der Karten” am
Mainboard ist. Denn es war schon lustig unter Freunden und Bekannten
herauszufinden, was sie für Ton-Macher verbaut hatten.&lt;/p&gt;

&lt;p&gt;Aber wenn ich an die Problemchen von damals denke, wo nicht zwei Apps 
gleichzeitig Töne abspielen konnten und der Windows-Beep-Sound das
Abspielen eines Mediums einfach unterbrach … dann muss ich zugeben:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Heute (ohne separate Soundkarten) funktioniert das alles viel besser.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/sound-card-02.jpg&quot; alt=&quot;Soundcard 02&quot; /&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Win32 Netzwerk-Setup</title>
   <link href="https://www.opengate.at/blog/2023/01/netcfg/"/>
   <published>2023-01-28T12:00:00+01:00</published>
   <updated>2023-01-28T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2023/01/netcfg</id>
   <category term="devel" />
   <summary type="text">Besonders für “Lizenzen” hatte ich schon öfter den Auftrag, Hardware-Infos
auszulesen. Sehr beliebt sind dafür MAC-Adressen.
Aber auch für manche Server braucht man die Liste der aktuellen IP Adressen,
damit man sich daran binden kann.

Leider hat Windows in den 
letzten 30 Jahren da einiges geändert und somit braucht man oft mehrere
Schnittstellen.
</summary>
   <content type="html">&lt;p&gt;Besonders für “Lizenzen” hatte ich schon öfter den Auftrag, Hardware-Infos
auszulesen. Sehr beliebt sind dafür &lt;a href=&quot;https://de.wikipedia.org/wiki/MAC-Adresse&quot;&gt;MAC-Adressen&lt;/a&gt;.
Aber auch für manche Server braucht man die Liste der aktuellen IP Adressen,
damit man sich daran binden kann.&lt;/p&gt;

&lt;p&gt;Leider hat &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows&quot;&gt;Windows&lt;/a&gt; in den 
letzten 30 Jahren da einiges geändert und somit braucht man oft mehrere
Schnittstellen.
&lt;!--more--&gt;
————————————————————&lt;/p&gt;

&lt;p&gt;Zu Zeiten von &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_NT_4.0&quot;&gt;WinNT 4&lt;/a&gt; 
war die Welt noch einfach.&lt;br /&gt;
Grundsätzlich sollte der User gar keine Details über das Netzwerk wissen, 
sondern nur Laufwerke darüber verbinden und dann “transparent” mit anderen
Systemen im Netzwerk Daten austauschen.&lt;br /&gt;
Ob da jetzt ein &lt;a href=&quot;https://de.wikipedia.org/wiki/NetBEUI&quot;&gt;NetBEUI&lt;/a&gt;, 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Sequenced_Packet_Exchange&quot;&gt;IPX/SPX&lt;/a&gt; oder 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Transmission_Control_Protocol&quot;&gt;TCP/IP&lt;/a&gt; dahinter
benutzt wurde, sollte niemanden interessieren.&lt;/p&gt;

&lt;p&gt;Und dann kam das Internet und TCP/IP wurde DER Standard.&lt;/p&gt;

&lt;p&gt;Und dann wurde es noch komplizierter:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Wir erhielten mehrere IP’s pro physischen Adapter&lt;/li&gt;
  &lt;li&gt;Dann tauchten virtuelle Netzwerkgeräte auf&lt;/li&gt;
  &lt;li&gt;IPv6 kam auch noch dazu&lt;/li&gt;
  &lt;li&gt;Und spätestens mit &lt;a href=&quot;https://de.wikipedia.org/wiki/Hyper-V&quot;&gt;Hyper-V&lt;/a&gt; wurde 
ein Adapter in mehrere aufgeteilt.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Wir müssen heute also zuerst mal unterscheiden, ob wir Netzwerkgeräte oder
Endknoten (wie IP Adressen) auflisten wollen. 
Und wegen möglicher virtualisieren kann durchaus eine MAC-Adresse auch
mehrfach vorkommen.&lt;/p&gt;

&lt;h3 id=&quot;die-nt-apis&quot;&gt;Die NT APIs&lt;/h3&gt;

&lt;p&gt;Mit &lt;a href=&quot;https://learn.microsoft.com/en-us/windows/win32/api/iphlpapi/nf-iphlpapi-getiftable&quot;&gt;GetIfTable&lt;/a&gt;
kommt man bis ins Jahr 1998 zurück, als NT4 SP4 und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_98&quot;&gt;Windows 98&lt;/a&gt; die API 
eingeführt haben.&lt;br /&gt;
Sie liefert alle “Interfaces” als &lt;code&gt;MIB_IFROW&lt;/code&gt; zurück, die im System 
installiert sind. Früher war das mal das &lt;strong&gt;eine&lt;/strong&gt; IP-Interface, das an den 
&lt;strong&gt;einen&lt;/strong&gt; Netzwerkadapter gebunden war. Heute liefert die Funktion leider 
eine Vielzahl von virtuellen und deaktivierten Schnittstellen, womit man
erst viele Flags und andere Kriterien auswerten muss, bis man die 
relevanten Schnittstellen ausgefiltert bekommen hat.&lt;/p&gt;

&lt;p&gt;Im Feld &lt;code&gt;wszName&lt;/code&gt; finden wir heute die Interface-GUID, mit der man bevorzugt 
arbeiten sollte, wenn man die Infos mit anderen Schnittstellen abgleichen will.
Zu NT4 Zeiten gab es die GUID auf der Ebene noch nicht, sondern man musste 
über den &lt;code&gt;dwIndex&lt;/code&gt; (Netzwerk-Interface-Index) das Gerät eindeutig 
identifizieren.&lt;br /&gt;
Das &lt;code&gt;bDescr&lt;/code&gt; Feld gibt uns einen anzeigbaren Namen der Netzwerkschnittstelle
zurück und &lt;code&gt;bPhysAddr&lt;/code&gt; enthält die MAC-Adresse des verbundenen Adapters.&lt;/p&gt;

&lt;p&gt;Die API &lt;a href=&quot;https://learn.microsoft.com/en-us/windows/win32/api/iphlpapi/nf-iphlpapi-getipaddrtable&quot;&gt;GetIpAddrTable&lt;/a&gt;
listet alles in einer &lt;code&gt;struct MIB_IPADDRTABLE&lt;/code&gt; auf, was eine IP-Adresse hat
oder haben könnte.&lt;br /&gt;
Hier kann man eine Verbindung zu &lt;code&gt;GetIfTable&lt;/code&gt; über &lt;code&gt;dwIndex&lt;/code&gt; herstellen und 
somit einen Eintrag der “Interface-Table” mit der “IP-Addr-Table” verknüpfen.&lt;/p&gt;

&lt;h3 id=&quot;windows-2000-und-teils-win98&quot;&gt;Windows 2000 (und teils Win98)&lt;/h3&gt;

&lt;p&gt;Mit &lt;a href=&quot;https://learn.microsoft.com/en-us/windows/win32/api/iphlpapi/nf-iphlpapi-getadaptersinfo&quot;&gt;GetAdaptersInfo&lt;/a&gt; 
erhalten wir in Win2K und teils Win98 bereits eine Combo aus Adapter und IP
Adressen in der &lt;code&gt;IP_ADAPTER_INFO&lt;/code&gt; Struktur. Hier sind dann sogar Gateways 
und DHCP Infos mit dabei, wie auch die gute alte MAC-Adresse.&lt;/p&gt;

&lt;p&gt;Fast könnte man glauben, diese wäre die perfekte API, doch leider listet sie
nur “aktivierte” Adapter mit IPs auf. Das reicht für Socket-Bindungen, aber
MAC-Adressen für Lizenzen sind dann ein Problem. 
Außerdem fehlt der Support für IPv6, da es dieses Protokoll damals noch 
nicht gab.&lt;/p&gt;

&lt;h3 id=&quot;windows-xp&quot;&gt;Windows XP&lt;/h3&gt;

&lt;p&gt;XP brachte uns daher &lt;a href=&quot;https://learn.microsoft.com/en-us/windows/win32/api/iphlpapi/nf-iphlpapi-getadaptersaddresses&quot;&gt;GetAdaptersAddresses&lt;/a&gt;,
welches uns auch IPv6 Daten in seinen &lt;code&gt;IP_ADAPTER_ADDRESSES&lt;/code&gt; Strukturen
liefert.&lt;br /&gt;
Hier wird es wieder kompliziert, wenn es um die Verknüpfung mit anderen APIs
geht. Der Interface-Index liegt hier nämlich entweder im Feld &lt;code&gt;IfIndex&lt;/code&gt; oder 
in &lt;code&gt;Ipv6IfIndex&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Ich nutze die API daher nur für IPv6 Adressen und hole die anderen Daten
über &lt;code&gt;GetAdaptersInfo&lt;/code&gt; ab.&lt;/p&gt;

&lt;h3 id=&quot;von-windows-vista-bis-heute&quot;&gt;Von Windows Vista bis heute&lt;/h3&gt;

&lt;p&gt;Am Ende kam dann mit &lt;a href=&quot;https://learn.microsoft.com/en-us/windows/win32/api/netioapi/nf-netioapi-getiftable2&quot;&gt;GetIfTable2&lt;/a&gt;
und der &lt;code&gt;MIB_IF_TABLE2&lt;/code&gt; ab Windows Vista eine aktualisierte Variante von 
&lt;code&gt;GetIfTable&lt;/code&gt; auf den Markt, die uns mehr Flags und Details über die Hardware
liefert. So wissen wir, ob es ein WLAN oder Ethernet-Gerät ist, oder ob es nur
eine virtuelle Verbindungsbrücke zwischen zB. IPv4 und IPv6 ist.&lt;/p&gt;

&lt;p&gt;Die klassischen NT-APIs liefern heute im schlimmsten Fall 60 Geräte, wie bei 
mir, wenn Hyper-V, WSL und Docker läuft, und dann weiß kein Mensch mehr,
welches davon ein Adapter ist, über den eine lokale Anwendung ihre
Daten hinausschicken würde.&lt;/p&gt;

&lt;h3 id=&quot;andere-apis&quot;&gt;Andere APIs&lt;/h3&gt;

&lt;p&gt;Eine hervorragende Alternative zu alle dem ist übrigens 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_Management_Instrumentation&quot;&gt;WMI&lt;/a&gt;, denn
dort kann man sich die vielen APIs schenken und WMI-Queries absetzen und die 
Ergebnisse einsammeln.&lt;br /&gt;
Ein paar interessante Queries sind:&lt;/p&gt;

&lt;div class=&quot;language-sql highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;SELECT&lt;/span&gt; __Path, Name, GUID, PNPDeviceID &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;FROM&lt;/span&gt; Win32_NetworkAdapter &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;WHERE&lt;/span&gt; NetConnectionID &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;IS&lt;/span&gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;NOT&lt;/span&gt; &lt;span style=&quot;color:#069&quot;&gt;NULL&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;SELECT&lt;/span&gt; __Path &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;FROM&lt;/span&gt; Win32_NetworkAdapter &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;WHERE&lt;/span&gt; GUID=&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;{nif-guid}&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;SELECT&lt;/span&gt; __Path, SettingID &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;FROM&lt;/span&gt; Win32_NetworkAdapterConfiguration &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;WHERE&lt;/span&gt; SettingID=&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;{set-guid}&amp;quot;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#D20&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Die WMI Objekte unterstützen Methoden wie &lt;code&gt;Disable&lt;/code&gt;, &lt;code&gt;EnableStatic&lt;/code&gt; 
&lt;code&gt;EnableDHCP&lt;/code&gt; oder &lt;code&gt;SetGateways&lt;/code&gt; und somit kann man auch gleich die
Netzwerkeinstellungen nach Belieben abändern.&lt;/p&gt;

&lt;p&gt;Die &lt;a href=&quot;https://de.wikipedia.org/wiki/Component_Object_Model&quot;&gt;COM&lt;/a&gt;
API der Internet-Connection-Sharing Umgebung stellt auch ein paar Methoden
bereit, um Netzwerkeinstellungen auszulesen. Ich habe allerdings stets nur 
das Interface &lt;a href=&quot;https://learn.microsoft.com/en-us/windows/win32/api/netcon/nn-netcon-inetconnection&quot;&gt;INetConnection&lt;/a&gt; 
zum Ein- und Ausschalten eines Netzwerkadapters benutzt.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Im GATE Projekt nutze ich alle nativen Win32 APIs, aber optional. 
Auf einem modernen Host bekomme ich so also IPv6 Details und Infos, welche
Adapter zu streichen sind.&lt;br /&gt;
Und dann wird bis zur alten NT4-API alles aufgerufen, was da ist, um den
Datensatz anzureichern, der dann am Ende ausgegeben wird.&lt;/p&gt;

&lt;p&gt;Ja, die Windows Netzwerk APIs sind kompliziert … aber sie bilden eben
30 Jahre Softwaregeschichte ab … und Geschichte ist immer auch ein 
bisschen kompliziert.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>XMake, das LUA-CMake</title>
   <link href="https://www.opengate.at/blog/2023/01/xmake/"/>
   <published>2023-01-22T12:00:00+01:00</published>
   <updated>2023-01-22T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2023/01/xmake</id>
   <category term="devel" /><category term="software" />
   <summary type="text">Die CMake Syntax mag zwar zweckdienlich
sein, aber schön ist sie nicht. Es ist keine richtige Programmiersprache, 
auch wenn es versucht, wie eine auszusehen.

Doch nun kommt XMake … ein CMake Ersatz auf Basis 
der Scriptsprache Lua.
</summary>
   <content type="html">&lt;p&gt;Die &lt;a href=&quot;https://de.wikipedia.org/wiki/CMake&quot;&gt;CMake&lt;/a&gt; Syntax mag zwar zweckdienlich
sein, aber schön ist sie nicht. Es ist keine richtige Programmiersprache, 
auch wenn es versucht, wie eine auszusehen.&lt;/p&gt;

&lt;p&gt;Doch nun kommt &lt;a href=&quot;http://xmake.io/&quot;&gt;XMake&lt;/a&gt; … ein &lt;code&gt;CMake&lt;/code&gt; Ersatz auf Basis 
der Scriptsprache &lt;a href=&quot;https://de.wikipedia.org/wiki/Lua&quot;&gt;Lua&lt;/a&gt;.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;problem-scriptsprachen&quot;&gt;Problem: Scriptsprachen&lt;/h3&gt;

&lt;p&gt;Scriptsprachen zur Build-Prozess-Steuerung sind so eine Sache.&lt;br /&gt;
&lt;a href=&quot;https://de.wikipedia.org/wiki/Conan_(Software)&quot;&gt;Conan&lt;/a&gt; setzt auf einem
komplizierten Python-Modul auf und braucht je nach Projekt Zusatzbibliotheken
um ausgeführt werden zu können.&lt;br /&gt;
Das stört sich dann oft auf älteren Systemen mit Python-2 Scripts des OS.&lt;/p&gt;

&lt;p&gt;Unix-Shell-Scripts sind wiederum nicht portabel, angefangen bei 
&lt;code&gt;/bin/sh&lt;/code&gt; vs. &lt;code&gt;/bin/bash&lt;/code&gt; bis zu den BSD-Shells, und Windows-Batch-Dateien 
und die verkrüppelte &lt;a href=&quot;https://de.wikipedia.org/wiki/PowerShell&quot;&gt;Powershell&lt;/a&gt;
stellen auch eine andere Gattung dar.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Verdammt! Ich will EINE einfache, portable und systemunabhängige 
Script-Sprache haben!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Diese Sprache heißt &lt;code&gt;Lua&lt;/code&gt; … aber das nur nebenbei.&lt;/p&gt;

&lt;h3 id=&quot;xmake-einführung&quot;&gt;XMake Einführung&lt;/h3&gt;

&lt;p&gt;Ich bin eher zufällig über &lt;code&gt;XMake&lt;/code&gt; gestoßen, und erfuhr, dass sich jemand die
Mühe gemacht hat, Lua für Buildscripts einzusetzen.&lt;/p&gt;

&lt;p&gt;Meine Assoziation war: &lt;strong&gt;Also ein CMake mit Lua-Syntax&lt;/strong&gt;.&lt;br /&gt;
Das ist nicht ganz richtig, aber auch nicht ganz falsch.&lt;/p&gt;

&lt;p&gt;Wer in XMake sein Buildsystem aufsetzen will, platziert in jedem 
Projektverzeichnis eine Datei namens &lt;code&gt;xmake.lua&lt;/code&gt; (ganz genau so wie
&lt;code&gt;CMakeLists.txt&lt;/code&gt; für &lt;code&gt;CMake&lt;/code&gt;) und ruft darin &lt;code&gt;XMake&lt;/code&gt; Funktionen auf, die die
Statemachine des XMake-Prozesses konfigurieren.&lt;/p&gt;

&lt;div class=&quot;language-lua highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;target(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;my_lib&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;  set_kind(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  add_files(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;my_lib.c&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;target_end()
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;target(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;my_prog&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  set_kind(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;binary&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;  add_files(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;my_prog.c&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;  add_deps(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;my_lib&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  add_links(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;my_lib&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;target_end()
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Es hat sich eingebürgert, dass über Einrückungen zusammengehörende Blöcke 
optisch sichtbar gemacht werden (wie im Beispiel zwischen &lt;code&gt;target()&lt;/code&gt; und 
&lt;code&gt;target_end()&lt;/code&gt;). Notwendig wäre das aber nicht.&lt;/p&gt;

&lt;p&gt;Ruft man nun in dem Projektverzeichnis &lt;code&gt;xmake&lt;/code&gt; auf, wird eine statische
Bibliothek &lt;code&gt;my_lib&lt;/code&gt; erstellt und danach das Programm &lt;code&gt;my_prog&lt;/code&gt;, welches
gegen &lt;code&gt;my_lib&lt;/code&gt; linkt.&lt;/p&gt;

&lt;p&gt;Jetzt braucht man eigentlich nur noch wissen, dass &lt;code&gt;add_files()&lt;/code&gt; auch 
Wildcards anbietet und dass man aus einer &lt;code&gt;xmake.lua&lt;/code&gt; Unterverzeichnisse
mit anderen &lt;code&gt;xmake.lua&lt;/code&gt; Dateien einbinden kann.&lt;/p&gt;

&lt;div class=&quot;language-lua highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#777&quot;&gt;--root/xmake.lua&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;includes(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;src/lib/lib1&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;includes(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;src/lib/lib2&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;includes(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;src/bin/my_project&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div class=&quot;language-lua highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#777&quot;&gt;--root/src/bin/my_project&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;target(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;my_project&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  set_kind(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;binary&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  add_files(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;*.c&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  add_files(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;*.cpp&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;So kann man nämlich schon viele übliche Projekte mit &lt;code&gt;XMake&lt;/code&gt; bauen lassen.&lt;/p&gt;

&lt;h3 id=&quot;plattformen-und-toolsets&quot;&gt;Plattformen und Toolsets&lt;/h3&gt;

&lt;p&gt;Interessant wird es dann, wann man bei Plattformen ankommt und wenn es um
Cross-Compiling geht.&lt;/p&gt;

&lt;p&gt;Hierfür stehen dem &lt;code&gt;xmake&lt;/code&gt; Tool Parameter zur Verfügung, um z.B. Plattform
und Architektur zu setzen, die man in &lt;code&gt;xmake.lua&lt;/code&gt; Scripts wieder interpretieren
kann:&lt;/p&gt;

&lt;div class=&quot;language-lua highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;target(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;my_target&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;  set_kind(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  add_files(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;generic/*.c&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt; is_plat(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;windows&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;) &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;then&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;    add_files(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;windows/*.c&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt; is_arch(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;x64&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;) &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;then&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;      add_files(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;windows/x64/*.c&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;else&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;      add_files(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;windows/x86/*.c&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;elseif&lt;/span&gt; is_plat(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;linux&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;) &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;then&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;    add_files(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;linux/*.c&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;target_end()
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;An der Konsole kann dann per&lt;br /&gt;
&lt;code&gt;xmake config -plat=windows -arch=x64&lt;/code&gt;
konfiguriert werden, welche Einstellung der folgende Aufruf von&lt;br /&gt;
&lt;code&gt;xmake&lt;/code&gt; am Ende bauen soll.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;XMake&lt;/code&gt; ist eine neue spannende Welt für mich und ich fange gerade erst an,
an der Oberfläche zu kratzen.
Es gibt noch viele offene Fragen, wie man “Options”, also Schalter für
spezielle Einstellungen gut integrieren kann.&lt;br /&gt;
Ein anderer Punkt sind Paketabhängigkeiten, denn &lt;code&gt;XMake&lt;/code&gt; kann neben eigenen
Repos auch Conan Remotes abrufen und Bibliotheken herunterladen und in den
Build Prozess integrieren.&lt;/p&gt;

&lt;p&gt;Im GATE Projekt konnte ich bereits einige Standard-Builds mit &lt;code&gt;XMake&lt;/code&gt;
durchführen und das Ergebnis gefällt mir, weil z.B. für Windows kein 
&lt;code&gt;msbuild&lt;/code&gt; eingesetzt wird, sondern direkt der Compiler und Linker
aufgerufen werden.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;XMake&lt;/code&gt; führt die Builds auch wesentlich schneller aus als &lt;code&gt;CMake&lt;/code&gt;, was sich
in langsamen Docker-Containern positiv auswirkt.&lt;/p&gt;

&lt;p&gt;Ich glaube aber nicht, dass &lt;code&gt;XMake&lt;/code&gt; bei mir &lt;code&gt;CMake&lt;/code&gt; auf die Schnelle 
ersetzen wird. Denn wenn es um den Support älterer Hardware oder Compiler 
geht (z.B.: Watcom), ist &lt;code&gt;CMake&lt;/code&gt; dem noch jungen &lt;code&gt;XMake&lt;/code&gt; eben 15 Jahre voraus.&lt;/p&gt;

&lt;p&gt;Trotzdem liegt in diesem schlanken Projekt natürlich ein großes Potential
besonders für neue Projekte.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>BSD doas und Linux sudo</title>
   <link href="https://www.opengate.at/blog/2023/01/doas-sudo/"/>
   <published>2023-01-21T12:00:00+01:00</published>
   <updated>2023-01-21T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2023/01/doas-sudo</id>
   <category term="software" />
   <summary type="text">Sich als root in einem Unix System 
einzuloggen gehört bzw. ist verboten.
In SSH gilt das ganz besonders.

Und nachdem das klassische su auch gefährlich bzw. nachteilig ist,
wurde sudo für BSD 
erfunden, mit dem Linux
ebenso glücklich wurde.

Doch den BSDlern wurde sudo auch wieder zu unsicher, weshalb sie mit
doas das ganze nochmal neu implementierten.
</summary>
   <content type="html">&lt;p&gt;Sich als &lt;code&gt;root&lt;/code&gt; in einem &lt;a href=&quot;https://de.wikipedia.org/wiki/Unix&quot;&gt;Unix&lt;/a&gt; System 
einzuloggen gehört bzw. ist verboten.
In &lt;a href=&quot;https://de.wikipedia.org/wiki/Secure_Shell&quot;&gt;SSH&lt;/a&gt; gilt das ganz besonders.&lt;/p&gt;

&lt;p&gt;Und nachdem das klassische &lt;code&gt;su&lt;/code&gt; auch gefährlich bzw. nachteilig ist,
wurde &lt;code&gt;sudo&lt;/code&gt; für &lt;a href=&quot;https://de.wikipedia.org/wiki/Berkeley_Software_Distribution&quot;&gt;BSD&lt;/a&gt; 
erfunden, mit dem &lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt;
ebenso glücklich wurde.&lt;/p&gt;

&lt;p&gt;Doch den BSDlern wurde &lt;code&gt;sudo&lt;/code&gt; auch wieder zu unsicher, weshalb sie mit
&lt;a href=&quot;http://man.openbsd.org/doas&quot;&gt;doas&lt;/a&gt; das ganze nochmal neu implementierten.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Die Hintergründe für &lt;code&gt;doas&lt;/code&gt; vs. &lt;code&gt;sudo&lt;/code&gt; sind eine andere Geschichte, ich
weiß nur, dass &lt;code&gt;sudo&lt;/code&gt; viele Features und damit Codes umfasst, die ein
System wieder unsicher machen können, weshalb &lt;code&gt;doas&lt;/code&gt; als entschlacktes
&lt;code&gt;sudo&lt;/code&gt; neugestartet wurde.&lt;/p&gt;

&lt;p&gt;Doch nicht jede Distribution bzw. Installation bereitet dieses Hilfsmittel
vor und somit ist der erste Schritt nach einer Linux oder BSD Installation
die Einrichtung von &lt;code&gt;sudo&lt;/code&gt; oder &lt;code&gt;doas&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;sudo-unter-linux&quot;&gt;sudo unter Linux&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;sudo&lt;/code&gt; fehlt zwar selten in einer Linux-Distribution, doch um sicher zu sein,
startet man:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Debian: &lt;code&gt;apt install sudo&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Alpine: &lt;code&gt;apk add sudo&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;SUSE: &lt;code&gt;zypper install sudo&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nun folgt die Definition, welcher Account per &lt;code&gt;sudo&lt;/code&gt; root-Rechte erhalten soll.
Das wird in der Regel über die Datei &lt;code&gt;/etc/sudoers&lt;/code&gt; gesteuert.&lt;/p&gt;

&lt;p&gt;Will man den eigenen Account namens &lt;code&gt;myuser&lt;/code&gt; zu solchen Rechten verhelfen, 
reicht die zusätzlich Zeile:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;# WER    WO    ALS-WER  WIE       WAS
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;myuser   ALL = (ALL)    NOPASSWD: ALL
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;Der Benutzer &lt;code&gt;myuser&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;darf auf jedem Host (erstes &lt;code&gt;ALL&lt;/code&gt;)&lt;/li&gt;
  &lt;li&gt;als jeder Benutzer (zweites &lt;code&gt;ALL&lt;/code&gt;)&lt;/li&gt;
  &lt;li&gt;ohne Passwort (&lt;code&gt;NOPASSWD&lt;/code&gt;)&lt;/li&gt;
  &lt;li&gt;jedes Kommando ausführen (drittes &lt;code&gt;ALL&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Lässt man &lt;code&gt;NOPASSWD:&lt;/code&gt; weg, muss man beim &lt;code&gt;sudo&lt;/code&gt; Aufruf sein Passwort eintippen.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;myuser ALL = (ALL) ALL
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Die bessere und vorgeschlagene Variante ist aber eine andere:&lt;br /&gt;
Man erteilt einer Gruppe das Recht, mit &lt;code&gt;sudo&lt;/code&gt; alles ausführen zu dürfen und 
fügt den Benutzer dieser Gruppe hinzu.&lt;br /&gt;
Je nach Distribution heißt diese Gruppe entweder direkt &lt;code&gt;sudo&lt;/code&gt; oder
&lt;code&gt;wheel&lt;/code&gt; (früher auch noch &lt;code&gt;admin&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;/etc/sudoers&lt;/code&gt; steht eine von folgenden Beispielzeilen:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;%sudo ALL = (ALL) NOPASSWD: ALL
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;%wheel ALL = (ALL) NOPASSWD: ALL
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Denn mit vorgestelltem &lt;code&gt;%&lt;/code&gt; lassen sich alle Mitglieder einer Gruppe ansprechen.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Und wie fügt man seinen &lt;code&gt;myuser&lt;/code&gt; Account zur &lt;code&gt;sudo&lt;/code&gt; Gruppe hinzu?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class=&quot;language-shell highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;usermod --append --groups sudo myuser
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;bzw. in Kurzform:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;usermod -a -G sudo myuser
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h4 id=&quot;anwendung&quot;&gt;Anwendung&lt;/h4&gt;

&lt;p&gt;Ein &lt;code&gt;cat /etc/sudoers&lt;/code&gt; sollte bei nicht-&lt;code&gt;root&lt;/code&gt; Benutzern einen Zugriffsfehler
auslösen.&lt;br /&gt;
Aber &lt;code&gt;sudo cat /etc/sudoers&lt;/code&gt; wird den Dateiinhalt ausgeben.&lt;/p&gt;

&lt;p&gt;Interessant ist noch &lt;code&gt;sudo -E my_root_comamnd params&lt;/code&gt;, wo die Environment 
Variablen des nicht-privilegierten Accounts an den privilegierten Prozess
übergeben werden. Fehlt &lt;code&gt;-E&lt;/code&gt;, so startet der Prozess mit Standard 
env-Variablen von &lt;code&gt;root&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;doas-in-bsd&quot;&gt;doas in BSD&lt;/h3&gt;

&lt;p&gt;Ein fehlendes &lt;code&gt;doas&lt;/code&gt; wird einfach per&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;FreeBSD: &lt;code&gt;pkg install doas&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;NetBSD und OpenBSD: &lt;code&gt;pkg_add doas&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;nachinstalliert.&lt;/p&gt;

&lt;p&gt;Die primäre Konfigurationsdatei heißt 
&lt;code&gt;/usr/local/etc/doas.conf&lt;/code&gt; in FreeBSD bzw.
&lt;code&gt;/etc/doas.conf&lt;/code&gt; in Net- und OpenBSD.&lt;/p&gt;

&lt;p&gt;Um hier den Account &lt;code&gt;myuser&lt;/code&gt; zu berechtigen, sollte eine Zeile auf&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;permit keepenv nopass myuser
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;lauten. Lässt man &lt;code&gt;nopass&lt;/code&gt; weg, muss das Passwort eingetippt werden.
&lt;code&gt;keepenv&lt;/code&gt; überträgt die Umgebungsvariablen des eigenen Benutzers auf den
Prozess, der als &lt;code&gt;root&lt;/code&gt; laufen soll, ohne &lt;code&gt;keepenv&lt;/code&gt; startet den Prozess mit
Standard env-Variablen.&lt;/p&gt;

&lt;p&gt;Natürlich kann man auch hier gleich alle Mitglieder einer Gruppe
(wie &lt;code&gt;wheel&lt;/code&gt;) berechtigen mit:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;permit keepenv nopass :wheel
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Hier kündigt der &lt;code&gt;:&lt;/code&gt; eine Gruppe an.&lt;/p&gt;

&lt;p&gt;Um den Benutzer &lt;code&gt;myuser&lt;/code&gt; in die Gruppe &lt;code&gt;wheel&lt;/code&gt; aufzunehmen, ist das Kommando&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;pw group mod wheel -m myuser
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;erforderlich.&lt;/p&gt;

&lt;h4 id=&quot;anwendung-1&quot;&gt;Anwendung&lt;/h4&gt;

&lt;p&gt;Ein &lt;code&gt;cat /etc/master.passwd&lt;/code&gt; sollte allen nicht-&lt;code&gt;root&lt;/code&gt; Usern verboten sein, 
doch mit&lt;br /&gt;
&lt;code&gt;doas cat /etc/master.passwd&lt;/code&gt; werden die Geheimnisse offenbart.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Natürlich kann man in beiden Tools noch viele wunderbare Regeln definieren,
und z.B.: nur bestimmte Programme zulassen.
Doch auf meinen eigenen Systemen (und auch in manchen Embedded Produkten),
reicht es aus, einem speziellen Admin-User per &lt;code&gt;sudo&lt;/code&gt;/&lt;code&gt;doas&lt;/code&gt; quasi alles
zu erlauben.&lt;br /&gt;
Denn genau das ist es, was Administratoren am Ende brauchen.&lt;/p&gt;

&lt;p&gt;Andere Dienste sollten gar nicht in die Verlegenheit kommen, dass sie mehr
Rechte für bestimmte Prozesse brauchen.&lt;br /&gt;
Doch falls das wirklich notwendig ist, bieten beide Tools die Möglichkeit,
viel feingradigere Abstufungen vorzunehmen.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;sudo&lt;/code&gt; und &lt;code&gt;doas&lt;/code&gt; sind nun seit über 15 Jahren meine stetigen Begleiter,
und ich vermute, dass das auch so bleiben wird.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>PIPO W12 Upgrade auf Windows 11</title>
   <link href="https://www.opengate.at/blog/2023/01/pipo-update/"/>
   <published>2023-01-15T12:00:00+01:00</published>
   <updated>2023-01-15T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2023/01/pipo-update</id>
   <category term="hardware" /><category term="software" />
   <summary type="text">Schon seit Monaten steht ein Update im Raum, doch bisher wurde es immer wieder
verzögert. Mein ARM64 Tablet 
PIPO W12 lief bisher brav mit 
Windows 10, doch
seit Visual Studio 2022 
für ARM64 ist Windows 11 
attraktiv geworden.

Seit dem Jahreswechsel schlägt Microsoft selbst das Upgrade vor.
</summary>
   <content type="html">&lt;p&gt;Schon seit Monaten steht ein Update im Raum, doch bisher wurde es immer wieder
verzögert. Mein &lt;a href=&quot;https://de.wikipedia.org/wiki/Arm-Architektur&quot;&gt;ARM64&lt;/a&gt; Tablet 
&lt;a href=&quot;/blog/2021/01/pipo-tablet/&quot;&gt;PIPO W12&lt;/a&gt; lief bisher brav mit 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_10&quot;&gt;Windows 10&lt;/a&gt;, doch
seit &lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_Studio#Version_2022&quot;&gt;Visual Studio 2022&lt;/a&gt; 
für ARM64 ist &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_11&quot;&gt;Windows 11&lt;/a&gt; 
attraktiv geworden.&lt;/p&gt;

&lt;p&gt;Seit dem Jahreswechsel schlägt Microsoft selbst das Upgrade vor.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Windows Upgrades auf ARM64 sind etwas Neues, denn da Windows 10 das erste ARM64
OS von Microsoft war, gab es bisher kein “neueres” OS.&lt;br /&gt;
Doch genau wie auf &lt;a href=&quot;https://de.wikipedia.org/wiki/X64&quot;&gt;X64&lt;/a&gt;, 
war die Strategie eine sehr sehr seltsame.&lt;/p&gt;

&lt;p&gt;Auch meine anderen PCs machten diese seltsame Phase durch, dass kurz nach dem
Erscheinen von Windows 11 der Upgrade Assistent sofort parat war und die
Installation anbot.&lt;br /&gt;
Damals verweigerte ich und verblieb bei einer einzigen Win11-Test-Installation 
in einer virtuellen Maschine.&lt;/p&gt;

&lt;p&gt;Wochen später änderte sich dann der Assistent und meinte, dass meine Hardware
nicht zum Upgrade auf Windows 11 bereit war. (Es handelte sich um einen Core i3,
der eigentlich als Minimum reichen sollte).&lt;br /&gt;
Beim PIPO Tablet war das ähnlich, es wurde kurz “generisch” angeboten, dann
mit einem Inkompatibilitätsverweis verweigert und seit kurzem erstrahlt wieder
der grüne Haken, der das Gerät als Windows 11-kompatibel einschätzt.&lt;/p&gt;

&lt;p&gt;Natürlich hätte ich (parallel zu meinen &lt;a href=&quot;/blog/2022/06/apcsilmic/&quot;&gt;dot-1-mini-PC&lt;/a&gt; 
Installationen) einfach selbst eine neue Windows 11 Installation einleiten 
können, doch einen gravierenden Unterschied gibt es:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ich besitze nur Windows 11 IoT für ARM64 in meiner MSDN Subscription, 
das Tablet kam jedoch mit einem Windows 10 Pro.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ich kann also nicht die üblichen Windows 11 Home oder Pro ISO Images für
ARM64 beziehen, sondern nur die etwas anders aufgebauten IoT Varianten.&lt;/p&gt;

&lt;p&gt;Mit dem nun vorgeschlagenem Upgrade hoffte ich also die mir sonst nicht
zugängliche Windows 11 Home ARM64 Version zu bekommen.&lt;/p&gt;

&lt;h3 id=&quot;update-installation&quot;&gt;Update Installation&lt;/h3&gt;

&lt;p&gt;Der Download und die erste Installationsphase verliefen recht zäh und dauerte
über eine Stunde.&lt;/p&gt;

&lt;p&gt;Doch danach lief die Windows 11-Upgradeinstallation ganze regulär an.
Erst lief die Hintergrundinstallation in der aktuellen Sitzung und dann wurde
zum Neustart aufgefordert.&lt;/p&gt;

&lt;p&gt;Während des Neustarts wurde das System ausgetauscht und nach einigem Warten
erschien dann die übliche Windows 11 Login-Maske.&lt;br /&gt;
Auch hier dauerte der erste Login wieder recht lange, doch am Ende war die
Installation erfolgreich abgeschlossen wurden.&lt;/p&gt;

&lt;p&gt;Auf den ersten Blick war das Upgrade ein voller Erfolg. Ich deinstallierte das
alte übernommene Visual Studio X64 und ersetzte es doch Studio 2022 ARM64 und
an der Stelle hätte alles in perfektem Zustand enden können.&lt;/p&gt;

&lt;h4 id=&quot;kein-touchscreen&quot;&gt;Kein Touchscreen&lt;/h4&gt;

&lt;p&gt;Allerdings hatte ich die Neuinstallation ausschließlich über die Tastatur und
Maus bedient, die einwandfrei funktionierten.
Als ich jedoch das Tablet hochhob und über den Touchscreen bedienen wollte,
erfolgte keine Reaktion.&lt;br /&gt;
Offenbar war der Touchscreen Treiber nicht korrekt übernommen worden.&lt;/p&gt;

&lt;p&gt;Und leider konnte ich auch nach mehreren Herumspielereien dieses Feature nicht
mehr zum Laufen bekommen.&lt;br /&gt;
Das war ein No-Go, denn ein Tablet-PC “muss” auch ohne Peripherie “von Hand”
genutzt werden können.&lt;/p&gt;

&lt;p&gt;Am Ende traf ich dann doch die Entscheidung, Windows 11 vollständig neu zu 
installieren, und zwar meine verfügbare “Windows 11 IOT Enterprise” Variante.&lt;/p&gt;

&lt;h3 id=&quot;neuinstallation-mit-iot-11&quot;&gt;Neuinstallation mit IOT 11&lt;/h3&gt;

&lt;p&gt;Ein “normales” Windows 11 ARM64 Image startet am PIPO Tablet nicht vollständig,
da Treiber fehlen. Diese müssen also vorher in das Windows-Setup-Image 
integriert werden.&lt;/p&gt;

&lt;h4 id=&quot;pipo-w12-driver-installation&quot;&gt;PIPO W12 Driver Installation&lt;/h4&gt;

&lt;p&gt;Ich hatte natürlich per &lt;code&gt;dism /Export-Driver&lt;/code&gt; schon vor dem Upgrade alle 
Treiber exportiert und gesichert.&lt;br /&gt;
Nun nutzte ich die &lt;a href=&quot;/blog/2022/10/apcsilmic-drivers/&quot;&gt;Treiber-Integrations-Prozedur&lt;/a&gt;, 
die ich schon am &lt;code&gt;dot-1-mini-PC&lt;/code&gt; erprobt hatte und integrierte die Treiber 
in &lt;code&gt;boot.wim&lt;/code&gt; und &lt;code&gt;install.wim&lt;/code&gt; des originalen Windows 11 IOT Images.&lt;/p&gt;

&lt;p&gt;Am Ende kam alles auf einen FAT32 USB Stick, den das 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Unified_Extensible_Firmware_Interface&quot;&gt;UEFI&lt;/a&gt; 
des &lt;code&gt;PIPO-W12&lt;/code&gt; problemlos erkannte und die Installationsroutine startete.&lt;/p&gt;

&lt;p&gt;Ich löschte alle bestehenden Partitionen und ließ das gesamte Betriebssystem
neu installieren.&lt;br /&gt;
Auch diese Prozedur dauerte wieder recht lange beim ersten Boot mit der
Treiber Einrichtung, doch am Ende landete ich in einem jungfräulichem
Windows 11 Login-Screen … aber diesmal mit funktionierendem Touchscreen.&lt;/p&gt;

&lt;p&gt;Der Rest verlief wie üblich bei mir:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Account einrichten&lt;/li&gt;
  &lt;li&gt;Windows aktivieren&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Windows-Subsystem_f%C3%BCr_Linux&quot;&gt;WSL&lt;/a&gt; und 
Debian installieren&lt;/li&gt;
  &lt;li&gt;Visual Studio 2022 installieren&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Fertig war das aufgefrischte ARM64-Entwickler-Tablet.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Also … ein Upgrade von Windows 10 auf 11 ist auf etwas exotischerer ARM64
Hardware doch ein gewisses Risiko. Es wurden alle außer einem Treiber korrekt
neu integriert … doch auf eben genau den einen fehlenden kam es bei mir an.&lt;/p&gt;

&lt;p&gt;Ich weiß zwar nicht, warum sich dieser nicht im Nachhinein zur Kooperation 
überreden ließ, doch am Ende bestätigt sich eine alte Regel, die ich schon
in der Jugend aufgestellt hatte:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Eine komplette Neuinstallation ist besser als ein Upgrade.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Denn man schleppt immer irgend welche alten Installationsreste mit, die im 
Zweifelsfall eher stören.&lt;/p&gt;

&lt;p&gt;Und nachdem Nutzdaten bei mir sowieso entweder am One-Drive oder im GIT-Repo
liegen, und alle Apps online verfügbar sind, ist eine Neuinstallation oft
schneller fertig, als ein Upgrade, wo man dann stundenlang die Probleme
beheben muss.&lt;/p&gt;

&lt;p&gt;Am Ende war die Aktion also erfolgreich … obwohl nicht so wie erwartet.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>CONAN NO_OUTPUT_DIRS</title>
   <link href="https://www.opengate.at/blog/2023/01/conan-dirs/"/>
   <published>2023-01-14T12:00:00+01:00</published>
   <updated>2023-01-14T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2023/01/conan-dirs</id>
   <category term="devel" /><category term="software" />
   <summary type="text">Beim ersten conan build Aufruf landen alle finalen Dateien im richtigen 
Verzeichnis. Man debugged ein bisschen und ruft cmake zur Aktualisierung
auf … doch die Binärdateien werden nicht aktualisiert.

Anstatt dessen findet man die Dateien in anderen Verzeichnissen.
Willkommen in der Conan 
(v1) Hilfegruppe.
</summary>
   <content type="html">&lt;p&gt;Beim ersten &lt;code&gt;conan build&lt;/code&gt; Aufruf landen alle finalen Dateien im richtigen 
Verzeichnis. Man debugged ein bisschen und ruft &lt;code&gt;cmake&lt;/code&gt; zur Aktualisierung
auf … doch die Binärdateien werden nicht aktualisiert.&lt;/p&gt;

&lt;p&gt;Anstatt dessen findet man die Dateien in anderen Verzeichnissen.
Willkommen in der &lt;a href=&quot;https://de.wikipedia.org/wiki/Conan_(Software)&quot;&gt;Conan&lt;/a&gt; 
(v1) Hilfegruppe.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Wenn &lt;code&gt;Conan&lt;/code&gt; den &lt;a href=&quot;https://de.wikipedia.org/wiki/CMake&quot;&gt;CMake&lt;/a&gt; Generator benutzt, 
stellt dieser diverse Pfade für den Buildoutput ein. Denn Conan “wünscht” 
sich, dass Ausgabepfade wie &lt;code&gt;bin&lt;/code&gt; für Binaries und &lt;code&gt;lib&lt;/code&gt; für Bibliotheken 
benutzt werden.&lt;br /&gt;
Doch auch &lt;code&gt;CMake&lt;/code&gt; interne Scripts können diese Pfade anpassen. 
Und so kommt es gerne mal zu Konflikten, die nicht immer gleich sichtbar 
werden.&lt;/p&gt;

&lt;p&gt;Ich hatte in der Firma genau das Problem, dass der erste &lt;code&gt;conan install&lt;/code&gt; 
und &lt;code&gt;conan build&lt;/code&gt; Aufruf genau zu den Ergebnissen geführt hatte, die auch
zu erwarten waren.&lt;/p&gt;

&lt;p&gt;Wenn man nun aber während der aktiven Weiterentwicklung &lt;code&gt;cmake&lt;/code&gt; oder &lt;code&gt;make&lt;/code&gt;
erneut aufrief, um Änderungen nachzukompilieren, landeten sie in den von
CONAN definierten Verzeichnissen und nicht dort, wo die CMake Scripts sie
hätten ablegen sollen.&lt;/p&gt;

&lt;h3 id=&quot;lösung-no_output_dirs&quot;&gt;Lösung: NO_OUTPUT_DIRS&lt;/h3&gt;

&lt;p&gt;In von &lt;code&gt;Conan&lt;/code&gt; v1 addressierteb  &lt;code&gt;CMakeLists.txt&lt;/code&gt; Dateien befindet sich in der 
Regel der Aufruf:&lt;br /&gt;
&lt;code&gt;conan_basic_setup()&lt;/code&gt;.&lt;br /&gt;
Diese Makro holt alle notwendigen Variablen für den Buildprozess in das 
CMake-Projekt und ist unter anderem auch für die “ungewollte” Änderung der 
Pfade verantwortlich.&lt;br /&gt;
Doch die &lt;code&gt;Conan&lt;/code&gt; Macher haben dem Makro einige Parameter übergeben, 
darunter auch:&lt;br /&gt;
&lt;code&gt;conan_basic_setup(NO_OUTPUT_DIRS)&lt;/code&gt;.
Damit wird das manchmal störende Verhalten von Conan abgeschaltet und die
Kontrolle alleine an &lt;code&gt;CMake&lt;/code&gt; übergeben.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Es gibt noch ein paar andere Optionen für das Basic-Setup, doch
&lt;code&gt;NO_OUTPUT_DIRS&lt;/code&gt; zeigt, dass die &lt;code&gt;Conan&lt;/code&gt; Macher viele Varianten von 
Builds schon durchgedacht haben.&lt;br /&gt;
Im Standard schreibt &lt;code&gt;Conan&lt;/code&gt; alles so um, dass es am Ende möglichst einfach
wieder Paket erzeugen kann. Doch da viele &lt;code&gt;CMake&lt;/code&gt; Scripts hier manuell 
eingreifen, kann dieses Feature optional ausgeschaltet werden.&lt;/p&gt;

&lt;p&gt;Ein einfältiger Kollege meinte auch gleich, es müsse das gesamte 
&lt;code&gt;Conan&lt;/code&gt; Build-System auf den Kopf stellen um Kontrolle über Pfade zu erhalten.&lt;br /&gt;
Naja, ein Blick in die Doku und 14 Zeichen lösen das Problem natürlich 
auch und beschreiten den vorgesehenen Pfad.&lt;/p&gt;

&lt;p&gt;Zugegeben, &lt;code&gt;Conan&lt;/code&gt; ist auf Grund seiner vielen Möglichkeiten ein komplexer 
Moloch geworden … doch je länger ich damit arbeite, um so mehr lerne ich,
wie flexibel die Software gestaltet ist.&lt;/p&gt;

&lt;p&gt;Und ab &lt;code&gt;Conan&lt;/code&gt; v2 wird ohnehin die Verantwortung für den Build viel 
weitreichender an die Generator-Toolsets abgegeben.&lt;br /&gt;
Aber das ist eine andere Geschichte.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Ich schau dir in die Augen, ...</title>
   <link href="https://www.opengate.at/blog/2023/01/spyglasses/"/>
   <published>2023-01-08T12:00:00+01:00</published>
   <updated>2023-01-08T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2023/01/spyglasses</id>
   <category term="devel" />
   <summary type="text">Das tolle an den Spielzeugen von James Bond
war damals (vor Jahrzehnten),dass es Alltagsgegenstände wie Kugelschreiber 
waren, die hoch technisch ausgestattet waren.

Es war Science-Fiction, weil 
man so etwas nicht oder nur sehr schwer bauen konnte.
Doch heute passen Chips auf wenige Quadratmillimeter und stellen an ganz
neuen Orten ihre Dienste bereit.
</summary>
   <content type="html">&lt;p&gt;Das tolle an den Spielzeugen von &lt;a href=&quot;https://de.wikipedia.org/wiki/James_Bond&quot;&gt;James Bond&lt;/a&gt;
war damals (vor Jahrzehnten),dass es Alltagsgegenstände wie Kugelschreiber 
waren, die hoch technisch ausgestattet waren.&lt;/p&gt;

&lt;p&gt;Es war &lt;a href=&quot;https://de.wikipedia.org/wiki/Science-Fiction&quot;&gt;Science-Fiction&lt;/a&gt;, weil 
man so etwas nicht oder nur sehr schwer bauen konnte.&lt;br /&gt;
Doch heute passen Chips auf wenige Quadratmillimeter und stellen an ganz
neuen Orten ihre Dienste bereit.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Ich bleibe bei meiner Aussage:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ich brauche keine Brille, ich brauchte nur ein größeres Display.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Und zum Glück leisten mir meine schwer geprüften Augen immer noch gute
Dienste … doch das wird vielleicht nicht immer so sein.&lt;/p&gt;

&lt;p&gt;Um so lustiger finde ich es, wenn ich mir eine Fake-Brille aufsetze und 
mitverfolge, wie ich von Arbeitskollegen nicht mehr erkannt werde.
(&lt;a href=&quot;https://de.wikipedia.org/wiki/Superman&quot;&gt;Clark Kent&lt;/a&gt; lässt grüßen).&lt;/p&gt;

&lt;p&gt;Und es ist auch interessant einmal zu erleben, wie sich ein Brillenträger
so fühlt. Denn selbst die mir nun gut vertraute 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Atemschutzmaske#Partikelfiltrierende_Halbmaske_(FFP-Maske)&quot;&gt;FFP2-Maske&lt;/a&gt;, 
die mir keine Probleme macht, erweist sich als lästig, wenn man im Bus auf das 
Brillenglas “hinauf atmet”, womit die Brille sofort beschlägt.&lt;/p&gt;

&lt;p&gt;Und dann haben diese unter-20-Euro-Gläser noch eine Zusatzfunktion.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/spy-glasses-1.jpg&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;x-megapixel-kamera-und-mikrofon&quot;&gt;X Megapixel Kamera und Mikrofon&lt;/h3&gt;

&lt;p&gt;Unglaublich aber wahr, doch in dem etwas dickeren Bügel ist ein 
Kamerachip samt &lt;a href=&quot;https://de.wikipedia.org/wiki/MicroSD&quot;&gt;Micro-SD&lt;/a&gt; Kartenmodul 
verbaut. Ich kann also im 007-Stil durch die Straßen schlendern und dabei 
die Umgebung mitfilmen.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/spy-glasses-3.jpg&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Ein Mikrofon kann parallel zum Videostream auch noch Laute aus der Umgebung
aufzeichnen. Die Qualität ist natürlich nicht “berauschend”, aber ausreichend
um Gespräche mitaufzeichnen zu können.&lt;/p&gt;

&lt;p&gt;Gesteuert wird die kleine Kamera über einen Knopf an der Innenseite des
Bügels.&lt;br /&gt;
&lt;img src=&quot;/blog/assets/img/spy-glasses-4.jpg&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;steuerung&quot;&gt;Steuerung&lt;/h3&gt;

&lt;p&gt;Mit einem längeren Druck auf die Taste (3+ Sekunden) wird das Modul 
eingeschaltet und eine rote LED erscheint sichtbar im Blickfeld der
Brille, um den Stand-By Modus anzudeuten.&lt;/p&gt;

&lt;p&gt;Mit einem kurzen Druck auf die Taste können nun Fotos gemacht werden,
die auf die eingelegte SD-Karte gespeichert werden.&lt;/p&gt;

&lt;p&gt;Hält man die Taste knapp 3 Sekunden gedrückt, wird der Video-Modus
aktiviert. Die LED blinkt kurz rot dann blau und erlischt dann.
Nun werden Videodateien samt Audio aufgezeichnet und auf die Karte
geschrieben.&lt;/p&gt;

&lt;p&gt;Ein kurzer Tastendruck beendet die Aufnahme und schaltet wieder in
den Stand-By Modus (rote LED leuchtet) zurück.&lt;/p&gt;

&lt;p&gt;Hält man die Taste 5 Sekunden gedrückt, wird das Kameramodul wieder
ausgeschaltet und die LED erlischt.&lt;/p&gt;

&lt;h3 id=&quot;datenspeicherung&quot;&gt;Datenspeicherung&lt;/h3&gt;

&lt;p&gt;Die Videos werden mit einer Auflösung von 1920 x 1080 Pixel bei 30 fps und 
8 KHz Audioabtastung gespeichert. Als Format dienen klassische 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Audio_Video_Interleave&quot;&gt;AVI Dateien&lt;/a&gt;,
wobei die Video-Frames als &lt;a href=&quot;https://de.wikipedia.org/wiki/Motion_JPEG&quot;&gt;MJPEG&lt;/a&gt; 
vorliegen und die Tonaufzeichnung im unkomprimierten PCM-Format kodiert ist.&lt;/p&gt;

&lt;p&gt;Die Videos werden in festen Intervallen als neue Dateien gespeichert, 
bei mir sind 5 Minuten konfiguriert.
Eine 5-Minuten-Videodatei belegt dabei zwischen 600 und 700 MB.&lt;br /&gt;
Und ich konnte mit einer vollen Akkuladung 16 Videodateien aufzeichnen, bevor
sich die Brille ausschaltete, womit 80 Minuten erreicht werden konnten.&lt;/p&gt;

&lt;p&gt;Auf der Unterseite des Bügels befindet sich auch ein USB-Anschluss, über den
der Brillenakku geladen werden kann (Rot blinkende LED während der Ladung, 
Blaue LED wenn voll). 
Außerdem wird bei einer Verbindung mit dem PC der Inhalt der SD Karte 
angezeigt und man kann Videos und Bilder auf den Computer verschieben.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Dieses interessante Spielzeug verändert gerade meine Sichtweise auf die Welt.
Denn ich lerne hiermit, wie leicht es ist, Menschen unbemerkt zu überwachen
und Daten aufzuzeichnen.&lt;/p&gt;

&lt;p&gt;Wer weiß wie oft ich nun schon “gefilmt” wurde und wie bzw. wo diese Daten 
benutzt werden.&lt;br /&gt;
Und auch ich muss mir nun die Frage stellen, wann dich die Brille 
einschalten will, darf und soll.&lt;/p&gt;

&lt;p&gt;Eine Busfahrt und eine Autofahrt habe ich schon mal aufgenommen und muss 
leider feststellen, dass Gehbewegungen die Aufnahme schwer stören.
Außerdem filmt die Brille leicht nach oben und man muss den Kopf senken
um Menschen in der Umgebung gut einfangen zu können, ansonsten sieht man 
nur ihre Köpfe oder weniger.&lt;/p&gt;

&lt;p&gt;Wenn man aber ruhig sitzt oder steht liefert die Brille verhältnismäßig 
gute Bilder und Videos. Die können zwar bei weitem mit einem
Smartphone nicht mithalten, sind aber für diese minimalistische Hardware
scharf und aussagekräftig … solange man eben nicht weitergeht.&lt;/p&gt;

&lt;p&gt;Als Fake-Brille werde ich das Teil also noch häufiger tragen.
Wie oft ich sie einschalten werde … tja, das muss ich mir noch gut
überlegen.&lt;/p&gt;

&lt;h3 id=&quot;nachtrag&quot;&gt;Nachtrag&lt;/h3&gt;

&lt;p&gt;Alles Wichtige steht natürlich auch in der Produktbeschreibung:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/spy-glasses-info-1.gif&quot; alt=&quot;Spy-glasses Info 1&quot; /&gt;
&lt;img src=&quot;/blog/assets/img/spy-glasses-info-2.gif&quot; alt=&quot;Spy-glasses Info 2&quot; /&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>RDP/DNS Versagen</title>
   <link href="https://www.opengate.at/blog/2023/01/rdp-fail/"/>
   <published>2023-01-07T12:00:00+01:00</published>
   <updated>2023-01-07T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2023/01/rdp-fail</id>
   <category term="software" />
   <summary type="text">Da versuche ich - wie so oft - meinen
Windows Server per 
RDP zu erreichen und
sehe ein:

  Your computer could not connect to another console session on the remote computer
because you already have a console session in progress.


… aber ich hatte gar keine laufende Verbindung.
</summary>
   <content type="html">&lt;p&gt;Da versuche ich - wie so oft - meinen
&lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_Server_2022&quot;&gt;Windows Server&lt;/a&gt; per 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Remote_Desktop_Protocol&quot;&gt;RDP&lt;/a&gt; zu erreichen und
sehe ein:&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;Your computer could not connect to another console session on the remote computer
because you already have a console session in progress.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;… aber ich hatte gar keine laufende Verbindung.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;lösung-bei-mir&quot;&gt;Lösung bei mir&lt;/h3&gt;

&lt;p&gt;Ein einfaches&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;ipconfig /flushdns
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;sollte nur zwischengespeicherte DNS Namen und IPs löschen … doch tatsächlich,
nach der Ausführung konnte ich mich per RDP wieder zum Server verbinden.&lt;/p&gt;

&lt;p&gt;Keine Ahnung, was da im Hintergrund passiert ist, vielleicht hatte mein lokal 
laufender &lt;a href=&quot;https://de.wikipedia.org/wiki/Hyper-V&quot;&gt;Hyper-V&lt;/a&gt; Dienst was damit zu tun
oder mein PC war zu lange online oder überlebte eine VPN Sitzung nicht.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Caches zu Löschen ist ein guter Tipp um unerklärbare Probleme zu beheben.
Man muss nur leider herausfinden, um welchen Cache es sich handelt.&lt;/p&gt;

&lt;p&gt;Dass der DNS-Cache der Grund für die obige Fehlermeldung war, hatte ich so
nicht erwartet …&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Tja, man lernt eben nie aus!&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>Mein C64 lebt wieder</title>
   <link href="https://www.opengate.at/blog/2023/01/c64-refresh/"/>
   <published>2023-01-06T12:00:00+01:00</published>
   <updated>2023-01-06T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2023/01/c64-refresh</id>
   <category term="hardware" /><category term="retro" />
   <summary type="text">Vor einiger Zeit wollte ich ihn nochmals
starten … doch es klappte nicht.
Nun habe ich ihn erneut zu mir geholt, meinen C64, 
ihn zerlegt, gereinigt und wieder zusammengesetzt.

Und wenn man dann auch noch das richtige Monitor anschließt … dann sieht
man: COMMODORE BASIC, wie es sich gehört.
</summary>
   <content type="html">&lt;p&gt;&lt;a href=&quot;/blog/2019/03/c64/&quot;&gt;Vor einiger Zeit&lt;/a&gt; wollte ich ihn nochmals
starten … doch es klappte nicht.
Nun habe ich ihn erneut zu mir geholt, meinen &lt;a href=&quot;https://de.wikipedia.org/wiki/Commodore_64&quot;&gt;C64&lt;/a&gt;, 
ihn zerlegt, gereinigt und wieder zusammengesetzt.&lt;/p&gt;

&lt;p&gt;Und wenn man dann auch noch das richtige Monitor anschließt … dann sieht
man: COMMODORE BASIC, wie es sich gehört.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Wenn Hardware 30 Jahre übersteht und dann noch funktioniert, dann nennt man 
das entweder “Wunder” oder “höchste Qualität”.&lt;/p&gt;

&lt;p&gt;Als ich meinen C64 am Zweitwohnsitz am originalen Monitor startet und dieser
schwarz blieb, dachte ich, das war es jetzt.
Doch nun stellte sich heraus, das Gerät selbst funktioniert (meistens).&lt;/p&gt;

&lt;h3 id=&quot;c64-von-außen-und-innen&quot;&gt;C64 von außen und innen&lt;/h3&gt;

&lt;p&gt;C64 von vorne:
&lt;img src=&quot;/blog/assets/img/commodore64-1.jpg&quot; alt=&quot;Commodore64-1&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Links:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;2 Joystick oder Mouse-Ports&lt;/li&gt;
  &lt;li&gt;Ein/Aus-Schalter&lt;/li&gt;
  &lt;li&gt;Stromzufuhr vom Netzteil&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/commodore64-2.jpg&quot; alt=&quot;Commodore64-2&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Rückseite:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Expansion Port für Erweiterungskarten&lt;/li&gt;
  &lt;li&gt;TV/Monitor Ausgang&lt;/li&gt;
  &lt;li&gt;A/V Composite Video bzw. S-Video&lt;/li&gt;
  &lt;li&gt;Serieller Port für Diskettenlaufwerk&lt;/li&gt;
  &lt;li&gt;I/O Port für &lt;a href=&quot;https://de.wikipedia.org/wiki/Datasette&quot;&gt;Datasette&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;User-Port, unterschiedliche I/O Pins für Peripheriegeräte.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/commodore64-3.jpg&quot; alt=&quot;Commodore64-3&quot; /&gt;
&lt;img src=&quot;/blog/assets/img/commodore64-4.jpg&quot; alt=&quot;Commodore64-4&quot; /&gt;&lt;/p&gt;

&lt;p&gt;An der Unterseite befinden sich die Schrauben die den Tastaturoberteil und
den Mainboard-Unterteil zusammenhalten.&lt;br /&gt;
&lt;img src=&quot;/blog/assets/img/commodore64-5.jpg&quot; alt=&quot;Commodore64-5&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Öffnet man den Brotkasten, fällt ein Alufolie auf, die das Keyboard vom
Mainboard trennt.&lt;br /&gt;
&lt;img src=&quot;/blog/assets/img/commodore64-6.jpg&quot; alt=&quot;Commodore64-6&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Darunter befindet sich dann das C64 Mainboard:&lt;br /&gt;
&lt;img src=&quot;/blog/assets/img/commodore64-7.jpg&quot; alt=&quot;Commodore64-7&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Die (extrem verdreckte) Tastatur war der spannende Teil, denn alle Tasten
saßen auf Sprungfedern über den Druckpunkten. Bei der Entfernung der
Tasten war etwas Kraft notwendig, und leider brach mir bei einer Taste der
Stift unter der Taste ab. Es empfiehlt sich also behutsam vorzugehen.
&lt;img src=&quot;/blog/assets/img/commodore64-8.jpg&quot; alt=&quot;Commodore64-8&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Die Unterseite des Keyboards ist nicht so besonders spektakulär.
Nur die Shift-Lock Taste unterscheidet sich mit einem speziellen 
Bauteil von den anderen Tasten.
&lt;img src=&quot;/blog/assets/img/commodore64-9.jpg&quot; alt=&quot;Commodore64-9&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;reinigung&quot;&gt;Reinigung&lt;/h3&gt;

&lt;p&gt;So viele Wattestäbchen habe ich schon lange nicht mehr verbraucht, denn mit
etwas Brennspiritus putzte ich alle Chips der Platine und auch die verdreckte
Tastatur.&lt;br /&gt;
Die Tasten genossen ein kurzes Seifenbad, nur die Sprungfedern ließ ich 
unbehandelt, da sie noch relativ gut aussahen und nicht weiter rosten sollen.&lt;/p&gt;

&lt;p&gt;Nun sind Tasten und die Mainboard-Bauteile wieder großteils staubfrei.&lt;/p&gt;

&lt;h3 id=&quot;c64-monitor-im-programm-fenster&quot;&gt;C64 Monitor im Programm-Fenster&lt;/h3&gt;

&lt;p&gt;Bei meiner C64 Ausrüstung war auch ein Adapter des C64-A/V Ausgangs nach
&lt;a href=&quot;https://de.wikipedia.org/wiki/Composite_Video&quot;&gt;Composite Cinchstecker&lt;/a&gt; 
enthalten, und da erinnerte ich mich, dass ich vor Jahren mal ein USB-Gerät
gekauft hatte, mit dem Filme von VHS-Videorekordern übertragen werden konnten.&lt;/p&gt;

&lt;p&gt;Es war quasi eine primitive USB-TV-Capture-Karte mit Cinch-Eingängen und eben
diese Verband ich mit dem C64-Teil.&lt;br /&gt;
&lt;img src=&quot;/blog/assets/img/commodore64-video.jpg&quot; alt=&quot;C64-Video-Cable&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Windows erkannte das Gerät und installierte den generischen USB-Capture 
Treiber.&lt;br /&gt;
Nun startete ich VirtualDUB und fand das neue Capture-Device, mit welchem ich
die Videoaufzeichnung startete. 
Kaum schaltete ich den C64 ein, erschien in Graustufen das übliche C64-BASIC 
Build. Ich konnte sogar ein kurzes “Hello” Basic-Programm eintippen und 
ausführen:&lt;br /&gt;
&lt;img src=&quot;/blog/assets/img/commodore64-screen-capture.gif&quot; alt=&quot;C64-Screen-Capture&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Wow! Ich bin wieder voll motiviert.&lt;br /&gt;
Mein C64 läuft wieder und ist für alle Schandtaten bereit.&lt;/p&gt;

&lt;p&gt;Die Tastatur ist leider nicht mehr ausreichen funktionsfähig, da viele
Tasten nicht richtig funktionieren oder nur nach vielen Aufwänden ein 
Zeichen an das System senden.&lt;/p&gt;

&lt;p&gt;Trotzdem liebe ich den alten Brotkasten alleine dafür, dass er nach 30 Jahren
wieder erfolgreich anspringt.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ich hoffe, wir beide werden noch viele glückliche Jahre miteinander haben.&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>Happy New Year 2023</title>
   <link href="https://www.opengate.at/blog/2023/01/happy-new-2023/"/>
   <published>2023-01-01T12:00:00+01:00</published>
   <updated>2023-01-01T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2023/01/happy-new-2023</id>
   <category term="general" />
   <summary type="text">
  Das neue Jahr ist da - Hurra!


Trotz Knallgewitter gegen Mitternacht, steht die Welt noch.

</summary>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;Das neue Jahr ist da - Hurra!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Trotz Knallgewitter gegen Mitternacht, steht die Welt noch.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Ich blicke etwas unsicherer in die Zukunft als das die letzten Jahre
der Fall war, schließlich tobt immer noch ein Krieg in der Nähe.
Wirtschaft und Politik sind auch gerade nicht berauschend, und wie
es aussieht hat über Nacht auch noch 
&lt;a href=&quot;https://de.wikipedia.org/wiki/AliExpress&quot;&gt;Aliexpress&lt;/a&gt; die Lieferung 
von Waren nach Österreich eingestellt.&lt;/p&gt;

&lt;p&gt;Hmm … nicht gerade die besten Aussichten möchte man meinen.&lt;/p&gt;

&lt;p&gt;Aber, dann schaue ich mich um, stelle fest, dass es mir an nichts fehlt,
dass auch mehr als genug Arbeit (und Vergnügen) auf mich wartet,
und dass es allen wichtigen Menschen gut geht.&lt;/p&gt;

&lt;p&gt;Was soll also der Pessimismus?&lt;/p&gt;

&lt;p&gt;Für Wirtschaft und Politik kann jeder einzelne mit gutem Beispiel
voran gehen und einfach seinen Beitrag leisten.&lt;br /&gt;
Einen Krieg kann der einzelne nicht verhindern, aber jeder kann daran
arbeiten, dass kein weiterer ausbricht und dass man den Opfern 
bestmöglichst hilft.&lt;/p&gt;

&lt;p&gt;Und Aliexpress dürfte sich gerade wegen neuer Verpackungsgesetze 
umstellen, das heißt, auch das wird sich nach einiger Zeit lösen.&lt;/p&gt;

&lt;p&gt;Ich erwarte nun sehnlichst das neue &lt;a href=&quot;https://de.wikipedia.org/wiki/CMake&quot;&gt;CMake&lt;/a&gt; 
3.26 Release, was dieses Monat rauskommen soll und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Arm-Architektur#Armv8-A_(2011)&quot;&gt;ARM64&lt;/a&gt; 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Assembler_(Informatik)&quot;&gt;Assembler&lt;/a&gt; Support 
(&lt;code&gt;MARMASM&lt;/code&gt;) mitbringt und spiele aktuell mit dem Developer-Build herum.&lt;/p&gt;

&lt;p&gt;Und nach dem üblichen Weihnachtsfest-Fressen sind jetzt wieder 
einige Kohlenhydrat-reduzierte Wochen angesagt.&lt;/p&gt;

&lt;p&gt;Am Ende ist also doch alles im Rahmen, das Rad kann weiterlaufen
und daher wünsche ich allen:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Prosit Neujahr!&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>The same procedure as every year</title>
   <link href="https://www.opengate.at/blog/2022/12/year-2022/"/>
   <published>2022-12-31T12:00:00+01:00</published>
   <updated>2022-12-31T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2022/12/year-2022</id>
   <category term="general" />
   <summary type="text">
  Das Jahr ist um - na bumm!


</summary>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;Das Jahr ist um - na bumm!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Irgendwie ist 2022 ein kurzes, vertanes Jahr für mich gewesen.&lt;br /&gt;
Ich weiß nicht warum es so schnell vergangen ist, und ich kann auch nicht
wirklich großes davon berichten kann.&lt;/p&gt;

&lt;p&gt;Es war wie wenn man zu Mittag im Sessel einschläft und am Abend aufwacht
und nicht weiß, wo die Zeit geblieben ist.&lt;/p&gt;

&lt;p&gt;Bestimmt war es auch ein Jahr der Umwälzungen, in welchem die Schrecken des
Krieges nahe an unserer Haustüre wieder aufgekommen sind. 
Da habe ich mir zum Spaß Anfang des Jahres noch ein Squid-Game Kostüm und
eine Militäruniform bestellt um einen “dummen Streich” damit zu planen, und
stelle jetzt fest, dass es plötzlich überhaupt nicht mehr komisch ist,
Krieg zu spielen.&lt;br /&gt;
Das war bisher so weit weg, dass man es gar nicht mehr ernst genommen hat.&lt;/p&gt;

&lt;p&gt;Vielleicht liegt es daran, dass sich “außen” so viel geändert hat, dass man
die Innenarbeiten gar nicht mehr wahrnimmt. 
Die Pandemiejahre 2020 und 2021 waren letztendlich auch nicht lustig, aber
schlimm habe ich sie nicht empfunden. Doch mit 2022 weiß ich nicht, was
ich so recht damit anfangen soll.&lt;/p&gt;

&lt;p&gt;Doch … zumindest ein paar Dinge sind gleich geblieben.
Draußen knallt es, die Kinder freuen sich, Hunde und Katzen eher weniger.
Aber so ist das eben an Silvester.&lt;br /&gt;
Und obwohl sich so vieles geändert hat, freut es mich dann doch, dass
sich einige Dinge eben nie ändern.&lt;/p&gt;

&lt;p&gt;Und wenn es allen anderen gelingt, gut gelaunt ins neue Jahr zu rutschen,
dann will ich mir den Spaß auch nicht nehmen lassen.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Guten Rutsch!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;iframe width=&quot;640&quot; height=&quot;360&quot; src=&quot;/blog/redirect.html?https%3A%2F%2Fwww.youtube-nocookie.com%2Fembed%2FTo8g9XxAdXs&quot; frameborder=&quot;1&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
</content>
 </entry>
 
 <entry>
   <title>Mac Mini 2009 Upgrade</title>
   <link href="https://www.opengate.at/blog/2022/12/mac-mini-upgrade/"/>
   <published>2022-12-30T12:00:00+01:00</published>
   <updated>2022-12-30T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2022/12/mac-mini-upgrade</id>
   <category term="hardware" />
   <summary type="text">Mit 2 GB RAM 
und einer 2.5 Zoll HDD
ist mein alter Mac Mini 
nicht gerade zu Spitzenleistungen nach heutigen Kriterien befähigt.

Jeden PC hätte ich längst aufgerüstet … doch ein Apple
Gerät zerlegen … das hatte ich mich bisher nicht getraut.

Nun ist die Zeit gekommen das Wagnis einzugehen.
</summary>
   <content type="html">&lt;p&gt;Mit 2 GB &lt;a href=&quot;https://de.wikipedia.org/wiki/Random-Access_Memory&quot;&gt;RAM&lt;/a&gt; 
und einer 2.5 Zoll &lt;a href=&quot;https://de.wikipedia.org/wiki/Festplattenlaufwerk&quot;&gt;HDD&lt;/a&gt;
ist mein alter &lt;a href=&quot;https://de.wikipedia.org/wiki/Mac_mini&quot;&gt;Mac Mini&lt;/a&gt; 
nicht gerade zu Spitzenleistungen nach heutigen Kriterien befähigt.&lt;/p&gt;

&lt;p&gt;Jeden PC hätte ich längst aufgerüstet … doch ein &lt;a href=&quot;https://de.wikipedia.org/wiki/Apple&quot;&gt;Apple&lt;/a&gt;
Gerät zerlegen … das hatte ich mich bisher nicht getraut.&lt;/p&gt;

&lt;p&gt;Nun ist die Zeit gekommen das Wagnis einzugehen.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;wie-man-einen-mac-mini-2009-zerlegt-&quot;&gt;Wie man einen Mac Mini 2009 zerlegt …&lt;/h3&gt;

&lt;p&gt;Den Mac-Mini zu öffnen ist schwerer als eine Kokosnuss zu knacken.
Tatsächlich ist “die Box” schraubenlos zusammengesteckt, doch ich musste
unsäglich lange mit hauchdünnen spitzen Werkzeugen herumfuhrwerken, bis
sich die “obere Schale” vom unteren Mainboard-Teil löste.&lt;/p&gt;

&lt;h4 id=&quot;abnehmen-der-ummantelung&quot;&gt;Abnehmen der Ummantelung&lt;/h4&gt;

&lt;p&gt;Hier die Schale:&lt;br /&gt;
&lt;img src=&quot;/blog/assets/img/mac-mini-internal-09.jpg&quot; alt=&quot;MAC-Mini-Inside-09&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Und der Kern:&lt;br /&gt;
&lt;img src=&quot;/blog/assets/img/mac-mini-internal-01.jpg&quot; alt=&quot;MAC-Mini-Inside-01&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Witzig sind die diversen Antennen für 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Wireless_Local_Area_Network&quot;&gt;WLAN&lt;/a&gt; 
und &lt;a href=&quot;https://de.wikipedia.org/wiki/Bluetooth&quot;&gt;Bluetooth&lt;/a&gt;, die an Sprungfedern
an der Seite eingeklinkt sind.&lt;br /&gt;
Diese muss man nämlich vorsichtig entfernen und vom Mainboard abstecken,
um den oberen Teil mit dem &lt;a href=&quot;https://de.wikipedia.org/wiki/Optischer_Datenspeicher&quot;&gt;DVD-Laufwerk&lt;/a&gt; 
entfernen zu können.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/mac-mini-internal-03.jpg&quot; alt=&quot;MAC-Mini-Inside-03&quot; /&gt;&lt;/p&gt;

&lt;h4 id=&quot;abkoppelung-des-laufwerksrahmen&quot;&gt;Abkoppelung des Laufwerksrahmen&lt;/h4&gt;

&lt;p&gt;DVD-Laufwerk und Festplatte sind auf einem eigenen Plastikrahmen 
angebracht, der mit 4 Schrauben am Mainboard befestigt ist, und 
die Daten laufen über ein dünnes Flachbandkabel, das man vorsichtig
abziehen muss.&lt;/p&gt;

&lt;p&gt;Verbindung zwischen Mainboard-Adapter und Laufwerksteil:&lt;br /&gt;
&lt;img src=&quot;/blog/assets/img/mac-mini-internal-11.jpg&quot; alt=&quot;MAC-Mini-Inside-11&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Schraubsockel des schwarzen Laufwerksrahmen links unten:&lt;br /&gt;
&lt;img src=&quot;/blog/assets/img/mac-mini-internal-04.jpg&quot; alt=&quot;MAC-Mini-Inside-04&quot; /&gt;&lt;/p&gt;

&lt;h4 id=&quot;upgrade-von-ram-und-festplatte&quot;&gt;Upgrade von RAM und Festplatte&lt;/h4&gt;

&lt;p&gt;Hat man aber diese heiklen Absteckaktionen hinter sich, kann der obere
Laufwerksteil entfernt werden und das eigentlich Mainboard kommt
zum Vorschein.&lt;br /&gt;
Hier kann man nun RAM nachrüsten:&lt;br /&gt;
&lt;img src=&quot;/blog/assets/img/mac-mini-internal-12.jpg&quot; alt=&quot;MAC-Mini-Inside-12&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Und die Festplatte durch eine SSD ersetzen.&lt;/p&gt;

&lt;p&gt;Laufwerksrahmen von unten:&lt;br /&gt;
&lt;img src=&quot;/blog/assets/img/mac-mini-internal-14.jpg&quot; alt=&quot;MAC-Mini-Inside-14&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Laufwerksrahmen von oben:&lt;br /&gt;
&lt;img src=&quot;/blog/assets/img/mac-mini-internal-13.jpg&quot; alt=&quot;MAC-Mini-Inside-13&quot; /&gt;&lt;/p&gt;

&lt;h4 id=&quot;erneute-zusammensetzung&quot;&gt;Erneute Zusammensetzung&lt;/h4&gt;

&lt;p&gt;Beim Anschließenden Zusammensetzen habe ich ganz besonders an den kleinen
Steckkontakten für die Antennen gelitten. Einer war nämlich unter dem
Laufwerksrahmen angebracht und die Verkabelung war leider zu kurz, als
dass ich sie im Vorfeld hätte anbringen können.&lt;br /&gt;
Mit Pinzette und viel Weinen bekam ich den Stecker auch von außen wieder
angeschlossen:&lt;br /&gt;
&lt;img src=&quot;/blog/assets/img/mac-mini-internal-02.jpg&quot; alt=&quot;MAC-Mini-Inside-02&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;upgrade-mit-problemen&quot;&gt;Upgrade mit Problemen&lt;/h3&gt;

&lt;p&gt;Mein Plan war es ursprünglich, den RAM zu verdoppeln und die Festplatte
durch eine schnellere SSD zu ersetzen.&lt;/p&gt;

&lt;h4 id=&quot;ram-upgrade-mit-problemen&quot;&gt;RAM Upgrade mit Problemen&lt;/h4&gt;

&lt;p&gt;In den beiden RAM Slots steckten 2x 1 GB DDR3 Module.
Mein Plan war es, diese auf 4 GB aufzustocken, indem ich 2x 2 GB Module
einsetzen wollte.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/mac-mini-internal-07.jpg&quot; alt=&quot;MAC-Mini-Inside-07&quot; /&gt;
&lt;img src=&quot;/blog/assets/img/mac-mini-internal-06.jpg&quot; alt=&quot;MAC-Mini-Inside-06&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Doch der erste Start ließ das Board mit einem Piepton alle 5 Sekunden 
nicht mehr regulär booten.
Nach einigem Herumprobieren fand ich leider die Ursache:&lt;br /&gt;
Ich muss wohl einen der RAM-Slots irgendwie beschädigt haben, denn
sobald ein RAM-Riegel in den unteren Slot eingeführt wird, startet
das Board nicht mehr.&lt;/p&gt;

&lt;p&gt;Sowohl die alte RAM-Bestückung, wie auch unterschiedlichste Kombinationen
des neuen RAMs führten immer zum Ergebnis, dass beim Einsatz des unteren
Slots das Board nicht mehr startet.&lt;br /&gt;
Wird nur der obere Slot befüllt, läuft &lt;a href=&quot;https://de.wikipedia.org/wiki/MacOS&quot;&gt;MacOS&lt;/a&gt;
ganz normal an.&lt;/p&gt;

&lt;p&gt;Meine Lösung war daher in den oberen Slot ein 4GB DDR3 Modul einzubauen 
und den unteren Slot frei zulassen, und so funktionierte es am Ende auch.&lt;/p&gt;

&lt;p&gt;Schade eigentlich, denn ich dachte, so könnte ich meine alten 2 GB Module
sinnvoll verbauen.&lt;/p&gt;

&lt;h4 id=&quot;ssd-statt-hdd&quot;&gt;SSD statt HDD&lt;/h4&gt;

&lt;p&gt;Da ich keine Ahnung hatte, ob und wie ich MacOS auf dem Gerät neu
installieren konnte, kopierte ich einfach den gesamten Inhalt der
160 GB Festplatte Sektor für Sektor auf eine neue 256 GB SSD.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/mac-mini-internal-05.jpg&quot; alt=&quot;MAC-Mini-Inside-05&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Das dauerte zwar eine Zeit lang, war aber am Ende erfolgreich.&lt;br /&gt;
Der Start von MacOS funktionierte auf Anhieb und war auch schneller,
als ursprünglich am alten Laufwerk.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ich müsste lügen, wenn ich sagen würde, ich hätte meinen Mac-Mini sehr vermisst.
Doch es ist gut zu wissen, dass das Gerät nun zumindest ein bisschen 
aufgefrischt ist.&lt;/p&gt;

&lt;p&gt;Mein &lt;a href=&quot;/blog/2020/02/mac-mini/&quot;&gt;Software-Update vor zwei Jahren&lt;/a&gt; 
hat dem Modell in Sachen Performance nicht gut getan, doch mit der neuen SSD 
und mehr RAM läuft es wieder ganz passabel.&lt;/p&gt;

&lt;p&gt;Ärgerlich ist nur der nun defekte RAM-Slot.&lt;br /&gt;
Ich kann daher nur zu größter Vorsicht aufrufen, wenn dort jemand Hand 
anlegen will. Vielleicht war es eine elektrostatische Entladung, weil
mir sonst kein “Abrutscher” bewusst geworden wäre. Auch konnte ich
keine andere physische Beschädigung feststellen.&lt;/p&gt;

&lt;p&gt;In Summe war es aber mal eine nette Abwechslung und definitiv ganz anders
als bei üblichen PCs oder &lt;a href=&quot;https://de.wikipedia.org/wiki/Mini-ITX&quot;&gt;ITX&lt;/a&gt;-Boards.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>WinCE Menüs</title>
   <link href="https://www.opengate.at/blog/2022/12/wince-menu/"/>
   <published>2022-12-26T12:00:00+01:00</published>
   <updated>2022-12-26T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2022/12/wince-menu</id>
   <category term="devel" />
   <summary type="text">
  Alle Jahre wieder…
tauchen die gleichen UI Probleme erneut auf.


Ich hatte doch schon mal Menüs in Windows CE 
angefangen … und wieder abgeändert und wieder noch etwas geändert … 
und dann lief es nicht mehr.
Oder … hat es überhaupt je richtig funktioniert ?

Es wird Zeit für eine Detailanalyse.
</summary>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;Alle Jahre wieder…&lt;br /&gt;
tauchen die gleichen UI Probleme erneut auf.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ich hatte doch schon mal Menüs in &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_CE&quot;&gt;Windows CE&lt;/a&gt; 
angefangen … und wieder abgeändert und wieder noch etwas geändert … 
und dann lief es nicht mehr.&lt;br /&gt;
Oder … hat es überhaupt je richtig funktioniert ?&lt;/p&gt;

&lt;p&gt;Es wird Zeit für eine Detailanalyse.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Windows CE ist nicht Windows CE, sondern es ist Windows CE oder (das alte) 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_Mobile#Windows_Mobile_6&quot;&gt;Windows Mobile&lt;/a&gt;. 
Und im Falle von Windows Mobile ist es ein “Smartphone” von vor 2007 mit 
Bildschirmauflösungen von 320x240, anders gesagt: Briefmarken-klein.&lt;/p&gt;

&lt;p&gt;Jetzt kann man zwar mit 
&lt;a href=&quot;https://learn.microsoft.com/en-us/uwp/api/windows.ui.xaml.controls.commandbar?view=winrt-22621&quot;&gt;CommandBar Controls&lt;/a&gt; “echte” 
Menüzeilen basteln, die dann aber auf diesen Kleingeräten unbenutzbare UIs 
bedeuten. Und das fällt einem nicht auf bei einem einzigen Menüeintrag, aber 
bei 3+ wird das schon sehr deutlich.&lt;/p&gt;

&lt;h3 id=&quot;die-pseudo-shell-menu-bar&quot;&gt;Die Pseudo-Shell-Menu-Bar&lt;/h3&gt;

&lt;p&gt;Die &lt;code&gt;AGYShell&lt;/code&gt; von Windows Mobile/CE bringt allerdings ein ähnliches Feature 
mit, nämlich die beiden “Software-Buttons” am unteren Rand.&lt;br /&gt;
Gedacht waren diese “Tasten” für ein schnelles &lt;code&gt;OK&lt;/code&gt; oder &lt;code&gt;Cancel&lt;/code&gt;, 
bzw. &lt;code&gt;Zurück&lt;/code&gt; und &lt;code&gt;Weiter&lt;/code&gt;.&lt;br /&gt;
An die beiden schmalen Schaltflächen schmiegt sich in der Mitte auch noch 
der Keyboard-Button, mit dem man die virtuelle Tastatur ausfahren kann.&lt;/p&gt;

&lt;h4 id=&quot;idee-popup-menü-durch-software-button&quot;&gt;Idee: Popup-Menü durch Software-Button&lt;/h4&gt;

&lt;p&gt;Ich dachte mir also, dass das Programm-Menü (Datei, Bearbeiten, usw.) unter
Windows Mobile nicht ständig angezeigt werden muss, sondern nur ein &lt;code&gt;Menü&lt;/code&gt;
Software-Button angezeigt wird, und erst beim Klick darauf, wird das 
eigentliche Menü als Popup-Menü ausgefahren.&lt;br /&gt;
Damit wird kein Platz unnötig belegt und die Programmlogik kann dann genau
so aussehen, wie auf einer vollen Desktop App.&lt;/p&gt;

&lt;h4 id=&quot;resourcen-zwang&quot;&gt;Resourcen-Zwang&lt;/h4&gt;

&lt;p&gt;Die Funktion 
&lt;a href=&quot;https://learn.microsoft.com/en-us/previous-versions/windows/embedded/aa453678(v=msdn.10)&quot;&gt;SHCreateMenuBar&lt;/a&gt; 
erzeugt zwar diese Software-Buttons, doch sie verlangt eine Menü-Ressource 
in der Programmdatei, und die sieht z.B.: so aus:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;// IDs from shared header
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;#define MY_MENU_ID            102
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;#define MY_MENU_BUTTON_1_TEXT 103
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;#define MY_MENU_BUTTON_2_TEXT 104
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;#define MY_MENU_BUTTON_1_MSG  40000
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;#define MY_MENU_BUTTON_2_MSG  40001
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;// .rc resource file:
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;STRINGTABLE  
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;BEGIN
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  MY_MENU_BUTTON_1_TEXT        &amp;quot;OK&amp;quot;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  MY_MENU_BUTTON_2_TEXT        &amp;quot;HELP&amp;quot;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;END
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;MY_MENU_ID SHMENUBAR DISCARDABLE
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;BEGIN
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  MY_MENU_ID, 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;  2,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;  I_IMAGENONE, MY_MENU_BUTTON_1_MSG, 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;  TBSTATE_ENABLED, TBSTYLE_BUTTON | TBSTYLE_AUTOSIZE,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;  MY_MENU_BUTTON_1_TEXT, 0, NOMENU,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;    
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;  I_IMAGENONE, MY_MENU_BUTTON_2_MSG, 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;  TBSTATE_ENABLED, TBSTYLE_DROPDOWN | TBSTYLE_AUTOSIZE,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;  MY_MENU_BUTTON_2_TEXT, 0, 0,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;END
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Im C Code kann man nun auf das &lt;code&gt;MY_MENU_ID&lt;/code&gt; Makro verweisen:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;HWND hwnd_of_windows;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;SHMENUBARINFO mbi;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;RECT rc_window, rc_menu;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#777&quot;&gt;// create menu bar&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;mbi.cbSize = &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;sizeof&lt;/span&gt;(mbi);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;mbi.hwndParent = hwnd_of_window;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;mbi.dwFlags = &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;mbi.hInstRes = (HINSTANCE)GetModuleHandle(&lt;span style=&quot;color:#069&quot;&gt;NULL&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;mbi.nToolBarId = MY_MENU_ID;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;SHCreateMenuBar(&amp;amp;mbi);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#777&quot;&gt;// resize main window to exclude menu-bar&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;GetWindowRect(hwnd_of_window, &amp;amp;rc_window);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;GetWindowRect(mbi.hwndMB, &amp;amp;rc_menu);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;rc_window.bottom -= (rc_menu.bottom - rc_menu.top);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;MoveWindow(hwnd_of_windows, rc_window.left, rc_window.top, 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;    rc_window.right - rc_window.left, rc_window.bottom - rc.top, 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;    FALSE);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;DrawMenuBar(hwnd_of_window);
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Anschließend lässt sich in der &lt;code&gt;WM_COMMAND&lt;/code&gt; Nachricht die
&lt;code&gt;MY_MENU_BUTTON_1_MSG&lt;/code&gt; und &lt;code&gt;MY_MENU_BUTTON_2_MSG&lt;/code&gt; ID wieder abfangen.
An dieser Stelle kann man dann ein übliches Win32 Popup-Menü mit den
eigentlichen Menüeinträgen anzeigen lassen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Dieser Workaround funktioniert tatsächlich, zumindest konnte ich im
Device-Emulator nun meinen Texteditor laden, der dort sein Menü nur beim
Klick auf den Software-Button anzeigt.&lt;br /&gt;
Und die gleiche Anwendungslogik erzeugt am herkömmlichen Desktop 
weiter ein Fenster-Menü.&lt;/p&gt;

&lt;p&gt;Mein Anliegen ist damit gelöst … doch man lernt daraus wieder,
wie verdammt schwierig es ist, mit “einer API” zwei unterschiedliche
Plattformen auf den gleichen Nenner zu bringen.&lt;/p&gt;

&lt;p&gt;Das erklärt auch, warum der Trend zu Webanwendungen geht,
denn dort ist “Responsive Design” mit ein paar Zeilen 
&lt;a href=&quot;https://de.wikipedia.org/wiki/CSS&quot;&gt;CSS&lt;/a&gt; erreichbar, während man auf der 
nativen Seite lange hin und her probieren muss, bis man eine
akzeptable Lösung gefunden hat.&lt;/p&gt;

&lt;h3 id=&quot;nachtrag-rc-in-cmake&quot;&gt;Nachtrag: RC in CMAKE&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;Und wie bindet man jetzt Resource-Dateien &lt;code&gt;.rc&lt;/code&gt; in CMake in ein Projekt ein?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Einfach per &lt;code&gt;target_sources&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-cmake highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;if(WIN32)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;  file(GLOB RC_RESOURCE_FILES
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;    &amp;quot;*.rc&amp;quot;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  )
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  target_sources(${PROJECT_NAME} PRIVATE ${RC_RESOURCE_FILES})
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;endif(WIN32)
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Denn ohne die Resource in der EXE schlägt der Aufruf von 
&lt;code&gt;SHCreateMenuBar&lt;/code&gt; fehl.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Kalter Krieg</title>
   <link href="https://www.opengate.at/blog/2022/12/war-against-winter/"/>
   <published>2022-12-25T12:00:00+01:00</published>
   <updated>2022-12-25T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2022/12/war-against-winter</id>
   <category term="general" />
   <summary type="text">Wenn es in Wien +5 Grad hat, hat es oben im Waldviertel etwa 5 Grad weniger 
und vielleicht schneit es dort sogar. Früher hatten wir auch schon mal -15 
Grad. Unter +20 Grad lässt meine Heizung die Temperatur in der Wohnung 
jedenfalls nicht fallen.

Aber … es soll tausende Menschen geben, in deren Häuser Löcher gebombt 
wurden. Wie warm wird denen jetzt sein?
</summary>
   <content type="html">&lt;p&gt;Wenn es in Wien +5 Grad hat, hat es oben im Waldviertel etwa 5 Grad weniger 
und vielleicht schneit es dort sogar. Früher hatten wir auch schon mal -15 
Grad. Unter +20 Grad lässt meine Heizung die Temperatur in der Wohnung 
jedenfalls nicht fallen.&lt;/p&gt;

&lt;p&gt;Aber … es soll tausende Menschen geben, in deren Häuser Löcher gebombt 
wurden. Wie warm wird denen jetzt sein?
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Ich habe das Privileg in einer Firma zu arbeiten, in der - hier in Wien - 
ein Russe, ein Weißrusse und ein Ukrainer zusammenarbeiten. 
Alle sind sie echt “gute Jungs” und halten unsere Controller Hardware und 
Software am Laufen, finden Fehler und beheben sie.&lt;/p&gt;

&lt;p&gt;Und trotz mancher Unterschiede funktioniert das sehr gut.&lt;br /&gt;
Es gibt kein physikalisches Gesetz, keine Naturkonstante, die die Menschen
zum Krieg zwingt. Und trotzdem vergehen keine 10 Jahre, in denen es auf
der Erde einmal “ruhig” zugegangen wäre.&lt;/p&gt;

&lt;p&gt;Ich sitze in der gut beheizten Wohnung und kann über den Sinn des Lebens
nachdenken … doch 1000 km weiter östlich haben die Menschen ein solches 
Privileg nicht.&lt;/p&gt;

&lt;p&gt;Wie kann es eigentlich sein, dass in einer Welt, in der noch nie so viel 
kommuniziert wurde wie heute, so effektiv an einander vorbeigeredet
wurde, wodurch am Ende die Waffen sprechen müssen?&lt;/p&gt;

&lt;p&gt;Vielleicht kommunizieren wir gar nicht, sondern reden nur sinnfrei in
den Äther hinein.&lt;br /&gt;
In der Technik wäre das Problem schnell gefunden:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Jeder Sender braucht einen Empfänger … und umgekehrt.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Wir haben auf den “Empfänger” vergessen.&lt;br /&gt;
Wir hören nicht mehr zu.&lt;br /&gt;
Und nichts kann einen wütender machen, als wenn man feststellt, 
dass einem keiner mehr zuhört.&lt;/p&gt;

&lt;p&gt;Es sind nicht nur&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;die Priester, die von der Kanzel aus predigen, die nicht zuhören.&lt;/li&gt;
  &lt;li&gt;die Politiker, die nur Reden schwingen und nicht zuhören.&lt;/li&gt;
  &lt;li&gt;die Youtuber, die sich nur selbst reden hören wollen, die nicht zuhören.&lt;/li&gt;
  &lt;li&gt;die Twitterer, die nur auffallen wollen und nicht zuhören.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Es sind wir alle.&lt;br /&gt;
Auch mich hat es nicht gekümmert, was X km entfernt passiert, obwohl seit 
2014 die Krise am Köcheln war.&lt;/p&gt;

&lt;h3 id=&quot;was-kann-man-tun&quot;&gt;Was kann man tun?&lt;/h3&gt;

&lt;p&gt;Tja … Spenden hilft vielleicht das Schlimmste abzuwenden, und wir alle 
können es uns leisten … wir müssen es nur wollen.&lt;/p&gt;

&lt;p&gt;Aber noch wichtiger ist, dass wir den eigenen moralischen Kompass wieder 
in Gang bekommen und das Gemeinwohl priorisieren, anstatt täglich über 
eigene Befindlichkeiten zu jammern.&lt;/p&gt;

&lt;p&gt;Ich saß neulich im Bus und beobachtete den Alltagsrassismus
(ein furchtbarer Begriff). Jederzeit hätte ich aufstehen können und mit 
wenigen Worten die Situation zu deeskalieren versuchen können.&lt;br /&gt;
Aber ich tat es nicht. Schließlich war ich nicht darauf vorbereitet …
und es war ja auch nicht meine Angelegenheit, wenn sich zwei Fremde
beflegeln.&lt;br /&gt;
Und wieder wurde eine weitere giftige Menge CO2 ausgestoßen, die nur
Hass erzeugt hat. Und es hätte vielleicht nur so wenig gefehlt, um es
verhindern zu können.&lt;/p&gt;

&lt;p&gt;Also nehme ich mir das mal als Vorsatz, dass ich mir ein paar Sätze 
überlege, die man da sagen kann, und beim nächsten Mal tue ich etwas,
anstatt nur im Nachhinein halbklug darüber zu berichten.&lt;/p&gt;

&lt;p&gt;Und ich hoffe, dass das mehr Menschen versuchen zu tun. Denn wenn jeder 
“seine Straße sauber hält”, dann können auch die Mächtigen nicht mehr so
einfach das Land verdrecken, indem sie Nachbarn bewaffnet auf die Straße
hetzen.&lt;/p&gt;

&lt;p&gt;Ich wünsche mir für alle Menschen in der Ukraine, genau so wie die unschuldig
zum Kriegsdienst gezwungenen Russen, dass sie nächstes Jahr zu Weihnachten 
in der warmen Stube sitzen und ins lodernde Kaminfeuer schauen
können, anstatt einen kalten Krieg befeuern zu müssen.&lt;/p&gt;

&lt;p&gt;In diesem Sinne:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ein frohes Weihnachtsfest …&lt;br /&gt;
… hoffentlich nächstes Jahr.&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>Großvaters Baum</title>
   <link href="https://www.opengate.at/blog/2022/12/grandfather/"/>
   <published>2022-12-24T12:00:00+01:00</published>
   <updated>2022-12-24T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2022/12/grandfather</id>
   <category term="general" />
   <summary type="text">Meine Mutter erzählte mir schon so manche interessante Geschichte rund um
meinen Großvater, doch eine, die mit dem Weihnachtsbaum, war eine
besondere.
</summary>
   <content type="html">&lt;p&gt;Meine Mutter erzählte mir schon so manche interessante Geschichte rund um
meinen Großvater, doch eine, die mit dem Weihnachtsbaum, war eine
besondere.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Meine Großeltern sind leider früh verstorben, und so habe ich an meinen
Großvater so gut wie keine Erinnerung mehr, da ich bei seinem Tod
6 Jahre alt war.&lt;br /&gt;
Und obwohl ich noch einige Weihnachtsabende mit Großmutter verbringen konnte,
so habe ich überhaupt kein Bild von Weihnachten im Kopf, wo beide
dabei waren.&lt;/p&gt;

&lt;h3 id=&quot;vor-über-60-jahren&quot;&gt;Vor über 60 Jahren&lt;/h3&gt;

&lt;p&gt;Es gab mal eine Zeit, in der meine Mutter als Kind auf den 
Weihnachtsabend wartete. Und in jenen Tagen war es Großvaters Aufgabe, 
im eigenen Wald den richten Baum für das Weihnachtsfest zu finden, 
zu schlägern und für die Bescherung vorzubereiten.&lt;/p&gt;

&lt;p&gt;Und ich finde es lustig zu hören, dass die Wahl des Baumes öfters fast
zum Auslöser eines Streites zwischen Großvater und Großmutter geworden wäre.&lt;br /&gt;
Denn Großmutter liebte es, die ganze Familie beisammen zu haben und idyllisch
unter einem prächtigen Weihnachtsbaum Lieder zu singen.&lt;br /&gt;
Großvater hingegen liebte seinen Wald und war stolz auf die schönen Bäume,
um die er sich das ganze Jahr gekümmert hatte. Nie hätte er “den besten Baum”
nur für eine Woche zu Fall gebracht.&lt;/p&gt;

&lt;p&gt;Und so erzählt mir meine Mutter heute noch, wie sie die Worte ihrer Mutter
vernahm, die sie vorwurfsvoll an Großvater richtete:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Von allen Leuten im Dorf haben wir den schiefsten 
und armseligsten Krampen im Zimmer stehen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Bis zur Bescherung hatte sich der Rauch wieder gelegt und es wurde auch
mit dem “nicht-schönsten” Baum stets ein schönes Fest.&lt;/p&gt;

&lt;h3 id=&quot;symbole&quot;&gt;Symbole&lt;/h3&gt;

&lt;p&gt;Ich kann beide Großeltern gut verstehen.&lt;/p&gt;

&lt;p&gt;Schließlich verprassen wir wirklich viel zu viele Ressourcen nur für ein
paar Tage um ein Bilderbuch-Bild von uns selbst zu malen. Danach fliegen
die Bäume auf die Straße und werden zu Müll, anstatt dass sie uns wertvollen
Sauerstoff über ihr gesamtes Leben liefern.&lt;br /&gt;
Da hatte Opa also recht, wenn er nur den “unschönsten” Baum fällen wollte.&lt;/p&gt;

&lt;p&gt;Und dann gibt es da diese vielen Geschichten, von Leid und Armut, und wie 
ein Ereignis, ein geschmückter Baum wieder Freude in die Gesichter der 
sonst frustrierten Menschen zeichnen kann. In der Stube sitzt man das 
ganze Jahr beisammen, doch wenn der Baum im Kerzenlicht erstrahlt, schaffen 
wir Erinnerungen, über die wir noch Jahrzehnte später sprechen werden.&lt;br /&gt;
Da hatte Oma also recht, wenn sie den schönsten Baum haben wollte.&lt;/p&gt;

&lt;h3 id=&quot;frohe-weihnachten&quot;&gt;Frohe Weihnachten!&lt;/h3&gt;

&lt;p&gt;Heute sind meine Großeltern wieder in meinen Gedanken … und vor allem
wegen der Geschichte mit dem Weihnachtsbaum.&lt;/p&gt;

&lt;p&gt;Obwohl ich viel zu wenig Zeit mit ihnen teilen konnte, weiß ich, dass
ich vieles heute nicht hätte, hätten sie nicht so viel Zeit und Arbeit
für mich aufgebracht.&lt;/p&gt;

&lt;p&gt;Und deshalb teile ich heute die Sprüche, den die beiden meiner Mutter
beibrachten, und die sie mich lehrte:&lt;/p&gt;

&lt;p&gt;Großvater:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Prahl’ nicht mit dem Erreichten groß!
Du stehst auf deiner Ahnen Schultern bloß!&lt;br /&gt;
Wie Stein auf Stein empor sich fügt zum First.&lt;br /&gt;
Du bist nur Giebel, bis du Sockel wirst!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;(Eine freie Fassung von 
&lt;a href=&quot;https://www.aphorismen.de/gedicht/168397&quot;&gt;Die Mauer der Menschheit&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Großmutter:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Wenn dich die Menschen auch kränken, 
weine nicht.
Alles kannst du dir denken,
sagen nicht.
Geh’ immer lachend durchs Leben,
hast du auch Kummer und Schmerz
Hilfe wird dir niemand geben,
denn Menschen von heut’ haben Herz.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Und von meiner Urgroßmutter lernten wir:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Du kannst so jung nicht bleiben,
bleib denn so gut und rein.
So wirst du stets wie heute,
der Liebling aller sein.&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>Thread oder Fiber</title>
   <link href="https://www.opengate.at/blog/2022/12/thread-fiber/"/>
   <published>2022-12-18T12:00:00+01:00</published>
   <updated>2022-12-18T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2022/12/thread-fiber</id>
   <category term="devel" />
   <summary type="text">Der Aufruf von Sleep()
schickt einen Thread schlafen. Aber wenn der Thread ein Fiber ist, wäre es 
sinnvoller, andere Fibers zu aktivieren, damit die was Sinnvolles tun können.

Doch wie weiß man jetzt, ob man in einem 
Thread oder in einem 
Fiber läuft?
</summary>
   <content type="html">&lt;p&gt;Der Aufruf von &lt;a href=&quot;https://learn.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-sleep&quot;&gt;Sleep()&lt;/a&gt;
schickt einen Thread schlafen. Aber wenn der Thread ein Fiber ist, wäre es 
sinnvoller, andere Fibers zu aktivieren, damit die was Sinnvolles tun können.&lt;/p&gt;

&lt;p&gt;Doch wie weiß man jetzt, ob man in einem 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Thread_(Informatik)&quot;&gt;Thread&lt;/a&gt; oder in einem 
&lt;a href=&quot;https://de.wikipedia.org/wiki/User-Thread#Windows&quot;&gt;Fiber&lt;/a&gt; läuft?
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;vorgeschichte-crash-auf-arm64&quot;&gt;Vorgeschichte: Crash auf ARM64&lt;/h3&gt;

&lt;p&gt;Ich schicke Threads selten schlafen, am ehesten warte ich auf Bedingungen 
mit Events, Conditions oder anderen Objekten.
Eine Ausnahme gibt es allerdings: Bei der Ermittlung der aktuellen 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Prozessor&quot;&gt;CPU&lt;/a&gt; Auslastung.
Denn hierfür soll der aktuelle Thread wirklich “schlafen gehen”, um danach
festzustellen, wie viele CPU Aktionen in der Zwischenzeit außerhalb passiert
sind.&lt;/p&gt;

&lt;p&gt;Tja und heute sehe ich zufällig einen Crash in meiner Sleep-Implementierung:&lt;/p&gt;

&lt;p&gt;In dieser wollte ich nämlich genau diese Unterscheidung machen:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Ist es ein Thread, rufe die OS &lt;code&gt;Sleep()&lt;/code&gt; Routine auf.&lt;/li&gt;
  &lt;li&gt;Ist es ein Fiber, führe ein &lt;code&gt;yield()&lt;/code&gt; aus, damit was anderes abgearbeitet 
werden kann.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Und für die Unterscheidung nutzte ich einfach 
&lt;a href=&quot;https://learn.microsoft.com/en-us/windows/win32/api/winnt/nf-winnt-getfiberdata&quot;&gt;GetFiberData()&lt;/a&gt; 
und erwartete einen &lt;code&gt;NULL&lt;/code&gt;-Pointer, wenn kein Fiber gestartet wurde.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Das ist leider verdammt falsch!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;code&gt;GetFiberData()&lt;/code&gt; ist ein Makro, das 
&lt;a href=&quot;https://learn.microsoft.com/en-us/windows/win32/api/winnt/nf-winnt-getcurrentfiber&quot;&gt;GetCurrentFiber()&lt;/a&gt;
und daraus einen Pointer zum Fiber-Datenzeiger ableitet. Dieser wird 
dereferenziert und genau hier dreht einem der Kernel den Hals um.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;GetCurrentFiber()&lt;/code&gt; liefert nämlich immer einen Nicht-&lt;code&gt;NULL&lt;/code&gt;-Pointer, der 
aber außerhalb eines Fibers auf “irgendwas” zeigt, nur nicht auf gültige
Daten.&lt;/p&gt;

&lt;h3 id=&quot;lösung&quot;&gt;Lösung&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_Vista&quot;&gt;Windows Vista&lt;/a&gt; führte 
die &lt;a href=&quot;https://learn.microsoft.com/en-us/windows/win32/api/fibersapi/nf-fibersapi-isthreadafiber&quot;&gt;IsThreadAFiber()&lt;/a&gt;
Funktion ein, die diese Frage eindeutig klärt. Das heißt, 
vor einem &lt;code&gt;Get*Fiber*()&lt;/code&gt; Aufruf prüft man, ob es sich überhaupt um einen 
Fiber handelt.&lt;/p&gt;

&lt;p&gt;Doch was ist mit &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_XP&quot;&gt;Windows XP&lt;/a&gt; 
und älter? Denn hier fehlt diese Schnittstelle.&lt;/p&gt;

&lt;p&gt;Meine Lösung ist: &lt;code&gt;IsBadReadPtr(GetCurrentFiber(), sizeof(void*))&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Ist dessen Rückgabewert nämlich &lt;code&gt;TRUE&lt;/code&gt; laufen wir in einem Thread, 
ist es &lt;code&gt;FALSE&lt;/code&gt;, ist ein Fiber am Werk.&lt;/p&gt;

&lt;p&gt;Man könnte natürlich auch per &lt;code&gt;__try/__except/__finally&lt;/code&gt; die Dereferenzierung
des Pointers gesichert abfangen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;Bug fixed.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Hier sieht man wieder mal, wie dumm das ausgehen kann, wenn man einmal Code
schreibt, der auf einem anderen aufbaut, und was passiert, wenn man dann 
1 Jahr später &lt;a href=&quot;https://de.wikipedia.org/wiki/Koroutine&quot;&gt;Koroutinen&lt;/a&gt; 
und Fibers einwebt. Schon ändert sich das Verhalten für einen Fall, 
den man nicht abgetestet hat.&lt;/p&gt;

&lt;p&gt;Mich verwundert, dass &lt;code&gt;IsThreadAFiber()&lt;/code&gt; erst 2006 mit Vista eingeführt wurde.
Ein solches &lt;code&gt;If&lt;/code&gt;-Tool hätte schon im originalen NT 4 1995 drinnen sein müssen.&lt;/p&gt;

&lt;p&gt;However … ich habe vorerst einen Workaround und bin glücklich.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>WASM: Webassembly mit C/C++</title>
   <link href="https://www.opengate.at/blog/2022/12/wasm/"/>
   <published>2022-12-17T12:00:00+01:00</published>
   <updated>2022-12-17T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2022/12/wasm</id>
   <category term="devel" />
   <summary type="text">Nun finden also meine ersten Ausflüge ins WASM-Land 
(Web-ASseMbly) statt.
Und neben beeindruckender Möglichkeiten sehe ich leider auch eine große
Anzahl von Problemen auf mich zukommen.

Denn es wäre doch zu schön, wenn ich einfach meine GATE-Apps für die
“Browser-Plattform” kompilieren könnte, und schon läuft alles online.
</summary>
   <content type="html">&lt;p&gt;Nun finden also meine ersten Ausflüge ins WASM-Land 
(&lt;a href=&quot;https://de.wikipedia.org/wiki/WebAssembly&quot;&gt;Web-ASseMbly&lt;/a&gt;) statt.
Und neben beeindruckender Möglichkeiten sehe ich leider auch eine große
Anzahl von Problemen auf mich zukommen.&lt;/p&gt;

&lt;p&gt;Denn es wäre doch zu schön, wenn ich einfach meine GATE-Apps für die
“Browser-Plattform” kompilieren könnte, und schon läuft alles online.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;vorgeschichte&quot;&gt;Vorgeschichte&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;Heißt das nicht &lt;a href=&quot;https://de.wikipedia.org/wiki/Java-Applet&quot;&gt;Java-Applet&lt;/a&gt; ?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Java-Technologie&quot;&gt;Java&lt;/a&gt; ist schon in den 90ern
daran gescheitert, als es mit seinen Applets und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/MIDlet&quot;&gt;Midlets&lt;/a&gt; jeden Browser infiziert hatte, 
die dann alle unter Java Sicherheitslücken litten.&lt;br /&gt;
Und am Ende wurde die Technologie abgeschaltet.&lt;/p&gt;

&lt;p&gt;Seit über 10 Jahren spukt nun der Gedanke im Äther herum, man könne doch 
native Anwendungen auch “im Web”, also im Browser laufen lassen.&lt;br /&gt;
Man müsste Code in eine Metasprache kompilieren, die der Browser dann
in nativen Maschinencode umwandelt und abspielt.&lt;br /&gt;
… das wäre dann also nochmal 
&lt;a href=&quot;https://de.wikipedia.org/wiki/.Net-Framework&quot;&gt;dotNet&lt;/a&gt; 1.0.&lt;/p&gt;

&lt;p&gt;Und daraus entstand &lt;a href=&quot;https://de.wikipedia.org/wiki/Asm.js&quot;&gt;asm.js&lt;/a&gt;, 
aus dem sich der heutige WebAssembly Standard entwickelte.&lt;/p&gt;

&lt;p&gt;Das heißt also:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Ich schreibe &lt;a href=&quot;https://de.wikipedia.org/wiki/C_(Programmiersprache)&quot;&gt;C Code&lt;/a&gt; 
und exportiere C-Funktionen&lt;/li&gt;
  &lt;li&gt;Ich übersetze den C Code in WASM Dateien&lt;/li&gt;
  &lt;li&gt;Ich lade &lt;a href=&quot;https://de.wikipedia.org/wiki/JavaScript&quot;&gt;Javascript&lt;/a&gt; Code im 
Browser, der meine WASM-Dateien lädt&lt;/li&gt;
  &lt;li&gt;Ich rufe die in C geschriebenen Funktionen aus JavaScript heraus auf.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;(Und natürlich geht das auch mit &lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B&quot;&gt;C++&lt;/a&gt;, 
nur Klassen sind da etwas schwieriger zu verwalten.)&lt;/p&gt;

&lt;h3 id=&quot;emscripten--ninja--cmake&quot;&gt;Emscripten + Ninja + CMake&lt;/h3&gt;

&lt;p&gt;WebAssemblies werden recht einfach mit dem 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Emscripten&quot;&gt;Emscripten&lt;/a&gt;
&lt;code&gt;EMSDK&lt;/code&gt; erstellt. Das ist ein angepasster Compiler mit weiteren Headern 
und Sourcen, den man herunterladen kann.&lt;br /&gt;
Das Setup ist in Tutorials gut beschrieben.&lt;/p&gt;

&lt;p&gt;Danach kann man die Environment-Variable &lt;code&gt;EMSDK&lt;/code&gt; auf das 
Installationsverzeichnis setzen und einige weitere Pfade ebenso bedenken:&lt;/p&gt;

&lt;div class=&quot;language-batch highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;set EMSDK=C:\path\to\emsdk
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;set EMSDK_NODE=%EMSDK%\node\14.18.2_64bit\bin\node.exe
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;set EMSDK_PYTHON=%EMSDK%\python\3.9.2-nuget_64bit\python.exe
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;set PATH=%PATH%;%EMSDK%
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;SET PATH=%PATH%;%EMSDK%\upstream\emscripten
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;SET PATH=%PATH%;%EMSDK%\node\14.18.2_64bit\bin
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Jetzt könnte man schon das erste “Hello-World” mit
&lt;code&gt;emcc hello.c&lt;/code&gt; erzeugen lassen.&lt;/p&gt;

&lt;p&gt;Aber interessant wird es erst mit &lt;a href=&quot;https://de.wikipedia.org/wiki/CMake&quot;&gt;CMake&lt;/a&gt;, 
und dafür brauchen wir unter Windows zuerst das Build-Tool 
&lt;a href=&quot;https://en.wikipedia.org/wiki/Ninja_(build_system)&quot;&gt;Ninja&lt;/a&gt;. 
Dessen EXE kommt am besten auch in den Pfad:&lt;/p&gt;

&lt;div class=&quot;language-batch highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;SET PATH=%PATH%;C:\path\to\ninja
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Und nachdem das &lt;code&gt;EMSDK&lt;/code&gt; bereits ein &lt;code&gt;CMake&lt;/code&gt; Umgebungstool mitgeliefert hat,
braucht man nur noch eine einfache &lt;code&gt;CMakeLists.txt&lt;/code&gt; zu seiner C-Datei
erstellen und&lt;br /&gt;
&lt;code&gt;emcmake cmake path\to\src&lt;/code&gt; aufrufen.&lt;br /&gt;
Denn &lt;code&gt;emcmake&lt;/code&gt; ruft &lt;code&gt;CMake&lt;/code&gt; mit den nötigen Parametern auf um 
Ninja-Buildscripts zu generieren.&lt;br /&gt;
Und wenn man am Ende noch &lt;code&gt;ninja&lt;/code&gt; im Buildverzeichnis aufruft,
startet die Übersetzung und man erhält eine &lt;code&gt;.wasm&lt;/code&gt; und eine
&lt;code&gt;.js&lt;/code&gt; Datei.&lt;/p&gt;

&lt;h3 id=&quot;brücke-zwischen-browser-und-webassembly&quot;&gt;Brücke zwischen Browser und WebAssembly&lt;/h3&gt;

&lt;p&gt;Die Idee ist, dass eine &lt;a href=&quot;https://de.wikipedia.org/wiki/Hypertext_Markup_Language&quot;&gt;HTML&lt;/a&gt; 
Seite die beim Kompilieren generierte Javascript-Datei lädt,
in der zahlreiche Initialisierungsschritte abgearbeitet werden
und die WASM-Datei geladen wird.&lt;/p&gt;

&lt;p&gt;Hierfür müssen einige Dinge “ausgetauscht” werden:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Der C-Code exportiert Funktionen, in der Regel ist &lt;code&gt;main()&lt;/code&gt; 
die erste Wahl.&lt;/li&gt;
  &lt;li&gt;Der Javascript-Code definiert selbst ein paar Funktionen, die
als Import-Objekte der WebAssembly zur Verfügung stehen
(z.B.: Callbacks für das Lesen und Schreiben von &lt;code&gt;stdin&lt;/code&gt; / &lt;code&gt;stdout&lt;/code&gt;).&lt;/li&gt;
  &lt;li&gt;Wir erhalten einen Heap-Speicherblock, der von der WebAssembly
und Javascript gemeinsam genutzt wird.&lt;/li&gt;
  &lt;li&gt;Und Javascript importiert C-Funktionen (allen voran &lt;code&gt;main&lt;/code&gt;) um
diese ausführen zu können.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Jetzt kann man WebAssemblies mit unterschiedlichen “Features”
kompilieren lassen und dementsprechend anders sieht dann der
Javascript Code aus.&lt;br /&gt;
Meine erste Annahme war nämlich, man könnte mit einer “generischen”
Javascript-Implementierung alle WebAssembly Features abgreifen, 
doch dem ist leider nicht so.&lt;/p&gt;

&lt;h3 id=&quot;problempunkt-threading&quot;&gt;Problempunkt: Threading&lt;/h3&gt;

&lt;p&gt;Wenn ich in Richtung GATE Projekt denke ergibt sich ein gröberes 
Problem: Ich setze gerne Threads ein, doch diese wiedersprechen dem
Javascript &lt;code&gt;async&lt;/code&gt;-Gedanken.&lt;/p&gt;

&lt;p&gt;Denn in Javascript läuft grundsätzlich nur ein Thread, und wenn etwas
system-spezifisches länger dauert, wird es als &lt;code&gt;async&lt;/code&gt; Funktion im 
Hintergrund abgearbeitet. Ein &lt;code&gt;sleep()&lt;/code&gt; oder andere Formen von 
blockierenden Funktionen darf es in dieser Welt nicht geben, weil 
sonst der Browser einfrieren würde.&lt;/p&gt;

&lt;p&gt;Am der Stelle wird es kompliziert und man hat mehrere
Möglichkeiten mit unterschiedlichen Seiteneffekten.&lt;/p&gt;

&lt;h4 id=&quot;asyncify&quot;&gt;Asyncify&lt;/h4&gt;

&lt;p&gt;Kompiliert man den Code mit der &lt;code&gt;ASYNCIFY&lt;/code&gt; Option, wird Code erzeugt,
der es erlaubt, laufende C-Funktionen zu unterbrechen … also in
etwa etwas wie &lt;a href=&quot;https://de.wikipedia.org/wiki/Koroutine&quot;&gt;Koroutinen&lt;/a&gt;.&lt;br /&gt;
So lassen sich dann &lt;code&gt;sleeps()&lt;/code&gt; ohne Störungen ausführen und man könnte
auch mehrere Aufgaben “anstoßen”, die schrittweise abgearbeitet werden
und “kooperativ” immer wieder den Mainthread weiterarbeiten lassen.&lt;/p&gt;

&lt;p&gt;Ein Ersatz für Threads ist das allerdings nichts und die Verwaltung
von vielen parallelen Funktionsaufrufen erfordert dann sehr viele 
Kreuzaufrufe zwischen WASM und dem Javascript-Code im Browser.&lt;/p&gt;

&lt;h4 id=&quot;pthreads&quot;&gt;Pthreads&lt;/h4&gt;

&lt;p&gt;Unglaublich, aber wahr: Man kann Webassemblies auch mit 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Portable_Operating_System_Interface&quot;&gt;POSIX&lt;/a&gt; 
Thread-API Support kompilieren.
Hierfür werden die neueren Worker-APIs des Browsers der C-Anwendung 
verfügbar gemacht, und somit entstehen echte parallele Ausführungsschienen.
Diese kommunizieren über &lt;code&gt;SharedArrayBuffer&lt;/code&gt;-Instanzen und senden sich so
Daten und Zustände zu.&lt;/p&gt;

&lt;p&gt;Das Problem daran ist: &lt;code&gt;SharedArrayBuffer&lt;/code&gt; ist auf Browsern im Standard 
gesperrt und kann nur durch spezielle HTTP-Header für “Cross-Origin” 
Scripting aktiviert werden. Außerdem braucht man dann mehrere 
Javascript-Dateien, weil &lt;code&gt;Worker&lt;/code&gt; Objekte mit unterschiedlichen Dateien 
funktionieren. Man kann also nicht einfach innerhalb einer Script-Datei 
einen Worker für eine Funktion anlegen.&lt;/p&gt;

&lt;h4 id=&quot;worker-api&quot;&gt;Worker API&lt;/h4&gt;

&lt;p&gt;Man kann aber auch direkt mit Web-Worker Objekten arbeiten und eine riesige
Menge an Javascript-Patchcode damit umgehen. Auch hier wird mit 
&lt;code&gt;SharedArrayBuffer&lt;/code&gt; und mehreren Javascript-Dateien gearbeitet und auch dafür
muss “Cross-Origin” Scripting am Webserver aktiviert sein.&lt;/p&gt;

&lt;p&gt;Zumindest hat man hier aber nur leichtgewichtige Konstrukte vor sich und
kann die &lt;code&gt;emscripten&lt;/code&gt;-Header nutzen, um neue Worker-Threads zu erzeugen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;Puh … wie fügt sich das jetzt in mein Weltbild ein ?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Die bisherige Anbindung von Plattformen an das GATE-Framework verlief so,
dass im Framework der Plattform-Support-Layer die Umgebungsdetails 
wegabstrahiert hat alles auf einen Nenner brachte.&lt;/p&gt;

&lt;p&gt;Doch WASM funktioniert im Browser nur in feiner Abstimmung mit externen
Javascript-Dateien, die wiederum mit Webseiten abgestimmt sind.&lt;/p&gt;

&lt;p&gt;Und dann kommt noch die Threading-Misere hinzu.&lt;/p&gt;

&lt;p&gt;Ich bin mir noch nicht sicher, ob und wie ich das mit meinen Vorstellungen
vereinen kann, doch eines kann ich bereits sagen:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Das Emscripten SDK ist eine hervorragende Möglichkeit, den Spielraum von
C/C++ gewaltig zu erweitern.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Denn bisher waren C/C++ Projekte als reine native System-Binaries abgestempelt.
Doch als WASM lassen sie sich über alle Mainstream-Browser auf jedes Gerät 
übertragen um dort ihr gutes Werk zu vollrichten.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Mastodon, Fosstodon und matrix.org</title>
   <link href="https://www.opengate.at/blog/2022/12/mastodon/"/>
   <published>2022-12-11T12:00:00+01:00</published>
   <updated>2022-12-11T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2022/12/mastodon</id>
   <category term="software" />
   <summary type="text">Die sogenannten sozialen Medien, die nachweislich ausschließlich asozial 
agieren, habe ich nie leiden und nutzen wollen. Vor allem sind sie ungeeignet
um intelligente Informationen zu verbreiten, denn die Wahrheit umfasst stets
mehr als 500 Zeichen.

Es gab zwar immer schon Open-Source
Alternativen auf denen sich die wenigen vernünftigen Techniker herumtrieben, 
doch Beachtung genossen sie nie.
… bis Elon Musk seine Überheblichkeit öffentlich zur Schau stellte.
</summary>
   <content type="html">&lt;p&gt;Die sogenannten sozialen Medien, die nachweislich ausschließlich asozial 
agieren, habe ich nie leiden und nutzen wollen. Vor allem sind sie ungeeignet
um intelligente Informationen zu verbreiten, denn die Wahrheit umfasst stets
mehr als 500 Zeichen.&lt;/p&gt;

&lt;p&gt;Es gab zwar immer schon &lt;a href=&quot;https://de.wikipedia.org/wiki/Open_Source&quot;&gt;Open-Source&lt;/a&gt;
Alternativen auf denen sich die wenigen vernünftigen Techniker herumtrieben, 
doch Beachtung genossen sie nie.&lt;br /&gt;
… bis Elon Musk seine Überheblichkeit öffentlich zur Schau stellte.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Irgendwie beweist sich gerade wieder von selbst, dass Techniker nichts in 
Wirtschaft und Politik verloren haben und umgekehrt Wirtschaftler und 
Politiker in der Technik nicht zu Hause sind.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Elon_Musk&quot;&gt;Elon Musk&lt;/a&gt;, der (ähnlich zu einem 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Steve_Jobs&quot;&gt;Steve Jobs&lt;/a&gt;) in der Technik viele 
wichtige Innovationen “ertrotzt” hatte, fährt gerade sein frisch eingekauftes 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Twitter&quot;&gt;Twitter&lt;/a&gt; mit reiner Egomanie an die 
Wand.&lt;br /&gt;
Und das gute daran ist, dass durch das Zerbrechen dieses üblen zentralen
Zeit-Totschlägers andere weniger schädliche Anbieter ins Rampenlicht kommen.&lt;/p&gt;

&lt;h3 id=&quot;mastodon&quot;&gt;Mastodon&lt;/h3&gt;

&lt;p&gt;Seit Jahren wird &lt;a href=&quot;https://de.wikipedia.org/wiki/Mastodon_(Software)&quot;&gt;Mastodon&lt;/a&gt; 
als Open-Source Alternative zu Twitter genannt.&lt;br /&gt;
Der größte Vorteil des Systems ist sein “föderierter” Ansatz.&lt;br /&gt;
Es gibt nicht “einen” zentralen Server, auf dem sich alle Nutzer tummeln, 
sondern jeder, der Willens ist, kann seinen eigenen Server aufstellen.&lt;br /&gt;
Damit jetzt nicht lauter kleine Inselstaaten entstehen, schließen sich die
Server zu einer “Föderation” zusammen, womit jeder im weltweiten Mastodon
Netz “suchen”, “folgen” und “teilen” kann.&lt;/p&gt;

&lt;p&gt;Richten sich Rechtsradikale, Bombenbauer oder Kinderpornohändler ebenfalls
einen solchen Server ein, so kann man das nicht verhindern, doch 
“die Föderation” kann solche Server ausschließen, womit ihre Inhalte isoliert
bleiben und keinen Schaden weltweit verbreiten.&lt;/p&gt;

&lt;p&gt;Ich wage jetzt mal den zaghaften Vergleich mit den Inhalten 
(nicht der Architektur!) von Wikipedia. Dort kann auch jeder Artikel 
schreiben, doch deren Qualität entscheidet am Ende, ob sie öffentlich 
bestehen bleiben.&lt;/p&gt;

&lt;h3 id=&quot;fosstodon-und-ich&quot;&gt;Fosstodon und ich&lt;/h3&gt;

&lt;p&gt;Das größte Problem bei Mastodon ist, dass man sich jetzt irgend einen Server
aussuchen muss, der einem die Mastodon Welt eröffnet und das ist sicher für 
viele schwierig. Es macht Sinn, sich einen Server mit “Gleichgesinnten” zu 
suchen, denn von dort wird man mehr relevante “lokale” Infos erhalten.&lt;/p&gt;

&lt;p&gt;Bei mir war die Sache vor eineinhalb Jahren einfach: Ich wollte mehr über die
&lt;a href=&quot;https://de.wikipedia.org/wiki/Pine64&quot;&gt;Pine64&lt;/a&gt; -Geräte erfahren und deren 
Community publiziert auf &lt;a href=&quot;https://fosstodon.org/&quot;&gt;fosstodon.org&lt;/a&gt;, wo sich 
viele Open Source Projekte herumtreiben. Also war klar, dass ich meinen 
Account dort anlege.&lt;/p&gt;

&lt;p&gt;So erhielt ich dann etwa wöchentlich von einigen Community-Accounts Infos
zu neuen Releases. Auch Privatpersonen posteten “twitter-like” ihre 
Tagesmeinung, doch das hielt sich im Verhältnis zu anderen Plapperblasen
im Netz sehr in Grenzen.&lt;/p&gt;

&lt;p&gt;Seit dem Twitter-Chaos ist die Anzahl der Nutzer und damit das Rauschen
und Gerede wesentlich lauter geworden. Mich interessiert das grundsätzlich
wenig, doch es hatte auch etwas Positives:&lt;br /&gt;
Projekte wie &lt;a href=&quot;https://de.wikipedia.org/wiki/FreeDOS&quot;&gt;FreeDOS&lt;/a&gt; und weitere 
kamen auch zu &lt;code&gt;fosstodon&lt;/code&gt; und veröffentlichten ihre News und so erfuhr ich 
wieder von neuen Projekten, die ansonsten an mir vorbeigegangen wären.&lt;/p&gt;

&lt;p&gt;Es ist also eine Frage des Filterns. 80% der neuen Beiträge sind Geschwafel, 
doch zwischendurch findet man immer wieder mal Perlen. 
Und dadurch, dass sich die Vollzeit-Egomanen auf anderen Mastodon-Servern
herumtreiben, wo ich sie nicht ständig sehen muss, ist diese 
“Twitter-Alternative” tatsächlich sogar für mich interessant geworden.&lt;/p&gt;

&lt;h3 id=&quot;matrixorg&quot;&gt;matrix.org&lt;/h3&gt;

&lt;p&gt;Die Ewig-Gestrigen nutzen den &lt;a href=&quot;https://de.wikipedia.org/wiki/Facebook&quot;&gt;Facebook&lt;/a&gt;
Messenger, Firmen starten 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Teams&quot;&gt;Microsoft Teams&lt;/a&gt;, die 
Möchtegern-Startup-Klugscheißer installieren 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Slack_(Software)&quot;&gt;Slack&lt;/a&gt;,
die Gamer nerven sich auf &lt;a href=&quot;https://de.wikipedia.org/wiki/Discord&quot;&gt;Discord&lt;/a&gt;
… und was sollen Open Source Enthusiasten nehmen?&lt;/p&gt;

&lt;p&gt;Ich nenne jetzt mal &lt;a href=&quot;https://matrix.org/&quot;&gt;Matrix&lt;/a&gt;, was eher ein 
Protokollstandard, als ein “Anbieter” ist, doch die 
Referenzimplementierung auf &lt;code&gt;matrix.org&lt;/code&gt; stellt einen freien kostenlosen 
Kommunikationsdienst bereit, der bereits von vielen Projekten aktiv genutzt 
wird.&lt;/p&gt;

&lt;p&gt;Ich sehe es als eine moderne Alternative zu den früheren 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Newsgroup&quot;&gt;Newsgroups&lt;/a&gt; und
&lt;a href=&quot;https://de.wikipedia.org/wiki/Internet_Relay_Chat&quot;&gt;IRC-Chats&lt;/a&gt;, die bis Anfang 
der 2000er verbreitet waren und danach versandeten.&lt;/p&gt;

&lt;p&gt;Auch hier kann jeder selbst einen Server aufsetzen und dann mit anderen
föderierten Servern in Kommunikation treten. 
Nutzen kann man die Chat-, Audio- und Videokonferenz-Dienste direkt im 
Webbrowser, doch mit Apps wie &lt;code&gt;Element&lt;/code&gt; erhält man am Smartphone wie auch
am Desktop eine angepasstere Oberfläche, die die Produktivität erhöht.&lt;/p&gt;

&lt;p&gt;Würde ich also mal einen Live-Support-Channel für irgendetwas aufsetzen 
wollen, wäre die Einrichtung eines eigenen Channels auf “matrix.org” oder 
auf einem &lt;a href=&quot;https://joinmatrix.org/servers/&quot;&gt;anderen Server&lt;/a&gt; meine Wahl.&lt;/p&gt;

&lt;p&gt;Ein kleines Problemchen sind die “kleinen” Server, die von Privatpersonen
eingerichtet werden, und manchmal nach einem Jahr wieder verschwinden.
Hier empfiehlt sich dann doch ein größerer Server, hinter dem eine 
Organisation steht, die nicht morgen gleich wieder verschwindet.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Das &lt;a href=&quot;https://de.wikipedia.org/wiki/Fediverse&quot;&gt;Fedi-verse&lt;/a&gt; löst hoffentlich 
mehr und mehr die fauligen Moloche wie Facebook, Twitter und Instagram ab.&lt;/p&gt;

&lt;p&gt;Man kann leider nicht ausschließen, dass auch in föderierten Netzen die 
Server “verderben” und abgeschaltet werden, doch dank des Protokollaufbaus, 
gibt es zumindest die Möglichkeit auf andere Server umzuziehen.&lt;br /&gt;
Bei kommerziellen Anbietern wird man garantiert keinen Umzugsdienst auf eine
Konkurrenzplattform finden und ist auf Gedeih und Verderb an einen Betreiber
gebunden.&lt;/p&gt;

&lt;p&gt;Und noch etwas zeichnet die “neu-entdeckten” Alternativen aus: Sie wollen
uns nicht (so intensiv) das Geld aus der Tasche ziehen. Soll heißen, Werbung
sieht man dort noch nicht. Ob das für immer so bleiben wird, steht in den
Sternen, aber aktuell bin ich von den Alternativen positiv beeindruckt.&lt;/p&gt;

&lt;p&gt;Mal sehen, ob ich auch mal einen selbstgeschriebenen 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Hypertext_Transfer_Protocol&quot;&gt;HTTP&lt;/a&gt; 
Request dort hin abschicke…&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>OpenGL als 2D Framebuffer</title>
   <link href="https://www.opengate.at/blog/2022/12/gl-framebuffer/"/>
   <published>2022-12-10T12:00:00+01:00</published>
   <updated>2022-12-10T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2022/12/gl-framebuffer</id>
   <category term="devel" />
   <summary type="text">
  Wie bekomme ich meine flachen Framebuffer jetzt auf’s 
Android Smartphone?


Antwort: Über OpenGL Texturen

</summary>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;Wie bekomme ich meine flachen Framebuffer jetzt auf’s 
Android Smartphone?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Antwort: Über &lt;a href=&quot;https://de.wikipedia.org/wiki/OpenGL&quot;&gt;OpenGL&lt;/a&gt; Texturen&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Der generische Framebuffer ist “die” Lösung im GATE Framework, um Bilder
plattformunabhängig überall anzeigen zu können. 
Dass das unter Windows über die WinAPI und auf Linux über die Xlib läuft,
ist nichts besonderes.&lt;/p&gt;

&lt;p&gt;Selbst für &lt;a href=&quot;https://de.wikipedia.org/wiki/MS-DOS&quot;&gt;DOS&lt;/a&gt; oder EFI, wo das Ganze
direkt in die Video-Hardware geschrieben wird, gibt es eine Implementierung.&lt;/p&gt;

&lt;p&gt;Nur &lt;a href=&quot;https://de.wikipedia.org/wiki/Android_(Betriebssystem)&quot;&gt;Android&lt;/a&gt; 
und UWP/&lt;a href=&quot;https://de.wikipedia.org/wiki/DirectX&quot;&gt;DirectX&lt;/a&gt; Apps 
fehlen mir noch.&lt;/p&gt;

&lt;p&gt;Doch an Android wird bereits gearbeitet.&lt;/p&gt;

&lt;h3 id=&quot;idee&quot;&gt;Idee&lt;/h3&gt;

&lt;p&gt;Wann immer der Framebuffer ein neues Bild erhält, wandelt er dieses in
OpenGL Texturen um und legt diese auf rechteckige GL Objekte, die im 
Vollbild angezeigt wird.&lt;/p&gt;

&lt;p&gt;Und tatsächlich funktioniert dieser Ansatz. Ich habe per &lt;code&gt;glOrtho()&lt;/code&gt; eine 2D 
Umgebung aufgesetzt und jedes rechteckige Teilbild wird als TRIANGLE_FAN an die 
richtige Stelle des Bildschirms gepackt.&lt;/p&gt;

&lt;p&gt;Ein bisschen Tricksen musste ich bei der Ereignisverwaltung, denn hier hatte 
ich für OpenGL eine gekapselte Eventloop vorgesehen, doch bei den Framebuffers
werden Ereignisse ge-poll-t und man muss die Eventloop selbst umsetzten.&lt;br /&gt;
Doch das lässt sich über Threads und Queues lösen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Die Grafik ist also mit ein bisschen Kopfrechnen machbar.&lt;/p&gt;

&lt;p&gt;Zugegeben, es nicht sehr effizient für einen OpenGL Host, wenn ich immer
alles per CPU in einen Framebuffer zeichne, diesen dann zerteile und in
Texturen umwandle und diese dann auf Flächen projiziert werden, aber
es funktioniert.&lt;/p&gt;

&lt;p&gt;Und hier geht es um best mögliche Kompatibilität und nicht um höchste
Performance.&lt;/p&gt;

&lt;p&gt;Mit diesem Ansatz ließe sich auch einige alte (gut designe-te) DOS Spiele 
für Android oder andere OpenGL-Systeme neu kompilieren, wenn man den 
Grafikspeicher als virtuellen Framebuffer ansieht und ähnlich auf eine 
neue Oberfläche abbildet.&lt;br /&gt;
Wäre mal interessant um wie viel besser das ist, als alles in einem 
Emulator laufen zu lassen.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>DirectX 11 für UWP</title>
   <link href="https://www.opengate.at/blog/2022/12/directx/"/>
   <published>2022-12-04T12:00:00+01:00</published>
   <updated>2022-12-04T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2022/12/directx</id>
   <category term="devel" />
   <summary type="text">
  O-M-G! Wenn ich mich verschätze, dann ordentlich!


Irgendwie glaubte ich, dass ich in ein paar Stunden die “paar Kernklassen”
von DirectX von 
C++ auf C manuell übersetzen 
zu können.

Schließlich wollte ich doch nur ein 
UWP Fenster 
mit einem Framebuffer erstellen lassen können …
</summary>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;O-M-G! Wenn ich mich verschätze, dann ordentlich!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Irgendwie glaubte ich, dass ich in ein paar Stunden die “paar Kernklassen”
von &lt;a href=&quot;https://de.wikipedia.org/wiki/DirectX&quot;&gt;DirectX&lt;/a&gt; von 
&lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B&quot;&gt;C++&lt;/a&gt; auf C manuell übersetzen 
zu können.&lt;/p&gt;

&lt;p&gt;Schließlich wollte ich doch nur ein 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Universal_Windows_Platform&quot;&gt;UWP&lt;/a&gt; Fenster 
mit einem Framebuffer erstellen lassen können …
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;So wie Mönche im Mittelalter die wenigen Bücher Seite für Seite und
Buchstabe für Buchstabe händisch abmalten, so investiere ich “gerne”
meine Freizeit in die Übersetzung von COM-Klassen von C++ nach C.&lt;/p&gt;

&lt;p&gt;Denn Microsofts generierter C++ Code ist nur 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_C%2B%2B&quot;&gt;MSVC&lt;/a&gt; treu, bringt aber andere
Compiler gerne zum Verzweifeln. Und nachdem Fingerübungen gut für
die Feinmotorik sind, weitete ich meine UWP-Spielchen auf DirectX aus.&lt;/p&gt;

&lt;h3 id=&quot;übersetzung-von-com-c-nach-c&quot;&gt;Übersetzung von COM C++ nach C&lt;/h3&gt;

&lt;p&gt;Ein in den Headern definiertes Interface, das z.B. so aussieht:&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;interface DECLARE_INTERFACE(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;12345678-abcd-1234-5678-1234567890ab&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;) 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;IMyClass : &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;public&lt;/span&gt; IUnknown
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;        STDMETHOD(MyFunc1)(DWORD param1) PURE;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;        STDMETHOD(MyFunc2)(INT param1, &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;* param2) PURE;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;};
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;wird in etwa so übersetzt:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;typedef&lt;/span&gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;struct&lt;/span&gt; IMyClass_interface IMyClass;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;typedef&lt;/span&gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;struct&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  wrt_result(WRT_ABI *QueryInterface)(IMyClass* This, wrt_iid &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt;* riid, &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;** ppvObject);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;  wrt_ulong(WRT_ABI *AddRef)(IMyClass* This);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  wrt_ulong(WRT_ABI *Release)(IMyClass* This);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;    
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;  wrt_result(WRT_ABI *MyFunc1)(IMyClass* This, wrt_dword param1);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  wrt_result(WRT_ABI *MyFunc2)(IMyClass* This, wrt_int param1, &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;* param2);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;} IMyClass_vtbl;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;struct&lt;/span&gt; IMyClass_interface
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;  IMyClass_vtbl &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt;* lpVtbl;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;};
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Dabei sind meine eigenen Datentypen wie &lt;code&gt;wrt_result&lt;/code&gt; oder &lt;code&gt;wrt_dword&lt;/code&gt; nur 
Hilfsmittel, um weniger Abhängigkeiten zu Microsoft Headern zu schaffen. Man
könnte auch die originalen &lt;code&gt;HRESULT&lt;/code&gt; oder &lt;code&gt;DWORD&lt;/code&gt; Typen nutzen.&lt;/p&gt;

&lt;h3 id=&quot;wieviele-klassen-hat-directx-&quot;&gt;Wieviele Klassen hat DirectX ?&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;Antwort: Fu**ing viele!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In den UWP DirectX Beispielen wird mit &lt;code&gt;D2D1Factory3&lt;/code&gt;, &lt;code&gt;DWriteFactory3&lt;/code&gt;,
&lt;code&gt;D3D11Device3&lt;/code&gt;, &lt;code&gt;D3D11DeviceContext3&lt;/code&gt; oder &lt;code&gt;DXGIDevice3&lt;/code&gt; gearbeitet.&lt;br /&gt;
Ich Naivling dachte: Das ist schnell erledigt … und stürzte mich ins 
Verderben.&lt;/p&gt;

&lt;p&gt;Denn die Zahl &lt;code&gt;3&lt;/code&gt; bedeutete schon mal, dass es ein &lt;code&gt;Original&lt;/code&gt;, ein 
&lt;code&gt;2&lt;/code&gt; und &lt;code&gt;3&lt;/code&gt; Interface zu jeder Klasse gab und nachdem schon teilweise 
das Original mit 20+ Methoden ausgestattet war, wurde der Spaß mit den 
höheren Interface Versionen nicht weniger.&lt;/p&gt;

&lt;p&gt;Doch am Schlimmsten war, dass jede der 20 Methoden ein neues Interface 
einführte, das mit einer Factory zu weiteren Instanzen führen konnte.&lt;/p&gt;

&lt;p&gt;Inzwischen habe ich 140 Klassen und mindestens genau so viele &lt;code&gt;struct&lt;/code&gt; 
und &lt;code&gt;enum&lt;/code&gt; Typen in mein “kleines” Projekt integriert und ich bin erst 
bei Interface &lt;code&gt;2&lt;/code&gt; angekommen. Die Methodenanzahl geht also schon weit über 
2000 hinaus, und ich habe bereits über 8000 Zeilen an übersetztem Code abgetippt.&lt;/p&gt;

&lt;p&gt;Dem gegenüber steht dann ein &lt;a href=&quot;https://de.wikipedia.org/wiki/OpenGL&quot;&gt;OpenGL&lt;/a&gt; 
1.1, wo ich mit einem Subset von 90 flachen C-Funktionen ganze 3D-Welten 
und 2D-Framebuffer umsetzen kann.&lt;/p&gt;

&lt;h3 id=&quot;lerneffekte&quot;&gt;Lerneffekte&lt;/h3&gt;

&lt;p&gt;Ein Hintergedanke von dieser “Fingerübung” stammt noch aus meiner Schulzeit:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Repetitio est mater studiorum.&lt;br /&gt;
Wiederholung ist der Mutter der Studien.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Denn beim Abtippen merkte ich erst, wie viele weitere Klassen (und damit 
Möglichkeiten) sich hinter DirectX versteckt. Und durch das wiederholte
Niederschreiben der Schnittstellennamen, ergibt sich teilweise ein gewisses
“Gefühl” für die Materie.&lt;/p&gt;

&lt;p&gt;Das hätte man vermutlich in einem guten Buch auch nachlesen können, doch 
wenn der Code durch die eigenen Hände geht, bleibt stets mehr hängen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ich bin noch nicht fertig und weiß auch noch gar nicht, ob meine Bemühungen
überhaupt fruchten werden. Denn erst mit allen vollständigen Schnittstellen
kann ich das erste Demoprogramm erstellen und versuchen es auszuführen.&lt;/p&gt;

&lt;p&gt;Ziel soll jedenfalls sein, dass eine beliebige Rastergrafik auf dem
Bildschirm erscheint und dass kein Microsoft-Header zum Einsatz kommen soll,
sondern dass nur COM-Aufrufe gegen die binäre Schnittstelle stattfinden.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Pokemon v9: Purpur</title>
   <link href="https://www.opengate.at/blog/2022/12/pokemon-9/"/>
   <published>2022-12-03T12:00:00+01:00</published>
   <updated>2022-12-03T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2022/12/pokemon-9</id>
   <category term="entertainment" />
   <summary type="text">Mit der Paldea Region ist 
Pokemon nun in der 9. 
Generation endgültig zum Open-World Rollenspiel geworden und zeigt, 
wie sich die 3D Grafik in den letzten Jahren verbessert hat.

Das unglaublichste ist aber, dass das Spiel jetzt seit 25 Jahren Bestand hat 
und die gleiche Idee immer wieder neu verpacken kann und dabei erfolgreich
bleibt.
</summary>
   <content type="html">&lt;p&gt;Mit der Paldea Region ist 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Pok%C3%A9mon&quot;&gt;Pokemon&lt;/a&gt; nun in der 9. 
Generation endgültig zum Open-World Rollenspiel geworden und zeigt, 
wie sich die 3D Grafik in den letzten Jahren verbessert hat.&lt;/p&gt;

&lt;p&gt;Das unglaublichste ist aber, dass das Spiel jetzt seit 25 Jahren Bestand hat 
und die gleiche Idee immer wieder neu verpacken kann und dabei erfolgreich
bleibt.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Ich habe mir Pokemon Purpur zugelegt (oder wie es im 
&lt;a href=&quot;https://miauzgenau.de/&quot;&gt;Miauz-Genau Podcast&lt;/a&gt; bezeichnet wurde: Purr-Purr)
und fühle mich (für kurze Zeit) wieder wie ein Kind.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/pokemon-9-a.jpg&quot; alt=&quot;Pokemon 9 Intro&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;back-to-school&quot;&gt;Back to school&lt;/h3&gt;

&lt;p&gt;Seit den ersten Spielen auf dem 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Game_Boy&quot;&gt;Gameboy&lt;/a&gt; findet man am Anfang des
Spieles meist eine Schule vor, in der “Pokemon unterrichtet wird”. 
So lernt der Anfänger ein paar Details, wie Typen und Attackenvorteile.&lt;/p&gt;

&lt;p&gt;Doch in der neuesten Generation ist man als 10-jähriger Student auf der
Akademie eingeschrieben, und das gesamte Spiel dreht sich sprichwörtlich
um diese, die Professoren und die anderen Studenten.&lt;/p&gt;

&lt;p&gt;So viel “Schule” gab es zuletzt in 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Final_Fantasy_VIII&quot;&gt;Final Fantasy VIII&lt;/a&gt; 
in einem Spiel, was für mich als “sehr-sehr-fortgeschrittener Teenager” etwas
befremdlich wirkt, für die eigentliche Zielgruppe aber gut passen dürfte.&lt;br /&gt;
Nur die Streber-Schuluniform ist aber definitiv zu viel des Guten, 
wie ich finde.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/pokemon-9-c.jpg&quot; alt=&quot;Pokemon trainer&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;spielverlauf&quot;&gt;Spielverlauf&lt;/h3&gt;

&lt;p&gt;Die Kämpfe sehen in etwa so aus, wie sie schon in Schwert/Schild und der
Neuadaption von Diamant/Perle eingeführt wurden.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/pokemon-9-b.jpg&quot; alt=&quot;Pokemon fight&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Interessant ist die neue Art der Fortbewegung und die wirklich schön 
designete Landschaft auf der Inselwelt Paldea.&lt;br /&gt;
Denn gleich am Anfang erhält man das legendäre aber geschwächte Pokemon 
&lt;a href=&quot;https://www.pokewiki.de/Miraidon&quot;&gt;Miraidon&lt;/a&gt;, welches im Laufe der Story 
stärker wird. Am Anfang reiten wir damit über die Felder (obwohl es eher
der Fahrt auf einem Motorrad gleicht). Sobald es springen kann, werden vorher
unerreichbare Anhöhen erreichbar.
Wenn es Schwimmen kann, können die umgebenden kleinen Inselchen besucht
werden, und am Ende kann es sich auch senkrecht an Bergen hinauf
“hochkrallen”, von denen man auch wieder durch die Lüfte 
“hinunter segeln” kann.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/pokemon-9-d.jpg&quot; alt=&quot;Pokemon Paldea&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Da bekommt man echt Lust stundenlang herumzulaufen, denn alle 100 Meter
liegen Items verstreut herum, die es einzusammeln gilt.&lt;/p&gt;

&lt;p&gt;Und es wäre nicht Pokemon, gäbe es nicht wieder hoch emotionale 
Freundschaftsbekundungen, die wie immer &lt;em&gt;niedlichst&lt;/em&gt; abgeschlossen werden.
Das regelmäßige Picknick mit seinen Lieblingspokemon gehört natürlich
auch dazu.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/pokemon-9-e.jpg&quot; alt=&quot;Pokemon Miraidon&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Gab es früher einen festgelegten Weg, den der Trainer einhalten musste, 
so kann man diesmal die Insel einmal umrunden und an den Kampfstätten 
unbeschadet vorbeilaufen. Das bringt einen dann gerne auch mal in Gebiete,
in denen die Gegner viel zu stark für einen sind und man quasi jedem 
ausweichen muss.&lt;/p&gt;

&lt;p&gt;Das Hauptspiel hat 3 Zielsetzungen, die man völlig frei angehen kann:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Wie immer 8 Arenakämpfe um in der Pokemonliga antreten zu dürfen.&lt;/li&gt;
  &lt;li&gt;Kämpfe in 5 Team-Star-Verstecken, in denen rebellische Schüler den
Unterricht schwänzen.&lt;/li&gt;
  &lt;li&gt;Sieg gegen 5 Herrscher-Pokemon, wodurch unser Reittier stärker wird.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Hat man das alles durch, öffnet sich der Weg zur Zone-Null, dem tiefen
Schlund im Zentrum der neuen Region, wo man die Hauptstory abschließen
kann.&lt;/p&gt;

&lt;h3 id=&quot;bewertung&quot;&gt;Bewertung&lt;/h3&gt;

&lt;p&gt;Ich sage mal: &lt;strong&gt;Daumen hoch&lt;/strong&gt;.&lt;br /&gt;
Anfangs war mir die Welt zu groß und alleine der Weg zum nächsten 
Pokemoncenter kam mir unnötig lange vor. Doch die schön gestaltete Landschaft
schuf mit ihrem Realismus dann das Bedürfnis, hinter jeden Hügel blicken zu 
wollen, und dann gefiel es mir immer besser.&lt;/p&gt;

&lt;p&gt;Technisch muss ich leider sagen, ist Pokemon im Jahr 2022 verspätet 
dort angekommen, wo ein 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Xenoblade_Chronicles_2&quot;&gt;Xenoblade Chronicles 2&lt;/a&gt;
schon im Jahr 2017 war. Wirklich neu war die Grafik für mich also nicht.&lt;/p&gt;

&lt;p&gt;Auch die freie Wahl der Spielziele war anfangs ungewohnt für mich und mir
sogar zu komplex. Denn bei älteren Spielen waren Dialoge unwichtig, weshalb
ich sie selten las und ignorierte, schließlich konnte man sowieso nur in eine
Richtung weitergehen.&lt;/p&gt;

&lt;p&gt;In Pokemon Karmesin und Purpur hingegen lernt man einige Personen kennen, die
einem Dinge erzählen, die man sich schon merken sollte, wenn man weiterkommen
will … oder man liest die Schummelzettel auf diversen Pokemonseiten, wenn
man sich nicht mehr zurecht findet.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ich merke, dass ich älter werde und nicht mehr die gleiche kindliche 
Begeisterung habe, wie damals vor über 20 Jahren … aber dieses Spiel schafft
es trotzdem immer wieder, dass ich am Ende sage:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ich hätte etwas verpasst, wenn ich es ausgelassen hätte.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Und so habe ich auch die 9. Generation mit inzwischen 1008 Pokemon in mein
Herz geschlossen, von denen 400 innerhalb der Edition fangbar sind.&lt;/p&gt;

&lt;p&gt;Den Online-Teil habe ich vorerst weggelassen, denn Nintendo will dafür
wieder eine Jahresmitgliedschaft abkassieren … aber das mache ich 
vielleicht nächstes Jahr. Alle 1000 Tierchen werde ich vermutlich nicht
mehr einfangen/eintauschen können.&lt;br /&gt;
Und das ist vermutlich der einzige Kritikpunkt:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Es ist einfach viel zu viel für mich.&lt;br /&gt;
Diese Aufgabe muss die junge Generation erledigen.&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>Client-Certificates</title>
   <link href="https://www.opengate.at/blog/2022/11/client-certificates/"/>
   <published>2022-11-27T12:00:00+01:00</published>
   <updated>2022-11-27T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2022/11/client-certificates</id>
   <category term="software" />
   <summary type="text">Für gewöhnlich möchten im Web nur die Clients (also unsere Browser) wissen,
ob sie auch mit der richtigen Gegenseite reden, folglich stellen nur Server ihre Zertifikate zur Einsicht bereit.

Doch wenn es um Sicherheit geht, dann muss auch der Server wissen, ob seine
Clients “die richtigen” sind. Genau hier kommen Client-Zertifikate ins Spiel.

</summary>
   <content type="html">&lt;p&gt;Für gewöhnlich möchten im Web nur die Clients (also unsere Browser) wissen,
ob sie auch mit der richtigen Gegenseite reden, folglich stellen nur Server ihre Zertifikate zur Einsicht bereit.&lt;/p&gt;

&lt;p&gt;Doch wenn es um Sicherheit geht, dann muss auch der Server wissen, ob seine
Clients “die richtigen” sind. Genau hier kommen Client-Zertifikate ins Spiel.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;wiederholungsstunde-zertifiakte&quot;&gt;Wiederholungsstunde: Zertifiakte&lt;/h3&gt;

&lt;p&gt;Beim üblichen TLS Handshake schickt der Server den öffentlichen Teil seines
Zertifikats an den Client und der kann es dann verifizieren oder ignorieren.
Das geschieht über die Liste der “vertrauenswürdigen” Zertifikate, die 
entweder im Betriebssystem oder in der Anwendung selbst hinterlegt sind.&lt;/p&gt;

&lt;p&gt;Zertifikate können bekanntlich untereinander verknüpft sein und deshalb 
existieren “Stamm-Zertifikate” (Root Certificates), die überall bekannt sein
sollten, und für jede Anwendung oder Domäne eigene Zertifikate, die mit
bestimmten Stamm-Zertifikaten signiert wurden.&lt;/p&gt;

&lt;p&gt;Der Client hat also entweder das empfange Zertifikat bereits als “sicher”
in seiner Datenbank, oder er erkennt das Stammzertifikat als korrekt an.&lt;/p&gt;

&lt;p&gt;Bei Webanwendungen und HTTPS gibt es noch ein Kriterium: Es muss nämlich 
auch der im Zertifikat enthaltene “Name” korrekt sein.&lt;br /&gt;
Wenn man also “https://opengate.at” aufruft, muss das Zertifikat als
“vertraut” (trustet) gelten, und außerdem muss das Zertifikat auch den
Namen “opengate.at” beinhalten.&lt;/p&gt;

&lt;p&gt;Passt das nicht, wird die Verbindung abgelehnt, außer man zwingt den
Browser, Zertifikatsfehler zu ignorieren.&lt;/p&gt;

&lt;h3 id=&quot;client-zertifikate&quot;&gt;Client Zertifikate&lt;/h3&gt;

&lt;p&gt;Bei Client-Zertifikaten entscheidet der Server, …&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;ob ihn diese gar nicht interessieren.&lt;/li&gt;
  &lt;li&gt;ob sie optional mitgeschickt werden dürfen.&lt;/li&gt;
  &lt;li&gt;ob sie zwingend erforderlich sind.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Der Client kann bzw. muss dann sein Zertifikat an den Server senden,
und dieser leitet dann die gleiche Prozedur ein, die ansonsten auch der
Client anwendet:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Prüfung, ob das Zertifikat oder sein “Stamm” vertrauenswürdig sind&lt;/li&gt;
  &lt;li&gt;Prüfung, ob der übermittelte Name auch korrekt ist.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;problem-namensprüfung&quot;&gt;Problem: Namensprüfung&lt;/h4&gt;

&lt;p&gt;Perfekt funktioniert das nur in einem perfekten Adress- bzw. Namensraum.
In einem Active-Directory hätten alle Server und Clients einen im DNS 
registrierten Hostnamen, womit auch für jeden Client ein Zertifikat mit 
diesem Namen ausgestellt werden kann.&lt;/p&gt;

&lt;p&gt;In IOT Netzen sieht das aber leider ganz anders aus. Oft werden die 
Clients dort per IP-Adresse konfiguriert und DNS vollkommen ausgespart.
Natürlich kann ein Zertifikat auch auf einen IP-Adresse lauten … doch
das geht dann nur, wenn diese statisch ist.&lt;br /&gt;
Wenn aber die Clients per DHCP bei jedem Start eine neue IP erhalten,
müssten sie auch ein neues Zertifikat ausgerollt bekommen, denn der
Server würde dann nur die IP des Clients erkennen und keinen Namen
ableiten können.&lt;/p&gt;

&lt;p&gt;Genau dieses Problem stellt aktuell viele Bereiche vor Probleme.
Denn einerseits verlangen immer mehr Endkunden erhöhte Sicherheit mit 
Zertifikaten, andererseits sind zumindest Clientzertifikate nicht in 
allen Bereichen einsetzbar.&lt;/p&gt;

&lt;h3 id=&quot;zertifikate-anlegen&quot;&gt;Zertifikate anlegen&lt;/h3&gt;

&lt;p&gt;Wer keine fertige Zertifikatsinfrastruktur zur Verfügung hat, dem bleibt dann
nur der Griff zum &lt;code&gt;openssl&lt;/code&gt; Tool, um selbst-signierte Zertifikate anzulegen.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Erzeugung eines Stamm-Zertifikats (Certificate Authority)
    &lt;ul&gt;
      &lt;li&gt;&lt;code&gt;openssl req -x509 -sha256 -days 3650 -nodes -newkey rsa:2048 -subj &quot;/C=AT/L=Vienna/O=OpenGATE/OU=Carbis&quot; -keyout ca-key.pem -out ca.pem&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;Wir erhalten die Datei &lt;code&gt;ca-key.pem&lt;/code&gt; und &lt;code&gt;ca.pem&lt;/code&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Erzeugung eines Signier-Anfrage für ein neues Zertifikats
    &lt;ul&gt;
      &lt;li&gt;&lt;code&gt;openssl req -newkey rsa:2048 -days 3650 -nodes -subj &quot;/C=AT/L=Vienna/O=OpenGATE/OU=Carbis/CN=127.0.0.1/emailAddress=admin@example.com&quot; -keyout cert-key.pem -out request.csr&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;Erzeugt &lt;code&gt;cert-key.pem&lt;/code&gt; mit dem Schlüssel und &lt;code&gt;request.csr&lt;/code&gt; für die Signieranfrage&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Signiert und erstellt ein neues Zertifikat:
    &lt;ul&gt;
      &lt;li&gt;&lt;code&gt;openssl x509 -req -in request.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -days 3650 -sha256 -out cert.pem&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;Erzeugt &lt;code&gt;cert.pem&lt;/code&gt; mit dem per CA signiertem Zertifikat.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Erzeugung eines Zertifikates ohne CA Signatur
    &lt;ul&gt;
      &lt;li&gt;&lt;code&gt;openssl req -new -x509 -days 3650 -nodes -subj &quot;/C=AT/L=Vienna/O=OpenGATE/OU=Carbis/CN=127.0.0.1/emailAddress=admin@example.com&quot; -keyout cert-key.pem -out cert.pem&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;Erzeugt &lt;code&gt;cert-key.pem&lt;/code&gt; mit dem privaten Schlüssel und &lt;code&gt;cert.pem&lt;/code&gt; mit dem Zertifikat.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nun kann man am Server entweder das Stammzertifikat (CA) als vertrauenswürdig 
hinzufügen, womit alle Zertifikate, die damit signiert wurden auch 
vertrauenswürdig sind (&lt;code&gt;ca.pem&lt;/code&gt;).&lt;br /&gt;
Oder man fügt jedes einzelne Zertifikat dem Server als vertrauenswürdig hinzu 
(also die &lt;code&gt;cert.pem&lt;/code&gt; Varianten).&lt;/p&gt;

&lt;p&gt;Die Clients selbst nutzen dann den privaten Schlüssel (&lt;code&gt;cert-key.pem&lt;/code&gt;) um die 
Kommunikationsdaten zu signieren und der Server kann die Signatur über sein(e)
Zertifikat(e) bestätigen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Zertifikate waren für mich immer “kompliziert”, weil meistens etwas nicht 
richtig funktioniert hatte.&lt;br /&gt;
Doch meist lag es an falschen Hostnamen oder anderen Konfigurationsfehlern.&lt;/p&gt;

&lt;p&gt;Inzwischen freue ich mich, dass ich zumindest die Grundbegriffe von 
verschlüsselter Kommunikation auch selbst nachimplementieren kann.&lt;br /&gt;
&lt;code&gt;openssl&lt;/code&gt; ist hierfür ein mächtiges und gleichsam nützliches Werkzeug.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>REST - Representational State Transfer</title>
   <link href="https://www.opengate.at/blog/2022/11/rest/"/>
   <published>2022-11-26T12:00:00+01:00</published>
   <updated>2022-11-26T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2022/11/rest</id>
   <category term="devel" /><category term="software" />
   <summary type="text">Das witzige ist:


  Jeder braucht heute eine 
REST 
Schnittstelle, doch leider versteht jeder etwas anderes darunter.


Und das macht mich REST-los unglücklich.
</summary>
   <content type="html">&lt;p&gt;Das witzige ist:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Jeder braucht heute eine 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Representational_State_Transfer&quot;&gt;REST&lt;/a&gt; 
Schnittstelle, doch leider versteht jeder etwas anderes darunter.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Und das macht mich REST-los unglücklich.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Der Stil der 70er Jahre ist leider auch heute noch weit verbreitet:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Globale Variablen&lt;/li&gt;
  &lt;li&gt;Singletons&lt;/li&gt;
  &lt;li&gt;Hart kodierte Pfade&lt;/li&gt;
  &lt;li&gt;Funktionen mit versteckte Zuständen (wie z.B. &lt;code&gt;strtok()&lt;/code&gt;)&lt;/li&gt;
  &lt;li&gt;und vieles mehr.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Und als Netzwerke, das Internet und das Web aufkamen, übersetzte man diese
“Denkfehler” teils 1:1 in das neue Medium.&lt;/p&gt;

&lt;p&gt;Doch im Netz sind solche Konstrukte viel störungsanfälliger, 
als im lokalen Prozess auf meiner Maschine.&lt;/p&gt;

&lt;h3 id=&quot;exakte-adressierung&quot;&gt;Exakte Adressierung&lt;/h3&gt;

&lt;p&gt;Ein Dienst wird gerne mit einem &lt;code&gt;start()&lt;/code&gt; begonnen und mit einem &lt;code&gt;stop()&lt;/code&gt; zum
Beenden gebracht. Das implementiert man auch gerne genau so, mit einem
globalen &lt;code&gt;start()&lt;/code&gt; und &lt;code&gt;stop()&lt;/code&gt; und verlässt sich dann darauf, dass es genau 
einen Anwender gibt, der “genau weiß”, wann er etwas starten und wieder 
stoppen will.&lt;/p&gt;

&lt;p&gt;Wenn aber ein zweiter Akteur auftritt, der zuerst &lt;code&gt;stop()&lt;/code&gt; und dann &lt;code&gt;start()&lt;/code&gt; 
durchführt, nachdem der erste nur &lt;code&gt;start()&lt;/code&gt;en wollte, ist dann das finale
&lt;code&gt;stop()&lt;/code&gt; des ersten genau das, was er wollte? Denn er stoppt nicht das,
was er gestartet hatte, sondern etwas, was ein anderer begonnen hatte.&lt;/p&gt;

&lt;p&gt;Solche Seiteneffekte sollten durch REST abgeschafft werden, und eine 
aktualisierte API kann dann z.B. so aussehen:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;start(my_token)&lt;/code&gt; und &lt;code&gt;stop(my_token)&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;stop_token = start()&lt;/code&gt; und &lt;code&gt;stop(stop_token)&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Oder wie man es in HTTP-Request ausdrücken könnte:
    &lt;ul&gt;
      &lt;li&gt;&lt;code&gt;POST /service/my_token&lt;/code&gt; und &lt;code&gt;DELTE /service/my_token&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;&lt;code&gt;my_token:= POST /service/new&lt;/code&gt; und &lt;code&gt;DELETE /service/my_token&lt;/code&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;rest--http--http--rest&quot;&gt;(REST != HTTP) &amp;amp;&amp;amp; (HTTP != REST)&lt;/h3&gt;

&lt;p&gt;Viele Leute glauben, REST wäre bereits der Einsatz von &lt;code&gt;GET&lt;/code&gt;, &lt;code&gt;POST&lt;/code&gt;, 
&lt;code&gt;PUT&lt;/code&gt; und &lt;code&gt;DELETE&lt;/code&gt; und jede HTTP-URL wäre bereits eine REST-Schnittstelle.&lt;br /&gt;
… Ähm: Nein!&lt;/p&gt;

&lt;p&gt;Es kommt darauf an, dass man das, was man auslöst, so parametrisiert, dass
im Idealfall keine der beiden Seiten sich merken muss, was die Gegenseite
schon getan hat.&lt;br /&gt;
Oder anders gesagt: Es müssen alle notwendigen Daten hin- und zurückübertragen
werden.&lt;/p&gt;

&lt;p&gt;Das geht auch dann, wenn man z.B. nur per &lt;code&gt;POST&lt;/code&gt; über HTTP kommuniziert und
z.B.: &lt;a href=&quot;https://de.wikipedia.org/wiki/XML-RPC&quot;&gt;XML-RPC&lt;/a&gt;, 
&lt;a href=&quot;https://de.wikipedia.org/wiki/JavaScript_Object_Notation&quot;&gt;JSON&lt;/a&gt; oder 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Protocol_Buffers&quot;&gt;Protobuf&lt;/a&gt; 
Objekte überträgt.&lt;br /&gt;
Wichtig ist vor allem, dass der Inhalt der Objekte vollständig ist und keine
Seiteneffekte durch gespeicherte Zustände auftreten können.&lt;/p&gt;

&lt;p&gt;Der Einsatz von HTTP Methoden macht Aufrufe allerdings “schön” lesbar und 
kann auch leicht in Funktionsaufrufe übersetzt werden:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;HTTP-REST&lt;/th&gt;
      &lt;th&gt;Pseudo-Funktion&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;GET /service/data_file&lt;/td&gt;
      &lt;td&gt;service.ReadContent(data_file)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;POST /service/new_data_file&lt;/td&gt;
      &lt;td&gt;service.AddContent(new_data_file, content)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;PUT /service/data_file&lt;/td&gt;
      &lt;td&gt;service.WriteContent(data_file, content)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;DELETE /service/data_file&lt;/td&gt;
      &lt;td&gt;service.DeleteContent(data_file)&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;(Und wer REST wirklich ernst nimmt, der nutzt natürlich die URL &lt;code&gt;/service/service_id/data_file&lt;/code&gt;)&lt;/p&gt;

&lt;h3 id=&quot;versionierung&quot;&gt;Versionierung&lt;/h3&gt;

&lt;p&gt;APIs brauchen Versionen, weil sie sich immer weiterentwickeln und der übliche
HTTP-REST-Weg ist, die Version in der URL als Teil des Pfades anzugeben, z.B.:&lt;br /&gt;
&lt;code&gt;/v1/service/something&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Doch wie genau man das macht, ist nicht vorgeschrieben. Und das führt auch 
leider zu manch seltsamen Erscheinungen.
Erst neulich musste ich so etwas in meiner Firma entdecken:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Endpoint: &lt;code&gt;POST /service/process&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;Protobuf content message can be v1 or v2&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Endpoint: &lt;code&gt;GET /service/is-v2&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;200 OK: v2 Protobuf messages in &lt;code&gt;/service&lt;/code&gt; enabled&lt;/li&gt;
      &lt;li&gt;Else: &lt;code&gt;/service&lt;/code&gt; must use v1 Protobuf messages.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Naja … hier sehe ich eindeutig, dass jene Kollegen ein anderes
Verständnis von REST haben, als ich.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ich kann nur allen Entwicklern anraten, sich die APIs der großen Hersteller im
Web anzusehen, wie die ihre Schnittstellen aufgebaut haben. Da ist sicher
nicht alles perfekt, aber da wurde schon eher auf Konsistenz geachtet.&lt;/p&gt;

&lt;p&gt;Das Problem sind die unzähligen Firmen und Konzerne, die intern ihr eigenes
Süppchen kochen, das nicht ins Netz gelangt und daher nie “ordentlich”
durchgedacht wurde.&lt;/p&gt;

&lt;p&gt;Die Meinung, “irgend einen HTTP Endpoint könne man mit REST gleichsetzen”, 
ist falsch und dennoch weit verbreitet, und produziert umgebungs-ignorante 
Schnittstellen die schwer zu warten sind, weil sie keinem logischen Muster 
folgen.&lt;/p&gt;

&lt;p&gt;Und das größte Problem ist, dass auch in neuen Produkten diese falschen 
Ansätze immer weiter verschleppt werden.&lt;br /&gt;
Es liegt also noch viel Arbeit vor mir bzw. vor uns, damit solche 
Legacy-Schnittstellen möglichst bald durch “echtes REST” abgelöst werden.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Also: Auf ans Werk!&lt;/strong&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>ShFileOperation vs RemoveDirectory und DeleteFile</title>
   <link href="https://www.opengate.at/blog/2022/11/shfileoperation/"/>
   <published>2022-11-20T12:00:00+01:00</published>
   <updated>2022-11-20T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2022/11/shfileoperation</id>
   <category term="devel" />
   <summary type="text">Ein weiterer halb-zerstörter windowsfilters 
Docker Fall hat mir 
aufgezeigt, dass APIs wie RemoveDirectory() und DeleteFile() entgegen
allen Erwartungen nicht funktionieren.

Doch der Windows Explorer schafft die Löschungen problemlos. 
Und dafür gibt es eine Erklärung: Er nutzt die Shell-APIs.
</summary>
   <content type="html">&lt;p&gt;Ein weiterer halb-zerstörter &lt;code&gt;windowsfilters&lt;/code&gt; 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Docker_(Software)&quot;&gt;Docker&lt;/a&gt; Fall hat mir 
aufgezeigt, dass APIs wie &lt;code&gt;RemoveDirectory()&lt;/code&gt; und &lt;code&gt;DeleteFile()&lt;/code&gt; entgegen
allen Erwartungen nicht funktionieren.&lt;/p&gt;

&lt;p&gt;Doch der Windows Explorer schafft die Löschungen problemlos. 
Und dafür gibt es eine Erklärung: Er nutzt die Shell-APIs.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;vorgeschichte&quot;&gt;Vorgeschichte&lt;/h3&gt;

&lt;p&gt;Windows unterscheidet sich in einem Punkt sehr von anderen Systemen, weil es
nämlich den Aufbau seiner “Shell” als Funktionsschnittstelle offenlegt.&lt;/p&gt;

&lt;p&gt;Unter Unix/Linux ist “die Shell” lediglich ein Konsolenverwalter wie
&lt;code&gt;bin/ksh&lt;/code&gt; oder &lt;code&gt;bin/bash&lt;/code&gt;, der über Befehle Prozesse starten und
verknüpfen lässt.&lt;/p&gt;

&lt;p&gt;Doch in Windows wurde eine “benutzerfreundlichere” Verwaltungsebene erdacht,
und diese ist in &lt;code&gt;shell32.dll&lt;/code&gt; implementiert und ein &lt;code&gt;explorer.exe&lt;/code&gt; zeigt sie
uns grafisch an, angefangen bei jeder Dateiauflistung, bis hin zur Vorschau
von Webinhalten.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;shell32.dll&lt;/code&gt; sieht auch das Dateisystem anders, während die &lt;code&gt;kernel32&lt;/code&gt; 
APIs bei Laufwerken und NT-Root-Pfaden die Hierarchie aufbauen, führt die
Shell-API virtuelle Namensräume, wie den “Computer” und den “Desktop” ein,
auf dem dann die Laufwerke liegen.&lt;/p&gt;

&lt;p&gt;Und das führt dazu, dass viele nativen APIs von &lt;code&gt;kernel32&lt;/code&gt; in irgend einer
ähnlichen Form auch in der Shell abgebildet sind, allerdings ein bisschen
mehr und etwas andere Pfade verstehen.&lt;br /&gt;
Und bisher dachte ich, dass die Shell-API nur ihre virtuellen Spielchen in
native Pfade übersetzt und im Hintergrund dann die &lt;code&gt;kernel32&lt;/code&gt; APIs bedient.&lt;/p&gt;

&lt;h3 id=&quot;removedirectory-mit-access-denied&quot;&gt;RemoveDirectory mit Access Denied&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;RemoveDirectory()&lt;/code&gt; kann Links (SymLinks, Junctions) löschen und tut das auch
brav. Doch bei meinen &lt;code&gt;windowsfilters&lt;/code&gt; Löschversuchen scheiterten meine 
Aufrufe, wie auch der &lt;code&gt;cmd&lt;/code&gt; Befehl &lt;code&gt;rmdir&lt;/code&gt; mit einem Access-Denied, das 
keinen Sinn machte. Die erforderlichen Rechte waren vorhanden und kein 
Prozess sperrte den Verzeichnispfad.&lt;/p&gt;

&lt;p&gt;Doch wenn man diesen verlinkten Ordner im Explorer zur Löschung auswählte,
verschwand dieser auch prompt.&lt;/p&gt;

&lt;p&gt;Nach einigem Suchen fand ich Beiträge, die meine Beobachtungen bestätigten:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Bestimmte Links zu Shell-UI-Ordnern erhalten einen besonderen Schutz durch
die &lt;code&gt;kernel&lt;/code&gt; APIs. Diese können bzw. dürfen nicht gelöscht werden.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Das sind &lt;code&gt;Dokumente&lt;/code&gt;, &lt;code&gt;Musik&lt;/code&gt;, &lt;code&gt;Videos&lt;/code&gt; … und wie sie sonst noch 
alle heißen.&lt;/p&gt;

&lt;p&gt;Man kann sie auch nicht von &lt;code&gt;cmd&lt;/code&gt; aus mit &lt;code&gt;rmdir&lt;/code&gt; oder &lt;code&gt;del&lt;/code&gt; löschen, doch der
Explorer schafft es stets ohne Probleme.&lt;/p&gt;

&lt;h3 id=&quot;shfileoperation-löst-das-problem&quot;&gt;&lt;code&gt;ShFileOperation&lt;/code&gt; löst das Problem&lt;/h3&gt;

&lt;p&gt;Wirft man aber solche “störrischen” Pfade der API 
&lt;a href=&quot;https://learn.microsoft.com/en-us/windows/win32/api/shellapi/nf-shellapi-shfileoperationw&quot;&gt;SHFileOperation&lt;/a&gt;
mit &lt;code&gt;SHFILEOPSTRUCT::wFunc = FO_DELETE&lt;/code&gt; vor die Füße, verschwinden die Links
genau so wortlos, wie sie es im Explorer tun.&lt;/p&gt;

&lt;p&gt;Die Funktion, bzw. die &lt;code&gt;SHFILEOPSTRUCT&lt;/code&gt; Struktur hat nur ein paar 
Besonderheiten bei den Pfaden: Diese müssen doppelt-null-terminiert sein, 
weil in einem Parameter mehrere null-terminierte Dateipfade vorkommen dürfen.&lt;/p&gt;

&lt;p&gt;Deshalb muss &lt;code&gt;SHFILEOPSTRUCT::pFrom = &quot;path/to/link\0\0&quot;&lt;/code&gt; derart gesetzt sein.&lt;/p&gt;

&lt;p&gt;Und weil ich keine UI-Interaktionen möchte, ist auch noch&lt;br /&gt;
&lt;code&gt;fFlags = FOF_NO_UI&lt;/code&gt; notwendig.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ich habe also die WinAPI-Implementierung im GATE-Framework angepasst und den
&lt;code&gt;RemoveDirectory()&lt;/code&gt; und &lt;code&gt;DeleteFile()&lt;/code&gt; Aufrufen einen Sonderfall angefügt:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Wenn der Primäraufruf fehlschlägt, wird &lt;code&gt;ShFileOperation()&lt;/code&gt; probiert.
Ist es ebenso nicht erfolgreich, wird der Fehler des Primäraufrufes
weiterbehandelt.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Mit diesem Patch konnte ich nahezu vollständig die Verzeichnisse einer 
weiteren versauten &lt;code&gt;windowsfilters&lt;/code&gt; Installation löschen, ohne dass auf dem
Server Probleme auftraten, weil Dateien am Hostsystem mitgelöscht wurden.&lt;/p&gt;

&lt;p&gt;Aber seltsam ist das schon!&lt;br /&gt;
Dass ausgerechnet die &lt;code&gt;kernel&lt;/code&gt; API von etwas abgelenkt wird, was die Shell-API
problemlos hinbekommt, ist für mich eine verkehrte Welt.&lt;br /&gt;
Denn meine Erwartungshaltung ist, dass Shell-APIs ein paar geheime Schützlinge
haben darf, die sie nicht löscht, dass aber die &lt;code&gt;kernel&lt;/code&gt; APIs alles dürfen.&lt;/p&gt;

&lt;p&gt;However … Gefahr erkannt, Gefahr gebannt.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>/e/OS upgrade am SONY Xperia XA2</title>
   <link href="https://www.opengate.at/blog/2022/11/eos/"/>
   <published>2022-11-19T12:00:00+01:00</published>
   <updated>2022-11-19T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2022/11/eos</id>
   <category term="hardware" /><category term="software" />
   <summary type="text">Ich und Android …
ein Buchbeispiel für puren Hass.
Und deshalb lag mein (mir vom Mobilbetreiber aufgedrängtes) Sony Xperia 
von 2018 bis heute unbenutzt in der Lade, nur gelegentliche 
APK Tests machte ich darauf.

Doch es gibt eine ent-google-te Android-Variante, die meine Abneigung
zumindest verringern könnte: nämlich 
/e/OS
</summary>
   <content type="html">&lt;p&gt;Ich und &lt;a href=&quot;https://de.wikipedia.org/wiki/Android_(Betriebssystem)&quot;&gt;Android&lt;/a&gt; …
ein Buchbeispiel für puren Hass.&lt;br /&gt;
Und deshalb lag mein (mir vom Mobilbetreiber aufgedrängtes) Sony Xperia 
von 2018 bis heute unbenutzt in der Lade, nur gelegentliche 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Apk_(Dateiformat)&quot;&gt;APK&lt;/a&gt; Tests machte ich darauf.&lt;/p&gt;

&lt;p&gt;Doch es gibt eine ent-google-te Android-Variante, die meine Abneigung
zumindest verringern könnte: nämlich 
&lt;a href=&quot;https://de.wikipedia.org/wiki//e/OS&quot;&gt;/e/OS&lt;/a&gt;
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;code&gt;/e/OS&lt;/code&gt; ist ein auf dem &lt;a href=&quot;https://de.wikipedia.org/wiki/LineageOS&quot;&gt;LineageOS&lt;/a&gt;
Projekt basiertes Android Betriebssystem, aus dem alle Google-Dienste 
entfernt wurden und die meist durch OpenSource-Alternativen ersetzt werden.&lt;/p&gt;

&lt;p&gt;Das alleine reicht mir, das Projekt zu mögen, doch &lt;code&gt;/e/OS&lt;/code&gt; kann noch einen
weiteren Pluspunkt verbuchen: Es wird (als OpenSource Projekt) stets
erweitert und bietet Support für die neuesten Versionen von Android.&lt;/p&gt;

&lt;p&gt;Mein altes SONY Xperia XA2 kam mit Android 8 auf dem Markt und konnte
dann über die SONY App auf Android 9 aktualisiert werden, doch dann lief
der Support aus und das Gerät verharrte auf dem heute veralteten Stand.&lt;/p&gt;

&lt;p&gt;Mit &lt;code&gt;/e/OS&lt;/code&gt; liegt für dieses Smartphone eine Android 11 Version vor und eine
stabile v12 kommt vielleicht auch bald ins Netz.&lt;/p&gt;

&lt;p&gt;Nicht für jede Smartphone Marke ist ein Stabiles &lt;code&gt;/e/OS&lt;/code&gt; Image verfügbar, 
doch ich hatte Glück und konnte mein Gerät auf der Seite
&lt;a href=&quot;https://doc.e.foundation/devices&quot;&gt;doc.e.foundation/devices&lt;/a&gt; finden.&lt;/p&gt;

&lt;h3 id=&quot;neues-betriebssystem-auf-smartphone-installieren&quot;&gt;Neues Betriebssystem auf Smartphone installieren&lt;/h3&gt;

&lt;p&gt;Man könnte sagen, unter 
&lt;a href=&quot;https://doc.e.foundation/devices/pioneer&quot;&gt;doc.e.foundation/devices/pioneer&lt;/a&gt;
findet man die Installationsanleitung und das war es auch schon.&lt;br /&gt;
… leider war es dann doch nicht so einfach und ich brauchte einiges an 
Geduld.&lt;/p&gt;

&lt;p&gt;Für die Installation braucht man einige Schritte:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Der Bootloader des Smartphones muss “entsperrt” werden&lt;/li&gt;
  &lt;li&gt;Man braucht die Tools &lt;code&gt;adb&lt;/code&gt; und &lt;code&gt;fastboot&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Ein eigener USB-INF-Treiber muss installiert sein, damit &lt;code&gt;adb&lt;/code&gt; 
und &lt;code&gt;fastboot&lt;/code&gt; korrekt funktionieren können&lt;/li&gt;
  &lt;li&gt;Man braucht ein &lt;code&gt;/e/OS&lt;/code&gt; “Recovery-Image”, welches das bestehende 
Android ersetzen kann&lt;/li&gt;
  &lt;li&gt;Man braucht das finale Android-Image, das installiert werden soll.&lt;/li&gt;
  &lt;li&gt;Und am Ende richtet man die neue Android-Version dann ein.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;smartphone-entsperren&quot;&gt;Smartphone entsperren&lt;/h4&gt;

&lt;p&gt;Also diese Prozedur ist echt lustig, und kann bei jedem Smartphone etwas 
anders sein. Ich musste eine dokumentierte Zahlensequenz in der Telefon-App 
eintippen, worauf sich das “Service-Menü” öffnet. Dort erfährt man die Geräte 
&lt;a href=&quot;https://de.wikipedia.org/wiki/International_Mobile_Equipment_Identity&quot;&gt;IMEI&lt;/a&gt;
Nummer und ob ein entsperren möglich ist.&lt;/p&gt;

&lt;p&gt;Danach musste ich auf eine Entsperr-Seite von 
&lt;a href=&quot;http://developer.sonymobile.com/unlockbootloader/unlock-yourboot-loader/&quot;&gt;developer.sonymobile.com/unlockbootloader/unlock-yourboot-loader/&lt;/a&gt; 
gehen, wo aus meiner IMEI dann ein Entsperrcode generiert wurde, der im 
Fastboot-Modus über den Befehl
&lt;code&gt;fastboot oem unlock 0x&lt;/code&gt; + Code&lt;br /&gt;
den Bootloader “überschreibbar” machen sollte.&lt;/p&gt;

&lt;h4 id=&quot;bockiger-usb-treiber&quot;&gt;Bockiger USB-Treiber&lt;/h4&gt;

&lt;p&gt;Ist das Gerät unter Windows per USB-Kabel verbunden, erkennt &lt;code&gt;adb&lt;/code&gt; alles
und laut Anweisung soll &lt;code&gt;adb reboot bootloader&lt;/code&gt; das Gerät in einen speziellen
Modus booten lassen, in dem weitere Änderungen vorgenommen werden können.&lt;/p&gt;

&lt;p&gt;Hier versagte allerdings jede weitere Kommunikation und der Test mit dem
Aufruf &lt;code&gt;fastboot devices&lt;/code&gt; konnte mein Smartphone nie finden.&lt;/p&gt;

&lt;p&gt;Grund dafür war, dass in diesem speziellen Boot-Modus ein anderer USB-Treiber
hätte geladen werden müssen und dieser fehlte mir.&lt;br /&gt;
Ich konnte zwar von 
&lt;a href=&quot;https://developer.sony.com/file/download/fastboot-driver/&quot;&gt;developer.sony.com/file/download/fastboot-driver/&lt;/a&gt;
eine INF-Datei herunterladen, doch diese ließ sich nicht installieren, und
gab stets die Info aus, dass die notwendige &lt;code&gt;winusb.sys&lt;/code&gt; Datei nicht gefunden 
wurde.&lt;br /&gt;
Dieser Treiber ist ein Standard-Teil von Windows, der mit den Hardware-IDs in
den INF-Dateien angewiesen wird, ein virtuelles Gerät im System anzulegen, 
zu dem sich Benutzerprogramme verbinden können.&lt;/p&gt;

&lt;p&gt;Ich musste erst in den Windows-Test-Modus schalten 
(&lt;code&gt;bcdedit /set testsigning on&lt;/code&gt;) und dort manuell den original INF-Treiber 
in &lt;code&gt;C:\Windows\System32\DriverStore\FileRepository\winusb.inf_amd64_ced441476847bd1a&lt;/code&gt; 
über das Gerät “darüberinstallieren”, bis dann endlich auch der Android ADB 
Treiber zu funktionieren begann.&lt;/p&gt;

&lt;p&gt;Jetzt konnte ich in den Fastboot-Modus wechseln, und den Entsperrcode über
das &lt;code&gt;fastboot&lt;/code&gt; Tool zum Gerät senden.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;D:\&amp;gt;fastboot oem unlock 0xaaaaaaaaaaaaaaaa
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;OKAY [  6.711s]
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;Finished. Total time: 6.711s
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Ab nun erscheint bei jedem Neustart die Meldung, dass der Bootloader 
“unlocked” ist.&lt;/p&gt;

&lt;h4 id=&quot;rescue-image-installieren&quot;&gt;Rescue Image installieren&lt;/h4&gt;

&lt;p&gt;Jetzt beginnt das eigentliche Upgrade im Fastboot-Modus, wo das Recovery
Image installiert wird&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;D:\&amp;gt;fastboot flash boot D:\apps\android\e-os\recovery-e-1.5-r-20221031230467-dev-pioneer.img
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;Sending &apos;boot_b&apos; (22345 KB)                        OKAY [  0.564s]
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;Writing &apos;boot_b&apos;                                   OKAY [  0.132s]
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;Finished. Total time: 0.789s
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Wenn man jetzt neu startet:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;D:\&amp;gt;fastboot reboot
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;Rebooting                                          OKAY [  0.008s]
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;Finished. Total time: 0.010s
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;und die Tasten &lt;code&gt;Volume-Down&lt;/code&gt; + &lt;code&gt;Power&lt;/code&gt; drückt, landet man im grafischen
Recovery Image, das zuvor installiert wurde.&lt;/p&gt;

&lt;p&gt;Dort führt man einen “Factory-reset” durch, der das frühere OS löscht und
das Gerät auf die Installation des vollständigen /e/OS Systems vorbereitet.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/eos-install-series-01.jpg&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;

&lt;h4 id=&quot;eos-sideload&quot;&gt;/e/OS “Sideload”&lt;/h4&gt;

&lt;p&gt;Mit dem Kommando &lt;code&gt;adb sideload&lt;/code&gt; wird in diesem Zustand das Image übertragen&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;D:\&amp;gt;adb sideload D:\apps\android\e-os\e-1.5-r-20221031230467-dev-pioneer.zip
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;serving: &apos;D:\apps\android\e-os\e-1.5-r-20221031230467-dev-pioneer.zip&apos;  (~11%)
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Das dauert viele Minuten und auch die Fortschrittsanzeige bleibt lange 
scheinbar hängen.
Hier muss man einfach geduldig warten, denn irgendwann sind alle Daten am 
richtigen Ort und die Installation endet mit einem schlichten:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Install completed with status 0.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/eos-install-series-02.jpg&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Jetzt ist ein finaler Reboot angesagt und dieser führt dann zum neuen
Logo während des Starts mit dem &lt;code&gt;e&lt;/code&gt; Symbol und einem springenden Punkt.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/eos-boot-logo.jpg&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;

&lt;h4 id=&quot;android-einrichten&quot;&gt;Android einrichten&lt;/h4&gt;

&lt;p&gt;Nun folgt die “übliche” Prozedur, wie bei allen Betriebssystemen, wo man
nach Ort, Datum, Netzwerk und Logindaten gefragt wird..&lt;/p&gt;

&lt;p&gt;Auffällig war dabei, dass der Touchscreen auf eine sehr dunkle Stufe 
geschaltet war. Damit waren die Texte etwas schwer lesbar, aber es war
akzeptabel.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/eos-install-series-03.jpg&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Nach dem setzen einiger Einstellungen, kam ich endlich zum Ende der
Installationsprozedur.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/eos-install-series-04.jpg&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Dahinter verbarg sich dann ein recht normales Android-Outfit, dem aber
tatsächlich alle üblichen Google-Icons fehlten&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/eos-phone.jpg&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;In den Einstellungen konnte ich den Touchscreen wieder heller einstellen
und dann das System schrittweise erkunden.&lt;/p&gt;

&lt;p&gt;In der &lt;code&gt;App Lounge&lt;/code&gt;, dem &lt;code&gt;/e/OS&lt;/code&gt; Ersatz für den Play-Store, fand ich diverse
Apps, die man “im Business” gebrauchen kann und installierte diese samt 
Updates für diverse Standard Apps.&lt;/p&gt;

&lt;p&gt;Und das war es auch schon … 
… ich habe erstmals ein Android-System selbst installiert.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Wenn der lästige Windows-Treiber-Bug nicht gewesen wäre, hätte ich sagen
könne: Es war eigentlich ganz einfach … doch ein solcher Fehler hält
vermutlich viele interessierte Anwender ab.&lt;br /&gt;
Denn dokumentiert ist ein solches Problem nicht.
Vielleicht liegt es auch an der aktuellen Windows Version und dass es vor
2 Jahren noch out-of-the-box lief … heute aber nicht mehr.&lt;/p&gt;

&lt;p&gt;Jetzt, 4 Jahre zu spät, entwickle ich langsam Interesse an meinem XA2, das 
bisher nur als Staubfänger fungierte.&lt;br /&gt;
Denn ohne die lästigen Fix-Apps wie Facebook und GMail, die sich auf 
üblichen Phones nicht deinstallieren lassen, ist &lt;code&gt;/e/OS&lt;/code&gt; genau das, was 
ich von einem Telefon verlange:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Es ist frei von sinnlosem Blödsinn und lässt mich genau das installieren,
was ich haben möchte.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In diesem Sinne sage ich:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ein Hoch auf die e-foundation, das Lineage-Team und alle Entwickler,
die mein Upgrade möglich gemacht haben.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Leider ist mein &lt;a href=&quot;/blog/2021/12/poco-m3/&quot;&gt;Poco M3&lt;/a&gt; noch 
nicht offiziell unterstützt, und so verbleibt es, wie zuvor das XA2, auf 
der Reservebank.&lt;br /&gt;
Denn mein altes Lumia Windows-Phone gibt und gibt nicht den Geist auf.&lt;br /&gt;
Und so habe ich weiter keinen Grund zu Android zu wechseln.
… doch wenn es passieren sollte, dann wechsle ich nun aufgeschlossen
zu &lt;code&gt;/e/OS&lt;/code&gt;.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Es war einmal ... ein Glücksspiel</title>
   <link href="https://www.opengate.at/blog/2022/11/luck/"/>
   <published>2022-11-13T12:00:00+01:00</published>
   <updated>2022-11-13T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2022/11/luck</id>
   <category term="general" />
   <summary type="text">Manchmal erfährt man aus den Medien, was gerade für Skandale ablaufen.
Und man wundert sich, wie das Schicksal solche Spinnfäden an Zufällen weben
konnte.

… und manchmal passiert so etwas auch im Bekanntenkreis.
</summary>
   <content type="html">&lt;p&gt;Manchmal erfährt man aus den Medien, was gerade für Skandale ablaufen.
Und man wundert sich, wie das Schicksal solche Spinnfäden an Zufällen weben
konnte.&lt;/p&gt;

&lt;p&gt;… und manchmal passiert so etwas auch im Bekanntenkreis.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Vor vielen vielen Jahren, lange vor meiner Geburt, ging eine fleißige 
junge Kellnerin in einem kleinen Dorf ihrer Arbeit nach:&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;Ein &lt;a href=&quot;https://de.wikipedia.org/wiki/Trinkglas#Schnapsglas&quot;&gt;Stamperl&lt;/a&gt; 
für den alten Herrn ganz hinten, 
ein &lt;a href=&quot;https://de.wikipedia.org/wiki/Bierglas&quot;&gt;Krügerl&lt;/a&gt; für den Apfelbauern 
und ein &lt;a href=&quot;https://de.wikipedia.org/wiki/Toast_Hawaii&quot;&gt;Toast Hawaii&lt;/a&gt; für 
den Straßenarbeiter.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Und in der Ecke stand der 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Spielautomat&quot;&gt;Einarmige Bandit&lt;/a&gt;, der mit dem 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Flipperautomat&quot;&gt;Flipper&lt;/a&gt; in keiner Kneipe 
dieser Zeit fehlen durfte.&lt;/p&gt;

&lt;p&gt;Und was ist so ein Automat ohne seine treuen Spieler?&lt;/p&gt;

&lt;p&gt;Die Hersteller und Verkäufer dieser Automaten, die regelmäßig vorbeikamen 
um das Gerät “zu justieren”, prägten den Spruch:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Erst füttern, dann melken.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Und so war das Glück etwas zu Gewinnen stets von den Besuchen dieser
Herrschaften abhängig, die einen Teil der üppig gefüllten Münzenkiste
dem Wirt zukommen ließen.&lt;/p&gt;

&lt;p&gt;Beim “Füttern” kam häufiger wieder genau das unten raus, was man oben
reingesteckt hatte, was sofort mit einem Bierchen gefeiert wurde.&lt;br /&gt;
Beim “Melken” musste die schlechte Laune wegen der “verfüttertem” Münze
ebenso wieder weggebechert werden.&lt;/p&gt;

&lt;p&gt;Und so hätte es ewig weiter gehen können, wenn da nicht dieser eine
Tag gekommen wäre.&lt;/p&gt;

&lt;p&gt;Wer weiß schon noch, ob es eine 3. Zitrone, Kirsche, eine 3. &lt;code&gt;7&lt;/code&gt; oder ein 
anderes Symbol war, was gerade dabei war, einzurasten und mit einem seltsamen
Mechanismus dann unerwartet doch noch eine Stelle weitersprang …&lt;br /&gt;
Das war jedenfalls der Augenblick, als die Stimmung kippte.&lt;/p&gt;

&lt;p&gt;Die Kellnerin hätte sich diesen Tag niemals gemerkt, hätte der Spieler nicht
laut schreiend ein Pistole aus dem Mantel gezogen und damit wild 
herumgefuchtelt.&lt;/p&gt;

&lt;p&gt;Nun, es ist zum Glück sonst nichts weiter passiert, es hatte sich kein Schuss
gelöst und es wurde auch nie geklärt, warum der Zivilist überhaupt eine
Waffe bei sich trug, doch hörte er nicht auf, den Namen des Herstellers 
auszustoßen, gefolgt von:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Dieser elende Betrüger! Das lasse ich mir nicht gefallen!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Und aus dieser Absicht schrieb sich fast von selbst “ein gewaschener Brief” 
gespickt mit Anschuldigungen gegen den Macher des teuflischen Automaten, der
nichts anderes im Schilde führen könne, als alle und jeden zu betrügen.&lt;/p&gt;

&lt;p&gt;Offenbar war der Brief so prall gefüllt mit kreativen Wortmeldungen,
dass der oberste Chef der Herstellerfirma, sich diesen Brief (vermutlich
mit einem schadenfrohen Lachen) aufhob und im Nachtkästchen verwahrte,
vermutlich um sich jeden Abend vor dem Schlafen gehen daran zu erfreuen.&lt;/p&gt;

&lt;p&gt;Wir alle wissen, dass Glücksspielfirmen gerne viel Geld hin und 
her verschieben, aber dieses furchtbar ungern versteuern.&lt;br /&gt;
Und weil dieses Geld scheu wie ein Reh ist, sieht man es bestenfalls in 
weiter Ferne entschwinden, und kein Finanzjäger konnte je eines erlegen.&lt;/p&gt;

&lt;p&gt;Unzählige Prüfungen und Durchsuchungen wurden durchgeführt, doch immer 
passte alles perfekt, kein Verdacht eines Betruges konnte sich erhärten.
Und auch bei der Hausdurchsuchung stand jener Firmenchef selbstsicher
daneben, als wieder einmal “nichts” über seine einarmigen Banditen
gefunden wurde.&lt;/p&gt;

&lt;p&gt;Hätte doch bloß niemand in das Nachtkästchen gesehen, wo der üble
Brief verwahrt war. Und obgleich man sonst nichts handfestes finden
konnte, dieser Brief gab den Ermittlern einen Grund.&lt;br /&gt;
Nämlich einen Grund zu graben und nicht wie üblich zum nächsten
“Kunden” zu gehen.&lt;/p&gt;

&lt;p&gt;Und wenn man nur tief genug gräbt, wird man immer auf etwas
Hartes stoßen.&lt;/p&gt;

&lt;p&gt;Genau so war es auch, statt der erwarteten Jahresbesuche bei der Firma,
fand man unerwartet doch die eine oder andere Unstimmigkeit und wenn
das Kartenhaus einmal wackelt, fällt es anderen Beteiligten auch nicht
mehr leicht, ruhig zu bleiben.&lt;/p&gt;

&lt;p&gt;Am Ende reihte sich die ganze Sache in eine von vielen Firmenpleiten in
Österreich ein, die nicht so ganz fair gespielt hatten, die anfangs viel
Geld gewonnen und am Ende mehr als alles verloren hatten.&lt;/p&gt;

&lt;p&gt;Unser Spieler hatte am Ende doch noch eine ordentliche Portion Schadenfreude
gewonnen, wenngleich sie nicht in Münzen ausbezahlt wurde.&lt;/p&gt;

&lt;p&gt;Und unsere damalige Kellnerin … sie erzählt gelegentlich noch heute,
wie ein einziger zorniger Brief eine ganze Unternehmung zu Fall bringen
konnte.&lt;/p&gt;

&lt;h3 id=&quot;-ihr-jonathan-frakes&quot;&gt;… ihr Jonathan Frakes&lt;/h3&gt;

&lt;p&gt;In der Serie 
&lt;a href=&quot;https://de.wikipedia.org/wiki/X-Factor:_Das_Unfassbare&quot;&gt;X-Factor&lt;/a&gt;
beendete 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Jonathan_Frakes&quot;&gt;Jonathan Frakes&lt;/a&gt; die manchmal 
wahren, manchmal erfundenen Geschichten immer mit Sätzen wie diesem:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Hat ein Blatt Papier ohne einen einzigen Beweis wirklich eine so große Macht
den Lauf der Geschichte zu verändern?&lt;br /&gt;
Denken Sie, dass diesmal die Feder mächtiger war als das Schwert,
oder haben wir nur zu tief ins Glas geblickt und Unsinn niedergeschrieben?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Und am Ende erfolgt die Auflösung:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Diese Geschichte ist war.
So ähnlich hat es sich vor 50 Jahren in einem kleinen Dorf zugetragen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;iframe width=&quot;640&quot; height=&quot;360&quot; src=&quot;/blog/redirect.html?https%3A%2F%2Fwww.youtube-nocookie.com%2Fembed%2FTLlBWZ7rc34&quot; frameborder=&quot;1&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;

&lt;p&gt;Und die Kellnerin von damals überlegte in ihrem später
in Wien aufgebautem eigenen Geschäftslokal ebenso einen Spielautomaten 
aufzustellen. Doch davon wurde ihr schnell abgeraten … denn das 
Automatengeschäft in Wien, so hieß es, war in neue feste Hände gekommen, 
mit denen “nicht gut Kirschen essen ist”.&lt;/p&gt;

&lt;p&gt;… aber das ist eine andere Geschichte.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Chromebook Recovery</title>
   <link href="https://www.opengate.at/blog/2022/11/chromebook-recovery/"/>
   <published>2022-11-12T12:00:00+01:00</published>
   <updated>2022-11-12T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2022/11/chromebook-recovery</id>
   <category term="hardware" /><category term="software" />
   <summary type="text">Auf PCs waren BIOS und 
EFI
stets das “Notfallprogramm”, wenn was schief ging, und man zwecks 
Wiederherstellung von einem anderen Medium booten musste.

Aber wie funktioniert das eigentlich auf dem 
Chromebook?

Grund genug, es kaputt zu machen, damit man es danach wiederherstellen kann…
</summary>
   <content type="html">&lt;p&gt;Auf PCs waren &lt;a href=&quot;https://de.wikipedia.org/wiki/BIOS&quot;&gt;BIOS&lt;/a&gt; und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Unified_Extensible_Firmware_Interface&quot;&gt;EFI&lt;/a&gt;
stets das “Notfallprogramm”, wenn was schief ging, und man zwecks 
Wiederherstellung von einem anderen Medium booten musste.&lt;/p&gt;

&lt;p&gt;Aber wie funktioniert das eigentlich auf dem 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Chromebook&quot;&gt;Chromebook&lt;/a&gt;?&lt;/p&gt;

&lt;p&gt;Grund genug, es kaputt zu machen, damit man es danach wiederherstellen kann…
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Ich liebe die PC Architektur vor allem für eine Sache: Das BIOS bzw. uEFI.&lt;br /&gt;
Denn dieser Standard machte alle x86 Varianten zu einander kompatibel und
jedes Betriebssystem kann generisch ausgelegt werden um überall starten 
und seine Treiber laden zu können.&lt;br /&gt;
EFI liest z.B. immer eine GUID-Partitionstabelle, findet die erste “EFI”
&lt;a href=&quot;https://de.wikipedia.org/wiki/File_Allocation_Table#FAT32&quot;&gt;FAT32&lt;/a&gt;
Partition und lädt dort eine &lt;code&gt;/EFI/BOOT/arch.EFI&lt;/code&gt;, und der OS-Loader läuft.&lt;/p&gt;

&lt;p&gt;Während uEFI auch für die 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Arm-Architektur&quot;&gt;ARM Architektur&lt;/a&gt; spezifiziert 
ist, haben sich die meisten ARM Gerätehersteller nie daran gehalten und stets
ihr eigenes Süppchen gekocht. Die Firmware des 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Raspberry_Pi&quot;&gt;Raspberry PI&lt;/a&gt; und seiner 
Verwandten geht von einer “alten” 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Master_Boot_Record&quot;&gt;MBR&lt;/a&gt; Partitionstabelle aus, 
in der eine FAT/FAT32 Partition liegt, und dort wird nach bestimmten 
Dateinamen gesucht, die an festgelegte Adressen geladen werden.&lt;/p&gt;

&lt;p&gt;Und schlimmer wird es auf weiteren ARM-Systemen, wo nach Codes (IDs) auf
den Datenträgern an bestimmten magischen Positionen gesucht wird …&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Und was macht mein Lenovo Chromebook?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Das hat mir folgendes Video aufgezeigt:&lt;/p&gt;
&lt;iframe width=&quot;480&quot; height=&quot;360&quot; src=&quot;/blog/redirect.html?https%3A%2F%2Fwww.youtube-nocookie.com%2Fembed%2FKd0Nftc98vE&quot; frameborder=&quot;1&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;

&lt;p&gt;Zusammengefasst: Also wieder was ganz anderes.&lt;/p&gt;

&lt;h3 id=&quot;recovery-sd-karte-oder-usb-stick-anlegen&quot;&gt;Recovery SD-Karte oder USB-Stick anlegen&lt;/h3&gt;

&lt;p&gt;Es gibt eine Chrome-Extension names “Chromebook Recovery Utility”.
Man sucht also nach dieser Extension im Browser und installiert sie.
Über das Extension Menü kann man dieses Plugin starten und schon
öffnet sich ein Fenster, in dem man die Erzeugung eines “Wiederherstellungs 
Mediums” einleiten kann.&lt;/p&gt;

&lt;p&gt;Man legt einfach eine SD-Karte ein oder steckt einen USB Stick an und wählt
diesen dann als Installationsziel.&lt;br /&gt;
Man muss auch noch die “Geräte-ID” angeben, um das richtige Image 
herunterzuladen, doch mein voll-unterstütztes Gerät wurde von selbst erkannt
und das Feld damit automatisch befüllt.&lt;/p&gt;

&lt;p&gt;Nun läuft der Download und nach dessen Fertigstellung wird das Zielmedium 
(SD-Karte / USB-Stick) überschrieben.&lt;/p&gt;

&lt;p&gt;Fertig ist das OS-Setup.&lt;/p&gt;

&lt;h3 id=&quot;von-sd-karte-oder-usb-booten&quot;&gt;Von SD-Karte oder USB Booten&lt;/h3&gt;

&lt;p&gt;Man braucht eine spezielle Tastenkombination um am Chromebook von USB/SD zu
booten, weshalb man die Maschine erst mal herunterfahren muss.&lt;/p&gt;

&lt;p&gt;Jetzt drückt man die Tasten &lt;code&gt;ESC&lt;/code&gt; und &lt;code&gt;Refresh&lt;/code&gt; (der Kreispfeil) und drückt
parallel den Einschaltknopf des Chromebooks.&lt;/p&gt;

&lt;p&gt;Nun sieht man die Info, dass man von einem externen Medium booten kann und
darunter befindet sich nochmals die Geräte-ID (mit der man das richtige Image
im Netz finden kann).&lt;/p&gt;

&lt;p&gt;Ist eine Karte/Stick mit einem korrekt signierten Image eingelegt, bootet
das System binnen Sekunden automatisch davon.&lt;br /&gt;
Zuerst wird das Medium selbst nochmal verifiziert, ob alles passt und danach
startet sofort die Löschung des bestehenden Systems gefolgt von dessen 
Neuinstallation.&lt;/p&gt;

&lt;p&gt;Schaltet man das Gerät in der Zeit ab (was ich getan habe), kann danach
nicht mehr gebootet werden und man erhält auch die Meldung, dass kein
gültiges OS vorhanden ist. (Die haben wirklich alles 
“ge-&lt;a href=&quot;https://de.wikipedia.org/wiki/Hashfunktion&quot;&gt;hash&lt;/a&gt;-t”.)&lt;/p&gt;

&lt;p&gt;Läuft die Wiederherstellung bzw. Neuinstallation allerdings bis zum Ende
durch, muss man das Geräte erst mal ausschalten (lange auf den Ausschalter
drücken).&lt;br /&gt;
Und beim nächsten Einschalten startet 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Google_ChromeOS&quot;&gt;ChromeOS&lt;/a&gt; wie frisch aus 
der Verpackung, fragt nach Userdaten und einer WLAN-Verbindung.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Der Vorgang ist ziemlich “deppen-sicher”. Während man sich in einem Windows
Setup beim Partitionieren verrennen kann, oder ein fehlender USB-Treiber die
ganze Installation aufhalten kann, ist das ChromeOS Setup unterbrechungs-
und eingabefrei.&lt;/p&gt;

&lt;p&gt;Hat man also sein Image im Netz gefunden (bzw. vom Recovery Utility finden 
lassen), muss man nur noch die geheime Tastenkombination für den Boot von
externen Medien kennen.&lt;br /&gt;
Der Rest läuft wirklich zu 100% automatisch.&lt;/p&gt;

&lt;p&gt;Doch trotz dieser Benutzerfreundlichkeit ist mir der Aufbau unsympathisch.
Google’s Nonstandard Bootprozess, seine verworrenen Partitionstabellen mit
signierten Inhalten wollen nur eines erreichen: Nämlich dass nichts anderes
außer ChromeOS auf der Hardware laufen darf.&lt;br /&gt;
Genau so als ließe sich ein Auto nur an einer ganz bestimmten Tankstelle
befüllen … und das ist Mist!&lt;/p&gt;

&lt;p&gt;Doch zumindest habe ich nun ein “Setup” für Notfälle, falls mir wieder mal 
was an dem Gerät kaputt geht.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Watcom DOS: wcl vs wcl386</title>
   <link href="https://www.opengate.at/blog/2022/11/watcom-dos16/"/>
   <published>2022-11-06T12:00:00+01:00</published>
   <updated>2022-11-06T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2022/11/watcom-dos16</id>
   <category term="devel" /><category term="retro" />
   <summary type="text">Wer mit CMake ein 
Watcom für 
DOS Projekt aufsetzt, erhält ein 
DPMI 32-bit 
Programm, das not mit einem DOS-Extender gestartet werden kann.

Das ist grundsätzlich gut, weil man dann “ganz” normal im 32-bit Flatmemory
Stil arbeiten kann. Aber die guten alten 
Realmode Hardwarezugriffe sind 
damit ein Problem.


  Wie macht man also “richtige” 16-bit DOS Programme im Jahr 2022?


</summary>
   <content type="html">&lt;p&gt;Wer mit &lt;a href=&quot;https://de.wikipedia.org/wiki/CMake&quot;&gt;CMake&lt;/a&gt; ein 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Watcom&quot;&gt;Watcom&lt;/a&gt; für 
&lt;a href=&quot;https://de.wikipedia.org/wiki/MS-DOS&quot;&gt;DOS&lt;/a&gt; Projekt aufsetzt, erhält ein 
&lt;a href=&quot;https://de.wikipedia.org/wiki/DOS_Protected_Mode_Interface&quot;&gt;DPMI&lt;/a&gt; 32-bit 
Programm, das not mit einem DOS-Extender gestartet werden kann.&lt;/p&gt;

&lt;p&gt;Das ist grundsätzlich gut, weil man dann “ganz” normal im 32-bit Flatmemory
Stil arbeiten kann. Aber die guten alten 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Real_Mode&quot;&gt;Realmode&lt;/a&gt; Hardwarezugriffe sind 
damit ein Problem.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Wie macht man also “richtige” 16-bit DOS Programme im Jahr 2022?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;!--more--&gt;

&lt;p&gt;————————————————————`&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Antwort:&lt;/strong&gt; Es liegt am eingesetzten Compiler.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;wcl386.exe&lt;/code&gt; erzeugt 32-bit Code und &lt;code&gt;wcl.exe&lt;/code&gt; generiert alten DOS 
16-bit Code.&lt;/p&gt;

&lt;p&gt;Je nachdem, welche EXE man ausführt und welche Parameter mitübergeben werden,
kommt ein anderer Binärtyp heraus:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;wcl386 main.c&lt;/code&gt;&lt;br /&gt;
erzeugt eine “Standard” WinNT-Console &lt;code&gt;main.exe&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;wcl386 -bcl=dos4g main.c&lt;/code&gt;&lt;br /&gt;
erzeugt eine DOS/4G 32-bit &lt;code&gt;main.exe&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;wcl386 -bcl=dos main.c&lt;/code&gt;&lt;br /&gt;
ist falsch und funktioniert nicht&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;wcl -bcl=dos main.c&lt;/code&gt;&lt;br /&gt;
erzeugt eine DOS 16-bit Realmode &lt;code&gt;main.exe&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;wcl -bcl=com main.c&lt;/code&gt;&lt;br /&gt;
erzeugt eine minimalistische DOS 16-bit Realmode &lt;code&gt;main.com&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Wenn man CMake auf DOS-Plattform einschwört, legt es sich auf DOS/4G 32-bit
fest und ruft daher auch genau die dafür notwendigen Kommandos auf.&lt;br /&gt;
Das konnte ich auch mit noch so viel CMake Variablen-Umdeutungen nicht 
verhindern.&lt;/p&gt;

&lt;h3 id=&quot;wie-überzeugt-man-also-cmake-von-dos-16-bit&quot;&gt;Wie überzeugt man also CMake von DOS 16-bit?&lt;/h3&gt;

&lt;p&gt;Das Geheimnis findet man in der Datei &lt;code&gt;DOS-OpenWatcom.cmake&lt;/code&gt; in den &lt;code&gt;CMake&lt;/code&gt;
Scripts. Dort steht nämlich:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;if(DEFINED CMAKE_SYSTEM_PROCESSOR AND CMAKE_SYSTEM_PROCESSOR STREQUAL &amp;quot;I86&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;  string(APPEND CMAKE_EXE_LINKER_FLAGS_INIT &amp;quot; system dos&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  string(APPEND CMAKE_SHARED_LINKER_FLAGS_INIT &amp;quot; system dos&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  string(APPEND CMAKE_MODULE_LINKER_FLAGS_INIT &amp;quot; system dos&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;else()
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;  string(APPEND CMAKE_EXE_LINKER_FLAGS_INIT &amp;quot; system dos4g&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  string(APPEND CMAKE_SHARED_LINKER_FLAGS_INIT &amp;quot; system dos4g&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;  string(APPEND CMAKE_MODULE_LINKER_FLAGS_INIT &amp;quot; system dos4g&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;endif()
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Das heißt also, wenn man die Variable &lt;code&gt;CMAKE_SYSTEM_PROCESSOR&lt;/code&gt; auf &lt;code&gt;I86&lt;/code&gt; 
setzt, dann erzeugt &lt;code&gt;CMake&lt;/code&gt; die &lt;code&gt;wmake&lt;/code&gt; Buildfiles genau so, dass eine
echte 16-bit DOS-EXE am Ende herauskommt.&lt;/p&gt;

&lt;p&gt;Konkret bedeutet das, mein CMake Aufruf muss so aussehen:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;cmake -G &amp;quot;Watcom WMake&amp;quot; -DCMAKE_SYSTEM_NAME=DOS -DCMAKE_SYSTEM_PROCESSOR=I86 -DCMAKE_BUILD_TYPE=Release path\to\sources
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Und schon kann auf einem Windows 10 im Jahr 2022 eine 1980er-Party steigen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Als nächstes musste ich mir ein paar klein-Apps mit dem GATE Framework 
schreiben, die auch in eine kleine 16-Bit EXE passen. Zusätzlich war ein 
expliziter Wechsel zum Large-Model notwendig, weil Code und Daten nicht mehr
in ein 64 KByte Segment passten.&lt;/p&gt;

&lt;p&gt;Das war mit&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;set(CMAKE_C_FLAGS &amp;quot;${CMAKE_C_FLAGS} -mm&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;set(CMAKE_CXX_FLAGS &amp;quot;${CMAKE_CXX_FLAGS} -mm&amp;quot;)
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;erledigt.&lt;/p&gt;

&lt;p&gt;Jetzt brauche ich nur noch einen 
&lt;a href=&quot;https://de.wikipedia.org/wiki/DeLorean_DMC-12&quot;&gt;DeLorean&lt;/a&gt; mit einem 
Fluxkompensator, damit ich mir selbst Glück bringen kann.&lt;br /&gt;
… aber das ist eine andere Geschichte.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Visual Studio 2013 Lizenz Update Probleme</title>
   <link href="https://www.opengate.at/blog/2022/11/vs2013/"/>
   <published>2022-11-05T12:00:00+01:00</published>
   <updated>2022-11-05T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2022/11/vs2013</id>
   <category term="software" />
   <summary type="text">Da möchte ich einen Build unter 
Visual Studio 2013 auf 
Windows 8.1
testen, doch plötzlich kommt die Meldung, dass meine Lizenz abgelaufen ist
und aktualisiert werden muss.

Doch die Aktualisierung schlägt fehl und das Studio lässt sich nur noch
beenden.


  Wieder mal so eine Kack-Online-Abhängigkeit!


</summary>
   <content type="html">&lt;p&gt;Da möchte ich einen Build unter 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_Studio&quot;&gt;Visual Studio&lt;/a&gt; 2013 auf 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_8#Windows_8.1&quot;&gt;Windows 8.1&lt;/a&gt;
testen, doch plötzlich kommt die Meldung, dass meine Lizenz abgelaufen ist
und aktualisiert werden muss.&lt;/p&gt;

&lt;p&gt;Doch die Aktualisierung schlägt fehl und das Studio lässt sich nur noch
beenden.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Wieder mal so eine Kack-Online-Abhängigkeit!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Wie schön war das früher, als man eine Software im Laden kaufte, die
&lt;a href=&quot;https://de.wikipedia.org/wiki/Diskette&quot;&gt;Diskette&lt;/a&gt; / CD / DVD installierte 
und alles funktionierte einfach.&lt;/p&gt;

&lt;p&gt;Um 2010 herum fingen alle an, das Internet als “gegeben” anzunehmen und 
erzwangen in irgend einer Art, dass man online “registriert” wird, bevor
man das bereits gekaufte Produkt wirklich einsetzen darf.&lt;/p&gt;

&lt;p&gt;Blöd ist nur, wenn dieser Dienst plötzlich nicht mehr läuft, oder etwas
anderes fehlschlägt.&lt;/p&gt;

&lt;p&gt;Es ist so, als müsste man sein Auto wegwerfen und ersetzen, wenn eine
einzelne Tankstelle schließt.&lt;/p&gt;

&lt;h3 id=&quot;lösung-stärkere-verschlüsselung-einschalten&quot;&gt;Lösung: Stärkere Verschlüsselung einschalten&lt;/h3&gt;

&lt;p&gt;Microsoft hat den Aktivierungsdienst zwar noch nicht eingestellt, verlangt
nun aber eine neuere 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Transport_Layer_Security&quot;&gt;SSL/TLS&lt;/a&gt; Version, 
um einen Aufruf durchzulassen.&lt;/p&gt;

&lt;p&gt;Zum Glück lässt sich das im 
&lt;a href=&quot;https://de.wikipedia.org/wiki/.Net-Framework&quot;&gt;Dot-Net Framework&lt;/a&gt; und im 
System per &lt;code&gt;regedit&lt;/code&gt; einstellen, wie ich aus einer 
&lt;a href=&quot;https://learn.microsoft.com/en-us/answers/questions/838376/vs2013-community-can-not-update-the-license.html&quot;&gt;MS Forum-Seite&lt;/a&gt;
gelernt habe.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;dotNet 4.0 Strong-Crypto:&lt;br /&gt;
Im Registry-Schlüssel&lt;br /&gt;
&lt;code&gt;HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\.NetFramework\v4.0.30319&lt;/code&gt;&lt;br /&gt;
braucht man einen &lt;code&gt;DWORD&lt;/code&gt; Eintrag namens &lt;code&gt;SchUseStrongCrypto&lt;/code&gt; mit dem Wert &lt;code&gt;1&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;SCHANNEL muss TLS 1 aktivieren:&lt;br /&gt;
Im Registry-Schlüssel&lt;br /&gt;
&lt;code&gt;HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.0\Client&lt;/code&gt;&lt;br /&gt;
muss der &lt;code&gt;DWORD&lt;/code&gt; Eintrag &lt;code&gt;Enabled&lt;/code&gt; ebenfalls auf &lt;code&gt;1&lt;/code&gt; gesetzt sein.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Der Schlüssel &lt;code&gt;TLS 1.0&lt;/code&gt; und &lt;code&gt;Client&lt;/code&gt; existierten bei mir nicht und mussten zuvor angelegt werden.&lt;/p&gt;

&lt;p&gt;Jetzt startet man die Kiste neu und öffnet wieder Visual Studio 2013.&lt;br /&gt;
Nun öffnet sich beim Klick auf die “Lizenzaktualisierung” ein Fenster zur 
Eingabe seiner Microsoft-Account-Daten und schon wird die Lizenz aktualisiert,
Die IDE startet und Projekte können geladen und bearbeitet werden.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Mission erfüllt.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;“Halb-moderne Software” ist wegen solcher erzwungener Online-Einbindungen der 
letzte Dreck und auch unser heutiges Visual Studio 2022 wird in spätestens 10 
Jahren durch ähnliche Blödheiten vermutlich auch ausfallen.&lt;/p&gt;

&lt;p&gt;Hingegen läuft ein MSVC-98 unbeirrt und stabil in seiner VM weiter, denn
damals wäre niemand auf die bescheuerte Idee gekommen, einen Onlinecheck vor 
dem Start zu machen.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Warum denkt heute niemand mehr an die Langzeitnutzung?&lt;br /&gt;
Warum werden nur noch Wegwerfprodukte erzeugt?&lt;/p&gt;

  &lt;p&gt;Ach Kinder! Werdet endlich erwachsen (und schreibt ordentliche Software).&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>Zeit und Genauigkeit (unter Windows)</title>
   <link href="https://www.opengate.at/blog/2022/10/time-accuracy/"/>
   <published>2022-10-30T12:00:00+01:00</published>
   <updated>2022-10-30T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2022/10/time-accuracy</id>
   <category term="devel" />
   <summary type="text">Und wieder haben wir auf 
Winterzeit 
umgestellt … der richtige Zeitpunkt sich wieder mal über Zeit den Kopf 
zu zerbrechen.

Ein Thema, das ich bisher immer ausgespart hatte, war “Genauigkeit” und wie
man sie erhöhen kann.
</summary>
   <content type="html">&lt;p&gt;Und wieder haben wir auf 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Sommerzeit#Grundlagen&quot;&gt;Winterzeit&lt;/a&gt; 
umgestellt … der richtige Zeitpunkt sich wieder mal über Zeit den Kopf 
zu zerbrechen.&lt;/p&gt;

&lt;p&gt;Ein Thema, das ich bisher immer ausgespart hatte, war “Genauigkeit” und wie
man sie erhöhen kann.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Es ist schon fast lustig, wenn man weiß, dass die früheren PCs 
(damals vor 30 Jahren) ziemlich genaue 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Echtzeituhr&quot;&gt;RTC&lt;/a&gt; (Real-Time-Clock) Chips
verbaut hatten, während die Betriebssysteme nur “ungefähre” Zeitangaben
speicherten.&lt;/p&gt;

&lt;p&gt;Heute sind die RTCs in unseren Maschinen der letzte Dreck und weichen schon
nach ein paar Stunden um Sekunden ab, während die Betriebssysteme die Zeit 
auf Bruchteile von Millisekunden genau ermitteln können müssen.&lt;/p&gt;

&lt;p&gt;Der Grund für den Verfall der RTC Chips liegt vermutlich darin begründet,
dass heute eine Internetanbindung samt 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Network_Time_Protocol&quot;&gt;NTP&lt;/a&gt; 
Synchronisierung erwartet wird.&lt;/p&gt;

&lt;p&gt;Und der Grund für die genauen Zeitablesungen sind Anwendungen, die 
möglichst in Echtzeit auf Ereignisse reagieren sollen.&lt;/p&gt;

&lt;h3 id=&quot;getsystemtime-und-getsystemtimeasfiletime&quot;&gt;GetSystemTime() und GetSystemTimeAsFileTime()&lt;/h3&gt;

&lt;p&gt;Mit &lt;a href=&quot;https://learn.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getsystemtime&quot;&gt;GetSystemTime()&lt;/a&gt;
nutzt man die API, die überall vorhanden ist, von Windows NT4/95 bis
heute und auch 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_CE&quot;&gt;Windows CE&lt;/a&gt; 
stellt sie bereit.&lt;/p&gt;

&lt;p&gt;Doch meistens braucht man die Zeit nicht als Datumsangabe wie in 
&lt;code&gt;SYSTEMTIME&lt;/code&gt; definiert, sondern als Integer-Zeitstempel, und das 
läuft in Windows unter &lt;code&gt;FILETIME&lt;/code&gt; als &lt;code&gt;UINT64&lt;/code&gt; Typ in Nanosekunden 
seit 1.1. 1601.&lt;br /&gt;
Hier hilft &lt;a href=&quot;https://learn.microsoft.com/en-us/windows/win32/api/timezoneapi/nf-timezoneapi-systemtimetofiletime&quot;&gt;SystemTimeToFileTime()&lt;/a&gt;
und damit kann man dann endlich rechnen.&lt;/p&gt;

&lt;p&gt;Die bessere Methode ist allerdings gleich die API &lt;a href=&quot;https://learn.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getsystemtimeasfiletime&quot;&gt;GetSystemTimeAsFileTime()&lt;/a&gt;,
denn Zeit wird Windows-intern gleich als &lt;code&gt;FILETIME&lt;/code&gt; behandelt und 
&lt;code&gt;GetSystemTime()&lt;/code&gt; nutzt eben diese andere Funktion um daraus ein 
Datum zu machen.&lt;/p&gt;

&lt;p&gt;Allerdings ist diese API nicht in Windows CE definiert, weshalb ich 
bisher stets mit &lt;code&gt;GetSystemTime&lt;/code&gt; gearbeitet habe.&lt;br /&gt;
Doch da WinCE jetzt nicht gerade “die wichtigste Plattform” ist, bin ich 
ebenfalls zu &lt;code&gt;GetSystemTimeAsFileTime()&lt;/code&gt; gewechselt, und habe für die 
CE-Welt eine einfache Umleitung hinterlassen:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;static&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt; GetSystemTimeAsFileTime(FILETIME* ptr_ftm)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  SYSTEMTIME stm;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  GetSystemTime(&amp;amp;stm);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  SystemTimeToFileTime(&amp;amp;stm, ptr_ftm);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Wie gut, dass Raymond Chen 
&lt;a href=&quot;https://devblogs.microsoft.com/oldnewthing/20131101-00/?p=2763&quot;&gt;das Thema Zeit-APIs&lt;/a&gt; 
aufgegriffen hatte.&lt;/p&gt;

&lt;h3 id=&quot;genauigkeit-erhöhen&quot;&gt;Genauigkeit erhöhen&lt;/h3&gt;

&lt;p&gt;Windows hat die Genauigkeit seiner klassischen Zeit-APIs auf
ungefähr 15 Millisekunden angegeben, was vor 20-30 Jahren bei CPUs mit ein
paar hundert Megahertz vielleicht noch OK war, heute ist das beim Logging 
allerdings schon problematisch.&lt;/p&gt;

&lt;p&gt;Mir ist das bisher nie so wichtig gewesen, doch im Job bei der Arbeit mit 
Kameras und Bilderkennung, ist das extrem wichtig, dass man bei der 
Synchronisation von zwei Systemen auch möglichst exakte Zeitstempel braucht.
+/- 15 Millisekunden ist da eine Ewigkeit.&lt;/p&gt;

&lt;p&gt;Mit der (uralten) Multimedia-API
&lt;a href=&quot;https://learn.microsoft.com/en-us/windows/win32/api/timeapi/nf-timeapi-timebeginperiod&quot;&gt;timeBeginPeriod(1)&lt;/a&gt;
kann man Windows dazu zwingen, die Reaktion von Warte-Routinen auf 1 
Millisekunde herunterzusetzen, denn auch ein &lt;code&gt;Sleep(1)&lt;/code&gt; wartet bis zu 10
Millisekunden, bis das Programm fortgesetzt wird.&lt;br /&gt;
Doch die Zeit-APIs werden auch mit &lt;code&gt;timeBeginPeriod()&lt;/code&gt; nur alle 
15 Millisekunden aktualisiert.&lt;/p&gt;

&lt;p&gt;Seit &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_10&quot;&gt;Windows 10&lt;/a&gt; ist die 
Genauigkeit der Windows Zeit-APIs auch auf etwa 1 ms verbessert worden, 
doch für ältere Betriebssysteme hat sich ein interessanter Hack 
etabliert:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Man startet einen Thread mit höherer Priorität und liest dort in einer 
Schleife die Zeit und einen Performance-Counter aus.&lt;br /&gt;
Die Zeit-Funktion wird wiederholt den gleichen Zeitstempel zurückliefern,
bis die “Ungenauigkeit” durch ein Update des Systems unterbrochen wird.
Genau zu diesem Zeitpunkt speichert man sich den Wert des
Performance-Counters ab und kann dann bei den weiteren Iterationen die 
Differenz der Performance-Counter Werte zum letzten “genauen” Zeitstempel 
addieren.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Zu den Themen wurden schon vor 20 Jahren 
&lt;a href=&quot;https://learn.microsoft.com/en-us/archive/msdn-magazine/2004/march/implementing-a-high-resolution-time-provider-for-windows&quot;&gt;Artikel verfasst&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Und ich habe ein Codebeispiel im 
&lt;a href=&quot;https://codeberg.org/GateNetwork/gate-blog-classroom/src/branch/main/c_cpp/win32_hires_time/&quot;&gt;Blog Classroom&lt;/a&gt; 
angelegt, das den Unterschied zwischen normalen und “hi-res” 
Zeitablesungen aufzeigt.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Timer und Zeitablesungen, sind für mich aktuell keine hohe Priorität. Denn
wenn etwas schnell erledigt werden soll, passiert das bei mir synchron ohne
künstliche Wartezeiten. Und wenn der Benutzer etwas “sehen” will, dann sind
Genauigkeiten von 15 Millisekunden aus meiner Sicht weiter ausreichend.&lt;/p&gt;

&lt;p&gt;Aber zugegeben … es wäre vielleicht nicht schlecht, wenn ich mir auch eine
Timer-Klasse anlege, um solche Betriebssystem-Details abstrahiert und damit
die Genauigkeit erhöht.&lt;/p&gt;

&lt;p&gt;Man darf dabei aber nicht vergessen, dass solche Schritte Seiteneffekte haben,
wie z.B. der Erhöhung der Timer-Genauigkeit für alle Prozesse oder dass die CPU
Last in Summe ansteigt.&lt;br /&gt;
Mit Standardeinstellungen sollte ein solches Hi-res Feature also nicht 
aktiviert werden.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Intrigen im Kindergarten</title>
   <link href="https://www.opengate.at/blog/2022/10/mc-intrigue/"/>
   <published>2022-10-29T13:00:00+02:00</published>
   <updated>2022-10-29T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2022/10/mc-intrigue</id>
   <category term="general" />
   <summary type="text">Jeden Tag wird die Welt ein bisschen mehr zerstört, weil machtgetriebene 
Personen glauben auf irgend einen Vorfall mit Gewalt reagieren zu müssen.

Meiner Beobachtung nach beginnt diese Egomanie aber nicht erst im politischen
Leben, nein sie startet bereits unter 10- bis 15-jährigen Kindern.

Heutiges Thema: Der Ursprung von Hass am Beispiel Minecraft
</summary>
   <content type="html">&lt;p&gt;Jeden Tag wird die Welt ein bisschen mehr zerstört, weil machtgetriebene 
Personen glauben auf irgend einen Vorfall mit Gewalt reagieren zu müssen.&lt;/p&gt;

&lt;p&gt;Meiner Beobachtung nach beginnt diese Egomanie aber nicht erst im politischen
Leben, nein sie startet bereits unter 10- bis 15-jährigen Kindern.&lt;/p&gt;

&lt;p&gt;Heutiges Thema: &lt;strong&gt;Der Ursprung von Hass am Beispiel Minecraft&lt;/strong&gt;
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Wenn ich mir Filme, Serien oder Diskussionsaufzeichnungen ansehe, brauche ich
eine Nebenbeschäftigung, also “was für die Hände”.&lt;br /&gt;
Es wäre vermutlich sinnvoller sich ein paar Socken zu stricken, doch ich 
werfe einfach den Minecraft Client an, weil man da so schön hirnlos 
herum springen kann, während man der Handlung folgt.&lt;/p&gt;

&lt;p&gt;Doch wenn man mit einem Onlineserver verbunden ist, bekommt man gelegentlich
die Chat-Nachrichten anderer Spieler mit. Diese ignoriere ich zwar meistens,
doch manchmal passiert es dann doch, dass “das Drama der Kids” meine 
Aufmerksamkeit abzieht.&lt;/p&gt;

&lt;h3 id=&quot;ego-kapitalismus&quot;&gt;Ego-Kapitalismus&lt;/h3&gt;

&lt;p&gt;Ich persönlich erfreue mich in Minecraft an “Bauwerken”, wenn jemand zeigen
kann, dass er aus den Blöcken etwas Schönes oder Funktionales hochziehen kann.&lt;/p&gt;

&lt;p&gt;Doch die MC-Online-Communities funktionieren anders und zielen auf das 
Geltungsbedürfnis von Jugendlichen ab.&lt;br /&gt;
Man soll Spiel-internes Geld verdienen und soll:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;sich täglich einloggen um Login-Coins zu erhalten.&lt;/li&gt;
  &lt;li&gt;möglichst schnell an Ressourcen kommen, die man zu Geld machen kann&lt;/li&gt;
  &lt;li&gt;Blöcke mit anderen gegen Coins handeln.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Hat man dann eine gewisse Summe beisammen, kann man sich einen “Rang” kaufen
und damit angeben, und sich besser fühlen.&lt;br /&gt;
Und unser minderjähriger Nachwuchs treibt dieses Spiel bis zum Exzess.&lt;/p&gt;

&lt;h4 id=&quot;verbrechen-ist-ein-weg-&quot;&gt;“Verbrechen ist ein Weg” …&lt;/h4&gt;

&lt;p&gt;… meinte einmal Christoph Walz, als er zu den hohen Preisen in London 
befragt wurde. In Minecraft ist das Praxis.&lt;/p&gt;

&lt;p&gt;“Gute Spieler” schaffen es besonders schnell Neulinge zu übertölpeln, bieten
sich als “Freunde” an, und rauben dann deren Schätze, sobald sie von denen
Rechte erhalten haben, auf ihre Grundstücke zu gelangen.&lt;/p&gt;

&lt;p&gt;Dass auch noch einige Server das Wort “Griefer” im Namen tragen und damit
schon darauf hinweisen: “Wir wollen, dass Böswilligkeit ausgelebt wird.”,
bestätigt leider, wie destruktiv dieses Spiel gespielt werden kann.&lt;/p&gt;

&lt;p&gt;Ich möchte aber nicht wissen, was das im Gehirn eines Kindes anrichten kann.
Schließlich trainiert man hiermit die zukünftigen Betrüger zur Perfektion.&lt;/p&gt;

&lt;h3 id=&quot;parallelgesellschaften&quot;&gt;Parallelgesellschaften&lt;/h3&gt;

&lt;p&gt;Ganz besonders witzig bzw. lächerlich finde ich es, wenn sich die Kids 
zusammenrotten und großtrabend eine neue Gesellschaft gründen wollen.
Das fängt dann mit zwei Personen an, die eine “Base” oder eine “Stadt” bauen
wollen und erst einmal viel Zeit in ihr Projekt investieren.&lt;/p&gt;

&lt;p&gt;Doch dann will man es “herzeigen” und dafür gelobt werden und schon kommt
das “Angebot” im öffentlichen Chat:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Willst du mal unsere Stadt sehen?&lt;/li&gt;
  &lt;li&gt;Du kannst gerne mitmachen und hier einziehen.&lt;/li&gt;
  &lt;li&gt;Du musst dich aber an einige Regeln halten.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Binnen einiger Tage werden dann aus 2 Personen 6 bis 10.&lt;br /&gt;
Für einige weitere Tage wird dann fleißig gebaut, bis jeder sein Haus 
fertig hat und ein gemeinsames Monument entstanden ist.&lt;/p&gt;

&lt;p&gt;An dieser Stelle wird es dann oft politisch. Jetzt soll einer die Führung
übernehmen, ein “Bürgermeister” wird gewählt, der bei 
Meinungsverschiedenheiten das letzte Wort hat.&lt;/p&gt;

&lt;p&gt;Hier beginnt dann der Streit, denn es gibt immer irgend jemanden, der dann,
wenn alle offline sind, einsteigt und “etwas dreht”. Am Morgen kommen alle
zum Ort des Verbrechens und beschuldigen sich gegenseitig.
… und dann fängt der Kinofilm an.&lt;/p&gt;

&lt;p&gt;Es wird beschuldigt, beleidigt und geweint, als ginge es um Leben und Tod,
bis dann alle anfangen, die Bauwerke ihrer Nachbarn mutwillig zu zerstören,
worauf am Ende eine Ruine zurückbleibt, 60% den Server verlassen und wo 
anders anfangen und der Rest sich einen neuen Baugrund sucht.&lt;/p&gt;

&lt;p&gt;Und dieses Aggressionsspiel wiederholt sich in Minecraft auf dutzenden 
Servern jedes Monat von Neuem.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Was für ein Glück, dass ich nicht auf solche “Online-Freunde” angewiesen bin,
und als stiller Beobachter meine Schlüsse ziehen kann.&lt;/p&gt;

&lt;p&gt;Ich lerne allerdings, dass Kinder ein ganz intensives Verlangen nach dem 
Spiel mit anderen haben und gleichzeitig unfähig sind, irgend etwas daraus
zu lernen.&lt;br /&gt;
Schließlich beobachte ich solche Zusammenrottungen und Zerfallsprozesse schon
seit einem Jahr und sie wiederholen sich von den gleichen Spielern im 
Monatstakt.&lt;/p&gt;

&lt;p&gt;Ich frage mich, was diese Erfahrung in den Köpfen der nächsten Generation 
anrichtet, denn wenn sie das ernst nehmen, was sie da an Beleidigungen 
schreiben, verheißt das nichts Gutes … und wenn es ihnen sowieso egal ist, 
ist das genau so schlimm.&lt;/p&gt;

&lt;p&gt;Für mich persönlich war Minecraft immer ein “konstruktives Spiel”, in dem 
man etwas aufbaut. Doch wenn ich anderen dabei zusehe, wie sie damit nur 
ihre Messer wetzen, muss ich diese Meinung zu meinem Bedauern revidieren.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>CompactOS macht Windows kleiner</title>
   <link href="https://www.opengate.at/blog/2022/10/compact/"/>
   <published>2022-10-23T13:00:00+02:00</published>
   <updated>2022-10-23T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2022/10/compact</id>
   <category term="software" />
   <summary type="text">Windows 10 Images 
wachsen leider schnell an. Die 10 GB der Neuinstallation, dehnen sich schon 
nach der Treiber und Updateinstallation auf bis zu 20 GB aus, ohne dass man 
ein einziges weiteres Softwarepaket hinzufügt.

Gerade im Embedded Bereich sind aber kleine Images von Vorteil, und dafür
gibt es ein eigenes Tool namens compact
</summary>
   <content type="html">&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_10&quot;&gt;Windows 10&lt;/a&gt; Images 
wachsen leider schnell an. Die 10 GB der Neuinstallation, dehnen sich schon 
nach der Treiber und Updateinstallation auf bis zu 20 GB aus, ohne dass man 
ein einziges weiteres Softwarepaket hinzufügt.&lt;/p&gt;

&lt;p&gt;Gerade im Embedded Bereich sind aber kleine Images von Vorteil, und dafür
gibt es ein eigenes Tool namens &lt;code&gt;compact&lt;/code&gt;
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Auf meiner üppigen 500 MB Festplatte meines 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Intel_80486&quot;&gt;486er&lt;/a&gt; belegten vor 25 Jahren:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_3.1&quot;&gt;Windows 3.1&lt;/a&gt; 
etwa 16 MB, also 3 %&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_95&quot;&gt;Windows 95&lt;/a&gt; 
etwa 80 MB, also 16 %&lt;/li&gt;
  &lt;li&gt;und &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_NT_4.0&quot;&gt;NT 4&lt;/a&gt; 
etwa 200 MB, also 40 %&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Die Installation von &lt;a href=&quot;https://de.wikipedia.org/wiki/Office-Paket&quot;&gt;Office&lt;/a&gt;
und &lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_Basic_Classic&quot;&gt;Visual Basic&lt;/a&gt;
füllten locker weitere 150 MB auf (weil ich immer alle Komponenten 
installierte) und wenn man dann noch ein 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Swapping#Auslagerungsdatei&quot;&gt;Pagefile&lt;/a&gt;
addiert, dann ist die Platte voll.&lt;/p&gt;

&lt;p&gt;Kompression war daher schon früh mein Thema und am interessantesten fand
ich die &lt;a href=&quot;https://de.wikipedia.org/wiki/NTFS&quot;&gt;NTFS&lt;/a&gt; Dateikompression.
Wird das ganze C-Laufwerk komprimiert, verbrauchte das OS etwa 25-33% weniger
Speicherplatz. So konnten z.B. 60 MB gewonnen werden, oder wie ich damals 
staunend feststellte:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Das sind ja über 40 Disketten !!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Das funktioniert zum Teil auch heute noch, doch da ein Windows 10 eine 
Vielzahl seiner Bibliotheken im Speicher hat, lässt sich auch vieles
nicht live komprimieren.&lt;/p&gt;

&lt;p&gt;Zusätzlich ist die NTFS-Kompression nicht besonders stark, weil sie 
auf Vorhersehbarkeit und nicht auf hohe Dichte optimiert ist.&lt;/p&gt;

&lt;h3 id=&quot;compactos&quot;&gt;CompactOS&lt;/h3&gt;

&lt;p&gt;Recht gut funktioniert aus meiner Sicht Windows PE, denn hier liegen
200 - 500 MB stark komprimiert in einer &lt;code&gt;boot.wim&lt;/code&gt;, die vollständig in den
RAM geladen werden und die dann als virtuelles Dateisystem fungieren.&lt;br /&gt;
Doch Aktualisierungen durch Updates oder neue Treiber bedeuten beim &lt;code&gt;WIM&lt;/code&gt;
immer den Aufwand, dass man das Image mit Tools wie &lt;code&gt;dism&lt;/code&gt; offline 
nachbearbeiten muss.&lt;/p&gt;

&lt;p&gt;Mit Windows 10 hat Microsoft dafür aber ein neues Feature hinzugefügt, dass
einerseits Kompression ermöglicht und andererseits flexibel ist.&lt;br /&gt;
Der Aufruf von&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;compact.exe /CompactOS:always
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;als Administrator lässt das Betriebssystem seine Dateien komprimieren und das
OS in den Compact-Modus wechseln.&lt;br /&gt;
Dadurch erspart man sich je nach Installationsgröße ein paar Gigabyte.&lt;/p&gt;

&lt;h3 id=&quot;monatliches-cleanup&quot;&gt;Monatliches Cleanup&lt;/h3&gt;

&lt;p&gt;Gute Ergebnisse konnte ich in Kombination mit einem 
&lt;a href=&quot;/blog/2021/10/image-cleanup/&quot;&gt;Image-Cleanup&lt;/a&gt; erzielen.
Hat man nämlich in der Mitte des Monats die üblichen Windows-Updates 
empfangen und installiert, empfiehlt sich ein Aufruf von:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;dism /Image:C:\ /Cleanup-Image /StartComponentCleanup /ResetBase
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;compact.exe /CompactOS:always
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Das Betriebssystem integriert dann alle Updates permanent und entfernt 
interne Backups und danach wird sichergestellt, dass auch alles gut
komprimiert ist.&lt;/p&gt;

&lt;p&gt;Gerade auf älteren Windows-Tablets mit unter 100 GB Speicherplatz hilft
einem jedes auf diese Weise gewonnene Gigabyte.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Mir wäre es zwar lieber, dass man Windows noch weiter entschlacken könnte und
vor allem Legacy-Komponenten ausschließen könnte (wie etwa bei den Embedded
oder IOT Varianten), doch mit der einfach zugänglichen Kompression kann ich
mich auch anfreunden.&lt;/p&gt;

&lt;p&gt;Genau solche Kompressions-Features hätte ich im Jahr 2011 dringend 
gebraucht, als ich für Industrieterminals Windows 7 Embedded Images 
inklusive eigener Software auf 12 GB SSDs zuschneiden musste.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Naja, gut zu wissen, dass auch Microsoft inzwischen dazugelernt hat.&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>Von Double- zu Drivespace</title>
   <link href="https://www.opengate.at/blog/2022/10/drivespace/"/>
   <published>2022-10-22T13:00:00+02:00</published>
   <updated>2022-10-22T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2022/10/drivespace</id>
   <category term="software" /><category term="retro" />
   <summary type="text">Mit den damaligen Festplattengrößen von 40 - 200 MB war neben einer Windows
Installation kaum noch Platz für weitere Software.

Doch ab MS-DOS 6 hatte Microsoft mit
“Doublespace” eine Lösung integriert um scheinbar den freien Speicherplatz zu 
verdoppeln. Wenig später folgte das verbesserte 
Drivespace und unter 
Windows 95 fing das
ganze wieder von vorne an …
</summary>
   <content type="html">&lt;p&gt;Mit den damaligen Festplattengrößen von 40 - 200 MB war neben einer Windows
Installation kaum noch Platz für weitere Software.&lt;/p&gt;

&lt;p&gt;Doch ab &lt;a href=&quot;https://de.wikipedia.org/wiki/MS-DOS&quot;&gt;MS-DOS&lt;/a&gt; 6 hatte Microsoft mit
“Doublespace” eine Lösung integriert um scheinbar den freien Speicherplatz zu 
verdoppeln. Wenig später folgte das verbesserte 
&lt;a href=&quot;https://de.wikipedia.org/wiki/DriveSpace&quot;&gt;Drivespace&lt;/a&gt; und unter 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_95&quot;&gt;Windows 95&lt;/a&gt; fing das
ganze wieder von vorne an …
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Die ursprüngliche “geniale” Erfindung gelang einer anderen Softwareschmiede, 
die das Tool &lt;a href=&quot;https://de.wikipedia.org/wiki/Stac_Electronics&quot;&gt;Stacker&lt;/a&gt; auf 
den Markt brachte.&lt;br /&gt;
Mit diesem Programm bin ich nie in Berührung bekommen, doch Microsofts 
Nachbau in DOS war mir dafür bestens bekannt und es arbeitete nach dem 
gleichen Prinzip.&lt;/p&gt;

&lt;p&gt;Es wurde auf dem “echten” Laufwerk eine Datei angelegt, in der ein virtuelles
Dateisystem untergebracht war, das jedoch alle Daten komprimiert ablegte.
Bei der Umstellung wurden dann alle Dateien des originalen Dateisystems auf
das virtuelle komprimiert gespeichert, womit real weniger Speicherplatz
notwendig war.&lt;/p&gt;

&lt;p&gt;Das originale Laufwerk &lt;code&gt;C:&lt;/code&gt; wurde nach der Kompression standardgemäß als 
&lt;code&gt;H:&lt;/code&gt; eingebunden und beinhaltete nur die DOS-Startdateien, während &lt;code&gt;C:&lt;/code&gt; nun
den Inhalt der virtuellen komprimierten Datenträgerdatei zur Verfügung 
stellte.&lt;/p&gt;

&lt;p&gt;Das Versprechen, dass sich der freie Speicherplatz so verdoppelte, war 
bestenfalls eine Hoffnung, denn hatte man Bilder oder reine Programme
auf der Platte, lag der freie Speicherplatzgewinn gefühlt nur zwischen 
20 und 30%. Reine Textdateien (zB. Quellcodes) konnten aber sehr gut 
komprimiert werden und so konnten auch 70% erreicht werden.&lt;/p&gt;

&lt;p&gt;Das Resultat waren übelst schwankende Anzeigen des “frei-erfundenen”
freien Speicherplatzes.&lt;/p&gt;

&lt;h3 id=&quot;dos-6-doublespace&quot;&gt;DOS 6: Doublespace&lt;/h3&gt;

&lt;p&gt;DOS 6.0 enthielt mit &lt;code&gt;dblspace.exe&lt;/code&gt; das Verwaltungsprogramm, dass ein
reales Laufwerk komprimieren konnte oder auch wieder von einem
virtuellen Speicher in die reale Welt dekomprimieren konnte.&lt;br /&gt;
Der eigentliche Support für komprimierte Laufwerksdateien war im DOS 
selbst enthalten.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/dos-dblspace-01.png&quot; alt=&quot;DOS dblspace 1&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Im Endeffekt startete man das Programm, akzeptierte die anstehende
Veränderung und schon lief der Transfer aller Dateien in die neue
Datenträgerdatei.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/dos-dblspace-02.png&quot; alt=&quot;DOS dblspace 2&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Nach einem Reboot sah alles aus wie zuvor, doch das neue Laufwerk &lt;code&gt;H:&lt;/code&gt; zeigte uns, dass die versteckte Datei &lt;code&gt;dblspace.000&lt;/code&gt; den Großteil des
Platzes des Host-Laufwerks belegte.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/dos-dblspace-03.png&quot; alt=&quot;DOS dblspace 3&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;dos-622-drivespace&quot;&gt;DOS 6.22: Drivespace&lt;/h3&gt;

&lt;p&gt;Microsoft benannte in den letzten DOS 6.x Varianten das Tool zu “Drivespace”
um, womit auch das Program den Namen &lt;code&gt;drvspace.exe&lt;/code&gt; erhielt. 
Ob es da gröbere Unterschiede bei der Kompression gab, habe ich damals nicht
ausgetestet.&lt;/p&gt;

&lt;p&gt;Jedenfalls sah die Kompressionsprozedur genau so aus, wie bei der früheren
Variante … nur eben mit dem neuen Namen “Drivespace”&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/dos-drvspace-01.png&quot; alt=&quot;DOS drvspace 1&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Hier zeigte sich, dass auch der Dateiname auf &lt;code&gt;drvspace.000&lt;/code&gt; umbenannt wurde.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/dos-drvspace-02.png&quot; alt=&quot;DOS drvspace 2&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;windows-95-drivespace-mit-doublespace-dateien&quot;&gt;Windows 95: Drivespace mit Doublespace-Dateien&lt;/h3&gt;

&lt;p&gt;Windows 95 brachte eine anschauliche grafische Oberfläche für die 
Kompressionsfunktion mit.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/win95-drvspace-01.png&quot; alt=&quot;Win95 drvspace 01&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Man startete also die Kompression nun per Fenster und konnte sich durch ein 
paar Optionen durchklicken.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/win95-drvspace-02.png&quot; alt=&quot;Win95 drvspace 02&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Doch da im 32-Bit Modus das Bootlaufwerk nicht frei umgestaltet werden 
konnte, wurde automatisch neu gestartet und plötzlich landete man …&lt;br /&gt;
wieder in &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_3.1&quot;&gt;Windows 3.11&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Microsoft kopierte (so wie auch beim Win95 Setup) eine Minimalvariante des 
Vorgängersystems auf die Platte und startete darin die nötigen Tools zur
Konvertierung.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/win95-drvspace-03.png&quot; alt=&quot;Win95 drvspace 03&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Das bedeutete, dass sämtliche Tools im Win-16 Format vorliegen.&lt;/p&gt;

&lt;p&gt;Selbst eine 16-bit Festplattendefragmentierung ist vorhanden, die nach
der Kompression automatisch anläuft.&lt;br /&gt;
(Das Tool hätte ich gerne auch im echten Win 3.x dabei gehabt).&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/win95-drvspace-04.png&quot; alt=&quot;Win95 drvspace 04&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/win95-drvspace-05.png&quot; alt=&quot;Win95 drvspace 05&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/win95-drvspace-06.png&quot; alt=&quot;Win95 drvspace 06&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Nach einem finalen Reboot landete man wieder im gewohnten Win95 System
und konnte sich an einigen Einstellungen im Drivespace Tool erfreuen, um
z.B. den freien Speicherplatz zwischen Host und virtuellen Laufwerk
neu festlegen zu können.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/win95-drvspace-07.png&quot; alt=&quot;Win95 drvspace 07&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Echt interessant ist, dass obwohl das Tool hier “Drivespace” hieß,
wieder der alte Dateiname &lt;code&gt;dblspace&lt;/code&gt; im Dateisystem herhalten musste.&lt;/p&gt;

&lt;p&gt;Auf dem &lt;code&gt;H:&lt;/code&gt; Laufwerk fand man nun auch die versteckten Ordner mit dem
Mini-Windows. Weitere Eingriffe (z.B. Dekompression) führten ebenfalls zu 
einem Neustart, wo dann der 16-Bit Code die eigentlichen Arbeiten übernahm.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/win95-drvspace-08.png&quot; alt=&quot;Win95 drvspace 08&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;windows-95-plus-drivespace-3&quot;&gt;Windows 95 Plus!: Drivespace 3.&lt;/h3&gt;

&lt;p&gt;Das Windows 95 Plus! Pack ist eine Zusatzsoftware von Microsoft, welche
Windows mit neuen Designs und weiteren Tools ausstattete.
Darunter war auch ein Upgrade für Drivespace, genannt “Drivespace 3”.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/win95-pluspack-2.png&quot; alt=&quot;Win95 Plus Pack&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Nach der Installation des Feature-Upgrades konnte man das ältere virtuelle
Laufwerk auf neue und bessere Formate umstellen lassen.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/win95-drvspace-09.png&quot; alt=&quot;Win95 drvspace 09&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Dabei wurden ein stärkere Kompression und der Support für größere 
Laufwerke angeboten.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/win95-drvspace-10.png&quot; alt=&quot;Win95 drvspace 10&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Es fand dann wieder ein Boot ins Mini-Windows statt, welches die Festplatte
nochmals umackerte.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/win95-drvspace-11.png&quot; alt=&quot;Win95 drvspace 11&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Und am Ende waren ein paar weitere Optionen auswählbar:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/win95-drvspace-12.png&quot; alt=&quot;Win95 drvspace 12&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Hier konnte man die neuere “HiPack” Kompression aktivieren, doch dafür wurde
mindestens ein Pentium PC empfohlen, während bei älteren 486er Prozessoren
dieses Format als zu CPU-intensiv beschrieben wurde.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/win95-drvspace-13.png&quot; alt=&quot;Win95 drvspace 13&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;windows-98-und-später&quot;&gt;Windows 98 und später&lt;/h3&gt;

&lt;p&gt;Drivespace wurde auf 
&lt;a href=&quot;https://de.wikipedia.org/wiki/File_Allocation_Table#FAT32&quot;&gt;FAT32&lt;/a&gt; Laufwerken 
nicht mehr unterstützt und dank der schnell wachsenden immer billiger 
werdenden Speicher, wurde dieses Feature unnötig.&lt;br /&gt;
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_98&quot;&gt;Windows 98&lt;/a&gt; hatte noch 
Support dafür integriert, doch da 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_NT_4.0&quot;&gt;Windows NT&lt;/a&gt; 
eine ganze andere auf &lt;a href=&quot;https://de.wikipedia.org/wiki/NTFS&quot;&gt;NTFS&lt;/a&gt; Ebene 
laufende Kompression integriert hatte, starb Drivespace mit dem Wechsel zu 
Windows 2000 und Windows XP aus.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Aus heutiger Sicht erscheint Kompression auf dieser Ebene unnötig und auch
kritisch, denn bei Datenträgerschäden ist unter Umständen das ganze Laufwerk
nicht mehr lesbar und sein Inhalt verloren.&lt;/p&gt;

&lt;p&gt;Interessant ist aber, dass erst mit 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_Vista&quot;&gt;Windows Vista&lt;/a&gt; bzw. 
7 eine ganz ähnliche Technik wieder in Windows Einzug erhalten hat. 
Denn WIM-Dateien sind ebenso virtuelle Datenträger Dateien, die vom OS 
native auch zum Booten unterstütz werden können.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_PE&quot;&gt;Windows PE&lt;/a&gt; funktioniert 
generell so, dass die komprimierte boot.wim als virtuelle Laufwerk &lt;code&gt;X:&lt;/code&gt; 
geladen wird, wo alle anderen Windows-Systemdateien enthalten sind.&lt;/p&gt;

&lt;p&gt;Ich muss auch zugeben, dass Double/Drivespace für mich einen Klugscheißer
Vorteil bot, denn damit konnte ich “magisch” Speicherplatz verdoppeln und
bei Verwandten bis hin zu Lehrern Eindruck schinden, die sich so eine
Funktion nicht vorstellen konnten.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Tja… wieder so eine schöne Erinnerung an damals 
… als alles noch viel besser war.&lt;br /&gt;
Nur der freie Speicherplatz, der war auch trotz Kompression immer zu wenig.&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>Apcsilmic ARM64 Qualcomm Windows Drivers</title>
   <link href="https://www.opengate.at/blog/2022/10/apcsilmic-drivers/"/>
   <published>2022-10-16T13:00:00+02:00</published>
   <updated>2022-10-16T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2022/10/apcsilmic-drivers</id>
   <category term="hardware" /><category term="software" />
   <summary type="text">Wenn ich ein frisches Windows 11 
IOT ARM64
oder Windows 10 IOT ARM64 auf meinem 
Apcsilmic Dot 1 Mini-PC 
installieren möchte, scheitert das Ganze schon vor der Installation, weil 
Maus, Tastatur und USB
generell nicht funktionieren.

Es fehlen also die notwendigen Treiber … und ich finde diese auch nicht
als Download im Internet.
Also … was tun?
</summary>
   <content type="html">&lt;p&gt;Wenn ich ein frisches &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_11&quot;&gt;Windows 11&lt;/a&gt; 
IOT &lt;a href=&quot;https://de.wikipedia.org/wiki/Arm-Architektur#Armv8-A_(2011)&quot;&gt;ARM64&lt;/a&gt;
oder Windows 10 IOT ARM64 auf meinem 
&lt;a href=&quot;/blog/2022/06/apcsilmic/&quot;&gt;Apcsilmic Dot 1 Mini-PC&lt;/a&gt; 
installieren möchte, scheitert das Ganze schon vor der Installation, weil 
Maus, Tastatur und &lt;a href=&quot;https://de.wikipedia.org/wiki/Universal_Serial_Bus&quot;&gt;USB&lt;/a&gt;
generell nicht funktionieren.&lt;/p&gt;

&lt;p&gt;Es fehlen also die notwendigen Treiber … und ich finde diese auch nicht
als Download im Internet.&lt;br /&gt;
Also … was tun?
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;windows-on-arm-neu-installieren&quot;&gt;Windows on ARM neu installieren&lt;/h3&gt;

&lt;p&gt;Die mitgelieferte Windows Lizenz auf meinem kleinen ARM-PC ist vermutlich
der größte Kritikpunkt. Denn im Netz findet man einige Berichte, dass die
Herstellerfirma entweder kein aktiviertes Windows vorinstalliert hatte,
oder die Lizenz “irgendwie fehlerhaft” sei.&lt;/p&gt;

&lt;p&gt;Für mich ist das kein Problem, da mir mein (teures) 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Developer_Network&quot;&gt;MSDN&lt;/a&gt; Abo 
ausreichend Windows-Lizenzen beschert. Doch interessanterweise habe ich 
genau das auf dem PC eingesetzte “Windows 11 Pro” nicht für ARM64 verfügbar.&lt;/p&gt;

&lt;p&gt;Nur “Windows 11 Enterprise” und “Windows 11 IOT Enterprise” habe ich im
Angebot und gleiches gilt auch für Windows 10. Alle anderen Downloads
betreffen nur x86 und x64.&lt;/p&gt;

&lt;h3 id=&quot;problem-keine-qualcomm-treiber-im-windows-image&quot;&gt;Problem: Keine Qualcomm Treiber im Windows Image&lt;/h3&gt;

&lt;p&gt;Wenn man ein ARM64 ISO Image dann auf einen 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Unified_Extensible_Firmware_Interface&quot;&gt;UEFI&lt;/a&gt;
FAT32 USB-Stick kopiert, boot der kleine PC auch brav in dessen Setup, kann 
aber dann die USB Ports nicht neu laden und man landet auf dem Setup 
Startbildschirm, kann aber in keinster Weise “Weiter” klicken.&lt;br /&gt;
Unter den Hardware-IDs im vorinstallierten Windows fand ich im Netz genau
gar nichts und weder auf der Herstellerseite, noch bei 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Qualcomm&quot;&gt;Qualcomm&lt;/a&gt; fand ich einen Treiber 
für Geräte wie:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Qualcomm(R) XHCI Filter Device&lt;/li&gt;
  &lt;li&gt;Qualcomm(R) USB Type-C Device&lt;/li&gt;
  &lt;li&gt;Qualcomm(R) Adreno(TM) 618 GPU&lt;/li&gt;
  &lt;li&gt;Qualcomm(R) Aqstic(TM) Audio Device&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;lösung-treiber-extrahieren&quot;&gt;Lösung: Treiber extrahieren&lt;/h3&gt;

&lt;p&gt;Wie gut, dass das Tool &lt;code&gt;dism&lt;/code&gt; inzwischen gelernt hat, aller Treiber aus 
einem bestehend Windows Image zu extrahieren.&lt;br /&gt;
Ich startete das originale Windows 11 im Reparaturmodus, wechselte zur 
Konsole und führte folgendes Kommando aus:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;mkdir c:\drivers
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;dism /Image:C:\Windows /Export-Driver /Destination:C:\drivers
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Das hätte man auch im laufenden Windows mit&lt;br /&gt;
&lt;code&gt;dism.exe /Online /Export-Driver /Destination:C:\drivers&lt;/code&gt; hinbekommen, aber 
ich wollte ohnehin die gesamte Windows-Installation in eine Backup-WIM-Datei
sichern.&lt;/p&gt;

&lt;p&gt;So kamen 96 Unterverzeichnisse mit jeder Menge Qualcomm Treiber heraus, die
ich wieder in ein anderes Windows Image integrieren kann.&lt;/p&gt;

&lt;h3 id=&quot;treiber-in-boot-und-installations-image-integrieren&quot;&gt;Treiber in Boot und Installations-Image integrieren.&lt;/h3&gt;

&lt;p&gt;In meinen Windows 10 und 11 IOT Images beinhalteten sowohl 
&lt;code&gt;sources/boot.wim&lt;/code&gt;, wie auch &lt;code&gt;sources/install.wim&lt;/code&gt; je zwei Images (einmal 
IOT und einmal nur  Enterprise) und so integrierte ich die zuvor 
exportierten Treiber allesamt viermal.&lt;/p&gt;

&lt;p&gt;Würde ich dafür ein Script schreiben, sähe das etwa so aus:&lt;/p&gt;

&lt;div class=&quot;language-batch highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;@ECHO OFF
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;SET PATH_TO_SETUP_FILES=c:\path\to\extracted_win_iso
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;SET PATH_TO_DRIVERS=C:\path\to\drivers
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;cd %PATH_TO_SETUP_FILES%
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;cd sources
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;mkdir mount
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;ECHO Adding drivers to boot image 1
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;dism /Mount-Wim /WimFile:boot.wim /index:1 /MountDir:mount
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;dism /Image:mount /Add-Driver /Driver:%PATH_TO_DRIVERS% /recurse
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;dism /UnMount-Wim /MountDir:mount /commit
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;ECHO Adding drivers to boot image 2
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;dism /Mount-Wim /WimFile:boot.wim /index:2 /MountDir:mount
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;dism /Image:mount /Add-Driver /Driver:%PATH_TO_DRIVERS% /recurse
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;dism /UnMount-Wim /MountDir:mount /commit
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;ECHO Adding drivers to windows image 1
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;dism /Mount-Wim /WimFile:install.wim /index:1 /MountDir:mount
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n21&quot; name=&quot;n21&quot;&gt;21&lt;/a&gt;&lt;/span&gt;dism /Image:mount /Add-Driver /Driver:%PATH_TO_DRIVERS% /recurse
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n22&quot; name=&quot;n22&quot;&gt;22&lt;/a&gt;&lt;/span&gt;dism /UnMount-Wim /MountDir:mount /commit
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n23&quot; name=&quot;n23&quot;&gt;23&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n24&quot; name=&quot;n24&quot;&gt;24&lt;/a&gt;&lt;/span&gt;ECHO Adding drivers to windows image 2
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n25&quot; name=&quot;n25&quot;&gt;25&lt;/a&gt;&lt;/span&gt;dism /Mount-Wim /WimFile:install.wim /index:2 /MountDir:mount
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n26&quot; name=&quot;n26&quot;&gt;26&lt;/a&gt;&lt;/span&gt;dism /Image:mount /Add-Driver /Driver:%PATH_TO_DRIVERS% /recurse
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n27&quot; name=&quot;n27&quot;&gt;27&lt;/a&gt;&lt;/span&gt;dism /UnMount-Wim /MountDir:mount /commit
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n28&quot; name=&quot;n28&quot;&gt;28&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n29&quot; name=&quot;n29&quot;&gt;29&lt;/a&gt;&lt;/span&gt;rmdir mount
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n30&quot; name=&quot;n30&quot;&gt;30&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;ECHO Splitting install.wim into SWM files
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n31&quot; name=&quot;n31&quot;&gt;31&lt;/a&gt;&lt;/span&gt;dism /Split-Image /ImageFile:install.wim /SWMFile:install.swm /FileSize:3500
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n32&quot; name=&quot;n32&quot;&gt;32&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n33&quot; name=&quot;n33&quot;&gt;33&lt;/a&gt;&lt;/span&gt;ECHO Deleting original install.wim
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n34&quot; name=&quot;n34&quot;&gt;34&lt;/a&gt;&lt;/span&gt;del install.wim
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Die originalen &lt;code&gt;install.wim&lt;/code&gt; Dateien waren knapp unter 4 GB und wuchsen
durch die Treiber Patches auf über 4 GB an, daher mussten die &lt;code&gt;wim&lt;/code&gt; Dateien 
in &lt;code&gt;swm&lt;/code&gt; Dateien aufgesplittet werden, damit sie auf einen FAT32 USB-Stick 
passen.&lt;/p&gt;

&lt;h3 id=&quot;installation-von-windows-11-und-windows-10&quot;&gt;Installation von Windows 11 und Windows 10&lt;/h3&gt;

&lt;p&gt;Und siehe da, das aktualisierte Windows Setup konnte die USB Ports und somit
Maus und Tastatur erkennen, womit die restliche Installation auf ARM64 genau
so verlief wie auch unter x86/x64.&lt;/p&gt;

&lt;p&gt;Etwas ins Schwitzen geriet ich beim ersten Start nach dem Setup, denn da
verharrte der Bildschirm 10 Minuten lang mit dem Hinweis:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Getting ready&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Doch nachdem die Treiber auch in &lt;code&gt;install.wim&lt;/code&gt; wirkten, wurden sie alle 
korrekt im System registriert … es dauerte nur eben recht lange ohne
weitere Hinweise.&lt;/p&gt;

&lt;p&gt;(Und da dem dot 1 Mini-PC LEDs für Festplattenzugriffe fehlen, weiß man
eben nicht, ob er eingefroren ist, oder im Hintergrund weiterarbeitet).&lt;/p&gt;

&lt;p&gt;Nach einer erfolgreichen Installation von Windows 11 IOT wiederholte ich
die Treiber-Integration in Windows 10 IOT und stellte fest, dass auch diese
Installation perfekt ohne Probleme ablief.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Mission erfolgreich durchgeführt!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Tatsächlich kommt es mir so vor, als wäre Windows 10 flüssiger im Betrieb
auf dem Kleinrechner, als das originale Windows 11 oder mein Windows 11 IOT.&lt;/p&gt;

&lt;p&gt;Allerdings funktioniert auf Windows 10 ARM64 das neue 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_Studio&quot;&gt;Visual Studio&lt;/a&gt; mit nativem ARM
Support nicht. Daher ist am Ende Windows 11 vielleicht doch die bessere Wahl.&lt;/p&gt;

&lt;p&gt;Ich bin jedenfalls glücklich, denn das Experiment hätte ja auch schief gehen
können und “Software-Support” ist für diese Hardware vermutlich nicht 
zubekommen.&lt;/p&gt;

&lt;p&gt;Es liegt also nur an der Verfügbarkeit von Treibern und an ein paar &lt;code&gt;dism&lt;/code&gt;
Zeilen, dass man sich eine Windows on ARM Installation selbst 
zusammenstellen kann.&lt;br /&gt;
Dass die Qualcomm Treiber im Windows-11 Standard-Setup fehlten verstört mich
etwas, schließlich hat Microsoft exklusive Verträge mit der Chip-Schmiede.&lt;/p&gt;

&lt;p&gt;Doch mit dem Wissen, wie ich die Treiber “konservieren” und “reintegrieren”
konnte, kann ich nun weiter für mehr Einsatz von ARM Systemen werben.
Besonders im Unternehmensbereich ist es wichtig, dass auch diese 
(heute noch exotische) Hardware genau so verwaltet werden kann, wie es 
mit x86 getan wird.&lt;/p&gt;

&lt;h3 id=&quot;nachtrag&quot;&gt;Nachtrag&lt;/h3&gt;

&lt;p&gt;Die Visual Studio 2022 Build-Tools (also Compiler ohne IDE) lassen sich auch
unter Windows 10 ARM64 installieren, es handelt sich dabei jedoch um x86
Binaries für Cross-Compiling, und außerdem unterstützt Windows 10 nur
x86, aber keine x64 Emulation.&lt;/p&gt;

&lt;p&gt;Und noch etwas konnte ich bestätigen: Minecraft läuft einigermaßen 
vernünftig, auf dem 7-Watt-PC, wenn man optische Verschönerungen wie Wolken 
und durchsichtige Baumblätterblöcke deaktiviert.&lt;br /&gt;
Nur manchmal gehen ein paar Frames verloren. Zum Bauen reicht das, an 
Weltmeisterschaften würde ich aber so nicht teilnehmen ;)&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>She-Hulk! Quo vadis, MCU?</title>
   <link href="https://www.opengate.at/blog/2022/10/she-hulk/"/>
   <published>2022-10-15T13:00:00+02:00</published>
   <updated>2022-10-15T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2022/10/she-hulk</id>
   <category term="entertainment" />
   <summary type="text">Also … den W-T-F-Award 2022 haben die Marvel Studios jetzt eindeutig 
gewonnen.

Denn diese Woche lief das Serien-Finale der She-Hulk Staffel über Disney Plus.
</summary>
   <content type="html">&lt;p&gt;Also … den W-T-F-Award 2022 haben die Marvel Studios jetzt eindeutig 
gewonnen.&lt;/p&gt;

&lt;p&gt;Denn diese Woche lief das Serien-Finale der She-Hulk Staffel über Disney Plus.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;strong&gt;Achtung! Spoiler folgt!&lt;/strong&gt;&lt;/p&gt;

&lt;h3 id=&quot;man-vögelt-offenbar-wieder-gerne-viel&quot;&gt;Man vögelt offenbar wieder gerne viel&lt;/h3&gt;

&lt;p&gt;Das letzte Mal, dass ich derart zusehen konnte, wie es einer Frau 
“sehr nach Männern verlangt”, war wohl in einem Porno gedreht Ende der 90er
Jahre.&lt;/p&gt;

&lt;p&gt;Denn die als “Superhelden-Serie” vorgestellte She-Hulk Staffel hat nur ein
wesentliches durchgehendes Element und das sind die Versuche von 
“Jennifer Walters”, die versehentlich etwas Blut des Hulk abgekommen hatte,
sich einen Mann zu angeln.&lt;/p&gt;

&lt;p&gt;Dabei kommt stets heraus, dass alle Männer Schweine sind, außer Daredevil,
der ist ein liebenswerter Engel (im Bett).&lt;/p&gt;

&lt;p&gt;Wäre das jetzt keine Marvel Serie gewesen, hätte ich vermutlich einen
Vergleich zu &lt;a href=&quot;https://de.wikipedia.org/wiki/Jersey_Shore&quot;&gt;Jersey Shore&lt;/a&gt; 
oder &lt;a href=&quot;https://de.wikipedia.org/wiki/Desperate_Housewives&quot;&gt;Desperate Housewives&lt;/a&gt;
gewagt.&lt;br /&gt;
Aber so bin ich völlig verwirrt, was das jetzt sollte.&lt;/p&gt;

&lt;h3 id=&quot;kein-leitfaden&quot;&gt;Kein Leitfaden&lt;/h3&gt;

&lt;p&gt;Die Phase 1-3 läuteten den Erfolg von Marvel vor allem dadurch ein, dass die
Filme und Nebenprojekte zusammenspielten und auf ein gemeinsames Ziel 
hinarbeiteten.&lt;/p&gt;

&lt;p&gt;Und des sah am Anfang von Phase 4 mit Wanda-Vision, Loki und Falcon so aus,
als würde diese Idee auch in den Disney-Plus Serien fortgesetzt werden.&lt;/p&gt;

&lt;p&gt;Doch dann kamen Moonknight und Ms.Marvel, wie auch der 4. Thor Film, die 
zwar weiter im Marvel Universum spielen, aber nicht mehr so wirklich zum
Gesamtbild passten.&lt;/p&gt;

&lt;p&gt;Aber nichts bisher wich so eklatant ab, wie She-Hulk.&lt;/p&gt;

&lt;h3 id=&quot;eine-frauen-serie-&quot;&gt;Eine Frauen-Serie ??&lt;/h3&gt;

&lt;p&gt;Ja, vielleicht denke ich falsch, den “Superhelden” hatten immer eine sehr
männlich geprägten Kampfhintergrund, in dem Frauen leider viel zu oft zu
Nebenfiguren degradiert wurden.&lt;br /&gt;
Mir ist schon klar, dass “die neue weibliche Hauptrolle” auch bewusst 
anders geschrieben sein musste, als vergangene Akteure.&lt;/p&gt;

&lt;p&gt;Aber warum kommt She-Hulk dann wie die dümmste “Tussi” bei mir an, die sich
primär für ihr Aussehen interessiert und wie sie Männer beeindrucken kann,
wobei mit der Berufsrolle der Anwältin doch eine super Vorlage für eine
seriöse Figur geschaffen wurde?&lt;/p&gt;

&lt;p&gt;Ich frage mich daher, ob man hier bewusst einen Gegenpol zu Scarlett Johannson’s
“Black Widow” herbei schreiben wollte … oder ob das einfach nur passiert ist.&lt;/p&gt;

&lt;h3 id=&quot;selbstironie&quot;&gt;Selbstironie&lt;/h3&gt;

&lt;p&gt;“Die 4. Wand zu brechen” und mit dem Publikum zu sprechen, ist inzwischen
schon häufiger in Marvel Serien passiert, doch She-Hulk treibt es auf die
Spitze und zwar so extrem, dass ich es auch beim besten Willen nicht mehr
als lustig empfinden kann.&lt;/p&gt;

&lt;p&gt;Und als dann am Ende auch noch der Marvel-Roboter “KEVIN” eingeführt wird,
von dem sich She-Hulk ein besseres Ende für die eigene Serie wünschen kann,
und ihr dieser Wunsch erfüllt wird, war der Bock aus meiner Sicht vollkommen
abgeschossen.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Quo vadis, Marvel?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Tja, wenn man mal Fan ist, bleibt man es auch.&lt;br /&gt;
Die She-Hulk Serie ist eine einzige Karikatur des Superhelden-Genres und 
wenn man es so betrachtet, kann man es auch lustig finden und genießen.&lt;/p&gt;

&lt;p&gt;Und trotzdem bemerke ich, dass dieser immer weiter um sich greifende 
Extremismus in Sachen Übertreibung mich immer weiter abschreckt.&lt;/p&gt;

&lt;p&gt;Es ist schon klar, dass man neue Geschichten heute anders bringen muss,
um nicht sofort mit den Urgesteinen IronMan, Thor und Captain Amerika
gleichgesetzt werden zu können.&lt;br /&gt;
Ich kann aber zur aktuellen Entwicklung leider nur sagen:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Nein, so bitte nicht.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Aber zugegeben … mir fehlt auch eine Vorstellung, wo ich dann hätte
sagen können:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Genau so hätte es sein sollen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Und somit hoffe ich auf das beste und bete dafür, dass weitere Serien
(wie Loki 2) nicht auch in diese Billig-Comedy Schiene einrasten.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>SFTP über libssh2</title>
   <link href="https://www.opengate.at/blog/2022/10/ssl-ssh2/"/>
   <published>2022-10-09T13:00:00+02:00</published>
   <updated>2022-10-09T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2022/10/ssl-ssh2</id>
   <category term="devel" />
   <summary type="text">Wenn im eigenen Programm eine SSH
Verbindung aufgebaut werden soll um Dateien auszutauschen oder eine entfernte
Shell ferngesteuert werden soll, dann greife ich zur libssh2 Bibliothek,
die als Aufsatz von OpenSSL viele
SSH Features zur Verfügung stellt.
</summary>
   <content type="html">&lt;p&gt;Wenn im eigenen Programm eine &lt;a href=&quot;https://de.wikipedia.org/wiki/Secure_Shell&quot;&gt;SSH&lt;/a&gt;
Verbindung aufgebaut werden soll um Dateien auszutauschen oder eine entfernte
Shell ferngesteuert werden soll, dann greife ich zur &lt;code&gt;libssh2&lt;/code&gt; Bibliothek,
die als Aufsatz von &lt;a href=&quot;https://de.wikipedia.org/wiki/OpenSSL&quot;&gt;OpenSSL&lt;/a&gt; viele
SSH Features zur Verfügung stellt.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Mit der zunehmenden Verbreitung von &lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt;,
kommt man an der Remote-Verwaltung über SSH nicht mehr vorbei. Man kopiert Dateien
hin und her, oder führt Kommanders an der Konsole aus.&lt;/p&gt;

&lt;p&gt;Übel wird mir immer, wenn in C oder C++ Programmen dann per&lt;br /&gt;
&lt;code&gt;system(&quot;ssh .....&quot;)&lt;/code&gt; solche Features “eingebaut” werden, in der Hoffnung,
ein &lt;code&gt;ssh&lt;/code&gt; ist installiert und erreichbar und alle Parameter sind korrekt 
übergeben. Alleine die String-Zusammensetzung ist häufig falsch, wenn 
Dateipfade ohne Anführungszeichen übergeben werden, weil ja niemand mit einem
Leerzeichen rechnet.&lt;/p&gt;

&lt;p&gt;Aus diesem Grund greife ich dann zur &lt;code&gt;libssh2&lt;/code&gt; und lasse dieses geniale 
Werkzeug die Protokollarbeit durchführen und erhalte dann schlüssige
Fehler- oder Erfolgscodes zurück.&lt;/p&gt;

&lt;p&gt;Angenehm ist vor allem, dass die Socketverwaltung einem selbst überlassen
bleibt. Man erzeugt sich seinen Socket genau so, wie man ihn braucht,
also &lt;a href=&quot;https://de.wikipedia.org/wiki/Transmission_Control_Protocol&quot;&gt;TCP&lt;/a&gt; auf
IPv4 oder IPv6 und “startet” die libssh2 damit, welche dann
nur mit &lt;a href=&quot;https://pubs.opengroup.org/onlinepubs/007904975/functions/recv.html&quot;&gt;recv()&lt;/a&gt;
und &lt;a href=&quot;https://pubs.opengroup.org/onlinepubs/007904975/functions/send.html&quot;&gt;send()&lt;/a&gt;
auf diesem arbeitet.&lt;/p&gt;

&lt;p&gt;Interessant ist der Login, bei dem man mit einem Login-Namen anfragt, 
welche Authentifizierung dafür vorgesehen ist und kann dann mit einer
Passwort-, Texteingabe oder Public-Key-Angabe reagieren.&lt;/p&gt;

&lt;p&gt;Aber … ein Code sagt mehr als 1000 Worte:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;static&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt; kbd_callback(
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt; *name, &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; name_len,
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt; *instruction, &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; instruction_len,
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; num_prompts,
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt; LIBSSH2_USERAUTH_KBDINT_PROMPT *prompts,
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  LIBSSH2_USERAUTH_KBDINT_RESPONSE *responses,
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt; **abstract)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt;(num_prompts != &lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;  {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#777&quot;&gt;/* unsupported interactive lines */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;  }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;/* one prompt/response pair is likely a password request */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt;* pass = &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;mypass&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;  size_t pass_len = strlen(pass);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt;* buffer = (&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt;*)malloc(pass_len + &lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  memcpy(buffer, pass, pass_len);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n21&quot; name=&quot;n21&quot;&gt;21&lt;/a&gt;&lt;/span&gt;  responses[&lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;].text = buffer;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n22&quot; name=&quot;n22&quot;&gt;22&lt;/a&gt;&lt;/span&gt;  responses[&lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;].length = pass_len;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n23&quot; name=&quot;n23&quot;&gt;23&lt;/a&gt;&lt;/span&gt;}
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n24&quot; name=&quot;n24&quot;&gt;24&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n25&quot; name=&quot;n25&quot;&gt;25&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;static&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt; run_ssh_client(&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; connected_tcp_socket)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n26&quot; name=&quot;n26&quot;&gt;26&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n27&quot; name=&quot;n27&quot;&gt;27&lt;/a&gt;&lt;/span&gt;  libssh2_init(&lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n28&quot; name=&quot;n28&quot;&gt;28&lt;/a&gt;&lt;/span&gt;  LIBSSH2_SESSION* session = libssh2_session_init();
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n29&quot; name=&quot;n29&quot;&gt;29&lt;/a&gt;&lt;/span&gt;  libssh2_session_set_blocking(session, &lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n30&quot; name=&quot;n30&quot;&gt;30&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  libssh2_session_set_timeout(session, &lt;span style=&quot;color:#00D&quot;&gt;10000&lt;/span&gt;); &lt;span style=&quot;color:#777&quot;&gt;/* 10 seconds */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n31&quot; name=&quot;n31&quot;&gt;31&lt;/a&gt;&lt;/span&gt;  libssh2_session_startup(session, connected_tcp_socket);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n32&quot; name=&quot;n32&quot;&gt;32&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt;* authlist = libssh2_userauth_list(session, 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n33&quot; name=&quot;n33&quot;&gt;33&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;myuser&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, strlen(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;myuser&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;));
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n34&quot; name=&quot;n34&quot;&gt;34&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt;(strstr(authlist, &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;password&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;))
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n35&quot; name=&quot;n35&quot;&gt;35&lt;/a&gt;&lt;/span&gt;  {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n36&quot; name=&quot;n36&quot;&gt;36&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#777&quot;&gt;/* send the password directly */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n37&quot; name=&quot;n37&quot;&gt;37&lt;/a&gt;&lt;/span&gt;    libssh2_userauth_password_ex(
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n38&quot; name=&quot;n38&quot;&gt;38&lt;/a&gt;&lt;/span&gt;      session,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n39&quot; name=&quot;n39&quot;&gt;39&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;myuser&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, strlen(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;myuser&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;),
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n40&quot; name=&quot;n40&quot;&gt;40&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;      &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;mypass&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, strlen(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;mypass&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;),
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n41&quot; name=&quot;n41&quot;&gt;41&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#069&quot;&gt;NULL&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n42&quot; name=&quot;n42&quot;&gt;42&lt;/a&gt;&lt;/span&gt;  }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n43&quot; name=&quot;n43&quot;&gt;43&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;else&lt;/span&gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt;(strstr(authlist, &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;keyboard-interactive&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;))
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n44&quot; name=&quot;n44&quot;&gt;44&lt;/a&gt;&lt;/span&gt;  {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n45&quot; name=&quot;n45&quot;&gt;45&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#777&quot;&gt;/* the keyboard-callback function sends the password */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n46&quot; name=&quot;n46&quot;&gt;46&lt;/a&gt;&lt;/span&gt;    libssh2_userauth_keyboard_interactive_ex(
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n47&quot; name=&quot;n47&quot;&gt;47&lt;/a&gt;&lt;/span&gt;      session,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n48&quot; name=&quot;n48&quot;&gt;48&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;myuser&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, strlen(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;myuser&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;),
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n49&quot; name=&quot;n49&quot;&gt;49&lt;/a&gt;&lt;/span&gt;      &amp;amp;kbd_callback);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n50&quot; name=&quot;n50&quot;&gt;50&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n51&quot; name=&quot;n51&quot;&gt;51&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;else&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n52&quot; name=&quot;n52&quot;&gt;52&lt;/a&gt;&lt;/span&gt;  {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n53&quot; name=&quot;n53&quot;&gt;53&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#777&quot;&gt;/* unsupported authentication method */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n54&quot; name=&quot;n54&quot;&gt;54&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n55&quot; name=&quot;n55&quot;&gt;55&lt;/a&gt;&lt;/span&gt;  }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n56&quot; name=&quot;n56&quot;&gt;56&lt;/a&gt;&lt;/span&gt;  LIBSSH2_SFTP* sftp = libssh2_sftp_init(session);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n57&quot; name=&quot;n57&quot;&gt;57&lt;/a&gt;&lt;/span&gt;  LIBSSH2_SFTP_HANDLE* handle = libssh2_sftp_open_ex(sftp,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n58&quot; name=&quot;n58&quot;&gt;58&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;/proc/version&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, strlen(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;/proc/version&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;), 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n59&quot; name=&quot;n59&quot;&gt;59&lt;/a&gt;&lt;/span&gt;    LIBSSH2_FXF_READ, LIBSSH2_SFTP_S_IFREG, LIBSSH2_SFTP_OPENFILE);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n60&quot; name=&quot;n60&quot;&gt;60&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt; content_buffer[&lt;span style=&quot;color:#00D&quot;&gt;4096&lt;/span&gt;] = { &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt; };
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n61&quot; name=&quot;n61&quot;&gt;61&lt;/a&gt;&lt;/span&gt;  libssh2_sftp_read(handle, content_buffer, &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;sizeof&lt;/span&gt;(content_buffer) - &lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n62&quot; name=&quot;n62&quot;&gt;62&lt;/a&gt;&lt;/span&gt;  printf(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;%s&lt;/span&gt;&lt;span style=&quot;color:#b0b&quot;&gt;\n&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, content_buffer);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n63&quot; name=&quot;n63&quot;&gt;63&lt;/a&gt;&lt;/span&gt;  libssh2_sftp_close_handle(handle);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n64&quot; name=&quot;n64&quot;&gt;64&lt;/a&gt;&lt;/span&gt;  libssh2_sftp_shutdown(sftp);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n65&quot; name=&quot;n65&quot;&gt;65&lt;/a&gt;&lt;/span&gt;  libssh2_session_disconnect(session, &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n66&quot; name=&quot;n66&quot;&gt;66&lt;/a&gt;&lt;/span&gt;  libssh2_session_free(session);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n67&quot; name=&quot;n67&quot;&gt;67&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;blockquote&gt;
  &lt;p&gt;Wehe jemand kopiert das ohne die notwendige Fehlerbehandlung
für alle Funktionen!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Wenn der SSH-Server das Passwort direkt akzeptiert wird es per
&lt;code&gt;libssh2_userauth_password_ex&lt;/code&gt; übermittelt.&lt;/p&gt;

&lt;p&gt;Ist Tastatur-Interaktion gewüscht, wird eine Callback-Funktion von 
&lt;code&gt;libssh2_userauth_keyboard_interactive_ex&lt;/code&gt; aufgerufen. Hier kann man 
entweder Tastenanschläge von &lt;code&gt;STDIN&lt;/code&gt; lesen, oder ein vorbereitete 
Passwort gleich in den Antwort-Puffer schreiben.&lt;/p&gt;

&lt;p&gt;Tja und sobald die Session authentifiziert ist, lässt sich eine
SFTP Sitzung starten (&lt;code&gt;libssh2_sftp_init&lt;/code&gt;), mit der man dann ganz ähnlich
zu den POSIX Funktionen &lt;code&gt;open&lt;/code&gt; &lt;code&gt;read&lt;/code&gt; &lt;code&gt;write&lt;/code&gt; &lt;code&gt;close&lt;/code&gt; Dateien lesen und
schreiben kann:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://libssh2.org/libssh2_sftp_open_ex.html&quot;&gt;libssh2_sftp_open_ex&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://libssh2.org/libssh2_sftp_read.html&quot;&gt;libssh2_sftp_read&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://libssh2.org/libssh2_sftp_write.html&quot;&gt;libssh2_sftp_write&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://libssh2.org/libssh2_sftp_close_handle.html&quot;&gt;libssh2_sftp_close_handle&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;libssh2&lt;/code&gt; benötigt nur den Crypto-Teil von OpenSSL oder alternativ von
&lt;a href=&quot;https://de.wikipedia.org/wiki/LibreSSL&quot;&gt;libReSSL&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Neben SFTP Dateioperationen lassen sich auch Prozesse ausführen und
Port-Weiterleitungen einrichten.&lt;/p&gt;

&lt;p&gt;Für diese einfache Möglichkeit mit SSH zu arbeiten, muss man diese
Bibliothek einfach lieben.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>4 Jahre Blog</title>
   <link href="https://www.opengate.at/blog/2022/10/blog-4-years/"/>
   <published>2022-10-08T13:00:00+02:00</published>
   <updated>2022-10-08T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2022/10/blog-4-years</id>
   <category term="general" /><category term="projects" />
   <summary type="text">Unglaublich, doch schon sind wieder 4 Jahre vorbei. 
Und ein bisschen hat sich der alte Witz wieder bewahrheitet:


  Wenn du Gott zum Lachen bringen willst,
dann mache einen Plan.


</summary>
   <content type="html">&lt;p&gt;Unglaublich, doch schon sind wieder 4 Jahre vorbei. 
Und ein bisschen hat sich der alte Witz wieder bewahrheitet:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Wenn du Gott zum Lachen bringen willst,&lt;br /&gt;
dann mache einen Plan.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Aktuell läuft alles etwas unstrukturiert. Es ist, als wäre ich in ein fremdes
Land in eine fremde Stadt gereist, wo ich an jedem Tag eine neue Gasse, einen
neuen Markt und neue Lokale entdecken würde.&lt;br /&gt;
Man isst und schläft nie zweimal am selben Platz.&lt;/p&gt;

&lt;p&gt;Und so geht es mir mit dem GATE Projekt, wo ich zwischen unterschiedlichen
Systemen, Technologien und Zielen hin- und herspringe.&lt;/p&gt;

&lt;p&gt;Doch es macht mir einfach Spaß 5 Zeilen für DOS, 5 Zeilen für Linux, 5 Zeilen
für die WinAPI und 15 für UEFI und dann noch 4x 50 Zeilen Assembler zu 
schreiben um dann festzustellen, dass es doch nicht so ganz ideal war.
Dabei lernt man viel, aber Berge versetzt man damit nicht leider auch nicht
all zu schnell.&lt;/p&gt;

&lt;h3 id=&quot;neue-plattformen&quot;&gt;Neue Plattformen&lt;/h3&gt;

&lt;p&gt;Mit Assembler und EFI habe ich ein faszinierendes Feld betreten, in dem ich 
viel experimentieren kann.&lt;/p&gt;

&lt;p&gt;Und spannenderweise sind es dann die Blog-Artikel, die erst richtig Wissen
aufwühlen, denn beim Verfassen und Verifizieren von Codebeispielen erkenne ich
bessere Lösungen als die, die ich ursprünglich im GATE Projekt
vorgesehen hatte.&lt;br /&gt;
Diese werden dann implementiert, daraus ergeben sich beobachtbare 
Seiteneffekte, die wiederum den Blog-Artikel erweitern oder zu Neuauflagen 
führen.&lt;/p&gt;

&lt;p&gt;So habe ich das Gefühl, das wirklich was “entwickelt” wird, und nicht einfach
nur hingerotzt wird … aber das kostet eben Zeit.&lt;/p&gt;

&lt;h3 id=&quot;datenumstellung&quot;&gt;Datenumstellung&lt;/h3&gt;

&lt;p&gt;Anfang nächsten Jahres werden vermutlich 600 Einzelartikel geschrieben sein 
und nun erweist sich mein “alles-in-einem-Verzeichnis” Ansatz als immer 
mühsamer. Ich werde also eine Aufspaltung mindestens nach Jahren ausprobieren.&lt;/p&gt;

&lt;p&gt;Übergroß sind inzwischen auch die RSS und Suche-Dateien geworden. Es macht
einfach keinen Sinn mehr, alles in eine einzelne XML oder JSON Datei zu
packen. Auch hier muss ich mir was einfallen lassen und die Daten 
besser aufteilen.&lt;br /&gt;
Mal sehen, wann ich dafür Zeit finde.&lt;/p&gt;

&lt;h3 id=&quot;neue-features&quot;&gt;Neue Features&lt;/h3&gt;

&lt;p&gt;Meine Inhalte sind zwar alles andere als Social-Media tauglich, aber dank 
einiger Tutorial-artiger Seiten verteile ich immer wieder mal Links,
wenn eine Frage im Bekannten- oder Kollegenkreis auftritt.&lt;br /&gt;
Genau für so etwas fehlt ein “Teilen” Button wie man ihn von einschlägigen
Seiten kennt, der zumindest mal die URL in die Zwischenablage kopiert.&lt;br /&gt;
Und vielleicht lässt sich auch sonst noch ein bisschen mehr Grafik durch
Unicode-Icons in die Seite bringen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Alles in allem bin ich einigermaßen zufrieden. Das Blog-Projekt wird 
weiterlaufen, schon alleine deshalb, dass ich meine Erkenntnisse 
dokumentieren kann.&lt;/p&gt;

&lt;p&gt;In diesem Sinne:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Bis zum nächsten Blog-Bericht in einem Jahr!&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>Phantastische Icons ...</title>
   <link href="https://www.opengate.at/blog/2022/10/icons/"/>
   <published>2022-10-02T13:00:00+02:00</published>
   <updated>2022-10-02T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2022/10/icons</id>
   <category term="devel" />
   <summary type="text">… und wo sie zu finden sind.

Während es heute ein Volkssport ist, dass jede noch so unnötige App ihre 
eigenen Grafiken designed um möglichst viel Individualität vorzuheucheln,
gab es früher mal die Idee, dass Benutzer sich leicht zurecht finden sollen.

Grafische Elemente sollte das Betriebssystem “zeichnen” und das 
UI dadurch 
einheitlich gestalten.

Die Frage ist nur … wo findet man das heute noch?
</summary>
   <content type="html">&lt;p&gt;&lt;strong&gt;… und wo sie zu finden sind&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Während es heute ein Volkssport ist, dass jede noch so unnötige App ihre 
eigenen Grafiken designed um möglichst viel Individualität vorzuheucheln,
gab es früher mal die Idee, dass Benutzer sich leicht zurecht finden sollen.&lt;/p&gt;

&lt;p&gt;Grafische Elemente sollte das Betriebssystem “zeichnen” und das 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Grafische_Benutzeroberfl%C3%A4che&quot;&gt;UI&lt;/a&gt; dadurch 
einheitlich gestalten.&lt;/p&gt;

&lt;p&gt;Die Frage ist nur … wo findet man das heute noch?
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Um Dateien zu erstellen, öffnen, speichern und kopieren zu können, haben sich
Symbole etabliert, die jeder “im Augenblick” mit der richtigen Funktion 
assoziieren und darauf klicken kann.&lt;br /&gt;
Dass bis heute eine &lt;a href=&quot;https://de.wikipedia.org/wiki/Diskette&quot;&gt;Disketten&lt;/a&gt; Bild 
als “Speichern” interpretiert wird, ist teilweise kurios, 
aber dennoch schlüssig.&lt;/p&gt;

&lt;p&gt;Dumm ist nur, wenn heute Designer versuchen, solche Symbole selbst zu 
zeichnen und so werden lustige “Platten-Kreise” sogar zu “Bleistifte”
in “Corporate-Colors” hingepixelt, und ich sitze dann vor einem UI
und versuche mühsam zu erraten, was das Gebilde jetzt auslösen wird,
wenn ich es anklicke.&lt;/p&gt;

&lt;h3 id=&quot;stock-icons-und--bitmaps&quot;&gt;Stock-Icons und -Bitmaps&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows&quot;&gt;Windows&lt;/a&gt; hatte von Anfang an 
(also zumindest ab Win95/NT4) Grafiken für 
“übliche” Symbole in seinen Innereien integriert und die großen X11-Toolkits
unter Linux taten das gleiche.&lt;/p&gt;

&lt;p&gt;Wer also Menüfunktionen für “Neu”, “Öffnen”, “Speichern”, “Drucken” 
integrieren wollte, konnte dafür eben diese “Standardsymbole” laden und seinen
UI Elementen hinzufügen, anstatt auf nachgezeichnete Eigenfabrikate zu setzen.&lt;/p&gt;

&lt;p&gt;Dadurch wird die “EXE” kleiner und das Programm erhält auch noch stets die
neuesten Grafiken mit jedem neuen OS oder Toolkit Release.&lt;/p&gt;

&lt;h3 id=&quot;winapi&quot;&gt;WinAPI&lt;/h3&gt;

&lt;p&gt;Microsoft hat es aber leider auch hier wieder geschafft eine gute Idee
möglichst schlecht umzusetzen.&lt;/p&gt;

&lt;h4 id=&quot;globale-bitmaps&quot;&gt;Globale Bitmaps&lt;/h4&gt;

&lt;p&gt;Einige wenige Icons und Bitmaps kann man aus einem globalen Pool laden
und dann als &lt;code&gt;HICON&lt;/code&gt; und &lt;code&gt;HBITMAP&lt;/code&gt; völlig frei benutzen. Man nutzt einfach
den &lt;code&gt;HINSTANCE&lt;/code&gt; Parameter mit &lt;code&gt;NULL&lt;/code&gt; und dann eine Resource-ID aus den
WinAPI Headern. 
Doch diese helfen einem wenig, weil es nur Pfeile oder Warnung- und 
Stoppsymbole sind.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;HBITMAP hbmp = LoadBitmap(&lt;span style=&quot;color:#069&quot;&gt;NULL&lt;/span&gt;, OBM_LFARROW);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;HICON hicon = LoadIcon(&lt;span style=&quot;color:#069&quot;&gt;NULL&lt;/span&gt;, IDI_ERROR);
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h4 id=&quot;spezialfall-toolbar&quot;&gt;Spezialfall Toolbar&lt;/h4&gt;

&lt;p&gt;Das Toolbar Control aus den Common-Controls hingegen arbeitet mit einer 
internen “ImageList” und diese kann man veranlassen, dass sie ein Set von 
Standard-Image lädt. Danach kann man mit vordefinierten Grafik-Indices 
übliche Symbole also Toolbar-Buttons anzeigen lassen.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;HIMAGELIST imglist = ImageList_Create(&lt;span style=&quot;color:#00D&quot;&gt;16&lt;/span&gt;, &lt;span style=&quot;color:#00D&quot;&gt;16&lt;/span&gt;, ILC_COLOR16 | ILC_MASK, &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;, &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;SendMessage(hwnd_toolbar, TB_SETIMAGELIST, (WPARAM)&lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;, (LPARAM)imglist);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;SendMessage(hwnd_toolbar, TB_LOADIMAGES, (WPARAM)IDB_STD_SMALL_COLOR, (LPARAM)HINST_COMMCTRL);
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Beim Hinzufügen von Toolbar-Buttons kann man dann Index-Konstanten wie
&lt;code&gt;IDM_NEW&lt;/code&gt;, &lt;code&gt;IDM_OPEN&lt;/code&gt;, &lt;code&gt;IDM_SAVE&lt;/code&gt; nutzen, um Icons für “Neu”, “Öffnen”
und “Speichern” anzuzeigen. Die vollständige Liste ist natürlich
&lt;a href=&quot;https://learn.microsoft.com/en-us/windows/win32/controls/toolbar-standard-button-image-index-values&quot;&gt;in der Dokumentation&lt;/a&gt;;
und ein 
&lt;a href=&quot;https://learn.microsoft.com/en-us/windows/win32/controls/create-toolbars&quot;&gt;Beispiel für die Erstellung von Toolbar Buttons&lt;/a&gt;
ist auch im Netz.&lt;/p&gt;

&lt;h4 id=&quot;shell32dll-als-icon-resource&quot;&gt;Shell32.dll als ICON-Resource&lt;/h4&gt;

&lt;p&gt;Ich nutze im GATE Framework unter anderem auch Icons aus der &lt;code&gt;shell32.dll&lt;/code&gt;.
Es gibt zwar keinen dokumentierten Standard dazu, doch Microsoft hat seit
NT4 in dieser DLL immer nur neue Symbole hinzugefügt, aber bestehende Indices
immer mit den gleichen Grafiken versorgt.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://learn.microsoft.com/en-us/windows/win32/api/shellapi/nf-shellapi-extracticonexa&quot;&gt;ExtractIconEx()&lt;/a&gt;
heißt die Funktion, die aus einer EXE oder DLL Icons herausziehen kann, und
mit den Zahlen für die wichtigsten Symbole, kann man auch so die “aktuellen”
Grafiken erhalten.&lt;/p&gt;

&lt;h3 id=&quot;gtk&quot;&gt;GTK&lt;/h3&gt;

&lt;p&gt;GTK definiert in seinen Headern bzw. in der Doku eine Reihe von Strings, die
zu Grafiken eines Themes verweisen. 
Mit der Funktion &lt;a href=&quot;https://docs.gtk.org/gtk3/method.IconTheme.lookup_icon.html&quot;&gt;gtk_icon_theme_lookup_icon()&lt;/a&gt;
lassen sich dann Icon-namen wie &lt;code&gt;document-save&lt;/code&gt;, &lt;code&gt;edit-copy&lt;/code&gt; oder 
&lt;code&gt;folder-open&lt;/code&gt; laden und in Controls anzeigen.&lt;/p&gt;

&lt;p&gt;Das ist eigentlich eine sehr elegante Lösung … wenn sie nicht instabil wäre.
Denn wenn das Theme eine entsprechende Grafikdatei nicht beinhaltet, kann es
zum Crash kommen. Offenbar fehlt hier die Fehlerbehandlung.&lt;/p&gt;

&lt;p&gt;Mir ist das unter Linux am Raspberry PI leider untergekommen, wo nach der
GTK-3 Installation das Thema nicht korrekt installiert war.&lt;/p&gt;

&lt;h3 id=&quot;silk-icons&quot;&gt;Silk Icons&lt;/h3&gt;

&lt;p&gt;Und weil man sich eben weder unter Windows noch unter Linux wirklich darauf 
verlassen kann, dass alle notwendigen Icons wirklich da sind, habe ich mich
dazu entschieden, einige PNGs der &lt;a href=&quot;http://www.famfamfam.com/lab/icons/silk/&quot;&gt;Silk Icons&lt;/a&gt;
in Pixmaps umzuwandeln und als C-Header dem GATE Projekt beigelegt.&lt;/p&gt;

&lt;p&gt;Denn diese Icons können dann auf jeder Plattform in das eigene Binary 
integriert und zur Laufzeit geladen werden.&lt;/p&gt;

&lt;p&gt;Diese unter der Creative Commons stehende Bildersammlung benötigt nur eine
Erwähnung des Authors und ist ansonsten kostenfrei für alle Zwecke 
nutzbar.&lt;br /&gt;
Empfohlen wurde sie mir vor vielen Jahren mal von einem Open-Source-Officer,
der sie als “sicher” qualifiziert hatte, gegenüber anderen Bildchen aus 
dem Netz.&lt;/p&gt;

&lt;p&gt;Und wer schon mehrere Softwarepakete ausprobiert hat, wird feststellen,
dass die Silk Icons in zahlreichen freien Desktop-Projekten integriert sind.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Eigentlich wünsche ich mir, dass Icons großteils vom Betriebssystem und dessen
aktuellem Theme kommen. Und deshalb bedauere ich sehr, dass der kleinste
gemeinsame Nenner an “bedeutungsgleichen” Icons zwischen Windows und Linux 
leider ein sehr kleiner ist, und dass man auf Non-standards angewiesen ist,
diese Icons dann zu laden.&lt;/p&gt;

&lt;p&gt;Zwar habe ich im GATE Framework einen solche Stock-Icon-Teilmenge definiert,
doch wegen der Crashes unter Linux, habe ich am Ende dann doch wieder die
Silk-Icons eingesetzt.&lt;/p&gt;

&lt;p&gt;Aber auch ein noch so kleines Set an “eindeutigen” Icons ist immer noch 
besser, als der klägliche Versuch mancher Herstelle, ihre eigenen Icons
zu designen.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Corona @ home</title>
   <link href="https://www.opengate.at/blog/2022/10/corona-is-back/"/>
   <published>2022-10-01T13:00:00+02:00</published>
   <updated>2022-10-01T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2022/10/corona-is-back</id>
   <category term="general" />
   <summary type="text">Jetzt hat es mich auch erwischt, nach 2.5 Jahren und 4 Impfungen.

Nun muss ich den “Husten” auskurieren und durchlebe meine erste
“echte” Quarantäne.
</summary>
   <content type="html">&lt;p&gt;Jetzt hat es mich auch erwischt, nach 2.5 Jahren und 4 Impfungen.&lt;/p&gt;

&lt;p&gt;Nun muss ich den “Husten” auskurieren und durchlebe meine erste
“echte” Quarantäne.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Am Donnerstag fühlte ich es schon beim Ausstieg aus dem Bus.
Mir war leicht schwindelig und leichte Kopfschmerzen setzten ein.
Als das nach einer Stunde nicht besser wurde, vermutete ich eine
“übliche” Verkühlung und machte mich auf den Heimweg.&lt;/p&gt;

&lt;p&gt;Der führte mich an der Testbox bei der Apotheke vorbei, wo 
sogleich ein Nasenabstrich gemacht wurde.&lt;/p&gt;

&lt;p&gt;Vorsorglich kaufte ich noch einige Fertigwaren ein und war
glücklich mich zu Hause ins Bett legen zu können, denn die
Kopfschmerzen und der Schwindel wurden stärker.&lt;/p&gt;

&lt;p&gt;Am Abend hatte ich dann meine 38° Fieber und ein “übliches” 
Unwohlsein, also das, was man sich von einem grippalem Infekt erwartet.
Da das Abendessen aber noch sehr gut schmeckte, schloss ich 
&lt;a href=&quot;https://de.wikipedia.org/wiki/COVID-19&quot;&gt;COVID-19&lt;/a&gt; für mich bereits aus.&lt;/p&gt;

&lt;p&gt;Am frühen Morgen am Freitag piepte schon der SMS-Signalton und 
informierte mich über meine positiven Corona-Testung und dass 
ich nun unter Quarantäne stehe.&lt;/p&gt;

&lt;p&gt;Ich informierte daher Arbeitgeber und Kollegen über die Infektion und
meldete mich telefonisch beim Arzt krank.&lt;/p&gt;

&lt;p&gt;Die Quarantäne gilt nun für 5 Tage, wonach ich mich wieder
“freitesten” kann, wenn ich symptomfrei bin.&lt;/p&gt;

&lt;p&gt;An Freitag Abend hatte ich dann auch einen Großteil meines
Geschmackssinnes verloren, doch da das Fieber schon auf 37.3
gesunken war, ging es mir wieder besser.&lt;br /&gt;
Leider fing dann in der Nacht auf Samstag die Husterei an,
was das Durchschlafen nicht gerade erleichterte.&lt;/p&gt;

&lt;p&gt;Und im Laufe des Samstags verbesserte sich dann die Lage etwas.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ich vermute, dass meine Genesung noch ein paar Tage dauern wird,
aber das schlimmste war wohl der Fieberausschlag von Donnerstag
auf Freitag.&lt;/p&gt;

&lt;p&gt;Wenn man von einer etwas laufenden Nase mal absieht, hatte ich sonst 
keine Probleme beim Atmen, nur der gelegentliche Husten kratze im Hals.&lt;/p&gt;

&lt;p&gt;Ich hoffe also, dass ich in den nächsten Tagen die Symptome hinter mir 
lassen kann und bin schon gespannt, wie lange das Freitesten dauern wird.&lt;/p&gt;

&lt;p&gt;Dass ich trotz fast täglicher Busfahrt erst nun von Corona “beglückt”
wurde, war ohnehin unerwartet, denn ich dachte mir schon häufig:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Jetzt hab’ ich es vermutlich auch.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Doch bisher war jeder Test negativ geblieben.&lt;/p&gt;

&lt;p&gt;Ich hoffe nur, dass ich mit meinem kurzen Firmen-Besuch keine
Kollegen angesteckt habe.&lt;/p&gt;

&lt;p&gt;Dass ich aber durchgehend in Geschäften und Verkehrsmitteln stets eine
Maske trage hat vielleicht auch zu meiner langen Verschonung beigetragen.
Und dass der Ausbruch nach 2 Tagen schon wieder vorbei zu sein scheint,
führe ich auf meine Impfungen zurück.&lt;/p&gt;

&lt;p&gt;Denn nicht jede Corona-Geschichte, die mir erzählt wurde, war so “annehmbar”.&lt;/p&gt;

&lt;p&gt;Mal sehen, wie fit ich nächste Woche sein werde.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Assembler und .SAFESEH</title>
   <link href="https://www.opengate.at/blog/2022/09/safeseh/"/>
   <published>2022-09-25T13:00:00+02:00</published>
   <updated>2022-09-25T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2022/09/safeseh</id>
   <category term="devel" />
   <summary type="text">Wenn in einem 32-bit Windows MSVC
Build der Fehler


  fatal error LNK1281: Unable to generate SAFESEH image


auftaucht, liegt es vermutlich an einem fehlenden Exception-Handler
in einem Assembler Modul.
</summary>
   <content type="html">&lt;p&gt;Wenn in einem 32-bit Windows &lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_C%2B%2B&quot;&gt;MSVC&lt;/a&gt;
Build der Fehler&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;fatal error LNK1281: Unable to generate SAFESEH image&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;auftaucht, liegt es vermutlich an einem fehlenden Exception-Handler
in einem &lt;a href=&quot;https://de.wikipedia.org/wiki/Assemblersprache&quot;&gt;Assembler&lt;/a&gt; Modul.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;In der C und &lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B&quot;&gt;C++&lt;/a&gt; Welt übernimmt der 
Compiler den Job, für alle Module Exception Handler zu generieren, wenn es 
notwendig ist. Und der Linker fügt dann alle diese “kompatiblen” Handler in 
die finale Binärdatei zusammen.&lt;/p&gt;

&lt;p&gt;Doch Assembler Module dürfen sich “anders” Verhalten, und wenn man dort
nur seinen Code schreibt, fehlt ein solcher Handler, womit sich dieses
Modul von den anderen C/C++ Modulen unterscheidet.&lt;/p&gt;

&lt;p&gt;Und das führt zum oben genannten Fehler.&lt;/p&gt;

&lt;p&gt;Jetzt kann man entweder die Notwendigkeit von “Safe Exception Handlers” deaktivieren&lt;br /&gt;
(&lt;code&gt;Project Properties&lt;/code&gt; - &lt;code&gt;Linker&lt;/code&gt; - &lt;code&gt;Advanced&lt;/code&gt; - &lt;code&gt;Image Has Safe Exception Handlers&lt;/code&gt;)
oder auch mit der Compiler Option &lt;code&gt;/SAFESEH:NO&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Oder man fügt dem &lt;code&gt;.asm&lt;/code&gt; Modul eine leere SEH-Funktion hinzu und registriert sie mit
der &lt;code&gt;.safeseh&lt;/code&gt; Direktive.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;;my_asmcode.asm
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;.386
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;.MODEL FLAT, C
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;.CODE
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;.SAFESEH my_seh_handler
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;my_seh_handler PROC
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;  ret
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;my_seh_handler ENDP
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;my_real_operative_asm_proc PROC
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;...
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Natürlich muss man jetzt die &lt;code&gt;.asm&lt;/code&gt; Datei auch mit der &lt;code&gt;/safeseh&lt;/code&gt; Option 
kompilieren lassen.&lt;br /&gt;
(&lt;code&gt;ASM File Properties&lt;/code&gt; - &lt;code&gt;Microsoft Macro Assembler&lt;/code&gt; - &lt;code&gt;Advanced&lt;/code&gt; - &lt;code&gt;Use Safe Exception Handler&lt;/code&gt;)&lt;/p&gt;

&lt;p&gt;Wenn man mit &lt;code&gt;CMAKE&lt;/code&gt; arbeitet, hilft einem der Eintrag:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;set_source_files_properties(
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;  my_asmcode.asm
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  PROPERTIES
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  COMPILE_FLAGS &amp;quot;/safeseh&amp;quot;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;)
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Wenn man ein Projekt mit vielen Optionen auf vielen Plattformen kompilieren 
will, vergisst man leider immer wieder, ein paar dieser Optionen und
Options-Kombinationen zu testen.&lt;/p&gt;

&lt;p&gt;Langsam wird es Zeit, dass ich mir jetzt richtige Build-Server für alle meine
Plattformen aufsetze, denn wegen der vielen Möglichkeiten vergesse ich 
zunehmend immer alles auszutesten und “auf Stand” zu halten.&lt;br /&gt;
Und dann wundert man sich plötzlich, wenn etwas nicht mehr baut und merkt 
erst dann mit Schrecken, dass es schon ein halbes Jahr nicht mehr funktioniert.&lt;/p&gt;

&lt;p&gt;Und genau das sollte eine Buildserverumgebung automatisiert erfassen und melden
können.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Alexa, füge einen Buildserver zu meiner Einkaufsliste hinzu.&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>Exception Drama</title>
   <link href="https://www.opengate.at/blog/2022/09/exceptions/"/>
   <published>2022-09-24T13:00:00+02:00</published>
   <updated>2022-09-24T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2022/09/exceptions</id>
   <category term="devel" />
   <summary type="text">
  Einst liebte ich sie … doch da wusste ich noch nicht, woraus sie bestehen.


So könnte man meine aktuelle Beziehung zu C++
Exception beschreiben.
Denn dieses wirklich gute “Sprachmittel” ist so etwas von unterschiedlich 
implementiert, dass man sie nur durch das Neuschreiben eines vollständigen 
Compilers in ihren Abläufen nachvollziehen kann.
</summary>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;Einst liebte ich sie … doch da wusste ich noch nicht, woraus sie bestehen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So könnte man meine aktuelle Beziehung zu &lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B&quot;&gt;C++&lt;/a&gt;
&lt;a href=&quot;https://de.wikipedia.org/wiki/Ausnahmebehandlung#C++&quot;&gt;Exception&lt;/a&gt; beschreiben.
Denn dieses wirklich gute “Sprachmittel” ist so etwas von unterschiedlich 
implementiert, dass man sie nur durch das Neuschreiben eines vollständigen 
Compilers in ihren Abläufen nachvollziehen kann.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;hintergrund-efi&quot;&gt;Hintergrund EFI&lt;/h3&gt;

&lt;p&gt;Ich bin wieder mal im &lt;a href=&quot;https://de.wikipedia.org/wiki/Unified_Extensible_Firmware_Interface&quot;&gt;EFI&lt;/a&gt;
Land unterwegs bzw. würde ich gerne mit einem C++ Compiler dort hinreisen, 
doch das erweist sich mit jedem weiteren Versuch als unmachbarer.&lt;/p&gt;

&lt;p&gt;Ich werde zwar noch nicht aufgeben, aber mit so krassen Widersprüchen 
zwischen den Implementierungen beim gleichen Hersteller hätte ich nie 
gerechnet.&lt;/p&gt;

&lt;p&gt;Hier mal ein Lagebericht von der Front:&lt;/p&gt;

&lt;h3 id=&quot;std-lib-und-runtime&quot;&gt;STD-Lib und Runtime&lt;/h3&gt;

&lt;p&gt;Man sollte glauben, es gäbe einen “Standard” der Standard-Exception Objekte
festlegt. Und den gibt es auch, nur der befasst sich lediglich mit 
öffentlichen Schnittstellen.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;std::exception&lt;/code&gt; wird aber von einigen anderen Klassen geerbt und diese 
bedienen sich dann an unterschiedlichen Methoden aus der Basisklasse, die
nicht spezifiziert sind.&lt;/p&gt;

&lt;p&gt;Microsofts MSVC ändert diese Schnittstellen mit jedem Release leicht ab und
fabriziert so neue Formen &lt;code&gt;std::exception&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Wenn ich nun für EFI einen Build ohne die C++-Runtime erstelle, erhalte ich
zahlreiche “undefinierte” Symbole in Zusammenhang mit &lt;code&gt;std::exception&lt;/code&gt;.
Implementiere ich diese nach, gelten diese nur für eine MSVC Version, z.B.
MSVC-2015. MSVC-2017/19/22 heißen dann die Member anders oder Methoden
werden durch andere ersetzt.&lt;/p&gt;

&lt;p&gt;Eine von mir angestrebte “generische” Implementierung existiert nicht.&lt;/p&gt;

&lt;h3 id=&quot;spezielle-cpu-register-und-adressen&quot;&gt;Spezielle CPU Register und Adressen&lt;/h3&gt;

&lt;p&gt;Viele Exception-Jobs laufen über “interne” Funktionen, die ebenfalls als
“undefinierte” Symbole sichtbar werden, wenn man “Freestanding” zu kompilieren
versucht. Und das wäre gut, denn hier kann man manuell eingreifen.&lt;/p&gt;

&lt;p&gt;Doch leider passiert das nicht überall, und so finde ich im X64-Assembler-Dump
einige Segmentregister-Zugriffe auf &lt;code&gt;FS&lt;/code&gt; zum 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Thread-local_storage&quot;&gt;Thread-Local-Storage&lt;/a&gt; (TLS).
Manchmal werden dafür zwar Funktionen aufgerufen, die man abfangen könnte,
aber &lt;code&gt;FS:addr&lt;/code&gt; Aufrufe, die der Compiler einfügt, gegen die bin ich
leider machtlos.&lt;/p&gt;

&lt;p&gt;Ich kann nur hoffen, dass es sich dabei um Dead-Codes oder um falsche 
Instruktionsinterpretationen handelt.&lt;/p&gt;

&lt;h3 id=&quot;unwinding-tabellen&quot;&gt;Unwinding-Tabellen&lt;/h3&gt;

&lt;p&gt;Das Finden von Aufräumcode funktioniert heute vermehrt über Metadaten,
als über IP-(Instruction-Pointer) Tabellen. Wie effizient das letztendlich ist,
&lt;a href=&quot;https://devblogs.microsoft.com/oldnewthing/20220228-00/?p=106296&quot;&gt;steht noch zur Diskussion&lt;/a&gt;,
Ein &lt;code&gt;throw&lt;/code&gt; stellt fest, von welcher Codeadresse der Aufruf kam, und sucht 
dann in einer Tabelle zwischen Anfang- und Endpunkten, was mit dem Ursprung 
assoziiert ist.&lt;br /&gt;
Und von dort erhält man wieder weitere Codezeiger, die man anspringen kann 
um den Stack-Cleanup einleiten zu können.&lt;/p&gt;

&lt;p&gt;Im GCC wird hierfür die Funktion &lt;code&gt;dl_iterate_phdr()&lt;/code&gt; aufgerufen, die durch 
die geladenen ELF-Handler durchgehen soll und Info-Objekte dazu an einen
Callback übergeben soll (z.B.: &lt;code&gt;_Unwind_IteratePhdrCallback()&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Leider ist der “Dynamic-Linker” im Freestanding-Betrieb ebenfalls nicht
vorhanden, somit muss ich die &lt;code&gt;dl_iterate_phdr()&lt;/code&gt; offenbar nachbauen.
Ein Problem könnte dann sein, dass mein EFI-Binary ein von ELF/Dwarf nach
COFF/PE konvertiertes Trägerformat ist.&lt;/p&gt;

&lt;p&gt;Ich hoffe also, dass durch diese Konvertierung (siehe &lt;code&gt;objcopy&lt;/code&gt;) die
Codeadressen nicht negativ beeinflusst.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;Es ist ein Alptraum.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Weder mit dem MSVC, noch mit dem GCC unter Linux oder mit dem MinGW ist die
Nutzung von Exceptions außerhalb der Betriebssystemumgebung machbar.&lt;/p&gt;

&lt;p&gt;Ich hätte mir ein vernünftiges API erwartet, das Exceptions und 
Typinformationen allokieren kann und eine Registrierungsfunktion für
Cleanup-Routinen, sowie standardisierte Einsprungpunkte für Catch-Handler.
Wäre dann die Exception-Behandlung und das Stack-Unwinding ein statischer
vom Compiler generierter Code, dann könnte all das mit den generischen
Metadaten betriebssystemunabhängig arbeiten.&lt;/p&gt;

&lt;p&gt;Doch so bleibt die Windows-Implementierung an Win32-SEH angeknüpft und
der GCC verbeißt sich in ELF und DL-Strukturen.&lt;/p&gt;

&lt;p&gt;Und das ist leider alles andere als “generisch”.&lt;/p&gt;

&lt;p&gt;Mal sehen wie das weitergehen wird.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Thread local storage</title>
   <link href="https://www.opengate.at/blog/2022/09/tls/"/>
   <published>2022-09-18T13:00:00+02:00</published>
   <updated>2022-09-18T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2022/09/tls</id>
   <category term="devel" />
   <summary type="text">Einer der Gründe, warum ich auf meinem Weg zu C++ außerhalb von 
Betriebssystemen stolpere, liegt am “thread local storage”.

Denn wo werden Exception-Daten abgelegt?
Offenbar genau dort!

Und was mir fehlt ist ein funktionierender Nachbau von __tls_get_addr.
</summary>
   <content type="html">&lt;p&gt;Einer der Gründe, warum ich auf meinem Weg zu C++ außerhalb von 
Betriebssystemen stolpere, liegt am “thread local storage”.&lt;/p&gt;

&lt;p&gt;Denn wo werden Exception-Daten abgelegt?&lt;br /&gt;
Offenbar genau dort!&lt;/p&gt;

&lt;p&gt;Und was mir fehlt ist ein funktionierender Nachbau von &lt;code&gt;__tls_get_addr&lt;/code&gt;.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Egal wie “free-standing” man sein Projekt kompiliert, ein Linux-GCC mischt
zwangsläufig Linux-Standards in den Code. Und das betrifft vor allem
C++ Exceptions und das dazugehörige Runtime-Type-Information (RTTI) System.&lt;/p&gt;

&lt;p&gt;Wenn nämlich in einem Thread eine Exception fliegt, muss der Callstack
rückabgewickelt werden, bis zum letzten installierten Exception Handler
und auf dem Weg dorthin müssen alle herumliegenden Objekte freigegeben 
werden.&lt;/p&gt;

&lt;p&gt;Das erfordert den Zugriff auf zwei OS-nahe Ressourcen:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Die ELF-Sections mit Cleanup-Codes, die an das Speicherlayout angepasst sind&lt;/li&gt;
  &lt;li&gt;Der Thread-local-storage, in dem die gültigen Exception Handler verlinkt sind.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Beide Ressourcen erfordern eine tiefe Kenntnis und “Konformität” zu den
Strukturen, wie Linux und die jeweilige C-Lib damit umgehen.&lt;br /&gt;
Und das ist unter Windows leider auch nicht anders.&lt;/p&gt;

&lt;p&gt;Noch krasser wird die Geschichte, weil die neueren C-Standards ab C11 mit der
&lt;code&gt;_Thread_local&lt;/code&gt; Speicherklasse einem jeden Datentypen ermöglichen, zum Thread
gehören zu können und im Hintergrund nötige Anpassungen machen.&lt;/p&gt;

&lt;p&gt;Offiziell erreicht man den Thread-local-storage über entsprechende APIs,
wie &lt;a href=&quot;https://pubs.opengroup.org/onlinepubs/009695399/functions/pthread_key_create.html&quot;&gt;pthread_key_create()&lt;/a&gt;
und &lt;a href=&quot;https://pubs.opengroup.org/onlinepubs/009695399/functions/pthread_setspecific.html&quot;&gt;pthread_get/setspecific()&lt;/a&gt;
oder &lt;a href=&quot;https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-tlsalloc&quot;&gt;TlsAlloc&lt;/a&gt;
und &lt;a href=&quot;https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-tlssetvalue&quot;&gt;TlsSetValue &lt;/a&gt;
unter Windows.&lt;/p&gt;

&lt;p&gt;Doch wie sich zeigt umgehen die internen Funktionen des GCC die POSIX API und
wollen mit APIs wie &lt;code&gt;__tls_get_addr()&lt;/code&gt; arbeiten und nutzen dann ihr
Geheimwissen und adressieren die Unterfelder dann direkt.&lt;/p&gt;

&lt;p&gt;Ich habe nun länger nach Infos zu all diesen Details gesucht und 
interessante Dinge über den TCB (thread control block) und den
DTV (dynamic thread vector) gelesen&lt;br /&gt;
… aber geholfen hat mir das leider nicht.&lt;/p&gt;

&lt;h3 id=&quot;fazit-keinen-thread-local-storage-nutzen&quot;&gt;Fazit: Keinen Thread-local-storage nutzen!&lt;/h3&gt;

&lt;p&gt;Was ich mit C++ Exception machen soll, weiß ich noch nicht,
aber ich habe zumindest gelernt, dass der leichtsinnige
Einsatz von &lt;code&gt;_Thread_local&lt;/code&gt; kontraproduktiv sein kann.&lt;/p&gt;

&lt;p&gt;Für mein UEFI Thema führt offenbar wirklich kein Weg daran vorbei, den
GCC und seine Kernbibliotheken neu zu bauen, denn dort hat man ein
paar Möglichkeiten, die Arbeitsweise zu beeinflussen.&lt;br /&gt;
Es gibt schließlich auch Mikrocontroller-Zielplattformen, die all
den Schnickschnack auch nicht unterstützen.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>EFI und MinGW inline API</title>
   <link href="https://www.opengate.at/blog/2022/09/mingw-inline/"/>
   <published>2022-09-17T13:00:00+02:00</published>
   <updated>2022-09-17T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2022/09/mingw-inline</id>
   <category term="devel" />
   <summary type="text">Es hätte so einfach sein können: Man implementiert einfach alle Funktionen der 
C-Standard Bibliothek 
selbst in einer statischen Bibliothek und linkt gegen diese. 
Schon hätte man C Programme direkt als 
EFI 
App laufen lassen können.

Aber nicht so mit MinGW … denn der 
hat keine “echte” C API.
</summary>
   <content type="html">&lt;p&gt;Es hätte so einfach sein können: Man implementiert einfach alle Funktionen der 
&lt;a href=&quot;https://de.wikipedia.org/wiki/C_(Programmiersprache)#Standardbibliothek&quot;&gt;C-Standard Bibliothek&lt;/a&gt; 
selbst in einer statischen Bibliothek und linkt gegen diese. 
Schon hätte man C Programme direkt als 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Unified_Extensible_Firmware_Interface&quot;&gt;EFI&lt;/a&gt; 
App laufen lassen können.&lt;/p&gt;

&lt;p&gt;Aber nicht so mit &lt;a href=&quot;https://de.wikipedia.org/wiki/MinGW&quot;&gt;MinGW&lt;/a&gt; … denn der 
hat keine “echte” C API.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Die klassischen Header wie &lt;code&gt;stdlib.h&lt;/code&gt; und &lt;code&gt;stdio.h&lt;/code&gt; deklarieren bei allen
Compilern die gleichen Funktionen wie&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;* malloc(size_t size);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; printf(&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt; * format, ...);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; getchar(&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; putchar(&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; character);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;...
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Die Implementierungen dieser Funktionen innerhalb der C-Laufzeitbibliothek,
die automatisch in alle C Programme injiziert wird, verweisen auf das 
jeweilige Betriebssystem, also wie z.B.: &lt;code&gt;ReadFile()&lt;/code&gt; und &lt;code&gt;WriteFile()&lt;/code&gt; in 
der &lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_Application_Programming_Interface&quot;&gt;WinAPI&lt;/a&gt; 
oder die &lt;code&gt;read()&lt;/code&gt; und &lt;code&gt;write()&lt;/code&gt; &lt;a href=&quot;https://de.wikipedia.org/wiki/Systemaufruf&quot;&gt;Systemcalls&lt;/a&gt;
in &lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Hat man kein OS (wie z.B. für EFI Apps), lässt man seinen Code mit
&lt;code&gt;/NODEFAULTLIB&lt;/code&gt; unter &lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_C%2B%2B&quot;&gt;MSVC&lt;/a&gt; 
oder &lt;code&gt;-ffreestanding -nostdlib&lt;/code&gt; beim &lt;a href=&quot;https://de.wikipedia.org/wiki/GNU_Compiler_Collection&quot;&gt;GCC&lt;/a&gt;
kompilieren und/oder linken, womit dann alle C-Standard-Funktionen als
“undefinierte Symbole” erkannt werden.&lt;/p&gt;

&lt;p&gt;Dann implementiert man diese Funktionen selbst und leitet sie auf direkte
Hardware- oder Firmware Features um.&lt;br /&gt;
Und das funktioniert auch einigermaßen, wenn man ein paar Ungleichheiten 
bei den C Headern ausbessert, wie der sporadische Einsatz von &lt;code&gt;restrict&lt;/code&gt; oder
&lt;code&gt;const&lt;/code&gt; bei Parametern. (Das lässt sich mit Makros leicht umsetzen).&lt;/p&gt;

&lt;h3 id=&quot;mingw-nutzt-inline-c-funktionen&quot;&gt;MinGW nutzt inline C-Funktionen&lt;/h3&gt;

&lt;p&gt;Mein Konzept brach aber total zusammen, als ich den MinGW bemühte meine
Quellcodes zu übersetzen.&lt;br /&gt;
Denn der lieferte hunderte Zeilen, die wie folgt aussahen:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;/.../gnu-efi-stdc/src/stdio_impl.c:194:5: error: redefinition of ‘sprintf’
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;  194 | int sprintf(char* str, const char* format, ...)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;      |     ^~~~~~~
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;/usr/share/mingw-w64/include/stdio.h:382:5: note: previous definition of ‘sprintf’ was here
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  382 | int sprintf (char *__stream, const char *__format, ...)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;      |     ^~~~~~~
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Meine Funktion hatte die gleiche Signatur wie die in &lt;code&gt;stdio.h&lt;/code&gt; doch soll nun
eine &lt;code&gt;Redefinition&lt;/code&gt; sein.
Und der Grund dafür befindet sich in Zeile &lt;code&gt;382&lt;/code&gt; von &lt;code&gt;stdio.h&lt;/code&gt;, denn dort
steht:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; sprintf(&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt;* __stream, &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt;* __format, ...)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; __retval;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  __builtin_va_list __local_argv;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  __builtin_va_start(__local_argv, __format);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;  __retval = __mingw_vsprintf(__stream, __format, __local_argv);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  __builtin_va_end(__local_argv);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; __retval;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;MinGW definiert also &lt;code&gt;sprintf&lt;/code&gt; gar nicht als eine &lt;code&gt;extern C&lt;/code&gt; Funktion, sondern
nur als inline-Funktion im Header, die auf eine interne Funktion namens 
&lt;code&gt;__mingw_vsprintf&lt;/code&gt; umleitet.&lt;/p&gt;

&lt;p&gt;Und das gleiche passiert auch bei allen anderen I/O Funktionen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Tja … leider ist das erlaubt, denn ein “API” definiert nur, wie eine 
Funktion heißt und welche Parameter sie hat und nicht wie sie implementiert
sein muss.&lt;/p&gt;

&lt;p&gt;Mich stellt das jetzt vor die Herausforderung, ob ich nun für den MinGW 
Spezialfälle wie &lt;code&gt;__mingw_vsprintf&lt;/code&gt; implementieren soll, oder versuchen soll,
&lt;code&gt;stdio.h&lt;/code&gt; und seine Freunde auf von mir erstellten Header umzuleiten.&lt;/p&gt;

&lt;p&gt;Interessant finde ich nur, dass MSVC und der Standard-GCC (mit glibc) hier 
sehr “kompatibel” sind, während das GCC-Derivat MinGW ganz anders aufgebaut 
ist.&lt;/p&gt;

&lt;p&gt;Leider zeigt sich hier, dass die MingGW-Hersteller nicht wirklich modular 
gedacht haben. Denn leicht hätten sie diese inline Umleitungen auch in 
(austauschbare) “extern C” Funktionen packen können um daraus ein echtes
“ABI” zu machen und um z.B: &lt;code&gt;__mingw_vsprintf&lt;/code&gt; dann inline einzubinden.&lt;/p&gt;

&lt;p&gt;Das hätte performance-technisch dann keinen Unterschied gemacht und wäre
mir jetzt sehr entgegengekommen.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Aber wie langweilig wäre die Welt ohne weitere Herausforderungen …&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>Online Übersetzungen</title>
   <link href="https://www.opengate.at/blog/2022/09/online-translation/"/>
   <published>2022-09-11T13:00:00+02:00</published>
   <updated>2022-09-11T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2022/09/online-translation</id>
   <category term="software" /><category term="projects" />
   <summary type="text">Vor 3 Jahren fand ich den Übersetzungsdienst für Webseiten bei 
Microsoft und verlinkte ihn auf der
Blog-Seite, damit bei Bedarf für jeden auch eine englische Variante des Blogs 
verfügbar ist.

Leider hat Microsoft diesen Dienst offenbar in diesem Jahr eingestellt.
Nun bleibt mir leider nur der Wechsel zu Google übrig.
</summary>
   <content type="html">&lt;p&gt;Vor 3 Jahren fand ich den Übersetzungsdienst für Webseiten bei 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft&quot;&gt;Microsoft&lt;/a&gt; und verlinkte ihn auf der
Blog-Seite, damit bei Bedarf für jeden auch eine englische Variante des Blogs 
verfügbar ist.&lt;/p&gt;

&lt;p&gt;Leider hat Microsoft diesen Dienst offenbar in diesem Jahr eingestellt.
Nun bleibt mir leider nur der Wechsel zu Google übrig.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;microsofttranslatorcom-für-webseiten-deaktiviert&quot;&gt;microsofttranslator.com für Webseiten deaktiviert&lt;/h3&gt;

&lt;p&gt;Es war so einfach …&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#070;font-weight:bold&quot;&gt;&amp;lt;a&lt;/span&gt; &lt;span style=&quot;color:#b48&quot;&gt;href&lt;/span&gt;=&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;https://www.microsofttranslator.com/bv.aspx?from=de&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;to=en&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;a=https%3A%2F%2Fwww.opengate.at%2Fblog&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#070;font-weight:bold&quot;&gt;&amp;gt;&lt;/span&gt;...&lt;span style=&quot;color:#070;font-weight:bold&quot;&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Durch dem Aufruf von &lt;code&gt;www.microsofttranslator.com/bv.aspx&lt;/code&gt; mit den Parameter:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;from=de&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;to=en&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;a=http....&lt;/code&gt; (also die URL im &lt;code&gt;urlencode&lt;/code&gt;-Format kodiert)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;lud der Dienst die Webseite, übersetzte sie online von Deutsch auf Englisch 
und gab eine Design-treue englische Variante zurück.&lt;/p&gt;

&lt;p&gt;Für statische &lt;a href=&quot;https://de.wikipedia.org/wiki/Hypertext_Markup_Language&quot;&gt;HTML&lt;/a&gt; 
Seiten ist das eine sehr bequeme Möglichkeit, die eigenen Worte in beliebig 
viele Sprachen zu übersetzen.&lt;/p&gt;

&lt;p&gt;Der originale Jekyll Code sah so aus:&lt;/p&gt;
&lt;div class=&quot;language-html highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#070;font-weight:bold&quot;&gt;&amp;lt;a&lt;/span&gt; &lt;span style=&quot;color:#b48&quot;&gt;href&lt;/span&gt;=&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;http://www.microsofttranslator.com/bv.aspx?from=de&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;to=en&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;a={{ page.url | prepend : &lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#b48&quot;&gt;https:&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#b48&quot;&gt;www.opengate.at&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#b48&quot;&gt;blog&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;&amp;quot;&lt;/span&gt; &lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;|&lt;/span&gt; &lt;span style=&quot;color:#b48&quot;&gt;url_encode&lt;/span&gt; &lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#070;font-weight:bold&quot;&gt;&amp;gt;&lt;/span&gt;...&lt;span style=&quot;color:#070;font-weight:bold&quot;&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h3 id=&quot;wechsel-zu-google&quot;&gt;Wechsel zu Google&lt;/h3&gt;

&lt;p&gt;Nach einigem Herumsuchen stellte ich fest, dass andere Dienste entweder 
limitiert sind (z.B.: nur X Zeichen pro Tag) oder mit Registrierungs- oder 
Bezahlzwang arbeiten.&lt;br /&gt;
Und das ist es mir nicht wert.&lt;/p&gt;

&lt;p&gt;Google ist für mich zwar grundsätzlich ein No-Go, doch da der Suchdienst meine
Seiten sowieso indiziert hat, dann kann er auch gleich etwas sinnvolles damit
machen und die Seite übersetzen.&lt;/p&gt;

&lt;p&gt;Datenschutztechnisch ist das natürlich furchtbar, da wieder eine weitere Form
des Trackings möglich wird, aber … was soll man tun … außer verkrampft
zuzustimmen.&lt;/p&gt;

&lt;h4 id=&quot;aufruf-der-webseite&quot;&gt;Aufruf der Webseite&lt;/h4&gt;

&lt;p&gt;Google arbeitet etwas anders als die vorig Lösung:
Die eigentliche Domain wird in eine Subdomain von &lt;code&gt;translate.goog&lt;/code&gt; umgewandelt
und der relative Pfad dem neuen Domainpfad angefügt.
Am Ende wird über die URL-Parameter &lt;code&gt;_x_tr_sl&lt;/code&gt; (Source Language) und 
&lt;code&gt;_x_tr_tl&lt;/code&gt; (Translation/Target Language) die Originalsprache
und die Zielsprache angegeben, wobei man &lt;code&gt;_x_tr_sl&lt;/code&gt; auch auf &lt;code&gt;auto&lt;/code&gt; setzen kann,
damit Google die Sprache selbst herausfindet.&lt;/p&gt;

&lt;p&gt;Das hat dann die Form:&lt;br /&gt;
&lt;code&gt;https://my-domain-tld.translate.goog/sub/path/?_x_tr_sl=auto&amp;amp;_x_tr_tl=en&lt;/code&gt;&lt;br /&gt;
oder wie im Falle meines Blogs:&lt;br /&gt;
&lt;code&gt;https://www-opengate-at.translate.goog/blog/?_x_tr_sl=auto&amp;amp;_x_tr_tl=en&lt;/code&gt;&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Es funktioniert … und das reicht mir vorerst.&lt;br /&gt;
Aber ich wäre glücklicher, wenn ich einen anderen Dienst für diese Aufgabe
finden würde.&lt;/p&gt;

&lt;p&gt;Fairerweise muss man sagen, dass auch das heute gar nicht mehr notwendig ist,
denn alle Mainstream Browser bieten die Übersetzung von Webseiten bereits an.
Ich finde es aber praktisch, wenn man bereits einen Link zur fertig 
übersetzten Seite generieren kann.&lt;/p&gt;

&lt;p&gt;Vielleicht erschließt sich da ja auch mal ein Möglichkeit, dass man die 
Übersetzung per &lt;a href=&quot;https://de.wikipedia.org/wiki/JavaScript&quot;&gt;JavaScript&lt;/a&gt; oder 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Cascading_Style_Sheets&quot;&gt;CSS&lt;/a&gt; im Browser 
aktivieren kann.&lt;br /&gt;
… aber vorerst bleibe ich mal beim Google-Link.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>CONAN Abhängigkeiten und Versionen</title>
   <link href="https://www.opengate.at/blog/2022/09/conan-version/"/>
   <published>2022-09-10T13:00:00+02:00</published>
   <updated>2022-09-10T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2022/09/conan-version</id>
   <category term="devel" />
   <summary type="text">Grundsätzlich gilt für CONAN 
Projekte:


  Ändert man die Version, eine Einstellung oder eine Option in einer 
Komponente, errechnet CONAN einen neuen 
Hash für ein Paket und auch 
alle Abhängigkeiten davon bekommen neue Hashes zugeteilt.


… dachte ich.
Doch nun kenne ich eine interessante Ausnahme.
</summary>
   <content type="html">&lt;p&gt;Grundsätzlich gilt für &lt;a href=&quot;https://de.wikipedia.org/wiki/Conan_(Software)&quot;&gt;CONAN&lt;/a&gt; 
Projekte:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ändert man die Version, eine Einstellung oder eine Option in einer 
Komponente, errechnet CONAN einen neuen 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Hashfunktion&quot;&gt;Hash&lt;/a&gt; für ein Paket und auch 
alle Abhängigkeiten davon bekommen neue Hashes zugeteilt.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;… dachte ich.&lt;br /&gt;
Doch nun kenne ich eine interessante Ausnahme.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;CONAN identifiziert seine Paket durch Namen und Version, wie auch durch
“Settings” (Compiler, OS, Build-Toolset) und “Options” (Shared, Static, …).&lt;/p&gt;

&lt;p&gt;So können dann aus einem Quellcode beliebig viele Pakete parallel gebaut 
werden, die sich durch mindestens ein Detail unterscheiden und das wird
am eindeutigsten durch die Paket-Hashes signalisiert.&lt;/p&gt;

&lt;script src=&quot;/blog/assets/mermaid/mermaid.min.js&quot;&gt;&lt;/script&gt;
&lt;div class=&quot;mermaid&quot;&gt;
graph TD
  REPO(myLib&lt;br /&gt;Repository)
  SRC1(myLib/1.1&lt;br /&gt;Source)
  SRC2(myLib/1.2&lt;br /&gt;Source)
  BIN11(myLib/1.1&lt;br /&gt;Windows 32&lt;br /&gt;Hash: 123)
  BIN12(myLib/1.1&lt;br /&gt;Windows 64&lt;br /&gt;Hash: 456)
  BIN13(myLib/1.1&lt;br /&gt;Linux GCC 10&lt;br /&gt;Hash: 789)
  BIN14(myLib/1.1&lt;br /&gt;Linux GCC 11&lt;br /&gt;Hash: abc)
  BIN21(myLib/1.2&lt;br /&gt;Windows 32&lt;br /&gt;Hash: def)
  BIN22(myLib/1.2&lt;br /&gt;Windows 64&lt;br /&gt;Hash: aaa)
  BIN23(myLib/1.2&lt;br /&gt;Linux GCC 10&lt;br /&gt;Hash: bbb)
  BIN24(myLib/1.2&lt;br /&gt;Linux GCC 11&lt;br /&gt;Hash: ccc)

  REPO --&amp;gt; SRC1
  REPO --&amp;gt; SRC2

  SRC1 --&amp;gt; BIN11
  SRC1 --&amp;gt; BIN12
  SRC1 --&amp;gt; BIN13
  SRC1 --&amp;gt; BIN14

  SRC2 --&amp;gt; BIN21
  SRC2 --&amp;gt; BIN22
  SRC2 --&amp;gt; BIN23
  SRC2 --&amp;gt; BIN24
&lt;/div&gt;

&lt;p&gt;Bei Abhängigkeiten zwischen Paketen bewirkt eine Änderung der Version 
ebenfalls sofort eine Änderung des Paket-Hashes.&lt;/p&gt;

&lt;script src=&quot;/blog/assets/mermaid/mermaid.min.js&quot;&gt;&lt;/script&gt;
&lt;div class=&quot;mermaid&quot;&gt;
graph LR
  subgraph Different Versions
    B1(baseLib/1.1)
    B2(baseLib/1.2)
  end

  subgraph Same Versions
    L1(myLib/1.1&lt;br /&gt;Hash: abc)
    L2(myLib/1.1&lt;br /&gt;Hash: 123)
    P1(myProg/1.0&lt;br /&gt;Hash: def)
    P2(myProg/1.0&lt;br /&gt;Hash: 456)
  end

  B1 --required by--&amp;gt; L1 
  L1 --required by--&amp;gt; P1

  B2 --required by--&amp;gt; L2
  L2 --required by--&amp;gt; P2
&lt;/div&gt;

&lt;h3 id=&quot;ausnahme-nach-der-3-versionstelle-wird-der-rest-ignoriert&quot;&gt;Ausnahme: Nach der 3. Versionstelle wird der Rest ignoriert&lt;/h3&gt;

&lt;p&gt;CONAN erkennt gemäß “Semantic Versioning” nur 3 Stellen in einer Version an.
Man kann aber noch mehr hinten anhängen, doch eben genau das wird in die 
Hashberechnung und damit in die Paket-Identifizierung nicht einberechnet.&lt;/p&gt;

&lt;p&gt;Hat man also eine Bibliothek mit der Version &lt;code&gt;1.2.3.4&lt;/code&gt; und wechselt zur Version
&lt;code&gt;1.2.3.5&lt;/code&gt;, so wird das zwar von CONAN korrekt erkannt und aufgelöst, doch
die davon abhängigen Projekte erfahren keine Hashänderung.&lt;/p&gt;

&lt;script src=&quot;/blog/assets/mermaid/mermaid.min.js&quot;&gt;&lt;/script&gt;
&lt;div class=&quot;mermaid&quot;&gt;
graph LR
  subgraph Different Versions
    B1(baseLib/1.4.2.1)
    B2(baseLib/1.4.2.2)
  end

  subgraph Same Versions
    L(myLib/1.1&lt;br /&gt;Hash: abc)
    P(myProg/1.0&lt;br /&gt;Hash: def)
  end

  B1 --required by--&amp;gt; L 
  B2 --required by--&amp;gt; L
  L --required by--&amp;gt; P
&lt;/div&gt;

&lt;p&gt;Für produktive Software ist das Beispiel grundsätzlich ungeeignet, weil man in
der Regel bei der Änderung der Version einer Abhängigkeit auch die eigene 
Version anpasst. Also aus&lt;br /&gt;
&lt;code&gt;base/1.1 -&amp;gt; lib/2.3&lt;/code&gt; wird dann ein &lt;code&gt;base/1.2 -&amp;gt; lib/2.4&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Doch wenn man Softwarestände testet und zwischen unterschiedlichen Patch-Levels
hin und her probiert, kommt es schon vor, dass man die “neue” Version der 
eigenen Komponenten mit unterschiedlichen Varianten von anderen Komponenten
testet.&lt;/p&gt;

&lt;h3 id=&quot;kein-support-für-mehr-als-3-stellen-in-versionen&quot;&gt;Kein Support für mehr als 3 Stellen in Versionen&lt;/h3&gt;

&lt;p&gt;Dass CONAN sich bei mehr als 3 Stellen anders verhält, zeigt sich auch bei
Range-Angaben.&lt;br /&gt;
Ein &lt;code&gt;conan install project/[1.2.*]@user/channel&lt;/code&gt; sollte die neueste Variante
der &lt;code&gt;1.2&lt;/code&gt; Serie herunterladen, also die mit der höchsten Versionsnummer.
Existiert aber eine 4. Stelle für solche Versionen im Repository, lädt 
CONAN “irgendeine” herunter. Für mich sieht es so aus, als wäre es die 
“erste” in der Auflistung.&lt;/p&gt;

&lt;script src=&quot;/blog/assets/mermaid/mermaid.min.js&quot;&gt;&lt;/script&gt;
&lt;div class=&quot;mermaid&quot;&gt;
graph LR
  INSTA(CONAN INSTALL&lt;br /&gt;libA/1.2.*)
  INSTB(CONAN INSTALL&lt;br /&gt;libB/2.3.*)

  subgraph libA
    A1[[libA/1.2.1]]
    A2[[libA/1.2.2]]
    A3[[libA/1.2.3]]
  end

  subgraph libB
    B1[[libA/2.3.9.1]]
    B2[[libA/2.3.9.2]]
    B3[[libA/2.3.9.3]]
  end

  RESULTA(libA/1.2.3)
  RESULTB(libB/????)
 
  INSTA -.Match-.-&amp;gt; A1
  INSTA -.Match-.-&amp;gt; A2
  INSTA --Select&lt;br /&gt;latest--&amp;gt; A3
  A3 --Install&lt;br /&gt;latest--&amp;gt; RESULTA

  INSTB -.Match-.-&amp;gt; B1
  INSTB -.Match-.-&amp;gt; B2
  INSTB -.Match-.-&amp;gt; B3

  B1 -.Random&lt;br /&gt;installation-.-&amp;gt; RESULTB
  B2 -.Random&lt;br /&gt;installation-.-&amp;gt; RESULTB
  B3 -.Random&lt;br /&gt;installation-.-&amp;gt; RESULTB
&lt;/div&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ich bin mir noch nicht so ganz sicher, was ich jetzt davon halten soll,
denn bisher ging ich fix davon aus, dass jede Versionsänderung eine
Hash-Änderung nach sich zieht.&lt;/p&gt;

&lt;p&gt;Bei einem &lt;code&gt;conan upload&lt;/code&gt; mit neuem Hash bleiben dann die alten Hashes im 
Upload-Repository liegen, sind aber über ein frisches &lt;code&gt;conan install&lt;/code&gt; nicht 
mehr herunterladbar. Man kann sie jedoch immer noch direkt über den Hash 
z.B.: per HTTP URL beziehen.&lt;/p&gt;

&lt;p&gt;Ändert sich der Hash jedoch nicht, dann kann eine “neue” Version einer
Abhängigkeit lautlos ein bestehendes Paket überschreiben, da der gleiche
Hash für zwei unterschiedliche Szenarien generiert wurde.&lt;/p&gt;

&lt;p&gt;Wichtig ist jedenfalls, dass man dieses Detail von CONAN kennen sollte,
denn gerade im Windows-Bereich sind 4-stellige Versionsnummern keine
Seltenheit und führen dann womöglich mit CONAN zu unerwarteten Seiteneffekten.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Corona Impfung - Teil 4</title>
   <link href="https://www.opengate.at/blog/2022/09/corona-4/"/>
   <published>2022-09-05T13:00:00+02:00</published>
   <updated>2022-09-05T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2022/09/corona-4</id>
   <category term="general" />
   <summary type="text">Nachdem mit Anfang September die allgemeine Empfehlung ausgesprochen wurde, 
sich eine 4. Covid-19 Booster-Impfung
zu holen, habe ich unmittelbar einen Termin im Impfzentrum gebucht und mir 
meine 4. Dosis gestern geholt.

Nun - so hoffe ich - komme ich weiter gut durch den Winter.
</summary>
   <content type="html">&lt;p&gt;Nachdem mit Anfang September die allgemeine Empfehlung ausgesprochen wurde, 
sich eine 4. &lt;a href=&quot;https://de.wikipedia.org/wiki/COVID-19&quot;&gt;Covid-19&lt;/a&gt; Booster-Impfung
zu holen, habe ich unmittelbar einen Termin im Impfzentrum gebucht und mir 
meine 4. Dosis gestern geholt.&lt;/p&gt;

&lt;p&gt;Nun - so hoffe ich - komme ich weiter gut durch den Winter.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;folgen-und-auswirkungen&quot;&gt;Folgen und Auswirkungen&lt;/h3&gt;

&lt;p&gt;Während die Dümmsten der Dummen unserer Gesellschaft weiter behaupten, es gäbe
kein Virus und alles sei nur eine Erfindung der Medien, kann ich in meinem
Umkreis folgende Bilanz ziehen:&lt;/p&gt;

&lt;p&gt;Wenn mir sogar Teenager erzählen, sie musste Wochen nach einer Infektion zum
Arzt, weil sie beim Sport plötzlich keine Luft mehr bekamen und dort eine 
verminderte Atemkapazität festgestellt wurde, dann sagt mir das, dass COVID-19
nicht nur ein Senioren-Schreck ist.&lt;/p&gt;

&lt;p&gt;Dennoch trifft es die Ältesten der Gemeinde am härtesten und so können wir
unsere Nachbarin nun nur noch am Friedhof besuchen. Sie hatte weder Corona,
noch ist sie daran gestorben. Doch konnte sie wegen der totalen Überlastung
in den Krankenhäusern nicht behandelt werden, und verstarb beim tagelangem
Warten auf eine Behandlung, weil ungeimpfte Corona-Patienten notwendige
Krankenhausplätze und Personal blockiert hatten.&lt;/p&gt;

&lt;p&gt;Es ist also unsere Verpflichtung - auch ohne persönlichem Interesse - alles 
zu tun, um Erkrankungen zu verhindern und die Ausbreitung aller Infektionen
einzudämmen, damit sich Ärzte wieder z.B. um Herzinfarkte und Blutvergiftungen
kümmern können, anstatt dass sie sturen Verschwörungsanhängern am Ende das
Leben retten müssen, wenn deren Selbstbehandlung mit Pferde-Entwurmungsmitteln
am Ende (wer hätte es gedacht?) doch nicht wirken.&lt;/p&gt;

&lt;h3 id=&quot;4-impfung&quot;&gt;4. Impfung&lt;/h3&gt;

&lt;p&gt;Ich hatte mir also wieder einen Termin im 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Austria_Center_Vienna&quot;&gt;Austria-Center&lt;/a&gt; gelöst 
und es war, wie schon beim letzten Mal, “ein Spaziergang”.&lt;br /&gt;
Wartezeiten und Schlangen gab es keine, und ich musste nur einmal quer durch
das Areal laufen, um&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;einmal meinen vorausgefüllten Datenzettel abzugeben,&lt;/li&gt;
  &lt;li&gt;dafür meinen Impfnummern-Sticker zu bekommen,&lt;/li&gt;
  &lt;li&gt;danach vom Arzt die üblichen Infos erzählt zu bekommen,&lt;/li&gt;
  &lt;li&gt;am Ende zur Impfkabine zu gehen.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Hätte ich keinen Termin online vereinbart, wären 3 Personen vor mir gewesen,
die auch schnell abgefertig wurden, doch mit Termin sparte ich diese 5 - 10
Minuten ein.&lt;/p&gt;

&lt;p&gt;Danach wurde noch 15 Minuten Platz genommen um zu warten und dann war die
Sache auch schon wieder vorbei.&lt;/p&gt;

&lt;h3 id=&quot;keine-reaktionen-außer-kopfschmerzen&quot;&gt;Keine Reaktionen außer Kopfschmerzen&lt;/h3&gt;

&lt;p&gt;Nachdem meine erste Impfung mir einen Tag im Bett beschert hatte, bereitete
ich mich auf ein solches Szenario wieder vor.&lt;br /&gt;
Doch krank fühlte ich mich den Rest des Sonntags gar nicht.&lt;/p&gt;

&lt;p&gt;Erst ab 23:00 Uhr als ich langsam schlafen gehen wollte, setzten Kopfschmerzen
ein. Diese waren unangenehm und ließen mich die Nacht auf Montag wenig
schlafen, womit ich tagsüber müde war.&lt;br /&gt;
Die Kopfschmerzen waren am Morgen auch schon wieder weg und ich holte
die fehlenden Schlaf am Nachmittag “im Home-Office” nach und machte dann
meine Tagesarbeiten am Abend fertig.&lt;/p&gt;

&lt;p&gt;In Summe hat sich also mein Tagesablauf um 4 Stunden verschoben, aber das
passiert auch, wenn ich mal aus anderen Gründen bis tief in die Nacht vor
dem Rechner sitze … also insofern nichts Neues.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Meine Abwehrzellen sind nun hoffentlich wieder etwas auftrainiert, damit sie
das Corona-Virus besser bekämpfen können.&lt;br /&gt;
Seit Beginn der Pandemie bin ich (so weit mir bekannt ist) nicht erkrankt und
bin auch atemtechnisch “voll einsatzbereit”.&lt;/p&gt;

&lt;p&gt;Und nun möchte ich, dass das so bleibt und plane lieber kontrolliert einen 
Ausfall-Tag nach der Booster-Impfung ein, als dass ich dann (wie manch andere)
wochenlang hustend im Bett verbringen muss, und dann noch weitere Monate 
eingeschränkt bin.&lt;/p&gt;

&lt;p&gt;Masken trage ich weiter in den Öffis und in Geschäften, wenn gleich ich auch 
so ziemlich der einzige bin. Doch wenn man weiß, dass wegen der Überlastungen
im Gesundheitssystem schon viele Menschen sinnlos gestorben sind, nur weil es
an Behandlungsplätzen wegen Corona-Patienten fehlt, dann ist es notwendig, 
mit gutem Beispiel voran zu gehen und nicht so zu tun, also ob es das Virus
nicht mehr gäbe.&lt;/p&gt;

&lt;p&gt;Vor zwei Jahren war ich selbst skeptisch gegenüber vielen Maßnahmen.&lt;br /&gt;
Heute sehe ich sie als genau so notwendig an, wie den Gurt im Auto anzulegen.
Bisher kam ich noch nie in die Situation, wo mir der Gurt das Leben gerettet
hätte … trotzdem nutze ich ihn.&lt;br /&gt;
Und bei der Corona Impfung ist es genau so.&lt;br /&gt;
Mag sein, dass es mit ihr nicht viel besser ist.&lt;br /&gt;
Aber ohne sie kann es vielfach schlimmer sein.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>GITLAB, CONAN und LF vs CRLF</title>
   <link href="https://www.opengate.at/blog/2022/09/gitlab-conan-crlf/"/>
   <published>2022-09-04T13:00:00+02:00</published>
   <updated>2022-09-04T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2022/09/gitlab-conan-crlf</id>
   <category term="devel" />
   <summary type="text">Seit langem quält mich eine Unschönheit in der 
CONAN Welt an 
meinem Arbeitsplatz:


  MSVC und GCC Pakete des gleichen Projektes erzeugen unterschiedliche
Recipe-Hashes, weshalb immer eine Variante als “outdated” markiert wird.


Lösung: Zeilenenden vereinheitlichen!

</summary>
   <content type="html">&lt;p&gt;Seit langem quält mich eine Unschönheit in der 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Conan_(Software)&quot;&gt;CONAN&lt;/a&gt; Welt an 
meinem Arbeitsplatz:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;MSVC und GCC Pakete des gleichen Projektes erzeugen unterschiedliche
Recipe-Hashes, weshalb immer eine Variante als “outdated” markiert wird.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Lösung: Zeilenenden vereinheitlichen!&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Hat man ein CONAN basiertes C++ Projekt auf einem &lt;a href=&quot;https://de.wikipedia.org/wiki/GitLab&quot;&gt;Gitlab&lt;/a&gt; 
Server liegen, dann laufen mindestens zwei Build-Jobs:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;einer für Windows&lt;/li&gt;
  &lt;li&gt;und einer für Linux&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Doch beim Upload ins JFrog Artifactory kommt es dann zu einer Überlappung,
da beide Builds ihr grundsätzlich gleiches “Rezept” (Recipe) exportieren.&lt;br /&gt;
Folglich müssten beide Builds zwar unterschiedliche Paket-Hashes bekommen,
aber den gleichen Recipe-Hash herausbekommen.&lt;/p&gt;

&lt;p&gt;Doch genau das trat in unserem Firmenprojekt nicht ein, Windows lieferte
einen anderen Recipe-Hash als Linux und so geschah es, dass der Build-Job,
der später fertig wurde, beim Upload den Recipe-Hash des früheren Jobs
überschrieb.&lt;br /&gt;
Und das wiederum führt dazu, dass beim Aufruf von&lt;br /&gt;
&lt;code&gt;conan search my_project/1.0.0@user/channel -r my_remote&lt;/code&gt; 
das frühere Build-Job-Ergebnis als “outdated” markiert wird.&lt;/p&gt;

&lt;p&gt;Das ist zwar nicht schlimm und andere CONAN Kommandos können die
“outdated” Pakete trotzdem laden, doch trotzdem störte mich diese
Inkonsistenz.&lt;/p&gt;

&lt;h3 id=&quot;git-und-line-endings&quot;&gt;GIT und Line-Endings&lt;/h3&gt;

&lt;p&gt;Als ursprüngliches Linux Produkt kennt GIT eigentlich nur &lt;code&gt;LF&lt;/code&gt; als Zeilenende.
GIT for Windows nutzt daher die default-Konfiguration:&lt;br /&gt;
&lt;code&gt;core.autocrlf=true&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Mit dieser Option wird beim &lt;code&gt;clone&lt;/code&gt;/ &lt;code&gt;fetch&lt;/code&gt; / &lt;code&gt;pull&lt;/code&gt; jedes &lt;code&gt;LF&lt;/code&gt; in Sourcen 
durch ein &lt;code&gt;CRLF&lt;/code&gt; ersetzt. Umgekehrt wird beim &lt;code&gt;commit&lt;/code&gt;/ &lt;code&gt;push&lt;/code&gt; wieder jedes 
&lt;code&gt;CRLF&lt;/code&gt; zu &lt;code&gt;LF&lt;/code&gt;, damit am GIT Server alles einheitlich im Linux-Standard 
gespeichert wird.&lt;/p&gt;

&lt;p&gt;Compiler können mit Sourcen beider Konventionen umgehen, doch CONAN bildet
seine Hashes über die Sourcen genau so, wie sie lokal ausgecheckt sind.&lt;br /&gt;
Und damit sieht der Recipe-Hash auf Windows und Linux unterschiedlich aus.&lt;/p&gt;

&lt;p&gt;Die Lösung ist also das Kommando&lt;br /&gt;
&lt;code&gt;git config --global core.autocrlf false&lt;/code&gt; 
auf der Windows Maschine, auf der der Build läuft, und alles ist gut.
GIT lädt dann die Sourcen genau so herunter und wieder hoch, wie sie sind,
und macht keine eigenmächtigen Anpassungen.&lt;/p&gt;

&lt;h3 id=&quot;gitlab-runners-und-git&quot;&gt;Gitlab Runners und GIT&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;Doch wie zum Teufel kann man jetzt GitLab dazu bringen, auf den 
Windows-Runnern ebenso diese Option zu setzen?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Nach langem Suchen blieb ich auf der 
&lt;a href=&quot;https://docs.gitlab.com/runner/configuration/advanced-configuration.html&quot;&gt;GitLab Seite zur Runner-Konfiguration&lt;/a&gt;
in &lt;code&gt;config.toml&lt;/code&gt; hängen, denn dort wird von der Konfigurationszeile&lt;br /&gt;
&lt;code&gt;pre_clone_script&lt;/code&gt; gesprochen.&lt;br /&gt;
Dieses “Script” wird ausgeführt, bevor der Gitlab-Runner die Sourcen 
herunterlädt und genau hier kann man per &lt;code&gt;git&lt;/code&gt; Kommando Einstellungen verändern.&lt;/p&gt;

&lt;div class=&quot;language-toml highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;[[runners]]
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;  name = &amp;quot;MY-WINDOWS-BUILD-SERVER&amp;quot;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  ...
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  executor = &amp;quot;docker-windows&amp;quot;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  shell = &amp;quot;powershell&amp;quot;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;  pre_clone_script = &amp;quot;git config --global core.autocrlf false&amp;quot;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  ...
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Diese Zeile wird tatsächlich als erstes im 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Docker_(Software)&quot;&gt;Docker&lt;/a&gt;
Container ausgeführt und sorgt dafür, dass GIT unter Windows alles genau 
so auscheckt, wie es auch unter Linux passiert.&lt;/p&gt;

&lt;p&gt;Und am Ende sind dann die Recipe-Hashes identisch und beide Builds werden als&lt;br /&gt;
&lt;code&gt;Outdated from recipe: False&lt;/code&gt; angezeigt&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Mission erfüllt!&lt;br /&gt;
Aber ich muss schon sagen, dass es sehr mühsam war, die Hintergründe
herauszufinden.&lt;/p&gt;

&lt;p&gt;Ich dachte eigentlich, es gibt eine GitLab CI Variable, mit der man das
steuern könnte, doch bisher habe ich keine solche gefunden.&lt;/p&gt;

&lt;p&gt;Das Anpassen der GitLab-CI-Runner ist eine schöne Sache, wenn man die
Server selbst verwaltet (was hier zum Glück der Fall war).&lt;br /&gt;
Doch wenn man zentrale Serverfarmen nutzt, ist es fraglich, ob einem der
Admin einen separaten Runner-TAG mit eben diese Konfiguration anlegen
wird.&lt;/p&gt;

&lt;p&gt;Eben deshalb wäre es notwendig, dieses Verhalten über die eigene 
CI-Konfiguration steuern zu können, und nicht über &lt;code&gt;config.toml&lt;/code&gt; am
Server.&lt;/p&gt;

&lt;p&gt;Wie auch immer, wieder ein Rätsel gelöst und ein Script 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Sudoku&quot;&gt;Sudoku&lt;/a&gt; vollgekritzelt&lt;br /&gt;
… das heißt, ich kann beruhigt schlafen gehen.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>ARM64 Assembler</title>
   <link href="https://www.opengate.at/blog/2022/09/arm64-asm/"/>
   <published>2022-09-03T13:00:00+02:00</published>
   <updated>2022-09-03T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2022/09/arm64-asm</id>
   <category term="devel" />
   <summary type="text">Mit meinem ARM64 Windows 11 und 
Linux am Pinebook habe ich zwei 
Umgebungen, auf denen ich endlich auch mal ARM64 
Assembler Codes testen kann.

Das Schlimme an dem Dialekt ist, dass er sich von ARM32 unterscheidet,
was die Portierung von ARM32 Code erschwert.
</summary>
   <content type="html">&lt;p&gt;Mit meinem &lt;a href=&quot;/blog/2022/06/apcsilmic/&quot;&gt;ARM64 Windows 11&lt;/a&gt; und 
&lt;a href=&quot;/blog/2022/08/pinebook/&quot;&gt;Linux am Pinebook&lt;/a&gt; habe ich zwei 
Umgebungen, auf denen ich endlich auch mal &lt;a href=&quot;https://de.wikipedia.org/wiki/Arm-Architektur#Armv8-A_(2011)&quot;&gt;ARM64&lt;/a&gt; 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Assemblersprache&quot;&gt;Assembler Codes&lt;/a&gt; testen kann.&lt;/p&gt;

&lt;p&gt;Das Schlimme an dem Dialekt ist, dass er sich von ARM32 unterscheidet,
was die Portierung von ARM32 Code erschwert.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;microsoft-arm-assembler-marmasm&quot;&gt;Microsoft ARM Assembler (MARMASM)&lt;/h3&gt;

&lt;p&gt;Wenn die &lt;a href=&quot;/blog/2022/06/arm-asm/&quot;&gt;Einrichtung des ARM Assemblers&lt;/a&gt; 
erfolgt ist, kann man schon munter drauf losprogrammieren.&lt;/p&gt;

&lt;p&gt;Wie schon erwähnt war die Konvention, dass Anweisungen eingerückt sein müssen 
und nur Labels und Prozedurnamen am Zeilenanfang starten dürfen, neu für mich.
Doch sobald man sich daran gewöhnt hat, ist es auch kein Problem mehr.&lt;/p&gt;

&lt;h4 id=&quot;register&quot;&gt;Register&lt;/h4&gt;

&lt;p&gt;Die Register &lt;code&gt;x0&lt;/code&gt; bis &lt;code&gt;x7&lt;/code&gt; stellen 8 Integer Funktionsparameter dar, wobei 
in &lt;code&gt;x0&lt;/code&gt; auch gleich wieder der Returnvalue zurückgegeben wird.
Ansonsten gelten &lt;code&gt;x0&lt;/code&gt; bis &lt;code&gt;x15&lt;/code&gt; als (volatile) Scratch-Register und können
innerhalb jeder Funktion frei verändert werden.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;x19&lt;/code&gt; bis &lt;code&gt;x28&lt;/code&gt; sind nicht-volatile Scratch-Register. Will eine Funktion sie
nutzen, müssen die Inhalte z.B.: auf dem Stack gesichert werden und am
Ende der Funktion wieder auf den Ursprungswert zurückgesetzt werden. 
Somit kann eine Funktion, die eine andere aufruft, erwarten, dass diese
Register nach dem Aufruf alle Werte “gehalten” haben.&lt;/p&gt;

&lt;p&gt;Der Framepointer liegt in &lt;code&gt;x29&lt;/code&gt;, kann aber auch als &lt;code&gt;fp&lt;/code&gt; angesprochen werden
und &lt;code&gt;x30&lt;/code&gt; ist das Link-Register, auch als &lt;code&gt;lr&lt;/code&gt; bekannt.&lt;/p&gt;

&lt;p&gt;Die Registern &lt;code&gt;x16&lt;/code&gt; und &lt;code&gt;x17&lt;/code&gt; sind volatile “Intra-Procedure-Call-Scratch-Register”,
deren Inhalt sich während eines Funktionsaufrufes ändern kann, etwa durch Debugging
oder Patches, innerhalb der Funktion kann es “normal” genutzt werden.
Und &lt;code&gt;x18&lt;/code&gt; gehört dem OS, unter Windows verweist es z.B.: auf den 
Thread-Environment-Block im Usermode.&lt;/p&gt;

&lt;h4 id=&quot;funktions-prolog-und--epilog&quot;&gt;Funktions-Prolog und -Epilog&lt;/h4&gt;

&lt;p&gt;Ein Bild sagt mehr als 1000 Worte.
Folgender Code zeigt eine Funktion, die in C als&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;long&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;long&lt;/span&gt; my_asm_func_add_2_parameters(&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;long&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;long&lt;/span&gt; a, &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;long&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;long&lt;/span&gt; b);
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;deklariert werden würde:&lt;/p&gt;

&lt;div class=&quot;language-asm highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;  AREA |.text|,CODE,READONLY
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  EXPORT my_asm_func_add_2_parameters
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;my_asm_func_add_2_parameters PROC
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;  ;; prologue begins
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;  pacibsp                     ; return address protection
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  ; save non-volatile registers
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;  stp fp, lr, [sp, #-0x60]!   ; sp -= 0x60
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;                              ; sp[0x00] = fp; sp[0x08] = lr
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;  stp x19, x20, [sp, #0x10]   ; sp[0x10] = x19; sp[0x18] = x20
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;  stp x21, x22, [sp, #0x20]   ; sp[0x20] = x21; sp[0x28] = x22
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;  stp x23, x24, [sp, #0x30]   ; sp[0x30] = x23; sp[0x38] = x24
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;  stp x25, x26, [sp, #0x40]   ; sp[0x40] = x25; sp[0x48] = x26
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;  stp x27, x28, [sp, #0x50]   ; sp[0x50] = x27; sp[0x58] = x28
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;  ; setup stack-frame
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  mov fp, sp                  ; fp = sp
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n21&quot; name=&quot;n21&quot;&gt;21&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n22&quot; name=&quot;n22&quot;&gt;22&lt;/a&gt;&lt;/span&gt;  ; allocate stack for local variables
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n23&quot; name=&quot;n23&quot;&gt;23&lt;/a&gt;&lt;/span&gt;  sub sp, sp, #0x10           ; 2 local variables
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n24&quot; name=&quot;n24&quot;&gt;24&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n25&quot; name=&quot;n25&quot;&gt;25&lt;/a&gt;&lt;/span&gt;  ;; prologue completed
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n26&quot; name=&quot;n26&quot;&gt;26&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n27&quot; name=&quot;n27&quot;&gt;27&lt;/a&gt;&lt;/span&gt;  ; parameters a+b (x0=a, x1=b)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n28&quot; name=&quot;n28&quot;&gt;28&lt;/a&gt;&lt;/span&gt;  add x0, x0, x1              ; x0 += x1        
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n29&quot; name=&quot;n29&quot;&gt;29&lt;/a&gt;&lt;/span&gt;  ; return value in x0
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n30&quot; name=&quot;n30&quot;&gt;30&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n31&quot; name=&quot;n31&quot;&gt;31&lt;/a&gt;&lt;/span&gt;  ;; epilogue begins
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n32&quot; name=&quot;n32&quot;&gt;32&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n33&quot; name=&quot;n33&quot;&gt;33&lt;/a&gt;&lt;/span&gt;  ; deallocate stack for local variables
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n34&quot; name=&quot;n34&quot;&gt;34&lt;/a&gt;&lt;/span&gt;  add sp, sp, #0x10           ; free 2 local variables
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n35&quot; name=&quot;n35&quot;&gt;35&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n36&quot; name=&quot;n36&quot;&gt;36&lt;/a&gt;&lt;/span&gt;  ; restore non-volatile registers
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n37&quot; name=&quot;n37&quot;&gt;37&lt;/a&gt;&lt;/span&gt;  ldp x27, x28, [sp, #0x50]   ; x27 = sp[0x50]; x28 = sp[0x58]
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n38&quot; name=&quot;n38&quot;&gt;38&lt;/a&gt;&lt;/span&gt;  ldp x25, x26, [sp, #0x40]   ; x25 = sp[0x40]; x26 = sp[0x48]
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n39&quot; name=&quot;n39&quot;&gt;39&lt;/a&gt;&lt;/span&gt;  ldp x23, x24, [sp, #0x30]   ; x23 = sp[0x30]; x24 = sp[0x38]
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n40&quot; name=&quot;n40&quot;&gt;40&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  ldp x21, x22, [sp, #0x20]   ; x21 = sp[0x20]; x22 = sp[0x28]
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n41&quot; name=&quot;n41&quot;&gt;41&lt;/a&gt;&lt;/span&gt;  ldp x19, x20, [sp, #0x10]   ; x19 = sp[0x10]; x20 = sp[0x18]
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n42&quot; name=&quot;n42&quot;&gt;42&lt;/a&gt;&lt;/span&gt;  ldp fp, lr, [sp], #0x060    ; fp = sp[0x00]; lr = sp[0x08]
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n43&quot; name=&quot;n43&quot;&gt;43&lt;/a&gt;&lt;/span&gt;                              ; sp += 0x60
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n44&quot; name=&quot;n44&quot;&gt;44&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n45&quot; name=&quot;n45&quot;&gt;45&lt;/a&gt;&lt;/span&gt;  autibsp                     ; return address check
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n46&quot; name=&quot;n46&quot;&gt;46&lt;/a&gt;&lt;/span&gt;  ;; epilogue ends
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n47&quot; name=&quot;n47&quot;&gt;47&lt;/a&gt;&lt;/span&gt;  ret
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n48&quot; name=&quot;n48&quot;&gt;48&lt;/a&gt;&lt;/span&gt;  ENDP
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n49&quot; name=&quot;n49&quot;&gt;49&lt;/a&gt;&lt;/span&gt;  END
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Und jetzt zu den Details:
&lt;code&gt;pacibsp&lt;/code&gt; und &lt;code&gt;autibsp&lt;/code&gt; dienen dem Schutz gegen Fehler und Malware,
aber das hat schon &lt;a href=&quot;https://devblogs.microsoft.com/oldnewthing/20220819-00/?p=107020&quot;&gt;Raymond Chen&lt;/a&gt;
super erklärt.&lt;/p&gt;

&lt;p&gt;Der Stack ist immer auf 16 Bytes ausgerichtet, weshalb man häufig immer gleich
zwei Register gleichzeitig auf den Stack speichert bzw. lädt.
&lt;code&gt;stp&lt;/code&gt; (store pair) und &lt;code&gt;ldp&lt;/code&gt; (load pair) erledigen das, man könnte aber auch
einzelne Register ansprechen mit &lt;code&gt;str&lt;/code&gt; (store register) und &lt;code&gt;ldr&lt;/code&gt; 
(load register).&lt;/p&gt;

&lt;p&gt;Gemäß ABI werden zuerst Framepointer und Linkregister auf den Stack gesichert, 
gefolgt von allen nicht-volatilen Registern &lt;code&gt;x19&lt;/code&gt; - &lt;code&gt;x28&lt;/code&gt;, die man in der 
Funktion verändern möchte. (Im Beispiel wird gar nichts verändert, aber zwecks
Demo werden trotzdem alle herangezogen).&lt;/p&gt;

&lt;p&gt;Die erste &lt;code&gt;stp&lt;/code&gt; Anweisung mit dem Rufzeichen am Ende führt zwei Änderungen
durch: Sie subtrahiert zuerst vom Stackpointer die Puffergröße für alle
zu speichernden Register (12 x 8 = 0x60) und danach werden &lt;code&gt;fp&lt;/code&gt; und &lt;code&gt;lr&lt;/code&gt; in 
den Stack gespeichert. Die Nachfolgenden &lt;code&gt;stp&lt;/code&gt;s sichern die restlichen Register
“über” dem aktuellen Stackpointer.&lt;/p&gt;

&lt;p&gt;Danach wird noch der Framepointer &lt;code&gt;fp&lt;/code&gt; auf den Stackpointer &lt;code&gt;sp&lt;/code&gt; gesetzt und 
es werden genau so viele Bytes vom Stackpointer subtrahiert, wie man für 
lokale Variablen braucht, die man dann über den Framepointer adressieren kann.&lt;/p&gt;

&lt;p&gt;Der Framepointer zeigt somit genau auf die Stack-Adresse, an der der alte
Framepointer und danach die Rücksprungadresse gesichert wurde, und so kann 
der Debugger den Callstack ermitteln.&lt;/p&gt;

&lt;p&gt;Lokale Variablen werden dann über &lt;code&gt;fp[-offset]&lt;/code&gt; oder &lt;code&gt;sp[+offset]&lt;/code&gt; 
angesprochen. Nach dem Prolog sieht das Stack-Layout so aus:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Frame ptr&lt;/th&gt;
      &lt;th&gt;Stack ptr&lt;/th&gt;
      &lt;th&gt;Bedeutung&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;fp[0x60]&lt;/td&gt;
      &lt;td&gt;sp[0x70]&lt;/td&gt;
      &lt;td&gt;Aufrufer-Stack, weitere Parameter&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;Beginn des lokalen Stacks&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;fp[0x58]&lt;/td&gt;
      &lt;td&gt;sp[0x68]&lt;/td&gt;
      &lt;td&gt;gesichertes NV Register 10 (x28)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;fp[0x50]&lt;/td&gt;
      &lt;td&gt;sp[0x60]&lt;/td&gt;
      &lt;td&gt;gesichertes NV Register 9 (x27)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;…&lt;/td&gt;
      &lt;td&gt;…&lt;/td&gt;
      &lt;td&gt;…&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;fp[0x18]&lt;/td&gt;
      &lt;td&gt;sp[0x28]&lt;/td&gt;
      &lt;td&gt;gesichertes NV Register 2 (x20)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;fp[0x10]&lt;/td&gt;
      &lt;td&gt;sp[0x20]&lt;/td&gt;
      &lt;td&gt;gesichertes NV Register 1 (x19)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;fp[0x08]&lt;/td&gt;
      &lt;td&gt;sp[0x18]&lt;/td&gt;
      &lt;td&gt;Rücksprungadresse zum Aufrufer&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;fp[0x00]&lt;/td&gt;
      &lt;td&gt;sp[0x10]&lt;/td&gt;
      &lt;td&gt;Framepointer des Aufrufers&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;fp[-0x08]&lt;/td&gt;
      &lt;td&gt;sp[0x08]&lt;/td&gt;
      &lt;td&gt;Erste 64-bit Stack Variable&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;fp[-0x10]&lt;/td&gt;
      &lt;td&gt;sp[0x00]&lt;/td&gt;
      &lt;td&gt;Zweite 64-bit Stack Variable&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;-&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;Ende des lokalen Stacks&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Nachdem auf ARM64 die ersten 8 Funktionsparameter per Register übergeben
werden, kann mit diesen sofort gerechnet werden. Im Beispiel werden
schließlich nur zwei Parameter (&lt;code&gt;x0&lt;/code&gt;, &lt;code&gt;x1&lt;/code&gt;) addiert und das Ergebnis in 
&lt;code&gt;x0&lt;/code&gt; zurückgegeben.&lt;/p&gt;

&lt;p&gt;Der Epilog ist die Umkehrung des Prologs. Zuerst wird der Speicher für lokale
Variablen vom Stackpointer “wegaddiert”, dann werden alle nicht-volatilen 
Register vom Stack zurückgelesen und am Ende der Stackpointer wieder erhöht,
damit er genau den Wert hat, den er am Anfang der Funktion hatte.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ret&lt;/code&gt; springt dann zur Adresse des wiederhergestellten Linkregisters.&lt;/p&gt;

&lt;h3 id=&quot;funktionsaufruf&quot;&gt;Funktionsaufruf&lt;/h3&gt;

&lt;p&gt;Die obige Beispielfunktion &lt;code&gt;my_asm_func_add_2_parameters&lt;/code&gt; wird ganz einfach per&lt;/p&gt;

&lt;div class=&quot;language-asm highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;  mov x0, #21
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;  mov x1, #12
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  bl my_asm_func_add_2_parameters
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;aufgerufen.&lt;br /&gt;
Es werden die Parameter-Register gesetzt, und danach springt
&lt;code&gt;bl&lt;/code&gt; die Adresse an und sichert gleichzeitig die Rücksprungadresse
im Linkregister &lt;code&gt;lr&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Mit dem Wissen kann man jetzt auch schon fleißig Assembler-Routinen
in ARM64 Programmen schreiben.&lt;/p&gt;

&lt;p&gt;Natürlich fehlt noch der Hinweis, dass bei mehr als 8 Parametern,
die anderen vor dem Funktionsaufruf auf den Stack gepusht werden,
und dass bei Variadic-Functions die Parameter Register ebenso 
zuerst auf den Stack gepusht werden, damit alle Parameter 
hintereinander auf dem Stack liegen … aber solche Details hat Raymond schon
&lt;a href=&quot;https://devblogs.microsoft.com/oldnewthing/20220825-00/?p=107050&quot;&gt;super beschrieben&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Nicht vergessen darf man auch, dass Floating-Point Argumente in 
eigenen Register übergeben werden und deren Nummerierung ist leider
kompliziert, wenn man sie mit Integer Parametern mischt.&lt;/p&gt;

&lt;p&gt;Am Ende bleibt zu sagen, dass ich nun meine Callstack-Switching Routinen im
GATE Framework in ARM64 Assembler nachziehen kann, damit auch diese 
Plattformen abgedeckt sind.&lt;/p&gt;

&lt;p&gt;Von X86 kommend wirkte ARM für mich anfangs sehr ungewohnt … doch nach 
ein paar Fingerübungen wirkt das ganze vertrauter und von den Instruktionen
recht genial umgesetzt.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Windows 11 mit altem Kontextmenü</title>
   <link href="https://www.opengate.at/blog/2022/08/win11-tweaks/"/>
   <published>2022-08-28T13:00:00+02:00</published>
   <updated>2022-08-28T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2022/08/win11-tweaks</id>
   <category term="software" />
   <summary type="text">Eigentlich bin ich grundsätzlich noch von 
Windows 11 unabhängig, 
denn nach einer ersten “Beschau”, stellte ich fest, dass ich es einfach nicht 
brauche, und blieb bei Windows 10.

Doch seit ich mit meinem APCSILMIC die 
ARM64 Welt erforsche, ist Windows 11 notwendig.
Und etwas, was mich dort in den Wahnsinn treibt, ist das beknackte 
“vereinfachte” Kontextmenü  …
… das muss weg!

</summary>
   <content type="html">&lt;p&gt;Eigentlich bin ich grundsätzlich noch von 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_11&quot;&gt;Windows 11&lt;/a&gt; unabhängig, 
denn nach einer ersten “Beschau”, stellte ich fest, dass ich es einfach nicht 
brauche, und blieb bei Windows 10.&lt;/p&gt;

&lt;p&gt;Doch seit ich mit meinem &lt;a href=&quot;/blog/2022/06/apcsilmic/&quot;&gt;APCSILMIC&lt;/a&gt; die 
ARM64 Welt erforsche, ist Windows 11 notwendig.&lt;br /&gt;
Und etwas, was mich dort in den Wahnsinn treibt, ist das beknackte 
“vereinfachte” Kontextmenü  …&lt;br /&gt;
… das muss weg!&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Was für ein Glück, dass sich schon mehrere Mitmenschen damit abgequält haben 
und eine einfache Lösung publiziert haben:&lt;/p&gt;

&lt;h3 id=&quot;windows-11-mit-klassischem-alten-kontextmenü&quot;&gt;Windows 11 mit klassischem alten Kontextmenü.&lt;/h3&gt;

&lt;p&gt;Lösung:&lt;br /&gt;
Man legt den &lt;a href=&quot;https://de.wikipedia.org/wiki/Registrierungsdatenbank&quot;&gt;Registry&lt;/a&gt; 
Schlüssel&lt;br /&gt;
&lt;code&gt;HKCU\Software\Classes\CLSID\{86ca1aa0-34aa-4e8b-a509-50c905bae2a2}\InprocServer32&lt;/code&gt;
an und setzt dessen &lt;code&gt;(Default)&lt;/code&gt; Welt auf einen Leerstring.&lt;br /&gt;
Also in &lt;code&gt;regedit&lt;/code&gt; den Eintrag &lt;code&gt;(Default)&lt;/code&gt; doppelklicken und wieder mit &lt;code&gt;OK&lt;/code&gt; 
bestätigen, weil ein neu erstellter Schlüssel zwar einen Default-Wert Eintrag 
hat, der aber nicht gesetzt ist (ursprünglich wird angezeigt: &lt;code&gt;(value not set)&lt;/code&gt;).
Nach der Aktion hat &lt;code&gt;(Default)&lt;/code&gt; einfach “nichts” in seiner Data-Spalte stehen.&lt;/p&gt;

&lt;p&gt;Man kann den Vorgang auch mit dem &lt;code&gt;reg&lt;/code&gt; Tool als Administrator ausführen:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;reg.exe add &amp;quot;HKCU\Software\Classes\CLSID\{86ca1aa0-34aa-4e8b-a509-50c905bae2a2}\InprocServer32&amp;quot; /f /ve
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h3 id=&quot;fehlentscheidung-im-design&quot;&gt;Fehlentscheidung im Design&lt;/h3&gt;

&lt;p&gt;Ja, ich kann es nachvollziehen, dass das Windows Kontextmenü für Anfänger zu
groß und überladen wirkt und damit verwirrt.&lt;/p&gt;

&lt;p&gt;Gleichzeitig ist es aber auch so, dass eben solche blutigen Anfänger von dem
Menü oder generell von Rechtsklicks nichts wissen.&lt;br /&gt;
Und das macht das neue Menü wiederum nutzlos.&lt;/p&gt;

&lt;p&gt;Doch für Entwickler wie mich (und sicher viele Administratoren und andere
im IT Umfeld) ist das neue Windows 11 Kontextmenü einfach nur eine Zumutung.&lt;/p&gt;

&lt;p&gt;Tools wie &lt;code&gt;7Zip&lt;/code&gt;, &lt;code&gt;Git&lt;/code&gt; oder &lt;code&gt;Visual Studio Code&lt;/code&gt; registrieren im klassischen
Menü ihre Einträge, womit man für jede Datei wichtige Operationen schnell
und effizient starten kann.&lt;/p&gt;

&lt;p&gt;Im neuen Windows 11 Menü fehlen diese Tools und man muss erst nach unten
fahren und auf &lt;code&gt;Weitere Optionen anzeigen&lt;/code&gt; klicken, bis das alte Menü 
erscheint.&lt;br /&gt;
Und ich brauche das bei der Arbeit bis zu hundert Mal wenn ich in 300 
Source-Directories Downloads und &lt;code&gt;diff&lt;/code&gt; Vergleiche durchführen muss.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;Augen auf, Microsoft!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Wäre es nicht viel sinnvoller gewesen eine neue Einstellung einzuführen um
das Kontextmenü leichter anpassen zu können?&lt;br /&gt;
z.B.: In dem man unwichtige Einträge auf “unsichtbar” setzen kann, oder
seltener genutzte Funktionen in ein Untermenü auslagern kann?&lt;/p&gt;

&lt;p&gt;Aber dass wir alle mit dem neuen nutzlosen Menü konfrontiert sind, das
sich nur durch einen Registry-Hack umgehen lässt, ist nicht OK.&lt;br /&gt;
Man hätte es zumindest per UI ein- und ausschaltbar gestalten können.&lt;/p&gt;

&lt;p&gt;However. Vielen Dank an die Finder des Registryschlüssels.&lt;br /&gt;
Hiermit sei er auch bei mir dokumentiert und verbreitet sich hoffentlich
weiter, bevor noch mehr Produktivität durch die Mehrfachklickerei 
verloren geht.&lt;/p&gt;

&lt;h3 id=&quot;nachtrag-klassisches-startmenü&quot;&gt;Nachtrag: Klassisches Startmenü&lt;/h3&gt;

&lt;p&gt;Ich hätte jetzt gerne auch noch das alte Windows-10 Startmenü zurückgefordert
und tatsächlich gab es hierfür anfangs auch einen Registry-Hack.
Doch Microsoft hat diese Möglichkeit mit Updates wieder entfernt, und so
laufen die bereits publizierten “Hacks” nur unter dem originalen Windows 11
Release, aber nicht mehr unter den aktuellen Varianten.&lt;/p&gt;

&lt;p&gt;Der Trick lautete in 
&lt;code&gt;HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\&lt;/code&gt; den
DWORD Eintrag &lt;code&gt;Start_ShowClassicMode&lt;/code&gt; auf &lt;code&gt;1&lt;/code&gt; setzen.&lt;br /&gt;
Doch leider leider leider, funktioniert das nicht mehr.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>GITLAB mit Tests und Code Coverage</title>
   <link href="https://www.opengate.at/blog/2022/08/gitlab-gcov/"/>
   <published>2022-08-27T13:00:00+02:00</published>
   <updated>2022-08-27T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2022/08/gitlab-gcov</id>
   <category term="software" />
   <summary type="text">Gitlab wird als Quellcode 
Verwaltungssystem in vielen Firmen eingesetzt, auch in denen für die ich 
gearbeitet habe und arbeite.

Gitlab ist simpel … und deshalb sehr kompliziert.
Den jeder Anwender kann sich seinen eigenen Weg durch einen Berg von 
Funktionen graben und deshalb sieht jeder Tunnel dann etwas anders aus.

Und eine interessante Herausforderung ist das Sammeln von 
Code-Coverage
Daten in C++.
</summary>
   <content type="html">&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/GitLab&quot;&gt;Gitlab&lt;/a&gt; wird als Quellcode 
Verwaltungssystem in vielen Firmen eingesetzt, auch in denen für die ich 
gearbeitet habe und arbeite.&lt;/p&gt;

&lt;p&gt;Gitlab ist simpel … und deshalb sehr kompliziert.&lt;br /&gt;
Den jeder Anwender kann sich seinen eigenen Weg durch einen Berg von 
Funktionen graben und deshalb sieht jeder Tunnel dann etwas anders aus.&lt;/p&gt;

&lt;p&gt;Und eine interessante Herausforderung ist das Sammeln von 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Testabdeckung&quot;&gt;Code-Coverage&lt;/a&gt;
Daten in &lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B&quot;&gt;C++&lt;/a&gt;.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;ci-pipelines-und-jobs&quot;&gt;CI Pipelines und Jobs&lt;/h3&gt;

&lt;p&gt;Das &lt;a href=&quot;https://de.wikipedia.org/wiki/Kontinuierliche_Integration&quot;&gt;Continuous Integration&lt;/a&gt; 
Feature (kurz CI) gestatt es automatisiert “Operationen” bei Bestimmten 
Ereignissen auszuführen.&lt;br /&gt;
Der Klassiker ist, dass man bei jedem Commit in einem &lt;a href=&quot;https://de.wikipedia.org/wiki/Git&quot;&gt;GIT&lt;/a&gt; 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Repository&quot;&gt;Repository&lt;/a&gt; dann eine Build-Pipeline 
startet, die den neuen Code kompiliert und gegebenenfalls abtestet.&lt;/p&gt;

&lt;p&gt;Eine Pipeline besteht dann aus einer oder mehreren “Stages” mit den größeren
Teilschritten und in jeder Stage laufen dann die eigentlichen “Jobs”, z.B.:
kann jeder “Job” eine Plattform wie Windows oder Linux abdecken oder für 
unterschiedliche Testframeworks.&lt;/p&gt;

&lt;p&gt;Ein mir vertrauter einfacher Ablauf solcher Pipeline “Stages” ist:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;em&gt;Build&lt;/em&gt;&lt;br /&gt;
Alle Sourcen werden kompiliert&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;Test&lt;/em&gt;&lt;br /&gt;
Unit Tests werden ausgeführt um Test und Code-Coverage Berichte zu erstellen&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;Deploy&lt;/em&gt;&lt;br /&gt;
Fertige Binaries werden irgendwo hin hochgeladen, wo sie direkt eingesetzt
werden oder auf einen Download warten.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;report-formate&quot;&gt;Report Formate&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Modultest&quot;&gt;Unit test&lt;/a&gt; Frameworks können ihre
Ergebnisse in unterschiedlichen Formaten ausgeben, was man meist über 
Commandline-Switches einstellen kann.&lt;br /&gt;
Zwei recht bekannte Formate sind:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/JUnit&quot;&gt;JUnit&lt;/a&gt; für das Zusammenfassen von Tests&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/cobertura/cobertura/wiki/FAQ&quot;&gt;Cobertura&lt;/a&gt; für das Sammeln 
von Code-Coverage Informationen&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;junit-test-reports&quot;&gt;JUnit Test Reports&lt;/h4&gt;

&lt;p&gt;JUnit und Cobertura entstanden ursprünglich von 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Java_(Programmiersprache)&quot;&gt;Java&lt;/a&gt; Projekten, sie
wurde aber von vielen Sprachen genutzt um eigene Tests standardisiert 
auszugeben.&lt;br /&gt;
Das C++ Framework &lt;a href=&quot;https://de.wikipedia.org/wiki/Boost_(C%2B%2B-Bibliothek)&quot;&gt;BOOST&lt;/a&gt; 
unterstützt in seinen &lt;code&gt;boost/test&lt;/code&gt; Klassen auch JUnit und mit eben diesem 
durfte ich die letzten Jahre arbeiten.&lt;/p&gt;

&lt;p&gt;Der Test:&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#define&lt;/span&gt; BOOST_AUTO_TEST_MAIN
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#define&lt;/span&gt; BOOST_TEST_MODULE test_my_code_module
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color:#B44;font-weight:bold&quot;&gt;&amp;lt;boost/test/auto_unit_test.hpp&amp;gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;BOOST_AUTO_TEST_SUITE(my_test_suite)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;BOOST_AUTO_TEST_CASE(my_test_case)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;throw&lt;/span&gt; &lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;}
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;BOOST_AUTO_TEST_SUITE_END()
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;führt dann zu sowas wie:&lt;/p&gt;

&lt;div class=&quot;language-xml highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#070;font-weight:bold&quot;&gt;&amp;lt;testsuite&lt;/span&gt; &lt;span style=&quot;color:#b48&quot;&gt;tests&lt;/span&gt;=&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;5&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span style=&quot;color:#b48&quot;&gt;skipped&lt;/span&gt;=&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span style=&quot;color:#b48&quot;&gt;errors&lt;/span&gt;=&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span style=&quot;color:#b48&quot;&gt;failures&lt;/span&gt;=&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span style=&quot;color:#b48&quot;&gt;id&lt;/span&gt;=&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span style=&quot;color:#b48&quot;&gt;name&lt;/span&gt;=&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;test_my_code_module&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span style=&quot;color:#b48&quot;&gt;time&lt;/span&gt;=&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;0.130668&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#070;font-weight:bold&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#070;font-weight:bold&quot;&gt;&amp;lt;testcase&lt;/span&gt; &lt;span style=&quot;color:#b48&quot;&gt;classname&lt;/span&gt;=&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;my_test_suite&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span style=&quot;color:#b48&quot;&gt;name&lt;/span&gt;=&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;my_test_case&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#070;font-weight:bold&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#070;font-weight:bold&quot;&gt;&amp;lt;error&lt;/span&gt; &lt;span style=&quot;color:#b48&quot;&gt;message&lt;/span&gt;=&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;unexpected exception&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span style=&quot;color:#b48&quot;&gt;type&lt;/span&gt;=&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;system error&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#070;font-weight:bold&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;font-weight:bold;color:#666&quot;&gt;&amp;lt;![CDATA[&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;        UNCAUGHT EXCEPTION ...
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;font-weight:bold;color:#666&quot;&gt;]]&amp;gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#070;font-weight:bold&quot;&gt;&amp;lt;/error&amp;gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#070;font-weight:bold&quot;&gt;&amp;lt;/testcase&amp;gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#070;font-weight:bold&quot;&gt;&amp;lt;/testsuite&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Ein Gitlab CI Job in &lt;code&gt;gitlab_ci.yml&lt;/code&gt;, der für einen Boost-Test in etwa so 
aussieht:&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#606&quot;&gt;test_job&lt;/span&gt;:
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#606&quot;&gt;script&lt;/span&gt;:
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;    - &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#D20&quot;&gt;mkdir ${CI_PROJECT_DIR}/test_results&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;    - &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt; 
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;path/to/test_my_code_module &lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;--report_sink=${CI_PROJECT_DIR}/test_results/my_test_results_sumary.txt&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;--logger=JUNIT,all,${CI_PROJECT_DIR}/test_results/my_test_results.xml&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;    - &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#D20&quot;&gt;echo &amp;quot;Done&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#606&quot;&gt;artifacts&lt;/span&gt;:
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;    &lt;span style=&quot;color:#606&quot;&gt;paths&lt;/span&gt;:
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;      - &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#D20&quot;&gt;${CI_PROJECT_DIR}/test_results/*&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#606&quot;&gt;reports&lt;/span&gt;:
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;junit&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#D20&quot;&gt;${CI_PROJECT_DIR}/test_results/my_test_results.xml&lt;/span&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Lädt die Ergebnisse dann zum Gitlab-Coordinator hoch und der kann dann die 
&lt;code&gt;my_test_results.xml&lt;/code&gt; sofort parsen und im Web-UI schön anzeigen.&lt;/p&gt;

&lt;h4 id=&quot;code-coverage&quot;&gt;Code Coverage&lt;/h4&gt;

&lt;p&gt;Bei der Code Coverage (oder auch Test-Coverage) wird im Sourcecode mitgezählt,
welche Zeilen ausgeführt wurden und welche nicht. Am Ende wissen wir, ob 
unsere Tests sinnvoll waren und alles abgetestet haben, oder viele Codezeilen
nie angesprungen und damit ungetestet verblieben sind.&lt;/p&gt;

&lt;p&gt;Je nach Umgebung muss man den Sourcecode speziell kompilieren und
mit Hilfsprogrammen die Coverage errechnen lassen.&lt;/p&gt;

&lt;p&gt;Beim GCC kann man die Sourcen mit &lt;code&gt;--coverage&lt;/code&gt; kompilieren womit bei der 
Ausführung &lt;code&gt;.gcno&lt;/code&gt; und &lt;code&gt;.gcda&lt;/code&gt; automatisch erstellt werden. 
Tools wie &lt;a href=&quot;https://gcovr.com/&quot;&gt;gcovr&lt;/a&gt; können diese Dateien dann in das 
Cobertura-XML Format umwandeln.&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;gcovr --xml-pretty -o coverage.xml --root path/to/source
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Unter Windows kann z.B.: &lt;code&gt;OpenCppCoverage&lt;/code&gt; ein Debug-Binary ausführen und misst
dessen Ausführung per Debugger mit.&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;OpenCppCoverage.exe --source path/to/sources --export_type cobertura:coverage.xml -- test.exe
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Doch leider reicht es jetzt nicht ganz aus, dieses Ergebnis einfach zum
Gitlab Coordinator hochzuladen mit:&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#606&quot;&gt;test_job&lt;/span&gt;:
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#606&quot;&gt;script&lt;/span&gt;:
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;    - &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#D20&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#606&quot;&gt;artifacts&lt;/span&gt;:
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#606&quot;&gt;paths&lt;/span&gt;:
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;      - &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#D20&quot;&gt;${CI_PROJECT_DIR}/test_results/*&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#606&quot;&gt;reports&lt;/span&gt;:
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;coverage_report&lt;/span&gt;:
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;        &lt;span style=&quot;color:#606&quot;&gt;coverage_format&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#D20&quot;&gt;cobertura&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;        &lt;span style=&quot;color:#606&quot;&gt;path&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#D20&quot;&gt;${CI_PROJECT_DIR}/test_results/coverage.xml&lt;/span&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Denn um die &lt;code&gt;%&lt;/code&gt; Zahl der Coverage registriert zu bekommen, nutzt Gitlab
nicht die XML-Datei (die wird nur bei Mergerequests herangezogen).&lt;br /&gt;
Gitlab erwartet, dass das Ergebnis auf die Konsole geschrieben wird, und 
dass man es von dort per 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Regul%C3%A4rer_Ausdruck&quot;&gt;Regular-Expression&lt;/a&gt; 
auslesen kann.&lt;/p&gt;

&lt;p&gt;Bei &lt;code&gt;gcovr&lt;/code&gt; muss man noch den Commandline-Switch &lt;code&gt;--print-summary&lt;/code&gt;
anfügen, damit der Output so aussieht:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;gcovr --xml-pretty --print-summary -o coverage.xml --root /path/to/src
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;lines: 85.0% (425 out of 500)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;branches: 30.0% (17106 out of 56994)
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Mit dem &lt;code&gt;coverage&lt;/code&gt; Zusatz im Gitlab Job wird die &lt;code&gt;lines&lt;/code&gt; Zeile extrahiert:&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#606&quot;&gt;test_job&lt;/span&gt;:
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#606&quot;&gt;script&lt;/span&gt;:
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;    - &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#D20&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#606&quot;&gt;coverage&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#D20&quot;&gt;/^\s*lines:\s*\d+.\d+\%/&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#606&quot;&gt;artifacts&lt;/span&gt;:
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#606&quot;&gt;paths&lt;/span&gt;:
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;      - &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#D20&quot;&gt;${CI_PROJECT_DIR}/test_results/*&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#606&quot;&gt;reports&lt;/span&gt;:
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;coverage_report&lt;/span&gt;:
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;        &lt;span style=&quot;color:#606&quot;&gt;coverage_format&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#D20&quot;&gt;cobertura&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;        &lt;span style=&quot;color:#606&quot;&gt;path&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#D20&quot;&gt;${CI_PROJECT_DIR}/test_results/coverage.xml&lt;/span&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Am Ende hat man dann Test-Reports und Coverage-Reports, die man im Gitlab
Web-UI anzeigen und per Rest-API abholen kann.&lt;/p&gt;

&lt;p&gt;Durch &lt;a href=&quot;http://docs.gitlab.com/ee/user/project/badges.html&quot;&gt;Gitlab-Badges&lt;/a&gt; 
lässt sich die Coverage-Zahl auch direkt auf der Projektseite anzeigen und
diese kleinen SVG-Bilder lassen sich auch hervorragend in andere Gitlab-Seiten
einbauen um einen Überblick zu erhalten.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>RISC-V: Lichee RV Allwinner D1</title>
   <link href="https://www.opengate.at/blog/2022/08/risc-v/"/>
   <published>2022-08-21T13:00:00+02:00</published>
   <updated>2022-08-21T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2022/08/risc-v</id>
   <category term="hardware" />
   <summary type="text">RISC-V ist der neue “heiße Scheiß”,
der kommt/kommen wird/gekommen ist.

Es ist eine Open-Source Prozessor-Architektur, die in Zukunft den Computer 
Markt mitbestimmen soll. So wie vor 15-20 Jahren ARM Prozessoren über 
Smartphones eine große Verbreitung erlebten, so soll jetzt mit RISC-V 
ein weiterer Spieler hinzukommen.
</summary>
   <content type="html">&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/RISC-V&quot;&gt;RISC-V&lt;/a&gt; ist der neue “heiße Scheiß”,
der kommt/kommen wird/gekommen ist.&lt;/p&gt;

&lt;p&gt;Es ist eine Open-Source Prozessor-Architektur, die in Zukunft den Computer 
Markt mitbestimmen soll. So wie vor 15-20 Jahren ARM Prozessoren über 
Smartphones eine große Verbreitung erlebten, so soll jetzt mit RISC-V 
ein weiterer Spieler hinzukommen.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;eine-geschichte-rund-um-patente&quot;&gt;Eine Geschichte rund um Patente&lt;/h3&gt;

&lt;p&gt;Was gab es nicht für Prozesse und Anfeindungen zwischen Intel und seinen
Nachahmern, wenn es um den Bau von Prozessoren ging. Jede neue Technologie
wurde mit Patenten zugekleistert um möglichst viel Profit aus den Ideen
der Konkurrenz auf der eigenen Plattform herauszupressen.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Doch was wäre, wenn die allgemeine Funktionsweise von Prozessoren
frei von solchen Patenten wären?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Dann könnte jede Chip-Fabrik anfangen Chips zu fertigen, ohne dass lange
Verhandlungen, Prozesse und Lizenzzahlungen durchlaufen müssten.&lt;/p&gt;

&lt;p&gt;Diese Idee wurde mit RISC-V geboren, bzw. RISC-V wurde für diese Idee
geboren.&lt;/p&gt;

&lt;h3 id=&quot;lichee-rv-mit-allwinner-d1&quot;&gt;Lichee RV mit Allwinner D1&lt;/h3&gt;

&lt;p&gt;Im &lt;a href=&quot;https://www.sipeed.com/&quot;&gt;sipeed&lt;/a&gt; Store bei Aliexpress fand ich das 
“Lichee-RV D1” Starter Kit bestehend aus dem Prozessorboard und dem IO Dock 
für 37 Euro und erwarb somit:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;1GHz Single Core CPU (XuanTie C906 Risc-V-64bit)&lt;/li&gt;
  &lt;li&gt;512 MB RAM (DDR3)&lt;/li&gt;
  &lt;li&gt;HDMI Display&lt;/li&gt;
  &lt;li&gt;SD-Kartenslot&lt;/li&gt;
  &lt;li&gt;WLAN&lt;/li&gt;
  &lt;li&gt;Bluetooth&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/lichee-rv-01.jpg&quot; alt=&quot;Lichee RV D1&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Das sind die Merkmale des Lichee-RV D1 RISC-V Entwicklerboards. 
Ungewöhnlicherweise wurde hier das “Mainboard” von der Peripherie getrennt.
Der Prozessor+RAM Chip wird in ein eigenes Docking-Board eingespannt um ein
vollwertiges System zu bilden.
Auf dem Docking-Board befindet sich der HDMI-Anschluss, wie auch eine USB 2
und eine USB-C Buchse. Und neben dem 40-Pin IO Header sind noch 3 einzelne
Buttons am Board angebracht.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/lichee-rv-02.jpg&quot; alt=&quot;Lichee RV D1 Front&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;prebuild-images&quot;&gt;Prebuild images&lt;/h3&gt;

&lt;p&gt;Man findet einige Links zu Debian-Risc-V-Images, doch wenn man die 1:1 auf 
eine SD-Karte überträgt, funktionieren sie nicht. Offenbar müssen die auf der
Karte speziell ausgerichtet sein und benötigen dafür eine spezielle Software.&lt;/p&gt;

&lt;p&gt;Zum Glück gibt es aber auch vollständig vorbereitete Images, die man direkt 
auf die SD-Karte übertragen kann, und ich konnte ein solches unter 
&lt;a href=&quot;https://linux-sunxi.org/Sipeed_Lichee_RV#Boot_and_system_support&quot;&gt;linux-sunxi.org&lt;/a&gt;
finden. Die Datei trägt den Namen&lt;br /&gt;
&lt;code&gt;20211230_LicheeRV_debian_d1_hdmi_8723ds.ddimg.xz&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Mit dem &lt;a href=&quot;https://sourceforge.net/projects/win32diskimager/&quot;&gt;Win32DiskImager&lt;/a&gt; oder 
mit &lt;code&gt;dd&lt;/code&gt; unter Linux werden die 16 GB auf eine minestens ebenso große SD-Karte
übertragen. Und nach dem Einlegen in den SD-Slot am D1-Board, bootet das Gerät
auch schon davon.&lt;/p&gt;

&lt;p&gt;Schnell ist der Vorgang nicht, doch nach einiger Zeit landet man in der X11 
Login-Maske und kann mit&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;User: &lt;code&gt;sipeed&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Passwort: &lt;code&gt;licheepi&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;den UI Login und weiteren Start von &lt;a href=&quot;https://de.wikipedia.org/wiki/LXDE&quot;&gt;LXDE&lt;/a&gt; 
durchführen.&lt;/p&gt;

&lt;p&gt;Mit dem Datenträger-Verwaltungswerkzeug kann man nun die letzte leere 
“Füllpartition” der Karte löschen und die davor liegende Systempartition bis zum
Ende des Datenträgers vergrößern. Es sind nämlich weniger als 8 GB benutzt und 
der Speicher ist schon ziemlich voll.&lt;/p&gt;

&lt;h3 id=&quot;wlan&quot;&gt;WLAN&lt;/h3&gt;

&lt;p&gt;Das WLAN Modul ist per Konfiguration deaktiviert und deshalb scheiterte ich auch
daran, mit &lt;code&gt;ip link&lt;/code&gt; oder &lt;code&gt;ifup&lt;/code&gt; das Netzwerk hochzufahren.&lt;br /&gt;
Doch “wer lesen kann ist klar im Vorteil”, denn es stand ohnehin auf der Webseite
beschrieben, dass das Netzwerk mit dem &lt;a href=&quot;https://wiki.debian.org/ConnMan&quot;&gt;ConnMan&lt;/a&gt;,
einem Netzwerkverwalter für Embedded Systeme betrieben wird, und im Startmenü
befindet sich mit “ConnMan Settings” auch ein UI dafür.&lt;/p&gt;

&lt;p&gt;Dort kann man den WLAN Adapter grafisch einschalten und sich zum nächsten WLAN 
Accesspoint verbinden.&lt;br /&gt;
Bisher hatte ich noch nie mit ConnMan gearbeitet … war also wieder mal 
&lt;a href=&quot;https://manpages.debian.org/testing/connman/connman.8.en.html&quot;&gt;eine neues MAN Erlebnis&lt;/a&gt; 
für mich.&lt;/p&gt;

&lt;p&gt;Interessant war, dass ich meinen normalen USB-LAN-Adapter auch nicht einfach 
anschließen konnte. Für diesen wurde kein Treiber geladen, was ich so nicht
gewohnt war.&lt;/p&gt;

&lt;h3 id=&quot;neue-schlüssel-für-apt&quot;&gt;Neue Schlüssel für apt&lt;/h3&gt;

&lt;p&gt;Als nächstes standen Updates an, doch Aufrufe von &lt;code&gt;apt update&lt;/code&gt; und &lt;code&gt;apt upgrade&lt;/code&gt;
scheiterten mit der Meldung:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Failed to fetch … The following signatures couldn’t be verified because 
the public key is not available: NO_PUBKEY …&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Die offizielle Lösung des Problems lautete auf:&lt;br /&gt;
&lt;code&gt;curl https://www.ports.debian.org/archive_2022.key | apt-key add -&lt;/code&gt;&lt;br /&gt;
doch leider waren weder &lt;a href=&quot;https://de.wikipedia.org/wiki/CURL&quot;&gt;curl&lt;/a&gt; 
noch &lt;a href=&quot;https://de.wikipedia.org/wiki/Wget&quot;&gt;wget&lt;/a&gt; im Linux Image enthalten.&lt;/p&gt;

&lt;p&gt;Ich musste also &lt;code&gt;https://www.ports.debian.org/archive_2022.key&lt;/code&gt; auf meinem 
PC herunterladen, auf einen USB Stick kopieren und diesen am Lichee-RV 
anschließen. Von dort konnte ich den Import mit&lt;br /&gt;
&lt;code&gt;apt-key add /path/to/archive_2022.key&lt;/code&gt; erfolgreich durchführen und im 
Anschluss das Update starten.&lt;/p&gt;

&lt;h3 id=&quot;upgrade&quot;&gt;Upgrade&lt;/h3&gt;

&lt;p&gt;Fast 1000 Update-Pakete wurden vorgeschrieben, und so startete eine 
stundenlange Download- und Installationsprozedur.&lt;/p&gt;

&lt;p&gt;Am Ende erkannte ich, dass meine Debian 11 Installation durch das sich noch 
in Entwicklung befindliche Debian 12 (Name Bookworm) ersetzt wurde.
Warum das ungefragt geschehen war, weiß ich nicht, denn &lt;code&gt;/etc/apt/sources.list&lt;/code&gt; 
verwies auf die allgemeine Debian Backports Pfade.&lt;/p&gt;

&lt;p&gt;Wer dieses Upgrade also nicht möchte, sollte Maßnahmen dagegen ergreifen.&lt;br /&gt;
Denn leider kam es ab dem Upgrade immer wieder mal zu Hängern beim Neustart.
Hier muss man Board entweder per Reset-Taste oder Stromentzug so lange
neu starten, bis der Startvorgang wieder vollständig bis zur UI durchläuft.
Das war vor dem Update in meinen Tests nämlich nicht so.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Das Lichee RV D1 Board ist in etwa auf dem Niveau eines originalen 
&lt;a href=&quot;https://www.raspberrypi.com/products/raspberry-pi-zero-w/&quot;&gt;Raspberry Pi Zero W&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Als Desktop Ersatz sind weder das D1 noch der Pi Zero geeignet, denn mit 512 MB 
RAM braucht man an einen Webbrowser gar nicht erst zu denken.&lt;/p&gt;

&lt;p&gt;Das Kompilieren des GATE-Frameworks lief wie erwartet träge und brach wegen zu
wenig RAM beim &lt;a href=&quot;https://gcc.gnu.org/wiki/LinkTimeOptimization&quot;&gt;LTO&lt;/a&gt; Linkvorgang
ab, doch ohne LTO erhält man feine RISC-V Binaries, die auch sogleich ausgeführt
werden können.&lt;/p&gt;

&lt;p&gt;Als nächstes werde ich mich den GPIO Funktionen widmen. Wie schön, dass die auf
der Rückseite beschrieben sind.&lt;br /&gt;
&lt;img src=&quot;/blog/assets/img/lichee-rv-03.jpg&quot; alt=&quot;Lichee RV D1 Back&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Wer einige Euros mehr investiert, erhält natürlich auch mehr Kerne und mehr RAM
in anderen Modellen und Produkten, doch aktuell liegen diese noch weit hinter
ARM basierten Modellen zurück.&lt;br /&gt;
Aber vergessen wir nicht, wie lange ARM hinter X86 zurück lag und heute ist
ARM auf der Überholspur, vor allem in Sachen Energieeffizienz.&lt;/p&gt;

&lt;p&gt;Ich erwarte bzw. erhoffe mir also, dass RISC-V in den kommenden Jahren einen
ähnlichen Sprint hinlegt, damit wir in Zukunft endlich auch mal einen
OpenSource-Prozessor in unseren Geräten eingebaut bekommen.&lt;/p&gt;

&lt;p&gt;Der erste Eindruck war also “OK”, ich darauf kompilieren und ich bin gespannt
wie es dort weitergehen wird.&lt;br /&gt;
Denn immer weitere Boards wie &lt;a href=&quot;https://jamesachambers.com/mangopi-mq-pro-d1-ubuntu-preview/&quot;&gt;MangoPI&lt;/a&gt; 
oder &lt;a href=&quot;https://www.okqubit.net/nezha/&quot;&gt;Nezha&lt;/a&gt; werden auf den Markt geworfen.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>GCC Weak Symbols und no-as-needed</title>
   <link href="https://www.opengate.at/blog/2022/08/weak-symbols/"/>
   <published>2022-08-20T13:00:00+02:00</published>
   <updated>2022-08-20T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2022/08/weak-symbols</id>
   <category term="devel" />
   <summary type="text">
  Mit dem GCC 
6 hat noch alles funktioniert und seit dem
Upgrade auf GCC 10 crashen unsere Binaries …


Und wieder einmal durfte ich lernen, dass kleine unscheinbare Änderungen
an Standard-Features große Ausfälle bei den Resultaten auslösen können.

Doch so lernte ich etwas über “Weak Symbols”, also “Schwache Symbole” 
in Bibliotheken.
</summary>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;Mit dem &lt;a href=&quot;https://de.wikipedia.org/wiki/GNU_Compiler_Collection&quot;&gt;GCC&lt;/a&gt; 
6 hat noch alles funktioniert und seit dem
Upgrade auf GCC 10 crashen unsere Binaries …&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Und wieder einmal durfte ich lernen, dass kleine unscheinbare Änderungen
an Standard-Features große Ausfälle bei den Resultaten auslösen können.&lt;/p&gt;

&lt;p&gt;Doch so lernte ich etwas über “Weak Symbols”, also “Schwache Symbole” 
in Bibliotheken.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;(Bei der Gelegenheit ein großes Danke an meinen Kollegen, der das
Problem analysiert, gelöst und mir vermittelt hat.)&lt;/p&gt;

&lt;p&gt;Spezielle Features von Compilern oder Betriebssystemen interessieren mich 
normalerweise wenig. Schließlich scheitert man an genau diesen, wenn man 
plattformunabhängigen Code erzeugen will.&lt;/p&gt;

&lt;p&gt;Darunter fielen bisher Microsofts 
&lt;a href=&quot;http://docs.microsoft.com/en-us/cpp/build/reference/linker-support-for-delay-loaded-dlls&quot;&gt;Delay-Loaded DLLs&lt;/a&gt;
oder so manche &lt;a href=&quot;https://docs.microsoft.com/en-us/cpp/cpp/declspec&quot;&gt;__declspec&lt;/a&gt; 
Erweiterungen und das gleiche gilt auch für &lt;code&gt;__attribute__&lt;/code&gt; beim GCC.&lt;br /&gt;
Nur &lt;code&gt;__declspec(dllexport/dllimport)&lt;/code&gt; und &lt;br /&gt;
&lt;code&gt;__attribute__((visibility (&quot;default/hidden&quot;)))&lt;/code&gt; sind die Ausnahme, weil sie 
de-facto Standards auf ihren jeweiligen Plattformen sind.&lt;/p&gt;

&lt;h3 id=&quot;gcc-weak-functions&quot;&gt;GCC Weak-Functions&lt;/h3&gt;

&lt;p&gt;Der GCC erlaubt, dass eine Funktion oder eine Variable deklariert und 
exportiert werden kann, ohne dass sie tatsächlich implementiert sein muss.
Mit dem Attribut &lt;code&gt;__attribute__((weak))&lt;/code&gt; bei z.B. einer Funktion, wird
diese exportiert ohne vorhanden sein zu müssen.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; lib_function(&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; param) __attribute__((weak));
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Man kann somit ein “Interface” in einer Bibliothek deklarieren ohne es
zu implementieren. Und die Bibliothek kann dann bei Bedarf eine andere
Bibliothek laden oder direkt linken, die den gleichen Funktionsnamen 
regulär implementiert.&lt;/p&gt;

&lt;p&gt;Denn Weak-Symbole werden von normalen (Strong-)Symbolen überschrieben.
So kann man öffentliche von privaten Bibliotheken trennen und z.B.: die
privaten Bibliotheksteile dann beliebig austauschen.&lt;/p&gt;

&lt;script src=&quot;/blog/assets/mermaid/mermaid.min.js&quot;&gt;&lt;/script&gt;
&lt;div class=&quot;mermaid&quot;&gt;
graph LR
  PROG(Main&lt;br /&gt;Program)
  IFACE[[&quot;Public Interface Library&lt;br /&gt;lib_function() weak&quot;]]
  IMPL[[&quot;Private Implementation Library&lt;br /&gt;lib_function() strong&quot;]]

  PROG --Link--&amp;gt; IFACE
  IFACE --Link--&amp;gt; IMPL
  PROG -. &quot;Invoke&lt;br /&gt;lib_function()&quot; .-&amp;gt; IMPL
&lt;/div&gt;

&lt;h3 id=&quot;problem-linker-optimierungen&quot;&gt;Problem Linker-Optimierungen&lt;/h3&gt;

&lt;p&gt;Dumm ist dann nur, wenn eine Bibliothek mit &lt;code&gt;weak&lt;/code&gt; Symbolen eine andere
mit &lt;code&gt;strong&lt;/code&gt; Symbolen linkt und dann keine direkten Aufrufe zur zweiten
Lib enthält.&lt;br /&gt;
Denn moderne Compiler ermitteln, dass keine Aufrufe stattfinden und 
entfernen die Bibliothek dann aus der Liste der Abhängigkeiten.
Diese Feature wird durch das Linker-Flag &lt;code&gt;--as-needed&lt;/code&gt; explizit aktiviert.&lt;/p&gt;

&lt;p&gt;Am Ende wird die “private” Bibliothek nicht geladen und die Interface-
Bibliothek steht alleine da mit einer “leeren” &lt;code&gt;weak&lt;/code&gt; Referenz.&lt;br /&gt;
Ein Programm, das diese &lt;code&gt;weak&lt;/code&gt; Funktion aufruft, springt somit in einen
&lt;a href=&quot;https://en.wikipedia.org/wiki/Null_pointer&quot;&gt;Null-Pointer&lt;/a&gt; hinein, 
was selten gut ausgeht.&lt;/p&gt;

&lt;p&gt;Und so erklärt sich, warum ältere Compiler ohne diese Optimierung Code
generieren, der solche &lt;code&gt;weak&lt;/code&gt; Funktionen in Bibliotheken samt deren
Abhängigkeiten laden kann, während neuere Kompilate zu einem&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Segmentation fault (core dumped)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;führen.&lt;/p&gt;

&lt;h3 id=&quot;lösung---no-as-needed&quot;&gt;Lösung: &lt;code&gt;--no-as-needed&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;Mit dem Linker-Flag &lt;code&gt;--no-as-needed&lt;/code&gt;, bzw. &lt;code&gt;-Wl,--no-as-needed&lt;/code&gt; beim Compiler
wird diese Optimierung deaktiviert und auch moderne GCC Compiler können dann
jene Bibliotheken korrekt laden, die per &lt;code&gt;weak&lt;/code&gt; Symbols auf andere 
Bibliotheken weiterverlinken.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Wieder mal etwas interessantes gelernt!&lt;br /&gt;
Ein &lt;a href=&quot;https://codeberg.org/GateNetwork/gate-blog-classroom/src/branch/main/c_cpp/weak_symbols/&quot;&gt;Codebeispiel&lt;/a&gt;
im Blog-Classroom zeigt den Sachverhalt im Code auf.&lt;/p&gt;

&lt;p&gt;Denn diese Arbeitsweise entdeckten wir bei einer 3rd-Party-Komponente, die
offenbar ähnlich über solche &lt;code&gt;weak&lt;/code&gt; Funktionen zwischen mehreren 
Implementierungen umschalten konnte.&lt;/p&gt;

&lt;p&gt;Ich bin allerdings der Meinung, dass man das mit &lt;code&gt;dlopen/dlsym&lt;/code&gt; hätte lösen
sollen und keine (jetzt fragile) GCC-Compiler-Erweiterungen hätte nutzen 
sollen.&lt;br /&gt;
Denn Compiler-Standards ändern sich und weder der C noch der C++ Standard
definieren Richtlinien, wie sich exportierte Funktionen im Detail verhalten.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>PS/2 Modell 30</title>
   <link href="https://www.opengate.at/blog/2022/08/ps2-30/"/>
   <published>2022-08-14T13:00:00+02:00</published>
   <updated>2022-08-14T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2022/08/ps2-30</id>
   <category term="hardware" />
   <summary type="text">In meiner Vergangenheit finden sich in erster Linie “billige” 
Klone von PCs.

Doch darunter steht tatsächlich auch ein “originaler” IBM PC der Gattung
PS/2 Modell 30.
Das Geräte ging vermutlich um das Jahr 1987 über den Ladentisch, bis es dann
im Jahr 2000 in meiner Sammlung von Althardware landete.
</summary>
   <content type="html">&lt;p&gt;In meiner Vergangenheit finden sich in erster Linie “billige” 
&lt;a href=&quot;https://de.wikipedia.org/wiki/IBM-PC-kompatibler_Computer&quot;&gt;Klone von PCs&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Doch darunter steht tatsächlich auch ein “originaler” IBM PC der Gattung&lt;br /&gt;
PS/2 Modell 30.&lt;br /&gt;
Das Geräte ging vermutlich um das Jahr 1987 über den Ladentisch, bis es dann
im Jahr 2000 in meiner Sammlung von Althardware landete.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;hardware&quot;&gt;Hardware&lt;/h3&gt;

&lt;p&gt;So sieht also ein “richtiger” PC aus. Ein flaches Desktopgehäuse, auf dem ein
fetter &lt;a href=&quot;https://de.wikipedia.org/wiki/Video_Graphics_Array9-Röhrenmonitor&quot;&gt;VGA&lt;/a&gt;
platziert wurde. Ein oder zwei Diskettenlaufwerke und ein übergroßer On/Off 
Schalter, den man sonst nur aus Filmen kennt um damit Atomraketen zu zünden.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/ibmps2-30-front.jpg&quot; alt=&quot;IBM PS/2 M30 Front&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Innen drinnen sieht man noch richtige Bauteile wie Zentimeter-große Dioden,
die man heute nur noch mit der Lupe oder mit Mikroskopen finden könnte.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/ibmps2-30-inside.jpg&quot; alt=&quot;IBM PS/2 M30 Inside&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Die faszinierendste Konstruktion, die ich je gesehen hatte war aber der große
rote Kippschalter, dessen Ausrichtung mechanisch über einen Bügel zum Netzteil
geleitet wurde, wo er den Stromkreis schließen oder unterbrechen konnte.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/ibmps2-30-power.jpg&quot; alt=&quot;IBM PS/2 M30 Power&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Mein Modell kam mit 2 Diskettenlaufwerken. Ursprünglich war auch eine 
Festplatte per ISA-Bus direkt verbunden, doch nachdem diese schon kurz nachdem
ich das Gerät bekommen hatte einging, hatte ich diese damals gleich ausgebaut,
weil sie (wie alle Platten damals) ziemlich laut war.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/ibmps2-30-floppydrives.jpg&quot; alt=&quot;IBM PS/2 M30 Floppydrives&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Auf der Rückseite findet man&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;PS/2 Anschluss für die Tastatur&lt;/li&gt;
  &lt;li&gt;PS/2 Anschluss für eine Maus&lt;/li&gt;
  &lt;li&gt;einen Parallelport Anschluss für Drucker&lt;/li&gt;
  &lt;li&gt;einen seriellen Port&lt;/li&gt;
  &lt;li&gt;und einen VGA D-SUB-15 Anschluss.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/ibmps2-30-back.jpg&quot; alt=&quot;IBM PS/2 M30 Back&quot; /&gt;&lt;/p&gt;

&lt;p&gt;… hmm, oder vielleicht nicht ganz, denn von den 15 Pins sind nur 14 
verfügbar. Pin Nr. 9 (der zweite von links in der mittleren Reihe) ist
nämlich nicht “durchgebohrt”. Nicht alle meine VGA-Kabel konnten damit 
umgehen, doch einige waren auf diesen fehlenden Pin zum Glück vorbereitet.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/ibmps2-30-vga.jpg&quot; alt=&quot;IBM PS/2 M30 VGA&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Zu meinem Bedauern sind auch die Floppylaufwerke offenbar nicht mehr in 
Ordnung. Eines ist überhaupt still, weil vermutlich der Motor defekt ist.
Das zweite konnte seinen Motor zwar starten, doch Disketten vermochte es
nicht zu lesen, zumindest kam es nie zu einem Bootvorgang.&lt;/p&gt;

&lt;p&gt;Beim Umbau der beiden Floppy-Laufwerke bekam ich anfangs leider das
Gehäuse nicht zerlegt. 
Hätte mir doch jemand gesagt, dass bei diesem Gerät alles nur 
“zusammengesteckt” ist und dass man nur an den richtigen Stellen “drücken”
muss, damit sich die Komponenten lösen.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/ibmps2-30-floppy.jpg&quot; alt=&quot;IBM PS/2 M30 Floppydrive&quot; /&gt;&lt;/p&gt;

&lt;p&gt;So werkelte ich lange herum, was nicht jede der Plastikhalterung schadfrei
überstand. Am Ende konnte ich jedoch die beiden Floppy-Laufwerke tauschen
um zu sehen, wie sich das zweite beim Boot verhalten sollte.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/ibmps2-30-floppybay.jpg&quot; alt=&quot;IBM PS/2 M30 Floppybay&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;software-ohne-datenträger&quot;&gt;Software ohne Datenträger&lt;/h3&gt;

&lt;p&gt;Nachdem beim Start kein Boot von Diskette möglich ist, erschient eine
interessante ASCII-Text Animation auf dem Bildschirm, die einen anweist
eine Boot-Diskette einzulegen.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/ibmps2-30-boot.jpg&quot; alt=&quot;IBM PS/2 M30 Bootscreen&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Wenn dann weiter kein Disketten-Boot möglich ist, landet man im 
IBM-BASIC, dass im Chip abgelegt ist.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/ibmps2-30-basic.jpg&quot; alt=&quot;IBM PS/2 M30 BASIC&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Das fühlt sich fast so an wie beim Commodore 64. Denn auch dort landet man
stets im BASIC-Editor und kann sich mit einige BASIC-Kommandos seine
eigene Software schreiben und direkt auf der Hardware ausführen.&lt;br /&gt;
Freilich geht jeder Code beim Neustart verloren, weil man kein Medium
verfügbar hat, worauf man den Code speichern könnte.&lt;/p&gt;

&lt;p&gt;Interessant ist es aber trotzdem.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Nachdem heutige PCs mit der EFI-Shell eigentlich auch eine mächtige Umgebung
direkt am Chip installiert haben, ist es Schade, dass keine Programmierung 
auf der Ebene möglich ist. Denn die paar Kilobytes hätte man auch noch 
finden können, um ein BASIC, LUA oder was Ähnliches bereitzustellen.&lt;/p&gt;

&lt;p&gt;Der IBM PS/2 ist für mich daher ein gutes Beispiel für einen durchdachten
Computer … obwohl seine Bauteile leider nicht alle bis heute überlebt haben.&lt;/p&gt;

&lt;p&gt;Und es zeigt sich wieder einmal, was früher mit derart wenigen Mitteln alles
möglich war.&lt;br /&gt;
Naja … es war eben IBM und die wollten immer schon im “Business” Eindruck 
machen, wie die Werbung deutlich machte:&lt;/p&gt;

&lt;iframe width=&quot;640&quot; height=&quot;360&quot; src=&quot;/blog/redirect.html?https%3A%2F%2Fwww.youtube-nocookie.com%2Fembed%2F4f01qfwyYMg&quot; frameborder=&quot;1&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
</content>
 </entry>
 
 <entry>
   <title>Pinebook Pro</title>
   <link href="https://www.opengate.at/blog/2022/08/pinebook/"/>
   <published>2022-08-13T13:00:00+02:00</published>
   <updated>2022-08-13T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2022/08/pinebook</id>
   <category term="hardware" />
   <summary type="text">Endlich … ein weiterer Schritt in Richtung 
ARM64.

2 Monate musste ich warten, bis “mein” Pinebook Pro von 
Pine64 endlich geliefert werden konnte, 
doch nun besitze ich einen Linux 
basierten Laptop, mit dem auch die 
mobile Programmierung möglich wird.
</summary>
   <content type="html">&lt;p&gt;Endlich … ein weiterer Schritt in Richtung 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Arm-Architektur#Armv8-A_(2011)&quot;&gt;ARM64&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;2 Monate musste ich warten, bis “mein” Pinebook Pro von 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Pine64&quot;&gt;Pine64&lt;/a&gt; endlich geliefert werden konnte, 
doch nun besitze ich einen &lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt; 
basierten &lt;a href=&quot;https://de.wikipedia.org/wiki/Notebook&quot;&gt;Laptop&lt;/a&gt;, mit dem auch die 
mobile Programmierung möglich wird.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Eigentlich mochte ich meinen &lt;a href=&quot;/blog/2019/11/pi-top/&quot;&gt;Pi-Top&lt;/a&gt; … 
doch etwas war darauf nicht so lustig:
Nämlich größere Codeprojekte zu bearbeiten. Denn der enthaltene 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Raspberry_Pi&quot;&gt;Raspberry PI&lt;/a&gt; 3B+ verhindert mit 
seinem einzelnen 1 GB RAM, dass IDEs und Buildprozesse stabil laufen.&lt;/p&gt;

&lt;p&gt;Und nachdem der Raspberry PI 4 mit einem anderen Layout inkompatibel zum 
Laptopformat war, blieb meine Motivation mit dem PI 3 “mehr” darauf zu machen
recht gering.&lt;/p&gt;

&lt;h3 id=&quot;pine64&quot;&gt;Pine64&lt;/h3&gt;

&lt;p&gt;Nach dem &lt;a href=&quot;/blog/2020/11/pinephone/&quot;&gt;PinePhone&lt;/a&gt;, dem Pinecil und der 
&lt;a href=&quot;/blog/2021/08/pinetime/&quot;&gt;PineTime&lt;/a&gt; habe ich ein weiteres 
Geschwisterchen der Pine64 Familie bestellt.&lt;br /&gt;
Ich machte bereits letztes Jahr den Fehler, das Gerät nicht zu bestellen und
musste nun über ein halbes Jahr warten, bis es überhaupt wieder produziert
wurde und kaufte schließlich eines der neuen Geräte (mit ANSI Tastatur).&lt;br /&gt;
Auch hier verzögerte sich die Lieferung von Juni/Juli auf die erste Augustwoche,
doch nun ist der Laptop endlich da.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/pinebook_pro.jpg&quot; alt=&quot;Pinebook Pro&quot; /&gt;&lt;/p&gt;

&lt;p&gt;220 Dollar ist der aktuelle Kaufpreis und DHL verrechnete noch weitere 70 Euro
an Einfuhrzöllen. Hier bin ich fast schwer beeindruckt, wie unkompliziert 
diese Zahlung per Link und &lt;a href=&quot;https://de.wikipedia.org/wiki/PayPal&quot;&gt;PayPal&lt;/a&gt; war, 
sodass der Lieferung keine 5 Minuten aufgehalten wurde. Ich wünschte, 
das wäre immer so einfach bei Importen.&lt;/p&gt;

&lt;h3 id=&quot;daten-und-leistung&quot;&gt;Daten und Leistung&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;6 Kerne (2x 1.8GHzm 4x 1.4GHz)&lt;/li&gt;
  &lt;li&gt;4 GB RAM&lt;/li&gt;
  &lt;li&gt;64 GB &lt;a href=&quot;https://de.wikipedia.org/wiki/Multimedia_Card#eMMC&quot;&gt;eMMC&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;1080p Display&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Das übertrifft den Raspberry PI 3B und auch Modell 4 bei weitem und sollte mir
ein völlig neues mobiles Arbeiten ermöglichen.&lt;br /&gt;
Und trotzdem bemerkte ich, dass ein 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_Studio_Code&quot;&gt;Visual Studio Code&lt;/a&gt; schon 
seine Zeit brauchte, um geladen zu werden und um Code “einzufärben”.&lt;br /&gt;
Ich vermute, dass hier aber eher das eMMC Modul ein Flaschenhals war, denn 
beim Kompilieren übertraf die ARM-Maschine meinen alten i3-Laptop (4 logische 
Kerne) aus dem Jahr 2016.&lt;/p&gt;

&lt;p&gt;Meine üblichen Videodateien in 720p Auflösung konnten problemlos abgespielt
werden, und viel mehr brauche ich im Alltag auch nicht.&lt;/p&gt;

&lt;h3 id=&quot;kleine-mankos&quot;&gt;Kleine Mankos&lt;/h3&gt;

&lt;p&gt;Irgend etwas stimmt mit dem Audio-Modul nicht, denn wenn ein Sound abgespielt
wird, erfolgt danach nach etwa 10 Sekunden ein ziemlich lautes Knacken, als
hätte jemand einen fetten Kippschalter umgelegt.&lt;br /&gt;
Dieses “Abschalten” der internen Lautsprecher erschreckte mich am Anfang 
furchtbar, weil ich dachte, dass der 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Lithium-Ionen-Akkumulator&quot;&gt;Lithium-Akku&lt;/a&gt; 
aufgeplatzt wäre.&lt;/p&gt;

&lt;p&gt;Ob das nun ein Softwareproblem ist oder einfach nur der Lautsprecher falsch
verdrahtet ist, weiß ich nicht … aber mal sehen ob im Pine-Forum jemand
etwas Ähnliches berichtet.&lt;/p&gt;

&lt;h3 id=&quot;manjaro-linux&quot;&gt;Manjaro Linux&lt;/h3&gt;

&lt;p&gt;Lange hatte ich schon überlegt &lt;a href=&quot;https://de.wikipedia.org/wiki/Manjaro_Linux&quot;&gt;Manjaro Linux&lt;/a&gt; 
auf dem PinePhone einzusetzen, doch mir gefiel die Tatsache eine “echtes” 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Alpine_Linux&quot;&gt;Alpine-Linux&lt;/a&gt; mit 
&lt;a href=&quot;https://en.wikipedia.org/wiki/PostmarketOS&quot;&gt;PostmarketOS&lt;/a&gt; einzusetzen.&lt;br /&gt;
Mit dem PineBook Pro kommt nun endlich mal eine 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Arch_Linux&quot;&gt;Arch-Linux&lt;/a&gt; Distribution bei mir 
zum Einsatz.&lt;/p&gt;

&lt;p&gt;Und diese Linux Variante gefällt mir bisher recht gut, weil sie vor allem
optisch gut gestaltet ist und ich mir vorstellen kann, dass auch ein Anfänger
sich gut darauf zurecht findet.&lt;/p&gt;

&lt;p&gt;Fehlende Apps wie etwa ein Mailclient und Updates sind einfach per UI
installierbar und alle anderen Pakete für spezielle Zwecke (wie Compiler
und Development-Libs) lassen sich per&lt;br /&gt;
&lt;code&gt;sudo pacman -S PACKNAME&lt;/code&gt;
einrichten.&lt;/p&gt;

&lt;p&gt;Einziges Manko hier war tatsächlich die Passwort-Vergabe.&lt;br /&gt;
Ich wechselte nämlich zuerst zum deutschen Tastaturlayout und tippte
im Dialog ein paar Seiten später mein Passwort ein.&lt;br /&gt;
Doch beim ersten Login nach einem Neustart funktionierte das nicht.&lt;/p&gt;

&lt;p&gt;Schnell wurde mir klar, dass die Sonderzeichen ursprünglich noch mit dem
englischen Tastaturlayout eingetippt wurden. 
Eine &lt;code&gt;passwd&lt;/code&gt; Aufruf korrigierte das Problem … doch diese unnötige
Fehler schreckt womöglich neue Kunden ab.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Von 2006 bis 2016 war ein Laptop an der Hälfte meiner Entwicklungen
beteiligt. Danach folgte eine intensive Desktop-Zeit, da ich einfach 
nicht mehr mit einem Monitor auskomme und meine Geräte stets an
Leistungsgrenzen stießen.&lt;/p&gt;

&lt;p&gt;Ich hoffe, mein PineBook nun häufiger zu benutzen und wieder mobiler
damit zu werden.&lt;/p&gt;

&lt;p&gt;Vor allem wird mir die Linux ARM64 Platform die Gelegenheit bieten können
ein paar Zeilen ARM64-Assembler zu lernen.&lt;br /&gt;
Und darauf freue ich mich schon ganz besonders.&lt;/p&gt;

&lt;p&gt;Von daher mal ein:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Herzlich willkommen im Team!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;an meinen neuen digitalen Gefährten. Der erste Eindruck ist ein guter.
Und die paar Macken, bekommen wir schon noch in den Griff.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>XTEA und Blowfish</title>
   <link href="https://www.opengate.at/blog/2022/08/xtea/"/>
   <published>2022-08-07T13:00:00+02:00</published>
   <updated>2022-08-07T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2022/08/xtea</id>
   <category term="devel" />
   <summary type="text">Kryptographie-Bibliotheken gibt es viele. OpenSSL
libReSSL und Crypto++ 
sind wiederkehrende Weggefährten meines Programmieralltags.

Doch wenn es darum geht ohne Abhängigkeiten “ein bisschen” Sicherheit über 
Daten zu legen (z.B.: am Mikrocontroller), dann sind die genannten Moloche
ungeeignet.

Hier greife ich dann gerne zu Blowfish 
oder XTEA.
</summary>
   <content type="html">&lt;p&gt;Kryptographie-Bibliotheken gibt es viele. &lt;a href=&quot;https://de.wikipedia.org/wiki/OpenSSL&quot;&gt;OpenSSL&lt;/a&gt;
&lt;a href=&quot;https://de.wikipedia.org/wiki/LibreSSL&quot;&gt;libReSSL&lt;/a&gt; und &lt;a href=&quot;https://en.wikipedia.org/wiki/Crypto%2B%2B&quot;&gt;Crypto++&lt;/a&gt; 
sind wiederkehrende Weggefährten meines Programmieralltags.&lt;/p&gt;

&lt;p&gt;Doch wenn es darum geht ohne Abhängigkeiten “ein bisschen” Sicherheit über 
Daten zu legen (z.B.: am Mikrocontroller), dann sind die genannten Moloche
ungeeignet.&lt;/p&gt;

&lt;p&gt;Hier greife ich dann gerne zu &lt;a href=&quot;https://de.wikipedia.org/wiki/Blowfish&quot;&gt;Blowfish&lt;/a&gt; 
oder &lt;a href=&quot;https://de.wikipedia.org/wiki/Extended_Tiny_Encryption_Algorithm&quot;&gt;XTEA&lt;/a&gt;.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Symmetrisches_Kryptosystem&quot;&gt;Symmetrische Verschlüsselung&lt;/a&gt; 
ist generell nicht hoch-sicher, gemessen an asynchronen Verfahren, die aber auch schwer an Bit-Adipositas leiden.&lt;/p&gt;

&lt;p&gt;Wer aber “nur” verhindern möchte, dass ein anderer seine Dateien lesen kann,
erzeugt sich einen Schlüssel und lässt seine Daten damit umordnen, so dass man
eben selbigen Schlüssel braucht, um das Ganze wieder lesbar zu machen.&lt;/p&gt;

&lt;p&gt;Wie man diesen Schlüssel jetzt “gut aufbewahrt” ist eine andere Frage,
um die es hier nicht gehen soll.&lt;/p&gt;

&lt;h3 id=&quot;blowfish&quot;&gt;Blowfish&lt;/h3&gt;

&lt;p&gt;Der von &lt;a href=&quot;https://de.wikipedia.org/wiki/Bruce_Schneier&quot;&gt;Bruce Schneier&lt;/a&gt; 
stammende Blowfish arbeitet auf 64-bit Blöcken und verschränkt bzw. 
verschiebt Bits mit durch den Schlüssel generierten Datenblöcken, die man 
durch eine Umkehrfunktion wiederherstellen kann 
(siehe &lt;a href=&quot;https://de.wikipedia.org/wiki/Feistelchiffre&quot;&gt;Feistelnetzwerk&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;In Berührung gekommen bin ich mit Blowfish vor langer Zeit 
&lt;a href=&quot;https://www.codeproject.com/articles/1400/a-c-implementation-of-the-blowfish-encryption-decr&quot;&gt;auf CodeProject&lt;/a&gt;
als die “schnelle” Verschlüsselung von Daten mit einem festen einkompilierten 
Schlüssel in einem Projekt notwendig war.&lt;br /&gt;
Der dortige C++ Code hat leider den Fehler, dass er nicht Streaming-fähig ist,
man kann also nicht stückweise die Daten an den En/Decoder verfüttern.
Genau das war meine erste Änderung an dem Modul und nach vielen weiteren 
Iteration ist ein darauf aufbauender Code noch am GATE Projekt gelandet.&lt;/p&gt;

&lt;p&gt;Zur Verifizierung des selbst überarbeiteten Codes nutze ich OpenSSL, das mit seinen
&lt;code&gt;BF_*&lt;/code&gt; APIs zum gleichen Ergebnis kommen muss.&lt;/p&gt;

&lt;h4 id=&quot;ecb-und-cbc&quot;&gt;ECB und CBC&lt;/h4&gt;

&lt;p&gt;Ich verstehe wenig von Kryptographie, doch durch die Befassung mit Blowfish 
wurde mir die ECB und CBC Varianten verständlich erklärt.&lt;br /&gt;
Beim Electronic CodeBook (ECB) wird der Datenstrom in Blöcke zerteilt und 
jeweils mit dem gleichen Schlüssel verknüpft.
Das Ergebnis ist eine Kette von verschlüsselten (gleich großen) Blöcken,
die leider nicht sehr sicher sind.&lt;/p&gt;

&lt;p&gt;Im &lt;a href=&quot;https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Electronic_codebook_(ECB)&quot;&gt;Wikipeda Artikel&lt;/a&gt;
zeigt die Verschlüsselung eines Bildes, dass das Ergebnis noch erkennbar das
Muster der Originaldaten aufweist.&lt;/p&gt;

&lt;p&gt;Beim Cipher Block Chaining (CBC) wird ein zusätzlicher “Initialisierungsvektor”
in Form von ein paar Bytes definiert (also wie ein Zusatz zum Hauptschlüssel),
der mit den Eingangsdaten vor der Verschlüsselung verknüpft wird.
Der neu erzeugte verschlüsselte Block wird dann mit dem darauffolgenden 
Eingangsblock verknüpft, bevor dieser verschlüsselt wird … usw.
Nachdem jeder verschlüsselte Block einen Teil des Vorgängerblocks in sich 
trägt, ist das Ergebnis der gesamten Verschlüsselung “so zufällig”, dass man
keine Muster mehr erkennen kann (zumindest nicht leicht).&lt;/p&gt;

&lt;p&gt;Aus diesem Grund ist CBC das einzige Verfahren, dass man für 
Datenverschlüsselung nutzen sollte.&lt;/p&gt;

&lt;h3 id=&quot;tea-xtea-und-xxtea&quot;&gt;TEA, XTEA und XXTEA&lt;/h3&gt;

&lt;p&gt;Für Mikrocontroller ist Blowfish leider oft zu groß. Die wenigen nutzbaren 
Kilobytes würden von den Blowfish-Tabellen ausgefüllt werden, und deshalb 
suchte ich nach einer einfacheren Alternative.&lt;br /&gt;
Gefunden habe ich XTEA und seinen Nachfolger XXTEA.&lt;/p&gt;

&lt;p&gt;Der &lt;a href=&quot;https://de.wikipedia.org/wiki/Tiny_Encryption_Algorithm&quot;&gt;Tiny Encryption Algorithm&lt;/a&gt; 
(kurz: TEA) verknüpft Blöcke von 64-bit Daten mit einem 128-bit Schlüssel.&lt;br /&gt;
TEA galt jedoch nicht als besonders sicher und so wurde sein Nachfolger 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Extended_Tiny_Encryption_Algorithm&quot;&gt;XTEA&lt;/a&gt;
ins Leben gerufen, welcher wiederum mit 
&lt;a href=&quot;https://en.wikipedia.org/wiki/XXTEA&quot;&gt;XXTEA&lt;/a&gt; verbessert wurde, der auch als 
“Corrected Block TEA” bekannt ist.&lt;/p&gt;

&lt;p&gt;Während XTEA mehrere Verschlüsselungsrunden mit dem 128-bit Schlüssel auf
jeden 64-bit Datenteilblock anwendet, verknüpft XXTEA alle aufeinanderfolgenden
64-bit Datenblöcke und verknüpft diese in mehreren Runden.&lt;/p&gt;

&lt;p&gt;All TEA-Varianten sind als &lt;a href=&quot;https://de.wikipedia.org/wiki/Gemeinfreiheit&quot;&gt;Public-Domain&lt;/a&gt; 
Code frei verfügbar und wegen ihrer geringen Größe auch für Mikrocontroller 
geeignet.&lt;br /&gt;
XTEA verbraucht nur 24 Bytes (8 für Daten, 16 für Schlüssel) um einen Block
zu bearbeiten, womit man eine Nachricht in kleinen Teilstücken verschlüsseln 
kann.&lt;br /&gt;
XXTEA erhöht die Sicherheit nur dann, wenn man größere gepufferte Datenmengen
in einem Schritt verschlüsselt. Soll heißen, am
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microchip_AVR#ATtiny&quot;&gt;ATtiny&lt;/a&gt; mit 128 bis 512 
Bytes RAM macht es keinen Sinn, aber mit mehr RAM und größeren Nachrichten 
stellt XXTEA ein gutes Verhältnis zwischen Sicherheit und Komplexität dar.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Im GATE Framework sind Blowfish, XTEA und XXTEA implementiert.
Zwar habe ich aktuell noch keine direkte Anwendung dafür, aber die Nutzung
als “einfache” Verschlüsselung für Daten steht bereits auf meiner Wunschliste.&lt;/p&gt;

&lt;p&gt;Denn wenn man z.B.: Passwörter oder URL speichern möchte, die nicht jeder
Gastbenutzer gleich finden soll, dann hilft es sehr, diese verschlüsselt zu
speichern.&lt;/p&gt;

&lt;p&gt;Das ersetzt natürlich keinen guten Passwort-Manager, aber zumindest lässt 
man die Daten nicht fahrlässig im Klartext liegen.
Und das ist zumindest mal ein Anfang.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>HTA - Hypertext Applikationen</title>
   <link href="https://www.opengate.at/blog/2022/08/hta/"/>
   <published>2022-08-06T13:00:00+02:00</published>
   <updated>2022-08-06T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2022/08/hta</id>
   <category term="devel" /><category term="retro" />
   <summary type="text">Hypertext Applications (HTAs, auch HTML-Applications)
waren eine interessante und heute bedeutungslose Erweiterungen von Microsofts
Internet Explorer, um 
“echte” Fenster per XML 
erweitertem HTML
zu erzeugen und Desktop UIs damit zu bauen.

Und mit eben einer solchen HTA gelang es mir vor etwas über 10 Jahren 
Windows PE basierte 
Setups zu erstellen.
</summary>
   <content type="html">&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/HTML-Applikation&quot;&gt;Hypertext Applications (HTAs, auch HTML-Applications)&lt;/a&gt;
waren eine interessante und heute bedeutungslose Erweiterungen von Microsofts
&lt;a href=&quot;https://de.wikipedia.org/wiki/Internet_Explorer&quot;&gt;Internet Explorer&lt;/a&gt;, um 
“echte” Fenster per &lt;a href=&quot;https://de.wikipedia.org/wiki/Extensible_Markup_Language&quot;&gt;XML&lt;/a&gt; 
erweitertem &lt;a href=&quot;https://de.wikipedia.org/wiki/Hypertext_Markup_Language&quot;&gt;HTML&lt;/a&gt;
zu erzeugen und Desktop UIs damit zu bauen.&lt;/p&gt;

&lt;p&gt;Und mit eben einer solchen HTA gelang es mir vor etwas über 10 Jahren 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_PE&quot;&gt;Windows PE&lt;/a&gt; basierte 
Setups zu erstellen.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;blockquote&gt;
  &lt;p&gt;“Sicher” war der Internet Explorer bekanntlich nie. Und wenn man schon keine
sicheren Seiten damit bauen konnte, dann zumindest funktionsreiche.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So stelle ich mir vor, wie Microsoft damals dachte und HTAs waren ein Resultat
davon.&lt;br /&gt;
Die Idee war einfach: Man fügt eine &lt;code&gt;XML&lt;/code&gt; Zeile in den HTML-Kopf ein und 
speichert die Datei mit der &lt;code&gt;.hta&lt;/code&gt; Endung.&lt;br /&gt;
Sobald man diese doppelklickt, startet der “HTA Host” und erzeugt ein 
Browserfenster gemäß den Optionen im XML-Teil.&lt;/p&gt;

&lt;p&gt;Der Content wird wie im Browser durch reguläres HTML erzeugt und darf auch 
alle Features wie &lt;a href=&quot;https://de.wikipedia.org/wiki/JavaScript&quot;&gt;Javascript&lt;/a&gt; 
und &lt;a href=&quot;https://de.wikipedia.org/wiki/Cascading_Style_Sheets&quot;&gt;CSS&lt;/a&gt; nutzen.&lt;br /&gt;
Man hat quasi einen Browser ohne Browsermenü.&lt;/p&gt;

&lt;p&gt;Zusätzlich hat man per &lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_Script_Host&quot;&gt;Scripting-Host&lt;/a&gt; 
und &lt;a href=&quot;https://de.wikipedia.org/wiki/ActiveX&quot;&gt;Active-X&lt;/a&gt; auch Zugang zu allerlei 
lokalen Ressourcen und kann per &lt;code&gt;JScript&lt;/code&gt; und &lt;code&gt;VBScript&lt;/code&gt; jede Menge 
Systemoperationen auslösen, wie z.B. auch Prozesse starten.&lt;/p&gt;

&lt;h3 id=&quot;hta-demo-app&quot;&gt;HTA Demo App&lt;/h3&gt;

&lt;div class=&quot;language-html highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#777&quot;&gt;&amp;lt;!-- my_app.hta --&amp;gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#070;font-weight:bold&quot;&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#070;font-weight:bold&quot;&gt;&amp;lt;head&amp;gt;&lt;/span&gt;        
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#070;font-weight:bold&quot;&gt;&amp;lt;title&amp;gt;&lt;/span&gt;My Main Window Title&lt;span style=&quot;color:#070;font-weight:bold&quot;&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;        
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#070;font-weight:bold&quot;&gt;&amp;lt;hta:application&lt;/span&gt; &lt;span style=&quot;color:#b48&quot;&gt;id&lt;/span&gt;=&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;myGlobalJSobject&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; 
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#b48&quot;&gt;applicationname&lt;/span&gt;=&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;My application title&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; 
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#b48&quot;&gt;border&lt;/span&gt;=&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;dialog&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#b48&quot;&gt;caption&lt;/span&gt;=&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;yes&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;    &lt;span style=&quot;color:#b48&quot;&gt;contextmenu&lt;/span&gt;=&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;no&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#b48&quot;&gt;icon&lt;/span&gt;=&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;img/my_app_icon.ico&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#b48&quot;&gt;maximizebutton&lt;/span&gt;=&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;no&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#b48&quot;&gt;minimizebutton&lt;/span&gt;=&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;no&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;        
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#b48&quot;&gt;navigable&lt;/span&gt;=&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;no&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#b48&quot;&gt;scroll&lt;/span&gt;=&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;no&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#b48&quot;&gt;selection&lt;/span&gt;=&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;no&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#b48&quot;&gt;showintaskbar&lt;/span&gt;=&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;yes&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#b48&quot;&gt;singleinstance&lt;/span&gt;=&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;yes&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#b48&quot;&gt;sysmenu&lt;/span&gt;=&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;yes&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  &lt;span style=&quot;color:#070;font-weight:bold&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#070;font-weight:bold&quot;&gt;&amp;lt;/hta&amp;gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n21&quot; name=&quot;n21&quot;&gt;21&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n22&quot; name=&quot;n22&quot;&gt;22&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#070;font-weight:bold&quot;&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n23&quot; name=&quot;n23&quot;&gt;23&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;background-color:hsla(0,0%,0%,0.07);color:black&quot;&gt;    &lt;span style=&quot;color:#070;font-weight:bold&quot;&gt;body&lt;/span&gt; { &lt;span style=&quot;color:#606&quot;&gt;width&lt;/span&gt;: &lt;span style=&quot;color:#60E&quot;&gt;700px&lt;/span&gt;; &lt;span style=&quot;color:#606&quot;&gt;height&lt;/span&gt;: &lt;span style=&quot;color:#60E&quot;&gt;500px&lt;/span&gt;; } &lt;span style=&quot;color:#777&quot;&gt;/* app window size */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n24&quot; name=&quot;n24&quot;&gt;24&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#070;font-weight:bold&quot;&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;        
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n25&quot; name=&quot;n25&quot;&gt;25&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#070;font-weight:bold&quot;&gt;&amp;lt;link&lt;/span&gt; &lt;span style=&quot;color:#b48&quot;&gt;rel&lt;/span&gt;=&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;stylesheet&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span style=&quot;color:#b48&quot;&gt;type&lt;/span&gt;=&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;text/css&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span style=&quot;color:#b48&quot;&gt;href&lt;/span&gt;=&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;my_styles.css&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span style=&quot;color:#070;font-weight:bold&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n26&quot; name=&quot;n26&quot;&gt;26&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#070;font-weight:bold&quot;&gt;&amp;lt;script&lt;/span&gt; &lt;span style=&quot;color:#b48&quot;&gt;Language&lt;/span&gt;=&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;JavaScript&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span style=&quot;color:#b48&quot;&gt;src&lt;/span&gt;=&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;my_scripts.js&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#070;font-weight:bold&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#070;font-weight:bold&quot;&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n27&quot; name=&quot;n27&quot;&gt;27&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#070;font-weight:bold&quot;&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n28&quot; name=&quot;n28&quot;&gt;28&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#070;font-weight:bold&quot;&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n29&quot; name=&quot;n29&quot;&gt;29&lt;/a&gt;&lt;/span&gt;  My HTML based content rendered in HTA&apos;s app window
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n30&quot; name=&quot;n30&quot;&gt;30&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;color:#070;font-weight:bold&quot;&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n31&quot; name=&quot;n31&quot;&gt;31&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#070;font-weight:bold&quot;&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h3 id=&quot;jscript-und-vbscript&quot;&gt;JScript und VBScript&lt;/h3&gt;

&lt;p&gt;Mit Aufrufen wie &lt;code&gt;GetObject(&quot;object-moniker&quot;)&lt;/code&gt;&lt;br /&gt;
oder &lt;code&gt;new ActiveXObject(&quot;com-class-moniker&quot;)&lt;/code&gt; konnte man den 
&lt;code&gt;Windows Script Host&lt;/code&gt; anwerfen und mit eben diesem quasi alles 
andere auslösen.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;z.B. 0815 UI Features, wie etwa die Ermittelung der Bildschirmgröße um das 
eigene Fenster anzupassen:
    &lt;div class=&quot;language-javascript highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;var&lt;/span&gt; wmi = GetObject(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;winmgmts:&lt;/span&gt;&lt;span style=&quot;color:#b0b&quot;&gt;\\&lt;/span&gt;&lt;span style=&quot;color:#b0b&quot;&gt;\\&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#b0b&quot;&gt;\\&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;root&lt;/span&gt;&lt;span style=&quot;color:#b0b&quot;&gt;\\&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;cimv2&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;var&lt;/span&gt; monitors = wmi.ExecQuery(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Select * From Win32_DesktopMonitor&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;var&lt;/span&gt; scrWidth = &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;var&lt;/span&gt; scrHeight = &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;for&lt;/span&gt;(&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;var&lt;/span&gt; monitor = &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;new&lt;/span&gt; Enumerator(monitors); !monitor.atEnd(); monitor.moveNext())
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  scrWidth = monitor.item().ScreenWidth;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;  scrHeight = monitor.item().ScreenHeight;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;break&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;Andere Programme ausführen:
    &lt;div class=&quot;language-javascript highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;shell = &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;new&lt;/span&gt; ActiveXObject(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;WScript.Shell&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;shell.run(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;c:&lt;/span&gt;&lt;span style=&quot;color:#b0b&quot;&gt;\\&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;path&lt;/span&gt;&lt;span style=&quot;color:#b0b&quot;&gt;\\&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;to&lt;/span&gt;&lt;span style=&quot;color:#b0b&quot;&gt;\\&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;my.exe my_arg1 my_arg2&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;, &lt;span style=&quot;color:#069&quot;&gt;true&lt;/span&gt;);
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;Mit lokalen Dateien arbeiten:
    &lt;div class=&quot;language-javascript highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;var&lt;/span&gt; fso = &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;new&lt;/span&gt; ActiveXObject(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Scripting.FileSystemObject&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;var&lt;/span&gt; temp_folder = fso.GetSpecialFolder(&lt;span style=&quot;color:#00D&quot;&gt;2&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;var&lt;/span&gt; temp_file = temp_folder + &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#b0b&quot;&gt;\\&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;my_file.txt&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;var&lt;/span&gt; strm = fso.CreateTextFile(temp_file, &lt;span style=&quot;color:#069&quot;&gt;true&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;strm.Write(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;My Content&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;strm.Close();
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;htas-als-virus&quot;&gt;HTAs als Virus&lt;/h3&gt;

&lt;p&gt;Der Tod von HTAs lag in “ihrer Macht”. Denn schnell fanden Schurken heraus, 
dass HTAs gleich mächtig wie die früheren &lt;code&gt;.VBS&lt;/code&gt; Scripts waren, nur dass 
diese anfangs wieder durch diverse Virenfilter durchrutschten.&lt;/p&gt;

&lt;p&gt;Letztendlich waren &lt;code&gt;.hta&lt;/code&gt; bald als genau so “böse” abgestempelt wie Active-X.
Und mit dem Ende des Internet-Explorers verschwand diese Technologie genau so
schnell, wie sie eingeführt wurde, da bereits ab dem IE 9 die Ausführung nur
noch sehr eingeschränkt möglich war und mit 100en Viren-Warnungen zugeklebt
wurde.&lt;/p&gt;

&lt;h3 id=&quot;htas-in-windows-pe&quot;&gt;HTAs in Windows PE&lt;/h3&gt;

&lt;p&gt;Interessant ist, dass Windows PE bis heute mit einem HTA-Modul ausgeliefert 
wird. Integriert man dieses in sein Win-PE Image, können HTAs direkt 
ausgeführt werden. Und in dieser Umgebung fehlen dann all die 
Sicherheitswarnungen, die im regulären Windows beim Start einer &lt;code&gt;.hta&lt;/code&gt; 
auftreten würden.&lt;/p&gt;

&lt;p&gt;Inspiriert von dieser Vorlage, entschied ich mich 2011 dafür, ein
&lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_Embedded_7&quot;&gt;Windows Embedded 7&lt;/a&gt; Setup 
auf einer HTA aufzubauen.&lt;br /&gt;
Es sollte den Benutzer durch ein paar Menüs führen, wo er zwischen 
installierbaren Windows Images und Updates auswählen konnte.&lt;br /&gt;
Im Hintergrund wurden dann einfach &lt;code&gt;diskpart&lt;/code&gt; und &lt;code&gt;imagex&lt;/code&gt; ausgeführt um die
gewünschten Optionen auf die Festplatte zu übertragen.&lt;/p&gt;

&lt;p&gt;Bis heute bin ich auf diese Lösung ein bisschen stolz, weil ich in wenigen
Stunden ein grafisch anschaubares “Setup” für Endkunden bauen konnte, ohne
gleich zu schweren Waffen wie &lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B&quot;&gt;C++&lt;/a&gt; 
greifen zu müssen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Falco meinte ja einmal:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;In Wien mußt’ erst sterben, damit sie dich hochleben lassen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;… und zumindest in meiner kleinen Wiener Wohnung bleibe ich dem Motto nun
treu und ernenne HTAs posthum zu einer bemerkenswerten Technik.&lt;/p&gt;

&lt;p&gt;Ich frage mich, ob diese Software weiter verbreitet worden wäre, hätte sie
nicht der Microsoft Konzern eingeführt, der (nicht ganz zu Unrecht) seit
dem Jahr 2000 in der Kritik stand und daher aus Prinzip abgelehnt wurde.&lt;br /&gt;
Tatsächlich waren HTAs schon in Windows 98 im IE5 integriert und waren damit
10 Jahre vor Google, Chromebooks und iPhones in der Lage, “produktive Apps”
mit HTML zu erstellen.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Fremden HTAs würde ich natürlich auch nicht vertrauen …&lt;br /&gt;
Aber meine eigenen liebe ich (fast) genau so, wie meine anderen C++ Kinder.&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>Atom D2550/D2700</title>
   <link href="https://www.opengate.at/blog/2022/07/atom-d2000/"/>
   <published>2022-07-31T13:00:00+02:00</published>
   <updated>2022-07-31T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2022/07/atom-d2000</id>
   <category term="hardware" />
   <summary type="text">Als nach der Pineview Serie (ich nutzte zuvor einen D510) die Cedarview Serie
von Intel Atom Boards in den Handel
kam, kaufte ich mir die Modelle D2550 und D2700 als Test-Client und 
als meinen neuen Home-Server.

Leider sind diese Modelle bis heute ein Lehrbeispiel dafür, wie man ein
System nicht gestalten sollte.
(Aber das passt ja perfekt zu mir: Nämlich mit schlechten Systemen zu arbeiten.)
</summary>
   <content type="html">&lt;p&gt;Als nach der Pineview Serie (ich nutzte zuvor einen D510) die Cedarview Serie
von &lt;a href=&quot;https://de.wikipedia.org/wiki/Intel_Atom&quot;&gt;Intel Atom&lt;/a&gt; Boards in den Handel
kam, kaufte ich mir die Modelle &lt;code&gt;D2550&lt;/code&gt; und &lt;code&gt;D2700&lt;/code&gt; als Test-Client und 
als meinen neuen Home-Server.&lt;/p&gt;

&lt;p&gt;Leider sind diese Modelle bis heute ein Lehrbeispiel dafür, wie man ein
System nicht gestalten sollte.&lt;br /&gt;
(Aber das passt ja perfekt zu mir: Nämlich mit schlechten Systemen zu arbeiten.)
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Da baute Intel also vor 10 Jahren einen Nachfolger des Atom D510 (45nm, 13 
Watt TDP) mit der damals neueren 32nm-Fertigungstechnik und nur 10 Watt TDP.&lt;/p&gt;

&lt;p&gt;Und 3 Watt weniger Strom ist ja “ur-viel” und “super-geil”, also war der D2700
auch schon gekauft. Das Board hieß &lt;code&gt;D2700MUD&lt;/code&gt; und es muss wohl um das Jahr 
2013 gewesen sein.&lt;/p&gt;

&lt;h3 id=&quot;d2700-server-installation-n-mal&quot;&gt;D2700: Server Installation N-mal&lt;/h3&gt;

&lt;p&gt;Zuerst dachte ich, es ist so weit, ich steige von 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_Server_2003&quot;&gt;Server 2003&lt;/a&gt; 
auf 2008 (R2) um, primär um Hyper-V einzusetzen. Doch Fehlanzeige, denn 
der Prozessor besaß keinen 
&lt;a href=&quot;https://de.wikipedia.org/wiki/X86-Virtualisierung#Intel-Virtualisierungstechnologie_(VT-x)&quot;&gt;VT-x Support&lt;/a&gt; 
und ließ Hyper-V Dienste nicht hochstarten. Womit ich wieder zum Server 2003 mit 
&lt;a href=&quot;/blog/2022/07/virtual-server/&quot;&gt;Virtual Server 2005&lt;/a&gt; zurückkehrte.&lt;/p&gt;

&lt;p&gt;Die nächste Ernüchterung setzte bei mir erst nach der Server 2003 (x64) 
Installation ein, als ich einen passenden Grafik-Treiber einspielen wollte.&lt;br /&gt;
Der war auf der Webseite nicht vorhanden, sondern dort gab es nur einen
Windows 7 (32 bit) Treiber.&lt;/p&gt;

&lt;p&gt;Dann erst las ich die Doku und stellte fest, dass ich zwar einen 64-Bit 
Prozessor gekauft hatte, Intel aber nur Treiber für Windows 7 32-bit 
geschrieben hatte und keinen weiteren Plattform-Support anbot.&lt;br /&gt;
Das Teil heißt: “Intel(R) Graphics Media Accelerator 3600 Series”
und hat folgende Hardware ID: &lt;code&gt;PCI\VEN_8086&amp;amp;DEV_0BE2&amp;amp;SUBSYS_20148086&amp;amp;REV_09&lt;/code&gt;.&lt;br /&gt;
Siehe: https://www.intel.com/content/www/us/en/support/articles/000005823/graphics.html&lt;/p&gt;

&lt;p&gt;Man musste also entweder ein 32-Bit Windows 7 installieren oder man freundete 
sich mit dem Standard VGA-Treiber mit seinen 4:3 Formaten auf den 
16:9 Bildschirmen an.&lt;/p&gt;

&lt;h4 id=&quot;eigenes-treiber-inf-zusammenstellen&quot;&gt;Eigenes Treiber INF zusammenstellen&lt;/h4&gt;

&lt;p&gt;Ich ging den dritten Weg, installierte nochmal Windows 2003 aber diesmal mit 
32 Bit und lud dann von Intel einen eigenen Treiber-Baukasten herunter, mit 
dem man den 32-Bit Treiber für Windows XP/Server 2003 anpassen konnte.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/intel-emgd-01.png&quot; alt=&quot;Intel EMGD 1&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Das Paket heißt &lt;code&gt;IEMGD&lt;/code&gt; (Intel Embedded Media and Graphics Driver) for
&lt;code&gt;Intel Atom Processor N2000 and D2000 Series&lt;/code&gt;.&lt;br /&gt;
Hintergrund war vermutlich &lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_Embedded_2009&quot;&gt;Windows XP Embedded 2009&lt;/a&gt; 
und &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_CE&quot;&gt;Windows CE&lt;/a&gt;, welches 
damals noch häufiger auf Industrie-Terminals zu finden war.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/intel-emgd-02.png&quot; alt=&quot;Intel EMGD 2&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Zuerst musste man eine Konfiguration anlegen um die unterstützten Ports
(z.B.: &lt;a href=&quot;https://de.wikipedia.org/wiki/VGA-Anschluss&quot;&gt;VGA&lt;/a&gt; und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/High_Definition_Multimedia_Interface&quot;&gt;HDMI&lt;/a&gt;) 
einzubinden. Und danach war nur noch die Auswahl der Zielplattform zu treffen.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/intel-emgd-03.png&quot; alt=&quot;Intel EMGD 3&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Der Menüpunkt &lt;code&gt;Generate Installation&lt;/code&gt; kopiert alle notwendigen Treiberdateien
installationsbereit (samt INF Datei) zusammen.&lt;br /&gt;
Und das funktionierte tatsächlich recht gut, womit ich am Ende mit vollem
Grafik-Support unter Server 2003 arbeiten konnte.&lt;/p&gt;

&lt;h3 id=&quot;d2550-der-kleine-bruder&quot;&gt;D2550, der kleine Bruder&lt;/h3&gt;

&lt;p&gt;Irgendwie dachte ich mir, ich müsste auch noch ein “moderneres” Windows XP
besitzen und kaufte mir dann auch noch das Geschwister-Mainboard &lt;code&gt;D2550MUD2&lt;/code&gt; 
mit dem &lt;code&gt;D2550&lt;/code&gt; Atom Prozessor. Der ist ein paar hundert Megahertz langsamer 
als der &lt;code&gt;D2700&lt;/code&gt;, aber sonst identisch.&lt;/p&gt;

&lt;p&gt;Und natürlich gab es mit diesem Teil die gleichen Probleme mit der Grafik.&lt;/p&gt;

&lt;h4 id=&quot;crashgefahr-ab-windows-8&quot;&gt;Crashgefahr ab Windows 8&lt;/h4&gt;

&lt;p&gt;Für kleine Aufgaben (&lt;a href=&quot;https://de.wikipedia.org/wiki/Secure_Shell&quot;&gt;SSH&lt;/a&gt;, Mail, 
Webrequests, VPN) arbeitet das alte Atom Board bis heute bei mir, wenn ich 
meinen “Hauptrechner” nicht extra starten möchte.&lt;br /&gt;
Versuche auf &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_8&quot;&gt;Windows 8&lt;/a&gt; 
oder Windows 10 zu wechseln scheiterten aber an einem interessanten Detail: 
Die Grafik schmiert ab, sobald Windows Store Apps geladen werden.&lt;/p&gt;

&lt;p&gt;Ich vermute mal, dass die Direct-X Implementierung des Windows-7 Treibers 
fehlerhaft ist oder Windows 8 im Treiber nicht vorhandene Features benötigt.
Denn immer wenn eine Store-App im Vollbild geöffnet wird, ist ein Bluescreen
“vorprogrammiert”.&lt;/p&gt;

&lt;p&gt;Win32 Apps und Spiele funktionierten allerdings auch unter Windows 8 in meinen
Tests.&lt;br /&gt;
However … nachdem ich aber kein instabiles System haben wollte, wechselte
ich wieder zu Windows 7 und bin damit bis heute glücklich.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Die Atom D2000 Serie ist ein Beispiel dafür, wie man Prozessoren nicht 
vermarkten sollte. Denn alle Vorgänger und Nachfolger nutzten Intel-Grafikchips
für die unter Windows und Linux ausreichend Treiber und Knowhow zur Verfügung
stand.&lt;br /&gt;
64-bit wegen der Grafik auszuschließen ist für ein Produkt aus dem Jahr 2012 
unsinnig und kam auch bei der Community nicht gut an.&lt;/p&gt;

&lt;p&gt;Die Lösung wäre gewesen, den Sourcecode zu veröffentlichen, doch auch dazu 
ließ sich Intel trotz vieler Support-Anfragen nicht überreden.&lt;/p&gt;

&lt;p&gt;Naja … ich nutze meine beiden &lt;code&gt;D2550MUD2&lt;/code&gt; und &lt;code&gt;D2700MUD&lt;/code&gt; Boards jedenfalls
weiter mit Windows 7 für Kleinkram und Server 2003 mit Virtual Server.&lt;/p&gt;

&lt;p&gt;Echt Schade, dass man daraus nicht mehr machen kann … aber so ist das Leben
bzw. Intel manchmal.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Virtual Server 2005</title>
   <link href="https://www.opengate.at/blog/2022/07/virtual-server/"/>
   <published>2022-07-30T13:00:00+02:00</published>
   <updated>2022-07-30T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2022/07/virtual-server</id>
   <category term="software" />
   <summary type="text">Mit Server 2008 
stieg Microsoft “richtig” ins Virtualisierung-Geschäft ein und schuf das 
erste Windows mit eingebautem 
Hyper-Visor Kern.

Doch tatsächlich gab es Virtualisierung schon vorher aus dem Hause Microsoft.
Und obwohl diese Produkte gegenüber VM-Ware und andere Lösungen “abstanken”,
erinnere ich mich noch gerne an Zeiten von 
Virtual PC und 
“Virtual Server 2005” zurück.
</summary>
   <content type="html">&lt;p&gt;Mit &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_Server_2008&quot;&gt;Server 2008&lt;/a&gt; 
stieg Microsoft “richtig” ins Virtualisierung-Geschäft ein und schuf das 
erste Windows mit eingebautem 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Hyper-V&quot;&gt;Hyper-Visor Kern&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Doch tatsächlich gab es Virtualisierung schon vorher aus dem Hause Microsoft.
Und obwohl diese Produkte gegenüber VM-Ware und andere Lösungen “abstanken”,
erinnere ich mich noch gerne an Zeiten von 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Virtual_PC&quot;&gt;Virtual PC&lt;/a&gt; und 
“Virtual Server 2005” zurück.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Microsoft übernahm Anfang der 2000er eine Firma namens Connectix und formte 
deren Virtualisierungsprodukt in “Microsoft Virtual PC” um.
Damit wurde es möglich unter &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_XP&quot;&gt;Windows (2000 und XP)&lt;/a&gt; 
ein anderes Gastbetriebssystem in einer virtuellen Umgebung laufen zu lassen.&lt;/p&gt;

&lt;p&gt;Gedacht war das ganze für Entwickler und Software-Tests mit älteren 
Betriebssystemen und nachdem &lt;a href=&quot;https://de.wikipedia.org/wiki/X86-Virtualisierung#Intel-Virtualisierungstechnologie_(VT-x)&quot;&gt;Intel’s VT-x&lt;/a&gt; 
Befehlssatzerweiterung für Virtualisierung gerade im Entstehen war, und kein
damalig Consumer-Prozessor ihn anbot, wurde Virtualisierung auf 
Softwareebene durchgeführt.&lt;/p&gt;

&lt;p&gt;Das war zwar langsam, aber da die alten Windows XP und älteren MS 
Betriebssysteme auch verhältnismäßig klein waren und auch mit 256 MB RAM 
auskamen, konnte ich auf meinen damaligen Systemen mit 2 GB RAM auch noch
eine oder zwei VMs ausführen lassen um zu sehen, ob Programme auch noch
unter &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_NT_4.0&quot;&gt;NT-4&lt;/a&gt; 
oder Windows 98 lauffähig waren.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/ms-virtual-pc.png&quot; alt=&quot;Microsoft Virtual PC&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Großer Nachteil von “Virtual PC” war, dass es ein UI Programm war, das 
man manuell starten musste um danach die VMs ebenso manuell starten zu können.&lt;/p&gt;

&lt;p&gt;Doch für den professionellen Einsatz gab es dann die Server Variante, namens
“Virtual Server 2005”.&lt;/p&gt;

&lt;h3 id=&quot;virtual-server-2005-und-sein-web&quot;&gt;Virtual Server 2005 und sein “Web”&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/ms-virtual-server-01.png&quot; alt=&quot;Virtual-Server&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Dieses Produkt war eine Erweiterung von “Virtual PC” und lief als Dienst auf 
einem &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_Server_2003&quot;&gt;Windows Server 2003&lt;/a&gt; 
(32 und 64 bit).&lt;br /&gt;
Die Administration der Software erfolgte in erster Linie über eine 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Hypertext_Transfer_Protocol&quot;&gt;HTTP&lt;/a&gt;
Webseite im Browser … schlimmer noch … exklusiv nur im 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Internet_Explorer&quot;&gt;Internet-Explorer&lt;/a&gt;.&lt;br /&gt;
Jedenfalls brauchte man einen damaligen 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Internet_Information_Services&quot;&gt;IIS (Internet Information Server)&lt;/a&gt;
vorinstalliert und das Setup legte eine Konfiguration für den Standard-Port 
&lt;code&gt;1024&lt;/code&gt; an, wo die Admin-Seiten laufen sollten.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/ms-virtual-server-02.png&quot; alt=&quot;Virtual-Server&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Und die Fehlentscheidung “Internet-Explorer” ist vermutlich der Grund dafür,
dass ich damit einige schlechte Erfahrungen machte.&lt;br /&gt;
Denn vermutlich um Konkurrenz-Browser zu behindern setzte die Admin-Seite 
intensiv auf &lt;a href=&quot;https://de.wikipedia.org/wiki/JavaScript&quot;&gt;Javascript&lt;/a&gt; und 
dynamischen Content (eigentlich progressiv für damals), nutzte jedoch viele 
Internet-Explorer Erweiterungen, die keinem Standard entsprachen.&lt;/p&gt;

&lt;p&gt;Und so kam es, dass bereits wenige Jahre später mit dem &lt;code&gt;IE-7&lt;/code&gt; und &lt;code&gt;IE-8&lt;/code&gt; 
Teile der Admin-Seiten nicht mehr richtig funktionierten, wenn man nicht 
einzelne Features im Kompatibilitätsmodus ein/ausschaltete.&lt;br /&gt;
Und mit dem IE9 strich Microsoft dann auch noch viele Erweiterungen 
vollständig, womit die Serversoftware unbenutzbar wurde.&lt;br /&gt;
Andere Browser versagten von Anfang an den Javascript-Content anzuzeigen
und deshalb nenne ich den “Virtual Server 2005” immer als Beispiel für 
die schlechtest mögliche Representation eines Dienstes im Web.&lt;/p&gt;

&lt;p&gt;However … wenn man brav beim &lt;code&gt;IE-6&lt;/code&gt; bleibt, sieht das Web-Interface recht
“OK” aus. Man kann neue Maschinen anlegen und Einstellungen per Webformular
anpassen. Alles unter der Einstiegsseite:&lt;br /&gt;
&lt;code&gt;http://HOSTNAME_OR_IP:1024/VirtualServer/VSWebApp.exe&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/ms-virtual-server-03.png&quot; alt=&quot;Virtual-Server&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Läuft eine Maschine, kann man sich über ein &lt;a href=&quot;https://de.wikipedia.org/wiki/ActiveX&quot;&gt;Active-X&lt;/a&gt;
Plugin im Browser “hineinverbinden”.&lt;br /&gt;
Tastaturanschläge werden korrekt übermittelt, wenn das Remote-Frame im 
Browser den Fokus hat.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/ms-virtual-server-04.png&quot; alt=&quot;Virtual-Server&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Allerdings sollte man während der Installation nie in das Fenster klicken
und die Maus bewegen. Denn diese Übersetzung ist (im 
&lt;a href=&quot;https://de.wikipedia.org/wiki/MS-DOS&quot;&gt;DOS&lt;/a&gt;-Modus) gebrochen und kann eine 
Installation verhindern, wenn intern ein Fokus wegen der Maus verloren geht
und dieser dann nicht wiedergewonnen werden kann.&lt;br /&gt;
(Es kann natürlich auch sein, dass das nur die Steuerung über 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Remote_Desktop_Protocol&quot;&gt;RDP&lt;/a&gt; betrifft,
denn ich bin stets über RDP zur Maschine verbunden, in der Virtual Server
und der IE6 läuft.)&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/ms-virtual-server-05.png&quot; alt=&quot;Virtual-Server&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Am Ende aktiviert man dann das CD-Image der Virtual-Server Plugins und 
installiert Treiber für die “virtuelle Umgebung”.
Ab da kann man dann auch die Maus gefahrlos über das Active-X-Webfenster
nutzen. Oder man installiert gleich ein OS, das man per Netzwerk erreichen
und fernwarten kann, denn die virtuelle Netzwerkkarte macht es möglich.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/ms-virtual-server-06.png&quot; alt=&quot;Virtual-Server&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;com-interface&quot;&gt;COM Interface&lt;/h3&gt;

&lt;p&gt;Die vermeintliche Rettung aus dem Web Chaos war tatsächlich eine meist recht
unbekannte alternative COM Schnittstelle. 
Als Vorbereitung initialisiert man COM mit&lt;/p&gt;
&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;CoInitializeSecurity(&lt;span style=&quot;color:#069&quot;&gt;NULL&lt;/span&gt;, -&lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;, &lt;span style=&quot;color:#069&quot;&gt;NULL&lt;/span&gt;, &lt;span style=&quot;color:#069&quot;&gt;NULL&lt;/span&gt;, 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;                     RPC_C_AUTHN_LEVEL_PKT_PRIVACY, 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;                     RPC_C_IMP_LEVEL_IMPERSONATE, 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;                     &lt;span style=&quot;color:#069&quot;&gt;NULL&lt;/span&gt;, 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;                     EOAC_DYNAMIC_CLOAKING,  
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;                     &lt;span style=&quot;color:#069&quot;&gt;NULL&lt;/span&gt;);
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;und dann erzeugt man eine Instanz der COM Klasse &lt;code&gt;VMVirtualServer&lt;/code&gt; über die 
Class-ID &lt;code&gt;CLSID_VMVirtualServer&lt;/code&gt; (&lt;code&gt;DA3111BC-1BD7-4884-A535-8470D36028F7&lt;/code&gt;) 
und landet beim Interface &lt;code&gt;IVMVirtualServer&lt;/code&gt; (&lt;code&gt;D1E64C50-A25D-450f-BE0B-9CA5A354CFF4&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Die anderen Schnittstellen sind im Header&lt;br /&gt;
&lt;code&gt;C:\Program Files\Microsoft Virtual Server\Documentation\VSComInterfaces.h&lt;/code&gt;
enthalten.&lt;br /&gt;
Viele Methoden sind recht selbsterklärend (wie z.B. &lt;code&gt;CreateVirtualMachine&lt;/code&gt;), 
jedoch stellt die große Anzahl von Schnittstellen zu Unterobjekten eine 
Herausforderung dar.&lt;/p&gt;

&lt;p&gt;Vielleicht finde ich ja mal irgendwann Zeit alle Details ins GATE Framework
aufzunehmen, denn diese Schnittstelle ist (analog zu 
&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/adsi/active-directory-service-interfaces-adsi&quot;&gt;ADSI&lt;/a&gt;) 
sicher ein schönes Beispiel, wie man einen Dienst über eine Service-API 
zugänglich machen kann.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Der Nachfolger Hyper-V machte grundsätzlich vieles richtig. Er integrierte 
seine Verwaltung in &lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_Management_Instrumentation&quot;&gt;WMI&lt;/a&gt;, 
womit sie automatisch in WinRM und &lt;a href=&quot;https://de.wikipedia.org/wiki/PowerShell&quot;&gt;Powershell&lt;/a&gt; 
verfügbar war. Außerdem war der Hyper-Visor im Kern des Betriebssystems und 
damit gut integriert, während der Vorgänger nur einen Netzwerktreiber im
System einspeiste und der Rest im Dienstprozess errechnet wurde.&lt;/p&gt;

&lt;p&gt;Dennoch verdanke ich “Virtual PC” und “Virtual Server” so einiges.
Ich erarbeitete damit Softwarekompatibilität für ältere Windows NT, 2000 und
sogar Windows 98 Systeme, die bis 2010 eine “Kundenanforderung” waren.&lt;br /&gt;
Und auch privat erfreute ich mich daran, Windows 3.11 und DOS darauf halbwegs
vernünftig laufen lassen zu können.&lt;/p&gt;

&lt;p&gt;Hyper-V 2008 begann seinen Support erst mit Windows 2000 und war anfangs für 
meine Zwecke einfach “zu neu” und auch generell muss ich sagen, dass auf 
älteren Systemen diese Form die Virtualisierung einfach funktioniert, während
andere Dienste wie &lt;a href=&quot;https://de.wikipedia.org/wiki/VirtualBox&quot;&gt;VirtualBox&lt;/a&gt; 
wesentlich mehr Ressourcen fressen und damit auf meinen älteren Systemen 
unbenutzbar werden.&lt;/p&gt;

&lt;p&gt;Und so läuft seit langem auf einem meiner älteren 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Intel_Atom&quot;&gt;Intel Atom&lt;/a&gt; Rechner immer noch ein 
Server 2003 mit “Virtual Server” bei mir zu Hause …&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;… und wenn der nicht gestorben ist, dann läuft er noch heute.&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>DOS API Aufrufe</title>
   <link href="https://www.opengate.at/blog/2022/07/dos-call/"/>
   <published>2022-07-24T13:00:00+02:00</published>
   <updated>2022-07-24T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2022/07/dos-call</id>
   <category term="devel" /><category term="retro" />
   <summary type="text">Heute bringen die meisten Programmiersprachen “alles” mit, was notwendig ist
um alle möglichen Formen von Programmen, UIs und Spielen zu bauen.
Doch zu DOS Zeiten, war man auf die 
C Standardbibliothek 
und einfache Text Ein- und Ausgaben beschränkt.

Den Spielraum konnte man sich mit direkten Aufrufen von Interrupt 
Service-Routinen erweitern, darunter vor allem der int 21h mit allen 
DOS Funktionen.
</summary>
   <content type="html">&lt;p&gt;Heute bringen die meisten Programmiersprachen “alles” mit, was notwendig ist
um alle möglichen Formen von Programmen, UIs und Spielen zu bauen.
Doch zu &lt;a href=&quot;https://de.wikipedia.org/wiki/MS-DOS&quot;&gt;DOS&lt;/a&gt; Zeiten, war man auf die 
&lt;a href=&quot;https://de.wikipedia.org/wiki/C-Standard-Bibliothek&quot;&gt;C Standardbibliothek&lt;/a&gt; 
und einfache Text Ein- und Ausgaben beschränkt.&lt;/p&gt;

&lt;p&gt;Den Spielraum konnte man sich mit direkten Aufrufen von Interrupt 
Service-Routinen erweitern, darunter vor allem der &lt;code&gt;int 21h&lt;/code&gt; mit allen 
DOS Funktionen.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Leider war das alles andere als “standardisiert” und trotzdem verfolgten die
Sprachen ähnlichen Ansätze.&lt;/p&gt;

&lt;h3 id=&quot;integration-von-inline-assembler&quot;&gt;Integration von Inline-Assembler&lt;/h3&gt;

&lt;p&gt;C und &lt;a href=&quot;https://de.wikipedia.org/wiki/Pascal_(Programmiersprache)&quot;&gt;Pascal&lt;/a&gt; 
Compiler erlaubten im normalen Programmfluss 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Assemblersprache&quot;&gt;Assembler&lt;/a&gt; Codes 
einzuschleusen. Man öffnete einen &lt;code&gt;asm&lt;/code&gt; Block und schrieb dort die Intel 
Syntax der X86 Anweisungen, oder sogar direkt den Bytecode des Prozessors.&lt;/p&gt;

&lt;p&gt;Doch diese Non-Standard Erweiterung änderte sich stets und vor allem die 
Interaktion zwischen Variablen und Konstanten der eigentlichen Sprache 
war unterschiedlich. Ich weiß bis heute nicht auswendig, wo man nun Variablen
in eckige Klammen setzen muss und wo nicht, oder ob Stack-Variablen und 
globale anders behandelt werden mussten.&lt;/p&gt;

&lt;p&gt;Und wenn dann noch &lt;a href=&quot;https://de.wikipedia.org/wiki/Turbo_C&quot;&gt;Turbo C&lt;/a&gt; den Code
an den externen Turbo Assembler auslagerte, war fraglich, ob der 
überhaupt installiert war.&lt;/p&gt;

&lt;h3 id=&quot;aufruf-von-interrupts-über-standard-funktionen&quot;&gt;Aufruf von Interrupts über Standard-Funktionen&lt;/h3&gt;

&lt;p&gt;Ein Alternative musste her, und diese war eine spezielle Funktion, die die
Assembler-Magie im Hintergrund durchführte. 
Man befüllte eine Struktur deren Member die CPU-Register abbildeten und
rief ebendiese Funktion auf, die DOS oder andere Interrupt nutzte und
das Ergebnis war ein neuer Satz an Register-Variablen in der zurückgegebenen
Struktur.&lt;/p&gt;

&lt;p&gt;In den nachfolgenden Beispielen nutze ich die DOS Funktion &lt;code&gt;ah=0x30&lt;/code&gt;, die 
die DOS-Version im Register &lt;code&gt;AX&lt;/code&gt; zurückgibt, und zwar &lt;code&gt;AL&lt;/code&gt; mit der Hauptversion
und &lt;code&gt;AH&lt;/code&gt; mit der Nebenversion:&lt;/p&gt;

&lt;h4 id=&quot;turbo-c-openwatcom&quot;&gt;Turbo C, OpenWatcom&lt;/h4&gt;

&lt;p&gt;Im &lt;code&gt;dos.h&lt;/code&gt; Header befindet sich die Funktion &lt;code&gt;intdos(in_regs, out_regs)&lt;/code&gt; 
um DOS Funktionen mit &lt;code&gt;union REGS&lt;/code&gt; Parametern aufzurufen.&lt;br /&gt;
Zusätzlich existiert noch &lt;code&gt;int86(int_nr, in_regs, out_regs)&lt;/code&gt; um jeden 
beliebigen Softwareinterrupt aufzurufen.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color:#B44;font-weight:bold&quot;&gt;&amp;lt;dos.h&amp;gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt; getDOSversion(&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt;* major, &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt;* minor)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;union&lt;/span&gt; REGS in_regs, out_regs;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;  in_regs.h.ah = &lt;span style=&quot;color:#02b&quot;&gt;0x30&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  in_regs.h.al = &lt;span style=&quot;color:#02b&quot;&gt;0x00&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;/*in_regs.x.ax = 0x3000;*/&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;  intdos(&amp;amp;in_regs, &amp;amp;out_regs);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  *major = (&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt;)out_regs.h.al;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;  *minor = (&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt;)out_regs.h.ah;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;}
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; main()
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; major, minor;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;  getDOSversion(&amp;amp;major, &amp;amp;minor);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;  printf(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;DOS v%d.%d&lt;/span&gt;&lt;span style=&quot;color:#b0b&quot;&gt;\n&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, major, minor);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h4 id=&quot;turbo-pascal&quot;&gt;Turbo Pascal&lt;/h4&gt;

&lt;p&gt;Turbo Pascal stellte in seinem &lt;code&gt;DOS&lt;/code&gt; Modul die Funktion &lt;code&gt;MsDos(regs)&lt;/code&gt; für 
DOS Funktionen bereit und mit &lt;code&gt;Intr(intNo, regs)&lt;/code&gt; kann man jeden beliebigen
Interrupt nutzen. Hier gibt es nur einen Registers-Parameter, der gleichzeitig
Input ist und danach zum Output wird.&lt;/p&gt;

&lt;div class=&quot;language-pascal highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;PROGRAM&lt;/span&gt; dosver;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;USES&lt;/span&gt; dos;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;PROCEDURE&lt;/span&gt; getDOSversion(&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;var&lt;/span&gt; major: WORD; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;var&lt;/span&gt; minor: WORD);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;VAR&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;  regs: REGISTERS;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;BEGIN&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;  regs.ah := &lt;span style=&quot;color:#02b&quot;&gt;$30&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;  regs.al := &lt;span style=&quot;color:#02b&quot;&gt;$00&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;{regs.ax := $3000;}&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;  MsDos(regs);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;  major := regs.al;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;  minor := regs.ah;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;END&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;VAR&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;  maj, min: WORD;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;  text: &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;STRING&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;BEGIN&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  getDOSversion(maj, min);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n21&quot; name=&quot;n21&quot;&gt;21&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;write&lt;/span&gt;(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;DOS v&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n22&quot; name=&quot;n22&quot;&gt;22&lt;/a&gt;&lt;/span&gt;  str(maj, text);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n23&quot; name=&quot;n23&quot;&gt;23&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;write&lt;/span&gt;(text);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n24&quot; name=&quot;n24&quot;&gt;24&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;write&lt;/span&gt;(&lt;span style=&quot;color:#D20&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n25&quot; name=&quot;n25&quot;&gt;25&lt;/a&gt;&lt;/span&gt;  str(min, text);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n26&quot; name=&quot;n26&quot;&gt;26&lt;/a&gt;&lt;/span&gt;  writeln(text);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n27&quot; name=&quot;n27&quot;&gt;27&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;END&lt;/span&gt;.
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h4 id=&quot;quickbasic-dos-interrupt-aufruf&quot;&gt;QuickBasic DOS Interrupt Aufruf&lt;/h4&gt;

&lt;p&gt;Startet man QuickBasic (4.5+) mit &lt;code&gt;QB.EXE /L&lt;/code&gt;, stehen Zusatzbibliotheken zur 
Verfügung, die man über das Metakommando&lt;br /&gt;
&lt;code&gt;REM $INCLUDE: &apos;file&apos;&lt;/code&gt; einbinden kann.&lt;br /&gt;
Und &lt;code&gt;QB.BI&lt;/code&gt; definiert die Funktion &lt;code&gt;INTERRUPT&lt;/code&gt; und den &lt;code&gt;RegType&lt;/code&gt; Typ, der
Registerzustände an die Funktion leiten soll, die wiederum einen 
Softwareinterrupt damit aufruft. So kann man jeden Interrupt aufrufen,
und natürlich auch &lt;code&gt;21h&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-qbasic highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;REM $INCLUDE: &apos;QB.BI&apos;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;DECLARE SUB getDOSversion (major AS INTEGER, minor AS INTEGER)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;DIM major AS INTEGER
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;DIM minor AS INTEGER
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;getDOSversion major, minor
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;PRINT &amp;quot;DOS v&amp;quot;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;PRINT USING &amp;quot;#&amp;quot;; major;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;PRINT &amp;quot;.&amp;quot;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;PRINT USING &amp;quot;#&amp;quot;; minor
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;SUB getDOSversion (major AS INTEGER, minor AS INTEGER)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;  DIM inreg AS RegType
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;  DIM outreg AS RegType
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;  inreg.ax = &amp;amp;H3000
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;  CALL INTERRUPT(&amp;amp;H21, inreg, outreg)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;  major = outreg.ax AND &amp;amp;HFF
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  minor = CINT(outreg.ax / 256)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n21&quot; name=&quot;n21&quot;&gt;21&lt;/a&gt;&lt;/span&gt;END SUB
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Der mit DOS mitgelieferte &lt;code&gt;QBASIC.EXE&lt;/code&gt; Interpreter unterstützt 
&lt;code&gt;CALL INTERRUPT&lt;/code&gt; nicht. Theoretisch gäbe es aber die Möglichkeit
mit &lt;code&gt;POKE&lt;/code&gt; Assembler-Bytes in den Speicher zu schreiben und dann per&lt;br /&gt;
&lt;code&gt;CALL ABSOLUTE&lt;/code&gt; die Funktion aufzurufen … aber soviel DOS-Hackerei
tut sich heute keiner mehr an.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Der große Nachteil dieser direkten Interrupt-Aufrufe liegt in der 
Unmöglichkeit der Portierbarkeit. Denn die Register sehen ja auf jeder 
CPU anders aus.&lt;br /&gt;
Definierte APIs sind die Lösung und davon haben wir heute nur 2
große Vertreter: die &lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_Application_Programming_Interface&quot;&gt;WinAPI&lt;/a&gt;
und &lt;a href=&quot;https://de.wikipedia.org/wiki/Portable_Operating_System_Interface&quot;&gt;POSIX&lt;/a&gt; 
parallel zur C-stdlib.&lt;/p&gt;

&lt;p&gt;Tja, deshalb brauche ich eine Zeitmaschine, um mein heutiges Wissen 25 Jahre 
in die Vergangenheit zu senden. Denn oft habe ich mühsam ganze Programme in
Assembler verfasst, nur weil ich ein paar Interrupt bzw. DOS Funktionen
aufrufen wollte. Dass man das auch einfacher tun kann, lernte ich erst,
als ich DOS nicht mehr wirklich brauchte und auch nicht mehr damit
programmierte.&lt;/p&gt;

&lt;p&gt;Aber … Wissen schadet nicht.&lt;br /&gt;
Im Gegenteil, es ist interessant zu sehen, wie sehr sich die 3 
“Hauptsprachen” C, Pascal und Basic ähneln was Interrupts unter DOS anbelangt.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Toshiba T300 - Teil 2</title>
   <link href="https://www.opengate.at/blog/2022/07/t300-again/"/>
   <published>2022-07-23T13:00:00+02:00</published>
   <updated>2022-07-23T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2022/07/t300-again</id>
   <category term="hardware" /><category term="software" /><category term="retro" />
   <summary type="text">Und wieder einmal musste ich mich davon überzeugen, dass mein 
Toshiba T-300 noch läuft.

Diesmal sah ich meine alten Disketten durch, ob ich vielleicht noch ein 
paar Infos über das Gerät aus dem Jahr 82/83 erhalten kann.
</summary>
   <content type="html">&lt;p&gt;Und wieder einmal musste ich mich davon überzeugen, dass mein 
&lt;a href=&quot;/blog/2019/09/toshiba-t300/&quot;&gt;Toshiba T-300&lt;/a&gt; noch läuft.&lt;/p&gt;

&lt;p&gt;Diesmal sah ich meine alten Disketten durch, ob ich vielleicht noch ein 
paar Infos über das Gerät aus dem Jahr 82/83 erhalten kann.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;der-boot-vorgang&quot;&gt;Der Boot Vorgang&lt;/h3&gt;

&lt;p&gt;Im &lt;a href=&quot;https://de.wikipedia.org/wiki/Per_Anhalter_durch_die_Galaxis&quot;&gt;Hitchhiker’s guide to the galaxy&lt;/a&gt;
steht bekanntlich das beruhigende&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Don’t panic&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;an erster Stelle.&lt;br /&gt;
Und irgendwie wurde ich daran erinnert, als ich das Gerät wieder einschaltete
und am Bildschirm sofort die Worte&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;WAIT A MINUTE&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;erschienen.&lt;br /&gt;
Schließlich braucht die Maschine (in Wahrheit nur 20 Sekunden) um warm zu
laufen und ein komplexes &lt;a href=&quot;https://de.wikipedia.org/wiki/BIOS&quot;&gt;BIOS&lt;/a&gt; mit 
RAM-Tests und vielen anderen Infos gab es damals nicht.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/toshiba-t300-start01.jpg&quot; alt=&quot;Toshiba-T300-Start-1&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Danach schaltet sich das 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Diskettenlaufwerk&quot;&gt;Diskettenlaufwerk&lt;/a&gt;
ein und versuchte von Laufwerk A zu booten, was ebenso mit&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;PROGRAM LOADING&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;kommentiert wird.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/toshiba-t300-start02.jpg&quot; alt=&quot;Toshiba-T300-Start-2&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Nach weiteren 10 bis 15 Sekunden, sieht man bereits, wie 
&lt;a href=&quot;https://de.wikipedia.org/wiki/MS-DOS#MS-DOS_2.x_und_h%C3%B6her&quot;&gt;MS-DOS 2.0&lt;/a&gt; 
seinen &lt;code&gt;COMAMD.COM&lt;/code&gt; Prozess startet und danach &lt;code&gt;CONFIG.SYS&lt;/code&gt; und 
&lt;code&gt;AUTOEXEC.BAT&lt;/code&gt; abarbeitet.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;TOSHIBA Personal Computer (UO200)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;MS-DOS version 2.00
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;Copyright 1981,82,83 Microsoft Corp.
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/toshiba-t300-start03.jpg&quot; alt=&quot;Toshiba-T300-Start-3&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;diskettenformat&quot;&gt;Diskettenformat&lt;/h3&gt;

&lt;p&gt;Ich erwähnte bereits, dass der T300 ein nicht IBM-konformes 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Diskette&quot;&gt;Diskettenformat&lt;/a&gt; einsetzt und 
wesentlich mehr Daten auf den alten 5.25 Zoll Floppies unterbringt.&lt;/p&gt;

&lt;p&gt;Mit dem &lt;code&gt;FORMAT B:&lt;/code&gt; Aufruf, konnte ich das jetzt nochmal nachstellen.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;A:\&amp;gt;format b:
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;Insert new diskette for drive B:
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;and strike any key when ready
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;Formating ... Track No.(79) Head No.(1)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;Format complete (2DD type)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;Volume label (11 characters, ENTER for none)?
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;  649216 bytes total disk space
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;  649216 bytes available on disk
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;Format another (Y/N)?
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Eine übliche IBM &lt;code&gt;2D&lt;/code&gt; (Double density) wird in der Regel mit 
40 Tracks (Spuren) und 9 Sektoren auf zwei Seiten zu je 512 Bytes formatiert.&lt;br /&gt;
Daraus ergeben sich dann &lt;code&gt;368 640&lt;/code&gt; Bytes, also &lt;code&gt;360 KB&lt;/code&gt;.&lt;br /&gt;
Es gab aber auch eine ältere Formatierung mit nur 8 Sektoren, die sich in 
neueren DOS-Version mit &lt;code&gt;format /8&lt;/code&gt; erreichen ließt, die dann auf 
&lt;code&gt;327 680&lt;/code&gt; Bytes, also &lt;code&gt;320 KB&lt;/code&gt; kam.&lt;/p&gt;

&lt;p&gt;Und offenbar verdoppelte Toshiba einfach die 40 auf 80 Tracks und blieb bei
den 8 Sektoren um auf 655360 Bytes oder &lt;code&gt;640 KB&lt;/code&gt; zu kommen.&lt;br /&gt;
Zieht man davon &lt;code&gt;6 KB&lt;/code&gt; für Bootsektor und FAT-Infrastruktur ab, kommt man 
nämlich genau zu den &lt;code&gt;649216&lt;/code&gt; Bytes oder &lt;code&gt;634 KB&lt;/code&gt;, die &lt;code&gt;FORMAT.COM&lt;/code&gt; am Ende 
für Nutzdaten meldet.&lt;/p&gt;

&lt;p&gt;Eine so formatierte Diskette konnte mein “normales” 5.25 Zoll Laufwerk unter
Windows nicht mehr lesen und beschwerte sich, dass “Spur Null” nicht gefunden
werden kann.&lt;br /&gt;
Das ist deshalb bemerkenswert, weil das gleiche Laufwerk die moderneren HD
(High-Density) Disketten mit 1.2 MB problemlos lesen und formatieren kann,
wobei die mit 80 Tracks und 15 Sektoren formatiert sind.&lt;/p&gt;

&lt;p&gt;Doch wenn man unter Windows eine Diskette mit 360 KB formatiert
(heute &lt;code&gt;FORMAT A: /T:40 /N:9&lt;/code&gt;, früher unter DOS &lt;code&gt;FORMAT A: /F:360&lt;/code&gt;), dann kann
sie vom Toshiba T300 problemlos gelesen und beschrieben werden.&lt;/p&gt;

&lt;p&gt;Die Toshiba Formatierung mit &lt;code&gt;FORMAT B: /2&lt;/code&gt; erzeugt wiederum eine 320 KB
Speicherdichte und meldet dann am Ende: &lt;code&gt;Format complete (2D type)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;2D&lt;/code&gt; ist also das IBM kompatible Format und &lt;code&gt;2DD&lt;/code&gt; Toshibas Verdoppelung.&lt;/p&gt;

&lt;h3 id=&quot;system-kopieren&quot;&gt;System Kopieren&lt;/h3&gt;

&lt;p&gt;Das wirklich nervige ist, dass &lt;code&gt;FORMAT /S&lt;/code&gt; zum Kopieren des Betriebssystems
nur Toshiba-formatierte Disketten zuließ. Die weiß noch von früheren Tests,
dass das an Toshiba angepasste MS-DOS die versteckten Systemdateien
&lt;code&gt;TBIOS.SYS&lt;/code&gt; und &lt;code&gt;TDOS.SYS&lt;/code&gt; für den Boot anlegt.&lt;br /&gt;
Doch da in DOS 2.0 weder &lt;code&gt;DIR /AS&lt;/code&gt; existiert noch &lt;code&gt;COPY&lt;/code&gt; mit Systemdateien
umgehen kann, sind diese Dateien für mich leider unerreichbar.&lt;/p&gt;

&lt;p&gt;Alle anderen Programme inklusive &lt;code&gt;COMMAND.COM&lt;/code&gt; konnte ich auf 360 KB Disketten
kopieren und am PC archivieren, doch leider nicht den DOS-Kern selbst. 
Und leider verfüge ich auch gar nicht über ein vollständiges DOS für das Gerät.
Meine Disketten waren nur ausgestattet mit:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;COMP.COM&lt;/code&gt; zum Dateien vergleichen&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;DEBUG.COM&lt;/code&gt; der klassische DOS x86-ASM Debugger&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;DISKCOPY.COM&lt;/code&gt; Disketten kopieren Byte für Byte&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;EDLIN.COM&lt;/code&gt; Ein Zeileneditor für Texte&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;FDISK.COM&lt;/code&gt; für eine Festplatte, die nicht eingebaut war&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;FORMAT.COM&lt;/code&gt; zum Formatieren von Disketten&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;GRKBPRG.COM&lt;/code&gt; der deutsche Tastaturtreiber&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;LABEL.COM&lt;/code&gt; benennt eine Diskette um&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;LOGO.COM&lt;/code&gt; die Programmiersprache &lt;a href=&quot;https://de.wikipedia.org/wiki/Logo_(Programmiersprache)&quot;&gt;Logo&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;MODE.COM&lt;/code&gt; verändert Parameter der Ein/Ausgabe&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;MORE.COM&lt;/code&gt; zeigt Ausgaben seitenweise an&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;PRINT.COM&lt;/code&gt; druckt im Hintergrund&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;RECOVER.COM&lt;/code&gt; versucht ein defektes Dateisystem wiederherzustellen&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;RST.COM&lt;/code&gt; startet die Maschine neu&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;TBASIC.COM&lt;/code&gt; Toshiba Basic, ein GW-BASIC Klon&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Andere Tools wie &lt;code&gt;ATTRIB&lt;/code&gt; oder &lt;code&gt;SYS&lt;/code&gt; fehlten. Ich selbst hatte vor 25 Jahren
mal ein &lt;code&gt;SYS.COM&lt;/code&gt; von DOS 3 auf eine der Disketten kopiert, nur um dort
beobachten zu können, dass es nicht funktionierte und das System einfrieren 
ließ.&lt;/p&gt;

&lt;p&gt;Ich vermute aber, dass ich mit Programmiersprachen wie 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Turbo_Pascal&quot;&gt;Turbo Pascal&lt;/a&gt; 3 ein Tool
wie &lt;code&gt;ATTRIB&lt;/code&gt; recht leicht nachbauen können sollte, denn die DOS &lt;code&gt;INT 21h&lt;/code&gt; 
Funktion &lt;code&gt;AH=43h&lt;/code&gt; kann mit &lt;code&gt;AL=01h&lt;/code&gt; Attribute ändern, und ich vermute,
wenn &lt;code&gt;TBIOS.SYS&lt;/code&gt; und &lt;code&gt;TDOS.SYS&lt;/code&gt; zu normalen Dateien werden, dann kann &lt;code&gt;COPY&lt;/code&gt;
sie auch kopieren.&lt;/p&gt;

&lt;p&gt;Und irgendwie glaube ich, dass es Taktik von Microsoft und/oder Toshiba war,
dass man das Betriebssystem nur auf Disketten mit dem eigenen Datenformat
übertragen konnte.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Leider habe ich damals keine weitere Toshiba-Software gerettet und das bereue 
ich. Denn somit ist womöglich wieder ein Stück IT-Geschichte verloren 
gegangen.&lt;/p&gt;

&lt;p&gt;Reine DOS-2-Software läuft vermutlich auf dem Gerät, doch viele Programme 
nutzten direkte Hardwarezugriffe oder neuere DOS-Versionen und sind somit 
nicht mit dem T-300 kompatibel.&lt;/p&gt;

&lt;p&gt;Ich frage mich, ob es noch andere Besitzer eines solchen Gerätes gibt, und ob
diese weitere Software dafür besitzen.&lt;/p&gt;

&lt;p&gt;Sollte es mir doch noch gelingen, die gesamte Diskette zu “sichern”, plane 
ich, sie auf &lt;code&gt;archive.org&lt;/code&gt; zu stellen … doch zur Zeit macht das wenig Sinn.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Variant in C++ 98/03</title>
   <link href="https://www.opengate.at/blog/2022/07/variant/"/>
   <published>2022-07-17T13:00:00+02:00</published>
   <updated>2022-07-17T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2022/07/variant</id>
   <category term="devel" />
   <summary type="text">Mit std::variant 
aus C++17 
hat die standardbibliothek 
boost::variant
integriert. Das Template ist mit C union Typen verwandt, bietet jedoch
Typensicherheit und Eindeutigkeit.

Ich bin bekanntlich auf die alten Standards C++98 und C++03 fixiert und 
fragte mich daher, wie schwer es wohl sei, so etwas “quick &amp;amp; dirty” auch
dort nachbauen zu können.
</summary>
   <content type="html">&lt;p&gt;Mit &lt;a href=&quot;http://en.cppreference.com/w/cpp/utility/variant&quot;&gt;&lt;code&gt;std::variant&lt;/code&gt;&lt;/a&gt; 
aus &lt;a href=&quot;https://en.wikipedia.org/wiki/C%2B%2B17&quot;&gt;C++17&lt;/a&gt; 
hat die &lt;code&gt;st&lt;/code&gt;an&lt;code&gt;d&lt;/code&gt;ardbibliothek 
&lt;a href=&quot;https://www.boost.org/doc/libs/1_61_0/doc/html/variant.html&quot;&gt;&lt;code&gt;boost::variant&lt;/code&gt;&lt;/a&gt;
integriert. Das Template ist mit C &lt;code&gt;union&lt;/code&gt; Typen verwandt, bietet jedoch
Typensicherheit und Eindeutigkeit.&lt;/p&gt;

&lt;p&gt;Ich bin bekanntlich auf die alten Standards C++98 und C++03 fixiert und 
fragte mich daher, wie schwer es wohl sei, so etwas “quick &amp;amp; dirty” auch
dort nachbauen zu können.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Mit C++11 kamen “variadic Templates” in den Standard womit man beliebig viele
Typen an ein Template weiterreichen kann. Und diese kann man dann mit anderen
Hilfstemplates durchlaufen und sich genau das daraus bauen, was man haben
will.&lt;/p&gt;

&lt;p&gt;Doch im originalen C++98 bzw. im Update 2003 gibt es dieses Feature nicht.&lt;/p&gt;

&lt;h3 id=&quot;idee&quot;&gt;Idee&lt;/h3&gt;

&lt;p&gt;“Default template arguments” geben uns die Möglichkeit, ein Template mit
Typen zu füttern, doch wenn wir weniger nutzen, werden die hinten fehlenden
Argumente durch “defaults” ersetzt.&lt;/p&gt;

&lt;p&gt;Meine Idee ist es daher ein &lt;code&gt;Variant&lt;/code&gt; Template mit vielen Typen zu erstellen
(10 sollten für die meisten Fälle ausreichen), wo jedoch ab dem zweiten ein 
Default-Typ gesetzt wird, der das Template Argument quasi als “ungültig” 
markiert.&lt;br /&gt;
Damit die “ungültigen” Argumente auch eindeutig identifiziert bzw. gezählt
werden können, kann dieser &lt;code&gt;InvalidType&lt;/code&gt; selbst ein Template sein, dessen
Argument eine Zahl ist:&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;template&lt;/span&gt;&amp;lt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;unsigned&lt;/span&gt; N&amp;gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;struct&lt;/span&gt; InvalidType { };
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;template&lt;/span&gt;&amp;lt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;T0&lt;/span&gt;, 
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;         &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;T1&lt;/span&gt; = InvalidType&amp;lt;&lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;&amp;gt;,
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;         &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;T2&lt;/span&gt; = InvalidType&amp;lt;&lt;span style=&quot;color:#00D&quot;&gt;2&lt;/span&gt;&amp;gt;,
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;         &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;T3&lt;/span&gt; = InvalidType&amp;lt;&lt;span style=&quot;color:#00D&quot;&gt;3&lt;/span&gt;&amp;gt;,
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;         &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;T4&lt;/span&gt; = InvalidType&amp;lt;&lt;span style=&quot;color:#00D&quot;&gt;4&lt;/span&gt;&amp;gt;,
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;         &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;T5&lt;/span&gt; = InvalidType&amp;lt;&lt;span style=&quot;color:#00D&quot;&gt;5&lt;/span&gt;&amp;gt;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;         &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;T6&lt;/span&gt; = InvalidType&amp;lt;&lt;span style=&quot;color:#00D&quot;&gt;6&lt;/span&gt;&amp;gt;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;         &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;T7&lt;/span&gt; = InvalidType&amp;lt;&lt;span style=&quot;color:#00D&quot;&gt;7&lt;/span&gt;&amp;gt;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;         &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;T8&lt;/span&gt; = InvalidType&amp;lt;&lt;span style=&quot;color:#00D&quot;&gt;8&lt;/span&gt;&amp;gt;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;         &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;T9&lt;/span&gt; = InvalidType&amp;lt;&lt;span style=&quot;color:#00D&quot;&gt;9&lt;/span&gt;&amp;gt;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;  &amp;gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;Variant&lt;/span&gt; { };
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Im Inneren reservieren wir Speicherplatz für alle möglichen Typen mit:&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;union&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt;  t0[&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;sizeof&lt;/span&gt;(T0)];
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt;  t1[&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;sizeof&lt;/span&gt;(T1)];
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt;  t2[&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;sizeof&lt;/span&gt;(T2)];
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt;  t3[&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;sizeof&lt;/span&gt;(T3)];
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt;  t4[&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;sizeof&lt;/span&gt;(T4)];
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt;  t5[&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;sizeof&lt;/span&gt;(T5)];
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt;  t6[&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;sizeof&lt;/span&gt;(T6)];
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt;  t7[&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;sizeof&lt;/span&gt;(T7)];
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt;  t8[&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;sizeof&lt;/span&gt;(T8)];
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt;  t9[&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;sizeof&lt;/span&gt;(T9)];
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;* alignment_dummy;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;} content;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Jetzt kann man mit &lt;code&gt;new (&amp;amp;content) Tx(source)&lt;/code&gt; bereits Objekte auf den
&lt;code&gt;content&lt;/code&gt; Speicher erzeugen … aber wie soll der Destruktor nun das
richtige Objekt freigeben?&lt;/p&gt;

&lt;p&gt;Im GATE Framework nutze ich für die C++-C Brücken C-Konstruktor und 
C-Destruktor Funktionen, die von C++ Templates generiert werden.&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;typedef&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;(*generic_copy_constructor)(&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;* dst, &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt;* src);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;typedef&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;(*generic_destructor)(&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;* obj);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;template&lt;/span&gt;&amp;lt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;T&lt;/span&gt;&amp;gt; 
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt; cpp_copy_construct(&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;* dst, &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt;* src)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  T* cpp_dst = &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;reinterpret_cast&lt;/span&gt;&amp;lt;T*&amp;gt;(dst);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;  T &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt;* cpp_src = &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;reinterpret_cast&lt;/span&gt;&amp;lt;T &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt;*&amp;gt;(src);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;new&lt;/span&gt; (cpp_dst) T(*cpp_src);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;}
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;template&lt;/span&gt;&amp;lt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;T&lt;/span&gt;&amp;gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt; cpp_destruct(&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;* obj)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;  T* cpp_obj = &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;reinterpret_cast&lt;/span&gt;&amp;lt;T*&amp;gt;(obj);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;  cpp_obj-&amp;gt;~T();
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Diese beiden Funktionszeiger kommen zusammen mit der &lt;code&gt;std::type_info&lt;/code&gt; 
ebenfalls in den Variant und beschreiben somit, welcher Type
gerade aktiv ist, und wie man ihn kopieren und zerstören kann:&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;... 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;Variant&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;private&lt;/span&gt;:
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  generic_copy_constructor content_cctor;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;  generic_destructor content_dtor;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  std::type_info &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt;* content_ti;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;};
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Jetzt baut man noch Konstruktoren und Assignment Operatoren für jeden
Template Typen ein, wie auch einen “getter”.&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;...
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;private&lt;/span&gt;:
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;template&lt;/span&gt;&amp;lt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;T&lt;/span&gt;&amp;gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt; insert(T &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt;&amp;amp; t)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  {
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;new&lt;/span&gt; (&amp;amp;content) T(t);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;    content_cctor = &amp;amp;generic_copy_constructor&amp;lt;T&amp;gt;;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;    content_dtor = &amp;amp;cpp_destruct;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;    content_ti = &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;typeid&lt;/span&gt;(T);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt; destruct()
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;  {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;    content_dtor(&amp;amp;content);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;  }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;public&lt;/span&gt;:
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;  Variant(T0 &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt;&amp;amp; t) { insert(t) }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;  Variant(T1 &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt;&amp;amp; t) { insert(t) }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;  ...
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;  Variant&amp;amp; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;operator&lt;/span&gt;=(T8 &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt;&amp;amp; t) { destruct(); insert(t); &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; *&lt;span style=&quot;color:#950&quot;&gt;this&lt;/span&gt;; }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  Variant&amp;amp; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;operator&lt;/span&gt;=(T9 &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt;&amp;amp; t) { destruct(); insert(t); &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; *&lt;span style=&quot;color:#950&quot;&gt;this&lt;/span&gt;; }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n21&quot; name=&quot;n21&quot;&gt;21&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n22&quot; name=&quot;n22&quot;&gt;22&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;template&lt;/span&gt;&amp;lt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;T&lt;/span&gt;&amp;gt; T&amp;amp; get()
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n23&quot; name=&quot;n23&quot;&gt;23&lt;/a&gt;&lt;/span&gt;  {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n24&quot; name=&quot;n24&quot;&gt;24&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt;(&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;typeid&lt;/span&gt;(T) != *content_ti)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n25&quot; name=&quot;n25&quot;&gt;25&lt;/a&gt;&lt;/span&gt;    {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n26&quot; name=&quot;n26&quot;&gt;26&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;throw&lt;/span&gt; std::runtime_error(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Invalid type&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n27&quot; name=&quot;n27&quot;&gt;27&lt;/a&gt;&lt;/span&gt;    }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n28&quot; name=&quot;n28&quot;&gt;28&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; *&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;reinterpret_cast&lt;/span&gt;&amp;lt;T*&amp;gt;(&amp;amp;content);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n29&quot; name=&quot;n29&quot;&gt;29&lt;/a&gt;&lt;/span&gt;  }
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Und fertig ist der C++98 Variant.
Das ganze Beispiel liegt auch im 
&lt;a href=&quot;https://codeberg.org/GateNetwork/gate-blog-classroom/src/branch/main/c_cpp/classic_variant/&quot;&gt;BLOG-Classroom&lt;/a&gt; 
vor.&lt;/p&gt;

&lt;p&gt;Natürlich kann man jetzt den Code noch weiter ausbauen und die echte
Konstruktion eines &lt;code&gt;InvalidType&lt;/code&gt; verhindern lassen, damit man ihn nicht 
(un)absichtlich deklarieren kann.&lt;br /&gt;
Und man kann sich auch noch den Typen-Index merken, mit dem der Variant
initialisiert wurde, um ihn (so wie bei &lt;code&gt;std::variant&lt;/code&gt;) zurückliefern
zu können.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Das Codebeispiel ist nicht so effizient, wie es durch C++11 möglich wird,
doch er tut so halbwegs das, was man von einem “Variant” erwartet.&lt;/p&gt;

&lt;p&gt;Ich selbst nutze &lt;code&gt;variant&lt;/code&gt; eher selten, doch kommt er mir in manch anderen
Projekten stets unter.&lt;/p&gt;

&lt;p&gt;Im GATE Projekt geht die ganze Sache natürlich noch einen Schritt weiter,
wo ein &lt;code&gt;gate_variant_t&lt;/code&gt; als C-Objekt genutzt wird, wo aber dennoch ein C++
Objekt dahinter verborgen sein kann. Dort hat man keine Templates und muss
sich quasi alle &lt;code&gt;typeid&lt;/code&gt;-Pointer mit den cctor/dtor Funktionen für jeden
erlaubten Typen merken.&lt;/p&gt;

&lt;p&gt;Und wieder gilt als erwiesen:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Wo ein Wille ist, da ist auch ein Weg.&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>Wikipedia</title>
   <link href="https://www.opengate.at/blog/2022/07/wikipedia/"/>
   <published>2022-07-16T13:00:00+02:00</published>
   <updated>2022-07-16T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2022/07/wikipedia</id>
   <category term="software" /><category term="projects" />
   <summary type="text">Wikipedia zählt zu den ganz wenigen Projekten im 
Netz, denen ich vertraue ohne Details über die internen Abläufe zu kennen. 
Ich glaube, dass es DAS Vorzeigeprojekte schlichthin ist, wie eine freie 
Gesellschaft im Internet produktiv arbeiten kann.

Und wenn sie jetzt noch eine “bessere” Markup-Syntax für ihre eigenen
Seiten hätten (z.B. Markdown), 
dann würde ich dort auch mehr beitragen.
</summary>
   <content type="html">&lt;p&gt;&lt;a href=&quot;http://de.wikipedia.org/&quot;&gt;Wikipedia&lt;/a&gt; zählt zu den ganz wenigen Projekten im 
Netz, denen ich vertraue ohne Details über die internen Abläufe zu kennen. 
Ich glaube, dass es DAS Vorzeigeprojekte schlichthin ist, wie eine freie 
Gesellschaft im Internet produktiv arbeiten kann.&lt;/p&gt;

&lt;p&gt;Und wenn sie jetzt noch eine “bessere” Markup-Syntax für ihre eigenen
Seiten hätten (z.B. &lt;a href=&quot;https://en.wikipedia.org/wiki/Markdown&quot;&gt;Markdown&lt;/a&gt;), 
dann würde ich dort auch mehr beitragen.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;vorgeschichte&quot;&gt;Vorgeschichte&lt;/h3&gt;

&lt;p&gt;Als ich den Blog startete, ging es mir primär um:&lt;br /&gt;
Dokumentation meiner Lebenserfahrung.&lt;/p&gt;

&lt;p&gt;Doch am Ende der Themenbeschreibungen dachte ich daran, was wohl passiert,
wenn ein interessierter Nutzer zufällig bei der Seite vorbeikommt, zu lesen
beginnt und schon nach wenigen Sekunden “aussteigt”, weil er mit einigen
Vokabeln nichts anfangen kann.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lösung:&lt;/strong&gt; Man verlinkt solche Wörter mit Seiten, die sie erklären.&lt;/p&gt;

&lt;p&gt;Wenn ich nun aber Herstellerseiten von Software verlinke, dann werden diese
Links alle paar Jahre ungültig, weil auf ein neues 
&lt;a href=&quot;https://en.wikipedia.org/wiki/Content_management_system&quot;&gt;CMS&lt;/a&gt; umgestellt wird, 
oder der Anbieter die Domäne wechselt oder diese sogar vom Netz nimmt.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Beste Lösung:&lt;/strong&gt; Ich nutze wann immer es geht &lt;code&gt;Wikipedia&lt;/code&gt;, denn dieses seit 20
Jahren existierende Projekt pflegt “das Wissen der Menschheit” in einem 
standardisiertem Format und zahlreiche Nutzer sorgen auch bei Verschiebungen
von Informationen zwischen Seiten, dass die früheren Begriffe zu neuen
Seiten umgeleitet werden.&lt;/p&gt;

&lt;h3 id=&quot;wie-wird-man-zum-wikipedia-author&quot;&gt;Wie wird man zum Wikipedia Author?&lt;/h3&gt;

&lt;p&gt;Es ist ganz einfach: Man registriert sich mit Email-Adresse, Usernamen und 
Passwort bei Wikipedia. Ab sofort kann man Änderungen durchführen und neue
Seiten anlegen.&lt;br /&gt;
Jede neue Änderung wird als “Ungesichtete Änderung” deklariert. Kommen Nutzer
zur Seite, sehen sie den alten Zustand, können aber oben im Tab 
&lt;code&gt;Ungesichtete Änderungen&lt;/code&gt; den neuen Text lesen oder in &lt;code&gt;Versionsgeschichte&lt;/code&gt;
zwischen den Updates hin und herwechseln.&lt;/p&gt;

&lt;p&gt;Erst wenn ein Mitarbeiter des offiziellen Wikipedia Teams den Text gelesen
und bestätigt hat, wird er zur “aktuelle Version” hinauf gestuft.&lt;br /&gt;
Natürlich kann er auch abgelehnt werden, und das geschieht meiner Erfahrung
nach nur dann, wenn der Text nicht dem Charakter einer Enzyklopädie entspricht.&lt;/p&gt;

&lt;p&gt;Man soll&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;über allgemeine Dinge berichten (und nicht etwa über den Lebenslauf seines 
Haustieres schreiben)&lt;/li&gt;
  &lt;li&gt;keine Lehrbücher verfassen sondern eine mögliche kurze und aussagekräftige
Themenbeschreibung abgeben.&lt;/li&gt;
  &lt;li&gt;keine persönlichen Meinungen oder andere subjektive Attribute einfließen 
lassen.&lt;/li&gt;
  &lt;li&gt;bestehende Seiten erweitern und nicht ständig neue Begriffe einzuführen.&lt;/li&gt;
  &lt;li&gt;alle Texte selbst verfassen und keinesfalls Textpassage kopieren (außer
sie werden als explizites Zitat markiert)&lt;/li&gt;
  &lt;li&gt;Jede Äußerung mit einer Quelle belegen, also einer anderen Internetseite,
die das Thema behandelt und sachlich beschreibt.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Das Anlegen neuer Seiten wird grundsätzlich nicht so gerne gesehen, denn 
nachdem &lt;code&gt;Wikipedia&lt;/code&gt; eine so unglaublich große Datenmenge beinhaltet, kann man
davon ausgehen, dass schon fast alles einmal erwähnt wurde und das ist 
auch oft so.&lt;br /&gt;
Man denkt ein Thema würde fehlen, schreibt einen Artikel und dann stellt sich
heraus, dass genau das gleiche schon als Absatz in einem Überbegriff 
beschrieben wurde. Ab wann eine Aufspaltung durchgeführt werden soll und wann
nicht, ist oft Diskussionsthema und lässt sich im Tab “Diskussionen” 
nachverfolgen, wo ebenso jeder mitdiskutieren kann.&lt;/p&gt;

&lt;h3 id=&quot;spezieller-syntax&quot;&gt;“Spezieller” Syntax&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;Wikipedia&lt;/code&gt; nutzt intern eine eigene Auszeichnungssprache namens 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Wikitext&quot;&gt;Wikitext&lt;/a&gt;, in welcher man Links oder 
Formatierungen mit speziellen Zeichen ausdrücken kann.&lt;br /&gt;
z.B.:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Überschriften werden mit &lt;code&gt;=&lt;/code&gt; Zeichen ummantelt, mehrere Gleichheitszeichen 
definieren untergeordnete Überschriften, z.B.:&lt;br /&gt;
&lt;code&gt;= Überschrift =&lt;/code&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Listen werden mit Sternen definiert, z.B.:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;* Element 1  
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;** Unterelement 1.1  
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;* Element 2  
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;Formatierungen für kursive und fette Satzteile mit Hochkommata, z.B.:
    &lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;So sieht ein &apos;&apos;kursiver&apos;&apos; Text aus,  
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;so ein &apos;&apos;&apos;fetter&apos;&apos;&apos; 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;und so ein &apos;&apos;&apos;&apos;kursiver und fetter&apos;&apos;&apos;&apos; Text
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;Links werden mit &lt;code&gt;[[]]&lt;/code&gt; Klammern ummantelt, z.B.:
    &lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;Hier ein Link zur [[Wikipedia]] Seite intern.  
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;Hier ein externer Link: [https://www.duckduckgo.com DuckDuckGo]
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Doch wenn es um Tabellen geht, bin ich enttäuscht, die sehen nämlich so aus:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;{|
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;|+
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;!Spaltenkopf 1
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;!Spaltenkopf 2
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;|-
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;|Zeile 1, Spalte1
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;|Zeile 1, Spalte2
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;|-
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;|Zeile 2, Spalte1
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;|Zeile 2, Spalte2
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;|}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Das gleiche sieht in Markdown so aus:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;| Spaltenkopf 1     | Spaltenkopf2     |
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;|-------------------|------------------|
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;| Zeile 1, Spalte 1 | Zeile1, Spalte 2 |
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;| Zeile 2, Spalte 1 | Zeile2, Spalte 2 |
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;blockquote&gt;
  &lt;p&gt;Und? Was ist jetzt übersichtlicher ??&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ich verstehe schon, dass es in Markdown bei vielen Spalten auch zu überlangen
und Zeilen kommt, aber dann hat man vielleicht auch zu viele Daten in seine
Ansicht gequetscht.&lt;/p&gt;

&lt;p&gt;Zum Glück gibt es heute einen Online-&lt;a href=&quot;https://de.wikipedia.org/wiki/WYSIWYG&quot;&gt;WYSIWYG&lt;/a&gt; 
Editor, wo man Tabellen per Maus Menü erstellen kann … aber bei manchen 
Details muss man dann doch wieder den nativen Quellcode anpassen.&lt;/p&gt;

&lt;p&gt;Ich brauchte neulich jedenfalls verdammt lange, eine Seite mit Prozessor
Modellen zu aktualisieren, weil ich meine lokal vorbereitete Textliste nicht
einfach in &lt;code&gt;Wikipedia&lt;/code&gt; einfügen konnte. Am Ende musste ich Zelle für Zelle
neu schreiben.&lt;/p&gt;

&lt;p&gt;Also hier würde ich mir “Optimierungen” wünschen … weiß aber gleichzeitig,
dass man so ein großes System nicht so einfach umstellen oder erweitern kann.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;Tut was für Wikipedia!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Diesen Aufruf kann ich immer nur wiederholen, denn jeder, wirklich jeder, 
nutzt &lt;code&gt;Wikipedia&lt;/code&gt;. Angefangen bei der Wahl des Urlaubszieles bis hin zum 
Nachschlagen von mathematischen Formeln.&lt;/p&gt;

&lt;p&gt;Man kann immer wieder mal ein paar Euro spenden um den Betrieb zu unterstützen
und noch besser ist es, im eigenen Fachbereich mal auf diversen Seiten die
Qualität zu heben.&lt;/p&gt;

&lt;p&gt;Ich maße mir auch nicht an, dort große Artikel zu schreiben, aber wenn es 
darum geht, Daten nachzutragen oder Beschreibungen mit Weblinks zu belegen,
dann kann jeder seinen Beitrag leisten um dieses vermutlich größte freie
Projekt auf dem Planeten zu verbessern, damit alle noch möglichst lange 
ihren Spaß damit haben und … noch wichtiger: viel daraus lernen.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>C Function Overloading</title>
   <link href="https://www.opengate.at/blog/2022/07/overloading/"/>
   <published>2022-07-10T13:00:00+02:00</published>
   <updated>2022-07-10T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2022/07/overloading</id>
   <category term="devel" />
   <summary type="text">In C kann eine Funktion
genau eine Signatur haben, während in C++ 
unter einem Funktionsnamen mehrere Implementierung möglich sind. Der Compiler
adressiert die richtige basierend auf den Datentypen beim Aufruf.

Aber mit ein paar Makro-Tricks, kann man zumindest bei der Anzahl der
Parameter ein bisschen C++ Overloading in den alten C Standard übertragen.
</summary>
   <content type="html">&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/C_(Programmiersprache)&quot;&gt;In C&lt;/a&gt; kann eine Funktion
genau eine Signatur haben, während in &lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B&quot;&gt;C++&lt;/a&gt; 
unter einem Funktionsnamen mehrere Implementierung möglich sind. Der Compiler
adressiert die richtige basierend auf den Datentypen beim Aufruf.&lt;/p&gt;

&lt;p&gt;Aber mit ein paar Makro-Tricks, kann man zumindest bei der Anzahl der
Parameter ein bisschen C++ Overloading in den alten C Standard übertragen.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;variadic-macros&quot;&gt;Variadic Macros&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Variadic_macro_in_the_C_preprocessor&quot;&gt;Makros können so wie auch &lt;em&gt;variadic&lt;/em&gt; Funktionen&lt;/a&gt; 
mit einer undefinierten Anzahl von Parametern aufgerufen werden. Das Makro 
kann aber dann nicht mehr damit tun, als diese Parameter “weiterzuleiten”.&lt;/p&gt;

&lt;p&gt;Das klassische Beispiel dafür sind &lt;code&gt;printf&lt;/code&gt; Adaptionen:&lt;/p&gt;
&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#define&lt;/span&gt; my_printf(format, ...)  printf(format, __VA_ARGS__)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; main()
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  my_printf(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;%s %s&lt;/span&gt;&lt;span style=&quot;color:#b0b&quot;&gt;\n&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Hello&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;World&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;  my_printf(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;%s&lt;/span&gt;&lt;span style=&quot;color:#b0b&quot;&gt;\n&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Bye!&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Und nun eine verrückte Frage:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Was wäre, wenn ein Makro eine Funktion simuliert und je
nach Anzahl der Parameter eine andere Funktion aufruft?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;argumente-mit-makros-zählen&quot;&gt;Argumente mit Makros zählen&lt;/h3&gt;

&lt;p&gt;Man findet im Netz einen interessanten Trick, mit dem man per
Makro die Anzahl der Argumente des Aufrufs zählen kann.&lt;br /&gt;
Mit dieser Zahl kann man dann einen Aufruf auf einen zusammengesetzten 
Funktionsnamen umleiten, der auf genau diese Zahl endet:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#define&lt;/span&gt; COUNT_ARGS_IMPL(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N,...) N
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#define&lt;/span&gt; COUNT_ARGS_HELPER(tuple) COUNT_ARGS_IMPL tuple
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#define&lt;/span&gt; COUNT_ARGS(...) COUNT_ARGS_HELPER((__VA_ARGS__, &lt;span style=&quot;color:#00D&quot;&gt;10&lt;/span&gt;, &lt;span style=&quot;color:#00D&quot;&gt;9&lt;/span&gt;, &lt;span style=&quot;color:#00D&quot;&gt;8&lt;/span&gt;, &lt;span style=&quot;color:#00D&quot;&gt;7&lt;/span&gt;, &lt;span style=&quot;color:#00D&quot;&gt;6&lt;/span&gt;, &lt;span style=&quot;color:#00D&quot;&gt;5&lt;/span&gt;, &lt;span style=&quot;color:#00D&quot;&gt;4&lt;/span&gt;, &lt;span style=&quot;color:#00D&quot;&gt;3&lt;/span&gt;, &lt;span style=&quot;color:#00D&quot;&gt;2&lt;/span&gt;, &lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;, &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;))
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#define&lt;/span&gt; CONCAT(a, b) a &lt;span style=&quot;color:#579&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;# b&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#define&lt;/span&gt; BUILD_FUNCTION(func_prefix, arg_count) CONCAT(func_prefix, arg_count)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#define&lt;/span&gt; CALL_OVERLOADED(func_prefix, args) BUILD_FUNCTION(func_prefix, COUNT_ARGS args)  args
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;&lt;code&gt;COUNT_ARGS&lt;/code&gt; fügt den originalen Argumenten die Zahlen 10 bis 0 hinzu, weil 
wir bis zu maximal 10 Argumente unterstützen.&lt;br /&gt;
Die damit aufgerufene Funktion &lt;code&gt;COUNT_ARGS_IMPL&lt;/code&gt; schluckt beliebig viele 
Parameter und interessiert sich für den 11. Denn dieser verrät uns die Anzahl
der Parameter der originalen Funktion.&lt;/p&gt;

&lt;p&gt;Ein Aufruf  &lt;code&gt;(a, b, c)&lt;/code&gt; wird umgeformt zu&lt;br /&gt;
&lt;code&gt;(a, b, c, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)&lt;/code&gt; und an der 11. Stelle steht dann 
&lt;code&gt;3&lt;/code&gt;, die von &lt;code&gt;COUNT_ARGS_IMPL&lt;/code&gt; zurückgegeben wird.&lt;/p&gt;

&lt;p&gt;Das Makro &lt;code&gt;CALL_OVERLOADED&lt;/code&gt; versucht jetzt ein Funktionsnamen über ein Präfix 
und die ermittelten Argumentanzahl zusammenzubauen und ruft sie mit den 
Argumenten auf.&lt;/p&gt;

&lt;p&gt;Jetzt kann man sich Funktionsaufrufe mit einem Makro umleiten lassen, z.B.:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#define&lt;/span&gt; foo(...) CALL_OVERLOADED(foo_, (__VA_ARGS__))
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Wird &lt;code&gt;foo(x, y)&lt;/code&gt; mit 2 Parametern aufgerufen, wird ein &lt;code&gt;foo_2(x, y)&lt;/code&gt; daraus.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; foo_1(&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; a);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; foo_2(&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; a, &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; b);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; foo_3(&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; a, &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; b, &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; c);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; main()
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  foo(&lt;span style=&quot;color:#00D&quot;&gt;10&lt;/span&gt;);         &lt;span style=&quot;color:#777&quot;&gt;/* calls foo_1(10) */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;  foo(&lt;span style=&quot;color:#00D&quot;&gt;20&lt;/span&gt;, &lt;span style=&quot;color:#00D&quot;&gt;30&lt;/span&gt;);     &lt;span style=&quot;color:#777&quot;&gt;/* calls foo_2(20, 30) */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;  foo(&lt;span style=&quot;color:#00D&quot;&gt;40&lt;/span&gt;, &lt;span style=&quot;color:#00D&quot;&gt;50&lt;/span&gt;, &lt;span style=&quot;color:#00D&quot;&gt;60&lt;/span&gt;); &lt;span style=&quot;color:#777&quot;&gt;/* calls foo_3(40, 50, 60) */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Ein vollständiges Beispiel liegt im 
&lt;a href=&quot;https://codeberg.org/GateNetwork/gate-blog-classroom/src/branch/main/c_cpp/c_function_overloading/&quot;&gt;BLOG-Classroom&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;problem-msvc&quot;&gt;Problem MSVC&lt;/h3&gt;

&lt;p&gt;Microsofts Präprozessor wurde lange nicht aktualisiert und läuft daher
nicht-standard-konform und kann die obigen Makros nicht richtig auflösen.&lt;/p&gt;

&lt;p&gt;Doch seit MSVC 2019 (14.2) existiert der Compilerswitch &lt;code&gt;/Zc:preprocessor&lt;/code&gt; 
mit dem man den Standard-konformen Modus einschalten kann und somit kann 
auch Microsoft endlich von den vielen “coolen” Makrospielereien profitieren,
die man so im Netz findet.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ich hatte eigentlich wieder an meinem &lt;a href=&quot;/blog/2022/02/local-type/&quot;&gt;Lambda-Problem&lt;/a&gt; 
herumexperimentiert und bin dabei über die Frage gestoßen, wie man aus der 
Anzahl von Makroparametern unterschiedliche Klassennamen generieren kann.&lt;/p&gt;

&lt;p&gt;Das hat im Endeffekt mein Problem zwar nicht lösen können, aber die Idee in
C etwas Overloading-ähnliches einzubauen, und auszuprobieren, hat wieder
Spaß gemacht.&lt;/p&gt;

&lt;p&gt;Im GATE Projekt kann ich das nicht auf großer Ebene einsetzen, weil dort 
auch ältere MSVC Compiler unterstützt werden sollen, aber vielleicht ist der
Ansatz ja bei manchen &lt;a href=&quot;https://en.wikipedia.org/wiki/GNU_Compiler_Collection&quot;&gt;GCC&lt;/a&gt; 
Fixes eine willkommene Option.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Thor: Love and Thunder</title>
   <link href="https://www.opengate.at/blog/2022/07/thor-4/"/>
   <published>2022-07-06T13:00:00+02:00</published>
   <updated>2022-07-06T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2022/07/thor-4</id>
   <category term="entertainment" />
   <summary type="text">Oder: Ihre Kinder werden es mögen.


  W-T-F ist denn das für eine Story?


… war einer der Gedanken, die ich heute Abend im Kino hatte.

</summary>
   <content type="html">&lt;h3 id=&quot;oder-ihre-kinder-werden-es-mögen&quot;&gt;Oder: Ihre Kinder werden es mögen.&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;W-T-F ist denn das für eine Story?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;… war einer der Gedanken, die ich heute Abend im Kino hatte.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Aktuell ist es gerade etwas schwierig, sich “als größter 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Marvel_Cinematic_Universe&quot;&gt;Marvel&lt;/a&gt;-Fan” zu 
bezeichnen, denn während die Filme vor 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Avengers:_Endgame&quot;&gt;Endgame&lt;/a&gt; 
versuchten auf einander zusammen zu laufen, erkenne ich jetzt das Gegenteil.&lt;/p&gt;

&lt;p&gt;Das mag vielleicht zu den vielen Comics ganz gut passen, aber das 
MCU (Marvel Cinematic Universe) wich von diesem Ansatz bisher zu seinem 
Vorteil ab.&lt;/p&gt;

&lt;p&gt;Ich habe heute einen wirklich komischen, lustigen Film gesehen.
Das Publikum hat immer wieder hell auf gelacht, so auch ich.
Und trotzdem war das kein MCU Marvel Film, obwohl das Logo und Intro
von Marvel vorkam.&lt;/p&gt;

&lt;h3 id=&quot;götter&quot;&gt;Götter&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Achtung Spoiler!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Thor Odinson mag vielleicht der nordischen Mythologie entspringen, doch 
Marvel hat sich in den ersten Filmen viel Mühe gegeben, Asgard und seine
Bürger als außerirdische überlegene Spezies darzustellen, die Technik
einsetzen, die für uns einfache Menschen nur wie Magie wirkt.&lt;br /&gt;
(OK, den fliegenden Hammer &lt;a href=&quot;https://de.wikipedia.org/wiki/Mj%C3%B6lnir&quot;&gt;Mjölnir&lt;/a&gt; 
lassen wir mal außen vor).&lt;/p&gt;

&lt;p&gt;Doch nun - und mit &lt;a href=&quot;https://en.wikipedia.org/wiki/Moon_Knight_(TV_series)&quot;&gt;Moonknight&lt;/a&gt; 
hat es angefangen - werden unzählige selbsternannte Gottheiten eingeführt, 
die sich einfach nur daran erfreuen angebetet zu werden.&lt;br /&gt;
Wie &lt;a href=&quot;https://de.wikipedia.org/wiki/Pok%C3%A9mon&quot;&gt;Pokemon&lt;/a&gt; im Pokedex saßen 
diese dann alle im nachgebauten Kolosseum und deckten ausgewogen die 
Elementtypen Feuer, Wasser, Pflanze bis hin zum Typ
Fee ab, ohne bekannt oder notwendig zu sein.&lt;/p&gt;

&lt;p&gt;Und dieser inflationär gebrauchte verwässerte “Gott”-Begriff schadet der
im MCU aufgebauten Welt mehr, als er ihr nützt.&lt;/p&gt;

&lt;p&gt;Und wer den Graupelschauer von Film namens 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Gods_of_Egypt&quot;&gt;Gods of Egypt&lt;/a&gt; gesehen hat, weiß
auch schon, wie sich Götter verhalten und was durch ihre Adern fließt.&lt;/p&gt;

&lt;h3 id=&quot;smells-like-teen-spirit---mal-anders&quot;&gt;Smells like Teen Spirit - mal anders&lt;/h3&gt;

&lt;p&gt;Also, ich freue mich ja total, wenn Kinder und Jugendliche mal größere 
Rollen im MCU erhalten, als nur “süß” auszusehen.&lt;br /&gt;
Wie schön war es, als der Junge aus Ironman 3 in Endgame beim Begräbnis 
dabei war, wie die Maximoff Zwillinge ihr Zuhause verteidigt haben, oder
wie Kid-Loki sein Schwert herbeiholt und Hawkeye mit seinen Kindern im
Musical sitzt.&lt;/p&gt;

&lt;p&gt;However … man kann es auch übertreiben, wenn Thor seine Kraft auf alle
Asgard-Teens überträgt, damit sie gemeinsam angreifen können und Blitze
aus dem Teddybären eines kleinen Mädchens schießen um Schattenmonster
“wegzublasen”.&lt;/p&gt;

&lt;p&gt;Ein gutes hat es: Heimdalls Sohn scheint mir “reif” genug zu sein, die
künftigen Young-Avengers zu unterstützen.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/marvel-thor-4.jpg&quot; alt=&quot;Thor-4-Kids&quot; /&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Nachtrag: Thor-4 läuft seit dem 8. September auf Disney+&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;love-without-thunder&quot;&gt;Love without Thunder&lt;/h3&gt;

&lt;p&gt;Die Liebesgeschichte zwischen Thor und Jane wurde ja schon im Trailer
aufgedeckt und ist in soweit nicht spektakulär.&lt;br /&gt;
Viel lustiger ist die Dreiecksbeziehung zwischen Thor, Mjölnir und 
Stormbreaker … denn niemand dachte, dass Stormbreaker so empfindlich und
eifersüchtig sein kann.&lt;/p&gt;

&lt;p&gt;Interessant ist der Hintergrund des Antagonisten, von dem man ganz
deutlich ableiten kann:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Nur wenn man ihn/sie/es geliebt hat, kann man ihn/sie/es dann so sehr hassen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Und leider kommt auch hier die Rolle des Bösen wieder viel zu kurz.
Denn diesem ernsten Thema hätte man mindestens eine halbe Stunde mehr Zeit
einräumen müssen, und dafür hätte ich sogar auf die lustigen Ziegen im Film
verzichtet.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ja, der Film hat mich sehr gut unterhalten und war sein Geld wert.&lt;br /&gt;
Aber als Teil des MCU hatte er nur einen wichtigen Aspekt:&lt;br /&gt;
In der Midcredit-Szene wurde ein neuer Gegner angekündigt.&lt;/p&gt;

&lt;p&gt;Und das finde ich dann doch schade.&lt;br /&gt;
Es hätte so viel mehr sein können.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Pinephone Keyboard</title>
   <link href="https://www.opengate.at/blog/2022/07/pine-kbd/"/>
   <published>2022-07-03T13:00:00+02:00</published>
   <updated>2022-07-03T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2022/07/pine-kbd</id>
   <category term="hardware" />
   <summary type="text">
  Smartphone + Keyboard = PC ?


Naja, nicht ganz. Aber wenn man mehr texten will, braucht man einfach eine
Tastatur, denn egal wie gut sie ist, die Onscreen-Tastatur kann einfach 
keine echte ersetzen.

Und dank des neuen Keyboard-Docks für mein PinePhone, 
lässt sich das jetzt realisieren.
</summary>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;Smartphone + Keyboard = PC ?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Naja, nicht ganz. Aber wenn man mehr texten will, braucht man einfach eine
Tastatur, denn egal wie gut sie ist, die Onscreen-Tastatur kann einfach 
keine echte ersetzen.&lt;/p&gt;

&lt;p&gt;Und dank des neuen Keyboard-Docks für mein &lt;a href=&quot;https://de.wikipedia.org/wiki/PinePhone&quot;&gt;PinePhone&lt;/a&gt;, 
lässt sich das jetzt realisieren.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Das Pine64-Projekt gefällt mir bekanntlich sehr, und daher unterstütze ich es
gerne mit dem Kauf ihrer Produkte, und eines davon ist das PinePhone-Keyboard.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/pinephone-keyboard.jpg&quot; alt=&quot;Pinephone-Keyboard&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Nun … eigentlich geht das jetzt ein bisschen in die falsche Richtung, weil
wir kennen alle das Video, in dem sich &lt;a href=&quot;https://de.wikipedia.org/wiki/Steve_Ballmer&quot;&gt;Steve Ballmer&lt;/a&gt;
über das &lt;a href=&quot;https://de.wikipedia.org/wiki/IPhone&quot;&gt;iPhone&lt;/a&gt; lustig macht und meint, 
ohne Stylus und Tastatur kann man darauf keine eMails schreiben.&lt;br /&gt;
Tja, er hätte sich nicht mehr irren können. Niemand braucht Tastaturen für
eMails … oder?&lt;/p&gt;

&lt;iframe width=&quot;640&quot; height=&quot;360&quot; src=&quot;/blog/redirect.html?https%3A%2F%2Fwww.youtube-nocookie.com%2Fembed%2Feywi0h_Y5_U&quot; frameborder=&quot;1&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;

&lt;p&gt;EMails habe ich am Pinephone noch kein einziges geschrieben und werde es
auch nicht, aber es gibt etwas, was ich häufiger darauf mache:&lt;br /&gt;
Ich öffne das Terminal und führe Programme wie &lt;code&gt;cmake&lt;/code&gt; und Buildscripts aus.&lt;/p&gt;

&lt;p&gt;Und das ist mit der Onscreen-Tastatur einfach nur ein Krampf.&lt;br /&gt;
Ja, &lt;a href=&quot;https://de.wikipedia.org/wiki/Secure_Shell&quot;&gt;SSH&lt;/a&gt; hilft, doch das Gerät 
befindet sich dann doch zu oft im falschen 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Wireless_Local_Area_Network&quot;&gt;WLAN&lt;/a&gt; und schon 
muss ich erst mühsam umkonfigurieren, um ein Script zu starten.&lt;/p&gt;

&lt;h3 id=&quot;pinephone-keyboard&quot;&gt;Pinephone Keyboard.&lt;/h3&gt;

&lt;p&gt;Ende letzten Jahres angekündigt, ist es schon seit ein paar Monaten
verfügbar: Ein Tastaturdock für das Phone.&lt;/p&gt;

&lt;p&gt;Und es ist so einfach: Man nimmt die Rückseite des Pinephone-Gehäuses ab und 
klinkt das Smartphone in das Tastaturdock, und sofort arbeitet die 
Tastatur als primäres Eingabegerät.&lt;/p&gt;

&lt;p&gt;Das Keyboard wirkt auf den ersten Blick recht reduziert, doch die Magie steckt
in der &lt;code&gt;Fn&lt;/code&gt; (Function) Taste zwischen &lt;code&gt;Ctrl&lt;/code&gt; und &lt;code&gt;Alt&lt;/code&gt;. Denn diese schaltet
bei vielen Tasten eine “alternative Funktion” ein, und so liegen die Pfeiltasten
bei den Sonderzeichen rechts unten bei den Sonderzeichen, wie auch die F-Tasten
über den Ziffern liegen.&lt;/p&gt;

&lt;p&gt;Die Kamera ist auch “ausgestanzt” und voll einsatzbereit.
Von den Ausmaßen her ist das Teil ziemlich gleich groß wie mein alter 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Nintendo_3DS#Nintendo_3DS_XL&quot;&gt;Nintendo 3DS XL&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/pinephone-keyboard-closed.jpg&quot; alt=&quot;Pinephone-Keyboard-closed&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;Eine echt gute Lösung diese Hardware.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Und als Entwickler, werde ich dieses Features noch häufig nutzen.&lt;/p&gt;

&lt;p&gt;Ob so eine Tastatur auch im Normalbetrieb relevant ist, wage ich aber zu
bezweifeln.&lt;br /&gt;
Da wird es eher wichtig werden neue Linux Apps zu schaffen, die sich mit
Touchscreens besser bedienen lassen.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>UI Blödheiten</title>
   <link href="https://www.opengate.at/blog/2022/07/ui-fails/"/>
   <published>2022-07-02T13:00:00+02:00</published>
   <updated>2022-07-02T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2022/07/ui-fails</id>
   <category term="software" />
   <summary type="text">Mit der Einführung von “mobilen” Apps haben eine Menge Ahnungsloser, die keine
bis wenig IT Erfahrung hatten, die Möglichkeit der Welt ihren Stempel 
aufzudrücken, weil es dem Marketing erfolgreich gelungen ist allen einzureden,
dass man jetzt alles neu braucht.

Und diesem Wahnsinn sind leider auch 
Checkboxen
und Textfelder zum Opfer gefallen.
</summary>
   <content type="html">&lt;p&gt;Mit der Einführung von “mobilen” Apps haben eine Menge Ahnungsloser, die keine
bis wenig IT Erfahrung hatten, die Möglichkeit der Welt ihren Stempel 
aufzudrücken, weil es dem Marketing erfolgreich gelungen ist allen einzureden,
dass man jetzt alles neu braucht.&lt;/p&gt;

&lt;p&gt;Und diesem Wahnsinn sind leider auch 
&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/apps/design/controls/checkbox&quot;&gt;Checkboxen&lt;/a&gt;
und Textfelder zum Opfer gefallen.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Neulich hatte ich einen “speziellen” Support-Anruf aus dem privaten Umfeld.&lt;br /&gt;
Die Online-Banking-Seite verwirrt nun noch mehr mit der Option einer
kostenpflichtigen Noch-Schneller-Sofort-Transaktion, die sich angeblich
nicht ausschalten lässt.&lt;/p&gt;

&lt;h3 id=&quot;toggle-buttons&quot;&gt;Toggle Buttons&lt;/h3&gt;

&lt;p&gt;“Toggle-Buttons” heißen diese UI-Dinger, die Optionen ein und ausschaltbar
machen sollen.&lt;br /&gt;
Dass unsere Teenagergeneration angeblich intuitiv dahinter steigt, wie man 
die bedient, mag vielleicht stimmen, aber für die 40+ Benutzer ist das 
nicht so.&lt;br /&gt;
Auch mir ist es schon öfter passiert, dass ich nicht auf Anhieb erkennen
konnte, was jetzt “on” und was “off” bedeuten soll.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/toggle-buttons.gif&quot; alt=&quot;Toggle-Buttons&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Der Grund für dieses Chaos liegt darin begründet, dass jetzt jede noch so 
unwichtige Firma glaubt, sie müssten ihr eigenes UI-Design mit eigenen
Farbspielen auf den Markt bringen.&lt;br /&gt;
Und ahnungslose Anfänger (auch &lt;a href=&quot;https://de.wikipedia.org/wiki/Webdesign&quot;&gt;Webdesigner&lt;/a&gt;
genannt) zeichnen dann drei Wochen an einem abgerundeten Viereck herum, wo man
innen einen Kreis nach links und rechts verschieben kann.&lt;br /&gt;
Ob jetzt “ON” links oder rechts, hell oder dunkel ist, hängt von der Laune 
des Zeichners ab.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Wieso konnte man nicht die gute alte Checkbox, die man schon vor 50 Jahren 
auf Antragsformularen auf Papier vor sich hatte, einfach weiterbenutzen?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Denn dieses UI Element ist in allen Betriebssystemen vorhanden und passt sich
and das Standard-Design an, reagiert zuverlässig auf Klicks und jeder
versteht, dass ein leerer Kasten “deaktiviert” bedeutet und ein angehakter 
mit “aktiviert” gleichgesetzt ist.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;input type=&quot;checkbox&quot; id=&quot;sample_check_1&quot; name=&quot;sample_check_1&quot; value=&quot;check1&quot; checked=&quot;&quot; /&gt;
  &lt;label for=&quot;sample_check_1&quot;&gt;&lt;small&gt;Here is a checkable option (click me)&lt;/small&gt;&lt;/label&gt;&lt;br /&gt;
  &lt;input type=&quot;checkbox&quot; id=&quot;sample_check_2&quot; name=&quot;sample_check_2&quot; value=&quot;check2&quot; /&gt;
  &lt;label for=&quot;sample_check_2&quot;&gt;&lt;small&gt;Here is another checkable option (click me)&lt;/small&gt;&lt;/label&gt;&lt;br /&gt;
&lt;/blockquote&gt;

&lt;p&gt;HTML kennt z.B.: den &lt;code&gt;&amp;lt;input type=&quot;checkbox&quot;&amp;gt;&lt;/code&gt; schon seit den aller ersten Tagen.&lt;/p&gt;

&lt;p&gt;Das Problem mit Toogle-Buttons sind die vielen Eigenentwicklungen, die
“möglichst cool” zur Firmenfarbe passen sollen.&lt;br /&gt;
Und dann passiert es, dass das Farbschema so dezent ist, dass man den 
“Ein” vom “Aus” Zustand optisch nicht mehr unterscheiden kann.&lt;/p&gt;

&lt;h3 id=&quot;textbox-mit-50-cpu-auslastung&quot;&gt;Textbox mit 50% CPU Auslastung&lt;/h3&gt;

&lt;p&gt;Der nächste Dreck sind selbst-designete (oder von Google kopierte) Textbox 
Imitate, die&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;bei jedem Tastenanschlag Webrequests absetzen&lt;/li&gt;
  &lt;li&gt;kein Copy/Paste unterstützen&lt;/li&gt;
  &lt;li&gt;bei Internetaussetzern Daten verlieren&lt;/li&gt;
  &lt;li&gt;dauerhaft 50% CPU Auslastung generieren, weil sie sich dauernd neuzeichnen&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Oft reicht die klassische Combobox aus, also eine Textbox, die mit einer 
Listbox kombiniert ist und beim Tippen Auswahlmöglichkeiten bietet.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;label for=&quot;sample_combo&quot;&gt;Enter your Platform:&lt;/label&gt;
  &lt;input list=&quot;sample_list&quot; name=&quot;sample_combo&quot; id=&quot;sample_combo&quot; /&gt;
  &lt;datalist id=&quot;sample_list&quot;&gt;
    &lt;option value=&quot;Windows 7&quot; /&gt;
    &lt;option value=&quot;Windows 8&quot; /&gt;
    &lt;option value=&quot;Windows 10&quot; /&gt;
    &lt;option value=&quot;Windows 11&quot; /&gt;
    &lt;option value=&quot;Windows CE&quot; /&gt;
    &lt;option value=&quot;Debian Linux&quot; /&gt;
    &lt;option value=&quot;SuSE Linux&quot; /&gt;
    &lt;option value=&quot;Redhat Linux&quot; /&gt;
    &lt;option value=&quot;CentOS Linux&quot; /&gt;
    &lt;option value=&quot;Alpine Linux&quot; /&gt;
    &lt;option value=&quot;Other Linux&quot; /&gt;
    &lt;option value=&quot;OpenBSD&quot; /&gt;
    &lt;option value=&quot;NetBSD&quot; /&gt;
    &lt;option value=&quot;FreeBSD&quot; /&gt;
    &lt;option value=&quot;MacOS&quot; /&gt;
    &lt;option value=&quot;Haiku&quot; /&gt;
  &lt;/datalist&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/HTML5&quot;&gt;HTML5&lt;/a&gt; führte das&lt;br /&gt;
&lt;code&gt;&amp;lt;datalist id=&quot;list_id&quot;&amp;gt;&lt;/code&gt; Tag ein um &lt;code&gt;&amp;lt;option&amp;gt;&lt;/code&gt; Einträge auch
z.B. an &lt;code&gt;&amp;lt;input type=&quot;text&quot; list=&quot;list_id&quot;&amp;gt;&lt;/code&gt; binden zu können.&lt;/p&gt;

&lt;h3 id=&quot;janein-linksrechts-&quot;&gt;Ja/Nein Links/rechts ?&lt;/h3&gt;

&lt;p&gt;Und dann noch die Sache mit der Frage, ob “Ja” und “Nein” (bzw. “OK” und 
“Abbrechen”) jetzt von links nach rechts angeordnet ist, oder umgekehrt.&lt;/p&gt;

&lt;p&gt;Zugegeben, das ist plattformabhängig.&lt;br /&gt;
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows&quot;&gt;Windows&lt;/a&gt; nutzt den ersten 
Ansatz, &lt;a href=&quot;https://de.wikipedia.org/wiki/MacOS&quot;&gt;MacOS&lt;/a&gt; den zweiten und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt; wechselte vom ersten zum zweiten.&lt;/p&gt;

&lt;p&gt;Wenn die Leute also ihre eigenen Dialoge schreiben, entscheiden sie sich
für ein Schema, doch das entspricht dann nicht immer der Plattform.&lt;/p&gt;

&lt;p&gt;Auch hier kann man zumindest bei ein paar Dialogen auf System-Implementierungen
setzen.&lt;/p&gt;

&lt;p&gt;&lt;input type=&quot;button&quot; value=&quot;Click me&quot; onclick=&quot;confirm(&apos;Is it OK?&apos;);&quot; /&gt;&lt;/p&gt;

&lt;p&gt;In HTML kann man z.B. auf die Javascript Funktion &lt;code&gt;confirm()&lt;/code&gt; zurückgreifen.
Der Browser zeigt den Dialog so an, wie der Browser-Standard es festlegt.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Individualität ist super, ich mache ja oft auch gerne Dinge “einfach anders”.&lt;br /&gt;
Aber gerade UIs sollten sich “an alle richten” und deshalb sind hier 
Standards wichtig.&lt;/p&gt;

&lt;p&gt;Und wenn eine Bank sich einbildet, sie müsste ihre eigenen Toggle-Buttons
implementieren und die so verunstaltet, dass die Kunden Angst haben am UI
was falsch zu machen, ist das &lt;em&gt;nicht gut&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Das Schlimme ist, dass das die Webentwicklung ebenso trifft, wie native
UI-Programme.&lt;br /&gt;
Auch mir wurde schon der Auftrag erteilt, bloß keine Standard-Controls
zun nutzen und alles mit ersetzbaren Bitmaps vollzupflastern.&lt;br /&gt;
Das Resultat war eine schlechte UI mit CPU-Spitzen, wenn man die Maus
drüberfahren ließ … aber:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Der Markt will das so.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Wir brauchen daher weniger Eigen-UI-Entwickler, sondern welche, die die
Plattformen kennen und wissen, wie man diese richtig einsetzt um zu 
besseren Ergebnissen zu gelangen.&lt;br /&gt;
Oder anders gesagt:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Weniger ist manchmal mehr.&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>Dokumentation</title>
   <link href="https://www.opengate.at/blog/2022/06/docu/"/>
   <published>2022-06-26T13:00:00+02:00</published>
   <updated>2022-06-26T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2022/06/docu</id>
   <category term="projects" />
   <summary type="text">Wenn man den Satz


  Gute Programmierer sind schlechte Dokumentierer.


umgekehrt auffasst, dann bin ich einer der besten Programmierer, 
denn Dokus schreiben mag ich so gar nicht.

However … auch das muss mal sein.
</summary>
   <content type="html">&lt;p&gt;Wenn man den Satz&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Gute Programmierer sind schlechte Dokumentierer.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;umgekehrt auffasst, dann bin ich einer der besten Programmierer, 
denn Dokus schreiben mag ich so gar nicht.&lt;/p&gt;

&lt;p&gt;However … auch das muss mal sein.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Der C-Teil der Kernbibliothek des GATE Frameworks &lt;code&gt;gatecore&lt;/code&gt; ist nun zum 
Großteil mit &lt;code&gt;doxygen&lt;/code&gt; Kommentarblöcken befüllt und somit konnte die
erste sinnvolle Version der Projektdokumentation generiert werden.&lt;/p&gt;

&lt;p&gt;Da mein &lt;code&gt;doxygen&lt;/code&gt; Setup so aussieht, dass nur dokumentierte Codes abgebildet
sind (und nicht alles automatisch extrahiert wird), musste ich also vor 
jeder öffentlichen Funktion entsprechende Kommentare anfügen.&lt;/p&gt;

&lt;p&gt;Das ist zwar noch lange nicht vollständig, doch nun sind zumindest viele
Kernfunktionen mal “offiziell” geworden.&lt;/p&gt;

&lt;p&gt;Dokumentation ist gleichzeitig auch ein Interface-Review und tatsächlich sind 
mir einige Inkonsistenzen aufgefallen, die ich teils gleich korrigieren 
konnte. Andere Details stehen auf der “Redesign” Liste.&lt;/p&gt;

&lt;p&gt;Damit auch ein bisschen mehr Qualitätsdruck entsteht, wurden die generierten
HTML Dateien auf den Webspace hochgeladen, wo sie unter
&lt;code&gt;http://www.opengate.at/doc&lt;/code&gt; einsehbar sind.&lt;/p&gt;

&lt;p&gt;Der nächste Punkt wird das C++ Interface werden und parallel verlangen auch 
die Bibliotheken &lt;code&gt;gateio&lt;/code&gt;, &lt;code&gt;gatesystem&lt;/code&gt;, &lt;code&gt;gateencode&lt;/code&gt;, &lt;code&gt;gatenet&lt;/code&gt; und 
&lt;code&gt;gategraphics&lt;/code&gt; nach einer Schnittstellenbeschreibung.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Leider frisst das Dokumentieren wirklich extrem viel Zeit, denn hier gilt
tatsächlich im Header:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Für eine Zeile Code, braucht man 5 Zeilen Dokumentation.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Und wenn dann noch jeder Parameter seine Geheimnisse preisgeben soll, merkt
man erst, dass tatsächlich 5 mal mehr Beschreibungszeilen erforderlich sind,
als für die eine Codezeile, die eine Funktion ankündigt.&lt;/p&gt;

&lt;p&gt;Ich hoffe, dass meine Motivation hinreichend lange aufrecht bleibt, um die
Grundzüge des Projektes darzustellen.&lt;/p&gt;

&lt;p&gt;Mal sehen, was in einem Jahr daraus werden wird.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Makro-C-Objekte in Doxygen</title>
   <link href="https://www.opengate.at/blog/2022/06/doxygen-macros/"/>
   <published>2022-06-25T13:00:00+02:00</published>
   <updated>2022-06-25T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2022/06/doxygen-macros</id>
   <category term="devel" />
   <summary type="text">Wenn ich meine selbstgestrickten Makros einsetze, um 
V-Table structs 
generieren zu lassen und anschließend C-Klassen structs, dann schreibt
Doxygen ziemlich wirres Zeug.

Ähnlich ergeht es manch alten COM Projekten 
in C, die ebenfalls 
mit Makros arbeiten (die mir ja auch als Inspiration gedient haben).

Wie bekommt man also eine Doxygen-konforme Lösung hin?
</summary>
   <content type="html">&lt;p&gt;Wenn ich meine selbstgestrickten Makros einsetze, um 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Tabelle_virtueller_Methoden&quot;&gt;V-Table&lt;/a&gt; &lt;code&gt;struct&lt;/code&gt;s 
generieren zu lassen und anschließend C-Klassen &lt;code&gt;struct&lt;/code&gt;s, dann schreibt
&lt;a href=&quot;https://doxygen.nl/&quot;&gt;Doxygen&lt;/a&gt; ziemlich wirres Zeug.&lt;/p&gt;

&lt;p&gt;Ähnlich ergeht es manch alten &lt;a href=&quot;https://de.wikipedia.org/wiki/Component_Object_Model&quot;&gt;COM Projekten&lt;/a&gt; 
in &lt;a href=&quot;https://de.wikipedia.org/wiki/C_(Programmiersprache)&quot;&gt;C&lt;/a&gt;, die ebenfalls 
mit Makros arbeiten (die mir ja auch als Inspiration gedient haben).&lt;/p&gt;

&lt;p&gt;Wie bekommt man also eine Doxygen-konforme Lösung hin?
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Wie Microsoft’s COM in reinem C Code aussah, hat 
&lt;a href=&quot;https://devblogs.microsoft.com/oldnewthing/author/oldnewthing&quot;&gt;Raymond Chan&lt;/a&gt;
bereits &lt;a href=&quot;https://devblogs.microsoft.com/oldnewthing/20200909-00/?p=104198&quot;&gt;super dokumentiert&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Im GATE Projekt beginnt alles mit dem “gate_object” Interface und das wird aus
“ähnlichen” Makros zusammengebaut.
Alle Ableitungen müssen dabei das Interface der Basisklassen nochmals 
exakt nachstellen, damit die entstehende V-Table “kompatibel” bleibt:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;GATE_INTERFACE(gate_object)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  GATE_METHOD0(&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt;*, get_interface_name);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  GATE_METHOD0(&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;,        release);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  GATE_METHOD0(&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt;,         retain);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;};
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;GATE_INTERFACE(gate_cloneable)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;/* extends: gate_object */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;  GATE_METHOD0(&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt;*, get_interface_name);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;  GATE_METHOD0(&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;,        release);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;  GATE_METHOD0(&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt;,         retain);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;/* clonable methods: */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;  GATE_METHOD1(gate_result_t, clone, gate_cloneable_t** clone);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;};
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Daraus wird für ein &lt;code&gt;gate_cloneable&lt;/code&gt; Interface in etwa folgender Code 
generiert:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;typedef&lt;/span&gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;struct&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt;* (*get_interface_name)(&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;* thisptr);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;        (*release)           (&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;* thisptr);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt;         (*retain)            (&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;* thisptr);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  gate_result_t (*clone)(&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;* thisptr, gate_cloneable_t** clone);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;} gate_cloneable_vtbl;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;typedef&lt;/span&gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;struct&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;  gate_cloneable_vtbl &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt;* vtbl;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;} gate_cloneable_t;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Doxygen kann jedoch die etwas komplexeren Makros im Hintergrund leider nicht
alle Auflösen und somit kann ich leider nicht einfach vor &lt;code&gt;GATE_INTERFACE()&lt;/code&gt;
oder vor &lt;code&gt;GATE_METHOD()&lt;/code&gt; meine Doku schreiben.&lt;/p&gt;

&lt;h3 id=&quot;lösung-pseudo-klasse-in-doxygen-nachbauen&quot;&gt;Lösung: Pseudo-Klasse in Doxygen nachbauen&lt;/h3&gt;

&lt;p&gt;Es gibt zwar ein paar Tricks, um den Doxygen Parser zu beeinflussen um ihm
neue Vokabel beizubringen (für COM existieren solche Zusätze), doch ich
hätte gerne eine Lösung, die “Out of the box” funktioniert.&lt;/p&gt;

&lt;p&gt;Und die sieht dann so aus:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#777&quot;&gt;/**&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#777&quot;&gt; * @interface gate_object_t&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#777&quot;&gt; * @brief     Base type of all GATE C objects&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#777&quot;&gt; */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#777&quot;&gt;/**&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#777&quot;&gt; * @fn       char const* get_interface_name()&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#777&quot;&gt; * @memberof gate_object_t&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#777&quot;&gt; * @brief    Returns on object&apos;s interface path name&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;color:#777&quot;&gt; * @return   Static string describing the interface.&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#777&quot;&gt; *&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#777&quot;&gt; * @fn       void release()&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#777&quot;&gt; * @memberof gate_object_t&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#777&quot;&gt; * @brief    Decrease ref-counter, releases object when count == 0&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#777&quot;&gt; *&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#777&quot;&gt; * @fn       int retain()&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#777&quot;&gt; * @memberof gate_object_t&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#777&quot;&gt; * @brief    Increase object&apos;s reference counter&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#777&quot;&gt; * @return   Returns the current reference counter value&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;color:#777&quot;&gt; */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n21&quot; name=&quot;n21&quot;&gt;21&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n22&quot; name=&quot;n22&quot;&gt;22&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n23&quot; name=&quot;n23&quot;&gt;23&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#777&quot;&gt;/**&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n24&quot; name=&quot;n24&quot;&gt;24&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#777&quot;&gt; * @interface  gate_cloneable_t&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n25&quot; name=&quot;n25&quot;&gt;25&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#777&quot;&gt; * @implements gate_object_t&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n26&quot; name=&quot;n26&quot;&gt;26&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#777&quot;&gt; * @brief      Base interface for all objects that can be cloned.&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n27&quot; name=&quot;n27&quot;&gt;27&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#777&quot;&gt; */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n28&quot; name=&quot;n28&quot;&gt;28&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n29&quot; name=&quot;n29&quot;&gt;29&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#777&quot;&gt;/**&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n30&quot; name=&quot;n30&quot;&gt;30&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;color:#777&quot;&gt; * @fn         gate_result_t clone(gate_cloneable_t** clone)&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n31&quot; name=&quot;n31&quot;&gt;31&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#777&quot;&gt; * @memberof   gate_cloneable_t&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n32&quot; name=&quot;n32&quot;&gt;32&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#777&quot;&gt; * @brief      Creates a new object by cloning this object&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n33&quot; name=&quot;n33&quot;&gt;33&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#777&quot;&gt; * @param[out] ptrclone receives the new cloned object&apos;s pointer&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n34&quot; name=&quot;n34&quot;&gt;34&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#777&quot;&gt; * @return     GATE_RESULT_* result code&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n35&quot; name=&quot;n35&quot;&gt;35&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#777&quot;&gt; */&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Folgendes habe ich gelernt:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Der Doxygen-Kommentar Block sollte nach dem Macro-Block folgen.
Steht er davor, wird &lt;code&gt;GATE_INTERFACE()&lt;/code&gt; als Makro oder Funktion erkannt,
die dann auch ohne Bedeutung in der Doku steht.&lt;/li&gt;
  &lt;li&gt;Wichtig ist auch, dass man zuerst einen Kommentarblock schreibt, der die 
Klasse deklariert und anschließend einen neuen Kommentarblock für die 
Funktionen anlegt.&lt;br /&gt;
Wenn man beides in einen Block zusammenfügt kommt keine schöne Doku 
dabei heraus.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;@memberof&lt;/code&gt; nach einem &lt;code&gt;@fn&lt;/code&gt; markiert die Funktion als zugehörig zur 
angegebenen &lt;code&gt;@struct&lt;/code&gt;, &lt;code&gt;@class&lt;/code&gt; oder &lt;code&gt;@interface&lt;/code&gt;.&lt;br /&gt;
(Eigentlich hätte ich ja &lt;code&gt;struct&lt;/code&gt; nutzen müssen, aber das eigentlich von
der IDL stammende &lt;code&gt;interface&lt;/code&gt; benennt dann auch in der Doku die Strukturen
als “Interface”).&lt;/li&gt;
  &lt;li&gt;Mit &lt;code&gt;@implements&lt;/code&gt; werden Vererbungshierarchien definiert, die man dann im 
generierten Doxygen-HTML auch in einem Graphen durchklicken kann.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Naja, ich sehe es jetzt mal als annehmbaren Workaround.&lt;br /&gt;
Alle anderen Spielereien mit Doxygen zwischen den Makros haben die generierte
&lt;a href=&quot;https://de.wikipedia.org/wiki/Hypertext_Markup_Language&quot;&gt;HTML&lt;/a&gt; Doku nur 
vernudelt.&lt;/p&gt;

&lt;p&gt;Doch mit der Lösung habe ich jetzt endlich etwas funktionierendes, mit dem
ich meine Interface Definitionen auch verständlich dokumentieren kann.&lt;/p&gt;

&lt;p&gt;Denn eigentlich war dieser offene Punkt einer der Gründe, warum ich seit
zwei Jahren die Dokumentation des Projektes immer wieder aufgeschoben habe.
Bisher habe ich nur sporadisch freie C-Funktionen mit Doxygen Kommentaren
versehen.&lt;/p&gt;

&lt;p&gt;Das Schlimme ist … jetzt muss ich meinen hunderten Funktionen auch wirklich
mal eine verständliche Bedeutung zuordnen.&lt;/p&gt;

&lt;p&gt;Doch das ist auch gut … denn damit erfolgt implizit auch ein Code-Review.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>ARM Assembler in MSVC++</title>
   <link href="https://www.opengate.at/blog/2022/06/arm-asm/"/>
   <published>2022-06-18T13:00:00+02:00</published>
   <updated>2022-06-18T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2022/06/arm-asm</id>
   <category term="devel" />
   <summary type="text">Mit meinem neuen ARM-PC und dem 
ebenso neuen Visual Studio 2022 Preview für ARM64 eröffnet sich mir wieder
ein neues Kapitel in der Softwareentwicklung:


  ARM32 und ARM64 Assembly Language.


Denn nun kann ich beides live debuggen.
</summary>
   <content type="html">&lt;p&gt;Mit meinem neuen &lt;a href=&quot;/blog/2022/06/apcsilmic/&quot;&gt;ARM-PC&lt;/a&gt; und dem 
ebenso neuen Visual Studio 2022 Preview für ARM64 eröffnet sich mir wieder
ein neues Kapitel in der Softwareentwicklung:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;ARM32 und ARM64 Assembly Language.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Denn nun kann ich beides live debuggen.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;einrichtung-in-visual-studio&quot;&gt;Einrichtung in Visual Studio&lt;/h3&gt;

&lt;p&gt;Wenn man &lt;code&gt;*.asm&lt;/code&gt; Dateien einem Visual Studio Projekt hinzufügt und
die &lt;code&gt;Build Dependencies&lt;/code&gt; - &lt;code&gt;Build Customizations&lt;/code&gt; - &lt;code&gt;masm Targets&lt;/code&gt;
aktiviert hat, ist lediglich X86 und X64 Support (&lt;code&gt;ml.exe&lt;/code&gt;) verfügbar.&lt;/p&gt;

&lt;p&gt;Für die ARM Entwicklung braucht man aber den ARM Assembler (&lt;code&gt;armasm.exe&lt;/code&gt;)
und dieser kann über den &lt;code&gt;marmasm&lt;/code&gt; Eintrag der 
&lt;code&gt;Visual C++ Build Customization Files&lt;/code&gt; aktiviert werden.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/msvc_marmasm_custombuild.png&quot; alt=&quot;Microsoft ARM Assembler Build Customization&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Hat man in seinem MSVC Projekt parallel auch &lt;code&gt;masm&lt;/code&gt; aktiviert, dann sollte
man für jede Zielplattform die korrekten &lt;code&gt;*.asm&lt;/code&gt; Dateien einschließen und
ihren &lt;code&gt;Item Type&lt;/code&gt; in den &lt;code&gt;Properties&lt;/code&gt; korrekt setzen.&lt;br /&gt;
Dieser lautet dann nämlich &lt;code&gt;Microsoft ARM Assembler&lt;/code&gt; (und nicht wie sonst
&lt;code&gt;Microsoft Macro Assembler&lt;/code&gt;)&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/msvc_marmasm_fileprops.png&quot; alt=&quot;Microsoft ARM Assembler File&quot; /&gt;&lt;/p&gt;

&lt;p&gt;In älteren Varianten von Visual Studio fehlt ein solches Custom-Target.
Hier kann man sich entweder das &lt;code&gt;masm&lt;/code&gt; Target-File hernehmen und anpassen
oder von Anfang an neu erstellen.&lt;br /&gt;
Oder man definiert einen generischen Kommandoaufruf.
Am Ende muss mindestens ein:&lt;br /&gt;
&lt;code&gt;armasm64.exe &quot;path\to\my_code.asm&quot; -o &quot;ARM64\Debug\my_code.obj&quot;&lt;/code&gt;&lt;br /&gt;
dabei herauskommen.&lt;/p&gt;

&lt;h3 id=&quot;noch-kein-direkter-cmake-support&quot;&gt;Noch kein direkter CMake Support&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/CMake&quot;&gt;CMake&lt;/a&gt; unterstützt den MARMASM 
leider noch nicht.&lt;br /&gt;
Es gibt einige Diskussions-Hinweise im Netz darauf, dass im Modul 
&lt;code&gt;CMakeDetermineASM_MASMCompiler.cmake&lt;/code&gt; ein Patch notwendig wäre, weil dort 
nur &lt;code&gt;ML64&lt;/code&gt; und &lt;code&gt;ML&lt;/code&gt; erkannt werden.&lt;/p&gt;

&lt;p&gt;Ich vermute aber, dass Microsoft das in der nächsten Preview, aller-spätestens 
aber mit dem nächsten Visual Studio Produkt nachliefern wird.&lt;/p&gt;

&lt;p&gt;Vorläufig muss ich alle Assembler-Tests manuell einrichten.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Update 2023:&lt;br /&gt;
Ab CMake 3.26 (3.25.2023 nightly builds) ist der Sprachdialekt 
“ASM_MARMASM” enthalten und erzeugt damit alle notwendigen MSVC 
Einstellungen automatisch.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;arm-syntax-ja-nicht-auf-das-leerzeichen-vergessen&quot;&gt;ARM Syntax: Ja nicht auf das Leerzeichen vergessen!&lt;/h3&gt;

&lt;p&gt;Meine ersten Versuche mit kopierten Zeilen aus dem Netz scheiterten
alle mit seltsamen Fehlern wie:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;code&gt;error A2034: unknown opcode: .text&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;wenn die erste Zeile &lt;code&gt;AREA |.text|,CODE,READONLY&lt;/code&gt; übersetzt wird.&lt;/p&gt;

&lt;p&gt;Eine ARM Assembly Language Zeile ist immer nach dem gleichen Schema 
aufgebaut, nämlich:&lt;br /&gt;
&lt;code&gt;{symbol} {instruction|directive|pseudo-instruction} {;comment}&lt;/code&gt;&lt;br /&gt;
Und damit muss jede Zeile entweder mit einer Zeilenmarke anfangen 
(Funktionsnamen oder Sprung-Label),
oder eben mit einem Leerzeichen oder &lt;code&gt;TAB&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-asm highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;;demo.asm: Wrong! No space before directives/instructions
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;AREA |.text|,CODE,READONLY
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;EXPORT my_add_func
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;my_add_func PROC
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;  add x0, x0, x1
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  ret
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;ENDP
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;END
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Direktiven wie &lt;code&gt;AREA&lt;/code&gt;, &lt;code&gt;EXPORT&lt;/code&gt; oder &lt;code&gt;ENDP&lt;/code&gt; und alle CPU Anweisungen müssen 
also immer eingerückt werden:&lt;/p&gt;

&lt;div class=&quot;language-asm highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;  ;demo.asm: Correct! With space before directives/instructions
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;  AREA |.text|,CODE,READONLY  ; location + type of generated code
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  EXPORT my_add_func ;declare &amp;quot;my_add_func&amp;quot; as public function
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;my_add_func PROC  ;&amp;quot;my_add_func&amp;quot; entry-point symbol
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;  add x0, x0, x1  ; ret = param_1 + param2
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  ret             ;ARM return instruction
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;  ENDP            ;end of procedure &amp;quot;my_add_func&amp;quot;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  END            ;end of assembly file
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Kaum hat man es richtig gemacht, lässt sich die Assemblerzeile mit dem ARM64
Assembler übersetzen und aus C++ mit dem Prototyp&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color:#B44;font-weight:bold&quot;&gt;&amp;lt;stdint.h&amp;gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;extern&lt;/span&gt; &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;C&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; intptr_t my_add_func(intptr_t a, intptr_t b);
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;aufrufen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Nun kann ich also meine Stack-Switching-Routinen auch auf ARM Plattformen 
portieren und das wiederrum eröffnet ein weiteres spannendes Feld:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;EFI-Apps auf ARM Hardware&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Doch bis ich mich ausreichend gut mit ARM Assembler Codes auskenne, wird wohl
noch der eine oder andere Test notwendig sein.&lt;br /&gt;
Schließlich habe ich bisher immer nur mit X86 gearbeitet und kenne die
weit gestreuten Möglichkeiten der ARM Architektur noch nicht.&lt;/p&gt;

&lt;p&gt;Zumindest freue ich mich, dass ich jetzt wenigstens alle Windows-Plattformen 
mit Assemblercode beglücken kann.&lt;br /&gt;
Doch auch das wird nicht das Ende sein … denn mein 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Raspberry_Pi&quot;&gt;Raspberry PI&lt;/a&gt; verdient eine 
mindestens genau so gute Linux Abdeckung.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Spaziergang nach Schwechat</title>
   <link href="https://www.opengate.at/blog/2022/06/walk/"/>
   <published>2022-06-16T13:00:00+02:00</published>
   <updated>2022-06-16T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2022/06/walk</id>
   <category term="general" />
   <summary type="text">Ich soll doch mehr Bewegung machen, also dachte ich mir, ich marschiere mal
vom Reumannplatz aus in 
Richtung Simmeringer Hauptstraße und über die gerade aus nach 
Schwechat.

Gesagt … getan … denn das Wetter war herrlich schön.
</summary>
   <content type="html">&lt;p&gt;Ich soll doch mehr Bewegung machen, also dachte ich mir, ich marschiere mal
vom &lt;a href=&quot;https://de.wikipedia.org/wiki/Reumannplatz&quot;&gt;Reumannplatz&lt;/a&gt; aus in 
Richtung Simmeringer Hauptstraße und über die gerade aus nach 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Schwechat&quot;&gt;Schwechat&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Gesagt … getan … denn das Wetter war herrlich schön.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Der uralte Witz:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Habt ihr es schon gehört?&lt;br /&gt;
Über 3 Millionen Tote!&lt;br /&gt;
Wo?&lt;br /&gt;
Am &lt;a href=&quot;https://de.wikipedia.org/wiki/Wiener_Zentralfriedhof&quot;&gt;Wiener Zentralfriedhof&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;kam mir wieder ins Gedächtnis, als ich an den “Toren” des Friedhofs vorbeikam.
Bis heute war ich dort noch nie drinnen und das wird auch noch so bleiben, denn
heute wollte ich ja wo anders hingehen.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/central-graveyard.jpg&quot; alt=&quot;Vienna central graveyard&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Interessant ist nur, das die gesamte Umgebung um den kilometerlangen Friedhof 
mit kleinen Steinmetzbetrieben zugepflastert ist. Da frage ich mich immer, 
ob da nicht zu viel Konkurrenz auf einem Fleck sitzt … aber offenbar nicht.&lt;br /&gt;
Gestorben wird schließlich andauernd.&lt;/p&gt;

&lt;p&gt;Ich dachte eigentlich, dass ich die ganze Zeit der Straßenbahnlinie 6 nachgehe,
den deren Endstation war früher das letzte Tor des Zentralfriedhofs … doch
offenbar hat sich das schon vor Jahren geändert. Der 6er endet nun an der 
Geiereckstraße und die Linie 11 übernimmt die Fahrt zum Friedhof.&lt;/p&gt;

&lt;p&gt;Und nach einem ordentlichen Marsch, sah ich sie dann, die Ortstafel
“Wien Ende”.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/vienna-end.jpg&quot; alt=&quot;Vienna End&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Und nach einer Brücke unmittelbar gefolgt von der Ortstafel “Schwechat”.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/vienna-schwechat.jpg&quot; alt=&quot;Schwechat&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Dann durch die Stadt vorbei an der Veranstaltungshalle “Multiversum”
(mit einer halb guten und halb schlechten Erinnerung).&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/schwechat-multiversum.jpg&quot; alt=&quot;Schwechat Multiversum&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Bis ich endlich am Ziel war: Das Lucky Food, das dortige asiatische
Restaurant, dass ich von einem früheren Besuch in sehr guter Erinnerung hatte.&lt;br /&gt;
Hier gab es ein köstliches Mittagessen zur Stärkung.&lt;/p&gt;

&lt;p&gt;75 Minuten brauchte ich für die etwa 9 bis 10 Kilometern.&lt;/p&gt;

&lt;p&gt;Den Rückweg habe ich etwas abgekürzt, und beim Zentralfriedhof die
Straßenbahn benutzt.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Es war zwar gegen Mittag schon recht heiß geworden, aber in Summe war das
ein entspannender Spaziergang.&lt;/p&gt;

&lt;p&gt;Da hat man Zeit über Gott und die Welt nachzudenken und kann dann 
am Abend zur Abwechslung mal sagen: Heute habe ich genug Bewegung gemacht.&lt;/p&gt;

&lt;p&gt;Ich plane bei gutem Wetter an den kommenden Wochenenden in alle Richtungen 
durch Wien zu laufen, mich an vergangene Ereignisse, Arbeitsorte und Wohnorte 
erinnern.&lt;/p&gt;

&lt;p&gt;Mal sehen wie weit die Motivation über den Sommer hin reicht.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Windows on ARM: APCSILMIC Dot 1 Mini PC</title>
   <link href="https://www.opengate.at/blog/2022/06/apcsilmic/"/>
   <published>2022-06-12T13:00:00+02:00</published>
   <updated>2022-06-12T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2022/06/apcsilmic</id>
   <category term="hardware" />
   <summary type="text">Mit dem Dot 1 Mini PC von APCSILMIC ist nun 
ein alter Traum von mir endlich in Erfüllung gegangen:

  Ein günstiger ARM64 PC mit 
Windows 11 Support für
unter 300 Euro ist auf dem Markt!


Und das Teil ist echt genial, denn mit Windows 11 ARM64 hat man nun ein
Betriebssystem, das alles ausführen kann. x86, x64, ARM32 und ARM64
Windows Binaries, sowie WSL Linux.
</summary>
   <content type="html">&lt;p&gt;Mit dem &lt;code&gt;Dot 1 Mini PC&lt;/code&gt; von &lt;a href=&quot;https://www.apcsilmic.com/&quot;&gt;APCSILMIC&lt;/a&gt; ist nun 
ein alter Traum von mir endlich in Erfüllung gegangen:&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;Ein günstiger &lt;a href=&quot;https://en.wikipedia.org/wiki/AArch64&quot;&gt;ARM64&lt;/a&gt; PC mit 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_11&quot;&gt;Windows 11&lt;/a&gt; Support für
unter 300 Euro ist auf dem Markt!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Und das Teil ist echt genial, denn mit Windows 11 ARM64 hat man nun ein
Betriebssystem, das alles ausführen kann. x86, x64, ARM32 und ARM64
Windows Binaries, sowie WSL Linux.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Ich weiß nicht warum Microsoft mir das Leben so schwer macht.
Bereits im Herbst 2021 wurde ein ARM-Entwickler-System vorgestellt um den
Umstieg auf die ARM Plattform voranzutreiben.&lt;br /&gt;
Doch diese Hardware war nur innerhalb der USA lieferbar.&lt;/p&gt;

&lt;p&gt;Und auf der letzten Build-Veranstaltung von MS wurde ein weiterer ARM
PC angekündigt … der irgendwann erscheinen soll.&lt;/p&gt;

&lt;p&gt;Welch ein Glück, dass es das Unternehmen APCSILMIC gibt, welches ein neues
kostengünstigen ARM PC-Produkt mit Windows 11 anbietet, das mir genau das
bietet, was ich brauche:&lt;br /&gt;
Nämlich eine kostengünstige Hardware, mit der ich endlich ARM64 live nutzen
kann.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/apcsilmic_1.jpg&quot; alt=&quot;APCSILMIC-box&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Mein &lt;a href=&quot;/blog/2021/01/pipo-tablet/&quot;&gt;PIPO W12&lt;/a&gt; Tablet ist bekanntlich
auch ein ARM System, mit dem ich schon viel erforschen konnte, nur leider ist
dieses an Windows 10 gebunden und es gibt noch keinen sicheren Upgrade Pfad 
auf Windows 11 … und weil es eben gut läuft, habe ich etwas Angst es in 
einen unbenutzbaren Zustand zu versetzen.&lt;/p&gt;

&lt;h3 id=&quot;apcsilmic-dot-1-mini-pc&quot;&gt;APCSILMIC: Dot 1 Mini PC&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/apcsilmic_2.jpg&quot; alt=&quot;APCSILMIC-parts&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Mit 3 RAM+SSD-Varianten von 4GB/64GB, 6GB/128GB und 8GB/256GB kann man 
zwischen 220, 250 und 290 Dollar an Gerätekosten wählen.&lt;/p&gt;

&lt;p&gt;Bei allen Varianten gleich sind:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;SC7180 Qualcomm &lt;a href=&quot;https://de.wikipedia.org/wiki/Snapdragon_(Prozessor)&quot;&gt;Snapdragon&lt;/a&gt; 
mit 8 logischen Kernen&lt;/li&gt;
  &lt;li&gt;2x HDMI&lt;/li&gt;
  &lt;li&gt;2x USB 2.0&lt;/li&gt;
  &lt;li&gt;1x USB 1.0&lt;/li&gt;
  &lt;li&gt;100 MBit LAN&lt;/li&gt;
  &lt;li&gt;WLAN (2.4 + 5 GHz)&lt;/li&gt;
  &lt;li&gt;Bluetooth 5.1&lt;/li&gt;
  &lt;li&gt;1x Micro-SD Kartenleser&lt;/li&gt;
  &lt;li&gt;Optional: 1x SIM Karte für 4G Breitband (gegen Aufpreis)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/apcsilmic_3.jpg&quot; alt=&quot;APCSILMIC-front&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Nun, das Gerät ist sicher kein Rennpferd, bietet aber mehr Leistung als 
meine &lt;a href=&quot;https://de.wikipedia.org/wiki/Intel_Atom&quot;&gt;Intel Atoms&lt;/a&gt; mit Baytrail 
Kernen, und verbraucht aber selbst unter Volllast nicht mehr als 8 bis 
9 Watt, im Leerlauf gerade mal 4-5 Watt.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/apcsilmic_4.jpg&quot; alt=&quot;APCSILMIC-back&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Das System ist vollständig ARM64 &lt;a href=&quot;https://de.wikipedia.org/wiki/Unified_Extensible_Firmware_Interface&quot;&gt;UEFI&lt;/a&gt;
tauglich, womit auch der Boot anderer Betriebssysteme neben Windows leicht 
möglich wird.&lt;/p&gt;

&lt;p&gt;Schließlich gibt es viele ARM-Geräte aus China, die den 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Raspberry_Pi&quot;&gt;Raspberry PI&lt;/a&gt; nachahmen,
doch alle nutzen sie proprietäre Bootsequenzen, für die nur veraltete
Linux-Distros existieren.&lt;/p&gt;

&lt;p&gt;Der Dot 1 Mini PC ist dank EFI und Microsoft-Support zukunftssicher.&lt;/p&gt;

&lt;h3 id=&quot;visual-studio-2022-preview&quot;&gt;Visual Studio 2022 Preview&lt;/h3&gt;

&lt;p&gt;Parallel zum Gerät kam in den letzten Tagen 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_Studio#Version_2022&quot;&gt;Visual Studio 2022&lt;/a&gt;
mit nativem &lt;a href=&quot;https://devblogs.microsoft.com/visualstudio/arm64-visual-studio/&quot;&gt;ARM64 Support als Preview&lt;/a&gt; 
ins Netz. Das Studio ist nun voll nativ ARM64-tauglich und lässt mich ARM 
Code direkt auf dem Gerät debuggen.&lt;br /&gt;
Das war mit den Vorgängerversionen (und dem “normalen” VS 2022) nur per 
Remote-Debugging möglich.&lt;/p&gt;

&lt;p&gt;Interessant ist das für mich deshalb, weil ich nun endlich damit beginnen
kann, ARM-Assembler Code zu schreiben, den ich auch durchdebuggen kann.
Zuvor konnte ich nur C/C++ Code kompilieren und dann am Tablet ausführen.&lt;/p&gt;

&lt;p&gt;Die Installation war zugegeben eine Qual und dauerte lange.
Da zeigt sich, dass die Kombination von vielen SSD-Zugriffen eine 
schwache Performance aufweist.&lt;br /&gt;
Doch ist Visual Studio erst einmal installiert lässt es sich 
“wie üblich” nutzen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;Heute braucht jeder Entwickler ein vollwertiges ARM-Gerät!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Denn ohne ein solches kann man seinen nativen Code nicht mehr live testen.&lt;/p&gt;

&lt;p&gt;Ich spreche hier keine Werbeempfehlungen aus, sondern wünsche mir, dass in
jedem Supermarkt heute ein ARM PC angeboten wird.&lt;br /&gt;
Doch leider ist das noch nicht so und der “Dot 1 Mini PC” war das einzige
Gerät, das finden konnte, das Windows-11 kompatibel ist und sofort geliefert
werden konnte.&lt;/p&gt;

&lt;p&gt;Die Webseite wirkt zugegeben etwas “quick-and-dirty” zusammengeschustert.
Und als ich meine Bestellbestätigung erhielt und den enthaltenen Link anklickte,
so verwies der zu einer nicht mehr gültigen Domain.&lt;br /&gt;
Ich dachte schon fast, ich wäre einem Betrug zum Opfer gefallen, doch
das Paket-Tracking bestätigte, dass meine Hardware auf dem Weg war.&lt;/p&gt;

&lt;p&gt;Und nach 3 Wochen wurde der PC bei mir geliefert und startet “out-of-the-box”
ohne Probleme.&lt;/p&gt;

&lt;p&gt;Ich liebe das Teil nun sehr und denke, es ist wie damals vor 15 Jahren beim
Switch zu x64 ein ganz wichtiger Technologiewechsel, den ich mit dem
Mini PC nun bei mir fortführen kann.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Linux hasst static binaries</title>
   <link href="https://www.opengate.at/blog/2022/06/static/"/>
   <published>2022-06-12T13:00:00+02:00</published>
   <updated>2022-06-12T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2022/06/static</id>
   <category term="devel" />
   <summary type="text">Ich staune immer wieder darüber, wie etwas so “einfaches” wie statisch 
Abhängigkeiten unter Linux so schwer 
bzw. unmöglich gemacht werden.

Denn eigentlich sind Programme mit dem Compiler Flag -static etwas ganz
Tolles … denn sie laufen unter jedem Linux-System (naja, zumindest unter
vielen davon) ohne dass man Bibliotheken nachinstallieren muss.

… doch dann fangen die Probleme an.
</summary>
   <content type="html">&lt;p&gt;Ich staune immer wieder darüber, wie etwas so “einfaches” wie statisch 
Abhängigkeiten unter &lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt; so schwer 
bzw. unmöglich gemacht werden.&lt;/p&gt;

&lt;p&gt;Denn eigentlich sind Programme mit dem Compiler Flag &lt;code&gt;-static&lt;/code&gt; etwas ganz
Tolles … denn sie laufen unter jedem Linux-System (naja, zumindest unter
vielen davon) ohne dass man Bibliotheken nachinstallieren muss.&lt;/p&gt;

&lt;p&gt;… doch dann fangen die Probleme an.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Es geht wieder mal um die alte Geschichte:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ich hätte gerne (so wie unter &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows&quot;&gt;Windows&lt;/a&gt;) 
ein Programm, dass ich einfach auf ein Zielsystem kopiere und es dort 
ohne weitere Schritte läuft.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In Windows kompiliert man eine solche EXE gegen die statische Version der 
C-Runtime und achtet darauf, andere Nicht-OS-Libs ebenso statisch zu linken.&lt;/p&gt;

&lt;p&gt;Am Ende hat man eine etwas größere, dafür aber unabhängige EXE, die in jeder
Windows-Variante läuft.&lt;/p&gt;

&lt;p&gt;In der Linux GCC-Welt gibt es ein solches Compiler-Feature auch, und es heißt 
&lt;code&gt;-static&lt;/code&gt;. Mit diesem Flag werden alle sonst dynamisch gelinkten Bibliotheken
wie &lt;code&gt;pthread&lt;/code&gt;, &lt;code&gt;dl&lt;/code&gt; oder &lt;code&gt;libc&lt;/code&gt; statisch in das Binary eingebunden.&lt;/p&gt;

&lt;p&gt;Theoretisch kann man ein solches auf &lt;a href=&quot;https://de.wikipedia.org/wiki/Ubuntu&quot;&gt;Ubuntu&lt;/a&gt;
erstelltest Binary nehmen und auf &lt;a href=&quot;https://de.wikipedia.org/wiki/OpenSUSE&quot;&gt;OpenSUSE&lt;/a&gt; 
oder &lt;a href=&quot;https://de.wikipedia.org/wiki/Alpine_Linux&quot;&gt;Alpine&lt;/a&gt; ausführen.
Und bei einfachen Hello-World Apps funktioniert das auch wunderbar.&lt;/p&gt;

&lt;h3 id=&quot;problem-dl-dynamic-linker&quot;&gt;Problem “dl”: Dynamic Linker&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;http://linux.die.net/man/3/dlopen&quot;&gt;&lt;code&gt;dlopen&lt;/code&gt; und &lt;code&gt;dlsym&lt;/code&gt;&lt;/a&gt; sind in Linux kein 
Betriebssystem-Feature wie es 
&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryw&quot;&gt;&lt;code&gt;LoadLibrary&lt;/code&gt; und &lt;code&gt;GetProcAddress&lt;/code&gt;&lt;/a&gt; 
unter Windows sind, sondern werden von der Bibliothek &lt;code&gt;dl&lt;/code&gt; nachgeliefert.&lt;br /&gt;
Zusätzlich ist der Startup-Code der C-Bibliothek darauf ausgerichtet,
Datenblöcke beim Start durchzulaufen, die der Compiler/Linker eingefügt hat,
um dynamische Bibliotheken zu öffnen (&lt;code&gt;open&lt;/code&gt;) und in den Prozessraum zu
laden (&lt;code&gt;mmap&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Mit &lt;code&gt;-static&lt;/code&gt; wird diese Prozedur umgangen und der Compiler sucht von allen
notwendigen Bibliotheken die statische Variante und fügt sie in die finale
Binärdatei ein.&lt;/p&gt;

&lt;p&gt;In einem solchen Binary sind “dynamische” Features nicht mehr vorhanden und
auch &lt;code&gt;dlopen&lt;/code&gt; wird zu einer Funktion, die nichts mehr tun kann und mit einer
“not-supported” Meldung abbricht.&lt;/p&gt;

&lt;p&gt;Bislang ist es mir nicht gelungen eine allgemeine Verwendung von &lt;code&gt;dlopen()&lt;/code&gt;
mit &lt;code&gt;-static&lt;/code&gt; zu finden, die auf allen Plattformen lauffähig wäre.&lt;/p&gt;

&lt;p&gt;Meine Debian-Derivate melden dann durch eine Warnung, dass man jetzt nur noch
jene Bibliotheken dynamisch laden kann, die mit der gleichen Version der
&lt;code&gt;glibc&lt;/code&gt; erstellt wurden.&lt;br /&gt;
Und Alpine Linux liefert den erwähnten &lt;code&gt;Not-Supported&lt;/code&gt; Errorcode.&lt;/p&gt;

&lt;h3 id=&quot;nicht--static-aber--bstatic&quot;&gt;Nicht &lt;code&gt;-static&lt;/code&gt; aber &lt;code&gt;-BStatic&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;Alternativ kann man ein Binary auch &lt;code&gt;-dynamic&lt;/code&gt; kompilieren (der Default-Fall 
und das Gegenteil von &lt;code&gt;-static&lt;/code&gt;) und dann aber beim Linken auf statische
Versionen der notwendigen Bibliotheken verweisen.&lt;/p&gt;

&lt;p&gt;In &lt;a href=&quot;https://de.wikipedia.org/wiki/CMake&quot;&gt;CMake&lt;/a&gt; ging das mit Linker-Flags wie:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;-Wl,-Bstatic -lc&lt;/code&gt;&lt;br /&gt;
linkt die C-Runtime statisch&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;-Wl,-Bstatic -lpthread&lt;/code&gt;&lt;br /&gt;
linkt &lt;code&gt;pthread&lt;/code&gt; statisch&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;-Wl,-Bstatic -ldl&lt;/code&gt;&lt;br /&gt;
linkt &lt;code&gt;dl&lt;/code&gt; statisch&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Hier steckt der Teufel wieder im Detail, was man wo darf und was wo nicht.&lt;/p&gt;

&lt;p&gt;Am Ende fand ich aber auch hier keine Variante, die “portable” Binaries
für mehrere Linux-Varianten ermöglichte.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ich bleibe also bei “dynamischen” Binaries, weil das GATE Framework eben von
anderen externen Bibliotheken abhängig ist.&lt;br /&gt;
Ginge es ausschließlich um C-Runtime Funktionen wäre vielleicht ein Möglichkeit
offen reine statische und portable Binaries zu erzeugen, doch die Kombination 
mit &lt;code&gt;dl*&lt;/code&gt; Funktionen schließt diese Option (aus meiner aktuellen Sicht) aus.&lt;/p&gt;

&lt;p&gt;Gelernt habe ich allerdings, dass die &lt;code&gt;glibc&lt;/code&gt; einigermaßen kompatibel 
geblieben ist und so kann ich ein Binary, das mit &lt;code&gt;GCC5&lt;/code&gt; unter &lt;code&gt;Ubuntu 16.04&lt;/code&gt;
gebaut wurde, auch in den Folgeversion (Ubuntu 22.04), Debian und OpenSUSE
ohne weitere Installationen nutzen.&lt;/p&gt;

&lt;p&gt;Ich muss daher in Zukunft bei Linux nicht Distributionen unterscheiden,
sondern deren Bindung an lib-c Implementierungen.&lt;br /&gt;
Und da kenne ich aktuell eben nur &lt;code&gt;glibc&lt;/code&gt; und &lt;code&gt;musl-libc&lt;/code&gt;.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>printf() Marke Eigenbau</title>
   <link href="https://www.opengate.at/blog/2022/06/printf/"/>
   <published>2022-06-05T13:00:00+02:00</published>
   <updated>2022-06-05T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2022/06/printf</id>
   <category term="devel" />
   <summary type="text">
  Und Schuld hat libsupc++ …


… dass ich jetzt auch noch printf() 
und seine Freunde nachbauen darf.

Und so beginnt ein weiterer Tag meiner Reise ins EFI-Land.
</summary>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;Und Schuld hat &lt;a href=&quot;https://wiki.osdev.org/Libsupcxx&quot;&gt;&lt;code&gt;libsupc++&lt;/code&gt;&lt;/a&gt; …&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;… dass ich jetzt auch noch &lt;a href=&quot;http://cplusplus.com/reference/cstdio/printf/&quot;&gt;&lt;code&gt;printf()&lt;/code&gt;&lt;/a&gt; 
und seine Freunde nachbauen darf.&lt;/p&gt;

&lt;p&gt;Und so beginnt ein weiterer Tag meiner Reise ins EFI-Land.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;blockquote&gt;
  &lt;p&gt;Mit dem &lt;a href=&quot;https://de.wikipedia.org/wiki/GNU_Compiler_Collection&quot;&gt;GCC&lt;/a&gt; werden 
&lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B&quot;&gt;C++&lt;/a&gt; Exceptions in 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Unified_Extensible_Firmware_Interface&quot;&gt;EFI&lt;/a&gt; 
Apps kein Problem mehr sein.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;dachte ich. Tja, falsch gedacht.&lt;/p&gt;

&lt;p&gt;Das alte Problem, dass C++ Exception Handler und &lt;code&gt;RTTI&lt;/code&gt; jede Menge im
Hintergrund ausführen, der in der C-Runtime verankert ist, verfolgt mich
nun nicht nur am &lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_C%2B%2B&quot;&gt;MSVC&lt;/a&gt; 
sondern auch im GCC Build.&lt;/p&gt;

&lt;p&gt;Grundsätzlich gibt es dort zwar eine Trennung von Kernfunktionen und
Runtime-Zusätzen. Und zwar bietet die &lt;code&gt;libsupc++&lt;/code&gt; einige Basis 
Unwinding-Routinen an, doch diese greifen auf jede Menge C Funktionen
zu, die es in nativen EFI Apps nicht gibt.&lt;/p&gt;

&lt;p&gt;In Foren ließt man dann, man könnte die Bibliothek und Teile der
&lt;code&gt;glibc&lt;/code&gt; anpassen und sich neu zusammenkompilieren, doch dann schaffe 
ich wieder Code, der im MSVC explizit ausgeblendet werden muss.&lt;/p&gt;

&lt;h3 id=&quot;unabhängige-printf-sprintf-und-fprintf-funktionen&quot;&gt;Unabhängige printf(), sprintf() und fprintf() Funktionen&lt;/h3&gt;

&lt;p&gt;Das Problem sind tiefe Verschachtelungen zwischen String-Funktionen
und den Betriebssystem-Primitiven.&lt;/p&gt;

&lt;p&gt;Wenn eine &lt;code&gt;printf()&lt;/code&gt; Implementierung direkt ein &lt;code&gt;write&lt;/code&gt; auf &lt;code&gt;STDOUT&lt;/code&gt;
beinhaltet, ist das zwar effizient, aber nur 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Portable_Operating_System_Interface&quot;&gt;POSIX&lt;/a&gt;
oder Linux tauglich.
Das gleiche gilt dann auch für die WinAPI am MSVC.&lt;br /&gt;
Und schlimmer wird es, wenn im Code dann noch Compiler-spezifische
Erweiterungen benutzt werden.&lt;/p&gt;

&lt;p&gt;Ich brauche also ein &lt;code&gt;printf()&lt;/code&gt;, das Zeichen für Zeichen an einen Callback
schickt. Und dieser Callback kann dann einfach an EFI oder etwas
anderes angepasst werden. &lt;code&gt;sprintf()&lt;/code&gt; und &lt;code&gt;fprintf()&lt;/code&gt; funktionieren
genau so, nur dass noch ein Parameter angefügt wird, der eine Referenz
zum String oder zum FILE Objekt mitführt.&lt;/p&gt;

&lt;p&gt;Und eben mit dieser Aufgabe werde ich wohl etwas Zeit verbringen müssen,
denn erst wenn man seine Implementierung startet, merkt man, dass
&lt;code&gt;printf&lt;/code&gt; gar nicht so “unkomplex” ist, wenn die unterschiedlichen
Format-Spezifizierer kombiniert werden müssen.&lt;/p&gt;

&lt;h3 id=&quot;und-wozu-das-ganze&quot;&gt;Und wozu das Ganze?&lt;/h3&gt;

&lt;p&gt;Der GCC produziert interne Funktionen für z.B. &lt;code&gt;purecall&lt;/code&gt; oder cast Fehler und
diese nutzen offenbar &lt;code&gt;printf()&lt;/code&gt; und &lt;code&gt;fprintf()&lt;/code&gt; und &lt;code&gt;sprintf()&lt;/code&gt; um Debugging 
Nachrichten auf die Konsole zu schreiben.&lt;/p&gt;

&lt;p&gt;Und dann wird beim Linken sichtbar, dass das &lt;code&gt;unresolvable symbol printf&lt;/code&gt;
nicht in &lt;code&gt;cxx_purecall_xyz&lt;/code&gt; aufgerufen werden kann.&lt;/p&gt;

&lt;p&gt;Während es mir (mehr oder weniger) gelungen ist, andere Bibliotheken von 
&lt;code&gt;zlib&lt;/code&gt; bis zur &lt;code&gt;libjpeg&lt;/code&gt; so abzuspecken, dass sie nur noch ihre Algorithmen
umsetzen und keine OS-Funktionen aufrufen, zwingt mich jetzt ausgerechnet 
der C++ Compiler selbst, diese C-Schnittstelle auch in EFI nachzubauen.&lt;/p&gt;

&lt;p&gt;Die Bibliothek &lt;a href=&quot;https://wiki.osdev.org/GNU-EFI&quot;&gt;GNU-EFI&lt;/a&gt; hätte zwar eine 
eigene &lt;code&gt;Print()&lt;/code&gt; Implementierung, doch diese arbeitet nur mit &lt;code&gt;wchar_t&lt;/code&gt; und 
unterstützt nicht alle Refinessen von &lt;code&gt;printf()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Mich enttäuscht daher, dass sich dieses Verhalten nicht “leichter” 
abschalten lässt.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Aber etwas Gutes hat es am Ende:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Früher oder später habe ich die Sourcen für einen kleinen
Betriebssystemkern beieinander.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Denn wenn man alle STD-C Funktionen selbst implementiert hat, kann man viele
Fremdprogramme damit neu kompilieren und sie über die “eigene Schnittstelle”
laufen lassen.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Erdbeeren++</title>
   <link href="https://www.opengate.at/blog/2022/06/strawberry-pp/"/>
   <published>2022-06-04T13:00:00+02:00</published>
   <updated>2022-06-04T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2022/06/strawberry-pp</id>
   <category term="general" />
   <summary type="text">Neben Schokolade sind Erdbeeren schon seit eh und je eine meiner Schwächen.
Tatsächlich verbinde ich damit aber viele schöne Erinnerungen an meine
Kindheit.

Und obwohl die Preise für das schmackhafte Obst nicht gerade niedrig sind,
fällt es mir schwer am Supermarkt vorbei zu gehen ohne eine Schale 
mitzunehmen.
</summary>
   <content type="html">&lt;p&gt;Neben Schokolade sind Erdbeeren schon seit eh und je eine meiner Schwächen.
Tatsächlich verbinde ich damit aber viele schöne Erinnerungen an meine
Kindheit.&lt;/p&gt;

&lt;p&gt;Und obwohl die Preise für das schmackhafte Obst nicht gerade niedrig sind,
fällt es mir schwer am Supermarkt vorbei zu gehen ohne eine Schale 
mitzunehmen.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;erdbeeren&quot;&gt;Erdbeeren&lt;/h3&gt;

&lt;p&gt;Ein Fixpunkt in den Sommerferien war früher für mich die jährliche Fahrt
“zum Erdbeerfeld”.&lt;br /&gt;
Dort konnte man auf ausgedehnten Erdbeerstreifen selbst den einen oder 
anderen Eimer vollpflücken und dann die Kilomenge bezahlen.&lt;/p&gt;

&lt;p&gt;Was man zwischendurch verspeiste, blieb natürlich unverrechnet und so
erinnere ich mich bis heute an die Zeit, als ich mit Mutter, Großmutter
und weiterer Verwandtschaft zum Erdbeerfeld fuhr und dort Vorräte
“abbaute”.&lt;/p&gt;

&lt;p&gt;Unvergesslich bleibt da die Erinnerung, als meine Tante meiner kleinen
Kusine mehrfach erklärte:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Die Roten kommen in den Kübel.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Doch diese steckte die roten Beeren zielsicher in den Mund und streute
die unreifen grünen Beeren in den Eimer.&lt;/p&gt;

&lt;h3 id=&quot;wald-erdbeeren&quot;&gt;Wald-Erdbeeren&lt;/h3&gt;

&lt;p&gt;Noch besser als gewöhnliche Erdbeeren sind &lt;a href=&quot;https://de.wikipedia.org/wiki/Wald-Erdbeere&quot;&gt;Wald-Erdbeeren&lt;/a&gt;, doch diese Delikatesse findet man heute leider nicht im Supermarkt.&lt;/p&gt;

&lt;p&gt;Die kleinen Beerchen haben das best mögliche Aroma, das man sich vorstellen
kann und mit der Aufgabe “Walderdbeeren suchen” schaffte es meine 
Großmutter stets auch meine faulen Beine in Richtung Wald laufen zu lassen.&lt;/p&gt;

&lt;p&gt;Da Wald-Erdbeeren sehr klein sind und nur an bestimmten Stellen zu finden
waren, dauerte es lange, bis man eine kleine Schale von ihnen beisammen hatte.&lt;/p&gt;

&lt;p&gt;Doch sie sofort zu Essen wäre eine Sünde gewesen, denn Großmutter wusste etwas
besseres: 
Sie zerdrückte die Beeren und rührte sie mit Sauerrahm und etwas Süßstoff
zum schmackhaftesten Leckerbissen überhaupt.&lt;br /&gt;
Kein Joghurt, Shake, oder Eischreme weder im Handel und noch im Restaurant
oder an der Bar konnte mir je wieder so eine Gaumenfreude bereiten, wie
Großmutters Walderdbeeren-Rezept.&lt;/p&gt;

&lt;p&gt;Ach ich vermisse diese Zeit … denn solche Gourmetstücke kennt man nur,
wenn man am Land aufgewachsen ist. 
Zwar schätze ich die Warenvielfalt in den Wiener Läden, aber an Großmutters
Walderdbeeren kommt einfach niemand heran.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Und so kommt es, dass ich auch heute vor allem im Sommer an vielen
Arbeitstagen die Erdbeerschale mit ins Büro nehme und dann Stück 
für Stück wegputze.&lt;/p&gt;

&lt;p&gt;Es gilt der klassische Ablauf:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;ol&gt;
    &lt;li&gt;Write a C++ line&lt;/li&gt;
    &lt;li&gt;Eat a strawberry&lt;/li&gt;
    &lt;li&gt;Goto 1&lt;/li&gt;
  &lt;/ol&gt;
&lt;/blockquote&gt;

&lt;p&gt;Es ist zwar ärgerlich, wenn man den Genuss auch an der “klebrigen”
Tastatur erleben darf … aber für Erdbeeren muss man auch ein
paar Opfer bringen.&lt;/p&gt;

&lt;p&gt;Mahlzeit!&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/strawberry_pp.jpg&quot; alt=&quot;Strawberry++&quot; /&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Kein Safe-Bool Idiom?</title>
   <link href="https://www.opengate.at/blog/2022/05/safebool/"/>
   <published>2022-05-29T13:00:00+02:00</published>
   <updated>2022-05-29T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2022/05/safebool</id>
   <category term="devel" />
   <summary type="text">Das Safe-Bool Idiom 
wurde früher jedem eingetrichtert, der daran dachte eigene
Smart-Pointer Strukturen 
zu bilden.

Doch plötzlich, mit dem Aufkommen von C++11 
und seinen Nachfolgern, verschwand dieses Mysterium wieder …
</summary>
   <content type="html">&lt;p&gt;Das &lt;a href=&quot;http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Safe_bool&quot;&gt;Safe-Bool Idiom&lt;/a&gt; 
wurde früher jedem eingetrichtert, der daran dachte eigene
&lt;a href=&quot;https://de.wikipedia.org/wiki/Intelligenter_Zeiger&quot;&gt;Smart-Pointer&lt;/a&gt; Strukturen 
zu bilden.&lt;/p&gt;

&lt;p&gt;Doch plötzlich, mit dem Aufkommen von &lt;a href=&quot;https://en.wikipedia.org/wiki/C%2B%2B11&quot;&gt;C++11&lt;/a&gt; 
und seinen Nachfolgern, verschwand dieses Mysterium wieder …
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Objekte sind (besonders im System-nahen Bereich) oft nur Wrapper um native 
Konstrukte (z.B. aus der &lt;a href=&quot;https://de.wikipedia.org/wiki/C_(Programmiersprache)&quot;&gt;C Welt&lt;/a&gt;).&lt;br /&gt;
Man nennt solche Dinge auch gerne “Smart-Handles” als Anlehnung an 
Smart-Pointer und viele von ihnen haben die Eigenschaft, dass sie auch 
“leer” oder “ungültig” sein können.&lt;/p&gt;

&lt;p&gt;Und deshalb hätte man gerne, dass solche Objekte möglichst einfach
“ausge-&lt;code&gt;if&lt;/code&gt;-t” werden können, so wie das hier:&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;HandleWrapper handle;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;...
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt;(handle)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  do_something_with(handle);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;}
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;else&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;throw&lt;/span&gt; std::runtime_error(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Nothing to do&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Das ist eigentlich alles kein Problem, denn da schreibt man einfach:&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;HandleWrapper&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;public&lt;/span&gt;:
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;bool&lt;/span&gt; empty() &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  {
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; my_secret_impl() ? &lt;span style=&quot;color:#069&quot;&gt;true&lt;/span&gt; : &lt;span style=&quot;color:#069&quot;&gt;false&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  }
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;operator&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;bool&lt;/span&gt;() &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; !&lt;span style=&quot;color:#950&quot;&gt;this&lt;/span&gt;-&amp;gt;empty();
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;  }    
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;};
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Und schon klappt der &lt;code&gt;if&lt;/code&gt; Aufruf.&lt;/p&gt;

&lt;p&gt;Doch unglücklicherweise klappt dann noch viel mehr, wie z.B.:&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;bool&lt;/span&gt; b = handle;     &lt;span style=&quot;color:#777&quot;&gt;// handle -&amp;gt; bool&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; i = &lt;span style=&quot;color:#00D&quot;&gt;42&lt;/span&gt; + handle; &lt;span style=&quot;color:#777&quot;&gt;// handle -&amp;gt; bool -&amp;gt; int(1)&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt; foo(&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;long&lt;/span&gt; l);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;foo(handle);           &lt;span style=&quot;color:#777&quot;&gt;// handle -&amp;gt; bool -&amp;gt; long(1)&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt;(handle == handle2); &lt;span style=&quot;color:#777&quot;&gt;// (handle -&amp;gt; bool) == (handle2 -&amp;gt; bool)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Und schon regiert das absolute Chaos.&lt;/p&gt;

&lt;h3 id=&quot;safe-bool-über-exotische-pointer&quot;&gt;Safe Bool über exotische Pointer&lt;/h3&gt;

&lt;p&gt;Weil &lt;code&gt;bool&lt;/code&gt; sich in jeden anderen Integer konvertieren lässt, kam der Gedanke
auf, dass man einen anderen Typen braucht, der auch gegen &lt;code&gt;true&lt;/code&gt; / &lt;code&gt;false&lt;/code&gt;
auswertbar ist aber nicht automatisch in Rechnungen oder Vergleichen aktiv 
wird.&lt;/p&gt;

&lt;p&gt;Die Lösung fand man in einem an den Typen gebunden Methoden-Pointer, der
im &lt;code&gt;true&lt;/code&gt; Fall auf eine existierende private Methode zeigt, und im &lt;code&gt;false&lt;/code&gt;
Fall ein &lt;code&gt;NULL&lt;/code&gt;-Pointer wird.&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;HandleWrapper&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;private&lt;/span&gt;:
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt; useless_function() &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt; 
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  {    
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;  }
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;public&lt;/span&gt;:
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;typedef&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;(HandleWrapper::*safe_bool_type)() &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;operator&lt;/span&gt; safe_bool_type() &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;  {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color:#950&quot;&gt;this&lt;/span&gt;-&amp;gt;empty() ? &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt; : &amp;amp;HandleWrapper::useless_function;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;  }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;};
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Unser &lt;code&gt;if(handle)&lt;/code&gt; findet dann einen “primitiven” Pointer-Typen, der 
ausge-&lt;code&gt;if&lt;/code&gt;-t werden kann und nutzt ihn “implizit”.&lt;/p&gt;

&lt;p&gt;Wenn man das ganze jetzt noch in eine Template-Klasse wirft, die als 
Basisklasse eines “aus-&lt;code&gt;if&lt;/code&gt;-barem” Objektes genutzt wird, landet man bei der
Implementierung, die ich im GATE Framework immer noch einsetze um C++98/03 
kompatibel zu sein.&lt;br /&gt;
Man kann z.B.: den safe-bool cast immer auf &lt;code&gt;operator!()&lt;/code&gt; umleiten und diesen
implementieren.&lt;br /&gt;
Dann hat man sowohl &lt;code&gt;if(x)&lt;/code&gt; und &lt;code&gt;if(!x)&lt;/code&gt; erledigt:&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;template&lt;/span&gt;&amp;lt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;T&lt;/span&gt;&amp;gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;SafeBoolBase&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;private&lt;/span&gt;:
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt; safe_bool_method() &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt; { }
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;public&lt;/span&gt;:
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;typedef&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;(SafeBoolBase::*bool_type)() &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;operator&lt;/span&gt; bool_type() &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;    T &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt;&amp;amp; derived_impl = *&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;static_cast&lt;/span&gt;&amp;lt;T &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt;*&amp;gt;(&lt;span style=&quot;color:#950&quot;&gt;this&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; !derived_impl ? &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt; : &amp;amp;SafeBoolBase&amp;lt;T&amp;gt;::safe_bool_method;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;  }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;};
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;MyIfableType&lt;/span&gt; : &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;public&lt;/span&gt; SafeBoolBase&amp;lt;MyIfableType&amp;gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;public&lt;/span&gt;:
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;bool&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;operator&lt;/span&gt;!() &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n21&quot; name=&quot;n21&quot;&gt;21&lt;/a&gt;&lt;/span&gt;    ...
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n22&quot; name=&quot;n22&quot;&gt;22&lt;/a&gt;&lt;/span&gt;  }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n23&quot; name=&quot;n23&quot;&gt;23&lt;/a&gt;&lt;/span&gt;};
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h3 id=&quot;c11-und-explicit-operator-bool&quot;&gt;C++11 und explicit operator bool()&lt;/h3&gt;

&lt;p&gt;In C++11 ist dieser verdrehte Pointer-Kunstgriff nicht mehr notwendig, denn
eine Funktion &lt;code&gt;explicit operator bool() const&lt;/code&gt; bedient nur noch wirklich 
explizit casts oder eben &lt;code&gt;if(x)&lt;/code&gt;, lässt aber Rechnungen oder Vergleiche
hart abblitzen.&lt;/p&gt;

&lt;p&gt;Vor C++11 war &lt;code&gt;explicit&lt;/code&gt; nur dem Konstruktor vorbehalten und konnte nicht auf
Operatorfunktionen angewendet werden. Konvertierungen waren damals also immer 
“implizit”.&lt;/p&gt;

&lt;p&gt;Die explizite Operatorfunktion macht sogar den &lt;code&gt;bool operator!() const&lt;/code&gt; in
einige Szenarien unnötig, denn ein&lt;br /&gt;
&lt;code&gt;if(!x)&lt;/code&gt; landet ebenfalls im &lt;code&gt;explicit operator bool() const&lt;/code&gt; und dreht sein
Ergebnis einfach um.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Das Safe-Bool Idiom gerät bereits in Vergessenheit, denn junge Programmierer 
kennen es schlicht weg nicht.&lt;/p&gt;

&lt;p&gt;Und obwohl ich die Eleganz des neueren Standards hier sehr schätze, hat das
Safe-Bool Idiom trotzdem einen hohen Lehrwert:&lt;br /&gt;
Genau weil ich damals vor 15 Jahren über implizite Konvertierungen
von &lt;code&gt;operator bool&lt;/code&gt; gestolpert bin, wurden mir viele Details des Typensystems 
bewusst, die einem sonst verborgen bleiben.&lt;/p&gt;

&lt;p&gt;Daher meine Empfehlung an alle:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Lernt beide Welten kennen!&lt;br /&gt;
Die alte wie die neue.&lt;br /&gt;
Nur so kann man Verständnis und eine bessere Zukunft aufbauen.&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>5.25 Floppy Disks</title>
   <link href="https://www.opengate.at/blog/2022/05/floppy-525/"/>
   <published>2022-05-28T13:00:00+02:00</published>
   <updated>2022-05-28T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2022/05/floppy-525</id>
   <category term="hardware" /><category term="retro" />
   <summary type="text">5.25 Zoll Disketten sind die ältesten
Computer-Medien, die ich besitze. Und aus gegebenem Anlass hatte ich 
(nach 20 Jahren) wieder mal Lust und Laune, meinen alten Rechner mit 
IDE und Diskettenanschlüssen zu 
aktivieren und meine 5.25er durchzuprobieren.
</summary>
   <content type="html">&lt;p&gt;5.25 Zoll &lt;a href=&quot;https://de.wikipedia.org/wiki/Diskette&quot;&gt;Disketten&lt;/a&gt; sind die ältesten
Computer-Medien, die ich besitze. Und aus gegebenem Anlass hatte ich 
(nach 20 Jahren) wieder mal Lust und Laune, meinen alten Rechner mit 
&lt;a href=&quot;https://de.wikipedia.org/wiki/ATA/ATAPI&quot;&gt;IDE&lt;/a&gt; und Diskettenanschlüssen zu 
aktivieren und meine 5.25er durchzuprobieren.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Dass ich mit 5.25 Zoll Disketten überhaupt noch in Kontakt gekommen bin, 
lag an meiner stets gebrauchten veralteten Hardware und so stand Mitte der
90er Jahre mein erster PC auf dem Tisch, der eigentlich in die 80er gehörte:&lt;br /&gt;
Ein &lt;a href=&quot;https://de.wikipedia.org/wiki/AMD_Am386&quot;&gt;80386 Klon&lt;/a&gt; mit einem 3.5 Zoll 
und einem 5.25 Zoll Laufwerk.&lt;/p&gt;

&lt;p&gt;Und genau dieses 5.25 Zoll Laufwerk hat in den Folgejahren in mehreren 
Gehäusen gedient, und hängt aktuell an meinem 
&lt;a href=&quot;https://de.wikipedia.org/wiki/AMD_Athlon_XP&quot;&gt;Athlon XP&lt;/a&gt; 2600 aus der frühen
Mitte der 2000er.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/floppy-disk-drive-525-top.jpg&quot; alt=&quot;5.25 floppy drive top&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Meine ersten &lt;a href=&quot;https://de.wikipedia.org/wiki/QBasic&quot;&gt;QBasic&lt;/a&gt; Programme wurden 
darüber auf den “großen dünnen” Disketten gespeichert, die damals ein wenig 
billiger waren, als die “modernen” 3.5 Zoll Nachfolger.&lt;/p&gt;

&lt;p&gt;Und als meine alte Schule anfing, ihren Diskettenvorrat ihrer noch älteren 
&lt;a href=&quot;https://de.wikipedia.org/wiki/IBM_Personal_Computer&quot;&gt;IBM 8086 Systeme&lt;/a&gt; zu 
entsorgen, fing ich einige davon vor der Mülltonne ab.&lt;/p&gt;

&lt;h3 id=&quot;laufwerk&quot;&gt;Laufwerk&lt;/h3&gt;

&lt;p&gt;Das massive Laufwerk belegt gleich viel Raum wie ein klassisches 5.25 Zoll 
&lt;a href=&quot;https://de.wikipedia.org/wiki/CD-ROM-Laufwerk&quot;&gt;CD/DVD Laufwerk&lt;/a&gt; und wird
über einen alten Molex Stecker (12V und 5V) mit Strom versorgt.
Der Slot-Anschluss unterscheidet sich sehr von den neueren IDE-Anschlüssen,
die über Pin-Stecker mit dem Kabel zum Mainboard verbunden werden.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/floppy-disk-drive-525-back.jpg&quot; alt=&quot;5.25 floppy drive back&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Früher gab es dafür eigene erweiterte Diskettenanschluss-Flachkabel, die für
jedes der beiden möglichen Laufwerke zwei Anschlüsse bereitstellte 
(also in Summe 4 Stecker).&lt;/p&gt;

&lt;p&gt;Eine eingelegte Diskette musste mit einer Klappe “fixiert” werden. Diese 
Klappe senkte nämlich den Lese-Schreibkopf und den Motor herab, damit er
die Diskettenscheibe bewegt und bearbeitet werden konnte.&lt;br /&gt;
Gleichzeitig verhinderte sie, dass die Diskette im laufenden Betrieb 
wieder entfernt werden konnte.&lt;/p&gt;

&lt;p&gt;Man musste stets die Klappe öffnen um das Medium wieder entfernen zu können.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/floppy-disk-drive-525-front.jpg&quot; alt=&quot;5.25 floppy drive front&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Ein ganz besonderes Merkmal dieser Laufwerke war ihre Betriebslautstärke.
Denn sobald ein Datenträgerzugriff erfolgte, startete hörbar der Motor und dann
vernahm man krachende Geräusche, wenn der Lese/Schreibkopf vor und zurückbewegt
wurde.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/floppy-disk-drive-525-bottom.jpg&quot; alt=&quot;5.25 floppy drive bottom&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Man konnte stets hören, was das Laufwerk gerade tat.
Wurden Daten sequentiell von vorne nach hinten gelesen oder die Diskette formatiert,
glich das Geräusch einem Metronom, wo ein lautes Ticken den (kleinen) Spurwechsel in
regelmäßigen Intervallen andeutete.&lt;/p&gt;

&lt;p&gt;Freie Zugriffe im Dateisystem “ratterten” lauter und ungleichmäßig, wenn der Kopf
zwischen vielen Spuren mal weiter mal kürzer bewegt wurde.&lt;br /&gt;
Das Öffnen von zwei Dateien ertönte etwa so:&lt;br /&gt;
&lt;code&gt;traaaa-traaa-traaaaaaa tak-tak-tak-tak-tak-tak-tak traaaaa-traaaaa tak tak tak tak&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Ganz interessant waren fehlerhafte Disketten, wo der Schreibkopf sehr schnell immer
auf die gleiche Position gesetzt wurde und dann nochmal vollständig ausgerichtet
wurde um den Leseversuch zu wiederholen.&lt;br /&gt;
Das hörte sich etwa so an:&lt;br /&gt;
&lt;code&gt;traaaaaaa t-t-t-t-t-t-t-t-t-t-t-t-t-t-t traaaaaa t-t-t-t-t-t-t-t-t&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Soa wusste man rein akustisch, dass das Betriebssystem gleich einen Lesefehler 
melden würde.&lt;/p&gt;

&lt;h3 id=&quot;525-zoll-disketten-varianten&quot;&gt;5.25 Zoll Disketten-Varianten&lt;/h3&gt;

&lt;p&gt;Die Daten werden auf der Diskette in Spuren (Cylinder oder Tracks, also Kreise
auf der Scheibe) geschrieben, die in Sektoren unterteilt sind.&lt;br /&gt;
Ein kleines Loch in der Datenscheibe lässt das Laufwerk erkennen, wann 
eine Umdrehung fertig und der nächste Sektor 0 erreicht ist.&lt;br /&gt;
Die Diskette konnte entweder nur auf einer Seite beschrieben werden
(Single-Sided) oder auf beiden (Double-Sided), was dann durch die
Anzahl der benutzten Lese/Schreib-Köpfe des Laufwerks (Heads) realisiert
wurde.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/floppy-disks-525.jpg&quot; alt=&quot;5.25 floppy disk&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Ja nach Qualität des Mediums lassen sich mehr oder weniger Seiten, Spuren und 
Sektoren auf einer Diskette unterbringen.&lt;br /&gt;
Physikalisch adressiert wurde nach dem &lt;a href=&quot;https://de.wikipedia.org/wiki/CHS-Adressierung&quot;&gt;CHS&lt;/a&gt;
(Cylinder, Header, Sector) Schema. Der logische Sektor 0 befand sich also an&lt;br /&gt;
Spur (Cylinder) 0, Kopf (Head) 0, und Sektor 0.&lt;/p&gt;

&lt;p&gt;Ich kenne grundsätzlich 3 Formate (4 wenn man das 
&lt;a href=&quot;/blog/2019/09/toshiba-t300/&quot;&gt;Toshiba&lt;/a&gt; Spezialformat einbezieht):&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;360 KB, &lt;code&gt;DD&lt;/code&gt; (&lt;a href=&quot;https://de.wikipedia.org/wiki/Double_Density&quot;&gt;Double Density&lt;/a&gt;), 
Double-Sided (DS) mit 40 Spuren und 9 Sektoren&lt;/li&gt;
  &lt;li&gt;180 KB, wie zuvor, eben nur auf einer Seite formatiert (40 Spuren, 9 Sektoren).&lt;/li&gt;
  &lt;li&gt;1.2 MB, &lt;code&gt;HD&lt;/code&gt; (&lt;a href=&quot;https://de.wikipedia.org/wiki/High_Density_(Diskette)&quot;&gt;High Density&lt;/a&gt;), 
Double-Sided (DS) mit 80 Spuren und 15 Sektoren&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Single_Density&quot;&gt;Single Density&lt;/a&gt; Disketten sind
mir nie untergekommen (so weit ich weiß).&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/floppy-disks-525-types.jpg&quot; alt=&quot;5.25 floppy disk types&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;fehlerrate&quot;&gt;Fehlerrate&lt;/h3&gt;

&lt;p&gt;Die meisten Daten habe ich schon vor vielen Jahren von den Disketten 
wegkopiert, womit ich heute nur mehr wenige übrig habe, die “prüfbare”
Daten beinhalteten, doch der Großteil funktioniert offenbar noch und hat 
alle Daten gehalten.&lt;/p&gt;

&lt;p&gt;Meine durchschnittliche Fehlerrate ist aber dennoch etwas höher und das liegt
an einem absoluten Billigfehlkauf Ende der 90er.&lt;br /&gt;
Man erkannte die mangelhafte Qualität am lieblosen logofreiem Papiersticker
und dem furchtbaren Reibgeräusch, sobald die Schreibe zu rotieren begann.&lt;br /&gt;
Man hätte diese Varianten eher &lt;em&gt;Schleifkette&lt;/em&gt; statt &lt;em&gt;Diskette&lt;/em&gt; nennen sollen.&lt;/p&gt;

&lt;p&gt;Schon damals fielen mir viele dieser Disketten schon am ersten Arbeitstag aus.
Heute funktioniert keine einzige mehr und wenn man die Datenscheibe vor eine
Lichtquelle hält, erkannt man die Kratzspuren, wo sich das Material bereits
zersetzt hat, oder durch Rauheiten in der Plastikhülle abgekratzt wurde.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/floppy-disk-525-error.jpg&quot; alt=&quot;Floppy disk error&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Doch diverse Qualitätsdisketten aus den 80er Jahren liefern immer noch 
zuverlässig ihre Daten und ließen sich heute im Test fehlerfrei neu 
formatieren.&lt;/p&gt;

&lt;h3 id=&quot;schreibschutz&quot;&gt;Schreibschutz&lt;/h3&gt;

&lt;p&gt;Bis heute “legendär” ist die Schreibschutz-Ecke (write-protect-notch) auf der 
rechten Seite einer jeden 5.25 Zoll Diskette.&lt;br /&gt;
3 cm von oben wurde ein 6 x 4 mm Rechteck aus der Schutzhülle weggestanzt,
womit das Laufwerk erkennen konnte, dass die Diskette beschreibbar ist.&lt;/p&gt;

&lt;p&gt;Wenn man diese “Ecke” mit einem undurchsichtigen Sticker überklebte, galt
die Diskette als schreibgeschützt, womit das Laufwerk nur noch Lesevorgänge
zuließ.&lt;/p&gt;

&lt;p&gt;Solche Disketten-Klebestreifen waren bei den teureren Modellen einfach bei,
oder konnten separat gekauft werden.&lt;br /&gt;
Oder man nutzte einfach ein Stück Papier mit einem üblichen Klebeband um 
die Ecke “abzudichten”.&lt;/p&gt;

&lt;h3 id=&quot;formatierung&quot;&gt;Formatierung&lt;/h3&gt;

&lt;p&gt;Damals unter &lt;a href=&quot;https://de.wikipedia.org/wiki/MS-DOS&quot;&gt;DOS&lt;/a&gt; nutzte man das 
klassische &lt;code&gt;FORMAT A:&lt;/code&gt; um eine uninitialisierte Floppydisk nutzbar zu machen 
oder um eine zu löschen und zu testen.&lt;/p&gt;

&lt;p&gt;Mit dem Parameter  &lt;code&gt;/F:xxx&lt;/code&gt; konnte man die Größe in Kilobytes angeben, 
womit man explizit mit &lt;code&gt;/F:180&lt;/code&gt;, &lt;code&gt;/F:360&lt;/code&gt; oder &lt;code&gt;/F:1200&lt;/code&gt; die Sollkapazität
angeben konnte.&lt;br /&gt;
Das funktionierte nur mit Kapazitäten kleiner oder gleich der korrekten
Größe. Man konnte also keine 360 KB Disk auf 1.2 MB hochformatieren,
doch eine 1.2 MB Diskette wurde so auf 360 KB limitiert.&lt;/p&gt;

&lt;p&gt;Irgendwo zwischen &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_2000&quot;&gt;Windows 2000&lt;/a&gt;, 
XP und Server 2003 hat Microsoft diesen Parameter jedoch auf &lt;code&gt;1440&lt;/code&gt; für 
3.5 Zoll Disketten reduziert. Alle anderen Angaben werden abgelehnt.&lt;/p&gt;

&lt;p&gt;Es gibt jedoch noch die Low-level Parameter &lt;code&gt;/T:tracks&lt;/code&gt; und &lt;code&gt;/N:sectors&lt;/code&gt;
mit denen man explizit die korrekten Größen angeben kann:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;360 KB: &lt;code&gt;format b: /T:40 /N:9&lt;/code&gt;&lt;br /&gt;
(40 Spuren * 9 Sektoren * 2 Seiten * 512 Bytes pro Sektor)&lt;/li&gt;
  &lt;li&gt;1.2 MB: &lt;code&gt;format b: /T:80 /N:15&lt;/code&gt;&lt;br /&gt;
(80 Spuren * 15 Sektoren * 2 Seiten * 512 Bytes pro Sektor)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Für eine Limitieren auf nur eine Seite konnte ich keinen Parameter finden.
Schade, denn früher gab es den Trick, eine doppelseitige Diskette nur 
einseitig zu formatieren, dann stanzte man selbst eine Ecke auf der linken
Seite aus und konnte die Diskette so auf der zweiten Seite separat 
formatieren, in dem man sie verkehrt einlegt.&lt;/p&gt;

&lt;p&gt;So konnte man auf jeder Seite der Diskette ein eigenes Dateisystem anlegen.
Nützlich war das eigentlich nicht, eher eine Spielerei. Aber man konnte so
auf einer Diskette zwei unterschiedliche bootbare Betriebssysteme halten.
(Denn zu DOS 2/3 Zeiten belegten die Startdateien nicht mehr als 100 KB.)&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;Augen auf! Liebe &lt;a href=&quot;https://de.wikipedia.org/wiki/SD-Karte&quot;&gt;SD-Karten&lt;/a&gt; Hersteller.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Denn viele “modernen” Medien überleben keine 5 Jahre und verlieren dabei 
ihre Daten.&lt;/p&gt;

&lt;p&gt;Doch 5.25 Zöller halten diese 30 Jahre und länger.&lt;/p&gt;

&lt;p&gt;Mir ist natürlich schon klar, dass 360 KB und 1.2 MB mit heutigen Gigabyte
SD-Karten nicht vergleichbar sind.&lt;br /&gt;
Aber wenn ich nun meine 100 KB Textdatei aus der Schule noch lesen kann,
jedoch das 10 MB Word-Dokument (mit gleichwertigem Textinhalt!) von der
SD-Karte am Smartphone einfach nicht mehr öffnen kann, dann werde ich wieder
zu folgender Aussage verleitet:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Früher war alles besser!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ein Hoch jedoch auf die kultigen 5.25 Zoll Disketten … die heute wohl nur 
noch die alten Hasen kennen.&lt;br /&gt;
… damals … als man den Datentransfer noch hören konnte.&lt;/p&gt;

&lt;h3 id=&quot;nachtrag-diskette-zerlegen&quot;&gt;Nachtrag: Diskette zerlegen&lt;/h3&gt;

&lt;p&gt;Wenn man schon eine defekte Diskette entdeckt hat, kann man auch die Hülle
auffalten und einen Blick hineinwerfen:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Die Hülle ist einem Kuvert ähnlich und die Faltstreifen sind mit 
Druckpunkten an die Hülle “getackert”.
Mit einem Taschenmesser lässt sich das leicht wieder “aufdrücken”.&lt;br /&gt;
&lt;img src=&quot;/blog/assets/img/floppy-disk-525-inside-01.jpg&quot; alt=&quot;Floppy 5.25 Inside 01&quot; /&gt;&lt;/li&gt;
  &lt;li&gt;Die Magnetscheibe ist an den Innenseiten durch eine Schutzfolie an der Hülle
ummantelt.
&lt;img src=&quot;/blog/assets/img/floppy-disk-525-inside-02.jpg&quot; alt=&quot;Floppy 5.25 Inside 02&quot; /&gt;&lt;/li&gt;
  &lt;li&gt;Die faserige Struktur der Schutzfolie ist in den 30 Jahren offenbar auch schon 
sehr vergilbt.&lt;br /&gt;
&lt;img src=&quot;/blog/assets/img/floppy-disk-525-inside-03.jpg&quot; alt=&quot;Floppy 5.25 Inside 03&quot; /&gt;&lt;/li&gt;
  &lt;li&gt;Auf der Magnetscheibe kann man schön das “Index-Loch” sehen, über welches
das Laufwerk den Beginn des ersten Sektors feststellen kann, wenn sich die 
Scheibe dreht.
&lt;img src=&quot;/blog/assets/img/floppy-disk-525-inside-04.jpg&quot; alt=&quot;Floppy 5.25 Inside 04&quot; /&gt;&lt;/li&gt;
  &lt;li&gt;Aufgefaltet besetzt eine solche Diskette eine recht große Oberfläche
&lt;img src=&quot;/blog/assets/img/floppy-disk-525-inside-05.jpg&quot; alt=&quot;Floppy 5.25 Inside 05&quot; /&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
 </entry>
 
 <entry>
   <title>Windows User-Mode Scheduling entfernt</title>
   <link href="https://www.opengate.at/blog/2022/05/no-ums/"/>
   <published>2022-05-22T13:00:00+02:00</published>
   <updated>2022-05-22T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2022/05/no-ums</id>
   <category term="devel" /><category term="software" />
   <summary type="text">Tja, einen offenen Punkt auf meiner Liste kann ich jetzt unerledigt abhaken:
nämlich die Ums-APIs, die mit Windows 7 
eingeführt wurden.

Denn mit der Einführung von Windows 11 sind diese Funktionen beinhart entfernt
worden, bzw. zu ERROR_NOT_SUPPORTED degradiert worden.
</summary>
   <content type="html">&lt;p&gt;Tja, einen offenen Punkt auf meiner Liste kann ich jetzt unerledigt abhaken:
nämlich die &lt;code&gt;Ums&lt;/code&gt;-APIs, die mit &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_7&quot;&gt;Windows 7&lt;/a&gt; 
eingeführt wurden.&lt;/p&gt;

&lt;p&gt;Denn mit der Einführung von Windows 11 sind diese Funktionen beinhart entfernt
worden, bzw. zu &lt;code&gt;ERROR_NOT_SUPPORTED&lt;/code&gt; degradiert worden.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Ich bin es von Microsoft eigentlich gewohnt, dass APIs - egal wie nutzlos 
sie sind - für alle Ewigkeiten im Betriebssystem verbleiben.&lt;br /&gt;
Natürlich gibt es da auch ein paar “High-Level”-Ausnahmen, wenn z.B.: der
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Agent&quot;&gt;Microsoft-Agent&lt;/a&gt; 
(ein Comic-Assistent zum Vorlesen von Texten) samt seiner 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Component_Object_Model&quot;&gt;COM&lt;/a&gt; API verschwindet, 
weil ihn nach 2003 ohnehin keiner mehr nutzte.&lt;/p&gt;

&lt;p&gt;Doch Kernfunktionen rund um Prozess- und Thread-Verwaltung sind seit spätestens
Windows 2000 “fix” im &lt;code&gt;kernel32&lt;/code&gt; und wachsten mit jeder neuen OS-Version an,
entfernt wird aber nichts mehr.&lt;/p&gt;

&lt;h3 id=&quot;user-mode-scheduling&quot;&gt;User Mode Scheduling&lt;/h3&gt;

&lt;p&gt;Letztes Jahr (zu Beginn meiner &lt;a href=&quot;https://de.wikipedia.org/wiki/Koroutine&quot;&gt;Koroutinen&lt;/a&gt; 
Analyse) erinnerte ich mich wieder an ein paar Vorträge zu einer “neuen” 
Threading API, abgekürzt &lt;code&gt;UMS&lt;/code&gt;, die einige Probleme mit Microsofts 
&lt;a href=&quot;https://de.wikipedia.org/wiki/User-Thread#Windows&quot;&gt;Fibers&lt;/a&gt; Ansatz lösen sollte.&lt;/p&gt;

&lt;p&gt;Allgemeiner Code weiß oft nichts von &lt;code&gt;Fibers&lt;/code&gt;, glaubt aber zu wissen, in 
einem Thread zu laufen und nutzt daher explizit oder implizit 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Thread-local_storage&quot;&gt;Thread-local-storage&lt;/a&gt; 
(&lt;code&gt;TLS&lt;/code&gt;).&lt;br /&gt;
Genau das kann mit Fibers dann Probleme erzeugen, wenn zwei Fibers Code 
ausführen, der &lt;code&gt;TLS&lt;/code&gt; nutzt und schon kommen States durcheinander.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Randnotiz: Die MS CRT Implementierung nutzt übrigens &lt;code&gt;FLS&lt;/code&gt; 
(Fiber-Local-Storage) für Funktionen wie 
&lt;a href=&quot;https://cplusplus.com/reference/cstring/strtok/&quot;&gt;&lt;code&gt;strtok()&lt;/code&gt;&lt;/a&gt; 
und ist damit sowohl Thread- als auch Fiber-sicher.&lt;br /&gt;
Doch Anwenderprogramme sind nicht immer so flexibel ausprogrammiert.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;code&gt;UMS&lt;/code&gt; sollte mit einer neuen API eine neue Art Thread einführen, dessen
Scheduling vom Usermode-Prozess aus verwaltet werden kann.&lt;/p&gt;

&lt;p&gt;Bisher hatte ich noch nie einen Grund mich mit dieser Technik auseinander
zu setzen und wollte das im Zuge des GATE Projektes nachholen, 
doch mit dieser neuesten Wendung wird daraus wohl nichts.&lt;br /&gt;
Schließlich bringt es nichts, eine API zu implementieren, die selbst
Microsoft als “unnötig” eingeschätzt hat und auch keinen “historischen”
Bezug hat.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Hmm … ich kann also nichts weiter zum UMS sagen, habe leider keine
Erfahrung damit und werde es vermutlich auch in Zukunft nicht nutzen.
Ich weiß nur, dass von 2009 bis 2021 existiert hat.&lt;/p&gt;

&lt;p&gt;Ein Detail habe ich dennoch aus der &lt;code&gt;UMS&lt;/code&gt; API entnommen:&lt;br /&gt;
Koroutinen sind im GATE Framework ähnlich aufgebaut, denn dort wird auch
ein “normaler” Thread als Scheduler eingesetzt um zwischen Koroutinen
hin und her zu springen.&lt;br /&gt;
Und im &lt;code&gt;UMS&lt;/code&gt; hätte es auch so einen Scheduler-Thread gegeben.&lt;/p&gt;

&lt;p&gt;Ein altes Video aus der frühen Channel-9 Zeit gibt (damals wie heute)
einen kleinen Überblick über diese Schnittstelle:&lt;/p&gt;

&lt;iframe width=&quot;640&quot; height=&quot;360&quot; src=&quot;/blog/redirect.html?https%3A%2F%2Fwww.youtube-nocookie.com%2Fembed%2FPYlP8MXRCZc&quot; frameborder=&quot;1&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
</content>
 </entry>
 
 <entry>
   <title>M.2 SSD 2242 Adapter zu 2280</title>
   <link href="https://www.opengate.at/blog/2022/05/m2-adapter/"/>
   <published>2022-05-21T13:00:00+02:00</published>
   <updated>2022-05-21T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2022/05/m2-adapter</id>
   <category term="hardware" />
   <summary type="text">Ein Betriebssystem ist einfach
zu wenig … doch mit 250 GB wird es dann eng.
Und so wollte ich heute meinem Laptop eine andere 
SSD verpassen.

Doch der war nur auf M.2 SSDs mit der 
Größe 2280 (also 80 mm Länge) ausgelegt, ich hatte aber nur eine mit Größe 
2242 (also 42 mm Länge) in der Schublade.

Welch Glück, dass ein 3D Drucker das 
Problem sofort lösen kann.
</summary>
   <content type="html">&lt;p&gt;Ein &lt;a href=&quot;https://de.wikipedia.org/wiki/Betriebssystem&quot;&gt;Betriebssystem&lt;/a&gt; ist einfach
zu wenig … doch mit 250 GB wird es dann eng.&lt;br /&gt;
Und so wollte ich heute meinem Laptop eine andere 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Solid-State-Drive&quot;&gt;SSD&lt;/a&gt; verpassen.&lt;/p&gt;

&lt;p&gt;Doch der war nur auf &lt;a href=&quot;https://de.wikipedia.org/wiki/M.2&quot;&gt;M.2&lt;/a&gt; SSDs mit der 
Größe 2280 (also 80 mm Länge) ausgelegt, ich hatte aber nur eine mit Größe 
2242 (also 42 mm Länge) in der Schublade.&lt;/p&gt;

&lt;p&gt;Welch Glück, dass ein &lt;a href=&quot;/blog/2019/01/ender-3/&quot;&gt;3D Drucker&lt;/a&gt; das 
Problem sofort lösen kann.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Mein alter &lt;code&gt;HP-250-G5&lt;/code&gt; (mit einen Core-i3, 8 GB RAM und 250 GB SSD) ist gerade
noch “akzeptabel” für die tägliche Arbeit (wenn gleich 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Teams&quot;&gt;Microsoft Teams&lt;/a&gt; spürbar immer 
schlechter darauf ausführbar wird).&lt;/p&gt;

&lt;p&gt;Doch ein OS ist mir zu wenig, ich hätte gerne 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_10&quot;&gt;Windows 10&lt;/a&gt;, Windows 7 
und &lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt; darauf (wie so oft bei 
meinen Teststellungen) und Virtualisierung wäre auf der Maschine wirklich 
kein Vergnügen.&lt;/p&gt;

&lt;p&gt;Als ich das Ding aufschraubte, fiel mir die “lange” M.2 SSD auf, für die ich
keinen Ersatz zu Hause hatte, während noch eine “kürzere” 512 GB Variante
vorrätig war.&lt;/p&gt;

&lt;h3 id=&quot;adapter-modell&quot;&gt;Adapter Modell&lt;/h3&gt;

&lt;p&gt;Mein erster Gedanke:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Mal schauen ob auf &lt;a href=&quot;https://de.wikipedia.org/wiki/Thingiverse&quot;&gt;Thingiverse&lt;/a&gt; 
jemand ein kleines Adapter-Plastikstück modelliert hat, um den M.2 Chip 
zu “verlängern”.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Und tatsächlich gibt es so etwas, und zwar unter dem Titel
&lt;a href=&quot;https://www.thingiverse.com/thing:4627082&quot;&gt;m.2 ssd adapter 2242 to 2280&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Also:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Download&lt;/li&gt;
  &lt;li&gt;Mit &lt;a href=&quot;https://de.wikipedia.org/wiki/Ultimaker_Cura&quot;&gt;CURA&lt;/a&gt; eine &lt;code&gt;.gcode&lt;/code&gt; 
Datei für meinen Ender-3 erstellen.&lt;/li&gt;
  &lt;li&gt;SD-Karte rein&lt;/li&gt;
  &lt;li&gt;Drucken&lt;/li&gt;
  &lt;li&gt;Ausprobieren …&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
  &lt;p&gt;Fu**! Geht nicht!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Denn der Adapter umklammert die M.2 mit einer über einem 1cm eng anliegenden
Umrandung, doch meine 2242 Variante ist schon 5 mm vom Rand entfernt mit SMD
Bauteilen und dem Speicherchip flächendecken bestückt.&lt;/p&gt;

&lt;p&gt;Man kann den Adapter also nicht über den Chip stülpen.&lt;/p&gt;

&lt;h3 id=&quot;lösung-bescheidung&quot;&gt;Lösung: Bescheidung&lt;/h3&gt;

&lt;p&gt;Die Store-App &lt;a href=&quot;https://apps.microsoft.com/store/detail/3d-builder/9WZDNCRFJ3T6&quot;&gt;3D Builder&lt;/a&gt; 
von Microsoft unterstützt allerdings ein paar einfache Bearbeitungsmethoden 
für 3D Modelle und dazu gehören:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Rotation&lt;/li&gt;
  &lt;li&gt;Aufsplitterung&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Man kann beim Aufsplitten nur unterscheiden, ob man oben oder unten was
wegschneiden will, also musste ich den Adapter zuerst 90 Grad rotieren, dass
er aufrecht steht und dann konnte ich per “Augenmaß” etwa so viel 
wegschneiden, dass nur noch 5 mm der Halterung übrig waren.&lt;/p&gt;

&lt;p&gt;Das wurde dann wieder zurück rotiert, gespeichert, wieder für den Ender-3
vorbereitet und gedruckt.&lt;/p&gt;

&lt;p&gt;15 Minuten später, und voila: Es passt.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/m2-ssd-2242-2280.jpg&quot; alt=&quot;M2-SSD-2242-2280&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Und wieder zeigt sich, wie “cool” es ist, sich Dinge selber basteln zu können.&lt;/p&gt;

&lt;p&gt;Früher hätte ich vermutlich lange nach einem Händler suchen müssen, um 
entweder einen solchen Adapter zu finden, oder ich hätte eine neue M.2
SSD im richtigen Format kaufen müssen.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/laptop-hp250g5.jpg&quot; alt=&quot;Laptop M2&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Und selbst wer keinen 3D Drucker zu Hause hat, findet in der Stadt
schnell einen Shop, der solche Druckaufträge binnen eines Tages ausführen
kann.&lt;br /&gt;
… und das ist allemal schneller, als lange Bestellprozesse absetzen zu
müssen.&lt;/p&gt;

&lt;p&gt;Somit kann ich hier vergnügt behaupten:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Heute ist einfach alles besser!&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>operator&lt;()</title>
   <link href="https://www.opengate.at/blog/2022/05/less-compare/"/>
   <published>2022-05-15T13:00:00+02:00</published>
   <updated>2022-05-15T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2022/05/less-compare</id>
   <category term="devel" />
   <summary type="text">Jahre code ich herum, und dann passieren mir so unglaublich dumme 
Anfängerfehler, wie ein falsch implementierter operator&amp;lt;().
(C++ Operator overloading)

Und das Schlimme ist, dass man das nicht immer gleich mitbekommt,
wenn plötzlich ganz andere Codes anfangen zu bocken.

Es wird also Zeit, das Thema zu “wiederholen” … so lange bis auch
ich es richtig mache.
</summary>
   <content type="html">&lt;p&gt;Jahre code ich herum, und dann passieren mir so unglaublich dumme 
Anfängerfehler, wie ein falsch implementierter &lt;code&gt;operator&amp;lt;()&lt;/code&gt;.
(&lt;a href=&quot;https://en.cppreference.com/w/cpp/language/operators&quot;&gt;C++ Operator overloading&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;Und das Schlimme ist, dass man das nicht immer gleich mitbekommt,
wenn plötzlich ganz andere Codes anfangen zu bocken.&lt;/p&gt;

&lt;p&gt;Es wird also Zeit, das Thema zu “wiederholen” … so lange bis auch
ich es richtig mache.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;datentyp-als-mapping-key&quot;&gt;Datentyp als Mapping-Key&lt;/h3&gt;

&lt;p&gt;Es war einmal eine Datenverwaltung, die einen &lt;code&gt;int&lt;/code&gt; als Schlüssel
nutzte, um Datensätze in einer &lt;a href=&quot;https://cplusplus.com/reference/map/map/&quot;&gt;&lt;code&gt;std::map&lt;/code&gt;&lt;/a&gt; 
leicht auffindbar zu halten.&lt;/p&gt;

&lt;p&gt;Dann erkannte man, dass der &lt;code&gt;int&lt;/code&gt; nicht eindeutig genug war, es
sollte ein zweiter angefügt werden und so wurde aus:&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;std::map&amp;lt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt;, data_t&amp;gt; mapping;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;ein&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;struct&lt;/span&gt; int_key
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; a;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; b;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;};
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;std::map&amp;lt;int_key, data_t&amp;gt; mapping;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Doch das funktioniert noch nicht, weil &lt;code&gt;int_key&lt;/code&gt; Instanzen vergleichbar
sein müssen, um in einer &lt;code&gt;std::map&lt;/code&gt; benutzt werden zu dürfen.&lt;/p&gt;

&lt;p&gt;Dafür schreibt man also eine &lt;code&gt;operator&amp;lt;()&lt;/code&gt; Funktion, die zwei Instanzen
vergleicht, denn (ohne zusätzlich Angaben) nutzt &lt;code&gt;std::map&lt;/code&gt; ein 
&lt;a href=&quot;https://cplusplus.com/reference/functional/less/&quot;&gt;&lt;code&gt;std::less(x, y)&lt;/code&gt;&lt;/a&gt;
für die Ordnung innerhalb seiner Elemente und &lt;code&gt;std::less&lt;/code&gt; führt  wiederum&lt;br /&gt;
&lt;code&gt;return x &amp;lt; y;&lt;/code&gt; aus.&lt;/p&gt;

&lt;p&gt;Und die Implementierung kann dann etwa so aussehen:&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;bool&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;operator&lt;/span&gt;&amp;lt;(int_key &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt;&amp;amp; k1, int_key &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt;&amp;amp; k2)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt;(k1.a &amp;lt; k2.a)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  {
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#777&quot;&gt;// primary value less -&amp;gt; return true&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color:#069&quot;&gt;true&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  } 
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt;(k2.a &amp;lt; k1.a) &lt;span style=&quot;color:#777&quot;&gt;/*OR: if(k1.a &amp;gt; k2.a) */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;  {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;    &lt;span style=&quot;color:#777&quot;&gt;// primary value greater -&amp;gt; return false&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color:#069&quot;&gt;false&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;  }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;// primary values are equal -&amp;gt; use second&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; k1.b &amp;lt; k2.b;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Muss man mehrere Member vergleichen, kann man immer davon ausgehen,
dass wenn ein Member kleiner ist als der im Vergleichsobjekt, dann
ist das gesamte Objekt bereits “kleiner”.
Ist ein Member größer, ist auch das gesamte Objekt größer.
Sind beide Member aber gleich, geht man zum nächsten und wiederholt
das Spiel, bis am Schluss der letzte Member entscheiden darf, wenn
alle seine Vorgänger gleich waren.&lt;/p&gt;

&lt;p&gt;So ist alles in Ordnung und eine &lt;code&gt;std::map&lt;/code&gt; kann ihre Daten korrekt
einordnen.&lt;/p&gt;

&lt;h3 id=&quot;und-was-wenn-nicht-&quot;&gt;Und was wenn nicht ??&lt;/h3&gt;

&lt;p&gt;Ich habe neulich folgendes schlampiges Fabrikat abgeliefert:&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;bool&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;operator&lt;/span&gt;&amp;lt;(int_key &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt;&amp;amp; k1, int_key &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt;&amp;amp; k2)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt;(k1.a &amp;lt; k2.a)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color:#069&quot;&gt;true&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;  } 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; k1.b &amp;lt; k2.b;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Und dann brach die Hölle los.&lt;br /&gt;
Denn mit der Implementierung werden Größer/Kleiner Aussagen widersprüchlich.
Hier ein Beispiel:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;x = (20, 8)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;y = (30, 7)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;x &amp;lt; y --&amp;gt; true (wegen: 20 &amp;lt; 30)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;y &amp;lt; x --&amp;gt; true (wegen: 30 !&amp;lt; 20 aber 7 &amp;lt; 8)
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;&lt;code&gt;std::map&lt;/code&gt; kann &lt;code&gt;std::less&lt;/code&gt; in beiden Richtungen nutzen, nämlich:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;std::less(x, y)&lt;/code&gt;: Ist &lt;code&gt;x&lt;/code&gt; kleiner als &lt;code&gt;y&lt;/code&gt; ?&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;std::less(y, x)&lt;/code&gt;: Ist &lt;code&gt;x&lt;/code&gt; größer als &lt;code&gt;y&lt;/code&gt; ?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Und wenn beides &lt;code&gt;true&lt;/code&gt; wird, ergeben sich fiese Abfrageschleifen.&lt;/p&gt;

&lt;p&gt;So ist das Problem dann auch aufgefallen, nämlich als das 
Einfügen eines neuen Wertes plötzlich zu einer Endlosschleife
wurde.&lt;/p&gt;

&lt;p&gt;Dummerweise waren die Zahlen bei Tests zufällig so gestrickt,
dass es mir nicht aufgefallen war.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;Peinlich! Peinlich! Peinlich!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ja, Tippfehler passieren, aber ich habe schon auch ein Talent solche 
Kindergartenbeispiele zu versemmeln.&lt;/p&gt;

&lt;p&gt;Ein weiterer “meiner” Klassiker ist:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt;(error_detected)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  continue_operation();
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;}
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;else&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  cancel_due_to_error();
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Es ist einfach Schlampigkeit oder mangelnde Konzentration, die so etwas
auslösen und genau das sollte einem beim finalen Durchlesen sofort auffallen.&lt;/p&gt;

&lt;p&gt;Denn was man nicht vergessen darf: Software steuert heute alles.
Und leider sind es dann solche Fehler, die böse Dinge auslösen.&lt;/p&gt;

&lt;p&gt;Hoffentlich wird mir diese Peinlichkeit eine Lehre sein, damit ich in 
Zukunft genau hinsehe, wenn ich wieder mal so einen Blödsinn schreiben sollte.&lt;/p&gt;

&lt;p&gt;Und vielen Dank an meinen Kollegen, der meinen Patzer herausgefunden hat,
bevor er in produktiver Software breiten Schaden anrichten konnte.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>dlopen(NULL, 0)</title>
   <link href="https://www.opengate.at/blog/2022/05/dlopen/"/>
   <published>2022-05-14T13:00:00+02:00</published>
   <updated>2022-05-14T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2022/05/dlopen</id>
   <category term="devel" />
   <summary type="text">Da Linux Distributionen hart daran 
arbeiten zu einander so inkompatibel wie möglich zu sein, suchte ich nach 
Strategien, wie man ohne Plattform-spezifische Linkereien so viel möglich an 
Features erhalten kann.

Aber um zu wissen, was einem überhaupt fehlt, muss man erst mal wissen,
was man schon hat … und hier kommt 
dlopen 
ins Spiel.
</summary>
   <content type="html">&lt;p&gt;Da &lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt; Distributionen hart daran 
arbeiten zu einander so inkompatibel wie möglich zu sein, suchte ich nach 
Strategien, wie man ohne Plattform-spezifische Linkereien so viel möglich an 
Features erhalten kann.&lt;/p&gt;

&lt;p&gt;Aber um zu wissen, was einem überhaupt fehlt, muss man erst mal wissen,
was man schon hat … und hier kommt 
&lt;a href=&quot;https://pubs.opengroup.org/onlinepubs/009695399/functions/dlopen.html&quot;&gt;&lt;code&gt;dlopen&lt;/code&gt;&lt;/a&gt; 
ins Spiel.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Funktionen wie &lt;a href=&quot;http://man7.org/linux/man-pages/man3/backtrace.3.html&quot;&gt;&lt;code&gt;backtrace()&lt;/code&gt;&lt;/a&gt; 
oder &lt;a href=&quot;https://pubs.opengroup.org/onlinepubs/009695399/functions/getcontext.html&quot;&gt;&lt;code&gt;getcontext()&lt;/code&gt; &lt;code&gt;setcontext()&lt;/code&gt;&lt;/a&gt;
und &lt;a href=&quot;https://pubs.opengroup.org/onlinepubs/009695399/functions/makecontext.html&quot;&gt;&lt;code&gt;makecontext() swapcontext()&lt;/code&gt;&lt;/a&gt; 
sind zwar nicht 0815, aber auch nicht extrem selten.
Schließlich helfen sie einem den Callstack “zu bearbeiten” oder 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Koroutine&quot;&gt;Koroutinen&lt;/a&gt; oder eine spezielle 
Fehlerbehandlung zu implementieren.&lt;/p&gt;

&lt;p&gt;Linux-Varianten, die mit der &lt;code&gt;glibc&lt;/code&gt; aufgebaut wurden, integrieren diese
Funktionen quasi in jeden Prozess, weil die &lt;code&gt;glibc&lt;/code&gt; sie beinhaltet.
Wie die “echte” Bibliothek heißt, ist versionsabhängig und grundsätzlich 
unbekannt, weil die Standard-Bibliothek automatisch gelinkt wird.&lt;/p&gt;

&lt;p&gt;Ganz anders &lt;a href=&quot;https://de.wikipedia.org/wiki/Alpine_Linux&quot;&gt;Alpine Linux&lt;/a&gt; oder 
andere Distros, die auf abgespeckte C-Libraries wie &lt;code&gt;uClibc&lt;/code&gt;, &lt;code&gt;musl-libc&lt;/code&gt; oder
&lt;code&gt;dietlibc&lt;/code&gt; aufbauen.
Hier braucht man z.B.: &lt;code&gt;libucontext.so.1&lt;/code&gt; für die Context-Funktionen.&lt;/p&gt;

&lt;h3 id=&quot;dlopen-ohne-bibliothek&quot;&gt;dlopen() ohne Bibliothek&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;dlopen&lt;/code&gt; bietet aber eine interessante Zusatzfunktion. 
Ruft man es nämlich mit&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;* process_handle = dlopen(&lt;span style=&quot;color:#069&quot;&gt;NULL&lt;/span&gt;, RTLD_GLOBAL);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;* ptr_function = dlsym(process_handle, &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;makecontext&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;);
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;auf, erhält man Zugang zu allen bereits geladenen globalen Symbolen.
&lt;code&gt;dlsym&lt;/code&gt; kann nun von jeder Funktion, die bereits geladen ist, den
Funktionszeigern ermitteln und zurückgeben.&lt;/p&gt;

&lt;p&gt;Und auf diese Weise, kann man also zuerst “prüfen”, ob eine benötigte Funktion
schon da ist.&lt;/p&gt;

&lt;h3 id=&quot;kein-if-alpine-elseif-debian-&quot;&gt;Kein: if alpine, elseif debian …&lt;/h3&gt;

&lt;p&gt;Brauche ich also eine Funktion, die manchmal schon in der C-Bibliothek 
integriert ist und manchmal nicht, prüfe ich das zuerst mit &lt;code&gt;dlopen(NULL)&lt;/code&gt;
und nur wenn hier &lt;code&gt;NULL&lt;/code&gt; zurückkommt, lade ich andere Bibliotheken und 
versuche mein Glück mit diesen.&lt;/p&gt;

&lt;p&gt;Früher musste ich unseelige Spielereien wie&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color:#B44;font-weight:bold&quot;&gt;&amp;lt;my_lib/my_func.h&amp;gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;typedef&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt;(*my_func_ptr_t)(&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; param);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#if&lt;/span&gt; defined(LINUX_MUSLIBC)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;* my_lib = dlopen(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;libmy_lib.so&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, RTLD_GLOBAL);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;  my_func_ptr_t my_func_ptr = dlsym(my_lib, &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;my_func&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#else&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;  my_func_ptr_t my_func_ptr = &amp;amp;my_func;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#endif&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;bemühen und den Code per &lt;a href=&quot;https://de.wikipedia.org/wiki/CMake&quot;&gt;CMake&lt;/a&gt; mit 
Hilfs-Makros anreichern.&lt;br /&gt;
Heute kann ich eine Array von Bibliotheksnamen anlegen und diese dann per 
Schleife durchlaufen lassen, wenn &lt;code&gt;dlopen(NULL)&lt;/code&gt; eben nicht erfolgreich war.&lt;/p&gt;

&lt;p&gt;Dieser Code ist dann OS-unabhängiger und läuft auf mehr Plattformen, weil er 
eben nicht per &lt;code&gt;#ifdef&lt;/code&gt; auf eine Plattform fixiert ist.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Das Thema, wie man Linux-Binaries baut, die überall laufen, ist ein 
schwieriges. Denn leider löst der Ansatz immer noch nicht das Problem, das
z.B.: Alpine Linux und Debian zwei unterschiedliche Binaries brauchen.&lt;/p&gt;

&lt;p&gt;Ich hatte auch schon mal mit dem &lt;code&gt;-static&lt;/code&gt; Flag des 
&lt;a href=&quot;https://de.wikipedia.org/wiki/GNU_Compiler_Collection&quot;&gt;GCC&lt;/a&gt; 
gespielt um absolut unabhängige Executables zu produzieren … doch bei denen funktioniert dann
&lt;code&gt;dlopen&lt;/code&gt; gar nicht mehr.&lt;br /&gt;
Womit der Ansatz leider auch wegfällt.&lt;/p&gt;

&lt;p&gt;Zumindest wurden so wieder ein paar Makros wegrationalisiert.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ein kleiner Schritt für die einzelne Projektdatei.&lt;br /&gt;
Aber ein großer für die Zukunft des Projekt.&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>WinCE Patches</title>
   <link href="https://www.opengate.at/blog/2022/05/ce-patches/"/>
   <published>2022-05-08T13:00:00+02:00</published>
   <updated>2022-05-08T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2022/05/ce-patches</id>
   <category term="devel" /><category term="projects" />
   <summary type="text">Mit jeder Plattform gibt es Probleme in Sachen Kompatibilität, aber mit keiner
gibt es so viel wie mit Windows CE.

Und vermutlich beschäftigte ich mich genau deshalb immer wieder mit dieser
eigentlich schon ausgestorbenen Umgebung, denn:


  Ich liebe die Herausforderung.


</summary>
   <content type="html">&lt;p&gt;Mit jeder Plattform gibt es Probleme in Sachen Kompatibilität, aber mit keiner
gibt es so viel wie mit &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_CE&quot;&gt;Windows CE&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Und vermutlich beschäftigte ich mich genau deshalb immer wieder mit dieser
eigentlich schon ausgestorbenen Umgebung, denn:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ich liebe die Herausforderung.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Ich selbst habe mit WinCE eigentlich gar keine Probleme, doch leider haben
eine Vielzahl anderer Bibliotheken ihre Probleme mit dem limitierten 
Funktionsset.&lt;/p&gt;

&lt;p&gt;Und das liegt in erster Linie daran, dass der &lt;a href=&quot;https://de.wikipedia.org/wiki/C_(Programmiersprache)&quot;&gt;C-Standard&lt;/a&gt;
nicht vollständig abgebildet ist. Das manifestiert sich folgendermaßen:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Ein Header fehlt (z.B.: &lt;code&gt;stdbool.h&lt;/code&gt; oder &lt;code&gt;io.h&lt;/code&gt;)&lt;/li&gt;
  &lt;li&gt;Funktionen sind im Header, aber nicht in der C-Runtime implementiert
(z.B.: &lt;code&gt;time()&lt;/code&gt; oder &lt;code&gt;clock()&lt;/code&gt;)&lt;/li&gt;
  &lt;li&gt;Funktionen fehlen im Header (z.B.: &lt;code&gt;strcoll()&lt;/code&gt;)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Ein fehlender Header lässt sich ganz leicht ersetzen. Man fügt ihn dem 
eigenen Projekt hinzu inklusive einer Implementierung, die z.B.: direkt 
auf &lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_Application_Programming_Interface&quot;&gt;WinAPI&lt;/a&gt;
Aufrufe umleitet.&lt;/p&gt;

&lt;p&gt;Wenn nur die Implementierung einer C-Funktion in der 
C-&lt;a href=&quot;https://de.wikipedia.org/wiki/Laufzeitumgebung&quot;&gt;Runtime&lt;/a&gt; fehlt, verfährt 
man ähnlich: Man fügt einfach eine neue Implementierung im eigenen Projekt an
und schon kann das “nicht-aufgelöste-Symbol” gefunden werden.&lt;/p&gt;

&lt;p&gt;Am schlechtesten ist die dritte Variante, nämlich das Fehlen einer Funktion
im Header und der CRT.&lt;/p&gt;

&lt;p&gt;Viele Header in WinCE sind nur Umleitungen auf &lt;code&gt;stdlib.h&lt;/code&gt; in der vieles
notwendige enthalten ist. Doch leider fehlen die meisten IO-Funktionen
wie &lt;a href=&quot;https://cplusplus.com/reference/cstdio/freopen/&quot;&gt;&lt;code&gt;freopen()&lt;/code&gt;&lt;/a&gt;, 
&lt;a href=&quot;https://cplusplus.com/reference/cstdio/remove/&quot;&gt;&lt;code&gt;remove()&lt;/code&gt;&lt;/a&gt; oder 
&lt;a href=&quot;https://cplusplus.com/reference/cstdio/rename/&quot;&gt;&lt;code&gt;rename()&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Nutzt man nun eine Bibliothek, die selbst nur &lt;code&gt;stdio.h&lt;/code&gt; einbindet und sich
eine Funktion dahinter erwartet, treten seltsame Seiteneffekte auf.&lt;br /&gt;
Denn C nutzt den Funktionsaufruf als Deklaration mit eine undefinierten
Prototyp wie:&lt;br /&gt;
&lt;code&gt;int c_function(...);&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Fügt man nun seine eigene Implementierung mit der richtigen Deklaration
parallel hinzu, gilt die &lt;a href=&quot;https://en.wikipedia.org/wiki/One_Definition_Rule&quot;&gt;One-Definition-Rule&lt;/a&gt;
als verletzt, weil das gleiche Symbol zwei mal unterschiedlich definiert 
wurde.&lt;br /&gt;
z.B.:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; c_function(...);          &lt;span style=&quot;color:#777&quot;&gt;//&amp;lt; implicit declaration&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt; c_function(&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt;*); &lt;span style=&quot;color:#777&quot;&gt;//&amp;lt; correct declaration&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h3 id=&quot;platform-support-layer&quot;&gt;Platform Support Layer&lt;/h3&gt;

&lt;p&gt;Im Platform-Layer des GATE Projektes nutzte ich bisher ein &lt;code&gt;wince&lt;/code&gt; 
Unterverzeichnis, in dem einige Header mit Inline Funktionen enthalten waren.
Diese Header wurden dann von &lt;a href=&quot;https://de.wikipedia.org/wiki/CMake&quot;&gt;CMake&lt;/a&gt; 
aus adressiert, um unter Windows CE meine manipulierten Header zu laden und 
nicht jene C-Standard-Bibliothek.&lt;/p&gt;

&lt;p&gt;Doch leider nahm die Menge der notwendigen Funktionen zu und daher
brauchte ich einen neuen Ansatz.&lt;/p&gt;

&lt;h3 id=&quot;stdcpatches-bibliothek&quot;&gt;stdcpatches Bibliothek&lt;/h3&gt;

&lt;p&gt;Die Hilfsbibliothek &lt;code&gt;stdcpatches&lt;/code&gt; ist eine statische Bibliothek im &lt;code&gt;libs&lt;/code&gt;
Ordner des GATE Projektes und soll eine Vielzahl von &lt;code&gt;std-c&lt;/code&gt; Header und 
Implementierungen nachbilden.&lt;/p&gt;

&lt;p&gt;Für jede Plattform und jeden Typ von C-Header gibt es Unterverzeichnisse,
die alle notwendigen Dateien beinhalten.&lt;br /&gt;
Am Ende entscheidet dann &lt;code&gt;CMake&lt;/code&gt;, welche Ordner als Include-Directories
eingebunden oder übersprungen werden sollen.&lt;/p&gt;

&lt;p&gt;Auf diese Weise können Patches für Plattformen wie Windows CE oder Compiler
wie &lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_C%2B%2B&quot;&gt;MSVC&lt;/a&gt; eingebaut werden.&lt;/p&gt;

&lt;p&gt;Fordert eine Bibliothek wie &lt;code&gt;libpng&lt;/code&gt; z.B.: &lt;code&gt;errno.h&lt;/code&gt; an, existiert dafür
in &lt;code&gt;stdcpatches&lt;/code&gt; ein eigener Header &lt;code&gt;errno.h&lt;/code&gt;, der fehlende Makros und 
Definitionen nachliefert. Parallel dazu veröffentlicht eine eigene 
&lt;code&gt;wince_errno.c&lt;/code&gt; Einheit die Implementierung innerhalb der statischen
Bibliothek.&lt;/p&gt;

&lt;p&gt;Für den MSVC allgemein existieren Header wie &lt;code&gt;sys/stat.h&lt;/code&gt; oder &lt;code&gt;stdint.h&lt;/code&gt;,
die in älteren Versionen nicht enthalten waren.
Auch hier bindet &lt;code&gt;CMake&lt;/code&gt; die Dateien nur bei älteren Compilern ein und 
verzichtet darauf, wenn sie in neuen Versionen schon enthalten sind.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Die Umstellung von “kleinen Patches” in &lt;code&gt;gate/platform/wince&lt;/code&gt; auf eine eigene
Bibliothek &lt;code&gt;stdcpatches&lt;/code&gt; war eine größere und auch recht mühsam.&lt;br /&gt;
Dennoch glaube ich, dass es mir langfristig mehr bringt, solche 
Codeverrenkungen kontrolliert an genau einer Stelle durchzuführen.&lt;/p&gt;

&lt;p&gt;Schließlich hat die bisherige Implementierung den Abhängigkeitsbaum 
korrumpiert, denn externe Bibliotheken sollten vor dem GATE Framework Code
kompiliert werden. Doch nur für WinCE wurden einige wenige 
Include-Directories schon vorher aus dem GATE-Projekt geladen.&lt;/p&gt;

&lt;p&gt;Jetzt sind externe Bibliotheken in Sonderfällen von der Bibliothek 
&lt;code&gt;stdcpatches&lt;/code&gt; abhängig, und am Ende wird alles zusammen vom GATE Projekt
konsumiert.&lt;/p&gt;

&lt;script src=&quot;/blog/assets/mermaid/mermaid.min.js&quot;&gt;&lt;/script&gt;
&lt;div class=&quot;mermaid&quot;&gt;
graph LR
  GATE[[GATE&lt;br /&gt;Framework]]
  EXT[[External&lt;br /&gt;Libraries]]
  PATCH[[stdcpatches]]
  STDC[[STD-C&lt;br /&gt;Libraries]]
  OS[[OS native API]]

  GATE --include--&amp;gt; EXT
  EXT --include--&amp;gt; PATCH
  EXT --include --&amp;gt; STDC
  PATCH --include--&amp;gt; STDC
  PATCH --include--&amp;gt; OS
&lt;/div&gt;

&lt;p&gt;Ein Vorteil ergibt sich daraus außerdem: &lt;code&gt;stdcpatches&lt;/code&gt; kann jetzt auch ohne
das GATE Projekt mit anderen Libs für Fremdprojekte benutzt werden.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Picard, Moon Knight, Strange und Strange New Worlds</title>
   <link href="https://www.opengate.at/blog/2022/05/watchlist/"/>
   <published>2022-05-07T13:00:00+02:00</published>
   <updated>2022-05-07T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2022/05/watchlist</id>
   <category term="entertainment" />
   <summary type="text">Also, diese Woche hatte es so was von in sich:
Zwei Serienstaffeln endeten, eine startete und ein neuer Blockbuster läuft
im Kino:

  Marvel’s Moon Knight
  StarTrek: Picard
  StarTrek: Strange New Worlds
  Doctor Strange in the Multiverse of Madness


So viel Stress hatte ich schon lange nicht mehr …
</summary>
   <content type="html">&lt;p&gt;Also, diese Woche hatte es so was von in sich:
Zwei Serienstaffeln endeten, eine startete und ein neuer Blockbuster läuft
im Kino:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Moon_Knight_(TV_series)&quot;&gt;Marvel’s Moon Knight&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Star_Trek:_Picard&quot;&gt;StarTrek: Picard&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Star_Trek:_Strange_New_Worlds&quot;&gt;StarTrek: Strange New Worlds&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Doctor_Strange_in_the_Multiverse_of_Madness&quot;&gt;Doctor Strange in the Multiverse of Madness&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So viel Stress hatte ich schon lange nicht mehr …
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;marvels-moon-knight&quot;&gt;Marvel’s Moon Knight&lt;/h3&gt;

&lt;p&gt;Alle bisherigen Marvel Serien spannen Geschichten rund um Figuren aus den 
Marvel Filmen des MCU weiter, doch nun kommt Moon Knight und startet etwas
ganz anderes: Ägyptische Götter&lt;/p&gt;

&lt;p&gt;Diese suchen sich menschliche Avatare um die Erde zu beobachten, wollen aber 
in der Regel nicht eingreifen.&lt;/p&gt;

&lt;p&gt;Und wäre da nicht ein Anhänger &lt;a href=&quot;https://de.wikipedia.org/wiki/Ethan_Hawke&quot;&gt;Ethan Hawke&lt;/a&gt; 
der verbannten Krokodil-Gottheit &lt;a href=&quot;https://de.wikipedia.org/wiki/Ammit&quot;&gt;Ammit&lt;/a&gt;, 
die er wiederbeleben wollte, dann bräuchten wir nicht einen Helden, der das 
verhindert, und das ist der Moon Knight &lt;a href=&quot;https://de.wikipedia.org/wiki/Oscar_Isaac&quot;&gt;Oscar Isaac&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Der Mondgott &lt;a href=&quot;https://de.wikipedia.org/wiki/Chons&quot;&gt;Khonshu&lt;/a&gt; will die 
Wiederauferstehung Ammits verhindern und bringt dafür seinen Avatar in 
Stellung, der aber ein gröberes Problem hat, nämlich eine gespaltene
Persönlichkeit.&lt;/p&gt;

&lt;p&gt;Und so lebt die Serie von dem teils komischen Wechselspiel zwischen den 
Persönlichkeiten “Steven Grant” und “Marc Spector”. Der eine furchtloser
Kämpfer, der andere mit dem Gemüt eines nervösen Museumsangestellten.&lt;/p&gt;

&lt;p&gt;Die Serie ist echt witzig und auf jeden Fall eine einzige Ägypten Werbung.
Unsicher bin ich mir allerdings, wie das ins Marvel Cinematic Universe 
passt und ob oder wie es daran anknüpft.&lt;/p&gt;

&lt;h3 id=&quot;startrek-picard-staffel-2&quot;&gt;StarTrek: Picard (Staffel 2)&lt;/h3&gt;

&lt;p&gt;Wenn schon in der ersten Folge der zweiten Staffel ein Borg-Angriff erfolgt, 
der unseren alten Admiral Picard (&lt;a href=&quot;https://de.wikipedia.org/wiki/Patrick_Stewart&quot;&gt;Patrick Stewart&lt;/a&gt;)
zwingt die schiffsweite Selbstzerstörungssequenz auszulösen und vermeintlich
alle sterben, tja dann wissen wir, dass diese Staffel eine ganz andere Action
bereitstellt, als die erste.&lt;/p&gt;

&lt;p&gt;Doch wie schon damals in &lt;a href=&quot;https://de.wikipedia.org/wiki/Raumschiff_Enterprise_%E2%80%93_Das_n%C3%A4chste_Jahrhundert&quot;&gt;StarTrek: Next Generation&lt;/a&gt;
taucht das Überwesen Q auf schickt den Hauptcast in eine andere Zeitlinie und
gibt ihnen die Lösung eines Rätsels auf.&lt;/p&gt;

&lt;p&gt;Von dort aus geht es zurück ins Jahr 2024, wo eine Veränderung der Zeitlinie
verhindert (oder vielleicht ausgelöst) werden soll … 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Star_Trek_IV:_Zur%C3%BCck_in_die_Gegenwart&quot;&gt;StarTrek IV: Zurück in die Gegenwart&lt;/a&gt; 
lässt grüßen.&lt;/p&gt;

&lt;p&gt;Womit wir schon bei meiner Kritik wären:&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;Ich erwarte, dass StarTrek in der Zukunft spielt.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ja sicher, die Einzelfolgen, in denen per Zeitreise “die alte Erde” besucht 
wurde, sind alle toll, aber wenn ich nun 8 von 10 Folgen in den heutigen USA
verbringen muss, nur um zu zeigen, wie schlecht vieles ist, und wie gut es 
hätte sein können, dann ist das nicht mehr StarTrek.&lt;/p&gt;

&lt;p&gt;Doch die letzte Folge brachte ein Ereignis hervor, das zwar auch viel 
Herz-Schmerz zeigte, aber dennoch so unerwartet und “gut” war, dass ich der
restlichen Handlung einiges verzeihe.&lt;br /&gt;
Sie war das genaue Gegenstück der letzten Folge der ersten Staffel.&lt;br /&gt;
Denn das Ende der ersten Staffel hat mir vieles versaut.&lt;br /&gt;
Das Ende Ende der zweiten hat vieles gerettet.&lt;/p&gt;

&lt;p&gt;Fazit: Es ist StarTrek und damit Pflicht.&lt;/p&gt;

&lt;h3 id=&quot;startrek-strange-new-worlds&quot;&gt;StarTrek: Strange New Worlds&lt;/h3&gt;

&lt;p&gt;Captain Pike &lt;a href=&quot;https://de.wikipedia.org/wiki/Anson_Mount&quot;&gt;Anson Mount&lt;/a&gt; und 
Lt. Spock &lt;a href=&quot;https://de.wikipedia.org/wiki/Ethan_Peck&quot;&gt;Ethan Peck&lt;/a&gt; durften wir
ja schon in der zweiten Staffel von &lt;a href=&quot;https://de.wikipedia.org/wiki/Star_Trek:_Discovery&quot;&gt;StarTrek: Discovery&lt;/a&gt;
begrüßen, doch jetzt erhalten sie (wie der zurück auf der USS Enterprise) ihre
eigene Serie und dürfen damit die ursprüngliche Enterprise noch vor Captain 
Kirk durch das Galaxie springen lassen.&lt;/p&gt;

&lt;p&gt;Das krasseste ist natürlich das Raumschiff Enterprise selbst, denn mit jeder
neuen Serie sieht das Schiff moderner aus und hat inzwischen überhaupt nichts
mehr mit der Darstellung zu tun, die wir in der ursprünglichen Serie gesehen
haben.&lt;/p&gt;

&lt;p&gt;Die Serie soll das alte Schema wiederbeleben, dass jede Folge ein anderes
Problem (== anderer Planet) behandelt wird. Verstrickte Zusammenhänge wie
in StarTrek Picard oder Discovery sollen reduziert werden.&lt;/p&gt;

&lt;p&gt;Und von daher hat mich die neue Serie mit der ersten Folge schon überzeugt.
Mal sehen wie es weitergehen wird.&lt;/p&gt;

&lt;h3 id=&quot;dr-strange&quot;&gt;Dr Strange&lt;/h3&gt;

&lt;p&gt;WTF! So viele brutale Tötungen habe ich in einem Marvel Film noch nie 
gesehen. Kein Wunder, dass der Film also Horrorstreifen angekündigt wurde.&lt;/p&gt;

&lt;p&gt;Zwar muss man sagen, dass ein echter Horrorfilm noch viel mehr Grusel 
beinhalten muss, aber für Marvel war das neu.&lt;/p&gt;

&lt;p&gt;Wer den Film vollständig verstehen will, muss die Serie
&lt;a href=&quot;https://de.wikipedia.org/wiki/WandaVision&quot;&gt;WandaVision&lt;/a&gt; gesehen haben, wo
Wanda Maximoff &lt;a href=&quot;https://de.wikipedia.org/wiki/Elizabeth_Olsen&quot;&gt;Elizabeth Olson&lt;/a&gt; 
zur Scarlet Witch wird und am wichtigsten: Wo man den Hintergrund um ihre 
Kinder mitverfolgen kann.&lt;/p&gt;

&lt;p&gt;Dass die beiden Jungs Billy (&lt;a href=&quot;https://de.wikipedia.org/wiki/Julian_Hilliard&quot;&gt;Julian Hilliard&lt;/a&gt;)
und Tommy (&lt;a href=&quot;https://de.wikipedia.org/wiki/Jett_Klyne&quot;&gt;Jett Klyne&lt;/a&gt;) im Film 
waren war mein persönliches Highlight, denn ich mochte die beiden bereits
in der Serie sehr.&lt;/p&gt;

&lt;p&gt;Thematisiert wird das Multiversum und eine neue Figur, America Chavez 
(&lt;a href=&quot;https://de.wikipedia.org/wiki/Xochitl_Gomez&quot;&gt;Xochitl Gomez&lt;/a&gt;), die durch 
dieses reisen kann, aber nicht wirklich Herr über diese Fähigkeit ist.
Immer wenn das Mädchen Angst bekommt öffnet sich ein Portal und schon 
wechsel sie in eine andere Welt.&lt;/p&gt;

&lt;p&gt;Und Angst hat sie zurecht, weil dunkle Mächte ihre diese Fähigkeit entziehen
wollen. Letztendlich landet sie bei “unserem” Dr. Strange, dessen Aufgabe 
es wird, sie zu beschützen.&lt;/p&gt;

&lt;p&gt;Der interessante Teil des Films ist, dass man nie so richtig weiß, wer der 
Gute und wer der Böse ist und wann sich der Status ändert.
Und wenn die Grenzen zwischen den Welten überschritten werden und die
Protagonisten auf ihre Alter-Egos in anderen Universen treffen, ergeben
sich interessante neue Aspekte.&lt;/p&gt;

&lt;p&gt;Leider kann man hier wirklich nichts weiteres sagen ohne einem den Film
zu verderben und das möchte ich keinesfalls.&lt;/p&gt;

&lt;p&gt;Dieses Spektakel muss man im Kino gesehen haben!&lt;/p&gt;

&lt;p&gt;Ich hätte zwar gesagt:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Weniger ist mehr!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Und vielleicht hätte man eine Welt herauskürzen können und mehr Interaktion
zwischen den Charakteren setzen sollen, denn der Film wirkt schon recht
“gehetzt”, wenn man stets neue Welten findet und bald danach wieder verlassen
muss.&lt;/p&gt;

&lt;p&gt;Ich hatte jedenfalls meinen Spaß bei der Premiere am Mittwoch und bin jetzt
wieder um so gespannter, wie es weiter geht.&lt;/p&gt;

&lt;p&gt;Denn ein dritter Dr. Strange Teil ist quasi schon angekündigt und auch
wissen wir nicht, wie es nun mit Wanda Maximoff weitergehen wird.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Es bleibt also spannend.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Was für eine Woche!&lt;br /&gt;
Crazy … aber trotzdem geil.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Weisheit ohne Zahn</title>
   <link href="https://www.opengate.at/blog/2022/05/wisdom/"/>
   <published>2022-05-06T13:00:00+02:00</published>
   <updated>2022-05-06T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2022/05/wisdom</id>
   <category term="general" />
   <summary type="text">Dass ich die beste Zahnchirurgin aller Zeiten erwischte hatte, war mir klar,
als sie bei der Vorbesprechung den Satz einleitete mit:


  Sie sind ja jetzt schon ein bisschen über dem Teenager-Alter …


um mich dann vorzuwarnen:


  … da wird die Entfernung des Weisheitszahns ein bisschen länger dauern.


Jetzt ist er draußen, und mir geht’s trotzdem (noch) gut.
</summary>
   <content type="html">&lt;p&gt;Dass ich die beste Zahnchirurgin aller Zeiten erwischte hatte, war mir klar,
als sie bei der Vorbesprechung den Satz einleitete mit:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Sie sind ja jetzt schon ein bisschen über dem Teenager-Alter …&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;um mich dann vorzuwarnen:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;… da wird die Entfernung des Weisheitszahns ein bisschen länger dauern.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Jetzt ist er draußen, und mir geht’s trotzdem (noch) gut.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Das hat mich wirklich gefreut, dass ich “nur ein bisschen” über dem 
Teenager-Alter liegen soll. Da hätte ich eigentlich spontan ein
Tränchen rausdrücken sollen und antworten müssen:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;So etwas Liebes hat noch nie jemand zu mir gesagt.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Aber Spaß bei Seite.&lt;/p&gt;

&lt;p&gt;Vor 5 Jahren musste bereits mein rechter am Unterkiefer gezogen werden, weil
durchgerostet war. Der linke durfte bleiben, doch nun begann auch Karies seine
Spur zu ziehen. Zwar ohne Schmerzen doch nun wurde empfohlen ihn vorsorglich
entfernen zu lassen.&lt;/p&gt;

&lt;p&gt;Interessant ist, dass man in der Chirurgie verwundert war, dass mir dieser
nicht gleich im Jungendalter entfernt wurde, doch das hatte man mir bei den 
jährlichen Kontrollen nie angeraten.&lt;/p&gt;

&lt;h3 id=&quot;termin-10-uhr&quot;&gt;Termin 10 Uhr&lt;/h3&gt;

&lt;p&gt;Gestartet wurde mit 2 ordentlichen Spritzen zur Betäubung, die ich 20 Minuten
lang “einwirken” lassen musste. Am Unterhaltungsmonitor, der heute in keiner
Praxis mehr fehlt, lief Popeye, der ständig Bluto aufs Maul schlug … auch
ein interessanter Aspekt.&lt;/p&gt;

&lt;p&gt;Dann ging es los. Über eine halbe Stunde lang wurde gebohrt, herausgebrochen
und weiter gebohrt.&lt;br /&gt;
Gespürt habe ich nicht das geringst, obwohl ich permanent darauf wartete,
dass sogleich schlimme Schmerz einsetzen. Denn der Bohrer am Kieferknochen
lässt den Schädel durchaus mitvibrieren. Man spürt das zwar nicht, aber
es hört sich furchtbar an.&lt;/p&gt;

&lt;p&gt;Einige Bohrer gaben an mir den Geist auf und mussten durch neue ersetzt werden.
Meine Ärztin meinte, dass sie schon lange kein so hartes Zahnmaterial mehr 
gesehen hätte.&lt;br /&gt;
Das ist wohl der Grund dafür, dass der Eingriff häufiger im Teenager-Alter 
gemacht wird, wo der Knochen noch viel weicher ist.&lt;/p&gt;

&lt;p&gt;Doch mit einigem Werken und Ziehen wurde der Zahn mit seine vier verdrehten
Wurzeln, der seitlich tief vergraben war, letztendlich entfernt.&lt;/p&gt;

&lt;p&gt;Hier zeigt sich wieder mal die Kunst der Medizin, die einem 
hochspezialisiertem Handwerk gleicht.&lt;/p&gt;

&lt;h3 id=&quot;medikation&quot;&gt;Medikation&lt;/h3&gt;

&lt;p&gt;Meine letzte Entfernung vor 5 Jahren hatte einen Seiteneffekt: Die Heilung
setzte nicht wie gewünscht ein und zwei Tage später fingen die Schmerzen
so richtig an.&lt;br /&gt;
Ich hoffe, dass diesmal alles “normal” verläuft, womit ich noch ein paar
Tage Schmerzmittel und Antibiotika nehme und dann alles ganz natürlich
weiter verheilt.&lt;/p&gt;

&lt;p&gt;Seractil forte 400mg sollen mir die anfänglichen Schmerzen nehmen und 
Augmentin 875 mg wird als Antibiotikum dienen.&lt;/p&gt;

&lt;p&gt;Auch da erinnere ich mich daran, dass ich beim letzten Mal noch dachte:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ach was, so schlimm war das nicht, die Schmerzmittel werde ich nicht
aufbrauchen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Alter Schwede, war ich am Ende froh, dass es diese Mittel gibt.&lt;br /&gt;
Wenn nämlich der ganze Kopf zu hämmern beginnt, ist man für jede Form
der Linderung einfach nur dankbar.&lt;/p&gt;

&lt;h3 id=&quot;empfehlungen-und-ausblicke&quot;&gt;Empfehlungen und Ausblicke&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;Keine Milch!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;hieß es sofort, denn Milch dürfte die Aufnahme des Antibiotikums 
erschweren.&lt;br /&gt;
Anstatt dessen soll man “normal” essen, aber nichts Hartes, was die
Wunde reizen könnte.&lt;/p&gt;

&lt;p&gt;Auch soll man weiter (mit Vorsicht) die Zähne putzen aber nie durchspülen,
weil das ebenso der Wundheilung schadet.&lt;/p&gt;

&lt;p&gt;Wichtig ist auch, die Wange keiner Wärme auszusetzen, denn das kann zu einer
starken Schwellung führen.&lt;br /&gt;
Zum Glück habe ich aber noch vom letzten Mal Gelkühlpacks, die man im
Kühlschrank aufbewahrt und dann an die Wange legen kann um sie zu kühlen.
Ein altes Stirnbad bindet nun das Gelpack an mich.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Das war es dann also … mit meiner Weisheit.&lt;/p&gt;

&lt;p&gt;Wie der weitere Verlauf sein wird, wird sich noch zeigen, aber ich habe
ein gutes Gefühl da bisher alles reibungslos verlaufen ist.&lt;/p&gt;

&lt;p&gt;Respekt kann ich der Zahnmedizin zollen, die heute in kürzester Zeit
solche Eingriffe für den Patienten unkompliziert durchführen kann.&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>Keyboards</title>
   <link href="https://www.opengate.at/blog/2022/05/keyboards/"/>
   <published>2022-05-01T13:00:00+02:00</published>
   <updated>2022-05-01T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2022/05/keyboards</id>
   <category term="hardware" />
   <summary type="text">Und wieder sind 40 Euro sinnlos verbrannt, weil ich nicht genau genug 
aufgepasst habe.
Aber wieso ist es heute notwendig aufzupassen, dass eine 
Tastatur auch alle üblichen 
Tasten hat?

Denn früher gab es Standards … heute gibt es jedoch Chaos.

</summary>
   <content type="html">&lt;p&gt;Und wieder sind 40 Euro sinnlos verbrannt, weil ich nicht genau genug 
aufgepasst habe.&lt;br /&gt;
Aber wieso ist es heute notwendig aufzupassen, dass eine 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Tastatur&quot;&gt;Tastatur&lt;/a&gt; auch alle üblichen 
Tasten hat?&lt;/p&gt;

&lt;p&gt;Denn früher gab es Standards … heute gibt es jedoch Chaos.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;In Ländern mit lateinischen Buchstaben gibt es grundsätzlich zwei 
Tastaturlayouts:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;em&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/American_National_Standards_Institute&quot;&gt;ANSI&lt;/a&gt;:&lt;/em&gt; 
Das originale amerikanische Format, das man leicht an der einzeiligen 
&lt;code&gt;ENTER&lt;/code&gt; Taste erkennt.&lt;br /&gt;
&lt;img src=&quot;/blog/assets/img/keyboard-layout-ansi-de.jpg&quot; alt=&quot;Keyboard-Layout-ANSI-DE&quot; /&gt;&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Internationale_Organisation_f%C3%BCr_Normung&quot;&gt;ISO&lt;/a&gt;:&lt;/em&gt; 
In unseren Breiten bevorzugt benutzt und bekannt durch seine zweizeilige 
Eingabe-Taste.&lt;br /&gt;
&lt;img src=&quot;/blog/assets/img/keyboard-layout-iso-de.jpg&quot; alt=&quot;Keyboard-Layout-ISO-DE&quot; /&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Die meisten europäischen Länder nutzen ISO, belegen aber die Tasten
entsprechend ihren Bedürfnissen, wie z.B. das deutsche  &lt;code&gt;Y&lt;/code&gt; und &lt;code&gt;Z&lt;/code&gt;, 
die in den meisten anderen Ländern im Verhältnis zu uns vertauscht sind.&lt;/p&gt;

&lt;p&gt;Im amerikanischen ANSI sind einige Tasten breiter (wie &lt;code&gt;ENTER&lt;/code&gt; und &lt;code&gt;SHIFT&lt;/code&gt;),
weil sie keinen Raum für Sondertasten wie unsere Umlaute vorsehen und 
an eben diesen Plätzen Zeichen wie &lt;code&gt;;&lt;/code&gt; oder &lt;code&gt;\&lt;/code&gt; verbaut haben.&lt;/p&gt;

&lt;p&gt;Von daher musste ich bei der Bestellung einer Tastatur nur darauf achten,
dass “ISO” oder “DE-Layout” in der Produktbeschreibung vermerkt war und ob
die &lt;code&gt;ENTER&lt;/code&gt; Taste einzeilig oder zweizeilig war.&lt;/p&gt;

&lt;p&gt;Ein meiner älteren deutschen ANSI-artigen Tastaturen (siehe Bild bei ANSI) 
verletzte bereits den Standard, da die linke SHIFT Taste klein und neben ihr
das ISO-Größer/kleinerzeichen zu finden war.&lt;/p&gt;

&lt;p&gt;Ich konnte sie aber dennoch nie ordentlich nutzen, weil ich beim Tippen eines 
Hashtags immer versehentlich &lt;code&gt;ENTER&lt;/code&gt; auslöste, was im Chat besonders blöd
rüberkam. Doch zumindest waren “alle” Tasten darauf irgendwie zu finden.&lt;/p&gt;

&lt;h3 id=&quot;programmiererfeindliche-tasten&quot;&gt;Programmiererfeindliche Tasten&lt;/h3&gt;

&lt;p&gt;Da kaufe ich mir also eine neue Tastatur im Online-Handel, bekomme sie, bin
begeistert von der Ausführung, schließe sie an, genieße die ersten Eingaben
und starte dann &lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_Studio&quot;&gt;Visual Studio&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Ich tippe die ersten Zeilen, bis ich zur ersten Objektmember komme, will
&lt;code&gt;object-&amp;gt;method&lt;/code&gt; tippen, doch der Pfeil will nicht erscheinen.&lt;/p&gt;

&lt;p&gt;Erster Gedanke: &lt;em&gt;defekte Taste&lt;/em&gt;.&lt;br /&gt;
Aber nein, ich sehe hin und kann es nicht fassen …&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Die Größer-Kleinerzeichen-Taste fehlt.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/keyboard-layout-iso-shift.jpg&quot; alt=&quot;Keyboard-Layout-ISO-SHIFT&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Anstatt dass in der zweiten Zeile von unten nach der SHIFT Taste die
Ungleichheitszeichen-Taste kommt, wurde die SHIFT-Taste um genau eine
Tastelänge verbreitert.&lt;br /&gt;
Das entspricht eigentlich wieder der ANSI-Norm, doch laut &lt;code&gt;ENTER&lt;/code&gt; Taste 
(und Produktbeschreibung) habe ich eine deutsche ISO Tastatur vor mir.&lt;/p&gt;

&lt;p&gt;Enttäuschung breitete sich aus, dennoch begann ich, eine alternative
Taste auf dem Keyboard zu suchen.&lt;br /&gt;
Die Hersteller mussten doch eine andere Möglichkeit vorgesehen haben,
um solche Zeichen mit dem deutschen Layout erhalten zu können.&lt;/p&gt;

&lt;p&gt;Doch leider &lt;em&gt;NEIN&lt;/em&gt;. Auch mit den Funktionstasten war es nicht möglich, 
die fehlende Taste per “Umschaltung” zu ersetzen.
Lediglich Kombinationen wie &lt;code&gt;Alt&lt;/code&gt; + &lt;code&gt;60&lt;/code&gt; oder  &lt;code&gt;Alt&lt;/code&gt; + &lt;code&gt;62&lt;/code&gt;  konnten
unter Windows den Tastendruck per  ASCII Code nachstellen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;Lieber einmal öfter kontrollieren!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Denn die “komische” ANSI-Shift-Taste auf der deutschen ISO-Tastatur war auch 
auf der Verpackung und der Abbildung auf der Bestellseite dokumentiert, 
doch ich achtete nur auf die Größe der &lt;code&gt;ENTER&lt;/code&gt; Taste.&lt;br /&gt;
&lt;strong&gt;Fail!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Mich ärgert es schon ziemlich, dass solche Fabrikate überhaupt existieren, 
doch offenbar dachte man, dass Gamer ohnehin keine Ungleichheitszeichen 
tippen müssen, aber häufig &lt;code&gt;SHIFT&lt;/code&gt; zum Ducken brauchen und schuf dieses 
Hybridmodell.&lt;/p&gt;

&lt;p&gt;Als Konsequenz darauf marschierte ich (nach langem wieder einmal persönlich)
zum Elektronikladen, wählte eine alternative Tastatur, ließ sie mir 
vorsorglich vom Berater auspacken und vorzeigen um letzte Zweifel 
auszuräumen und kaufte sie anschließend.&lt;/p&gt;

&lt;p&gt;Ab sofort kann ich wieder ordentlich programmieren und &lt;code&gt;object-&amp;gt;method()&lt;/code&gt; 
ohne Hilfsmittel abtippen.&lt;/p&gt;

&lt;p&gt;Eine kurzfristige Zwischenlösung bereiteten mir die 
&lt;a href=&quot;https://github.com/microsoft/PowerToys/releases&quot;&gt;PowerToys für Windows 10&lt;/a&gt;,
mit denen man Tasten “umleiten” kann.&lt;/p&gt;

&lt;p&gt;Ich behalf mir, indem ich die Taste &lt;code&gt;F11&lt;/code&gt; auf &lt;code&gt;&amp;lt;&lt;/code&gt; imd &lt;code&gt;F12&lt;/code&gt; auf &lt;code&gt;&amp;gt;&lt;/code&gt; umwandeln ließ.&lt;/p&gt;

&lt;p&gt;Ganz sinnlos war mein Fehlkauf aber trotzdem nicht, schließlich komme ich mit
meinen &lt;a href=&quot;/blog/2022/04/uefi-gcc/&quot;&gt;UEFI&lt;/a&gt; Experimenten ohnehin immer 
in den Genuss eines amerikanischen Tastaturlayouts und somit bin ich diesem 
zumindest um “eine Taste” näher gekommen. Allerdings sitzen für dieses Schema 
&lt;code&gt;\&lt;/code&gt; und &lt;code&gt;|&lt;/code&gt;  wiederum falsch, die eigentlich über der einzeiligen &lt;code&gt;ENTER&lt;/code&gt; 
Taste angebracht sein sollte.
Doch bei mir liegt sie unten neben der zweizeiligen Eingabetaste.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Früher war eben alles besser … unterscheidbar.&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>MSVC&apos;s verbockter C11-Support</title>
   <link href="https://www.opengate.at/blog/2022/04/msvc-c11/"/>
   <published>2022-04-30T13:00:00+02:00</published>
   <updated>2022-04-30T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2022/04/msvc-c11</id>
   <category term="devel" />
   <summary type="text">Aus meiner Sicht sollte jedes OS 
und jeder Compiler so funktionieren:


  Die wichtigsten OS Features sind durch die 
C Standard
Bibliothek abgebildet. Und die C++
Implementierung baut genau auf diesen C Standard auf.


Microsoft hingegen pfiff bis 2020 
auf den C Standard und baute langsamst nur C++11 und C++14 ein.

Doch tief versteckt im Wald, findet man seit 2017 den Header thr/xthreads.h

</summary>
   <content type="html">&lt;p&gt;Aus meiner Sicht sollte jedes &lt;a href=&quot;https://de.wikipedia.org/wiki/Betriebssystem&quot;&gt;OS&lt;/a&gt; 
und jeder Compiler so funktionieren:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Die wichtigsten OS Features sind durch die 
&lt;a href=&quot;https://de.wikipedia.org/wiki/C_(Programmiersprache)&quot;&gt;C Standard&lt;/a&gt;
Bibliothek abgebildet. Und die &lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B&quot;&gt;C++&lt;/a&gt;
Implementierung baut genau auf diesen C Standard auf.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft&quot;&gt;Microsoft&lt;/a&gt; hingegen pfiff bis 2020 
auf den C Standard und baute langsamst nur C++11 und C++14 ein.&lt;/p&gt;

&lt;p&gt;Doch tief versteckt im Wald, findet man seit 2017 den Header &lt;code&gt;thr/xthreads.h&lt;/code&gt;&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;eine-geschichte-des-verschweigens&quot;&gt;Eine Geschichte des Verschweigens&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://www.cplusplus.com/reference/thread/thread/&quot;&gt;Threads&lt;/a&gt;, 
&lt;a href=&quot;https://www.cplusplus.com/reference/mutex/&quot;&gt;Mutexe&lt;/a&gt;, 
&lt;a href=&quot;https://www.cplusplus.com/reference/condition_variable/&quot;&gt;Condition-Variablen&lt;/a&gt; 
und Thread-Local-Storage sind Teil des
C11 Standards.&lt;br /&gt;
Der kam damals (2011) auch schon 10 Jahre zu spät, denn eigentlich gibt es
keine Entschuldigung dafür, dass nach dem Jahr 2000 auch nur eine einzige
Sprachvariante auf Threads verzichten musste.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_Application_Programming_Interface&quot;&gt;Win32&lt;/a&gt;
Threads und &lt;a href=&quot;https://de.wikipedia.org/wiki/Portable_Operating_System_Interface&quot;&gt;POSIX&lt;/a&gt; 
Threads sind seit Mitte der 90er spezifiziert, und Microsofts fehlende 
Condition-Variablen wurden seit den 2000ern mit Workarounds ersetzt.&lt;br /&gt;
Es ist also schon lange alles da, was man zu einem übergreifenden Standard
vereinen hätte können.&lt;/p&gt;

&lt;p&gt;Doch da Microsoft den C-Teil seines C++ Compilers auf dem Stand von 1989
belassen hatte (nicht mal C99 war unterstützt) und nur auf C++ setzte, hätte
diese Story auch hier enden können.&lt;/p&gt;

&lt;p&gt;Mit dem &lt;a href=&quot;https://en.wikipedia.org/wiki/Microsoft_Visual_C%2B%2B&quot;&gt;MSVC&lt;/a&gt; 2013 
setzte ein Umdenken ein und plötzlich waren C99 Codes halbwegs fehlerfrei 
kompilierbar, was die Kernsprache betraf.&lt;br /&gt;
Ich bemerkte das daran, dass &lt;a href=&quot;https://de.wikipedia.org/wiki/LibreSSL&quot;&gt;libReSSL&lt;/a&gt;
plötzlich kompilierbar wurde, welche vom MSVC 2012 abgelehnt worden war.&lt;br /&gt;
Endlich konnte ich von &lt;a href=&quot;https://de.wikipedia.org/wiki/OpenSSL&quot;&gt;OpenSSL&lt;/a&gt;
zur libReSSL wechseln.&lt;/p&gt;

&lt;h3 id=&quot;thrd-mtx-und-cnd-per-define&quot;&gt;thrd, mtx und cnd per define&lt;/h3&gt;

&lt;p&gt;Spätestens 2015 hätte dann meines Erachtens &lt;code&gt;thrd_create&lt;/code&gt;, &lt;code&gt;mtx_lock&lt;/code&gt; und
&lt;code&gt;cnd_signal&lt;/code&gt; auch bei Microsoft ihren Siegeszug antreten können, doch aus 
irgend einem seltsamen Grund, wurde das abgewendet und in den Hintergrund
gedrängt.&lt;/p&gt;

&lt;p&gt;Denn in MSVC 2015 und MSVC 2017 existiert der Header &lt;code&gt;thr/xthreads.h&lt;/code&gt; 
inklusive CRT Implementierung, der zwar nicht den C11 Standard umsetzt, aber 
fast ausschließlich aus C11-ähnlichen Symbolen besteht.&lt;/p&gt;

&lt;p&gt;Tatsächlich fehlen nur noch ein paar Makros, um aus den &lt;code&gt;xthreads&lt;/code&gt; 
vernünftige C11 Funktionen zu machen.&lt;/p&gt;

&lt;p&gt;Und genau das findet auch im GATE Projekt statt, wenn man dieses mit der
C11-Option baut:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color:#B44;font-weight:bold&quot;&gt;&amp;lt;thr/xthreads.h&amp;gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#define&lt;/span&gt; thrd_t       _Thrd_t
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#define&lt;/span&gt; thrd_start_t _Thrd_start_t
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#define&lt;/span&gt; thrd_create(thr, fun, arg) _Thrd_create(thr, fun, arg)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#define&lt;/span&gt; thrd_detach(thr)           _Thrd_detach(thr)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#define&lt;/span&gt; thrd_exit(code)            _Thrd_exit(code)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#define&lt;/span&gt; thrd_join(thr, res)        _Thrd_join(thr, res)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#define&lt;/span&gt; thrd_sleep(tm)             _Thrd_sleep(tm)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#define&lt;/span&gt; thrd_yield                 _Thrd_yield
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#define&lt;/span&gt; thrd_equal(thr0, thr1)     _Thrd_equal(thr0, thr1)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#define&lt;/span&gt; thrd_current               _Thrd_current
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#define&lt;/span&gt; thrd_success _Thrd_success
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#define&lt;/span&gt; thrd_nomem   _Thrd_nomem
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#define&lt;/span&gt; thrd_timeout _Thrd_timedout
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#define&lt;/span&gt; thrd_busy    _Thrd_busy
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#define&lt;/span&gt; thrd_error   _Thrd_error
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n21&quot; name=&quot;n21&quot;&gt;21&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#define&lt;/span&gt; mtx_t                       _Mtx_t
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n22&quot; name=&quot;n22&quot;&gt;22&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#define&lt;/span&gt; mtx_init(ptr_mtx, mtx_type) _Mtx_init(ptr_mtx, mtx_type)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n23&quot; name=&quot;n23&quot;&gt;23&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#define&lt;/span&gt; mtx_destroy(ptr_mtx)        _Mtx_destroy(*ptr_mtx)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n24&quot; name=&quot;n24&quot;&gt;24&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#define&lt;/span&gt; mtx_lock(ptr_mtx)           _Mtx_lock(*ptr_mtx)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n25&quot; name=&quot;n25&quot;&gt;25&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#define&lt;/span&gt; mtx_unlock(ptr_mtx)         _Mtx_unlock(*ptr_mtx)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n26&quot; name=&quot;n26&quot;&gt;26&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#define&lt;/span&gt; mtx_trylock(ptr_mtx)        _Mtx_trylock(*ptr_mtx)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n27&quot; name=&quot;n27&quot;&gt;27&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n28&quot; name=&quot;n28&quot;&gt;28&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#define&lt;/span&gt; mtx_plain     _Mtx_plain
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n29&quot; name=&quot;n29&quot;&gt;29&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#define&lt;/span&gt; mtx_timed     _Mtx_timed
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n30&quot; name=&quot;n30&quot;&gt;30&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#define&lt;/span&gt; mtx_recursive _Mtx_recursive
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n31&quot; name=&quot;n31&quot;&gt;31&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n32&quot; name=&quot;n32&quot;&gt;32&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#define&lt;/span&gt; cnd_t                      _Cnd_t
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n33&quot; name=&quot;n33&quot;&gt;33&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#define&lt;/span&gt; cnd_init(ptr_cnd)          _Cnd_init(ptr_cnd)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n34&quot; name=&quot;n34&quot;&gt;34&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#define&lt;/span&gt; cnd_destroy(ptr_cnd)       _Cnd_destroy(*ptr_cnd)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n35&quot; name=&quot;n35&quot;&gt;35&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#define&lt;/span&gt; cnd_signal(ptr_cnd)        _Cnd_signal(*ptr_cnd)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n36&quot; name=&quot;n36&quot;&gt;36&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#define&lt;/span&gt; cnd_broadcast(ptr_cnd)     _Cnd_broadcast(*ptr_cnd)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n37&quot; name=&quot;n37&quot;&gt;37&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#define&lt;/span&gt; cnd_wait(ptr_cnd, ptr_mtx) _Cnd_wait(*ptr_cnd, *ptr_mtx)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n38&quot; name=&quot;n38&quot;&gt;38&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#define&lt;/span&gt; cnd_timedwait(ptr_cnd, ptr_mtx, ptr_timespec) \
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n39&quot; name=&quot;n39&quot;&gt;39&lt;/a&gt;&lt;/span&gt;  _Cnd_timedwait(*ptr_cnd, *ptr_mtx, (xtime &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt;*)ptr_timespec)
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Nachdem diese Ähnlichkeiten also schon so groß sind, frage ich mich, was
wohl der Grund war, diese nützliche C-Schicht im Hintergrund zu verstecken.&lt;/p&gt;

&lt;p&gt;Absolut unverzeihlich ist aber das, was im MSVC 2019 und 2022 dann gemacht
wurde. Denn hier hat Microsoft den Header &lt;code&gt;thr/xthreads.h&lt;/code&gt; entfernt und 
durch den kürzeren Pfad &lt;code&gt;xthreads.h&lt;/code&gt; ersetzt.&lt;/p&gt;

&lt;p&gt;Dieser neue &lt;code&gt;xthreads.h&lt;/code&gt; setzt (aus meiner Sicht vollkommen unverständlich)
C++ Vokabel ein und schließt damit die Nutzung von reinem C aus.&lt;br /&gt;
Es handelt sich um die exakt gleichen C Funktionen &lt;code&gt;_Thrd_*&lt;/code&gt;, &lt;code&gt;_Mtx_*&lt;/code&gt;, 
&lt;code&gt;_Cnd_*&lt;/code&gt;, doch weil irgend ein Vollhonk ein paar &lt;code&gt;typedef&lt;/code&gt;s durch &lt;code&gt;using&lt;/code&gt;
ersetzt hat und alles mit dem &lt;code&gt;namespace std&lt;/code&gt; einleitet, wurde die
C Kompatibilität sinnlos zerstört.&lt;/p&gt;

&lt;p&gt;Noch abstruser ist, dass im Dev-Blog angekündigt wurde, dass der 
C11-Library Support in Arbeit ist, doch leider bis zum MSVC 2022 Release
noch nicht fertig war.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Wie konnte man das also so verbocken, dass man 2015 quasi schon 
fertig war (siehe &lt;code&gt;#define&lt;/code&gt; Beispiel), und 2019 dann alles mit wenigen
C++ Phrasen zerstört hat ???&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Eine ähnliche Katastrophe ereignete sich auch bei &lt;code&gt;stdatomic.h&lt;/code&gt;, das es
2015 auch schon als &lt;code&gt;xatomic.h&lt;/code&gt; gab. Doch dort lag von Anfang an alles im 
C++ Namespace, wobei die Routinen trotzdem die meisten C11 
Atomic-Funktionen nachbilden.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Im GATE Framework werden letztendlich alle diese Wirrungen der vergangenen 
Dekaden sichtbar. Nämlich wenn ich C11 &lt;code&gt;cnd_t&lt;/code&gt; Typen nutze um Semaphoren 
nachzubauen und parallel dazu im &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_NT_4.0&quot;&gt;NT4&lt;/a&gt; 
Layer mit Win32 &lt;a href=&quot;https://de.wikipedia.org/wiki/Semaphor_(Informatik)&quot;&gt;Semaphoren&lt;/a&gt;
Condition-Variablen simuliert werden.&lt;/p&gt;

&lt;p&gt;Hätte es bereits gegen 2003 einen Standard wie C11 gegeben und wäre Microsoft
hierbei fitter gewesen, hätten wir (in einer idealen Welt) bereits 2005 mit 
standardisierten C-Threads arbeiten können.&lt;br /&gt;
Viele unnötige Workarounds wären uns erspart geblieben und C++ hätte seine
&lt;code&gt;std::threads&lt;/code&gt; auf einem stabilen (und leichtgewichtigen) C-Fundament aufbauen
können.&lt;/p&gt;

&lt;p&gt;Ich bezweifle, dass (außer mir) noch andere Entwickler multi-threaded 
Standard-C Codes in Windows einsetzen. Und das ist mehr als schade, 
denn die effizientesten Webserver und Sprachcompiler liegen bis heute in 
reinem C Code vor.&lt;/p&gt;

&lt;p&gt;Tja … heute heißt es also:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Früher hätte alles besser werden können.&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>UEFI, CMake und GCC</title>
   <link href="https://www.opengate.at/blog/2022/04/uefi-gcc/"/>
   <published>2022-04-24T13:00:00+02:00</published>
   <updated>2022-04-24T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2022/04/uefi-gcc</id>
   <category term="devel" />
   <summary type="text">Manchmal sind es die Dinge, wo man denkt:


  Ach, das sollte in 15 Minuten erledigt sein.


die einen dann den ganzen Tag (oder länger) beschäftigen.

Mir erging es mit der Einrichtung eines CMake 
Scripts für UEFI-Apps in einer 
GCC 
Linux Umgebung heute so.

</summary>
   <content type="html">&lt;p&gt;Manchmal sind es die Dinge, wo man denkt:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ach, das sollte in 15 Minuten erledigt sein.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;die einen dann den ganzen Tag (oder länger) beschäftigen.&lt;/p&gt;

&lt;p&gt;Mir erging es mit der Einrichtung eines &lt;a href=&quot;https://de.wikipedia.org/wiki/CMake&quot;&gt;CMake&lt;/a&gt; 
Scripts für &lt;a href=&quot;/blog/2021/11/efi-apps/&quot;&gt;UEFI-Apps&lt;/a&gt; in einer 
&lt;a href=&quot;https://de.wikipedia.org/wiki/GNU_Compiler_Collection&quot;&gt;GCC&lt;/a&gt; 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt; Umgebung heute so.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Der &lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_C%2B%2B&quot;&gt;MSVC&lt;/a&gt; hat es mir mit seinem 
EFI-Applications Build-Typ recht einfach gemacht, Apps ohne Betriebssystem 
zu erstellen.&lt;br /&gt;
Doch ein großes Problem stellen &lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B&quot;&gt;C++&lt;/a&gt;, 
seine Exception und &lt;a href=&quot;https://de.wikipedia.org/wiki/Runtime_Type_Information&quot;&gt;RTTI&lt;/a&gt; 
dar, bei denen der MSVC Code generiert, der eine C-Runtime voraussetzt, die 
an den Windows &lt;a href=&quot;https://de.wikipedia.org/wiki/Kernel_(Betriebssystem)&quot;&gt;Kernel&lt;/a&gt; 
angepasst ist … also etwas, was in UEFI nicht existiert.&lt;/p&gt;

&lt;p&gt;Der &lt;code&gt;GCC&lt;/code&gt; hingegen lässt sich leichter dazu bewegen, solche Datenstrukturen
generisch zu erzeugen, und somit war mein erster Schritt schon festgelegt:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ich möchte den EFI-App-Build in einer GCC Umgebung durchführen können.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Doch da der &lt;code&gt;GCC&lt;/code&gt; unter Linux das &lt;a href=&quot;https://de.wikipedia.org/wiki/Executable_and_Linking_Format&quot;&gt;ELF-Format&lt;/a&gt; 
einsetzt und UEFI APIs auf Microsofts &lt;a href=&quot;https://de.wikipedia.org/wiki/Common_Object_File_Format&quot;&gt;COFF&lt;/a&gt;
Spezifikation aufsetzen, gestaltet sich das Bauen von UEFI-Apps im &lt;code&gt;GCC&lt;/code&gt; 
wesentlich schwieriger.&lt;/p&gt;

&lt;h3 id=&quot;makefile-analyse&quot;&gt;Makefile Analyse&lt;/h3&gt;

&lt;p&gt;Die GNU-EFI Bibliothek sieht folgende Prozedur vor:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Die EFI-Schnittstellen werden in eine statische &lt;code&gt;libefi.a&lt;/code&gt; kompiliert.&lt;/li&gt;
  &lt;li&gt;Der (&lt;a href=&quot;https://de.wikipedia.org/wiki/Assemblersprache&quot;&gt;Assembler&lt;/a&gt; basierte) 
Startup Code kommt in die statische &lt;code&gt;libgnuefi.a&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Die eigene EFI-App wird als &lt;code&gt;shared library&lt;/code&gt; gebaut, die gegen die beiden 
vorherigen mit ein paar speziellen Flags linkt.&lt;/li&gt;
  &lt;li&gt;Das Tool &lt;code&gt;objcopy&lt;/code&gt; extrahiert die Code und Datenbereiche aus der 
&lt;code&gt;shared lib&lt;/code&gt; und baut daraus ein EFI-App-Binary mit dem richtigen 
Target-Subsystem zusammen.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Wichtige Compiler-Optionen hierfür sind:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;-ffreestanding&lt;/code&gt;: Verzicht auf die übliche C-Standard-Bibliothek&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;-fpic&lt;/code&gt;: Shared-lib position independent code&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;-fshort-wchar&lt;/code&gt;: wchar_t als 16-bit wie bei Microsoft&lt;/li&gt;
  &lt;li&gt;Deaktivierung diverser Stack-Prüfungen, wie: 
&lt;code&gt;-fno-stack-protector&lt;/code&gt;, &lt;code&gt;-fno-stack-check&lt;/code&gt;, &lt;code&gt;-mno-red-zone&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;und noch ein paar Kleinigkeiten (siehe &lt;code&gt;CMake&lt;/code&gt; Beispiel)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Der Linker braucht folgende Zusätze:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;-shared&lt;/code&gt;: erzeugt eine temporäre dynamische Lib&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;-nostdlib&lt;/code&gt;: Verzicht die übliche C-Standard-Bibliothek zu linken&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;-Bsymbolic&lt;/code&gt;: Verhaltensanpassung, wie Symbole im Code aufgelöst werden&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;-e_start&lt;/code&gt;: Festlegung des Funktionsnamens, der beim App-Start benutzt
werden soll, also &lt;code&gt;_start()&lt;/code&gt;, eine in Assembler geschriebene 
Einsprungfunktion aus &lt;code&gt;libgnuefi.a&lt;/code&gt;.&lt;br /&gt;
Sie initialisiert alles und ruft dann &lt;code&gt;efi_main&lt;/code&gt; auf.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;-T /path/to/gnuefi/elf_x86_64_efi.lds&lt;/code&gt; Pfad zum Linkerscript, das
wichtige Details zum Linken der EFI-App beinhaltet.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Die &lt;code&gt;Makefile&lt;/code&gt; Dateien, die &lt;code&gt;gnu-efi&lt;/code&gt; mitliefert, dokumentieren, dass 
&lt;code&gt;libgnuefi.a&lt;/code&gt; zwar gelinkt wird, aber dass das &lt;code&gt;crt0&lt;/code&gt; Objekt (&lt;code&gt;*.o&lt;/code&gt;) 
trotzdem nochmal separat zur finalen EFI-App gelinkt wird.&lt;br /&gt;
So wird die darin enthaltene &lt;code&gt;_start&lt;/code&gt; Funktion automatisch zum 
Einsprungpunkt.&lt;/p&gt;

&lt;p&gt;Bei meinen Tests, wo ich die &lt;code&gt;.o&lt;/code&gt; nicht mehr separat angab, musste ich 
den Einsprungpunkt eben mit &lt;code&gt;-e_start&lt;/code&gt; festlegen, ansonsten wählte der 
Compiler selbsttätig immer &lt;code&gt;efi_main&lt;/code&gt; aus.&lt;/p&gt;

&lt;h3 id=&quot;cmake-umsetzung&quot;&gt;CMake Umsetzung&lt;/h3&gt;

&lt;p&gt;Das Standard &lt;code&gt;CMake&lt;/code&gt; Setup nutzt &lt;code&gt;cc&lt;/code&gt; um seine Kompilate umzusetzen.&lt;br /&gt;
Da die originalen &lt;code&gt;gnu-efi&lt;/code&gt; Sourcen &lt;a href=&quot;https://de.wikipedia.org/wiki/Make&quot;&gt;Makefiles&lt;/a&gt; 
einsetzen, die explizit zwischen &lt;code&gt;gcc&lt;/code&gt; und &lt;code&gt;ld&lt;/code&gt; Aufrufen unterscheiden, muss 
man beim Wechsel zu &lt;code&gt;CMake&lt;/code&gt; mit &lt;code&gt;cc&lt;/code&gt; darauf achten, welche Kommandos für den
Linker bestimmt sind.&lt;/p&gt;

&lt;p&gt;Diese muss man dann mit &lt;code&gt;-Wl,&lt;/code&gt; präfixen, z.B: &lt;code&gt;-Wl,-nostdlib&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Man erhält nun eine EFI &lt;code&gt;.so&lt;/code&gt; Datei, die man aber noch umwanden muss.
Ein Custom-Build-Job mit dem Aufruf von &lt;code&gt;objcopy&lt;/code&gt; führt zum gewünschten 
Ergebnis:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;objcopy -j .text -j .sdata -j .data -j .dynamic -j .dynsym -j .rel -j .rela -j .reloc --target=efi-app-x86_64 my-efi-app.so my-efi-app.efi
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Die Datei &lt;code&gt;my-efi-app.efi&lt;/code&gt; kann nun auf einen mit &lt;a href=&quot;https://de.wikipedia.org/wiki/File_Allocation_Table#FAT32&quot;&gt;FAT32&lt;/a&gt;
formatierten USB Stick kopiert werden.&lt;br /&gt;
Bootet man in die UEFI-Shell, kann man mit &lt;code&gt;fs0:&lt;/code&gt; (oder &lt;code&gt;fsX:&lt;/code&gt; wenn mehrere
Laufwerke erkannt werden) zum Stick wechseln und &lt;code&gt;my-efi-app.efi&lt;/code&gt; einfach 
durch Eingabe des Dateinamens + &lt;code&gt;ENTER&lt;/code&gt; ausführen lassen
(&lt;a href=&quot;https://de.wikipedia.org/wiki/MS-DOS&quot;&gt;DOS&lt;/a&gt; lässt grüßen).&lt;/p&gt;

&lt;p&gt;Wer keine UEFI-Shell in seinem BIOS hat, kann die Datei auch als
&lt;code&gt;/EFI/BOOT/BOOTX64.EFI&lt;/code&gt; speichern und vom Stick booten.&lt;br /&gt;
Die EFI-App wird dann wie ein Bootloader ausgeführt … nur dass 
eben kein OS geladen wird, sondern nur unser Code in &lt;code&gt;efi_main()&lt;/code&gt; 
ausgeführt wird.&lt;/p&gt;

&lt;h3 id=&quot;problem-calling-convention&quot;&gt;Problem Calling Convention&lt;/h3&gt;

&lt;p&gt;… und dann sitze ich stundenlang vor meinem Bildschirm und stelle fest,
dass die erzeugte EFI-App sofort zum Einfrieren des Systems führt.&lt;/p&gt;

&lt;p&gt;Doch erst nach längerer Analyse der Assembler und C Sourcen wurde mir mein
Fehler bewusst.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;_start()&lt;/code&gt; versucht zuerst dynamische Symbole korrekt auszurichten (&lt;code&gt;reloc()&lt;/code&gt;)
und will am Ende die Funktion &lt;code&gt;efi_main&lt;/code&gt; aufrufen, in der der eigene Code
startet.&lt;/p&gt;

&lt;p&gt;Und hier hatte ich die Signatur&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;EFI_STATUS EFIAPI efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable) 
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;gewählt. Und der Token &lt;code&gt;EFIAPI&lt;/code&gt; war des Pudels Kern.
Denn dieses Makro ist im &lt;code&gt;GCC&lt;/code&gt; definiert als:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#define&lt;/span&gt; EFIAPI __attribute__((ms_abi))
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;&lt;code&gt;EFIAPI&lt;/code&gt; wird für die EFI-Schnittstellenfunktionen benutzt und ermahnt 
den &lt;code&gt;GCC&lt;/code&gt; Compiler, die Aufrufe im Microsoft-Format (x86_64) durchzuführen.&lt;/p&gt;

&lt;p&gt;Doch &lt;code&gt;_start&lt;/code&gt; geht davon aus, dass &lt;code&gt;efi_main&lt;/code&gt; eine “lokale” nicht-EFI-Funktion
ist, die sich auch nicht an die Microsoft-Konvention halten muss. Stattdessen 
wird die übliche GCC x86_64 &lt;code&gt;cdecl&lt;/code&gt; Konvention benutzt, bei der die Register 
anders belegt sind.&lt;/p&gt;

&lt;p&gt;Microsoft’s &lt;code&gt;cdecl&lt;/code&gt; nutzt die Register &lt;code&gt;RCX&lt;/code&gt; und &lt;code&gt;RDX&lt;/code&gt; für die ersten beiden 
Parameter und der &lt;code&gt;GCC&lt;/code&gt; nutzt die &lt;code&gt;System-V cdecl&lt;/code&gt; Spezifikation und übergibt die 
gleichen Parameter in den Register &lt;code&gt;RDI&lt;/code&gt; und &lt;code&gt;RSI&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Und so erhielt meine &lt;code&gt;efi_main&lt;/code&gt; Funktion also zwei ungültige Registerwerte,
was den Crash auslöste.&lt;br /&gt;
Die Entfernen von &lt;code&gt;EFIAPI&lt;/code&gt; in &lt;code&gt;efi_main&lt;/code&gt; vermochte mein Problem zu lösen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Nun wo der C-Teil bei &lt;code&gt;GCC&lt;/code&gt;, &lt;code&gt;CMake&lt;/code&gt; und EFI durchprobiert wurde, kann ich 
mich also in Zukunft mehr um die C++ Seiten kümmern.&lt;/p&gt;

&lt;p&gt;Wie “cool” wäre es, wenn man nun auch vollständige C++ Routinen 
außerhalb eines OS nutzen kann?&lt;/p&gt;

&lt;p&gt;Ich freue mich daher schon, diese neue Welt entdecken zu dürfen.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Position Indipendent Code (-fPIC) für Assembler</title>
   <link href="https://www.opengate.at/blog/2022/04/gnu-asm/"/>
   <published>2022-04-23T13:00:00+02:00</published>
   <updated>2022-04-23T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2022/04/gnu-asm</id>
   <category term="devel" />
   <summary type="text">Mit dem Fehler


  /usr/bin/ld: (…S.o): relocation R_X86_64_PC32 against symbol ‘…’ 
can not be used when making a shared object; recompile with -fPIC


konnte ich genau gar nichts anfangen, schließlich hatte ich alle Sourcen
mit -fpic kompiliert.

Was unterscheidet also meine Assembler-Funktion von meinen anderen
C-Funktionen?
</summary>
   <content type="html">&lt;p&gt;Mit dem Fehler&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;/usr/bin/ld: (…S.o): relocation R_X86_64_PC32 against symbol ‘…’ 
can not be used when making a shared object; recompile with -fPIC&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;konnte ich genau gar nichts anfangen, schließlich hatte ich alle Sourcen
mit &lt;code&gt;-fpic&lt;/code&gt; kompiliert.&lt;/p&gt;

&lt;p&gt;Was unterscheidet also meine Assembler-Funktion von meinen anderen
&lt;a href=&quot;https://de.wikipedia.org/wiki/C_(Programmiersprache)&quot;&gt;C-Funktionen&lt;/a&gt;?
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Weil mich der &lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_C%2B%2B&quot;&gt;MSVC&lt;/a&gt; in 
Sachen &lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B&quot;&gt;C++&lt;/a&gt; bei 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Unified_Extensible_Firmware_Interface&quot;&gt;UEFI&lt;/a&gt; im 
Stich lässt, wollte ich das Ganze dem 
&lt;a href=&quot;https://de.wikipedia.org/wiki/GNU_Compiler_Collection&quot;&gt;GCC&lt;/a&gt; anvertrauen.&lt;/p&gt;

&lt;p&gt;Doch das erforderte einige Updates, denn beim GCC kann man nicht so einfach
EFI-Applications erstellen.&lt;br /&gt;
Man baut zuerst spezielle Shared-Libraries und wandelt diese dann in EFI
Anwendungen um.&lt;/p&gt;

&lt;p&gt;Doch hier scheiterte ich an meinen handgeschriebenen Assembler-Implementierungen
für den Stack-Context-Switch bei &lt;a href=&quot;https://de.wikipedia.org/wiki/Koroutine&quot;&gt;Koroutinen&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Konkret ging es um einen Aufruf der Assembler-Funktion &lt;code&gt;B&lt;/code&gt; innerhalb der 
Funktion &lt;code&gt;A&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Wenn &lt;code&gt;A&lt;/code&gt; also &lt;code&gt;B&lt;/code&gt; aufrufen will, gibt es ein Relocation Problem.&lt;/p&gt;

&lt;h3 id=&quot;lösung-plt&quot;&gt;Lösung: @plt&lt;/h3&gt;

&lt;p&gt;Anstatt&lt;/p&gt;

&lt;div class=&quot;language-asm highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;call B
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;nutzt man einfach&lt;/p&gt;

&lt;div class=&quot;language-asm highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;call B@plt
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;und schon lässt sich wieder alles kompilieren.&lt;/p&gt;

&lt;h3 id=&quot;die-hintergründe&quot;&gt;Die Hintergründe&lt;/h3&gt;

&lt;p&gt;Shared-Libraries und EFI schreiben ihre Funktionen nicht an fixe Adressen,
sondern arbeiten mit Einträgen in einer &lt;em&gt;“Global Offset Table”&lt;/em&gt; (&lt;code&gt;GOT&lt;/code&gt;).
Wird eine Lib geladen, landet der Code an einer beliebigen Speicheradresse
und um Funktionen anspringen zu können, muss diese Adresse errechnet werden
können.&lt;/p&gt;

&lt;p&gt;Und genau dafür generiert der Assemblercompiler Hilfsfunktionen die mit &lt;code&gt;@PLT&lt;/code&gt;
(&lt;em&gt;Procedure Linkage Table&lt;/em&gt;) erreicht werden können um zur korrekten Adresse 
der Funktion gelangen zu können.&lt;/p&gt;

&lt;p&gt;Hinter dieser Magie dürfte offenbar relative Adressierung stecken, wo der
Aufruf der &lt;code&gt;@plt&lt;/code&gt; Funktion relativ zur aufrufenden Funktion fix ist und die
&lt;code&gt;@plt&lt;/code&gt; Funktion löst dann die echte aufzurufende Adresse auf und springt hin.&lt;/p&gt;

&lt;p&gt;Eine tolle Aufschlüsselung der Vorgänge findet man unter
&lt;a href=&quot;https://maskray.me/blog/2021-09-19-all-about-procedure-linkage-table&quot;&gt;maskray.me/blog&lt;/a&gt;&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Meine Erwartungen aus der MSVC Welt basieren auf der Vorstellung, dass solche
Details immer im Hintergrund aufgelöst werden müssen.&lt;br /&gt;
Doch wie sich zeigt, muss man beim GCC sehr wohl zwischen Aufrufen 
zu öffentlichen und privaten Funktionen unterscheiden.&lt;/p&gt;

&lt;p&gt;Tja, bisher bin ich von solchen Details verschont geblieben, denn damals, 
als ich mit Assembler noch in der &lt;a href=&quot;https://de.wikipedia.org/wiki/MS-DOS&quot;&gt;DOS&lt;/a&gt; 
Welt unterwegs war, gab es keine Shared-Libraries, die man hätte beachten 
müssen.&lt;br /&gt;
Und heutige &lt;a href=&quot;https://de.wikipedia.org/wiki/Mikrocontroller&quot;&gt;Mikrocontroller&lt;/a&gt;
Spielereien kennen auch keine Relocations.&lt;/p&gt;

&lt;p&gt;Eines kann ich also jede Woche über die Programmierung sagen:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Hier lernt man nie aus!&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>Ostern und die Ratscher-Buam</title>
   <link href="https://www.opengate.at/blog/2022/04/easter-eggs/"/>
   <published>2022-04-17T13:00:00+02:00</published>
   <updated>2022-04-17T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2022/04/easter-eggs</id>
   <category term="general" />
   <summary type="text">Heute erzählte mir meine Mutter, dass seit langem wieder mal ein älterer
Brauch am Land es bis zu ihr in die Seitengasse geschafft hatte:
Die Ratscher.

Als Kind erklärte man mir diesen Osterbrauch sinngemäß so:


  Zu Ostern fliegen die 
Kirchenglocken alle nach Rom.
Und deshalb müssen die Dorfburschen mit ihren Ratschen
die Leute an die Zeit erinnern.


Ich würde daher sagen: Ratschen ist eine analoge Form von 
NTP.

</summary>
   <content type="html">&lt;p&gt;Heute erzählte mir meine Mutter, dass seit langem wieder mal ein älterer
Brauch am Land es bis zu ihr in die Seitengasse geschafft hatte:&lt;br /&gt;
Die &lt;a href=&quot;https://de.wikipedia.org/wiki/Ratschen&quot;&gt;Ratscher&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Als Kind erklärte man mir diesen Osterbrauch sinngemäß so:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Zu &lt;a href=&quot;https://de.wikipedia.org/wiki/Ostern&quot;&gt;Ostern&lt;/a&gt; fliegen die 
Kirchenglocken alle nach Rom.
Und deshalb müssen die Dorfburschen mit ihren Ratschen
die Leute an die Zeit erinnern.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ich würde daher sagen: Ratschen ist eine analoge Form von 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Network_Time_Protocol&quot;&gt;NTP&lt;/a&gt;.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;ratschen&quot;&gt;Ratschen&lt;/h3&gt;

&lt;p&gt;Ich bin mir nicht mehr sicher, ob es mein Großvater oder Onkel war,
der mir damals meine erste Holz-Ratsche in seiner Werkstatt 
zusammengeschnitzt hat, jedoch werde ich das 15cm dicke Zahnrad mit Kurbel 
und die 3 Klapperbretter nie vergessen.&lt;/p&gt;

&lt;p&gt;Es muss wohl schon kurz nach meinem Schuleintritt gewesen sein, als ich das
erste mal im Dorf der Großeltern mit den älteren Burschen mitmarschieren durfte,
wenn zu Ostern am &lt;a href=&quot;https://de.wikipedia.org/wiki/Gr%C3%BCndonnerstag&quot;&gt;Gründonnerstag&lt;/a&gt;, 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Karfreitag&quot;&gt;Karfreitag&lt;/a&gt; und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Karsamstag&quot;&gt;Karsamstag&lt;/a&gt; jeweils früh am Morgen,
zu Mittag und am Abend Krawall gemacht werden sollte, um das ganze Dorf an 
die Zeit zu erinnern.&lt;/p&gt;

&lt;p&gt;Meines Wissens ist der Ratscher-Brauch in vielen Teilen Österreichs üblich,
wenngleich er mit der Größe von Städten seltener wird.&lt;br /&gt;
In den Dörfern marschiert dann jedenfalls eine Gruppe von Kindern durch die 
Straßen, betätigt kräftig die Ratschen und sorgt somit für ausreichend Krach, 
damit jeder es hören kann.&lt;/p&gt;

&lt;h4 id=&quot;der-weckruf&quot;&gt;Der Weckruf&lt;/h4&gt;

&lt;p&gt;Zeitig am Morgen (es muss wohl 6 Uhr gewesen sein) hieß es:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Wir ratschn, wir ratschn Dumpa-Mettn.&lt;br /&gt;
Leitln steht’s auf, backt’s Osterflecken!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Es gab zwar nie eine “Dumpa-Mette” (Frühmesse) in der Dorfkapelle und man 
hat mir auch nie “Osterflecken” serviert, aber die Leute vor hundert Jahren
wussten bestimmt, was damit gemeint war.&lt;/p&gt;

&lt;h4 id=&quot;mittag&quot;&gt;Mittag&lt;/h4&gt;

&lt;p&gt;Das kurze und knackige:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Wir ratschn, wir ratschn: Zwölfe!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;war am einfachsten zu merken … und von Haus zu Haus wurde das &lt;code&gt;Zwölfe&lt;/code&gt;
immer musikalischer über Straße getrillert.&lt;br /&gt;
Auf jeden Fall hat das Mittagessen danach immer besser geschmeckt, 
weil man es sich so richtig verdient hatte.&lt;/p&gt;

&lt;h4 id=&quot;karfreitag-um-15-uhr&quot;&gt;Karfreitag um 15 Uhr&lt;/h4&gt;

&lt;p&gt;Eigentlich sollten am Freitag um diese Zeit alle braven Christen in die 
Stadt zur Kirche gefahren sein um den Gottesdienst zu feiern.&lt;br /&gt;
Doch wer zu Hause geblieben war, wurde von uns erinnert:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Wir ratschn, wir ratschn das Leiden und Sterben unseres Herrn Jesus Christus!&lt;br /&gt;
Leitln, fallt’s nieder auf euchere Kniea.&lt;br /&gt;
Betet’s drei Vater unser und Ave Maria.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4 id=&quot;der-abend-gruß&quot;&gt;Der Abend-Gruß&lt;/h4&gt;

&lt;p&gt;Und am Ende des Tages (so gegen 18 Uhr) zog die Truppe ein letztes Mal durchs
Dorf um zu bekunden:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Wir ratschn, wir ratschn den englischen Gruaß,&lt;br /&gt;
den jeder katholische Christ beten muaß.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Dass der “Engel-ische” Gruß zu “englisch” mutiert war, verärgerte unter anderem
den Stadtpfarrer besonders, der mit diesen “lokalen” Ratscher-Sprüchen wenige 
anfangen konnte.&lt;br /&gt;
Generell gibt es aber meines Wissens keinen festgelegten Text, 
der beim Ratschen gesprochen werden musste. 
Das regelte jedes Dorf offenbar ein bisschen anders.&lt;/p&gt;

&lt;h3 id=&quot;lokale-traditionen&quot;&gt;Lokale Traditionen&lt;/h3&gt;

&lt;p&gt;So läuft das in manchen Dörfern schon seit vielen Generationen ab. Es gibt kein
Handbuch dafür und die älteren Jungs bringen die Sprüche den jüngeren 10 Minuten 
vor Beginn einer Tour bei.&lt;/p&gt;

&lt;p&gt;Eigentlich eine schöne Sache, die die meisten Kinder zwischen 7 und 14 Jahren
jährlich mitmachen. 
Ich weiß nicht, ob das Ritual ursprünglich eine reine “Männersache” war, 
weil am Anfang immer nur von den “Ratscher-Bubn” die Rede war.&lt;br /&gt;
Doch mangels männlichem Nachwuchs gingen bereits ein paar Jahre später meine
Kusinen mit und übernahmen “das Geschäft” später ganz.
Und heute sind es ihre Töchter und Söhne, die diese alte Tradition fortführen.&lt;/p&gt;

&lt;h3 id=&quot;der-verdienst&quot;&gt;Der Verdienst&lt;/h3&gt;

&lt;p&gt;So ehrenamtlich die ganze Sache im Grunde natürlich ist, so will am Ende aber
niemand auf das “Absammeln” vergessen.&lt;br /&gt;
Denn es kamen beim letzten Rundgang stets die Hausbewohner auf die Straße
um den Ratschern etwas Gutes zu tun.&lt;/p&gt;

&lt;p&gt;Deshalb wurde immer eine Geldbüchse und ein Sack mitgenommen, um Geldspenden,
Süßigkeiten und Ostereier mitnehmen zu können. Geld und Speisen wurden dann 
unter den Ratschern gerecht aufgeteilt und somit war das Osternest auch ohne 
Zutun des &lt;a href=&quot;https://de.wikipedia.org/wiki/Osterhase&quot;&gt;Osterhasen&lt;/a&gt; bei allen 
Ratschern gefüllt.&lt;/p&gt;

&lt;p&gt;In gewisser Weise ist es ein bisschen vergleichbar mit dem amerikanischen 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Halloween&quot;&gt;Halloween&lt;/a&gt; nur eben zu Ostern und
ohne Verkleidung, dafür aber mit lautem Geknatter.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Meine Religiosität und Teilnahme an kirchlichen Aktivitäten liegt wie mein 
Kirchenaustritt jetzt schon etwa 20 Jahre zurück.&lt;/p&gt;

&lt;p&gt;Und seit ich in Wien wohne, gehören solche Rituale nicht mehr zu meinem Alltag.&lt;/p&gt;

&lt;p&gt;Aber ich freue mich, dass es diese Tradition in den Dörfern gibt, weil es
die Jugend in die Gemeinschaft einbindet und schöne Erinnerungen beschert.&lt;/p&gt;

&lt;p&gt;Meine Mutter, die in einer kleinen Stadt in der Nähe des Dorfes meiner Großeltern
wohnt, hatte in ihrer Siedlung auch viele Jahre keine Ratscher mehr gesehen, 
doch nun hat ein Nachbar auch dort die Tradition wieder eingeführt.&lt;/p&gt;

&lt;p&gt;Und das ist wirklich gut so.&lt;/p&gt;

&lt;p&gt;In diesem Sinne: &lt;strong&gt;Frohe Ostern!&lt;/strong&gt;&lt;/p&gt;

&lt;h3 id=&quot;nachtrag&quot;&gt;Nachtrag&lt;/h3&gt;

&lt;p&gt;Die Glocken fliegen übrigens nachweislich nicht nach Rom in der Osterzeit.&lt;/p&gt;

&lt;p&gt;Jahre später stellte ich fest, dass nur das elektronische Läutwerk der 
Stadtkirche in der Osterwoche abgeschaltet wird.&lt;/p&gt;

&lt;p&gt;Nun wird klar, was &lt;a href=&quot;https://de.wikipedia.org/wiki/Richard_David_Precht&quot;&gt;Richard David Precht&lt;/a&gt; 
meinte, als er nach einem Gespräch mit einem Linzer &lt;a href=&quot;https://de.wikipedia.org/wiki/Bischof&quot;&gt;Bischof&lt;/a&gt;
sagte:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Die Kirche hatte 2000 Jahre lang das Monopol auf erfundene Wahrheiten (Fake News).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;iframe width=&quot;640&quot; height=&quot;360&quot; src=&quot;/blog/redirect.html?https%3A%2F%2Fwww.youtube-nocookie.com%2Fembed%2FtTMbgnRh2_s%3Fstart%3D3437&quot; frameborder=&quot;1&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
</content>
 </entry>
 
 <entry>
   <title>Rückkehr ins Kino</title>
   <link href="https://www.opengate.at/blog/2022/04/cinema-is-back/"/>
   <published>2022-04-16T13:00:00+02:00</published>
   <updated>2022-04-16T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2022/04/cinema-is-back</id>
   <category term="entertainment" />
   <summary type="text">Mit der Einführung der Registrierungspflicht wegen COVID-19
am Kinoeingang wurde es mir unmöglich gemacht, Vorstellungen zu genießen.
Schließlich kämpfe ich nicht grundlos seit Jahren für Verbesserungen im
Datenschutz und all das wurde mit der Ausrede “CORONA” mit Füßen getreten.

Doch nun wurde diese sinnlose Aktion beendet, womit auch ich mein persönliches
Film- Embargo zurückziehen kann.
</summary>
   <content type="html">&lt;p&gt;Mit der Einführung der Registrierungspflicht wegen &lt;a href=&quot;https://de.wikipedia.org/wiki/COVID-19&quot;&gt;COVID-19&lt;/a&gt;
am Kinoeingang wurde es mir unmöglich gemacht, Vorstellungen zu genießen.&lt;br /&gt;
Schließlich kämpfe ich nicht grundlos seit Jahren für Verbesserungen im
Datenschutz und all das wurde mit der Ausrede “CORONA” mit Füßen getreten.&lt;/p&gt;

&lt;p&gt;Doch nun wurde diese sinnlose Aktion beendet, womit auch ich mein persönliches
Film- &lt;a href=&quot;https://de.wikipedia.org/wiki/Embargo&quot;&gt;Embargo&lt;/a&gt; zurückziehen kann.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;ein-falscher-ansatz&quot;&gt;Ein falscher Ansatz&lt;/h3&gt;

&lt;p&gt;Wer auch immer auf die absurde Idee kam, dass das Unternehmertum einfach alle
Daten ihrer Kunden “irgendwie” vorrats-speichern soll, war nicht ganz dicht.&lt;/p&gt;

&lt;p&gt;Die Ämter verteilten A4-Zettel an Veranstaltungsbetreiber und ordneten an, 
es sollen alle Kunden Name, Adresse und Telefonnummer darauf schreiben und dem
Betreiber zurückgeben.&lt;br /&gt;
Dieser sollte die A4 Zettel einige Wochen aufheben und falls ein 
Coronafall gemeldet worden wäre und dieser angegeben hätte, er hätte einer
Veranstaltung beigewohnt, ja dann hätte die Behörde alle Zettel eingefordert
um eventuelle Kontakte darüber zu informieren, dass eine Corona-Infektion 
aufgetreten sei.&lt;/p&gt;

&lt;p&gt;Ich gehe also 1 mal im Monat 3 Stunden ins Kino und werde 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Kontaktpersonennachverfolgung&quot;&gt;ge-TRACE-t&lt;/a&gt;,
fahre dann aber täglich eine Stunde mit den öffentlichen Verkehrsmitteln,
sitze die Hälfte der Woche in einer Firma mit tausend anderen Mitarbeitern
und bin dabei Corona-technisch vogelfrei.&lt;/p&gt;

&lt;p&gt;Mir kann also niemand erzählen, dass die Preisgabe meiner Wohnadresse im Kino
Leben rettet, während 20 Stunden Autobusfahrt im Monat mit fremden Personen
gleichsam egal ist.&lt;/p&gt;

&lt;p&gt;Denn TRACING funktioniert nur dann zuverlässig, wenn es flächendeckend 
umgesetzt wird.&lt;br /&gt;
Und dabei lassen wir mal weg, dass niemand die Daten prüft.
Ich hätte mich also auch als &lt;a href=&quot;https://de.wikipedia.org/wiki/Pok%C3%A9mon_(Anime)#Hauptcharaktere&quot;&gt;Ash Ketchum&lt;/a&gt;
aus Alabastia mit der Nummer 123456789 registrieren können, denn der 17 
jährige Praktikant am Schalter (oder auch seine älteren Kollegen) wollten nie
einen Ausweis sehen, sondern legten die Zettel einfach auf einen Stapel.&lt;/p&gt;

&lt;p&gt;Der Datenschutz-bezogene Schaden, der jedoch angerichtet wurde, ist 
erheblich größer:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Wer garantiert mir denn, dass die A4 Zettel wirklich nach 3 Wochen den 
reinigenden Flammen übergeben wurden?&lt;/li&gt;
  &lt;li&gt;Wer stellt denn sicher, dass nur datenschutzrechtlich geschultes Personal
mit den Daten hantieren darf?&lt;/li&gt;
  &lt;li&gt;Und wer trägt die Verantwortung bzw. wer ist mein Ansprechpartner im Falle
eines erkannten Problems?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;… aber lassen wir das Thema … es regt mich einfach nur auf.&lt;/p&gt;

&lt;h3 id=&quot;phantastische-tierwesen-3&quot;&gt;Phantastische Tierwesen 3&lt;/h3&gt;

&lt;p&gt;Um also wieder “in Stimmung” zu kommen, sah ich mir 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Phantastische_Tierwesen:_Dumbledores_Geheimnisse&quot;&gt;Phantastische Tierwesen - Dumbledores Geheimnisse&lt;/a&gt;
an, da ich schon die beiden Vorgänger im Kino miterleben durfte.&lt;/p&gt;

&lt;p&gt;Hmm … naja … ein bisschen erinnert mich das an 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Black_Widow_(Film)&quot;&gt;Black Widow&lt;/a&gt;.
Ich freute mich alle Charaktere wieder zu sehen … aber die Story konnte 
mich nicht überzeugen.&lt;/p&gt;

&lt;p&gt;Wenn man den ersten Teil ansieht, wo wirklich noch “magische Tiere” im 
Mittelpunkt standen, und dann zu Teil 2 und 3 wechselt, stellt man fest,
dass die neuesten beiden Teile eigentlich eher unter dem Titel:
“Dumbledore vs Grindelwald” hätten veröffentlicht werden sollen.&lt;/p&gt;

&lt;p&gt;Die namensgebenden “Tierwesen” spielen de facto keine Rolle und wirken
künstlich herbei geschrieben um den original Titel irgendwie rechtfertigen
zu können.&lt;/p&gt;

&lt;p&gt;Es ist etwa so, als hätte es einen 
“&lt;a href=&quot;https://de.wikipedia.org/wiki/Harry_Potter&quot;&gt;Harry Potter&lt;/a&gt; 5,5 - Dracos Ferien”
Film gegeben, in dem Harry Potter in den ersten 5 Minuten auftaucht, und dann
aber durchgehend nur noch Szenen mit 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Figuren_der_Harry-Potter-Romane#Draco_Malfoy&quot;&gt;Draco Malfoy&lt;/a&gt;
ablaufen. Ein solcher Film hätte “Harry Potter” im Titel auch nicht verdient.&lt;/p&gt;

&lt;p&gt;Und trotzdem mag ich &lt;a href=&quot;https://de.wikipedia.org/wiki/Jude_Law&quot;&gt;Jude Law&lt;/a&gt; 
in der Rolle des jüngeren 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Figuren_der_Harry-Potter-Romane#Albus_Dumbledore&quot;&gt;Albus Dumbledore&lt;/a&gt; 
sehr und hätte gerne den Film “Dumbledores Geheimnisse” ohne Tierwesen 
gesehen, wo nur dieser Charakter im Mittelpunkt gestanden hätte, in dem 
nicht &lt;a href=&quot;https://de.wikipedia.org/wiki/Dan_Fogler&quot;&gt;Dan Folger&lt;/a&gt; als Jacob Kowalski
und &lt;a href=&quot;https://de.wikipedia.org/wiki/Katherine_Waterston&quot;&gt;Katherine Waterston&lt;/a&gt; 
als Tina Goldstein andauernd die Handlung gestört hätten.&lt;/p&gt;

&lt;p&gt;Auch cool gewesen wäre ein: “Phantastische Tierwesen - Die Jagd nach dem 
verlorenem Schatz”, in dem 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Figuren_der_Phantastische-Tierwesen-Reihe#Newt_Scamander&quot;&gt;Newt Scamander&lt;/a&gt;
(&lt;a href=&quot;https://de.wikipedia.org/wiki/Eddie_Redmayne&quot;&gt;Eddie Redmayne&lt;/a&gt;) 
mit seinem 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Begriffe_und_Handlungsorte_der_Phantastische-Tierwesen-Reihe#Niffler&quot;&gt;Niffler&lt;/a&gt;
eine magische Azteken-Pyramide durchsucht.&lt;/p&gt;

&lt;p&gt;So bin ich etwas gespalten, ich will den Film mögen, schaffe es aber nicht
ein “Daumen-hoch” auszusprechen.
Besonders deshalb, weil ich schon lange nicht mehr so viele “Nazi-Gesichter”
in Berlin abgefilmt bekommen habe, ohne dass der Begriff explizit gefallen 
wäre. … also mehr Clichè geht kaum noch.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Am wichtigsten ist aber: Ich kann wieder “bedenkenlos” ins Kino gehen, und
das kam auch keine Sekunde zu früh.&lt;br /&gt;
Erst seit kurzem darf ich 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Spider-Man:_No_Way_Home&quot;&gt;Spiderman - No way home&lt;/a&gt; 
mein Eigen nennen und bin trotzdem noch angepisst, dass ich den Film nicht 
zu Weihnachten auf der Kinoleinwand sehen durfte.&lt;/p&gt;

&lt;p&gt;In zwei Wochen startet 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Doctor_Strange_in_the_Multiverse_of_Madness&quot;&gt;Dr Stange in the Multiverse of Madness&lt;/a&gt; 
und wenn ich nicht live sehen darf, wie Wanda Maximoff ihre beiden 
Hero-Kids wiedersieht … dann gibt es einen Amok-Lauf, dass selbst Thanos
Angst bekommt.&lt;/p&gt;

&lt;p&gt;… oder anders gesagt: Ich kann es kaum noch erwarten.&lt;/p&gt;

&lt;p&gt;Auf jeden Fall freue ich mich über dieses Stück zurückgewonnener Freiheit
und ich hoffe, dass dieses idiotische TRACING-Schema nie wieder zur Anwendung
kommen wird.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>MS Exchange 2000 bis 2007</title>
   <link href="https://www.opengate.at/blog/2022/04/msexchange/"/>
   <published>2022-04-10T13:00:00+02:00</published>
   <updated>2022-04-10T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2022/04/msexchange</id>
   <category term="software" /><category term="retro" />
   <summary type="text">Es ist dem Active Directory 
(AD)zu verdanken, dass ich zum 
Microsoft Exchange Server 
eine “besondere” Beziehung habe, bzw. hatte.

Dort fanden, vor 15 Jahren, meine ersten “Hackereien” statt, die zwar alle
sehr hilfreich waren, aber auch verdammt ins Augen hätten gehen können.
</summary>
   <content type="html">&lt;p&gt;Es ist dem &lt;a href=&quot;https://de.wikipedia.org/wiki/Active_Directory&quot;&gt;Active Directory&lt;/a&gt; 
(&lt;code&gt;AD&lt;/code&gt;)zu verdanken, dass ich zum 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Exchange_Server&quot;&gt;Microsoft Exchange Server&lt;/a&gt; 
eine “besondere” Beziehung habe, bzw. hatte.&lt;/p&gt;

&lt;p&gt;Dort fanden, vor 15 Jahren, meine ersten “Hackereien” statt, die zwar alle
sehr hilfreich waren, aber auch verdammt ins Augen hätten gehen können.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Die nicht-automatisierte Useradministration in einem größeren Unternehmen
sah vor 15 Jahren so aus:&lt;/p&gt;

&lt;p&gt;Ein paar Leute klicken den ganzen Tag lang durch die Windows Active Directory
und Exchange UI-Masken um Benutzerdaten und Mailboxen so anzupassen, wie es 
von “den Kunden” verlangt wird.&lt;/p&gt;

&lt;p&gt;Hat man ein paar tausend Mitarbeiter, die quer über den Kontinent verteilt 
sind, dann will jeden Tag jemand eine andere Berechtigung für eine 
Projektressource haben oder sperren und man ist mit Klickereien beschäftigt.&lt;/p&gt;

&lt;p&gt;Und genau deshalb lernte ich die internen Details des &lt;code&gt;AD&lt;/code&gt; und seines 
wichtigsten Partners, Microsoft Exchange, nach und nach kennen.&lt;/p&gt;

&lt;p&gt;Denn die &lt;a href=&quot;https://de.wikipedia.org/wiki/PowerShell&quot;&gt;Powershell&lt;/a&gt; war damals 
noch am Zeichenbrett und hatte keine Anbindung an Exchange.&lt;/p&gt;

&lt;h3 id=&quot;exchange-20002003-installation&quot;&gt;Exchange 2000/2003 Installation&lt;/h3&gt;

&lt;p&gt;Bevor sich das Exchange Setup ausführen ließ, musste man den 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Internet_Information_Services&quot;&gt;IIS&lt;/a&gt; 
und &lt;a href=&quot;https://de.wikipedia.org/wiki/Active_Server_Pages&quot;&gt;ASP&lt;/a&gt; sowie 
den &lt;a href=&quot;https://de.wikipedia.org/wiki/Simple_Mail_Transfer_Protocol&quot;&gt;SMTP&lt;/a&gt; und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Network_News_Transfer_Protocol&quot;&gt;NNTP&lt;/a&gt; Dienst 
unter &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_2000#Serverfunktionen&quot;&gt;Server 2000&lt;/a&gt;
oder &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_Server_2003&quot;&gt;2003&lt;/a&gt; installieren.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/msx2k3_01.png&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Danach integriert sich Exchange ins Active Directory 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Lightweight_Directory_Access_Protocol&quot;&gt;LDAP&lt;/a&gt; 
Schema und erweitert es um seine Mail-spezifischen Attribute.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/msx2k3_02.png&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Kaum ist die Installation durchgelaufen, hat der System-Administrator Account
eine Mailbox erhalten und diese lässt sich auch gleich über den damaligen
&lt;a href=&quot;https://de.wikipedia.org/wiki/Outlook_on_the_web&quot;&gt;Outlook Web Access&lt;/a&gt; 
(OWA) öffnen und zwar über &lt;code&gt;http://exchange-host/exchange/&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/msx2k3_03.png&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;So schön sah OWA aber nur im &lt;a href=&quot;https://de.wikipedia.org/wiki/Internet_Explorer#Version_6&quot;&gt;Internet Explorer 6&lt;/a&gt; 
bis 8 aus.&lt;br /&gt;
Für die damaligen Nicht-Microsoft-Browser (und darunter fällte auch der 
heutige Microsoft Edge), gab es eine primitivere unschönere Ansicht.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/msx2k3_04.png&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Schließlich musste man ja künstlich den Eindruck bestehen lassen, dass der &lt;code&gt;IE&lt;/code&gt;
alles besser macht.&lt;/p&gt;

&lt;h4 id=&quot;programmierung-von-exchange-2003&quot;&gt;Programmierung von Exchange 2003&lt;/h4&gt;

&lt;p&gt;Wer die Exchange-Admin-Tools installiert hatte, konnte mit &lt;code&gt;CDOEXM&lt;/code&gt; 
(Collaboration Data Objects for Exchange Management … oder so) und 
&lt;code&gt;VBScript&lt;/code&gt; zumindest ein paar Exchange Tasks automatisieren.&lt;br /&gt;
Viel besser klappte das im vollständigen &lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_Basic_Classic&quot;&gt;Visual Basic 6&lt;/a&gt;, 
oder im damaligen &lt;a href=&quot;https://de.wikipedia.org/wiki/.Net-Framework&quot;&gt;dotNet Framework&lt;/a&gt; 
1, welches über seine &lt;a href=&quot;https://de.wikipedia.org/wiki/Component_Object_Model&quot;&gt;COM&lt;/a&gt; 
Brücke auch auf die Exchange Objekte zugreifen konnte.&lt;/p&gt;

&lt;div class=&quot;language-vbscript highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;Set user = GetObject(&amp;quot;LDAP://path,to,ad_user&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;Set ado = CreateObject(&amp;quot;ADODB.Connection&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;ado.Provider = &amp;quot;ExOLEDB.DataSource&amp;quot;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;ado.Open
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;Set person = CreateObject(&amp;quot;CDO.Person&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;person.DataSource.Open user.ADsPath, ado, adModeReadWrite, adFailIfNotExists, adOpenSource
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;Set recipient = person.GetInterface(&amp;quot;IMailRecipient&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;recipient.CreateMailbox &amp;quot;LDAP://CN=Mailbox Store,CN=Storage Group,CN=InformationStore,CN=ExchangeServerName,CN=Servers,CN=Administrative Group,CN=Administrative Groups&amp;quot;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;person.DataSource.Save
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Das interessante am klassischen Exchange damals war das 
&lt;code&gt;Recipient Update Service&lt;/code&gt; (kurz RUS). Dieser Dienst scannte das AD nach 
Änderungen (z.B. neue User) und leitete die nötigen Schritte ein, um eine 
verknüpfte Mailbox automatisch anzulegen.&lt;/p&gt;

&lt;p&gt;Um die richtigen LDAP-Pfade für die “versteckten” Exchange Objekte 
herauszufinden, installierte man einfach &lt;code&gt;\support\tools\suptools.msi&lt;/code&gt; von 
der Server 2003 CD um das Tool &lt;code&gt;ADSI-Edit&lt;/code&gt; zu erhalten. Dieses konnte man 
dann in der Microsoft Management Console &lt;code&gt;mmc.exe&lt;/code&gt; manuell hinzufügen und 
sich damit zur &lt;code&gt;Configuration&lt;/code&gt; Partition des Active Directory verbinden.&lt;br /&gt;
(User und Gruppen liegen in der &lt;code&gt;Domain&lt;/code&gt; Partition und die wird mit dem 
AD Users und Groups Plugin schön angezeigt, doch für &lt;code&gt;Configuration&lt;/code&gt; 
brauchte man eben ein natives LDAP Tool).&lt;/p&gt;

&lt;p&gt;So erfuhr man, dass Mailboxen in einer &lt;code&gt;Storage Group&lt;/code&gt; liegen, die auf einem 
&lt;code&gt;Server&lt;/code&gt; liegen, der einer &lt;code&gt;Administrative Group&lt;/code&gt; zugeordnet ist, die in 
einer &lt;code&gt;Organisation&lt;/code&gt; liegt.&lt;br /&gt;
Das sieht hierarchisch so aus:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;my-ad.domain.tld/Configuration/Services/Microsoft Exchange/MyOrganization/Administrative Groups/MyAdminGroup/Servers/MyMXServer/InformationStore/MyStorageGroup/MyMailboxStore
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;wobei die Token &lt;code&gt;MyOrganization&lt;/code&gt;, &lt;code&gt;MyAdminGroup&lt;/code&gt;, &lt;code&gt;MyMXServer&lt;/code&gt;, 
&lt;code&gt;MyStorageGroup&lt;/code&gt; und &lt;code&gt;MyMailboxStore&lt;/code&gt; bei der Installation festgelegt oder 
auf einen Default gesetzt sind.&lt;/p&gt;

&lt;p&gt;“In LDAP” wird das dann so ausgesprochen:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;CN=MyMailboxStore,CN=MyStorageGroup,CN=InformationStore,CN=MyMXServer,CN=Servers,CN=MyAdminGroup,CN=Administrative Groups,CN=MyOrganization,CN=Microsoft Exchange,CN=Services,CN=Configuration,DC=my-ad,DC=domain,DC=tld
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Witzig ist, dass mit Exchange 2007 das Konzept mehrerer &lt;code&gt;Administrative Groups&lt;/code&gt;
aufgegeben wurde und bei einer Installation nur noch eine Gruppe mit dem Namen
&lt;code&gt;FYDIBOHF&lt;/code&gt; erstellt wird. Das ist ein Zeichenspiel, wo vom Token &lt;code&gt;EXCHANGE&lt;/code&gt; 
einfach immer bei jedem Buchstaben der nachfolgende herangezogen wurde.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Meine “Exchange-Zeit” endete programmiertechnisch etwa um 2007. Ich spielte
noch etwas mit &lt;code&gt;Exchange 2007&lt;/code&gt; auf API-Ebene, doch mein Berufswechsel trug 
mich wieder davon weg.&lt;/p&gt;

&lt;p&gt;Um 2011 durfte ich wieder ein &lt;code&gt;Exchange 2010&lt;/code&gt; System für eine Firma einrichten
und seine Zusammenarbeit mit dem Data Protection Manager prüfen, aber auch 
das war nur ein “Sidequest”.&lt;/p&gt;

&lt;p&gt;Leider kenne ich keine Alternativen zur Microsoft-Standard-Lösung, mit der
man größere Organisationen verwalten kann und somit bleibt Exchange für 
mich ein “guter” Ansatz. (Obwohl es bestimmt gute Alternativen dazu gibt.)&lt;/p&gt;

&lt;p&gt;Es war jedenfalls Mitte der 2000er ein besonderes Gefühl, wenn man mit ein 
paar Zeilen Code gleich mal 1000 User-Mailboxen verschieben oder 
nachbearbeiten konnte, während andere Admins Wochen damit zubrachten, bei
100 Kunden manuell bei jedem Mailaccount eine SMTP Adresse hinzuzufügen.&lt;/p&gt;

&lt;p&gt;Daraus habe ich gelernt, wie unglaublich wichtig es ist, dass jedes
Softwareprodukt einen Programmierschnittstelle braucht, über die man 
administrative Aufgaben automatisieren kann.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>ARM Crosscompiler</title>
   <link href="https://www.opengate.at/blog/2022/04/arm-crosscompile/"/>
   <published>2022-04-09T13:00:00+02:00</published>
   <updated>2022-04-09T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2022/04/arm-crosscompile</id>
   <category term="devel" />
   <summary type="text">Wenn man jetzt schon dank MinGW 
unter Linux seine Windows Programme kompilieren 
lassen kann, warum soll man denn nicht auch unter 
X86 PCs
die ARM Binaries für den 
Raspberry PI erstellen lassen 
können?

Und mit Debian geht das echt einfach
… und am Ende klappt das Ganze sogar unter 
WSL 
in Windows 10.
</summary>
   <content type="html">&lt;p&gt;Wenn man jetzt schon dank &lt;a href=&quot;https://de.wikipedia.org/wiki/MinGW&quot;&gt;MinGW&lt;/a&gt; 
unter &lt;a href=&quot;/blog/2021/02/win-linux/&quot;&gt;Linux seine Windows Programme kompilieren&lt;/a&gt; 
lassen kann, warum soll man denn nicht auch unter 
&lt;a href=&quot;https://de.wikipedia.org/wiki/X86-Prozessor&quot;&gt;X86 PCs&lt;/a&gt;
die &lt;a href=&quot;https://de.wikipedia.org/wiki/Arm-Architektur&quot;&gt;ARM&lt;/a&gt; Binaries für den 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Raspberry_Pi&quot;&gt;Raspberry PI&lt;/a&gt; erstellen lassen 
können?&lt;/p&gt;

&lt;p&gt;Und mit &lt;a href=&quot;https://de.wikipedia.org/wiki/Debian&quot;&gt;Debian&lt;/a&gt; geht das echt einfach
… und am Ende klappt das Ganze sogar unter 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Windows-Subsystem_f%C3%BCr_Linux&quot;&gt;WSL&lt;/a&gt; 
in Windows 10.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Wenn man nach &lt;em&gt;“Raspberry Pi crosscompile”&lt;/em&gt; sucht, findet man einige
Beiträge, die einen alle Tools im Internet zusammentragen lassen, dann
noch alle Raspberry Header und Libs per GIT klonen lassen, um endlich
einen Build zu starten.&lt;/p&gt;

&lt;p&gt;Zumindest seit Debian 9 (oder 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Ubuntu&quot;&gt;Ubuntu&lt;/a&gt; 18.04) geht das viel einfacher:&lt;/p&gt;

&lt;h3 id=&quot;debian-crossbuild-essential-armhf&quot;&gt;Debian: crossbuild-essential-armhf&lt;/h3&gt;

&lt;p&gt;Die Paketinstallation&lt;br /&gt;
&lt;code&gt;apt install crossbuild-essential-armhf -y&lt;/code&gt;&lt;br /&gt;
legt den &lt;a href=&quot;https://de.wikipedia.org/wiki/GNU_Compiler_Collection&quot;&gt;GCC&lt;/a&gt; ARM 
Compiler und die meisten notwendigen Libs in 
&lt;code&gt;/usr/arm-linux-gnueabihf&lt;/code&gt; ab.&lt;br /&gt;
Und mit einer &lt;code&gt;.cmake&lt;/code&gt; Toolchain-Datei leitet man einfach die Aufrufe
zum ARM Compiler um.&lt;/p&gt;

&lt;h3 id=&quot;cmake-toolchain-datei&quot;&gt;CMake: Toolchain Datei&lt;/h3&gt;

&lt;p&gt;Meine &lt;a href=&quot;https://de.wikipedia.org/wiki/CMake&quot;&gt;CMake&lt;/a&gt; Toolchain-Datei 
&lt;code&gt;arm-linux-gnueabihf.cmake&lt;/code&gt; sieht in etwa so aus:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;set(CMAKE_SYSTEM_NAME &amp;quot;Linux&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;set(CMAKE_SYSTEM_PROCESSOR &amp;quot;arm&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;set(TOOLCHAIN_PREFIX &amp;quot;arm-linux-gnueabihf&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;set(CMAKE_C_COMPILER &amp;quot;${TOOLCHAIN_PREFIX}-gcc&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;set(CMAKE_CXX_COMPILER &amp;quot;${TOOLCHAIN_PREFIX}-g++&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;set(CMAKE_CROSSCOMPILING TRUE)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;set(THREADS_PTHREAD_ARG &amp;quot;2&amp;quot; CACHE STRING &amp;quot;THREADS_PTHREAD_ARG&amp;quot; FORCE)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;set(CMAKE_FIND_ROOT_PATH &amp;quot;/usr/${TOOLCHAIN_PREFIX}&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Ich brauchte den Eintrag &lt;code&gt;THREADS_PTHREAD_ARG&lt;/code&gt;, da ansonsten der Fehler:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;CMake Error: TRY_RUN() invoked in cross-compiling mode, 
please set the following cache variables appropriately:
THREADS_PTHREAD_ARG (advanced)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;auftritt.&lt;/p&gt;

&lt;p&gt;Schon kann man &lt;code&gt;CMake&lt;/code&gt; mit dem Kommando:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;cmake -DCMAKE_TOOLCHAIN_FILE=/path/to/arm-linux-gnueabihf.cmake /path/to/sources
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;ausführen und erhält am Ende &lt;code&gt;ARMv7&lt;/code&gt; Binaries.&lt;/p&gt;

&lt;p&gt;Diese wurden zu meinem alten &lt;code&gt;Raspberry Pi 2B&lt;/code&gt; kopiert und dieser konnte 
sie sofort und ohne Probleme ausführen.&lt;/p&gt;

&lt;h3 id=&quot;andere-plattformen&quot;&gt;Andere Plattformen&lt;/h3&gt;

&lt;p&gt;Nachdem der Raspberry Pi &lt;code&gt;Zero&lt;/code&gt; und &lt;code&gt;1&lt;/code&gt; den &lt;code&gt;ARMv6&lt;/code&gt; Befehlssatz nutzen, der 
&lt;code&gt;2&lt;/code&gt;er den &lt;code&gt;ARMv7&lt;/code&gt; und die späteren &lt;code&gt;ARMv8&lt;/code&gt;, macht es Sinn, diese Info der 
Toolchain mitzugeben, damit optimierter Code für die gewünschte Plattform 
rauskommt.&lt;/p&gt;

&lt;p&gt;Eine tolle Übersicht hat &lt;code&gt;fm4dd&lt;/code&gt; unter &lt;a href=&quot;https://gist.github.com/fm4dd/c663217935dc17f0fc73c9c81b0aa845&quot;&gt;github.com&lt;/a&gt;
eingestellt.&lt;/p&gt;

&lt;p&gt;Mit ein paar Zusatzzeilen&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;#set(RPI_FLAGS &amp;quot;-mcpu=arm1176jzf-s -mfloat-abi=hard -mfpu=vfp&amp;quot; CACHE STRING &amp;quot;RPi Zero/1&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;set(RPI_FLAGS &amp;quot;-mcpu=cortex-a7 -mfloat-abi=hard -mfpu=neon-vfpv4&amp;quot; CACHE STRING &amp;quot;RPi 2&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;#set(RPI_FLAGS &amp;quot;-mcpu=cortex-a53 -mfloat-abi=hard -mfpu=neon-fp-armv8 -mneon-for-64bits&amp;quot; CACHE STRING &amp;quot;RPi 3&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;#set(RPI_FLAGS &amp;quot;-mcpu=cortex-a72 -mfloat-abi=hard -mfpu=neon-fp-armv8 -mneon-for-64bits&amp;quot; CACHE STRING &amp;quot;RPi 4&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;set(CMAKE_C_FLAGS &amp;quot;${CMAKE_C_FLAGS} ${RPI_FLAGS}&amp;quot; CACHE STRING &amp;quot;C CPU Flags&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;set(CMAKE_CXX_FLAGS &amp;quot;${CMAKE_CXX_FLAGS} ${RPI_FLAGS}&amp;quot; CACHE STRING &amp;quot;C++ CPU Flags&amp;quot;)
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;lässt sich der generierte Code auf den gewünschten &lt;code&gt;Raspberry Pi&lt;/code&gt; anpassen.&lt;/p&gt;

&lt;p&gt;Leider ist der &lt;code&gt;ARMv6&lt;/code&gt; Befehlssatz des &lt;code&gt;RPi Zero&lt;/code&gt; und &lt;code&gt;1&lt;/code&gt; nicht mehr in 
den Standardcompilern enthalten und man bekommt Fehler wie:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;sorry, unimplemented: Thumb-1 hard-float VFP ABI&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Aber auch hier hat ein pfiffiger User eine Lösung mit einer angepassten
Toolchain eingestellt: &lt;a href=&quot;https://github.com/Pro/raspi-toolchain&quot;&gt;github.com/Pro/raspi-toolchain&lt;/a&gt;&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Mit &lt;code&gt;WSL&lt;/code&gt; und Ubuntu oder Debian kann ich nun also GATE Builds für die ARM
Plattform bauen lassen und während mein Raspberry 4 oder 2 schon ganz schön 
lange rechnen müsste, schafft das mein Intel i5 in unter einer Minute.&lt;/p&gt;

&lt;p&gt;Vermutlich enthalten ältere Distros von vor 2015 ebenfalls noch den &lt;code&gt;ARMv6&lt;/code&gt; 
Befehlssatz, aber mir reicht der &lt;code&gt;ARMv7&lt;/code&gt; Teil vollkommen für Tests aus.&lt;/p&gt;

&lt;p&gt;Sollte ich also wirklich mal einen &lt;code&gt;RPi Zero&lt;/code&gt; Build brauchen, werde ich die
alternative Toolchain bemühen müssen, oder direkt am R-PI bauen lassen.&lt;/p&gt;

&lt;p&gt;Jedenfalls wieder mal “eine coole Sache”, dass ich nun eine weitere Plattform
problemfrei abhaken kann.&lt;/p&gt;

&lt;p&gt;Es gibt zwar meines Wissens auch eine native Windows-Toolchain für ARM-Linux,
doch wozu die Mühe machen, wenn es mit &lt;code&gt;WSL&lt;/code&gt; so unkompliziert läuft.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>LUA: Scripts für C/C++</title>
   <link href="https://www.opengate.at/blog/2022/04/lua/"/>
   <published>2022-04-03T13:00:00+02:00</published>
   <updated>2022-04-03T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2022/04/lua</id>
   <category term="devel" /><category term="projects" />
   <summary type="text">Die Scriptsprache LUA beeindruckte mich 
schon vor vielen Jahren mit ihrer einfachen Implementierung und dem geringem 
Ressourcenverbrauch.

Und außerdem ist es in keiner anderen Sprache so leicht möglich Kernfunktionen
wie den Dateizugriff selbst zu implementieren oder ganz wegzulassen.
</summary>
   <content type="html">&lt;p&gt;Die Scriptsprache &lt;a href=&quot;https://de.wikipedia.org/wiki/Lua&quot;&gt;LUA&lt;/a&gt; beeindruckte mich 
schon vor vielen Jahren mit ihrer einfachen Implementierung und dem geringem 
Ressourcenverbrauch.&lt;/p&gt;

&lt;p&gt;Und außerdem ist es in keiner anderen Sprache so leicht möglich Kernfunktionen
wie den Dateizugriff selbst zu implementieren oder ganz wegzulassen.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Microsoft’s &lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_Basic_Script&quot;&gt;VBScript&lt;/a&gt; 
(und JScript) haben seit den 90ern eine &lt;a href=&quot;https://de.wikipedia.org/wiki/Component_Object_Model&quot;&gt;COM&lt;/a&gt; 
API um sie in eigene Projekte zu integrieren. &lt;a href=&quot;https://de.wikipedia.org/wiki/JavaScript&quot;&gt;Javascript&lt;/a&gt;
Engines wie &lt;a href=&quot;https://de.wikipedia.org/wiki/V8_(JavaScript-Implementierung)&quot;&gt;V8&lt;/a&gt; 
können das auch ohne COM und &lt;a href=&quot;https://de.wikipedia.org/wiki/Python_(Programmiersprache)&quot;&gt;Python&lt;/a&gt;
ist heute wohl der bekannteste Vertreter einer Scriptsprache, die man aus 
eigenen Programmen nutzen kann, oder wie man eigenen Code in diese Welt 
hin abbilden kann.&lt;/p&gt;

&lt;p&gt;Doch diese Moloche haben alle ein großes Problem:&lt;br /&gt;
Ihre Komplexität lässt sie zu einem &lt;a href=&quot;https://de.wikipedia.org/wiki/Fettleibigkeit&quot;&gt;Adipositas&lt;/a&gt;
Patienten werden, der jedes neue Projekt mit unzähligen Abhängigkeiten 
belegt, die dieses mühsam mitschleppen muss.&lt;/p&gt;

&lt;p&gt;Und mache Anwendungsgebiete wie Mikrocontroller fallen daher sofort weg.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;LUA&lt;/code&gt; hingegen definiert primär eine Kernsprache mit Konstrukten wie
&lt;code&gt;function&lt;/code&gt;, &lt;code&gt;if-then-else&lt;/code&gt;, &lt;code&gt;for&lt;/code&gt;, &lt;code&gt;while&lt;/code&gt;, &lt;code&gt;break&lt;/code&gt; und &lt;code&gt;return&lt;/code&gt;, sowie
das Definieren und Verändern von Variablen mit Grundrechenarten.&lt;/p&gt;

&lt;p&gt;Jede weitere Form von “Funktionalität” kann bzw. muss über 
&lt;a href=&quot;https://de.wikipedia.org/wiki/C_(Programmiersprache)&quot;&gt;C-Funktionen&lt;/a&gt;
in die Scriptsprache eingefügt werden.&lt;br /&gt;
Und so wird ein Standard-Mapping von üblichen C-Funktionen, wie
&lt;code&gt;print&lt;/code&gt; zur Ausgabe, oder &lt;code&gt;lower&lt;/code&gt;/&lt;code&gt;upper&lt;/code&gt; für Strings wie auch
&lt;code&gt;sin&lt;/code&gt;/&lt;code&gt;cos&lt;/code&gt;/&lt;code&gt;tan&lt;/code&gt; zum Rechnen, in die Sprache eingefügt.&lt;/p&gt;

&lt;p&gt;Doch: Das kann man auch bewusst weglassen.&lt;/p&gt;

&lt;p&gt;Und genau das macht &lt;code&gt;LUA&lt;/code&gt; in erster Linie mal zu einer besonders
sicheren Scriptsprache, denn es gibt grundsätzlich mal kein 
Feature, dessen Bugs man ausbeuten kann.&lt;br /&gt;
Wir können also die Scriptsprache nur mit den Funktionen
anreichern, die wir wirklich brauchen und müssen keine Angst davor
haben, dass man versehentlich unbenutzten Fremdcode ausführt.&lt;/p&gt;

&lt;p&gt;Von daher war es auch kein Problem, &lt;code&gt;LUA&lt;/code&gt; Scripts in meiner 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Unified_Extensible_Firmware_Interface&quot;&gt;UEFI&lt;/a&gt; 
Umgebung auszuführen, da ich hierfür die Script-&lt;code&gt;print&lt;/code&gt; Funktion nicht auf das
handelsübliche C &lt;code&gt;printf&lt;/code&gt; festlegte, sondern auf meine eigene Implementierung.&lt;/p&gt;

&lt;p&gt;Und genau hier startet der große Vorteil von &lt;code&gt;LUA&lt;/code&gt;: Man kann eigene Objekte
oder Funktionen für Scripts “nutzbar” machen.&lt;br /&gt;
Oder anders gesagt, man kann dynamisch eine Funktion injizieren lassen,
deren Aufruf auf eine native C-Funktion umgeleitet wird.&lt;/p&gt;

&lt;p&gt;Und genau so erreichen viele Programme einen enormen Funktionalitätsgewinn:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Man schreibt die interne Low-Level-Logik in effizientem C oder 
&lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B&quot;&gt;C++&lt;/a&gt; Code&lt;/li&gt;
  &lt;li&gt;Und dann lässt man diese High-Level-Funktion durch einfache &lt;code&gt;LUA&lt;/code&gt; Scripts
mit unterschiedlichen Parameter ausführen.&lt;/li&gt;
  &lt;li&gt;Am Ende erhält man ein kleines und effizientes C Programm, dessen interner
Ablauf mit &lt;code&gt;LUA&lt;/code&gt; Scripts verändert werden kann, ohne dass man neu kompilieren 
muss.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;LUA&lt;/code&gt; ist schon seit einiger Zeit im GATE Framework integriert und soll es
möglich machen, die nativen (und manchmal komplexen) C Routinen durch einfache
Aufrufe zu “verscripten”.&lt;/p&gt;

&lt;p&gt;Tatsächlich ist das Mapping zwischen &lt;code&gt;LUA&lt;/code&gt; und C Code etwas gewöhnungsbedürftig,
da man alles über Stacks austauscht, doch diese Details lassen sich durch
Hilfsroutinen bändigen.&lt;br /&gt;
Besonders der Einsatz von Templates in C++ vereinfacht diese Übersetzung enorm.&lt;/p&gt;

&lt;p&gt;Ich bin jedenfalls ein großer &lt;code&gt;LUA&lt;/code&gt; Fan geworden und sehe vor allem im Vergleich
zur Integration von Python große Vorteile.&lt;/p&gt;

&lt;p&gt;Ein Wermutstropfen ist leider Objektorientierung in &lt;code&gt;LUA&lt;/code&gt;, welches (ähnlich wie
in Python) sehr “hineingewurstet” aussieht. Man merkt, dass all diese Sprachen
ursprünglich rein funktionsorientiert gestaltet waren und Objekte später
angeheftet wurden.&lt;/p&gt;

&lt;p&gt;However, ich bin jedenfalls gespannt welche Möglichkeiten die “Verscriptung”
mir noch eröffnen wird, denn aktuell steht des ganze Thema noch am Anfang.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>C++ RTTI: Run-Time Type Information</title>
   <link href="https://www.opengate.at/blog/2022/04/rtti/"/>
   <published>2022-04-02T13:00:00+02:00</published>
   <updated>2022-04-02T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2022/04/rtti</id>
   <category term="devel" />
   <summary type="text">Die Run-Time Type Information 
(kurz RTTI) ist eines dieser Features in C++, 
weshalb mache Anwender auf Exceptions und virtuelle Methoden verzichten.

Denn während viele andere Features der Sprache genau “abgeschätzt” werden
können, eröffnet RTTI einen Baum von Abhängigkeiten, die schnell auch zu
ungewolltem Overhead werden können.
</summary>
   <content type="html">&lt;p&gt;Die &lt;a href=&quot;https://en.wikipedia.org/wiki/Run-time_type_information&quot;&gt;Run-Time Type Information&lt;/a&gt; 
(kurz &lt;code&gt;RTTI&lt;/code&gt;) ist eines dieser Features in &lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B&quot;&gt;C++&lt;/a&gt;, 
weshalb mache Anwender auf Exceptions und virtuelle Methoden verzichten.&lt;/p&gt;

&lt;p&gt;Denn während viele andere Features der Sprache genau “abgeschätzt” werden
können, eröffnet &lt;code&gt;RTTI&lt;/code&gt; einen Baum von Abhängigkeiten, die schnell auch zu
ungewolltem Overhead werden können.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Erstmals bewusst gemacht wurde mir &lt;code&gt;RTTI&lt;/code&gt; mit Studio 2005 und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_CE&quot;&gt;Windows CE&lt;/a&gt;.
Denn während &lt;code&gt;RTTI&lt;/code&gt; in jeder Standard-C++-Umgebung aktiviert ist (und bewusst
deaktiviert werden müsste), werden CE-Programme ohne &lt;code&gt;RTTI&lt;/code&gt; Support gebaut,
womit dann keine einzige C++ Exception durch den Compiler durchkommt.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;RTTI&lt;/code&gt; ist also diese geheime Kraft, die &lt;code&gt;dynamic_cast&lt;/code&gt; möglich macht, 
das &lt;code&gt;catch&lt;/code&gt;en von typisierten Exception bewirkt und dabei jede Menge 
kryptischen Code erzeugt, wenn man einen Blick auf den Assembler-Output wirft.&lt;/p&gt;

&lt;p&gt;Up-Casting (also Casts von einer Ableitung zur Basisklasse) ist in C++ 
meistens “kostenlos”, weil Objekte von der Basis zur Ableitung hin konstruiert
werden.&lt;/p&gt;

&lt;p&gt;Wird ein &lt;code&gt;Derived*&lt;/code&gt; Pointer zu &lt;code&gt;Base*&lt;/code&gt; ist die Speicheradresse meist 
identisch, nur im Falle von Mehrfachvererbung wird ein statischer Offset 
addiert, weil jedes &lt;code&gt;Derived&lt;/code&gt; Objekt seine &lt;code&gt;Base&lt;/code&gt; enthalten muss.&lt;/p&gt;

&lt;p&gt;Umgekehrt weiß ein &lt;code&gt;Base*&lt;/code&gt; nicht, ob es ursprünglich mal als &lt;code&gt;Derived*&lt;/code&gt; 
erzeugt wurde.&lt;br /&gt;
Die einzige Möglichkeit dies herauszufinden ist die &lt;code&gt;v-Table&lt;/code&gt; bei 
Objekten mit virtuellen Methoden.&lt;/p&gt;

&lt;p&gt;Der Compiler generiert daher für jedes Klasse mit virtuellen Methoden
eine &lt;code&gt;v-Table&lt;/code&gt; und verknüpft diese mit anderen &lt;code&gt;v-Table&lt;/code&gt; Einträgen in internen
Datenstrukturen.&lt;br /&gt;
So kann dann ein &lt;code&gt;dynamic_cast&lt;/code&gt; beim Aufruf nachsehen, welche &lt;code&gt;v-Table&lt;/code&gt; mit 
dem Objekt verknüpft ist und findet darüber heraus, ob der gewünschte Datentyp
in der Hierarchie mit dem originalen Typen verbunden ist.&lt;br /&gt;
Wenn ja, wird ein neuer Pointer + Typ erzeugt, falls nein fliegt
&lt;code&gt;std::bad_cast&lt;/code&gt; bei Referenzen oder man erhält einen Null-Pointer zurück.&lt;/p&gt;

&lt;p&gt;Bei Exceptions geschieht etwas Ähnliches, hier wird die Typeninformation 
“mitgeworfen”, damit der Code dann den richtigen &lt;code&gt;catch&lt;/code&gt; Handler findet,
wenn der Stack bis zu einem solchen zurückgebaut wurde.&lt;/p&gt;

&lt;h3 id=&quot;problem-runtime&quot;&gt;Problem: Runtime&lt;/h3&gt;

&lt;p&gt;Mein größtes Problem mit &lt;code&gt;RTTI&lt;/code&gt; ist, dass diese Typen-Information auf Daten
und Strukturen der C++-Runtime-Library zurückgreift.&lt;br /&gt;
Der Compiler generiert also nicht nur eigenen Code, sondern setzt auch das 
Vorhandensein einiger weiterer Funktionen im Binary voraus, die nicht 
“dynamisch” generiert werden.&lt;/p&gt;

&lt;p&gt;Beim &lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_C%2B%2B&quot;&gt;MSVC&lt;/a&gt; betrifft das vor 
allem das Exception Handling. Das ist in regulären Windows Programmen auch 
kein Problem, weil diese immer mit der C-Runtime verknüpft sind.&lt;/p&gt;

&lt;p&gt;Es gibt aber andere Orte, wo das zum Problem wird, und das wären z.B.:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;die Treiber Entwicklung&lt;/li&gt;
  &lt;li&gt;oder das Erzeugen von &lt;a href=&quot;https://de.wikipedia.org/wiki/Unified_Extensible_Firmware_Interface&quot;&gt;UEFI Apps&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Denn diese Kompilate enthalten keine C-Runtime und dürfen diese wegen ihrer 
Bindung zum OS-Usermode auch nicht beinhalten.&lt;/p&gt;

&lt;p&gt;Und das ärgert mich. Denn der Compiler hätte die Möglichkeit, den Code
generisch zu gestalten und auf die externe Runtime-Library zu verzichten.&lt;br /&gt;
Er tut das aber, um mit der Windows-API kompatibel zu sein und um das
Structured Exception Handling zu nutzen.&lt;/p&gt;

&lt;p&gt;Hier hätte ich mir einen Compiler-Switch erhofft, mit dem man auf
“Native Exceptions” oder so etwas wechseln kann.&lt;/p&gt;

&lt;p&gt;Aber vielleicht kommt das ja noch, denn seit ein paar Jahren geistert 
die Idee der Zero-Overhead-Exceptions durch die Community.&lt;/p&gt;

&lt;h3 id=&quot;neuer-ansatz-zero-overhead-deterministic-exceptions&quot;&gt;Neuer Ansatz: Zero-overhead deterministic exceptions.&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p0709r4.pdf&quot;&gt;Herb Sutter hat diese Vorschlag eingereicht&lt;/a&gt;,
und er stellt damit “meine Welt” schon etwas auf den Kopf … doch wenn ich
darüber nachdenke, wird mir die Idee immer sympathischer.&lt;/p&gt;

&lt;p&gt;Wir lernten:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Throw by value, catch by reference.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Und dieses &lt;code&gt;catch by reference&lt;/code&gt; baut ebenso auf &lt;code&gt;RTTI&lt;/code&gt; auf, wenn jede Exception
von &lt;code&gt;std::exception&lt;/code&gt; erben soll. Folglich kann &lt;code&gt;catch(std::exception&amp;amp;)&lt;/code&gt; eine
jede fangen.&lt;/p&gt;

&lt;p&gt;Hier braucht man dann zusätzlichen Code und Heap-Speicher, um die Exception
zu werfen. &lt;code&gt;throw&lt;/code&gt; muss also auf &lt;code&gt;new&lt;/code&gt; vertrauen, was leider auch schief 
gehen kann.&lt;/p&gt;

&lt;p&gt;Der andere Ansatz ist jedoch:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Wir fangen alle Exception &lt;code&gt;by value&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Und das bedeutet, dass in der Funktion, in welcher der &lt;code&gt;catch&lt;/code&gt; Block steht
schon speicher allokiert werden kann, um die Exception darauf abbilden zur 
können. Und wenn das schon der Fall ist, können wir auch weiter optimieren
und eine neue Exception schon während &lt;code&gt;throw&lt;/code&gt; genau dort konstruieren lassen,
wo sie letztendlich gefangen werden soll.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Wow, das wäre die Lösung.&lt;/em&gt; Denn wenn “mein Framework” keine polymorphen
Klassen mehr einsetzt und per Referenz fängt, dann könnte ein statisches
Programme alle Ausnahmen so generieren lassen, dass überhaupt keine 
dynamische Allokierung oder &lt;code&gt;RTTI&lt;/code&gt; Auflösung mehr notwendig sind.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Leider sind alle diese theoretischen Überlegungen noch ferne Zukunftsmusik.
Denn Compiler Hersteller brauchen oft einige Jahre, um neue Features einzufügen.&lt;/p&gt;

&lt;p&gt;Ein Verzicht auf &lt;code&gt;RTTI&lt;/code&gt; ist also heute für mich nicht denkbar und beim MSVC
leider ausgeschlossen.&lt;/p&gt;

&lt;p&gt;Ein bisschen Hoffnung hege ich noch beim GCC, ob man den so hinbekommen kann,
dass er Exceptions und &lt;code&gt;RTTI&lt;/code&gt; Auflösungen so umsetzt, dass keine externen CRT
Funktionen notwendig sind.&lt;/p&gt;

&lt;p&gt;Mal sehen, was daraus wird, doch bis dahin bleibt &lt;code&gt;C&lt;/code&gt; mein Favorit in Sachen
EFI.&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>Webmin</title>
   <link href="https://www.opengate.at/blog/2022/03/webmin/"/>
   <published>2022-03-27T13:00:00+02:00</published>
   <updated>2022-03-27T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2022/03/webmin</id>
   <category term="software" />
   <summary type="text">Es muss etwa im Jahr 2003 gewesen sein, als mir ein Freund die Installation
von webmin auf meinen Linux Systemen empfohlen hat.

Und tatsächlich war dann webmin der Grund, weshalb ich überhaupt angefangen
habe, mit Linux zu arbeiten.
</summary>
   <content type="html">&lt;p&gt;Es muss etwa im Jahr 2003 gewesen sein, als mir ein Freund die Installation
von &lt;code&gt;webmin&lt;/code&gt; auf meinen Linux Systemen empfohlen hat.&lt;/p&gt;

&lt;p&gt;Und tatsächlich war dann &lt;code&gt;webmin&lt;/code&gt; der Grund, weshalb ich überhaupt angefangen
habe, mit &lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt; zu arbeiten.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;code&gt;webmin&lt;/code&gt; ist ein spezieller HTTP-Webserver-Dienst, der die Verwaltung anderer
Dienste eines Betriebssystems über eine Weboberfläche ermöglicht.&lt;br /&gt;
Man kann also einen PC oder Server per Webbrowser fernwarten, überwachen
und teilweise auch “live” damit arbeiten.&lt;/p&gt;

&lt;p&gt;Obwohl es inzwischen Ports für Windows gibt, kenne ich &lt;code&gt;webmin&lt;/code&gt; in erster Linie
nur von Linux Systemen.&lt;br /&gt;
Die Software ist in &lt;a href=&quot;https://de.wikipedia.org/wiki/Perl_(Programmiersprache)&quot;&gt;Perl&lt;/a&gt; 
geschrieben, was sie zwar leicht portierbar macht, aber nicht immer für beste
Performance steht.&lt;/p&gt;

&lt;h3 id=&quot;installation&quot;&gt;Installation&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;webmin&lt;/code&gt; ist kein regulärer Bestandteil von Linux Distributionen und deshalb
wurden schon immer angepasste Installationspakete für die gängigsten 
Paketmanager auf der &lt;code&gt;webmin&lt;/code&gt; Homepage veröffentlicht:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;RPM für SuSE oder Redhat&lt;/li&gt;
  &lt;li&gt;DEB für Debian oder Ubuntu&lt;/li&gt;
  &lt;li&gt;oder ein TAR Ball mit den Sourcen für eine manuelle Einrichtung&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Hat man das Paket heruntergeladen und mit dem Standard-Toolset installiert,
z.B.:&lt;br /&gt;
&lt;code&gt;dpkg -i path/to/webmin.deb&lt;/code&gt; oder&lt;br /&gt;
&lt;code&gt;rpm -i path/to/webmin.rpm&lt;/code&gt;&lt;br /&gt;
dann sollte am Ende schon auf Port &lt;code&gt;10000&lt;/code&gt; der HTTPS Webserver laufen.&lt;/p&gt;

&lt;p&gt;Die weitere Einrichtung kann also schon remote über den Browser erfolgen.&lt;/p&gt;

&lt;p&gt;Denn dieser zeigt beim Öffnen von &lt;code&gt;https://webminserver:10000/&lt;/code&gt; einen 
Logindialog an, um sich mit einem lokalen administrativen Account 
einloggen zu können.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/webmin_dashboard.png&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;server-verwaltung&quot;&gt;Server Verwaltung&lt;/h3&gt;

&lt;p&gt;Zu den für mich wichtigsten Aspekten von &lt;code&gt;webmin&lt;/code&gt; zählt, dass unterschiedliche
Dienste über ein WebUI verwaltet werden können. 
Einige Beispiele sind:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Apache HTTP (Webserver)&lt;/li&gt;
  &lt;li&gt;FTP (File transfer: ProFTPD, WU-FTP)&lt;/li&gt;
  &lt;li&gt;SQL (Datenbank Server, MySQL, MariaDB, PostgreSQL)&lt;/li&gt;
  &lt;li&gt;SAMBA (Windows Filesharing)&lt;/li&gt;
  &lt;li&gt;SMTP (Mailversand: &lt;code&gt;sendmail&lt;/code&gt; / &lt;code&gt;postfix&lt;/code&gt;)&lt;/li&gt;
  &lt;li&gt;SQUID (HTTP Proxy)&lt;/li&gt;
  &lt;li&gt;DNS (Domain Namen)&lt;/li&gt;
  &lt;li&gt;DHCP (IP Verwaltung)&lt;/li&gt;
  &lt;li&gt;LDAP (User Authentifizierung)&lt;/li&gt;
  &lt;li&gt;VPN Server&lt;/li&gt;
  &lt;li&gt;SSH Server&lt;/li&gt;
  &lt;li&gt;… und viele mehr&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Der Dienst erkennt die Konfigurationsdateien und blendet ein WebUI ein, 
welches die abstrakten Zeilen in den Konfigurationsdateien in einfache 
Textboxen, Checkboxen und Buttons übersetzt.&lt;/p&gt;

&lt;p&gt;So kann man die Konfiguration “gesichert” editieren und versteht meist auch
viel leichter, wie der Dienst selbst aufgebaut ist, was einem beim reinen
Studium der kryptischen Einträge in Textdateien nicht immer so schnell
gelingt.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;webmin&lt;/code&gt; war somit für mich das Gegenstück zu Microsofts Windows Server,
der auch für jeden Dienst ein eigenes UI bereitstellt.&lt;/p&gt;

&lt;p&gt;Über die Jahre ist &lt;code&gt;webmin&lt;/code&gt; auch immer interaktiver geworden und 
benachrichtigt den Nutzer über Updates, der per Klick dann im Hintergrund
installiert werden.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/webmin_update.png&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;webmin&lt;/code&gt; ist vermutlich die Software unter Linux, die ich in Summe am längsten
einsetze. Denn jeder Raspberry PI und früher jeder Linux Server, den ich in
Betrieb nahm, war mit diesem Werkzeug versehen.&lt;/p&gt;

&lt;p&gt;Leider hat sich der Leistungshunger heutiger Scripts derartig erhöht, dass 
gerade der Einsatz auf einem Raspberry PI 2 oder Zero nicht mehr so viel
Spaß macht. Da wartet man schon teils recht lange, bis eine Seite geladen
werden kann, was aber an der Fülle von Funktionen liegen mag.&lt;/p&gt;

&lt;p&gt;However, ich wette auch in 10 Jahren wird &lt;code&gt;webmin&lt;/code&gt; weiter auf der Liste 
meiner “aktiven” Software sein.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>SFU und SUA: Unix unter Windows</title>
   <link href="https://www.opengate.at/blog/2022/03/sfu/"/>
   <published>2022-03-26T12:00:00+01:00</published>
   <updated>2022-03-26T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2022/03/sfu</id>
   <category term="retro" /><category term="software" />
   <summary type="text">Eher zufällig stolperte ich bereits für über 15 Jahren mit meinem damaligen
Server 2003 
über die interessante Erweiterung 
“Service for Unix”.

Denn tatsächlich gab es seit NT 4 kein Windows, das gänzlich ohne
POSIX 
Schnittstelle auskam. Windows 10/Server 2016 war hier anfangs die Ausnahme, 
doch bereits im Server 2019 kehrte der Nachfolger mit
Windows Subsystem for Linux 
zurück.

</summary>
   <content type="html">&lt;p&gt;Eher zufällig stolperte ich bereits für über 15 Jahren mit meinem damaligen
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_Server_2003&quot;&gt;Server 2003&lt;/a&gt; 
über die interessante Erweiterung 
“&lt;a href=&quot;https://en.wikipedia.org/wiki/Windows_Services_for_UNIX&quot;&gt;Service for Unix&lt;/a&gt;”.&lt;/p&gt;

&lt;p&gt;Denn tatsächlich gab es seit NT 4 kein Windows, das gänzlich ohne
&lt;a href=&quot;https://de.wikipedia.org/wiki/Portable_Operating_System_Interface&quot;&gt;POSIX&lt;/a&gt; 
Schnittstelle auskam. Windows 10/Server 2016 war hier anfangs die Ausnahme, 
doch bereits im Server 2019 kehrte der Nachfolger mit
&lt;a href=&quot;https://de.wikipedia.org/wiki/Windows-Subsystem_f%C3%BCr_Linux&quot;&gt;Windows Subsystem for Linux&lt;/a&gt; 
zurück.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Während der damalige Microsoft-Chef &lt;a href=&quot;https://de.wikipedia.org/wiki/Steve_Ballmer&quot;&gt;Steve Ballmer&lt;/a&gt; 
anfangs der 2000er noch kräftig gegen die OpenSource Bewegung wetterte und 
außer Windows am Wolkenhimmel nichts anderes zu sehen vermochte, war 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Unix&quot;&gt;Unix&lt;/a&gt; kein Feind der Windows Welt.&lt;/p&gt;

&lt;p&gt;NT 4 hatte bereits eine primitive POSIX-Schicht eingezogen, damit man 
Windows als Universalsystem vermarkten konnte.&lt;br /&gt;
Doch offen gesagt bin ich mit dieser Variante nie in Berührung gekommen.&lt;/p&gt;

&lt;p&gt;Ab Windows 2000, XP und Server 2003 konnte man den POSIX-Nachfolger
“Services for Unix” nachinstallieren.
Allerdings nur für die 32-bit Version von Windows.
Wer Server 2003 X64 oder WinXP 64 einsetzte, war von der Installation 
ausgeschlossen.&lt;/p&gt;

&lt;p&gt;Mit Windows Vista und Server 2008 war das Subsystem innerhalb des 
regulären Feature-Setups möglich und brachte auch X64 Support mit.
Man musste nur das umbenannte Feature “Subsystem for UNIX-based Applications” 
(kurz &lt;code&gt;SUA&lt;/code&gt;) aktivieren und schon bekam Windows unixoide Eigenschaften.&lt;/p&gt;

&lt;p&gt;Hier fehlten dann allerdings die Unix Tools, wie auch das SDK um 
Software dafür zu bauen. Um das zu erhalten musste man von Microsoft
weiter einen Installer herunterladen, der eben diese Dateien nachlieferte.&lt;/p&gt;

&lt;p&gt;Ich nutzte für meine Tests meinen Windows Server 2012 und die 
dazugehörigen &lt;a href=&quot;https://www.microsoft.com/en-sa/download/details.aspx?id=35512&amp;amp;SearchToggle=true&amp;amp;44F86079-8679-400C-BFF2-9CA5F2BCBDFC=1&quot;&gt;SUA SDK Tools&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;sfusuas-produktiver-nutzen&quot;&gt;SFU/SUA’s produktiver Nutzen&lt;/h3&gt;

&lt;p&gt;In meinen Arbeitsbereichen kamen &lt;code&gt;SFU&lt;/code&gt; und &lt;code&gt;SUA&lt;/code&gt; nie vor.&lt;br /&gt;
Wenn jemand Unix oder Linux-Tools nutzen wollte, installierte er
&lt;a href=&quot;https://de.wikipedia.org/wiki/Cygwin&quot;&gt;Cygwin&lt;/a&gt; und erhielt auf diese 
Weise die üblichen Unix/Linux Tools.&lt;/p&gt;

&lt;p&gt;Denn meistens ging es immer nur um die Ausführung von Scripts, 
und bevor sich in der zweiten Hälfte der 2000er die 
&lt;a href=&quot;https://de.wikipedia.org/wiki/PowerShell&quot;&gt;PowerShell&lt;/a&gt; unter
Windows durchsetzen konnte, war Scripting unter Windows mangelhaft
oder einfach unbekannt.&lt;/p&gt;

&lt;p&gt;Aufgaben wie das tägliche automatische Herunterladen von Dateien von 
HTTP oder FTP Servern war mit VBScript oder BATCH Dateien unter Windows
nicht direkt möglich, während Unix-Shellscripts besonders mit Linux für 
administrative Aufgaben schon 10 Jahre vorher “standard” waren.&lt;/p&gt;

&lt;h3 id=&quot;sfusua-dateisystem&quot;&gt;SFU/SUA Dateisystem&lt;/h3&gt;

&lt;p&gt;Die Standardinstallation legt unter XP/2003 &lt;code&gt;C:\SFU&lt;/code&gt; an, was innerhalb der Umgebung das
Root-Dateisystem darstellt.
So kann man von Windows aus direkt Dateien austauschen, z.B.: in &lt;code&gt;C:\SFU\usr&lt;/code&gt;
oder &lt;code&gt;C:\SFU\tmp&lt;/code&gt;.&lt;br /&gt;
Die neueren Varianten (wie auch mein Server 2012) nutzen &lt;code&gt;C:\Windows\SUA&lt;/code&gt; 
als Basis.&lt;/p&gt;

&lt;p&gt;Umgekehrt ist das Windows-Dateisystem in SFU über &lt;code&gt;/dev/fs/C/&lt;/code&gt; erreichbar. 
Das gilt auch für alle anderen Windows Laufwerksbuchstaben.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;/home&lt;/code&gt; existiert hier nicht, aber die &lt;code&gt;HOME&lt;/code&gt; Variable zeigt auf 
&lt;code&gt;/dev/fs/C/Documents and Settings/username&lt;/code&gt; bzw. &lt;code&gt;/dev/fs/C/Users/username&lt;/code&gt;
womit man auch hier wieder zwischen Win32 und &lt;code&gt;SFU/SUA&lt;/code&gt; Programmen Dateien 
austauschen kann.&lt;/p&gt;

&lt;p&gt;Interessant sind auch noch symbolische Links. Die werden im Windows
Dateisystem als normale Datei angelegt, deren Inhalt aber mit dem magischen
Token &lt;code&gt;IntxLNK&lt;/code&gt; beginnt, gefolgt vom verlinkten Dateipfad in UTF-16.
Die SFU Umgebung meldet sie jedoch wie übliche Links und löst den Pfad
intern auf.&lt;/p&gt;

&lt;h3 id=&quot;programme-für-sfusua-erstellen&quot;&gt;Programme für SFU/SUA erstellen.&lt;/h3&gt;

&lt;p&gt;In jedem &lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_C%2B%2B&quot;&gt;MSVC&lt;/a&gt; Win32 Programm 
kann man ja ein Linker-Subsystem festlegen und das ist entweder &lt;code&gt;CONSOLE&lt;/code&gt; 
oder &lt;code&gt;WINDOWS&lt;/code&gt;. Doch wer die Liste genau betrachtet, findet auch &lt;code&gt;POSIX&lt;/code&gt; unter 
den Möglichkeiten. Genau dieses Subsystem erstellt eine &lt;code&gt;SFU/SUA&lt;/code&gt; Binärdatei.&lt;br /&gt;
Doch beim ersten Versuch eine Hello-World-App zu kompilieren, erscheint:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;LINK : error LNK2001: unresolved external symbol ___PosixProcessStartup&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Man muss also die C-Runtime und Link-Libraries auch noch etwas anpassen:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Wir müssen die Standard-C-Runtime ausschließen.&lt;/li&gt;
  &lt;li&gt;Und explizit gegen die SFU/SUA Libraries linken.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Die entsprechenden Linker-Kommandos sind&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Linker-System-Subsystem:&lt;br /&gt;
&lt;code&gt;/SUBSYSTEM:POSIX&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Linker-Input-Ignore Specific Default Libraries:&lt;br /&gt;
&lt;code&gt;/NODEFAULTLIB:LIBCMT&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;VC++ Directories-Library Directories:&lt;br /&gt;
&lt;code&gt;/LIBPATH:C:\Windows\SUA\usr\lib\&lt;/code&gt; für X64&lt;br /&gt;
oder &lt;code&gt;/LIBPATH:C:\Windows\SUA\usr\lib\x86&lt;/code&gt; für X86&lt;/li&gt;
  &lt;li&gt;Linker-Input-Additional Dependencies:&lt;br /&gt;
&lt;code&gt;psxlibc.lib;crtexe.o;libpsxdll.a;libc.a&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Die &lt;code&gt;crtexe.o&lt;/code&gt; ist für mein ausführbares Programm notwendig. Allerdings liegen
auch noch &lt;code&gt;crt0.o&lt;/code&gt; und &lt;code&gt;crtdll.o&lt;/code&gt; vor, die vermutlich für DLLs oder mit
statischer/dynamischer Runtime notwendig sind.&lt;/p&gt;

&lt;p&gt;Am Ende erhält man eine EXE, die man im SFU/SUA Kontext ausführen kann.&lt;/p&gt;

&lt;p&gt;Im Dependency Walker kann man dann auch nachweisen, dass die EXE wirklich
gegen die &lt;code&gt;PSXDLL.DLL&lt;/code&gt; gelinkt ist, die wiederum alle POSIX Funktionen
implementiert und in die Windows Welt übersetzt.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/depwalker_psxdll.png&quot; alt=&quot;PSXDLL&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Randnotiz&lt;/em&gt;: Im WinXP SFU war sogar ein uralter 
&lt;a href=&quot;https://de.wikipedia.org/wiki/GNU_Compiler_Collection&quot;&gt;GCC&lt;/a&gt; 3.3 integriert, 
doch ohne &lt;a href=&quot;https://de.wikipedia.org/wiki/CMake&quot;&gt;CMake&lt;/a&gt; wollte ich mir nicht 
die Mühe machen, hierfür ein Testprogramm zu kompilieren. 
However … ich wette, es hätte funktioniert.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Nachdem ich Lust und Laune hatte, mir ein &lt;code&gt;SFU/SUA&lt;/code&gt;  Setup anzusehen, hat mir
vor allem der Blog Artikel &lt;a href=&quot;https://blog.ret2.io/2017/09/20/subsystem-posix/&quot;&gt;blog.ret2.io/2017/09/20/subsystem-posix&lt;/a&gt;
super weitergeholfen, meinen Linkerfehler wegzubekommen.&lt;br /&gt;
Danke an den Autor!&lt;/p&gt;

&lt;p&gt;Genau solche Infos gehen leider Stück für Stück verloren, denn &lt;code&gt;SFU/SUA&lt;/code&gt;
Installationsdateien mögen noch weiter viele Jahre im Netz auffindbar sein,
doch die Dokus hat Microsoft schon lange zurückgezogen.&lt;/p&gt;

&lt;p&gt;Ich bezweifle zwar, dass ich jemals wieder mit dieser Technologie arbeiten 
werde, doch es ist gut zu wissen, wie es funktioniert hat.&lt;/p&gt;

&lt;p&gt;Schade ist, dass Microsoft seine “Verbindung” zur Unix Welt so lange
verleugnet hat und erst 2017 mit &lt;code&gt;WSL&lt;/code&gt; eine Idee hat wiederaufleben lassen,
die es eigentlich schon im Jahr 2000 gab.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Star Trek: Discovery Staffel 4</title>
   <link href="https://www.opengate.at/blog/2022/03/discovery-4/"/>
   <published>2022-03-20T12:00:00+01:00</published>
   <updated>2022-03-20T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2022/03/discovery-4</id>
   <category term="entertainment" />
   <summary type="text">Mit der 4.Staffel von Star Trek: Discovery
hatten mich die Macher, Netflix und 
Paramount schwer verärgert, 
denn wenige Tage vor dem Beginn des Ausstrahlung wurde verkündet, dass die 
Serie gar nicht im europäischen Raum verfügbar sein würde.

Doch … nach sehr viel Kritik … entschied man sich doch noch auf 
pluto.tv jede Woche eine Episode zu zeigen.

Und so kam ich letztlich doch in den Genuss, die neueste Star Trek Produktion
(ganz ohne Tricks) mitverfolgen zu können.
</summary>
   <content type="html">&lt;p&gt;Mit der 4.Staffel von &lt;a href=&quot;https://de.wikipedia.org/wiki/Star_Trek:_Discovery&quot;&gt;Star Trek: Discovery&lt;/a&gt;
hatten mich die Macher, &lt;a href=&quot;https://de.wikipedia.org/wiki/Netflix&quot;&gt;Netflix&lt;/a&gt; und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Paramount_Pictures&quot;&gt;Paramount&lt;/a&gt; schwer verärgert, 
denn wenige Tage vor dem Beginn des Ausstrahlung wurde verkündet, dass die 
Serie gar nicht im europäischen Raum verfügbar sein würde.&lt;/p&gt;

&lt;p&gt;Doch … nach sehr viel Kritik … entschied man sich doch noch auf 
&lt;a href=&quot;https://pluto.tv&quot;&gt;pluto.tv&lt;/a&gt; jede Woche eine Episode zu zeigen.&lt;/p&gt;

&lt;p&gt;Und so kam ich letztlich doch in den Genuss, die neueste Star Trek Produktion
(ganz ohne Tricks) mitverfolgen zu können.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Das “Discovery-Problem”, nämlich dass mit diesem Zauber-Raumschiff alle 
galaktischen Probleme gelöst werden können, an denen alle anderen scheitern,
durchzieht wie erwartet auch die neueste Staffel.&lt;/p&gt;

&lt;p&gt;Waren &lt;a href=&quot;https://de.wikipedia.org/wiki/Figuren_im_Star-Trek-Universum#Captain_James_T._Kirk&quot;&gt;Kirk&lt;/a&gt;, 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Figuren_im_Star-Trek-Universum#Captain_Jean-Luc_Picard&quot;&gt;Picard&lt;/a&gt;, 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Figuren_im_Star-Trek-Universum#Captain_Benjamin_Sisko&quot;&gt;Sisko&lt;/a&gt; und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Figuren_im_Star-Trek-Universum#Captain_Kathryn_Janeway&quot;&gt;Janeway&lt;/a&gt; 
vor 20 Jahren immer wie Figuren in einem Schachspiel, die nur “in ihrer Ecke”
aufräumen konnten, hat die USS Discovery mit ihrem Sporenantrieb einen 
Joker im Ärmel, der scheinbar immer alles ändern kann.&lt;/p&gt;

&lt;p&gt;Ich gebe aber zu, dass ich dieses “neue StarTrek” mit jeder Staffel besser
akzeptieren und die Nostalgiebrille leichter abnehmen kann, um die Intention
der Story aufnehmen zu können.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/star-trek-discovery-4.jpg&quot; alt=&quot;Star Trek Discovery 4&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;achtung-spoiler&quot;&gt;Achtung Spoiler&lt;/h3&gt;

&lt;p&gt;Hatte die Discovery in Staffel 3 die “zerbrochene” Föderation wiedervereint,
musste nun eine neue galaktische Bedrohung her, die natürlich prompt auftauchte.
Ein destruktives Phänomen taucht auf, und zerstört jedes Sonnensystem in seiner
Umgebung, löscht binnen Sekunden Milliarden von Leben aus  …. und ganz wichtig:&lt;br /&gt;
Jeden kann es als nächstes treffen.&lt;/p&gt;

&lt;p&gt;Neben (aus meiner Sicht zu viel) Herzschmerz und anderen privaten Details der Crew,
erkennt man schnell:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Hier haben wir es mit einer überlegenen Technologie zu tun.&lt;br /&gt;
Eine maschinell eingeleitete Apokalypse eine unbekannten Spezies, 
die allen anderen bekannten Lebensformen haushoch überlegen zu sein scheint.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Hier kommt nun wieder ein bisschen 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Star_Trek:_Deep_Space_Nine&quot;&gt;Deep Space 9&lt;/a&gt;
Feeling auf, wenn die “Politik” endlich mal realistisch zu diskutieren 
beginnt und fragt:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Sollen wir versuchen zu kommunizieren, oder sollen wir “dem Angriff”
mit härtesten Gegenmaßnahmen begegnen?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Und so schreitet Episode für Episode die Divergenz voran, zwei Meinungen,
die nicht vereinbar sind, ziehen unterschiedliche Charaktere auf ihre Seite
und “interne Konflikte” gedeihen.&lt;/p&gt;

&lt;h3 id=&quot;ein-paar-bröckchen-fan-service&quot;&gt;Ein paar Bröckchen Fan-Service&lt;/h3&gt;

&lt;p&gt;Wenn eine neue Schiffswerft “Archer” getauft wird und die Melodie von 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Star_Trek:_Enterprise&quot;&gt;Star Trek: Enterprise&lt;/a&gt; 
läuft, wenn &lt;a href=&quot;https://memory-alpha.fandom.com/de/wiki/Boronit&quot;&gt;Boronit&lt;/a&gt;
erwähnt wird, oder &lt;a href=&quot;https://memory-alpha.fandom.com/de/wiki/Isolytische_Bombe&quot;&gt;Isolytische Waffen&lt;/a&gt;
oder die &lt;a href=&quot;https://memory-alpha.fandom.com/de/wiki/Gro%C3%9Fe_Barriere&quot;&gt;große Barriere&lt;/a&gt; 
durchquert werden muss, dann weiß jeder eingefleischte Fan, dass das nur 
eingebaut wurde, um die alten Hasen bei Laune zu halten.&lt;/p&gt;

&lt;p&gt;Hier würde ich auch mit der “technischen Kritik” starten, denn wenn mit 
Boronit die gefürchteten &lt;a href=&quot;http://memory-alpha.fandom.com/de/wiki/Omega-Molek%C3%BCl&quot;&gt;Omega-Moleküle&lt;/a&gt; 
hergestellt werden können, die “alle anderen Prioritäten” in 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Star_Trek:_Raumschiff_Voyager&quot;&gt;Star Trek: Voyager&lt;/a&gt; 
aufheben haben lassen, dann war das in Discovery nur eine beiläufige Bemerkung, 
a la:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ach sieh mal, die sammeln Boronit.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Und wenn ein Captain Kirk in seiner aller ersten Folge die “große Barriere”
streift und sich gleich zwei seiner Leute in Gott-gleiche Wesen 
weiterentwickeln, dann verstehe ich nicht, wie die Discovery einfach so 
in einer Quanten-Seifenblase da ohne Seiteneffekte durchtreiben kann.&lt;/p&gt;

&lt;p&gt;Aber genug davon … ganz so “kanonisch” war der Star Trek Kanon ja nie.&lt;/p&gt;

&lt;p&gt;Viel zu viel für meinen Geschmack war der andauernde Herzschmerz zwischen den
Figuren, die sich nur all zu schnell von ihren Gefühlen übermannen lassen … 
aber das scheint offenbar heute “normal” zu sein.&lt;/p&gt;

&lt;h3 id=&quot;raubbau-gier-und-egoismus&quot;&gt;Raubbau, Gier und Egoismus&lt;/h3&gt;

&lt;p&gt;Man muss tatsächlich bis zur letzten Folge warten um zu lernen, 
dass die angerichtete Zerstörung nur ein “umweltschädlicher” Nebeneffekt
eines “Erzabbaus” war.&lt;br /&gt;
Die geheimnisvolle Spezies “10-C” öffnet also wahlfrei Wurmlöcher in unsere
Galaxie um wertvolle Materialien für ihre Energiegewinnung absaugen zu können.&lt;br /&gt;
Noch besser: Um ihr eigenes Sonnensystem mit einem Energiefeld umgeben zu 
können um vom Rest der Welt “sicher zu sein”.&lt;/p&gt;

&lt;p&gt;Also … wenn da keine Kapitalismus- und Gesellschaftskritik drinnen war,
dann weiß ich auch nicht mehr weiter.&lt;/p&gt;

&lt;p&gt;Und offenbar brauchen wir genau das.&lt;/p&gt;

&lt;p&gt;Wir sehen jeden Tag, wie wir Menschen “unbewusst” unsere Welt zerstören,
nur um irgend ein egoistisches Luxusziel zu erreichen und gar nicht mehr 
fähig sind zu erkennen, was wir dabei anrichten.&lt;br /&gt;
Wissenschaftler, die uns die Wahrheit sagen wollen, erklären wir zu 
Lügner und Jugendlichen, die für eine bessere Welt demonstrieren, wird
Faulheit vorgeworfen, wenn sie einmal nicht brav vor dem Schreibtisch
sitzen.&lt;/p&gt;

&lt;p&gt;Während Star Trek in den 1960ern mit banalen “schwarz-weiß” Masken den
Rassismus erst “sichtbar” machen musste, brauchen wir heute offenbar 
auch erst eine andere Spezies, die “versehentlich” die Welt zerstört,
um vielleicht mal ein bisschen darüber nachzudenken, dass wir selbst
diese böswilligen Außerirdischen sind, die den Planeten mit Füßen
treten.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ich hatte damit nicht gerechnet, aber es ist mir in den letzten Minuten
der letzten Folge nicht gelungen, ein Tränchen zurückzuhalten.&lt;/p&gt;

&lt;p&gt;Als nach dem Sieg der Diplomatie über die Waffen, die Präsidentin der
Erde die wichtigen Worte spricht:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Es gibt nichts zu diskutieren.&lt;br /&gt;
Die Erde ist bereit der Föderation wieder beizutreten.&lt;br /&gt;
Und nichts könnte mich glücklicher machen, als diese Worte zu sagen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;iframe width=&quot;640&quot; height=&quot;360&quot; src=&quot;/blog/redirect.html?https%3A%2F%2Fwww.youtube-nocookie.com%2Fembed%2FOFno2X-uAcY&quot; frameborder=&quot;1&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;

&lt;p&gt;Ja, so ein Ende wünsche ich mir, für unsere reale Welt  … selbst wenn 
es wie hier mit kitschigen Kamerafahrten und Chorstimmen im Hintergrund 
gespickt ist.&lt;br /&gt;
Eine Welt, in der Trump’s Mauern immer noch in vielen Köpfen verharren 
und in denen sowjetische Autokraten mit Atomsprengköpfen liebäugeln.&lt;/p&gt;

&lt;p&gt;Ich wette, es wird eine Menge Stimmen im Netz geben, die jetzt alles Negative
an den Figuren und der Story durch den Kakao ziehen werden.&lt;br /&gt;
Und in 10 Jahren wird man (so wie bei allen Star Trek Serien) diese
Abbildung der aktuellen Probleme in die ScFi-Welt als “visionär” loben.&lt;/p&gt;

&lt;p&gt;Ich jedenfalls bin dem Team und der Besetzung von &lt;em&gt;Star Trek: Discovery&lt;/em&gt; 
dankbar, dass sie uns endlich wieder ein Bild der Hoffnung präsentiert 
haben, dem wir ideologisch folgen können.&lt;/p&gt;

&lt;p&gt;Ich hatte besonders am Beginn und am Ende der Staffel ein ungewöhnlich 
tiefes Verständnis für den Inhalt. Vielleicht sehe ich es in ein paar
Jahren wieder ganz anders, weil es doch zu plump war, aber aktuell kann 
ich Star Trek - wie so oft schon - einfach nur empfehlen.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Abstürze abfangen</title>
   <link href="https://www.opengate.at/blog/2022/03/crash-guard/"/>
   <published>2022-03-19T12:00:00+01:00</published>
   <updated>2022-03-19T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2022/03/crash-guard</id>
   <category term="devel" />
   <summary type="text">Das Schlimmste, was passieren kann, ist, wenn eine Fremdbibliothek in einem
internen Aufruf eine Schutzverletzung (Segmentation Fault)
produziert und den eigenen Prozess dann gleich mit in den Abgrund reißt.

Das Debugging wird dann sehr 
erschwert.

Doch es gibt Hoffnung: Man kann auch SegFaults abfangen und im Idealfall
einen Crash verhindern.
</summary>
   <content type="html">&lt;p&gt;Das Schlimmste, was passieren kann, ist, wenn eine Fremdbibliothek in einem
internen Aufruf eine &lt;a href=&quot;https://de.wikipedia.org/wiki/Schutzverletzung&quot;&gt;Schutzverletzung (Segmentation Fault)&lt;/a&gt;
produziert und den eigenen Prozess dann gleich mit in den Abgrund reißt.&lt;/p&gt;

&lt;p&gt;Das &lt;a href=&quot;https://de.wikipedia.org/wiki/Debuggen&quot;&gt;Debugging&lt;/a&gt; wird dann sehr 
erschwert.&lt;/p&gt;

&lt;p&gt;Doch es gibt Hoffnung: Man kann auch SegFaults abfangen und im Idealfall
einen Crash verhindern.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Das größte Problem von SegFaults oder Division durch Null sind das sofortige
Beenden des Auslöserprozesses. Es wird nichts mehr in ein Log geschrieben und
man kann keinen geordneten Shutdown durchführen.&lt;/p&gt;

&lt;p&gt;Doch auch Hardware-Ausnahmen wie fehlerhafte Speicherzugriffe oder 
Rechenfehler können im Usermode abgefangen werden.&lt;/p&gt;

&lt;p&gt;Und zwar sind das Fehler wie z.B.:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Zugriff auf ungültigem Speicher
    &lt;ul&gt;
      &lt;li&gt;Null-Pointer&lt;/li&gt;
      &lt;li&gt;Freigegebener Speicher&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Ungültige Instruktion
    &lt;ul&gt;
      &lt;li&gt;Eine CPU-Anweisung, die der aktuelle Prozessor nicht kennt (weil zu alt)&lt;/li&gt;
      &lt;li&gt;Eine privilegierte Anweisung, die nur der OS-Kernel, aber kein 
Nutzerprogramm ausführen darf&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Mathematische Fehler
    &lt;ul&gt;
      &lt;li&gt;Division durch &lt;code&gt;0&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;Rechenoperationen in Zahlenbereichen außerhalb der unterstützten Grenzen.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Interne Fehler des Betriebssystems
    &lt;ul&gt;
      &lt;li&gt;Ungültige Handles and Deskriptoren&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;windows-structured-exception-handling&quot;&gt;Windows Structured Exception Handling&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/debug/structured-exception-handling&quot;&gt;SEH (Structured Exception Handling)&lt;/a&gt;
definiert eine Schnittstelle, über die ein Programm einen Codepfad 
registrieren kann, der ausgeführt wird, wenn ein kritisches Problem auftritt.&lt;/p&gt;

&lt;p&gt;Microsofts Visual C/C++ nutzt eine Erweiterung des C-Standards und führt
die Schlüsselworte &lt;code&gt;__try&lt;/code&gt; und &lt;code&gt;__except&lt;/code&gt; ein, womit man SEH-Exception
ähnlich wie C++ Exceptions im Code einbetten kann.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;__try
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt;* ptr = &lt;span style=&quot;color:#069&quot;&gt;NULL&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  printf(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;%d&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, *ptr);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;}
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;__except(EXCEPTION_EXECUTE_HANDLER)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;  printf(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Exception caught&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Der &lt;code&gt;__try&lt;/code&gt; Block registriert am Anfang den Filter-Code innerhalb von 
&lt;code&gt;__except()&lt;/code&gt; im Thread Environment Block (TEB) und das OS ruft bei einem 
kritischen Fehler dann genau den Code auf.&lt;br /&gt;
Wenn der Rückgabewert &lt;code&gt;EXCEPTION_EXECUTE_HANDLER&lt;/code&gt; ist, wird der nachfolgende
Codeblock ausgeführt.&lt;/p&gt;

&lt;p&gt;Es ist aber auch erlaubt &lt;code&gt;EXCEPTION_CONTINUE_SEARCH&lt;/code&gt; zurückzugeben und dann
sucht das System in der Liste der registrierten Exception-Handler den
nächsten aus und springt in dessen Callstack-Zweig, wenn dieser dann 
&lt;code&gt;EXCEPTION_EXECUTE_HANDLER&lt;/code&gt; zurückgibt.&lt;/p&gt;

&lt;p&gt;Deshalb wird in &lt;code&gt;__except&lt;/code&gt; meist eine “Filterfunktion” aufgerufen, die mit
&lt;code&gt;GetExceptionCode()&lt;/code&gt; auswerten (und regieren) kann.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;static&lt;/span&gt; DWORD eval_exception(DWORD exception_code) 
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;{ 
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;switch&lt;/span&gt;(exception_code)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  {
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;case&lt;/span&gt; EXCEPTION_ACCESS_VIOLATION:
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;case&lt;/span&gt; EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;case&lt;/span&gt; EXCEPTION_DATATYPE_MISALIGNMENT:
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;case&lt;/span&gt; EXCEPTION_IN_PAGE_ERROR:
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#777&quot;&gt;/* we handle only memory errors */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; EXCEPTION_EXECUTE_HANDLER;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;default&lt;/span&gt;:
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#777&quot;&gt;/* other errors shall be handled by someone else */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; EXCEPTION_CONTINUE_SEARCH;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;  }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;} 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;__try
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;  ...
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;}
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n21&quot; name=&quot;n21&quot;&gt;21&lt;/a&gt;&lt;/span&gt;__except(eval_exception(GetExceptionCode()))
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n22&quot; name=&quot;n22&quot;&gt;22&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n23&quot; name=&quot;n23&quot;&gt;23&lt;/a&gt;&lt;/span&gt;  printf(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;This is a memory-related error&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n24&quot; name=&quot;n24&quot;&gt;24&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Alle Exception-Codes sind auf der 
&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/debug/getexceptioncode&quot;&gt;GetExceptionCode() Seite&lt;/a&gt;
dokumentiert.&lt;/p&gt;

&lt;h3 id=&quot;posix-signale-und-longjmp&quot;&gt;POSIX Signale und longjmp&lt;/h3&gt;

&lt;p&gt;Auf &lt;a href=&quot;https://de.wikipedia.org/wiki/Portable_Operating_System_Interface&quot;&gt;POSIX&lt;/a&gt;
Systemen unterbricht der Kernel einen korrumpierten Thread und sendet ihm ein 
Signal. Diese kann dann in einem vorher registrierten Signal-Handler behandelt 
werden. Ist ein solcher Handler nicht registriert, wird der Prozess beendet.&lt;/p&gt;

&lt;p&gt;Das Problem ist, dass nach dem Verlassen des Signal-Handlers der Prozess
ebenso beendet wird, weil nach dem Signal zum korrupten Code zurückgesprungen
werden müsste.&lt;/p&gt;

&lt;p&gt;Es gibt aber einen Ausweg, und der lautet: &lt;a href=&quot;https://www.cplusplus.com/reference/csetjmp/setjmp/&quot;&gt;&lt;code&gt;setjmp() / longjmp()&lt;/code&gt;&lt;/a&gt;. 
Hat man sich nämlich selbst darum gekümmert, den Callstack zu sichern,
dann kann im Signal-Handler per &lt;code&gt;longjmp&lt;/code&gt; zu diesem sicheren Ort 
zurückgesprungen werden.&lt;/p&gt;

&lt;p&gt;Und das funktioniert sogar bei den Signalen &lt;code&gt;SIGSEGV&lt;/code&gt; (Speicherverletzung),
&lt;code&gt;SIGILL&lt;/code&gt; (Falsche CPU Anweisung) oder &lt;code&gt;SIGFPE&lt;/code&gt; (Division durch &lt;code&gt;0&lt;/code&gt; und andere
Rechenfehler).&lt;/p&gt;

&lt;p&gt;Ein Flexibilitätsproblem ist jedoch, dass man Signal-Handler in der Regel 
Prozess-global setzt. Man kann also nicht in Thread &lt;code&gt;A&lt;/code&gt; den Signal-Handler 
&lt;code&gt;x()&lt;/code&gt; einrichten und in Thread &lt;code&gt;B&lt;/code&gt; dann &lt;code&gt;y()&lt;/code&gt; aufrufen lassen.&lt;/p&gt;

&lt;p&gt;Meine Strategie ist daher folgende:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Es wird je ein globaler Signal-Handler für die kritischen Signale
&lt;code&gt;SIGSEGV&lt;/code&gt;, &lt;code&gt;SIGILL&lt;/code&gt; und &lt;code&gt;SIGFPE&lt;/code&gt; am Programmstart gesetzt.&lt;/li&gt;
  &lt;li&gt;Es wird auch ein globaler Schlüssel für eine Thread-local-storage Eintrag
erzeugt (&lt;code&gt;pthread_key_create&lt;/code&gt;).&lt;/li&gt;
  &lt;li&gt;Vor einem kritischen Bereich (also wie beim Start von &lt;code&gt;__try&lt;/code&gt;) wird eine
lokale &lt;code&gt;jmp_buf&lt;/code&gt; Variable angelegt und per &lt;code&gt;setjmp&lt;/code&gt; initialisiert.&lt;/li&gt;
  &lt;li&gt;Nun wird ein Pointer zum &lt;code&gt;jmp_buf&lt;/code&gt; in den Thread-local-storage mit dem
zuvor registriertem Schlüssel gesetzt.&lt;/li&gt;
  &lt;li&gt;Tritt eines der obigen kritischen Signale auf, kann der gesetzte Signal-Handler
den Pointer zum &lt;code&gt;jmp_buf&lt;/code&gt; wieder auslesen und per &lt;code&gt;longjmp&lt;/code&gt; zum gesicherten
Stack zurückspringen.&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#777&quot;&gt;/* crash_guard_sample.c */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#777&quot;&gt;/* gcc ./crash_guard_sample.c -lpthread -o ./crash_guard_sample */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color:#B44;font-weight:bold&quot;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color:#B44;font-weight:bold&quot;&gt;&amp;lt;pthread.h&amp;gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color:#B44;font-weight:bold&quot;&gt;&amp;lt;setjmp.h&amp;gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color:#B44;font-weight:bold&quot;&gt;&amp;lt;signal.h&amp;gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;static&lt;/span&gt; pthread_key_t saved_context_key;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;typedef&lt;/span&gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;struct&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;  jmp_buf anchor;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;} saved_context_t;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;static&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt; crash_handler(&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; signum)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;  saved_context_t* ptr_context = 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;    (saved_context_t*)pthread_getspecific(saved_context_key);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;switch&lt;/span&gt;(signum)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n21&quot; name=&quot;n21&quot;&gt;21&lt;/a&gt;&lt;/span&gt;  {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n22&quot; name=&quot;n22&quot;&gt;22&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;case&lt;/span&gt; SIGSEGV: 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n23&quot; name=&quot;n23&quot;&gt;23&lt;/a&gt;&lt;/span&gt;    longjmp(ptr_context-&amp;gt;anchor, &lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n24&quot; name=&quot;n24&quot;&gt;24&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;case&lt;/span&gt; SIGILL:
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n25&quot; name=&quot;n25&quot;&gt;25&lt;/a&gt;&lt;/span&gt;    longjmp(ptr_context-&amp;gt;anchor, &lt;span style=&quot;color:#00D&quot;&gt;2&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n26&quot; name=&quot;n26&quot;&gt;26&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;case&lt;/span&gt; SIGFPE:
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n27&quot; name=&quot;n27&quot;&gt;27&lt;/a&gt;&lt;/span&gt;    longjmp(ptr_context-&amp;gt;anchor, &lt;span style=&quot;color:#00D&quot;&gt;3&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n28&quot; name=&quot;n28&quot;&gt;28&lt;/a&gt;&lt;/span&gt;  }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n29&quot; name=&quot;n29&quot;&gt;29&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;/* unhandled error */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n30&quot; name=&quot;n30&quot;&gt;30&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n31&quot; name=&quot;n31&quot;&gt;31&lt;/a&gt;&lt;/span&gt;}
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n32&quot; name=&quot;n32&quot;&gt;32&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n33&quot; name=&quot;n33&quot;&gt;33&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt; crashing_function()
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n34&quot; name=&quot;n34&quot;&gt;34&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n35&quot; name=&quot;n35&quot;&gt;35&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt;* &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;volatile&lt;/span&gt; ptr = &lt;span style=&quot;color:#069&quot;&gt;NULL&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n36&quot; name=&quot;n36&quot;&gt;36&lt;/a&gt;&lt;/span&gt;  *ptr = &lt;span style=&quot;color:#00D&quot;&gt;42&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n37&quot; name=&quot;n37&quot;&gt;37&lt;/a&gt;&lt;/span&gt;}
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n38&quot; name=&quot;n38&quot;&gt;38&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n39&quot; name=&quot;n39&quot;&gt;39&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt; run()
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n40&quot; name=&quot;n40&quot;&gt;40&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n41&quot; name=&quot;n41&quot;&gt;41&lt;/a&gt;&lt;/span&gt;  saved_context_t saved_context;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n42&quot; name=&quot;n42&quot;&gt;42&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; crash_status;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n43&quot; name=&quot;n43&quot;&gt;43&lt;/a&gt;&lt;/span&gt;  pthread_setspecific(saved_context_key, &amp;amp;saved_context);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n44&quot; name=&quot;n44&quot;&gt;44&lt;/a&gt;&lt;/span&gt;  crash_status = setjmp(saved_context.anchor);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n45&quot; name=&quot;n45&quot;&gt;45&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt;(crash_status == &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n46&quot; name=&quot;n46&quot;&gt;46&lt;/a&gt;&lt;/span&gt;  {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n47&quot; name=&quot;n47&quot;&gt;47&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#777&quot;&gt;/* try block: */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n48&quot; name=&quot;n48&quot;&gt;48&lt;/a&gt;&lt;/span&gt;    printf(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Before critical code&lt;/span&gt;&lt;span style=&quot;color:#b0b&quot;&gt;\n&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n49&quot; name=&quot;n49&quot;&gt;49&lt;/a&gt;&lt;/span&gt;    crashing_function();
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n50&quot; name=&quot;n50&quot;&gt;50&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;    printf(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Nothing bad happened&lt;/span&gt;&lt;span style=&quot;color:#b0b&quot;&gt;\n&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n51&quot; name=&quot;n51&quot;&gt;51&lt;/a&gt;&lt;/span&gt;  }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n52&quot; name=&quot;n52&quot;&gt;52&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;else&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n53&quot; name=&quot;n53&quot;&gt;53&lt;/a&gt;&lt;/span&gt;  {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n54&quot; name=&quot;n54&quot;&gt;54&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#777&quot;&gt;/* except/catch block */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n55&quot; name=&quot;n55&quot;&gt;55&lt;/a&gt;&lt;/span&gt;    printf(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Critical error #%d caught&lt;/span&gt;&lt;span style=&quot;color:#b0b&quot;&gt;\n&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, crash_status);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n56&quot; name=&quot;n56&quot;&gt;56&lt;/a&gt;&lt;/span&gt;  }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n57&quot; name=&quot;n57&quot;&gt;57&lt;/a&gt;&lt;/span&gt;}
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n58&quot; name=&quot;n58&quot;&gt;58&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n59&quot; name=&quot;n59&quot;&gt;59&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; main()
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n60&quot; name=&quot;n60&quot;&gt;60&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n61&quot; name=&quot;n61&quot;&gt;61&lt;/a&gt;&lt;/span&gt;  printf(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;main() begin&lt;/span&gt;&lt;span style=&quot;color:#b0b&quot;&gt;\n&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n62&quot; name=&quot;n62&quot;&gt;62&lt;/a&gt;&lt;/span&gt;  pthread_key_create(&amp;amp;saved_context_key, &lt;span style=&quot;color:#069&quot;&gt;NULL&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n63&quot; name=&quot;n63&quot;&gt;63&lt;/a&gt;&lt;/span&gt;  signal(SIGSEGV, &amp;amp;crash_handler);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n64&quot; name=&quot;n64&quot;&gt;64&lt;/a&gt;&lt;/span&gt;  signal(SIGILL, &amp;amp;crash_handler);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n65&quot; name=&quot;n65&quot;&gt;65&lt;/a&gt;&lt;/span&gt;  signal(SIGFPE, &amp;amp;crash_handler);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n66&quot; name=&quot;n66&quot;&gt;66&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n67&quot; name=&quot;n67&quot;&gt;67&lt;/a&gt;&lt;/span&gt;  run();
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n68&quot; name=&quot;n68&quot;&gt;68&lt;/a&gt;&lt;/span&gt;  printf(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;main() end&lt;/span&gt;&lt;span style=&quot;color:#b0b&quot;&gt;\n&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n69&quot; name=&quot;n69&quot;&gt;69&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Und streng genommen sollte man nicht &lt;code&gt;setjmp / longjmp&lt;/code&gt; einsetzen, sondern
&lt;code&gt;sigsetjmp / siglongjmp&lt;/code&gt;, die auch die Signalmaske sichern und 
wiederherstellen, ansonsten landet man bei undefiniertem Verhalten, wenn man 
den Signalhandler per &lt;code&gt;longjmp&lt;/code&gt; verlässt.&lt;br /&gt;
Ich hatte damit zwar keine Probleme, doch nur weil etwas funktioniert, heißt
es nicht, dass es damit richtig ist.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Im &lt;a href=&quot;https://codeberg.org/GateNetwork/gate-blog-classroom/src/branch/main/c_cpp/crash_guard/&quot;&gt;BLOG-CLASSROOM&lt;/a&gt; 
habe ich das ganze mal etwas vollständiger als Crash-Guard Bibliothek 
eingefügt. Und im GATE Framework sind die beschriebenen Techniken auch 
eingearbeitet.&lt;/p&gt;

&lt;p&gt;Mein Interesse für diese Thematik begann vor Jahren mit einer Software in 
der ein Plugin immer wieder rätselhafte Abstürze auslöste und mit solchen 
Crashguards konnte ich das Problem auf ein ganz bestimmtes Submodul eingrenzen
und letztendlich lösen.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>restrict</title>
   <link href="https://www.opengate.at/blog/2022/03/restrict/"/>
   <published>2022-03-13T12:00:00+01:00</published>
   <updated>2022-03-13T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2022/03/restrict</id>
   <category term="devel" />
   <summary type="text">Mit der Fehlermeldung


  error C2485: ‘constant’: unrecognized extended attribute


eröffnete mir der MSVC 2022 
beim Kompilieren von libreSSL die 
Möglichkeit, wieder einmal über ein “neueres”
C Schlüsselwort 
nachzudenken, nämlich  restrict

</summary>
   <content type="html">&lt;p&gt;Mit der Fehlermeldung&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;error C2485: ‘constant’: unrecognized extended attribute&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;eröffnete mir der &lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_C%2B%2B&quot;&gt;MSVC&lt;/a&gt; 2022 
beim Kompilieren von &lt;a href=&quot;https://de.wikipedia.org/wiki/LibreSSL&quot;&gt;libreSSL&lt;/a&gt; die 
Möglichkeit, wieder einmal über ein “neueres”
&lt;a href=&quot;https://de.wikipedia.org/wiki/C_(Programmiersprache)&quot;&gt;C Schlüsselwort&lt;/a&gt; 
nachzudenken, nämlich  &lt;code&gt;restrict&lt;/code&gt;&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;was-ist-ein-mit-restrict-markierter-pointer&quot;&gt;Was ist ein mit &lt;code&gt;restrict&lt;/code&gt; markierter Pointer?&lt;/h3&gt;

&lt;p&gt;Das &lt;a href=&quot;https://en.wikipedia.org/wiki/C99&quot;&gt;C99&lt;/a&gt; Schlüsselwort &lt;code&gt;restrict&lt;/code&gt; 
ist vielen Entwicklern unbekannt und hilft daher eher im Hintergrund, den 
generierten Code zu optimieren.&lt;br /&gt;
&lt;code&gt;restrict&lt;/code&gt; “qualifiziert” einen Pointer als alleinigen Zugang zu einer 
Ressource. Ähnlich wie &lt;code&gt;register&lt;/code&gt; ist &lt;code&gt;restrict&lt;/code&gt; nur ein Hinweis für den
Compiler, der angewendet oder ignoriert werden kann.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt;* &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;restrict&lt;/span&gt; foo(&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; arg1, &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt;* &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;restrict&lt;/span&gt; arg2);
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;z.B.: kann &lt;code&gt;malloc()&lt;/code&gt; seine zurückgegebenen Pointer als &lt;code&gt;restrict&lt;/code&gt;ed 
markieren um zu signalisieren, dass zum Zeitpunkt der Allokierung dieser 
Pointer als einziger auf den neuen Speicherblock zeigt.&lt;/p&gt;

&lt;p&gt;So lange Pointer ihren &lt;code&gt;restrict&lt;/code&gt;ed Status behalten, können Pointeroperationen
wie z.B.: &lt;code&gt;memcpy()&lt;/code&gt; oder &lt;code&gt;memmove()&lt;/code&gt; auf Prüfungen verzichten, ob Quelle und 
Ziel einer Speicheroperation sich überschneiden.&lt;br /&gt;
Zwei per &lt;code&gt;malloc()&lt;/code&gt; erzeugte Pointer können per &lt;code&gt;memcpy/move()&lt;/code&gt; sofort
abgearbeitet werden, und zwar mit den schnellst möglichen Instruktionen,
wie z.B. Vektoroperationen.&lt;/p&gt;

&lt;p&gt;Nicht &lt;code&gt;restrict&lt;/code&gt;ed Pointer könnten auf sich überlappende Speicherbereiche
zeigen, womit &lt;code&gt;memcpy/move()&lt;/code&gt; diesen Fall prüfen müssen und erst zur Laufzeit
die geeigneten Bearbeitungsinstruktionen auswählen können.&lt;br /&gt;
Anders gesagt: Da findet oft noch ein zusätzliches &lt;code&gt;if&lt;/code&gt; statt.&lt;/p&gt;

&lt;h3 id=&quot;compiler-support&quot;&gt;Compiler Support&lt;/h3&gt;

&lt;p&gt;Tja, leider hat jeder Compiler-Hersteller “anders” auf &lt;code&gt;restrict&lt;/code&gt; reagiert.
Microsoft hat C99 bis MSVC 13 ignoriert, aber schon vorher &lt;code&gt;__declspec(restrict)&lt;/code&gt;
in C und C++ aufgenommen.&lt;/p&gt;

&lt;p&gt;Im &lt;a href=&quot;https://de.wikipedia.org/wiki/GNU_Compiler_Collection&quot;&gt;GCC&lt;/a&gt; hingegen 
nimmt &lt;code&gt;__restrict__&lt;/code&gt; diesen Platz ein.&lt;/p&gt;

&lt;p&gt;Und aus diesem Grund nutzen manche Bibliotheken eigene Makros um nicht 
&lt;code&gt;restrict&lt;/code&gt; sondern die native Variante des Compiler zu nutzen.&lt;/p&gt;

&lt;p&gt;Und das wiederum kann die Quelle neuer Fehler sein:&lt;/p&gt;

&lt;h3 id=&quot;libressl-und-restrict&quot;&gt;libReSSL und &lt;code&gt;restrict&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;Als ich den Fehler &lt;code&gt;error C2485&lt;/code&gt; sah, konnte ich ihn zu folgender Codestelle
in &lt;code&gt;corecrt.h&lt;/code&gt; zurückverfolgen:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#if&lt;/span&gt; defined _CRT_SUPPRESS_RESTRICT || defined _CORECRT_BUILD
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#579&quot;&gt;#define&lt;/span&gt; _CRTRESTRICT
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#else&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#579&quot;&gt;#define&lt;/span&gt; _CRTRESTRICT __declspec(&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;restrict&lt;/span&gt;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#endif&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Viele allokierende C-Funktionen wie &lt;code&gt;malloc&lt;/code&gt; oder &lt;code&gt;calloc&lt;/code&gt; werden mit 
&lt;code&gt;_CRTRESTRICT&lt;/code&gt; deklariert.&lt;/p&gt;

&lt;p&gt;Die “schnelle” Lösung ist somit, das Makro &lt;code&gt;_CRT_SUPPRESS_RESTRICT&lt;/code&gt; zu
aktivieren, was in &lt;a href=&quot;https://de.wikipedia.org/wiki/CMake&quot;&gt;CMake&lt;/a&gt; so aussieht:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;add_definitions(/D_CRT_SUPPRESS_RESTRICT)
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;und tatsächlich würde das mein Problem bereits lösen.&lt;/p&gt;

&lt;p&gt;Doch bei genauerer Betrachtung, stellt sich heraus, dass nur &lt;code&gt;libreSSL&lt;/code&gt; ein
Problem mit der C-Runtime hat, während alle anderen Libs &lt;code&gt;malloc&lt;/code&gt; mit
&lt;code&gt;_CRTRESTRICT&lt;/code&gt; == &lt;code&gt;__declspec(restrict)&lt;/code&gt; problemlos nutzen können.&lt;/p&gt;

&lt;p&gt;Der Grund liegt in &lt;code&gt;libressl/CMakeLists.txt&lt;/code&gt;, denn dort findet man die Zeilen&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;if(WIN32)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;  add_definitions(-Drestrict)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  ...
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;endif()
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Es wird also ein Makro namens &lt;code&gt;restrict&lt;/code&gt; angelegt und ohne weiteren Parameter 
erhält das Makro den Wert &lt;code&gt;1&lt;/code&gt;.&lt;br /&gt;
Das führt dazu, dass &lt;code&gt;_CRTRESTRICT&lt;/code&gt; als &lt;code&gt;__declspec(1)&lt;/code&gt; aufgelöst wird und
schon haben wir die Ursache für&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;error C2485: ‘constant’: unrecognized extended attribute&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;gefunden.&lt;/p&gt;

&lt;h3 id=&quot;lösung&quot;&gt;Lösung&lt;/h3&gt;

&lt;p&gt;Ich habe den CMAKE Code von &lt;code&gt;libressl&lt;/code&gt; einfach auf&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;if(WIN32)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;  if(NOT MSVC)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;    add_definitions(-Drestrict)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  endif()
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  ...
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;endif()
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;umgestellt, womit MSVC Builds das Makro überspringen. 
In anderen Windows-Kompilaten wie z.B.: beim &lt;a href=&quot;https://de.wikipedia.org/wiki/MinGW&quot;&gt;MinGW&lt;/a&gt; 
kann das Makro gerne weiter seinen Zweck erfüllen, doch im MSVC stört es.&lt;/p&gt;

&lt;p&gt;Tatsächlich stört das Makro nur im Zusammenhang mit den neueren MSVC Compilern
und mit der Universal-CRT (UCRT).&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Im GATE Projekt mache ich weiter einen Bogen um &lt;code&gt;restrict&lt;/code&gt;.
Mir ist es lieber, wenn in machen Fällen ein nicht-perfekter Code generiert 
wird, doch dass dieser zumindest überall kompiliert werden kann.&lt;/p&gt;

&lt;p&gt;Würde ich &lt;code&gt;restrict&lt;/code&gt; selbst benutzen, müsste ich mir genau überlegen, auf 
welche Plattform es verfügbar ist, und dort, wo es fehlt, ebenfalls 
Ersatzmakros setzen.&lt;/p&gt;

&lt;p&gt;Genau diese “Ersatzmakros” machen dann immer Probleme, wenn unterschiedliche
Bibliotheken zusammengeführt werden, und deshalb lasse ich es.&lt;/p&gt;

&lt;p&gt;Aber grundsätzlich ist das sehr Schade, dass ein 20 Jahre altes Feature 
bis heute nicht einheitlich und problemfrei umgesetzt ist und deshalb
Probleme bereitet.&lt;/p&gt;

&lt;p&gt;Zum Glück können heutige Compiler aber viele Informationen aus dem Code
ableiten und auch ohne &lt;code&gt;restrict&lt;/code&gt; viele Optimierungen einleiten.&lt;/p&gt;

&lt;h3 id=&quot;nachtrag&quot;&gt;Nachtrag&lt;/h3&gt;

&lt;p&gt;Und zwei Tage später ist alles anders …&lt;/p&gt;

&lt;p&gt;Am 15. März wurde &lt;code&gt;libreSSL&lt;/code&gt; 3.4.3 veröffentlicht, wo die &lt;code&gt;-Drestrict&lt;/code&gt;
Zeile bereits entfernt wurde.
Offenbar hat man die sowieso nicht gebraucht.&lt;/p&gt;

&lt;p&gt;Das heißt also: Die &lt;a href=&quot;https://de.wikipedia.org/wiki/Transport_Layer_Security&quot;&gt;SSL&lt;/a&gt; 
Jungs haben brav auch ihre Aufgaben gemacht.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Serieller Bypass</title>
   <link href="https://www.opengate.at/blog/2022/03/serial-patch/"/>
   <published>2022-03-12T12:00:00+01:00</published>
   <updated>2022-03-12T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2022/03/serial-patch</id>
   <category term="hardware" />
   <summary type="text">Unterschiedliche Menschen sehen die gleichen Dinge unterschiedlich.
Manche schreiben Buchstaben, die einen von links nach rechts, die anderen 
umgekehrt, und wieder andere malen 
Logogramme von oben nach unten.

… und unterschiedliche Mainboards
nummerieren COM-Port 
Pins unterschiedlich. Einige waagerecht, andere senkrecht.
</summary>
   <content type="html">&lt;p&gt;Unterschiedliche Menschen sehen die gleichen Dinge unterschiedlich.&lt;br /&gt;
Manche schreiben Buchstaben, die einen von links nach rechts, die anderen 
umgekehrt, und wieder andere malen 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Logografie&quot;&gt;Logogramme&lt;/a&gt; von oben nach unten.&lt;/p&gt;

&lt;p&gt;… und unterschiedliche &lt;a href=&quot;https://de.wikipedia.org/wiki/Hauptplatine&quot;&gt;Mainboards&lt;/a&gt;
nummerieren &lt;a href=&quot;https://de.wikipedia.org/wiki/Serielle_Schnittstelle&quot;&gt;COM-Port&lt;/a&gt; 
Pins unterschiedlich. Einige waagerecht, andere senkrecht.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Bevor ich mein offenbar nicht mehr funktionierendes 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Nullmodem-Kabel&quot;&gt;Null-Modem-Kabel&lt;/a&gt; in den 
Müll werfen wollte, machte ich einen letzten Test mit einer Steckbrücke, wo
Senden- (&lt;code&gt;TX&lt;/code&gt;) und Empfangs-Pin (&lt;code&gt;RX&lt;/code&gt;) kurzgeschlossen, um zu erkennen: 
Es funktioniert doch noch!&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Aber warum ließ es mich im Stich, als ich meinen Development-PC mit einem 
meiner &lt;a href=&quot;https://de.wikipedia.org/wiki/Mini-ITX&quot;&gt;ITX-Boards&lt;/a&gt; verbinden wollte?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Beim ITX-Board war die serielle Schnittstelle hinten am Mainboard fix per
&lt;a href=&quot;https://de.wikipedia.org/wiki/D-Sub&quot;&gt;D-SUB-9&lt;/a&gt; Stecker verdrahtet, doch am 
Development-PC hatte ich den seriellen Stecker mit einem Adapter von den 
Mainboard-Pins selbst hinten rausleiten müssen. 
(Denn heutige PCs sparen den RS232-Anschluss leider ein.)&lt;/p&gt;

&lt;p&gt;Meinen Stecker-Adapter hatte ich vor vielen Jahren bei einem anderen Board
ausgebaut und dachte, dass COM Anschlüsse so wie 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Universal_Serial_Bus&quot;&gt;USB&lt;/a&gt; oder 
Audio-Anschlüsse normiert wären.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Tja, falsch gedacht.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/serial-dsub9-adapter.jpg&quot; alt=&quot;Serial DSUB-9 Adapter&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Bei diesem D-SUB-9-Stecker werden die Pins an beiden Enden wagerecht 
durchnumeriert, wie mein Test mit dem Multimeter nachweisen konnte.
Die Pins am Mainboard entsprechen also exakt dem Verlauf der Pins des 
seriellen Steckers von links nach rechts:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: right&quot;&gt;PIN&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Position&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Bedeutung&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;1&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Oben von links 1&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;DCD&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;2&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Oben von links 2&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;RX&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;3&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Oben von links 3&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;TX&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;4&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Oben von links 4&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;DTR&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;5&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Oben von links 5&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;GOUND&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;6&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Unten von links 1&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;DSR&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;7&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Unten von links 2&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;RTR&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;8&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Unten von links 3&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;CTS&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;9&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Unten von links 4&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;RING&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Doch laut Mainboard-Manual werden die Pins am Board immer von oben nach
unten durchgezählt:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/mainboard-serial-pins.gif&quot; alt=&quot;Mainboard serial pins&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;lösung--bastelplatine--steckerbuchsen--lötkolben&quot;&gt;Lösung = Bastelplatine + Steckerbuchsen + Lötkolben&lt;/h3&gt;

&lt;p&gt;Da ich für mein Mainboard keinen RS232-Adapter mitgeliefert bekommen habe,
war die Lösung einfach zwei Steckerbuchsen auf eine Platine zu löten und
die Pins zwischen den beiden richtig zu verdrahten:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/serial-pin-converter.jpg&quot; alt=&quot;Mainboard serial adapter&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Das lästige dabei ist das doppelte spiegelverkehrte Denken zwischen links
und rechts sowie oben und unten … doch für den ersten Test reichten
&lt;code&gt;GND&lt;/code&gt;, &lt;code&gt;TX&lt;/code&gt; und &lt;code&gt;RX&lt;/code&gt; vollkommen aus.&lt;/p&gt;

&lt;p&gt;Zum Glück hatte ich auch noch eine 10-Pin-Verlängerung in meiner 
Sammelkiste und schon konnte der erste Test gemacht werden.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/mainboard-pin-cable.jpg&quot; alt=&quot;Serial DSUB-9 Adapter&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Im Mainboard-Handbuch stand tatsächlich der Kommentar, ich solle mich mit
meinem lokalen Vertriebspartner in Verbindung setzen um einen “offiziellen”
Steckeradapter nachkaufen zu können.&lt;/p&gt;

&lt;p&gt;Doch mit 15 Minuten Bastelarbeit, hat sich das Problem von selbst gelöst und
mein altes Steckerstück darf weiter seinen Dienst tun.&lt;/p&gt;

&lt;p&gt;Es sieht zwar aus wie die Murxerei eines 10-Jährigen, aber es funktioniert.
Und mir geht es ja nur darum, meine Softwaretests durchführen zu können.&lt;/p&gt;

&lt;p&gt;Ich überlege noch, ob ich Schalter einlöten soll, um die Verbindung gezielt 
unterbrechen zu können, denn so kann man Übertragungsfehler ganz einfach
“mechanisch” simulieren.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>archive.org</title>
   <link href="https://www.opengate.at/blog/2022/03/archive-org/"/>
   <published>2022-03-06T12:00:00+01:00</published>
   <updated>2022-03-06T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2022/03/archive-org</id>
   <category term="software" />
   <summary type="text">Entgegen vieler Behauptungen nach der Art:


  Das Internet vergisst nicht.


behaupte ich: Das Gegenteil ist der Fall.
Denn Websites und Software, die 
älter als 5 Jahre sind, verschwinden von heute auf morgen, wenn Firmen Pleite
gehen oder Privatleute ihre Homepage auflösen. 
(Nur bescheuerte Fotos von Fresstellern und Katzen leben auf
Facebook ewig weiter.)

Doch einer kämpft gegen das globale Vergessen an:
Das Internetarchiv von archive.org.
</summary>
   <content type="html">&lt;p&gt;Entgegen vieler Behauptungen nach der Art:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Das Internet vergisst nicht.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;behaupte ich: &lt;em&gt;Das Gegenteil ist der Fall&lt;/em&gt;.&lt;br /&gt;
Denn &lt;a href=&quot;https://de.wikipedia.org/wiki/Website&quot;&gt;Websites&lt;/a&gt; und Software, die 
älter als 5 Jahre sind, verschwinden von heute auf morgen, wenn Firmen Pleite
gehen oder Privatleute ihre Homepage auflösen. 
(Nur bescheuerte Fotos von Fresstellern und Katzen leben auf
&lt;a href=&quot;https://de.wikipedia.org/wiki/Facebook&quot;&gt;Facebook&lt;/a&gt; ewig weiter.)&lt;/p&gt;

&lt;p&gt;Doch einer kämpft gegen das globale Vergessen an:&lt;br /&gt;
Das Internetarchiv von &lt;code&gt;archive.org&lt;/code&gt;.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Tja, da dachte man, die ersten Fehlgriffe in der Webentwicklung aus den
2000ern wären längst vergessen, und dann findet man dennoch ein Abbild
auf &lt;a href=&quot;http://web.archive.org&quot;&gt;&lt;code&gt;web.archive.org&lt;/code&gt;&lt;/a&gt;.
Denn bereits vor 20 Jahren hat das Internet Archiv entweder automatisch
oder bewusst “bestellt” &lt;a href=&quot;https://de.wikipedia.org/wiki/Hypertext_Markup_Language&quot;&gt;HTML&lt;/a&gt; 
Seiten herunter geladen und für die Nachwelt konserviert.&lt;/p&gt;

&lt;h3 id=&quot;ein-blick-in-die-vergangenheit&quot;&gt;Ein Blick in die Vergangenheit&lt;/h3&gt;

&lt;p&gt;Wenn mir also langweilig ist, kommt es schon mal vor, dass ich einen 
Domänennamen eines früheren Arbeitsplatzes eintippe und mich köstlich
darüber amüsiere, wie Homepages “damals” vor 15 Jahren aufgebaut waren
… oder man lacht, weil sich bis heute nichts daran geändert hat …
und dementsprechend “aussieht”.&lt;/p&gt;

&lt;p&gt;Leider funktionieren gerade neuere Snapshots nicht mehr richtig, weil zwar 
der HTML Content und ein paar Grafiken gespeichert wurden, doch diverse 
&lt;a href=&quot;https://de.wikipedia.org/wiki/JavaScript&quot;&gt;Javascripts&lt;/a&gt;, die Daten dynamisch
von den Originaldomains nachladen wollen, versagen unweigerlich.&lt;/p&gt;

&lt;p&gt;Ich selbst habe bei einigen Webprojekten immer wieder zahlreiche
&lt;a href=&quot;https://de.wikipedia.org/wiki/Uniform_Resource_Locator&quot;&gt;URLs&lt;/a&gt; bei 
&lt;code&gt;archive.org&lt;/code&gt; gemeldet, um sie sichern zu lassen, und bin froh, dass sie auf
diese Weise bis heute überlebt haben.&lt;/p&gt;

&lt;h3 id=&quot;das-große-retro-software-archiv&quot;&gt;Das große Retro-Software Archiv&lt;/h3&gt;

&lt;p&gt;Wenn man Wikipedia z.B.: zu &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_PE&quot;&gt;Windows PE&lt;/a&gt; 
befragt, lernt man viel über die unterschiedlichen Versionen … doch 
regulär erhalten kann man leider nur mehr die neuesten.&lt;br /&gt;
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft&quot;&gt;Microsoft&lt;/a&gt; bietet in seinen 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Developer_Network&quot;&gt;MSDN&lt;/a&gt; Abos zwar 
bis heute &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_3.1&quot;&gt;Windows 3.x&lt;/a&gt; und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_Basic_Classic&quot;&gt;Visual Basic Classic&lt;/a&gt; 
2 bis 6 an, doch WinPE wurde mit Ausnahme der neueren 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_10&quot;&gt;Windows 10&lt;/a&gt; Varianten von
den Downloadseiten entfernt.&lt;/p&gt;

&lt;p&gt;Welch Glück, dass einige aufmerksame Mitmenschen dieses Manko bemerkt haben 
und ihre damals gesicherten Downloads wieder verfügbar gemacht haben,
und zwar auf &lt;code&gt;archive.org&lt;/code&gt;.
(Lizenztechnisch sollte das in Ordnung gehen, da WinPE immer schon frei 
verfügbar war und nur der produktive Einsatz an andere Windows-Lizenzen 
gebunden war.)&lt;/p&gt;

&lt;p&gt;Nach einer Registrierung kann nämlich jeder User Daten auf diese Plattform 
hochladen.&lt;br /&gt;
Gedacht ist das natürlich primär für freie Informationen und persönliche
Daten (wie z.B. alte Fotos oder Bücher), doch inzwischen findet man dort auch 
eine Vielzahl von Softwarestücken, deren Softwarepatente und anderen 
Beschränkungen abgelaufen sind.&lt;/p&gt;

&lt;p&gt;Und so hat sich &lt;code&gt;archive.org&lt;/code&gt; zu einem interessantem 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Museum&quot;&gt;Museum&lt;/a&gt; für digitale Werke entwickelt 
und konserviert auf diese Weise auch den “Zeitgeist” der Softwareindustrie 
der vergangenen Jahrzehnte.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ich finde solche Projekte wirklich großartig, denn mit einer größeren
Organisation im Hintergrund, hege ich die Hoffnung, dass dieses Archiv 
sicher noch lange überdauern wird.&lt;/p&gt;

&lt;p&gt;Denn dass viele digitale Werke oft mit dem Tod ihrer Autoren vollständig
aus dem Netz verschwinden, ist dem kommerziellen Gedanken der Provider 
geschuldet. Sobald die nächste Jahresrechnung einer Domain nicht bezahlt
wurde, oder ein kostenloser Hoster eingegangen ist, verschwinden oft 
unzählige wertvolle Dokumentationen zu Technik und Software für immer.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;archive.org&lt;/code&gt; wirkt der Netz-Demenz nachhaltig entgegen und ich hoffe, 
dass vielleicht auch meine Beiträge auf diese Weise ein “längeres” Leben 
beschreiten dürfen.&lt;br /&gt;
Und gleichsam möchte ich auch für diese Plattform werben, dass auch andere
Entwickler und Blogger ihre Inhalte über das Archiv verewigen lassen.&lt;/p&gt;

&lt;p&gt;Wie man heute also sagt: &lt;em&gt;Daumen hoch!&lt;/em&gt;  👍&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Logging und Zustände</title>
   <link href="https://www.opengate.at/blog/2022/03/logging/"/>
   <published>2022-03-05T12:00:00+01:00</published>
   <updated>2022-03-05T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2022/03/logging</id>
   <category term="devel" />
   <summary type="text">Wenn man mit Hintergrunddiensten arbeitet, die sich schwerer debuggen lassen
und an keine UI oder 
Konsole gebunden sind, bekommt ein uraltes Schema wieder eine große 
Bedeutung: Nämlich leicht lesbare Logdateien.

Basierend auf den Erfahrungen mit anderen Bibliotheken wurde im GATE Framework
auch ein “etwas anderes” Logging-System integriert.

</summary>
   <content type="html">&lt;p&gt;Wenn man mit Hintergrunddiensten arbeitet, die sich schwerer debuggen lassen
und an keine &lt;a href=&quot;https://de.wikipedia.org/wiki/Benutzerschnittstelle&quot;&gt;UI&lt;/a&gt; oder 
Konsole gebunden sind, bekommt ein uraltes Schema wieder eine große 
Bedeutung: Nämlich leicht lesbare &lt;a href=&quot;https://de.wikipedia.org/wiki/Logdatei&quot;&gt;Logdateien&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Basierend auf den Erfahrungen mit anderen Bibliotheken wurde im GATE Framework
auch ein “etwas anderes” Logging-System integriert.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Viele Softwarekomponenten erachten Logs als Debugging-Feature, das keinen
Standards zu folgen braucht.&lt;br /&gt;
Genau deshalb gibt es keinen mir bekannten übergreifenden Standard, was in
einem Log-Eintrag genau drinnen stehen sollen.&lt;/p&gt;

&lt;p&gt;Das fängt an mit reinen Textzeilen, wo jede Zeile eine unformatierte Nachricht
sein kann und endet bei &lt;a href=&quot;https://de.wikipedia.org/wiki/CSV_(Dateiformat)&quot;&gt;CSV&lt;/a&gt; 
oder anders separierten Textzeilen, die beliebig viele Felder beinhalten können.&lt;/p&gt;

&lt;p&gt;Die meisten beginnen noch ziemlich gleich, nämlich mit einem Zeitstempel,
doch schon die Frage, wie der aufgebaut sein soll, zieht zahlreiche 
Interpretationsunterschiede (z.B. UTC oder Lokalzeit) nach sich.&lt;br /&gt;
Auch gibt es häufig &lt;code&gt;LOGLEVELS&lt;/code&gt;, die die nachfolgende Nachricht als
&lt;code&gt;INFO&lt;/code&gt;, &lt;code&gt;WARNING&lt;/code&gt; oder &lt;code&gt;ERROR&lt;/code&gt; qualifizieren sollen.&lt;br /&gt;
Und auch sie sind in jedem Projekt anders aufgebaut.&lt;/p&gt;

&lt;h3 id=&quot;gate-logentry-definition&quot;&gt;GATE LogEntry Definition&lt;/h3&gt;

&lt;p&gt;Das GATE Logging Framework definiert ein Interface, um eigene Logger
zu implementieren und um diese auch “global” registrieren zu können.&lt;br /&gt;
Die vorbereitete Standardimplementierung ist ebenso Text-Datei-basiert, 
setzt jedoch Dateisperren ein, um ein gegenseitiges Überschreiben von 
mehreren Threads zu verhindern.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Format:&lt;br /&gt;
Die Felder in einer Logzeile werden durch &lt;code&gt;TAB&lt;/code&gt; Zeichen getrennt, um weiter
maschinenlesbaren Code zu generieren, der aber bei der Ausgabe auf der 
Konsole zumindest “halbwegs” formatiert ist und die Felder zumindest
teilweise tabellarisch dargestellt werden.&lt;/li&gt;
  &lt;li&gt;Zeit:&lt;br /&gt;
Die Uhrzeit soll immer als &lt;a href=&quot;https://de.wikipedia.org/wiki/ISO_8601&quot;&gt;ISO 8601&lt;/a&gt; 
formatierte Lokalzeit dargestellt werden und eine Auflösung von 
Millisekunden haben.
z.B.: &lt;code&gt;2022-03-05T23:59:59.999+01:00&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;Durch ISO 8601 lässt sich die lokale Zeit immer auf eine vergleichbare 
globale umrechnen und trotzdem gehen wichtige Infos, wie die lokale
Datumsgrenze nicht verloren.&lt;br /&gt;
Denn häufig macht es Sinn sehen zu können, ob Probleme eher am lokalen 
Morgen auftreten (z.B. Arbeitsschichtbeginn), oder nach Mitternacht,
wenn oft Backups oder andere Mechanismen anspringen.&lt;/li&gt;
      &lt;li&gt;Eine Auflösung von Millisekunden erscheint mir in der Regel hoch
genug, da oft auch Betriebssysteme gar keine höhere Auflösung zuverlässig
liefern können. (Ausnahme bestätigen natürlich die Regel.)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Prozess + &lt;a href=&quot;http://en.cppreference.com/w/cpp/thread/thread/id&quot;&gt;Thread-ID&lt;/a&gt;:&lt;br /&gt;
So lassen sich Log-Einträge wunderbar eindeutig einer Ausführung zuordnen.
Prozess-IDs lassen Rückschlüsse auf Neustarts oder Abstürze zu, während
Thread-IDs parallele Ausführungen identifizieren können.&lt;/li&gt;
  &lt;li&gt;Log-Type (oder auch log-level):&lt;br /&gt;
Hier habe ich mir einen neuen einfallen lassen, den man sonst selten
antrifft, nämlich &lt;code&gt;STATUS&lt;/code&gt; und dieser reiht sich wie folgt ein:
    &lt;ul&gt;
      &lt;li&gt;&lt;code&gt;TRACE&lt;/code&gt;: Jede (auch noch so unwichtige) Aktion wird geloggt.&lt;/li&gt;
      &lt;li&gt;&lt;code&gt;DEBUG&lt;/code&gt;: Alle internen Zwischenschritte werden geloggt, die vor allem 
dem Programmierer helfen sollen.&lt;/li&gt;
      &lt;li&gt;&lt;code&gt;INFO&lt;/code&gt;: Logt alle logischen Schritte, damit ein Anwender den
Ablauf eines Prozesses nachvollziehen kann.&lt;/li&gt;
      &lt;li&gt;&lt;code&gt;STATUS&lt;/code&gt;: Logt alle großen “Meilensteine”, also Statusänderungen,
die durch den Abschluss einer Teiloperation erreicht werden.&lt;/li&gt;
      &lt;li&gt;&lt;code&gt;WARN&lt;/code&gt;: Logt Warnungen, also Fehler, die noch nicht sonderlich kritisch
sind, aber trotzdem beobachtet werden sollten.&lt;/li&gt;
      &lt;li&gt;&lt;code&gt;ERROR&lt;/code&gt;: Logt Fehler, die das Erreichen des Pogrammzieles verhindern
können oder verhindert haben.&lt;/li&gt;
      &lt;li&gt;&lt;code&gt;FATAL&lt;/code&gt;:  Logt extrem kritische Fehler, die eine spätere “Verbesserung”
der Situation ausschließen.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Result-Code:&lt;br /&gt;
Da fast alle GATE-APIs diese Codes nutzen, die Fehler einigermaßen
abstrakt beschreiben können, werden sie auch hier geloggt.&lt;/li&gt;
  &lt;li&gt;Native-Code:&lt;br /&gt;
Zusätzlich zum generischen Result-Code kann optional der originale
Fehler als Zahl ausgedrückt werden. Dieser hat dann je nach benutzter
API eine andere Bedeutung, hilft aber beim Debugging.
Meist stammt er aber von 
&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-getlasterror&quot;&gt;GetLastError()&lt;/a&gt;
oder &lt;a href=&quot;https://en.wikipedia.org/wiki/Errno.h&quot;&gt;errno&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;Origin/Module:&lt;br /&gt;
Name des Ursprungs oder des Modules, in dem das Log-Ereignis aufgetreten ist.
Hier kann man eine Kombination aus Software-Paket und Klasse oder Funktion
eintragen.&lt;/li&gt;
  &lt;li&gt;Message:&lt;br /&gt;
Diese Text Nachricht soll vor allem dem Endanwender konkret schildern, was
genau passiert ist.&lt;/li&gt;
  &lt;li&gt;Source/Location:
Optional kann man dann noch Quellcode-Datei + Zeilennummer speichern, um
den exakten Ort des Problems ausfindig machen zu können.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Bei der Initialisierung des Logging-Frameworks kann man auch konfigurieren,
ab welchem Loglevel Daten mitgeschrieben werden sollen.&lt;/p&gt;

&lt;p&gt;Und genau deshalb habe ich mich für den Loglevel &lt;code&gt;STATUS&lt;/code&gt; als reduzierte 
Form von &lt;code&gt;INFO&lt;/code&gt; entschieden, um nicht den Überblick in Detailinformationen
zu verlieren.&lt;/p&gt;

&lt;p&gt;Denn während Probleme (ab &lt;code&gt;WARN&lt;/code&gt;) hoffentlich eher selten in Logs vermerkt
sind, stellt das Level &lt;code&gt;INFO&lt;/code&gt; oft sehr viele Details ein, die anfangs alle
sinnvoll wirken, aber bei größeren Projekten gerne auswuchern.&lt;/p&gt;

&lt;p&gt;Mit &lt;code&gt;STATUS&lt;/code&gt; soll also nicht jede geöffnete Datei abgebildet werden, sondern 
nur das Erreichen von “operativ-relevanten” Zuständen.&lt;br /&gt;
Ein klassisches Beispiel wäre der “Operational” Zustand eines Dienstes,
nachdem er zahlreiche Initialisierungsschritte und kleinere Hilfsdienste
ausgeführt hat.&lt;/p&gt;

&lt;p&gt;Im produktiven Betrieb lässt sich so einfach nach &lt;code&gt;&amp;gt;= STATUS&lt;/code&gt; filtern um
schnell einen Überblick zu bekommen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Der Microservice-Hosting Dienst &lt;code&gt;gatesvc&lt;/code&gt; nutzt vorerst das “einfache”
Dateilogging um seine Zustände nachvollziehbar niederzuschreiben und
damit konnte ich vom &lt;a href=&quot;https://de.wikipedia.org/wiki/Docker_(Software)&quot;&gt;Docker&lt;/a&gt;,
&lt;a href=&quot;http://docs.microsoft.com/en-us/windows-server/get-started/getting-started-with-nano-server&quot;&gt;Nanoserver&lt;/a&gt;
bis hin zu &lt;a href=&quot;https://de.wikipedia.org/wiki/Berkeley_Software_Distribution&quot;&gt;BSD&lt;/a&gt;
Daemon Startups wieder einige Bugs finden und bekämpfen.&lt;/p&gt;

&lt;p&gt;Langfristig macht es vielleicht Sinn sich einen eigenen Logging-Dienst
zu basteln, der die Logs systematischer und ohne Dateisperren verwaltet, 
doch die aktuelle Implementierung glänzt durch Einfachheit und Unabhängigkeit.&lt;/p&gt;

&lt;p&gt;Mal sehen, wie sich das weiterentwickelt.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;strong&gt;PS&lt;/strong&gt;: Eines kann ich jedenfalls ausschließen:&lt;br /&gt;
Nämlich dass komplexe 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Log4j#Bekanntwerden_einer_Sicherheitsl%C3%BCcke_im_Dezember_2021&quot;&gt;Fehlerfallen wie log4j&lt;/a&gt;
bei mir Einzug erhalten, die ungefragt die zu loggende Nachricht auf Muster 
parsen und diese dann auch noch ausführen wollen.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Lokale C++ Typen</title>
   <link href="https://www.opengate.at/blog/2022/02/local-type/"/>
   <published>2022-02-27T12:00:00+01:00</published>
   <updated>2022-02-27T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2022/02/local-type</id>
   <category term="devel" />
   <summary type="text">Compiler Experimente mit älteren Varianten des GCC 
haben mir leider einen Workaround zerschossen, den ich als Abstraktion und 
Ersatz von  Lambda Ausdrücken 
vorgesehen hatte:

Nämlich den Einsatz von lokalen Typen.
Konkret: Klassen, die innerhalb einer Funktion deklariert werden.

</summary>
   <content type="html">&lt;p&gt;Compiler Experimente mit älteren Varianten des &lt;a href=&quot;https://de.wikipedia.org/wiki/GNU_Compiler_Collection&quot;&gt;GCC&lt;/a&gt; 
haben mir leider einen Workaround zerschossen, den ich als Abstraktion und 
Ersatz von  &lt;a href=&quot;/blog/2021/05/lambda/&quot;&gt;Lambda Ausdrücken&lt;/a&gt; 
vorgesehen hatte:&lt;/p&gt;

&lt;p&gt;Nämlich den Einsatz von lokalen Typen.&lt;br /&gt;
Konkret: Klassen, die innerhalb einer Funktion deklariert werden.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Wenn der GCC nämlich einen Fehler wie folgt produziert:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;error: template argument for &lt;code&gt;some_function(...)&lt;/code&gt; uses local type
&lt;code&gt;other_function::class_name&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Wurde ein Fall ausgelöst, den Microsofts &lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_C%2B%2B&quot;&gt;MSVC&lt;/a&gt;
offenbar immer schon ignoriert hatte und der beim GCC mit der Aktivierung 
von &lt;a href=&quot;https://en.wikipedia.org/wiki/C%2B%2B11&quot;&gt;C++11&lt;/a&gt; entschärft wurde.&lt;/p&gt;

&lt;p&gt;Auf &lt;a href=&quot;https://stackoverflow.com/questions/5751977/local-type-as-template-arguments-in-c&quot;&gt;stackoverflow.com&lt;/a&gt;
wurde auch schon die Erklärung präsentiert: Man darf nämlich solche lokalen 
Typen nicht in Templates benutzen.&lt;br /&gt;
Dort schlägt dann nämlich die Typenableitung fehlt.&lt;/p&gt;

&lt;p&gt;Bisher war mir das nicht aufgefallen, da meine Testkompilate immer mit
GCC Varianten &lt;code&gt;&amp;gt;= 6&lt;/code&gt; erfolgten, doch mit einem GCC 5 wird der Fehler 
sofort sichtbar.&lt;/p&gt;

&lt;p&gt;Mit C++11 wurde (vermutlich eben genau wegen Lambdas und &lt;code&gt;auto&lt;/code&gt;) diese Regel 
gelockert, wovon bei den neueren GCCs offenbar auch die älteren C++ Standards
berührt werden.&lt;/p&gt;

&lt;p&gt;Die “schnelle” Lösung sieht also so aus, dass beim GCC C++11 immer aktiviert
ist.&lt;/p&gt;

&lt;p&gt;In &lt;a href=&quot;https://de.wikipedia.org/wiki/CMake&quot;&gt;CMAKE&lt;/a&gt; kann man das entweder mit der 
Variable &lt;code&gt;CMAKE_CXX_STANDARD=11&lt;/code&gt; (ab CMAKE 3.1) erreichen, oder indem man den 
&lt;code&gt;CMAKE_CXX_FLAGS&lt;/code&gt; einfach ein &lt;code&gt;-std=gnu++11&lt;/code&gt; anhängt.&lt;/p&gt;

&lt;p&gt;Doch genau das führt jetzt meine ursprüngliche Implementierung teils ad 
absurdum und macht sie zu einer reinen MSVC-only Lösung.&lt;br /&gt;
Denn mit C++11 werden Lambdas im Sprachstandard aktiviert und somit kommt
mein Workaround mit Makros und lokalen Klassen gar nicht zu Einsatz.&lt;/p&gt;

&lt;p&gt;Und somit fällt die Kompatibilität zu noch älteren GCCs ohne C++11 
vollständig weg, was ich eigentlich nicht wollte.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;Tja … zu früh gefreut. Oder?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ich bin mir jetzt noch nicht sicher, wie ich mit der Erkenntnis umgehen soll.
In Sachen Kompatibilität ist mein Anspruch in Richtung Microsoft weitreichender,
als das unter &lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt; der Fall wäre.&lt;/p&gt;

&lt;p&gt;Mit &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_CE&quot;&gt;WinCE&lt;/a&gt; bleibt der 
MSVC 2005 nach wie vor ein “notwendiger” Compiler für mich, wo der 
Workaround funktioniert.&lt;br /&gt;
Aber antike Linux-Systeme mit C++98/03 von vor über 10 Jahren muss ich (aktuell)
nicht supporten … von daher kann ich mich vorläufig auf der erzwungenem C++11
Konfiguration ausruhen.&lt;/p&gt;

&lt;p&gt;Zumindest habe ich nun eine Erklärung dafür gefunden, warum z.B. 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Boost_(C%2B%2B-Bibliothek)&quot;&gt;boost&lt;/a&gt; Lambdas
auch nie über lokale Typen implementiert hat.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Und die Moral von der Geschicht’:&lt;br /&gt;
Buggy-Compiler erlauben vieles.&lt;br /&gt;
Aber standard-konforme eben nicht.&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>Lupus est homo homini</title>
   <link href="https://www.opengate.at/blog/2022/02/lupus/"/>
   <published>2022-02-26T12:00:00+01:00</published>
   <updated>2022-02-26T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2022/02/lupus</id>
   <category term="general" />
   <summary type="text">Während 1000 km von mir entfernt Schusswaffen abgefeuert werden, habe ich
sie heute wieder aus meiner DVD Sammlung
rausgesucht: Eine der vermutlich bedeutendsten Folgen aus der Serie 
Star Trek Deep Space 9.

Es war die 8. Folge der 7. Staffel, 
in der das sonst so sterile Set von Raumschiffen durch die raue 
Kulisse eines Stellungskrieges ausgewechselt wurde und wo nur Waffengewalt 
und Zerstörung die Handlung dominierten.
</summary>
   <content type="html">&lt;p&gt;Während 1000 km von mir entfernt Schusswaffen abgefeuert werden, habe ich
sie heute wieder aus meiner &lt;a href=&quot;https://de.wikipedia.org/wiki/DVD&quot;&gt;DVD&lt;/a&gt; Sammlung
rausgesucht: Eine der vermutlich bedeutendsten Folgen aus der Serie 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Star_Trek:_Deep_Space_Nine&quot;&gt;Star Trek Deep Space 9&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Es war die &lt;a href=&quot;https://de.wikipedia.org/wiki/Star_Trek:_Deep_Space_Nine/Staffel_7&quot;&gt;8. Folge der 7. Staffel&lt;/a&gt;, 
in der das sonst so sterile Set von Raumschiffen durch die raue 
Kulisse eines Stellungskrieges ausgewechselt wurde und wo nur Waffengewalt 
und Zerstörung die Handlung dominierten.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Und in dieser Folge spricht der sonst listige (außerirdische) Geschäftsmann 
einmal ernsthaft seinem Neffen ins Gewissen, der seinen Dienst in der 
Verteidigungstruppe antritt:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Menschen sind ein wundervolles zuvorkommendes Volk, 
so lange sie den Bauch voll haben, … 
aber wenn du ihnen ihre leiblichen Genüsse entziehst,
ihnen z.B. die Nahrung vorenthältst und den Schlaf …
dann wird das ihr Leben … in Gefahr bringen und genau die selben 
freundlichen, intelligenten und überaus zuvorkommenden Menschen, 
die werden plötzlich so gefährlich, und so gewalttätig, 
wie der schlimmste blutrünstigste 
&lt;a href=&quot;https://de.wikipedia.org/wiki/V%C3%B6lker_und_Gruppierungen_im_Star-Trek-Universum#Klingonen&quot;&gt;Klingone&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;(Zitat aus DS9-S7-E8.)&lt;/p&gt;

&lt;video controls=&quot;&quot;&gt;
  &lt;source src=&quot;/blog/assets/video/ds9-s7e08-clip.m4v&quot; type=&quot;video/mp4&quot; /&gt;
  Your browser does not support the HTML5 VIDEO tag.
&lt;/video&gt;

&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Armin_Shimerman&quot;&gt;Armin Shimerman&lt;/a&gt; in der Rolle 
des “Quark” und der inzwischen leider verstorbene 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Aron_Eisenberg&quot;&gt;Aron Eisenberg&lt;/a&gt; als junger 
Kadett “Nog” werden mir vor allem in dieser Szene immer in Erinnerung bleiben.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;600 Kilometer westlich von Wien endet Österreich beim &lt;a href=&quot;https://de.wikipedia.org/wiki/Bodensee&quot;&gt;Bodensee&lt;/a&gt;.
Die gleiche Strecke nach Osten (leicht nördlich) auf der Landkarte
aufgetragen befindet man sich bereits in der &lt;a href=&quot;https://de.wikipedia.org/wiki/Ukraine&quot;&gt;Ukraine&lt;/a&gt;, 
einem Land in dem diese Woche russische Truppen einmarschiert sind und 
mit schwerer Kriegsmaschinerie auf die Hauptstadt 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Kiew&quot;&gt;Kiew&lt;/a&gt; geschossen wird.&lt;/p&gt;

&lt;p&gt;Ich kenne weder Russen noch Ukrainer persönlich, verstehe nichts von der 
dortigen Lage und bilde mir auch nicht ein, ein Urteil über Recht und Unrecht
abgeben zu können.&lt;/p&gt;

&lt;p&gt;Aber vielleicht gibt es in der großen Stadt Kiew jemanden, der mir irgendwie 
ähnlich ist. Ein nerdiger Typ, der viel Zeit vor dem Computer verbringt und 
einfach nur Spaß daran hat, irgendwelche Problemchen mit seinen Maschinen
zu lösen. Einer, der auch sein Hobby zum Beruf gemacht hat und einfach nur 
sein Leben leben will.&lt;/p&gt;

&lt;p&gt;Nun schlagen Geschosse in Familienhäusern in seiner Nachbarschaft ein.
Seine Mutter und seine Schwester werden mit Nottransporten weggebracht,
doch er und sein Vater werden einberufen. Ihnen wird eine Waffe in die Hand
gedrückt und sie sollen mit anderen Männern die Heimat verteidigen.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Was wäre, wenn unsere Rollen vertauscht wären?&lt;br /&gt;
Er säße in Wien und könnte Codes tippen und ich müsste nun 
bewaffnet durch die Gassen von Kiew laufen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ich kann es mir einfach nicht vorstellen.&lt;br /&gt;
Ich kann an Szenen aus Filmen und Serien denken, wo am Ende wieder alles
gut wird.&lt;br /&gt;
Ich kann Nachrichten lesen und dann einen Kommentar drunter schreiben,
wie furchtbar das sei …&lt;br /&gt;
aber wirklich vorstellen kann ich es mir nicht.&lt;/p&gt;

&lt;p&gt;Ich würde innerlich vermutlich von Angst und Unverständnis zerfressen werden.
Ich könnte es einfach nicht fassen, wie es passieren konnte, dass nicht nur
mein Eigenheim, sondern auch mein Lebensinhalt gerade zerschossen wird.&lt;/p&gt;

&lt;p&gt;Es würde mich nicht interessieren, was Politiker sich gedacht hatten 
oder eben nicht gedacht hatten, als sie Öl ins Feuer gossen, warum sie
unverfroren zündelten oder ignorant zusahen, als andere zündelten.&lt;br /&gt;
Denn ich würde einfach nur nach Hause wollen, in mein unbeschadetes
Zuhause von gestern, als die Welt noch in Ordnung war.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Ich finde keine Worte, die ich weder meinem fiktiven “Coding-Bruder” in Kiew,
noch seiner Familie, noch seiner Nation sagen könnte, 
die hinreichend trösten können.&lt;/p&gt;

&lt;p&gt;Ich werde dem Spendenaufruf folgen, damit ich behaupten kann, ich hätte 
versucht zu helfen, aber den Menschen wirklich helfen kann nur 
die Einstellung aller Kampfhandlungen.&lt;/p&gt;

&lt;p&gt;Wie? Wie konnte es geschehen, dass Nachbarn auf einander schießen?&lt;br /&gt;
Es gab keine Hungersnot, keine Naturgewalt.&lt;br /&gt;
Es war einfach nur “ein Wille zur Gewalt”.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Die alte lateinische Zeile&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Homo_homini_lupus&quot;&gt;lupus est homo homini.&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;beschreibt, wie wir Menschen bis heute sind:
Nämlich unfähig das niedere Tier (den Wolf) in uns zu überwinden.&lt;br /&gt;
Und ausbaden dürfen das stets jene, die sich am wenigsten dagegen
wehren können.&lt;/p&gt;

&lt;p&gt;Den Opfern der Kriegshandlungen in der Ukraine (auf beiden Seiten) gilt mein 
Mitgefühl, denn hier kämpfen Menschen ohne einen ideologischen Grund gegen
einander. Nachbarn wurde aufgetragen auf einander zu schießen.&lt;/p&gt;

&lt;p&gt;Die DS9 Folge S07E08 endet für Star Trek ungewöhnlich düster.
Denn … die Opfer eines Krieges können nicht ungeschehen gemacht werden.
Man kann nur noch den Toten gedenken und stets einmahnen,
diese Opfer nie zu vergessen, wie auch das Serienzitat aufzeigt:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Wir dürfen das niemals vergessen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;video controls=&quot;&quot;&gt;
  &lt;source src=&quot;/blog/assets/video/ds9-s7e08-clip2.m4v&quot; type=&quot;video/mp4&quot; /&gt;
  Your browser does not support the HTML5 VIDEO tag.
&lt;/video&gt;
</content>
 </entry>
 
 <entry>
   <title>daemonize()</title>
   <link href="https://www.opengate.at/blog/2022/02/daemonize/"/>
   <published>2022-02-20T12:00:00+01:00</published>
   <updated>2022-02-20T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2022/02/daemonize</id>
   <category term="devel" />
   <summary type="text">Tools wie daemonize oder start-stop-daemon starten laut 
ManPage einen Prozess 
“als Daemon” unter 
BSD oder 
Linux.
Doch die Einrichtung und der automatische Start von Diensten unter 
unixoiden Systemen ist am Ende dann doch noch etwas ganz anderes.

Und wieder einmal muss ich mich zuerst mal mit mir selbst einigen, wie man
das daemon Konzept in C/C++ 
Programmen integrieren kann.
</summary>
   <content type="html">&lt;p&gt;Tools wie &lt;code&gt;daemonize&lt;/code&gt; oder &lt;code&gt;start-stop-daemon&lt;/code&gt; starten laut 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Manpage&quot;&gt;ManPage&lt;/a&gt; einen Prozess 
“als &lt;a href=&quot;https://de.wikipedia.org/wiki/Daemon&quot;&gt;Daemon&lt;/a&gt;” unter 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Berkeley_Software_Distribution&quot;&gt;BSD&lt;/a&gt; oder 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt;.&lt;br /&gt;
Doch die Einrichtung und der automatische Start von Diensten unter 
unixoiden Systemen ist am Ende dann doch noch etwas ganz anderes.&lt;/p&gt;

&lt;p&gt;Und wieder einmal muss ich mich zuerst mal mit mir selbst einigen, wie man
das &lt;code&gt;daemon&lt;/code&gt; Konzept in &lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B&quot;&gt;C/C++&lt;/a&gt; 
Programmen integrieren kann.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Während unter &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows&quot;&gt;Windows&lt;/a&gt; ein 
Hintergrunddienst vom Betriebssystem standardisiert verwaltet wird, lag die 
Verwaltung in &lt;a href=&quot;https://de.wikipedia.org/wiki/Unix&quot;&gt;Unix&lt;/a&gt;, BSD und Linux stets 
in den Händen der Hersteller.&lt;/p&gt;

&lt;p&gt;Eine Zeit lang waren &lt;a href=&quot;https://de.wikipedia.org/wiki/SysVinit&quot;&gt;SysV&lt;/a&gt; Init-Scripts
der einzige de-facto Standard, bis Linux mit &lt;a href=&quot;https://de.wikipedia.org/wiki/Systemd&quot;&gt;systemd&lt;/a&gt;
wieder auszuscheren versuchte.&lt;br /&gt;
Auf die &lt;a href=&quot;https://de.wikipedia.org/wiki/Linux_Standard_Base&quot;&gt;Linux-Standard-Base&lt;/a&gt; (LSB), 
die ursprünglich versuchte auch die Init-Scripts zu vereinheitlichen, kann 
man sich leider auch nicht verlassen, da einige Distributionen diesen 
Standard gar nicht und andere ihn nur halbherzig implementieren.&lt;/p&gt;

&lt;h3 id=&quot;problem-1-wer-forkt&quot;&gt;Problem 1: Wer fork()t?&lt;/h3&gt;

&lt;p&gt;Ein Prozess wird zum &lt;code&gt;daemon&lt;/code&gt; wenn er seine Abhängigkeiten zum Aufrufer
unterbricht. Das wird durch zwei &lt;a href=&quot;https://pubs.opengroup.org/onlinepubs/009695399/functions/fork.html&quot;&gt;&lt;code&gt;fork()&lt;/code&gt;&lt;/a&gt; 
Aufrufe erreicht, wo im ersten Kind per &lt;a href=&quot;https://pubs.opengroup.org/onlinepubs/009695399/functions/setsid.html&quot;&gt;&lt;code&gt;setsid()&lt;/code&gt;&lt;/a&gt;
eine neue Session (und Prozessgruppe) erstellt wird und optional auf einen 
anderen Useraccount gewechselt wird (&lt;a href=&quot;https://pubs.opengroup.org/onlinepubs/009695399/functions/setuid.html&quot;&gt;&lt;code&gt;setuid()&lt;/code&gt;&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Das zweite Kind ist dann der eigentliche &lt;code&gt;daemon&lt;/code&gt; und wenn sein Eltern- und 
Großelternprozess danach beendet werden, verliert der Daemon seine Bindung an
die Prozessgruppe des ursprünglichen Aufrufers. Der neue &lt;code&gt;parent&lt;/code&gt; wird
&lt;code&gt;init&lt;/code&gt; (bzw. ID &lt;code&gt;1&lt;/code&gt;) und der &lt;code&gt;daemon&lt;/code&gt; ist dann nicht mehr von Gruppen-&lt;code&gt;kill&lt;/code&gt; 
Aufrufen seiner Macher bedroht.&lt;/p&gt;

&lt;p&gt;Weil man hier aber auch viele Fehler machen kann, hat es sich eingebürgert,
dass ein Prozess diese &lt;code&gt;fork()&lt;/code&gt;s nicht mehr selbst durchführt.
Anstatt dessen ruft das &lt;code&gt;init&lt;/code&gt; Script &lt;code&gt;start-stop-daemon&lt;/code&gt; auf, der sich 
selbst entsprechend &lt;code&gt;fork()&lt;/code&gt;t und am Ende den &lt;code&gt;daemon&lt;/code&gt; Prozess einfach per 
&lt;a href=&quot;https://pubs.opengroup.org/onlinepubs/7908799/xsh/execl.html&quot;&gt;&lt;code&gt;exec()&lt;/code&gt;&lt;/a&gt; startet.&lt;/p&gt;

&lt;p&gt;Im &lt;code&gt;daemon&lt;/code&gt; muss man daher gar nichts mehr tun, nur noch den eigentlich Job.&lt;/p&gt;

&lt;p&gt;… doch diese Methode wird nicht von allen Diensten benutzt, und vor allem 
ist &lt;code&gt;start-stop-daemon&lt;/code&gt; oder auch &lt;code&gt;daemonize&lt;/code&gt; kein 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Portable_Operating_System_Interface&quot;&gt;POSIX&lt;/a&gt;
Standard, womit das auf jeder Distribution anders ablaufen kann.&lt;/p&gt;

&lt;h3 id=&quot;problem-2-wer-verwaltet-das-pid-file&quot;&gt;Problem 2: Wer verwaltet das PID-File?&lt;/h3&gt;

&lt;p&gt;Weil Dämonen eigenständig laufen und von außen wie gewöhnliche Prozesse 
aussehen, greifen &lt;code&gt;init&lt;/code&gt; Scripts auf spezielle Dateien zu, die die &lt;code&gt;PID&lt;/code&gt; 
des gerade laufenden &lt;code&gt;daemon&lt;/code&gt; enthalten sollen, sogenannte PID-Files.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Ist kein PID-File da, läuft kein &lt;code&gt;daemon&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Ist ein PID-File da, aber die enthaltene &lt;code&gt;PID&lt;/code&gt; verweist auf keinen 
laufenden Prozess, läuft kein &lt;code&gt;daemon&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Ist ein PID-File da und verweist auf einen laufenden Prozess, 
so ist das die &lt;code&gt;PID&lt;/code&gt; des &lt;code&gt;daemon&lt;/code&gt; und über diese kann man ihm 
Signale schicken.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Das &lt;code&gt;init&lt;/code&gt; Script liest das PID-File um seine &lt;code&gt;start&lt;/code&gt; und &lt;code&gt;stop&lt;/code&gt; Parameter
entsprechend umsetzen zu können, doch erzeugt wird es an unterschiedlichen
Orten.&lt;br /&gt;
&lt;code&gt;start-stop-daemon&lt;/code&gt; kann es anlegen, oder das &lt;code&gt;init&lt;/code&gt; Script legt es selbst an,
oder der &lt;code&gt;daemon&lt;/code&gt; tut es intern, sobald er läuft.&lt;/p&gt;

&lt;p&gt;Auch hier fehlt ein eindeutiger Standard.&lt;/p&gt;

&lt;h3 id=&quot;was-funktioniert-wo&quot;&gt;Was funktioniert wo?&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;systemd&lt;/code&gt; wollte &lt;code&gt;init&lt;/code&gt; Scripts abschaffen, und (ähnlich wie Windows) eine
Daemon-Registry aufbauen, wo &lt;code&gt;systemd&lt;/code&gt; per Konfiguration alle Start- und PID-
Formen korrekt umsetzen kann.&lt;/p&gt;

&lt;p&gt;Doch einerseits nutzen viele Dienste weiter nur klassische &lt;code&gt;init&lt;/code&gt; Scripts, 
womit ganz üble Hacks notwendig werden um &lt;code&gt;init&lt;/code&gt; Scripts mit &lt;code&gt;systemd&lt;/code&gt; zu
synchronisieren.&lt;br /&gt;
Und andererseits steht &lt;code&gt;systemd&lt;/code&gt; in einigen Umgebungen wie z.B. 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Docker_(Software)&quot;&gt;Docker&lt;/a&gt; gar nicht zur 
Verfügung. Da bleiben nur &lt;code&gt;init&lt;/code&gt; Scripts ohne &lt;code&gt;systemd&lt;/code&gt; Anbindung als einzige 
Alternative übrig.&lt;/p&gt;

&lt;p&gt;Und BSD fügt je nach Geschmacksrichtung auch noch seine eigenen Features
und Verzeichniskonvention hinzu.&lt;/p&gt;

&lt;p&gt;Kurz: Es ist ein absolutes Versionschaos, was wo funktionieren kann und 
bedarf somit immer einer individuellen Anpassung.&lt;/p&gt;

&lt;h3 id=&quot;gate-implementierung&quot;&gt;GATE Implementierung&lt;/h3&gt;

&lt;p&gt;Vor 10 Jahren habe ich den Ansatz gewählt, dass “meine” Dämonen fremdgesteuert
sind, und das &lt;code&gt;init&lt;/code&gt; Script zahlreiche Varianten durchprobiert um einen Dienst
auf mehr als einer Plattform hochziehen zu können.&lt;br /&gt;
Das hat zwar grundsätzlich funktioniert, doch das Script war unglaublich 
komplex und war damit auch fehleranfällig und nur sehr schwer zu debuggen.&lt;/p&gt;

&lt;p&gt;In meiner aktuellen Implementierung, gehe ich einen anderen Weg:&lt;br /&gt;
Jeder GATE-&lt;code&gt;daemon&lt;/code&gt; verwaltet sich vollständig selbst, das heißt, 
er &lt;code&gt;fork()&lt;/code&gt;t selbst, legt sein PID-File selbstständig an und gibt
&lt;code&gt;init&lt;/code&gt; Script konforme Exit-Codes zurück.&lt;/p&gt;

&lt;p&gt;Damit braucht das &lt;code&gt;init&lt;/code&gt; Script nur auf das Binary und die PID-Datei 
konfiguriert zu sein, um bei &lt;code&gt;start&lt;/code&gt; den Daemon Prozess auszuführen
und bei &lt;code&gt;stop&lt;/code&gt; ein &lt;code&gt;SIGTERM&lt;/code&gt; an die &lt;code&gt;PID&lt;/code&gt; aus der PID-Datei zu senden.&lt;/p&gt;

&lt;p&gt;Der Code zur Erkennung der Systemumgebung wandert dann ins Binary, wo
schon der Compiler per &lt;code&gt;#ifdef&lt;/code&gt; Unterschiede zwischen Linux und BSD
auflösen kann.&lt;/p&gt;

&lt;p&gt;Am Ende soll sich jeder Daemon sein &lt;code&gt;init&lt;/code&gt; Script selbst generieren 
können, damit man (so wie auch unter Windows) einfach per
&lt;code&gt;mydaemon --register&lt;/code&gt; oder &lt;code&gt;mydaemon --unregister&lt;/code&gt; den eigenen Dienst
korrekt im System integrieren kann.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;Zu viel Freiheit ist eine Einschränkung.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Oft sind &lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_Application_Programming_Interface&quot;&gt;WinAPI&lt;/a&gt;
Codes komplexer als POSIX Implementierung, doch beim Thema
Systemdienst dreht sich das um, wenn man plattformunabhängig bleiben möchte.&lt;/p&gt;

&lt;p&gt;Denn während ein paar Codezeilen von &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_NT_4.0&quot;&gt;NT4&lt;/a&gt;
bis &lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_Server_2022&quot;&gt;Server 2022&lt;/a&gt; stabil 
einen Dienst verwalten können, erfordern Patches für alle unterschiedlichen
Linux- und BSD-Varianten unzählige Implementierung und jede Menge Zusatzaufwand.&lt;/p&gt;

&lt;p&gt;Linux erschlägt das Problem mit zahlreicher billiger Arbeitszeit von 
Studenten, die jährlich das Script-Rad in jeder Distro neu erfinden …
aber wäre es nicht sinnvoller diese Zeit in relevantere Features zu stecken?&lt;/p&gt;

&lt;p&gt;Als unabhängiger Entwickler wird man so gezwungen seine Software nur auf 
bestimmten Distros anzubieten, weil man eben nicht alles abdecken kann.
Und der Verweis, alles zu Open-Source zu machen schreckt nachhaltig viele
Firmen ab.&lt;/p&gt;

&lt;p&gt;Gäbe es einen ähnlichen Standard wie das Root-Filesystem für Dienste unter 
allen POSIX Varianten, wäre die Welt wieder ein ordentliches Stück schöner.
(Denn &lt;code&gt;/etc&lt;/code&gt; oder &lt;code&gt;/usr&lt;/code&gt; erleichtern das Portieren zwischen Linux und BSD
enorm. Wäre doch schlimm, würden die auch immer anders heißen.)&lt;/p&gt;

&lt;p&gt;However… ich hab trotzdem Spaß an Code- Archäologie.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>HTTP Server</title>
   <link href="https://www.opengate.at/blog/2022/02/http-server/"/>
   <published>2022-02-19T12:00:00+01:00</published>
   <updated>2022-02-19T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2022/02/http-server</id>
   <category term="devel" /><category term="software" /><category term="projects" />
   <summary type="text">Mit der Entwicklung eines eigenen kleinen 
HTTP
Servers bin ich damals vor 9 Jahren in die Embedded-Welt eingestiegen.

Auch im GATE Projekt befindet sich eine adäquate neue rein 
auf C aufbauende 
Implementierung, die mir die Verwaltung von MicroServices erleichtern soll.
</summary>
   <content type="html">&lt;p&gt;Mit der Entwicklung eines eigenen kleinen 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Hypertext_Transfer_Protocol&quot;&gt;HTTP&lt;/a&gt;
Servers bin ich damals vor 9 Jahren in die Embedded-Welt eingestiegen.&lt;/p&gt;

&lt;p&gt;Auch im GATE Projekt befindet sich eine adäquate neue rein 
&lt;a href=&quot;https://de.wikipedia.org/wiki/C_(Programmiersprache)&quot;&gt;auf C&lt;/a&gt; aufbauende 
Implementierung, die mir die Verwaltung von MicroServices erleichtern soll.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;challenge-http&quot;&gt;Challenge: HTTP&lt;/h3&gt;

&lt;p&gt;HTTP hat deshalb einen solchen Reiz, weil man nur einen Webbrowser braucht, um
auf ein System zugreifen zu können.&lt;br /&gt;
Nicht grundlos haben heute auch fast alle Mikrocontroller bereits eine 
HTTP-Server Bibliothek in ihrem Basisumfang.&lt;/p&gt;

&lt;p&gt;Nachdem es bereits zahlreiche Implementierung gibt, stellt sich die Frage&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Warum tue ich mir eine Bit-für-Bit Eigenimplementierung überhaupt an?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Und die Antwort ist wie so oft:&lt;br /&gt;
Keine der mir bekannten Bibliotheken ist aus meiner Sicht “unabhängig” genug,
als dass ich sie mit den Zielen des GATE-Projektes problemlos vereinen könnte.
Und das fängt leider bei deren GPL-Variant an.&lt;/p&gt;

&lt;p&gt;Und während Windows und Linux halbwegs gut abgedeckt sind, machen der HTTPS
Zwang eine Portierung auf &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_CE&quot;&gt;Windows CE&lt;/a&gt;, 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Berkeley_Software_Distribution&quot;&gt;BSD&lt;/a&gt; oder ganz 
aktuell &lt;a href=&quot;https://de.wikipedia.org/wiki/Unified_Extensible_Firmware_Interface&quot;&gt;EFI&lt;/a&gt;
unmöglich. Und Mikrocontroller Lösungen sind wieder auf deren Hardware 
zugeschnitten, womit reguläre Desktops und Server nicht bedient werden können.&lt;/p&gt;

&lt;h3 id=&quot;umsetzung&quot;&gt;Umsetzung&lt;/h3&gt;

&lt;p&gt;Bevor ich überhaupt an Dinge wie &lt;a href=&quot;https://en.wikipedia.org/wiki/HTTP/2&quot;&gt;HTTP/2&lt;/a&gt;
denke, bleibe ich mal bei HTTP/1.0 und HTTP/1.1.&lt;/p&gt;

&lt;p&gt;Da ist die Sache theoretisch noch einfach:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Man öffnet einen Server-&lt;a href=&quot;https://de.wikipedia.org/wiki/Socket_(Software)#Stream_Sockets&quot;&gt;Socket&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Nimmt Verbindungen an und scannt nach &lt;code&gt;\r\n\r\n&lt;/code&gt; um das Ende eines HTTP
Headers festzustellen.&lt;/li&gt;
  &lt;li&gt;Dann parst man die Headerzeilen und entscheidet, ob weiterer Content
gelesen werden muss.&lt;/li&gt;
  &lt;li&gt;Ist der HTTP Request vollständig entgegengenommen, darf ein beliebiger
Callback die Daten verarbeiten.&lt;/li&gt;
  &lt;li&gt;Das Ergebnis wird in einen HTTP-Response Header gepresst und danach
darf ein entsprechender Response Stream an den Client zurückgeschickt werden.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Der Teufel steckt aber wie so oft im Detail:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;Content-Type: Keep-Alive&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;In einer Socket Session können mehrere HTTP Requests aneinander gereiht 
sein. Man braucht also eine gute State-Engine, die bei &lt;code&gt;Keep-Alive&lt;/code&gt; nach 
der Abwicklung des ersten Requests einen weiteren durchführt, ohne dass 
Daten versehentlich zwischen beiden geteilt werden.&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/HTTP-Pipelining&quot;&gt;HTTP Pipelining&lt;/a&gt; macht 
zusätzlich erforderlich, dass gelesene Daten nicht sofort bearbeitet 
werden, sondern bis zur Bearbeitung des nachfolgenden Requests 
zwischengespeichert bleiben.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code&gt;Content-Encoding&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;An allen Stellen darf Kompression eingesetzt und der Client darf darüber 
entscheiden, ob der Server ihm auch so antworten dürfen soll.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code&gt;Transfer-Encoding&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;code&gt;chunked&lt;/code&gt;: So können sowohl Requests als auch Responses in Stückchen zerteilt werden.
Das ist super für’s “Streaming”, aber mühsam zu implementieren.&lt;/li&gt;
      &lt;li&gt;&lt;code&gt;deflate&lt;/code&gt;, &lt;code&gt;gzip&lt;/code&gt;: Tritt in Konkurrenz zu &lt;code&gt;Content-Encoding&lt;/code&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code&gt;Accept-Ranges&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;Abgebrochene Downloads fortsetzen zu können, ist ein Feature aus
den 90ern, dass man auch nicht einfach weglassen sollte.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code&gt;HTTP CONNECT&lt;/code&gt; und &lt;code&gt;Upgrade: websocket&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;Beide sollte man entweder “korrekt” abwehren oder
“standardkonform” umsetzen.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;… und vieles mehr.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Man kommt also sehr schnell in jede Menge von Fallkombinationen, deren
Validität schwieriger festzustellen ist und die auch komplex bei der 
Umsetzung sind.&lt;/p&gt;

&lt;p&gt;However … wenn ich bedenke, wie mühsam es bei anderen Projekten war,
genau diese unterschiedlichen Fälle mit Fremdbibliotheken richtig abzudecken,
dann keimt um so mehr Motivation auf, es trotzdem selbst zu implementieren.&lt;/p&gt;

&lt;p&gt;Denn gerade diverse Encoding-Kombinationen lassen sich auch von großen
“professionellen” Bibliotheken nicht immer korrekt abbilden und da wird
es dann nochmal schwieriger, in den Fremdcode einzugreifen, oder aber 
man muss auf einige Features verzichten.&lt;/p&gt;

&lt;p&gt;HTTP ist jedenfalls ein Muss, und darf daher nicht fehlen.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>IP Konfiguration</title>
   <link href="https://www.opengate.at/blog/2022/02/ip-config/"/>
   <published>2022-02-13T12:00:00+01:00</published>
   <updated>2022-02-13T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2022/02/ip-config</id>
   <category term="software" />
   <summary type="text">Während alle Betriebssysteme vergleichbare APIs für das 
Dateisystem haben, ist die 
zweitwichtigste (manchmal auch wichtigste) Konfiguration vollkommen
individuell in die Software eingeflossen: Die 
TCP/IP 
Konfiguration.

Dass Windows und 
Linux unterschiedliche Meinungen haben,
war zu erwarten. Doch dass alle Unix Derivate unterschiedliche Wege gehen, 
überrascht mich immer wieder.
</summary>
   <content type="html">&lt;p&gt;Während alle Betriebssysteme vergleichbare APIs für das 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Dateisystem&quot;&gt;Dateisystem&lt;/a&gt; haben, ist die 
zweitwichtigste (manchmal auch wichtigste) Konfiguration vollkommen
individuell in die Software eingeflossen: Die 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Transmission_Control_Protocol/Internet_Protocol&quot;&gt;TCP/IP&lt;/a&gt; 
Konfiguration.&lt;/p&gt;

&lt;p&gt;Dass &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows&quot;&gt;Windows&lt;/a&gt; und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt; unterschiedliche Meinungen haben,
war zu erwarten. Doch dass alle Unix Derivate unterschiedliche Wege gehen, 
überrascht mich immer wieder.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;windows&quot;&gt;Windows&lt;/h3&gt;

&lt;p&gt;Während in Windows fast alles durch APIs erreichbar ist, fehlten auch hier 
einige Funktionen um IP Adressen im System zu setzen oder um Dienste wie
&lt;a href=&quot;https://de.wikipedia.org/wiki/Dynamic_Host_Configuration_Protocol&quot;&gt;DHCP&lt;/a&gt; und
&lt;a href=&quot;https://de.wikipedia.org/wiki/Domain_Name_System&quot;&gt;DNS&lt;/a&gt; ein und auszuschalten.&lt;/p&gt;

&lt;p&gt;Lustigerweise hat sich hier ein &lt;a href=&quot;https://de.wikipedia.org/wiki/Unix&quot;&gt;Unix&lt;/a&gt;
Ansatz eingeschlichen, indem die Netshell (&lt;code&gt;netsh&lt;/code&gt;) als Kommandozeilen
Werkzeug das Konfigurieren von IP Einstellungen “standardisiert” hat.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;netsh interface ipv4 set address &quot;Local Area Connection&quot; static 192.168.0.8 255.255.255.0 192.168.0.1&lt;/code&gt;&lt;br /&gt;
und &lt;code&gt;netsh interface ipv4 set dnsserver &quot;Local Area Connection&quot; static 192.168.0.1&lt;/code&gt;&lt;br /&gt;
können sowohl von Scripts als auch von Programmen benutzt werden um das 
Netzwerk zu verwalten.&lt;/p&gt;

&lt;p&gt;Seit Windows 2000 ist mit WMI auch eine COM-API vorhanden.
Die &lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/wmisdk/wmi-tasks--networking&quot;&gt;VB-Script Beispiele der MSDN&lt;/a&gt;
lassen sich mit einigen Anpassungen in native Programme integrieren, oder per
&lt;a href=&quot;https://docs.microsoft.com/en-us/mem/configmgr/develop/core/clients/programming/how-to-read-a-wmi-object-by-using-system.management&quot;&gt;System.Management&lt;/a&gt; 
auch von &lt;a href=&quot;https://de.wikipedia.org/wiki/.NET&quot;&gt;dotNET&lt;/a&gt; Programmen anwenden.&lt;/p&gt;

&lt;h3 id=&quot;unix-derivate&quot;&gt;Unix-Derivate&lt;/h3&gt;

&lt;p&gt;BSD und Linux Varianten nutzen häufig Konfigurationsdateien, um IP Adressen
beim Start statisch zu setzen, oder eben DHCP einzuschalten.
Doch leider ist diese Information bei jeder Distributionsfamilie wo anders
abgelegt.&lt;/p&gt;

&lt;p&gt;Und dann kommen auch noch unterschiedliche Zusatzdienste wie &lt;code&gt;networkmanager&lt;/code&gt;
hinzu, die - wenn aktiviert - diese Konfigurationsdateien entweder
überschreiben oder unwirksam machen.&lt;/p&gt;

&lt;h4 id=&quot;dns&quot;&gt;DNS&lt;/h4&gt;

&lt;p&gt;Relativ einig sind sich alle, wo ein statisch konfigurierter DNS-Server 
festgelegt wird, nämlich in &lt;code&gt;/etc/resolv.conf&lt;/code&gt;.
Dort drinnen stehen wenige Zeilen nach dem Schema:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;nameserver 192.168.0.254
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;nameserver 8.8.8.8
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h4 id=&quot;linux-klassisch&quot;&gt;Linux-klassisch&lt;/h4&gt;

&lt;p&gt;Viele “einfache” Linux Varianten nutzen die Datei
&lt;code&gt;/etc/network/interfaces&lt;/code&gt;, die nach folgendem Muster aufgebaut ist:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;auto lo
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;iface lo inet loopback
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;auto eth0
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;iface eth0 inet static
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;    address 192.168.0.13
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;    netmask 255.255.255.0
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;    gateway 192.168.0.254
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;um statische IPs zu vergeben. 
Die Namen der diversen Netzwerkadapter (hier &lt;code&gt;eth0&lt;/code&gt;) erhält man entweder 
per klassischem &lt;code&gt;ifconfig&lt;/code&gt; Aufruf, oder per &lt;code&gt;ip addr&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Will man den DHCP Client die IP Adressen setzen lassen, hilft:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;iface eth0 inet dhcp
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Weitere Beispiele unter 
&lt;a href=&quot;https://linuxhint.com/debian_etc_network_interfaces/&quot;&gt;linuxhint.com/debian_etc_network_interfaces&lt;/a&gt;&lt;/p&gt;

&lt;h4 id=&quot;linux-network-manager&quot;&gt;Linux Network Manager&lt;/h4&gt;

&lt;p&gt;Wer eine Network Manager Installation von der Konsole aus verwalten will,
findet unter 
&lt;a href=&quot;https://devconnected.com/network-manager-on-linux-with-examples/&quot;&gt;devconnected.com/network-manager-on-linux-with-examples/&lt;/a&gt;
eine detaillierte Beschreibung.&lt;/p&gt;

&lt;p&gt;Grundsätzlich kann man aber mit Tools wie &lt;code&gt;nmcli&lt;/code&gt; viele Einstellungen setzen
und anwenden lassen.&lt;/p&gt;

&lt;p&gt;z.B.:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;nmcli con mod eth0 ipv4.address 192.168.0.13/24
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;nmcli con mod eth0 ipv4.gateway 192.168.0.254
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;nmcli con mod eth0 ipv4.dns 8.8.8.8
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;nmcli con mod eth0 ipv4.method manual
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;nmcli con up eth0
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h4 id=&quot;freebsd&quot;&gt;FreeBSD&lt;/h4&gt;

&lt;p&gt;Die Datei &lt;code&gt;/etc/rc.conf&lt;/code&gt; enthält für jeden Netzwerkadapter eine 
&lt;code&gt;ifconfig_[NICNAME]&lt;/code&gt; Zeile neben einigen anderen Dienstkonfigurationen.
Man kann also mit&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;ifconfig_ethX=&amp;quot;DHCP&amp;quot;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;ifconfig_ethY=&amp;quot;inet 192.168.0.13 netmask 255.255.255.0&amp;quot;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;defaultrooter=&amp;quot;192.168.0.254&amp;quot;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;vieles abdecken.
Am Ende ruft man dann noch die Kommandos&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;/etc/rc.d/netif restart
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;/etc/rc.d/routing restart
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;auf um die Konfiguration sofort anwenden zu lassen.&lt;/p&gt;

&lt;p&gt;Weitere Infos unter:
&lt;a href=&quot;https://docs.freebsd.org/en/books/handbook/config/#config-network-setup&quot;&gt;docs.freebsd.org/en/books/handbook/config/#config-network-setup&lt;/a&gt;&lt;/p&gt;

&lt;h4 id=&quot;openbsd&quot;&gt;OpenBSD&lt;/h4&gt;

&lt;p&gt;OpenBSD speichert seine Daten in separate Dateien als 
&lt;code&gt;/etc/hostname.[nicname]&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Da drinnen findet man Zeilen wie:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;inet 192.168.0.1 255.255.255.0
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;inet6 autoconf
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;für statische IPs oder&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;inet autoconf
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;für DHCP.
Der Router wird in eine eigene Gateway Datei namens &lt;code&gt;/etc/mygate&lt;/code&gt; geschrieben
und beinhaltet dann nur die Zeile:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;192.168.0.254
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Weitere Infos findet man unter &lt;a href=&quot;https://www.openbsd.org/faq/faq6.html&quot;&gt;www.openbsd.org/faq/faq6.html&lt;/a&gt;&lt;/p&gt;

&lt;h4 id=&quot;netbsd&quot;&gt;NetBSD&lt;/h4&gt;

&lt;p&gt;NetBSD speichert die IP-Addresse in &lt;code&gt;/etc/ifconfig.[nicname]&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Ein Beispieldatei wie &lt;code&gt;/etc/ifconfig.hvn0&lt;/code&gt; sieht etwa so aus:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;up
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;192.168.0.1 netmask 0xffffff00
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Zusätzlich sollte die neue statische IP in &lt;code&gt;/etc/hosts&lt;/code&gt; eingetragen sein.&lt;/p&gt;

&lt;p&gt;Für die IPv4 Route, wird die Gateway IP entweder in &lt;code&gt;/etc/mygate&lt;/code&gt; hinterlegt, 
oder aber man fügt in &lt;code&gt;/etc/rc.conf&lt;/code&gt; den Eintrag&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;defaultroute=&amp;quot;192.168.0.254&amp;quot;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;an.&lt;/p&gt;

&lt;p&gt;Und zur Aktivierung von DHCP, muss man in &lt;code&gt;/etc/rc.conf&lt;/code&gt; die Zeile&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;dhcpcd=YES
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;anfügen.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.netbsd.org/docs/guide/en/chap-net-practice.html&quot;&gt;www.netbsd.org/docs/guide/en/chap-net-practice.html&lt;/a&gt;
listet auch noch weitere Details auf.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Was mich wirklich etwas anpisst, ist die Tatsache, dass alle Varianten extrem
ähnlich zu einander sind, also keine gravierenden Feature-Unterschiede 
erkennbar sind. (OK, ich lasse hier mal &lt;a href=&quot;https://de.wikipedia.org/wiki/Wireless_Local_Area_Network&quot;&gt;WLAN&lt;/a&gt; bewusst weg).&lt;/p&gt;

&lt;p&gt;Es wirkt so, als hätte man künstlich versucht Unterschiede zu schaffen.&lt;/p&gt;

&lt;p&gt;Für mich als Programmierer, der gerne Verwaltungsdienste schreibt, die ein
System fernwartbar machen sollen, ist das natürlich eine Katastrophe.
Denn hier kann man nur tausende Zeilen von IF-Orgien zusammenwerfen&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt; (net_config == variant_1)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;...
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;else&lt;/span&gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt; (net_config == variant_2)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;...
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;um seinen Code halbwegs auf alle Plattformen zu bringen.&lt;/p&gt;

&lt;p&gt;Andere Scripting Frameworks wie Perl, Python usw. haben das tatsächlich
auch gemacht. Und um so mehr ärgert es mich, dass dieses “Wissen” nicht
auch nativen Programmen zur Verfügung gestellt wird.&lt;/p&gt;

&lt;p&gt;Von daher: Daumen runter für diese Config-Chaos-Community.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Straßenkarten und Satellitenbilder</title>
   <link href="https://www.opengate.at/blog/2022/02/geomaps/"/>
   <published>2022-02-12T12:00:00+01:00</published>
   <updated>2022-02-12T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2022/02/geomaps</id>
   <category term="devel" />
   <summary type="text">Als ich damals meinen PKW Führerschein machte, war die 
Landkarte aus Papier 
immer noch ein übliches Inventar in jedem Fahrzeug.
Doch spätestens 2010 hatte jeder entweder ein separates Navigationsgerät
oder ein Smartphone mit einer entsprechenden App, um sich auf den Straßen
orientieren zu können.

Viel interessanter ist aber, wie man solche Karten-Apps selbst schreiben
kann.
</summary>
   <content type="html">&lt;p&gt;Als ich damals meinen PKW Führerschein machte, war die 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Karte_(Kartografie)&quot;&gt;Landkarte&lt;/a&gt; aus Papier 
immer noch ein übliches Inventar in jedem Fahrzeug.&lt;br /&gt;
Doch spätestens 2010 hatte jeder entweder ein separates Navigationsgerät
oder ein Smartphone mit einer entsprechenden App, um sich auf den Straßen
orientieren zu können.&lt;/p&gt;

&lt;p&gt;Viel interessanter ist aber, wie man solche Karten-Apps selbst schreiben
kann.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Während einige kostenpflichtigen Dienste ihr Kartenmaterial verstecken,
haben einige große Dienste ihre Weltbilder per HTTP Web Request (auch
&lt;a href=&quot;https://de.wikipedia.org/wiki/Representational_State_Transfer&quot;&gt;REST Service&lt;/a&gt; 
genannt) der Öffentlichkeit zur Verfügung gestellt.&lt;/p&gt;

&lt;p&gt;Schon vor einigen Jahren habe ich mit&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Google_Maps&quot;&gt;Google Maps&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Bing_Maps&quot;&gt;Bing Maps&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/OpenStreetMap&quot;&gt;OpenStreetMap&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;ein paar Experimente gemacht.&lt;/p&gt;

&lt;p&gt;Grundsätzlich ist die Sache recht einfach:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Registrierung und Einrichtung eines 
&lt;a href=&quot;https://en.wikipedia.org/wiki/Application_programming_interface_key&quot;&gt;API-Keys&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;Absetzen eines Webrequests mit &lt;a href=&quot;https://de.wikipedia.org/wiki/Geographische_Koordinaten&quot;&gt;Längen- und Breitengrad&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Empfang eines Bildes und/oder zusätzlicher Metadaten&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Der API-Key identifiziert den zugreifenden Dienst (also die App) und dient
auch zur Kontrolle der Anfragen.
Ist das Angebot kostenlos, hat der API-Key eine bestimmte Anzahl an freien
Zugriffen, z.B.: 1000 pro Tag, 100000 pro Jahr.
Zusätzliche Zugriffe kann man allerdings per Zahlung nachkaufen.&lt;br /&gt;
So wird verhindert, dass man mit einem Key die gesamte Weltkarte herunterladen
kann.&lt;/p&gt;

&lt;h3 id=&quot;kein-google-maps&quot;&gt;(Kein) Google Maps&lt;/h3&gt;

&lt;p&gt;Die besten Satellitenbilder hatte immer schon Google. Sie sind teils so
hochauflösend, dass man Bodenmarkierungen auf Straßen erkennen kann.&lt;/p&gt;

&lt;p&gt;Vor 6 Jahren schaltete ich daher mal einen API-Key frei um eine lokale Karte
in eine globale von Google einzubetten.&lt;/p&gt;

&lt;p&gt;Heute hat Google allerdings die Dienste gesperrt, wenn man keine 
Bezahlungsverknüpfung in seinem Konto eingerichtet hat … und eher sterbe ich,
als dass ich Google Bank- Kreditkarten- oder Paypal-Daten zukommen lasse.
Von daher ist Google von meiner Liste der zu implementierenden Kartenprovidern
gestrichen.&lt;/p&gt;

&lt;p&gt;Damals konnte man aber mit dem API-Key einfach die URL&lt;br /&gt;
&lt;code&gt;http://maps.googleapis.com/maps/api/staticmap?center=LAT,LONG&amp;amp;zoom=19&amp;amp;scale=1&amp;amp;size=WIDTHxHEIGHT&amp;amp;maptype=roadmap&amp;amp;key=KEYE&amp;amp;format=png&amp;amp;visual_refresh=true&lt;/code&gt;
mit entsprechenden Breitengrad- (&lt;code&gt;LAT&lt;/code&gt;) und Längengrad- (&lt;code&gt;LONG&lt;/code&gt;) Angaben 
zusammen mit dem API-Key (&lt;code&gt;KEY&lt;/code&gt;) und Pixelbreite und -höhe (&lt;code&gt;WIDTH&lt;/code&gt;, &lt;code&gt;HEIGHT&lt;/code&gt;) 
aufrufen und erhielt eine Grafik als Download.&lt;/p&gt;

&lt;p&gt;Ein bisschen komplex war die Sache mit der Auflösung. Google nutze einen &lt;code&gt;zoom&lt;/code&gt;
Faktor um die nähere oder entferntere Blickwinkel zum Zentrum (&lt;code&gt;LAT,LONG&lt;/code&gt;) 
darzustellen.&lt;/p&gt;

&lt;p&gt;Das Geheimnis war: Google hat alle Karten als 256 x 256 Pixel Teilgrafiken
vorberechnet und auf dem niedrigsten Zoom-Faktor &lt;code&gt;0&lt;/code&gt; findet man auf 256 
Pixeln die gesamte Weltkarte wieder. 
Jeder weitere Zoomfaktor verdoppelt die Auflösung und das geht runter bis
&lt;code&gt;22&lt;/code&gt;.
Wenn man jetzt weiß, dass der Erdumfang am Äquator 40075160 Meter lang ist,
erhält man &lt;code&gt;40075016 / 256 == 156543.594&lt;/code&gt; Meter pro Pixel am Äquator und mit
jedem weiteren Zoomfaktor halbiert sich diese Einheit.&lt;br /&gt;
Und da die Weltkarte eine &lt;a href=&quot;https://de.wikipedia.org/wiki/Mercator-Projektion&quot;&gt;Mercator-Projektion&lt;/a&gt; 
ist, ergeben sich die metrischen Maße um ein Zielpunkt aus der Formel:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;metersPerPixel = cos(latitude) * 40075016 / (256 * 2 ^ zoom)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Beim höchstmöglichen Faktor &lt;code&gt;22&lt;/code&gt; kommt man schon auf eine theoretische 
Auflösung von 4 cm pro Pixel. Die Kartenbilder sind zwar je nach Umgebung 
unterschiedlich scharf, aber im städtischen Gebiet ist das echt krass genau.&lt;/p&gt;

&lt;h3 id=&quot;bing-maps&quot;&gt;Bing Maps&lt;/h3&gt;

&lt;p&gt;Microsoft’s Bing Maps (früher als “Virtual Earth” bekannt) ist nun aber 
zwangsläufig der Gewinner, da ich nach wie vor ohne Bankdaten mit einem 
kostenlosen Account Daten davon beziehen kann.&lt;/p&gt;

&lt;p&gt;Unter &lt;a href=&quot;https://www.bingmapsportal.com/&quot;&gt;www.bingmapsportal.com&lt;/a&gt; kann man sich
im &lt;code&gt;Bing Maps Dev Center&lt;/code&gt; Account freischalten und unter &lt;code&gt;My Account&lt;/code&gt; - &lt;code&gt;My Keys&lt;/code&gt;
API Keys anlegen. 
Der Key kombiniert folgende Datenfelder:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Application name&lt;/li&gt;
  &lt;li&gt;Applikation URL&lt;/li&gt;
  &lt;li&gt;Key type (z.B.: Basic)&lt;/li&gt;
  &lt;li&gt;Application Type (z.B.: Mobile, Website, Dev, Win-App)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Und schon kann man folgende Requests absetzen, indem man den generierten 
API-Key in jedem HTTP-Request als &lt;code&gt;key&lt;/code&gt; Argument mitschickt.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;http://dev.virtualearth.net/REST/V1/Imagery/Map/aerial?mapArea=48.2,16.4,48.25,16.45&amp;amp;mapSize=800,600&amp;amp;key=AKPIKEY&amp;amp;mapMetadata=1&lt;/code&gt;&lt;br /&gt;
liefert JSON formatierte Daten zur gewählten Lage&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;http://dev.virtualearth.net/REST/V1/Imagery/Map/aerial?mapArea=48.2,16.4,48.25,16.45&amp;amp;mapSize=800,600&amp;amp;key=APIKEY&amp;amp;format=png&lt;/code&gt;&lt;br /&gt;
gibt ein PNG Bild als Download zurück.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Bing arbeitet mit Ausschnitten, daher gibt man 4 Parameter als 
&lt;code&gt;FROM-LATITUDE&lt;/code&gt;, &lt;code&gt;FROM-LONGITUDE&lt;/code&gt;, &lt;code&gt;TO-LATITUDE&lt;/code&gt;, &lt;code&gt;TO-LONGITUDE&lt;/code&gt; an.
Der JSON-Response gibt “angepasste” Koordinaten zurück, die zur &lt;code&gt;mapSize&lt;/code&gt;
(also Breite, Höhe) passen und mit eben diesen Daten, kann der PNG Request
abgesetzt werden, womit man präzise weiß, was im Bildausschnitt genau gezeigt
wird.&lt;/p&gt;

&lt;p&gt;Die JSON-Rückgabe sieht in etwas so aus und kann leicht geparset werden:&lt;/p&gt;

&lt;div class=&quot;language-json highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;authenticationResultCode&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;:&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;ValidCredentials&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;brandLogoUri&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;:&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;http:&lt;/span&gt;&lt;span style=&quot;color:#b0b&quot;&gt;\/&lt;/span&gt;&lt;span style=&quot;color:#b0b&quot;&gt;\/&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;dev.virtualearth.net&lt;/span&gt;&lt;span style=&quot;color:#b0b&quot;&gt;\/&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Branding&lt;/span&gt;&lt;span style=&quot;color:#b0b&quot;&gt;\/&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;logo_powered_by.png&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;copyright&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;:&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Copyright © 2022 Microsoft and its suppliers.&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;resourceSets&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;:
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;  [
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;    {
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;estimatedTotal&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;:&lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;resources&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;:
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;      [
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;        {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;          &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;__type&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;:&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;StaticMapMetadata:http:&lt;/span&gt;&lt;span style=&quot;color:#b0b&quot;&gt;\/&lt;/span&gt;&lt;span style=&quot;color:#b0b&quot;&gt;\/&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;schemas.microsoft.com&lt;/span&gt;&lt;span style=&quot;color:#b0b&quot;&gt;\/&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;search&lt;/span&gt;&lt;span style=&quot;color:#b0b&quot;&gt;\/&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;local&lt;/span&gt;&lt;span style=&quot;color:#b0b&quot;&gt;\/&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;ws&lt;/span&gt;&lt;span style=&quot;color:#b0b&quot;&gt;\/&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;rest&lt;/span&gt;&lt;span style=&quot;color:#b0b&quot;&gt;\/&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;v1&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;          &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;bbox&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;:
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;          [
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;            &lt;span style=&quot;color:#60E&quot;&gt;48.1908100765507&lt;/span&gt;,&lt;span style=&quot;color:#60E&quot;&gt;16.3564109802246&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;            &lt;span style=&quot;color:#60E&quot;&gt;48.2593128380802&lt;/span&gt;,&lt;span style=&quot;color:#60E&quot;&gt;16.4935684204101&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;          ],
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;          &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;imageHeight&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;:&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;600&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;          &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;imageWidth&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;:&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;800&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;          &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;mapCenter&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;:
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n21&quot; name=&quot;n21&quot;&gt;21&lt;/a&gt;&lt;/span&gt;          {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n22&quot; name=&quot;n22&quot;&gt;22&lt;/a&gt;&lt;/span&gt;            &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;coordinates&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;:[&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;48.2250061054994&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;16.425&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;]
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n23&quot; name=&quot;n23&quot;&gt;23&lt;/a&gt;&lt;/span&gt;          },
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n24&quot; name=&quot;n24&quot;&gt;24&lt;/a&gt;&lt;/span&gt;          &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;pushpins&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;:[],
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n25&quot; name=&quot;n25&quot;&gt;25&lt;/a&gt;&lt;/span&gt;          &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;zoom&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;:&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;13&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n26&quot; name=&quot;n26&quot;&gt;26&lt;/a&gt;&lt;/span&gt;        }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n27&quot; name=&quot;n27&quot;&gt;27&lt;/a&gt;&lt;/span&gt;      ]
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n28&quot; name=&quot;n28&quot;&gt;28&lt;/a&gt;&lt;/span&gt;    }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n29&quot; name=&quot;n29&quot;&gt;29&lt;/a&gt;&lt;/span&gt;  ],
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n30&quot; name=&quot;n30&quot;&gt;30&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;statusCode&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;:&lt;span style=&quot;color:#00D&quot;&gt;200&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n31&quot; name=&quot;n31&quot;&gt;31&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;statusDescription&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;:&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;OK&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n32&quot; name=&quot;n32&quot;&gt;32&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;traceId&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;:&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;...&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n33&quot; name=&quot;n33&quot;&gt;33&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Mit Bing-Maps (oder Google), kann man relativ einfach Landkarten-Grafiken 
per HTTP anfordern und in der eigenen Anwendung nutzen.&lt;br /&gt;
Statt hinterlegten Satellitenbildern, kann man die REST APIs auch auffordern
nur Straßenkarten (mit und ohne Häuseradressen) zurückzuliefern.&lt;br /&gt;
Und es gibt noch einige weitere Features, wie Routenplanung oder Distanzberechnung,
die man ebenso per HTTP-Request anfordern kann.&lt;/p&gt;

&lt;p&gt;Und mit ein bisschen Mathe zur Mercator-Projektion, kann man jedem Pixel unter
dem Mauszeiger auch seine Geo-Koordinaten zuordnen.&lt;/p&gt;

&lt;p&gt;OpenStreetMap steht auf meiner TODO-Liste, doch da dessen API nicht so 
einfach aussieht und man Koordinaten von Straßen und anderen Objekten 
zurückbekommt, die man erst selbst auf ein Bild aufmalen muss, wird das wohl
noch etwas dauern.&lt;/p&gt;

&lt;p&gt;Die freie Nutzung von Geo-Positionierung und Karten ist aber auf jeden Fall
ein wichtiges modernes Feature.&lt;/p&gt;

&lt;p&gt;Die Anbieter integrieren es gerne mit jeder Menge &lt;a href=&quot;https://de.wikipedia.org/wiki/JavaScript&quot;&gt;Javascript&lt;/a&gt;
Codes in Webseiten und Phone-Apps, aber verschweigen regelrecht, dass man auch
ohne Scripts und Werbe-Einblendungen an die Rohdaten gelangen kann.&lt;/p&gt;

&lt;p&gt;Man braucht also kein &lt;a href=&quot;https://de.wikipedia.org/wiki/Android_%28Betriebssystem%29&quot;&gt;Android&lt;/a&gt;-
oder Browser-Framework, um Karten in native Anwendungen einbetten zu können 
… doch leider werden diese Dienste auf diese Weise viel zu selten genutzt.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Webhosting 1.0</title>
   <link href="https://www.opengate.at/blog/2022/02/webhosting-1-0/"/>
   <published>2022-02-06T12:00:00+01:00</published>
   <updated>2022-02-06T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2022/02/webhosting-1-0</id>
   <category term="software" /><category term="retro" />
   <summary type="text">Als ich etwa im Jahr 2001 “das Internet” entdecken durfte, wollte ich 
auch meine eigene Webseite haben.
Aber bezahlen … nein … für so etwas reichte das Taschengeld nicht.

Also begann die Suche nach gratis Webhostern.
</summary>
   <content type="html">&lt;p&gt;Als ich etwa im Jahr 2001 “das Internet” entdecken durfte, wollte ich 
auch &lt;em&gt;meine eigene&lt;/em&gt; Webseite haben.
Aber bezahlen … nein … für so etwas reichte das Taschengeld nicht.&lt;/p&gt;

&lt;p&gt;Also begann die Suche nach gratis &lt;a href=&quot;https://de.wikipedia.org/wiki/Webhosting&quot;&gt;Webhostern&lt;/a&gt;.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;provider-webspace&quot;&gt;Provider Webspace&lt;/h3&gt;

&lt;p&gt;Viele Internetzugänge waren Anfang der 2000er “automatisch” mit Webspace 
ausgestattet, und zwar mit sagenhaften Dimensionen von 5 - 10 MB 
Speicherplatz insgesamt.
&lt;code&gt;http://www.your-hoster.tld/members/username&lt;/code&gt; war damals üblich für 
private &lt;a href=&quot;https://de.wikipedia.org/wiki/Uniform_Resource_Locator&quot;&gt;URLs&lt;/a&gt;, und
deshalb hatten viele Jung-Web-Enthusiasten eine kostenlose Umleitung einer 
&lt;a href=&quot;https://de.wikipedia.org/wiki/.tk&quot;&gt;.tk&lt;/a&gt; oder &lt;a href=&quot;https://de.wikipedia.org/wiki/.vu&quot;&gt;.vu&lt;/a&gt;
Subdomains zum eigenen Space eingerichtet.&lt;/p&gt;

&lt;p&gt;Hochgeladen wurden die rein statischen Inhalte über &lt;a href=&quot;https://de.wikipedia.org/wiki/File_Transfer_Protocol&quot;&gt;FTP&lt;/a&gt;, 
und manchmal gab es sogar eine “dynamische” Webseite zum Uploaden einzelner 
Dateien per Browser-Upload.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/PHP&quot;&gt;PHP&lt;/a&gt; oder irgend ein anderer Script 
Support war bei diesen Diensten nicht zu finden, doch dafür hatten viele 
ein unerträgliches &lt;a href=&quot;https://de.wikipedia.org/wiki/Adobe_Flash&quot;&gt;Flash&lt;/a&gt;-Element 
eingebunden, mit dem man “dynamische Inhalte” client-seitig simulieren konnte.&lt;/p&gt;

&lt;h3 id=&quot;werbung-10&quot;&gt;Werbung 1.0&lt;/h3&gt;

&lt;p&gt;Mit dem Suchbegriff &lt;code&gt;Free Webhoster&lt;/code&gt; fanden das damals noch sehr junge 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Google&quot;&gt;Google&lt;/a&gt; oder Klassiker wie 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Altaba&quot;&gt;Yahoo!&lt;/a&gt;, &lt;a href=&quot;https://de.wikipedia.org/wiki/Lycos_Europe&quot;&gt;Lycos&lt;/a&gt;
und &lt;a href=&quot;https://de.wikipedia.org/wiki/AltaVista&quot;&gt;AltaVisa&lt;/a&gt; oder das deutsche 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Fireball_(Suchmaschine)&quot;&gt;fireball.de&lt;/a&gt; einige 
Anbieter, die kostenlos HTML Files bereitstellen ließen, wenn dafür Werbung 
auf diesen Seiten eingeblendet wurde.&lt;/p&gt;

&lt;p&gt;Der Trick war denkbar einfach:&lt;br /&gt;
Jeder &lt;code&gt;.htm&lt;/code&gt;  oder &lt;code&gt;.html&lt;/code&gt; Datei fügte der Webserver ein paar Zeilen hinten
an, wodurch per &lt;a href=&quot;https://de.wikipedia.org/wiki/JavaScript&quot;&gt;Javascript&lt;/a&gt; ein 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Inlineframe&quot;&gt;Inlineframe&lt;/a&gt; oder etwas Ähnliches 
eingefügt wurde, wo dann Texte oder Grafiken aufblinken sollten.
Parallel dazu wurden Popups geöffnet um darüber zu informieren, dass man als
1000ster Besucher ein Auto gewonnen hätte.&lt;/p&gt;

&lt;p&gt;Doch die Webtüftler von damals hatten schnell heraus gefunden, dass sie ihr
eigenes HTML Dokument einfach nur entsprechend “enden” lassen mussten, um die
lästigen Einblendungen “weg-scripten” zu können.&lt;/p&gt;

&lt;p&gt;Codes wie&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#070;font-weight:bold&quot;&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;  ... 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  my content ends
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#070;font-weight:bold&quot;&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#070;font-weight:bold&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span style=&quot;color:#b48&quot;&gt;style&lt;/span&gt;=&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#606&quot;&gt;display&lt;/span&gt;:&lt;span style=&quot;color:#088&quot;&gt;none&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#070;font-weight:bold&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;oder&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#070;font-weight:bold&quot;&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;  ... 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  my content ends
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#070;font-weight:bold&quot;&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#777&quot;&gt;&amp;lt;!--&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#777&quot;&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;bewirkten, dass nachfolgende Elemente entweder unsichtbar wurden 
(z.B. Werbebilder am Ende der Seite), oder dass nachfolgender &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt;
Code nicht mehr ausgeführt wurde.&lt;/p&gt;

&lt;h3 id=&quot;geocities&quot;&gt;GeoCities&lt;/h3&gt;

&lt;p&gt;Angefangen hatte ich mit &lt;a href=&quot;https://de.wikipedia.org/wiki/GeoCities&quot;&gt;GeoCities&lt;/a&gt;,
wo man genau einen solchen Werbe-Script-Webspace kostenlos zugesprochen bekam.&lt;/p&gt;

&lt;p&gt;Nicht, dass ich damals wirklich relevante Inhalte hätte vorzeigen können.
Man wollte einfach eine Webseite herzeigen können, ohne wirklich etwas darauf
zu haben, was herzeigbar hätte sein können.&lt;/p&gt;

&lt;p&gt;Tatsächlich habe ich dort dann auch 2 oder 3 Texte zum 
&lt;a href=&quot;https://en.wikipedia.org/wiki/INT_13H&quot;&gt;INT 13h&lt;/a&gt; geschrieben um mit meinen 
rudimentären &lt;a href=&quot;https://de.wikipedia.org/wiki/MS-DOS&quot;&gt;DOS&lt;/a&gt; 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Assemblersprache&quot;&gt;Assembler&lt;/a&gt; Kenntnissen zu 
prahlen. Zum Glück hat sich diese Peinlichkeit dann beim Untergang von 
GeoCities selbst gelöscht.&lt;/p&gt;

&lt;p&gt;Die Werbeeinblendung fand ich aber damals schon sehr unseriös und so suchte
ich schnell nach einer Alternative:&lt;/p&gt;

&lt;h3 id=&quot;piranhode&quot;&gt;Piranho.de&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;http://www.piranho.de&quot;&gt;Piranho.de&lt;/a&gt; war ein deutscher Webhoster, der von zwei
damals jungen Enthusiasten aufgebaut wurde und stark auf eine 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Internetforum&quot;&gt;Forum&lt;/a&gt; Community hinarbeitete.&lt;br /&gt;
Man erhielt (was auch sehr selten war) kostenlos eine Subdomain 
&lt;code&gt;username.piranho.de&lt;/code&gt; wie auch &lt;code&gt;username.piranho.com&lt;/code&gt; und hatte formal 
unbegrenzt Speicherplatz. Doch die einzelnen Dateien durften nicht größer 
als 100 KB sein, was üppige Fotos einschränkte, aber in der damaligen 
Zeit “akzeptabel” war.&lt;/p&gt;

&lt;p&gt;Eine Grundidee war, dass jeder User seine Dateien kostenlos über ein
Web-Upload-Formular hochladen und administrieren konnte, doch wer mehr wollte,
musste sich im dortigen Webforum betätigen und fleißig Beiträge schreiben.&lt;br /&gt;
Denn - ich glaube - monatlich wurden unter den besten Teilnehmern dann 
FTP-Accounts verlost, womit diese größere Dateiuploads durchführen
konnten.&lt;/p&gt;

&lt;p&gt;Tatsächlich endete dann meine Motivation eine eigene Webseite zu haben recht
bald, doch das Piranho Forum hat mich dann noch recht lange bei der Stange
gehalten, weil es dort auch ein &lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B&quot;&gt;C++&lt;/a&gt;, 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Embarcadero_Delphi&quot;&gt;Delphi&lt;/a&gt; und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_Basic_Classic&quot;&gt;Visual-Basic&lt;/a&gt; Board gab, 
wo stets Fragen zu diesen Sprachen kamen, und ich selbst auch gelegentlich 
mal etwas gepostet hatte.&lt;/p&gt;

&lt;p&gt;Das ging dann ein paar Jahre so weiter, bis ich dann “aus beruflichen” Gründen
immer weniger Zeit fand, am Abend noch Beiträge zu lesen.&lt;br /&gt;
Doch alle paar Monate war dann doch wieder Lust und Laune am Wochenende da,
kurz ins Forum zu blicken.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Facebook&quot;&gt;Facebook&lt;/a&gt; und Co haben dann ab 2007 
erfolgreich alle Foren und deren Communities zerstört und damit war Piranho 
faktisch auch tot. Heute findet man nur noch ein trauriges Logo auf der Domain
und niemand vermutet, dass zwischen 2001 und 2005 auf dieser Seite keine 10 
Minuten vergingen, in denen nicht ein neuer Beitrag eröffnet wurde.&lt;br /&gt;
Es ist eigentlich ein Drama, dass all diese Interaktion und auch viele dort
verfassten Workshops offenbar verloren gegangen sind.&lt;br /&gt;
Nur das &lt;a href=&quot;https://de.wikipedia.org/wiki/Internet_Archive&quot;&gt;Internet Archive&lt;/a&gt; zeigt 
ein paar Bilder aus dieser Zeit:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://web.archive.org/web/20010521160005/http://www.piranho.de/&quot;&gt;Snapshot 2001&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://web.archive.org/web/20030530152102/http://www.piranho.com/&quot;&gt;Snapshot 2003&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://web.archive.org/web/20040610045315/http://piranho.de/&quot;&gt;Snapshot 2004&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://web.archive.org/web/20050203031841/http://www.piranho.de/&quot;&gt;Snapshot 2005&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://web.archive.org/web/20070915112534/http://piranho.com/index.php?xid=8a1fb3c437940d93591f50c21707d782&quot;&gt;Snapshot 2007&lt;/a&gt;&lt;/p&gt;

&lt;h3 id=&quot;die-lange-ruhe&quot;&gt;Die lange Ruhe&lt;/h3&gt;

&lt;p&gt;Ein Freund hatte damals (um 2004) die Idee bei einem Webhoster eine 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Domain_(Internet)&quot;&gt;Domain&lt;/a&gt; zu kaufen und diese
als Reseller weiterzuverkaufen.&lt;br /&gt;
Mit dem Gedanken (und vor allem wegen des dummen Namens der Domain) musste er 
damit natürlich scheitern.&lt;br /&gt;
Denn wer kauft schon eine kleinere Wohnung im Internet “in Untermiete”, wenn 
er an jeder Ecke eine halbe Villa fast kostenlos im Eigentum bekommt.&lt;/p&gt;

&lt;p&gt;Doch mit mir hatte er für viele Jahre einen treuen Kunden, der den dortigen 
Webspace bis 2010 glaube ich unbenutzt hat liegen lassen.&lt;/p&gt;

&lt;p&gt;Zwischendurch konnte ich aber immer wieder mal bei Bekannten und Verwandten 
die eine oder andere Webaufgabe übernehmen und dort ein paar 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Hypertext_Markup_Language&quot;&gt;HTML&lt;/a&gt;, Javascript
oder PHP Zeilen “im Netz” verbauen.&lt;/p&gt;

&lt;p&gt;Erst Ende 2018 war die Motivation wieder groß genug, selbst ein Webprojekt 
starten zu wollen, was bekanntlich auch zu diesem Blog geworden ist.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Web 1.0 war eine gute Sache und eines muss ich ganz klar sagen:&lt;br /&gt;
Mit meinen statisch generierten HTML Seiten bin ich bis heute (zum Glück)
gänzlich von Hacker Attacken verschont geblieben, während Projekte von
Bekannten alle paar Jahre mit ihren 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Content-Management-System&quot;&gt;Content-Management Systemen&lt;/a&gt; 
zusammenbrechen.&lt;/p&gt;

&lt;p&gt;Zwar war ich nie ein Community-Mensch, aber trotzdem trauere ich dieser
Zeit, in der alle Webentwickler sich gegenseitig überbieten wollten und dann
in einem Forum darüber prahlten, manchmal nach.&lt;/p&gt;

&lt;p&gt;Und eines habe ich dadurch auch lernen müssen:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Das Internet ist EXTREM vergesslich.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Denn fast keine der alten Web 1.0 Seiten von damals ist heute noch zugänglich.
Nur &lt;a href=&quot;http://web.archive.org&quot;&gt;web.archive.org&lt;/a&gt; hat ein paar Eindrücke von 
damals konserviert.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>MSVC 6/7 type traits</title>
   <link href="https://www.opengate.at/blog/2022/02/old-type-traits/"/>
   <published>2022-02-05T12:00:00+01:00</published>
   <updated>2022-02-05T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2022/02/old-type-traits</id>
   <category term="devel" />
   <summary type="text">Mit dem Visual Studio 2005 
wurde der MSVC halbwegs ordentlich nutzbar. Zwar nicht alle, aber zumindest
viele C++ Template-Konstruktionen
wurden mit dieser Version endlich standard-konform umgesetzt und so 
konnten boost
und andere Bibliotheken langsam in Richtung C++11 marschieren.

Doch … was war vorher?
Tatsächlich dokumentieren ältere boost Ausgaben einige faszinierende 
Workarounds um Template-Features wie Type-Traits auch mit älteren 
nicht-standard-konformen Compilern umzusetzen.

</summary>
   <content type="html">&lt;p&gt;Mit dem &lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_Studio&quot;&gt;Visual Studio&lt;/a&gt; 2005 
wurde der MSVC halbwegs ordentlich nutzbar. Zwar nicht alle, aber zumindest
viele &lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B&quot;&gt;C++&lt;/a&gt; Template-Konstruktionen
wurden mit dieser Version endlich standard-konform umgesetzt und so 
konnten &lt;a href=&quot;https://de.wikipedia.org/wiki/Boost_(C%2B%2B-Bibliothek)&quot;&gt;boost&lt;/a&gt;
und andere Bibliotheken langsam in Richtung C++11 marschieren.&lt;/p&gt;

&lt;p&gt;Doch … was war vorher?&lt;br /&gt;
Tatsächlich dokumentieren ältere &lt;code&gt;boost&lt;/code&gt; Ausgaben einige faszinierende 
Workarounds um Template-Features wie Type-Traits auch mit älteren 
nicht-standard-konformen Compilern umzusetzen.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;keine-partial-template-specialization&quot;&gt;Keine Partial template specialization&lt;/h3&gt;

&lt;p&gt;Template hatten in MSVC 6 und 7 zahlreiche Macken. Eine einfaches generisches
Template funktionierte, doch sobald man Spezialisierungen einsetze, wurde es
kompliziert.&lt;/p&gt;

&lt;p&gt;Gar nicht implementiert waren Teilspezialisierungen, um Typen-Attribute filtern
zu können.&lt;br /&gt;
Ein sehr bekanntes Beispiel wäre die Pointer-Erkennung:&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;template&lt;/span&gt;&amp;lt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;T&lt;/span&gt;&amp;gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;is_pointer&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;static&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;bool&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt; value = &lt;span style=&quot;color:#069&quot;&gt;false&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;};
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;template&lt;/span&gt;&amp;lt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;T&lt;/span&gt;&amp;gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;is_pointer&lt;/span&gt;&amp;lt;T*&amp;gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;static&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;bool&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt; value = &lt;span style=&quot;color:#069&quot;&gt;true&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;}
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; main()
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;  assert(&lt;span style=&quot;color:#069&quot;&gt;false&lt;/span&gt; == is_pointer&amp;lt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt;&amp;gt;::value);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;  assert(&lt;span style=&quot;color:#069&quot;&gt;true&lt;/span&gt; == is_pointer&amp;lt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt;*&amp;gt;::value);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Ein alter &lt;code&gt;MSVC&lt;/code&gt; würde hier mit einem Syntaxfehler abbrechen, weil es den 
Token &lt;code&gt;is_pointer&amp;lt;T*&amp;gt;&lt;/code&gt; nicht übersetzen könnte.&lt;/p&gt;

&lt;h3 id=&quot;lösung-per-funktionsüberladung&quot;&gt;Lösung per Funktionsüberladung&lt;/h3&gt;

&lt;p&gt;Im &lt;code&gt;MSVC&lt;/code&gt; können wir aber einen ganz anderen Ansatz nutzen.
Wir definieren eine Funktion, die den “gewünschten” Typen oder einen
angepassten Wrapper mit dem Typen entgegennimmt und die als Rückgabetyp
einen spezifischen Typ nutzt.&lt;br /&gt;
Und dann überladen wir die Funktion mit einer zweiten Implementierung,
die alles entgegennehmen kann (also eine variadic function) und die einen
anderen Rückgabetyp definiert.&lt;/p&gt;

&lt;p&gt;Ich übernehme hier gerne die &lt;code&gt;boost&lt;/code&gt; Konvention mit einem &lt;code&gt;yes_type&lt;/code&gt; und 
einen &lt;code&gt;no_type&lt;/code&gt;, denn die eigentliche Entscheidung, wie ein Typ klassifiziert
wird, erfolgt eben über diesen Rückgabetyp.&lt;br /&gt;
Wenn wir nämlich einen solchen überladenen Funktionsaufruf “andeuten”, 
ermittelt der Compiler, welche der Funktionen am besten passt, womit der
Rückgabetyp der Funktion entweder mit &lt;code&gt;yes&lt;/code&gt; oder mit &lt;code&gt;no&lt;/code&gt; typisiert wird.&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;typedef&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt; yes_type_t;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;typedef&lt;/span&gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;struct&lt;/span&gt; { &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt; n[&lt;span style=&quot;color:#00D&quot;&gt;2&lt;/span&gt;]; } no_type_t;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Und aus dieser Info lässt sich dann wieder eine Type-Trait Konstante bilden,
wenn man die Rückgabetypen mit &lt;code&gt;sizeof&lt;/code&gt; vergleicht.&lt;/p&gt;

&lt;p&gt;Das seltsame dabei ist, dass der “angedeutete” Funktionsaufruf nie stattfindet
und die Funktionen selbst gar nicht implementiert werden müssen.&lt;/p&gt;

&lt;h4 id=&quot;beispiel-is_pointer&quot;&gt;Beispiel is_pointer&lt;/h4&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;yes_type_t pointer_detector(&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt;* ptr);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;no_type_t  pointer_detector(...);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;template&lt;/span&gt;&amp;lt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;T&lt;/span&gt;&amp;gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;struct&lt;/span&gt; is_pointer_helper
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;static&lt;/span&gt; T&amp;amp; type_creator();
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;enum&lt;/span&gt; {
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;    value = (&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;sizeof&lt;/span&gt;(yes_type_t) == 
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;sizeof&lt;/span&gt;(pointer_detector(type_creator()))      
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  };
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;}
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;template&lt;/span&gt;&amp;lt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;T&lt;/span&gt;&amp;gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;struct&lt;/span&gt; is_pointer
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;enum&lt;/span&gt; {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;    value = is_pointer_helper&amp;lt;T&amp;gt;::value
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;  }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;};
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Jeder Pointer lässt sich implizit in &lt;code&gt;void const*&lt;/code&gt; casten, womit jeder 
Pointer die erste &lt;code&gt;yes&lt;/code&gt; Funktion nutzen würde. Alle anderen Typen landen bei 
der &lt;code&gt;no&lt;/code&gt; Funktion.&lt;/p&gt;

&lt;p&gt;(Für eine vollständige Implementierung müssten wir jetzt auch noch 
Fälle wie &lt;code&gt;void volatile*&lt;/code&gt; usw. abdecken, aber das Prinzip sollte klar sein).&lt;/p&gt;

&lt;h4 id=&quot;beispiel-is_reference&quot;&gt;Beispiel is_reference&lt;/h4&gt;

&lt;p&gt;Referenzen sind im MSVC leider wieder ein Spezialfall, weil der Compiler 
(nicht gedeckt durch den Standard) das Nutzen von Funktionsrückgabewerten
als nicht-konstante Parameter erlaubt.
&lt;code&gt;int foo(int&amp;amp; param)&lt;/code&gt; kann also auch mit einem &lt;code&gt;int bar()&lt;/code&gt; Aufruf gefüttert
werden, obwohl der Rückgabewerte keine Referenz ist. Andere Compiler würden
das als Fehler ablehnen.&lt;br /&gt;
Folglich können wir die &lt;code&gt;is_pointer&lt;/code&gt; Methode nicht einfach auf Referenzen 
anpassen.&lt;/p&gt;

&lt;p&gt;Die Kollegen des &lt;code&gt;boost&lt;/code&gt; Teams haben sich dafür etwas Besonderes einfallen
lassen:&lt;br /&gt;
Sie definieren eine Funktion, die zu einem Typ &lt;code&gt;T&lt;/code&gt; eine Funktion als Parameter
erwartet, die selbst wieder ein &lt;code&gt;T&amp;amp;&lt;/code&gt; zurückgibt.&lt;br /&gt;
Aus jeder Nicht-Referenz kann eine Referenz gemacht werden, aber es kann keine
Referenz zu einer Referenz geben.&lt;/p&gt;

&lt;p&gt;Und damit das mit Function-Overloading funktioniert, müssen wir statt unseres
Typen &lt;code&gt;T&lt;/code&gt; einen Hilfstypen &lt;code&gt;typed_dummy&lt;/code&gt; einführen, der als Parameter fungieren 
kann:&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;template&lt;/span&gt;&amp;lt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;T&lt;/span&gt;&amp;gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;struct&lt;/span&gt; typed_dummy { };
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;template&lt;/span&gt; &amp;lt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;T&lt;/span&gt;&amp;gt; 
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;T&amp;amp; (* ref_func_returner(typed_dummy&amp;lt;T&amp;gt;) ) (typed_dummy&amp;lt;T&amp;gt;);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt; ref_func_returner(...);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;template&lt;/span&gt; &amp;lt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;T&lt;/span&gt;&amp;gt; 
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;no_type_t ref_detector(T&amp;amp;(*)(typed_dummy&amp;lt;T&amp;gt;));
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;yes_type_t ref_detector(...);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;template&lt;/span&gt;&amp;lt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;T&lt;/span&gt;&amp;gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;struct&lt;/span&gt; is_reference_helper
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;enum&lt;/span&gt; { 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;    value = (&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;sizeof&lt;/span&gt;(yes_type_t) == 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;sizeof&lt;/span&gt;(ref_detector(ref_func_returner(typed_dummy&amp;lt;T&amp;gt;()))))
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;  };
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;};
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;template&lt;/span&gt;&amp;lt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;T&lt;/span&gt;&amp;gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;struct&lt;/span&gt; is_reference
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n21&quot; name=&quot;n21&quot;&gt;21&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;enum&lt;/span&gt; {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n22&quot; name=&quot;n22&quot;&gt;22&lt;/a&gt;&lt;/span&gt;    value = is_reference_helper&amp;lt;T&amp;gt;::value
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n23&quot; name=&quot;n23&quot;&gt;23&lt;/a&gt;&lt;/span&gt;  }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n24&quot; name=&quot;n24&quot;&gt;24&lt;/a&gt;&lt;/span&gt;};
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Der &lt;code&gt;ref_detector&lt;/code&gt; bekommt also den Rückgabewert der 
&lt;code&gt;ref_func_returner&lt;/code&gt; Funktion als Parameter.&lt;br /&gt;
Ist &lt;code&gt;T&lt;/code&gt; eine Referenz wird das generische &lt;code&gt;char ref_func_returner(...)&lt;/code&gt; 
aufgerufen und &lt;code&gt;ref_detector(...)&lt;/code&gt; antwortet mit &lt;code&gt;yes&lt;/code&gt;.&lt;br /&gt;
Wenn &lt;code&gt;T&lt;/code&gt; keine Referenz ist, lässt sich ein &lt;code&gt;T&amp;amp;&lt;/code&gt; daraus machen, was die 
Templatefunktion ins Spiel bringt, woraus am Ende ein &lt;code&gt;no&lt;/code&gt; wird.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Was solche Workaround anbelangt ist &lt;code&gt;boost&lt;/code&gt; vor allem in den älteren
Version (z.B. &lt;code&gt;1.3x&lt;/code&gt;) eine wahre Fundgrube.&lt;br /&gt;
Und es gibt noch jede Menge weitere Varianten und Compiler-Hacks, die das
Bereitstellen von Features ermöglichen sollen, die eigentlich mit diesen
alten Compilern nicht möglich waren.&lt;/p&gt;

&lt;p&gt;Leider wird vieles in &lt;code&gt;boost&lt;/code&gt; durch eine unendliche Anzahl von Makros
umgesetzt, die (zumindest für mich) schwer lesbar sind.&lt;br /&gt;
Um so mehr freut man sich dafür dann aber, wenn man einen Workaround mal
verstanden hat.&lt;/p&gt;

&lt;p&gt;Nachdem immer mehr Forenbeiträge und Blogs aus den Zeiten vor 2010 
verschwinden, möchte ich zumindest ein paar dieser Ideen im GATE Projekt
verewigen. Ich nutze type-traits zwar ziemlich selten … aber mit
diesen Hacks bleibt die Lauffähigkeit auch auf MSVC 6 weiter gegeben.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Bitbucket App-Passwords</title>
   <link href="https://www.opengate.at/blog/2022/01/app-passwords/"/>
   <published>2022-01-30T12:00:00+01:00</published>
   <updated>2022-01-30T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2022/01/app-passwords</id>
   <category term="software" />
   <summary type="text">Am 1. November wurde es angekündigt und am 1. März 2022 ist es so weit:


  Bitbucket sperrt User Passwörter
für den Zugang zu seinen GIT Repos.


Die Alternative sind SSH 
Schlüssel oder “App-Passwörter”.

</summary>
   <content type="html">&lt;p&gt;Am 1. November wurde es angekündigt und am 1. März 2022 ist es so weit:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Bitbucket&quot;&gt;Bitbucket&lt;/a&gt; sperrt User Passwörter
für den Zugang zu seinen &lt;a href=&quot;https://de.wikipedia.org/wiki/Git&quot;&gt;GIT&lt;/a&gt; Repos.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Die Alternative sind &lt;a href=&quot;https://de.wikipedia.org/wiki/Secure_Shell&quot;&gt;SSH&lt;/a&gt; 
Schlüssel oder “App-Passwörter”.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;vorgeschichte&quot;&gt;Vorgeschichte&lt;/h3&gt;

&lt;p&gt;Früher funktionierte Authentifizierung immer nach dem User + Passwort Prinzip.
Jedes Protokoll (
&lt;a href=&quot;https://de.wikipedia.org/wiki/Hypertext_Transfer_Protocol&quot;&gt;HTTP&lt;/a&gt;, 
&lt;a href=&quot;https://de.wikipedia.org/wiki/File_Transfer_Protocol&quot;&gt;FTP&lt;/a&gt;, SSH, 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Simple_Mail_Transfer_Protocol&quot;&gt;SMTP&lt;/a&gt;, 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Post_Office_Protocol&quot;&gt;POP3&lt;/a&gt;, 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Internet_Message_Access_Protocol&quot;&gt;IMAP&lt;/a&gt;, …) 
implementierte sein eigenes Format, in welchem der Benutzer und sein Passwort 
übertragen werden konnte.&lt;br /&gt;
… und leider haben sie es alle absolut falsch gemacht.&lt;br /&gt;
Denn das Passwort wurde immer im Klartext übertragen, und obgleich später
durch Protokollerweiterungen auch Hashes und andere Späße eingearbeitet 
wurden, so waren und sind Klartextpasswörter in den meisten Diensten 
möglich, außer wenn sie explizit abgeschaltet sind.&lt;/p&gt;

&lt;p&gt;Es fehlte an einem Standard, wie Passwörter sicher übertragen werden konnten.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Transport_Layer_Security&quot;&gt;SSL und TSL&lt;/a&gt; 
sicherten dann zwar die Datenverbindung zwischen zwei Systemen,
doch da im Hintergrund immer noch Klartextpasswörter eingesetzt wurden, 
ergaben sich immer noch andere Stellen, wo das Passwort abgefangen und 
gestohlen werden konnte.&lt;/p&gt;

&lt;p&gt;Zertifikate wäre ja eine schöne Sache gewesen um dieses Problem zu lösen, 
doch wie trägt man ein solches immer mit sich herum?&lt;/p&gt;

&lt;h3 id=&quot;api-token&quot;&gt;API Token&lt;/h3&gt;

&lt;p&gt;Anstatt also immer Namen + Passwort zu nutzen, dachte man sich für diverse
Automationsprozesse API-Token aus. Der immer noch per &lt;code&gt;Name + Passwort&lt;/code&gt; 
authentifizierte Benutzer kann in einer gesicherten Umgebung zufällige 
Token generieren lassen, die als Ersatz für Name/Passwort gelten und da
man diese Token auch nur mit Teilrechten ausstatten konnte, ergab sich somit
eine neue Welt für Web-Anwendungen.&lt;/p&gt;

&lt;p&gt;Viele Web-Zugriffe laufen heute über solche Token und nun stellt auch 
Bitbucket auf dieses Verfahren um.&lt;/p&gt;

&lt;p&gt;In Zukunft muss ich also mein “App-Password” == App-API-Token parat haben,
wenn ich Sourcecodes hoch- oder herunterladen möchte.&lt;br /&gt;
Sollte es mir verloren gehen, kann ich es sperren und ein neues anlegen.&lt;/p&gt;

&lt;p&gt;Doch bei meinem ersten Login per &lt;a href=&quot;https://de.wikipedia.org/wiki/TortoiseGit&quot;&gt;TortoiseGIT&lt;/a&gt;
lief es mir kalt über den Rücken…&lt;/p&gt;

&lt;h3 id=&quot;das-browser-problem&quot;&gt;Das Browser-Problem&lt;/h3&gt;

&lt;p&gt;Während früher &lt;code&gt;User+Passwort&lt;/code&gt; fixe Felder in Protokollen waren, gehen
heute mehr und mehr Dienste dazu über, die Dateneingabe über Webseiten
laufen zu lassen, wo am Ende ein finaler Zugriffstoken auf die Daten
nach der Anmeldung herausfällt.&lt;/p&gt;

&lt;p&gt;Hierfür öffnen die Apps tatsächlich HTML Webformulare, um stets dem
“neuesten” Sicherheitsstand (oder dem neuesten UI Logo) nachlaufen zu können.&lt;/p&gt;

&lt;p&gt;Genau diese schleichende Browser-isierung von Netzdiensten empfinde ich 
persönlich als “Bedrohung des Endanwenders”, obwohl es eigentlich der 
Sicherheit dienen sollte.&lt;br /&gt;
Denn an der Stelle findet erneut ein Browser-Krieg statt, der mir das
Arbeiten mit nicht-top-aktuellen Systemen übelst erschwert.&lt;/p&gt;

&lt;p&gt;Das fängt leider damit an, dass immer mehr &lt;a href=&quot;https://de.wikipedia.org/wiki/JavaScript&quot;&gt;Javascript&lt;/a&gt;
Code aktiv ausgeführt werden muss, damit ein Login auf einer solchen Webseiten
überhaupt funktionieren kann.&lt;br /&gt;
Folglich kann ich auf einer nicht-grafischen Konsole keinen Login mehr 
durchführen, weil mir dort ein Browser fehlt, der die Loginmaske adäquat
anzeigen könnte.&lt;/p&gt;

&lt;h3 id=&quot;bitbucket-web-login-nur-beim-ersten-mal&quot;&gt;Bitbucket Web-Login nur beim ersten Mal&lt;/h3&gt;

&lt;p&gt;TortoiseGIT hat das Feature bereits integriert und so öffnet sich beim
ersten Login eine Webseite, die das “App-Passwort” erkennt und die nötige
Freigabebestimmung abfragt.&lt;/p&gt;

&lt;p&gt;Zum Glück gilt das Passwort dann an der Stelle als “safe” und kann auch
wieder regulär über native Protokolle benutzt werden.&lt;br /&gt;
Somit kann ich auch auf meinem &lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt; 
VMs und &lt;a href=&quot;https://de.wikipedia.org/wiki/Raspberry_Pi&quot;&gt;Raspberry-PIs&lt;/a&gt;
weiter mit GIT über HTTPS und dem neuen “App-Passwort” arbeiten.&lt;/p&gt;

&lt;p&gt;Das App-Passwort ist mit seinen 20 Zeichen kurz genug, um es als Text
“mitführen” zu können, womit mir die Einrichtung von SSL-Zertifikaten 
auf allen Maschinen vorerst erspart bleibt.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ja, es war bisher immer “unsicher”, wenn ich bei jedem &lt;code&gt;git pull&lt;/code&gt; mein 
Passwort habe übertragen lassen und die neuen App-Passwords machen diesen
Teil um einiges sicherer.&lt;/p&gt;

&lt;p&gt;Dennoch frage ich mich, wie der initiale Login per Webinterface in Zukunft
aussehen wird, bzw. wie viele System damit ausgeschlossen werden.&lt;/p&gt;

&lt;p&gt;Auf meinem &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_Phone&quot;&gt;Windows Phone&lt;/a&gt;
von 2017/2018 laufen inzwischen viele Logins deshalb überhaupt nicht mehr, 
weil sich das Web zu sehr weiterentwickelt hat, während klassische Logins mit
&lt;code&gt;User + Passwort&lt;/code&gt; bei Mailaccounts dort auch weiter kein Problem sein werden.&lt;/p&gt;

&lt;p&gt;Es bleibt daher nur zu hoffen, dass künftige Umstellungen von Loginprozeduren
nicht so gestaltet sind, dass nur noch auf 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Android_%28Betriebssystem%29&quot;&gt;Android&lt;/a&gt; oder
&lt;a href=&quot;https://de.wikipedia.org/wiki/Apple&quot;&gt;Apple&lt;/a&gt; Smartphones ausführbar sind.&lt;br /&gt;
Denn zu meinem großen Bedauern geht der Trend leider in diese Richtung.&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>PCR und Antigen COVID Tests</title>
   <link href="https://www.opengate.at/blog/2022/01/pcr-test/"/>
   <published>2022-01-29T12:00:00+01:00</published>
   <updated>2022-01-29T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2022/01/pcr-test</id>
   <category term="general" />
   <summary type="text">Das Schicksal (oder meine schlechte Planung) wollte es, dass der Tausch meines
Firmen-PCs durchgeführt wurde, womit ich eine Woche lang keinen Home-Office 
Dienst geleistet habe.
Und wie es bei den aktuellen Infektionszahlen zu erwarten war, traten nun auch
positive COVID-19 Fälle in der Firma auf.

Somit hatte ich also einen Grund mich wieder auf das Virus testen zu lassen.

</summary>
   <content type="html">&lt;p&gt;Das Schicksal (oder meine schlechte Planung) wollte es, dass der Tausch meines
Firmen-PCs durchgeführt wurde, womit ich eine Woche lang keinen Home-Office 
Dienst geleistet habe.&lt;br /&gt;
Und wie es bei den aktuellen Infektionszahlen zu erwarten war, traten nun auch
positive &lt;a href=&quot;https://de.wikipedia.org/wiki/COVID-19&quot;&gt;COVID-19&lt;/a&gt; Fälle in der Firma auf.&lt;/p&gt;

&lt;p&gt;Somit hatte ich also einen Grund mich wieder auf das Virus testen zu lassen.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;pcr-tests-in-wien&quot;&gt;PCR-Tests in Wien&lt;/h3&gt;

&lt;p&gt;In der Theorie sieht die Prozedur recht einfach aus.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Man registriert sich auf &lt;a href=&quot;https://allesgurgelt.at/wien&quot;&gt;allesgurgelt.at/wien&lt;/a&gt; mit
    &lt;ul&gt;
      &lt;li&gt;Vornamen (interessant: kein Nachname an der Stelle)&lt;/li&gt;
      &lt;li&gt;Mailadresse&lt;/li&gt;
      &lt;li&gt;und einem Passwort.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Oder man loggt sich mit einer zuvor registrierten Mail-Adresse + Passwort
ein.&lt;/li&gt;
  &lt;li&gt;Nun lässt man sich auf der Webseite einen “Abhol-Barcode” generieren.&lt;/li&gt;
  &lt;li&gt;Mit diesem Barcode bekommt man in einigen Geschäften und Supermärkten
dann 8 PCR-Test-Kits kostenlos ausgehändigt.
&lt;img src=&quot;/blog/assets/img/covid-pcr-test-1.jpg&quot; alt=&quot;COVID19 PCR Test Kit&quot; /&gt;&lt;/li&gt;
  &lt;li&gt;Wieder zu Hause öffnet man erneut die Webseite, loggt sich ein und 
startet dort im Menü einen &lt;code&gt;Neuen Test&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Dort wird zuerst die Probennummer eingetippt, die in der Anleitung
im Testbox-Heft und auf dem Test-Röhrchen aufgeklebt ist.&lt;/li&gt;
  &lt;li&gt;Nun müssen persönliche Daten wie
    &lt;ul&gt;
      &lt;li&gt;Vorname, Nachname, Geschlecht&lt;/li&gt;
      &lt;li&gt;Geburtsdatum&lt;/li&gt;
      &lt;li&gt;Telefonnummer&lt;/li&gt;
      &lt;li&gt;Adresse
eingegeben werden.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Im Anschluss geht die Webseite die durchzuführenden Schritte durch, also:
&lt;img src=&quot;/blog/assets/img/covid-pcr-test-2.jpg&quot; alt=&quot;COVID19 PCR Test&quot; /&gt;
    &lt;ul&gt;
      &lt;li&gt;Gurgelflüssigkeit in den Mund nehmen und 1 Minute lang gurgeln&lt;/li&gt;
      &lt;li&gt;Flüssigkeit in das Teströhrchen fließen lassen.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Das verschlossene Teströhrchen mit der Flüssigkeit kommt wieder in die Box,
während das Anleitungsheftchen bei einem zu Hause bleibt um die Probennummer
aufzubewahren.&lt;/li&gt;
  &lt;li&gt;Die Box mit der Probe kann man dann in vielen Supermärkten an PCR-Test 
Sammelstellen abgeben.&lt;/li&gt;
  &lt;li&gt;Will man ein gültiges Test-Zertifikat erhalten, ist das Hochladen eines
Ausweises als Foto erforderlich. Man kann diesen Teil aber auch überspringen,
wenn man nur am Ergebnis interessiert ist.&lt;/li&gt;
  &lt;li&gt;Nun heißt es 24 Stunden warten, bis man das Testergebnis per Mail zugestellt
bekommt.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Meines Erachtens ist diese Prozedur an vielen Stellen extremst benutzerFEINDLICH
gestaltet und sicher mit ein Grund dafür, warum ältere Menschen, oder Menschen
ohne regulärem Smartphone (wie ich) von solchen Tests ausgeschlossen sind.&lt;/p&gt;

&lt;p&gt;Probleme:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Barcodes auf der Webseiten werden nicht per Mail zugesendet.
Man muss also mit dem Smartphone die Webseite öffnen, um den Code herzeigen
zu können, oder man muss ihn auf Papier ausdrucken. &lt;br /&gt;
Wer aber nur einen Computer ohne Drucker zu Hause hat, bekommt ein Problem.&lt;/li&gt;
  &lt;li&gt;Die Webseite arbeitet nur auf den neuesten &lt;a href=&quot;https://de.wikipedia.org/wiki/Chromium_(Browser)&quot;&gt;Chromium&lt;/a&gt;
und &lt;a href=&quot;https://de.wikipedia.org/wiki/Mozilla_Firefox&quot;&gt;Firefox&lt;/a&gt; Browsern 
korrekt. Nicht mal auf dem Legacy-Edge funktionieren die Buttons, und
diverse Opera-Varianten haben ebenfalls Probleme.
    &lt;blockquote&gt;
      &lt;p&gt;Wie inkompetent müssen die Entwickler eigentlich sein, dass man ein 
Formular für Name, Mail und Geburtsdatum nicht mehr absenden kann,
wenn der Browser nicht auf Google-Werbung basiert?&lt;br /&gt;
Das lief auf Netscape und IE4 alles schon mal besser … vor 25 Jahren!&lt;/p&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
  &lt;li&gt;Die Barcodes werden auch numerisch abgedruckt, nur leider scheitern die 
Angestellten an den Kassen, diesen manuell einzutippen, schließlich ist der
Zahlencode extrem lang. Diese “Backup”  gegenüber den Barcodes funktioniert 
offenbar nicht.&lt;/li&gt;
  &lt;li&gt;Die “Hilfe” auf der Webseite ist mehr als bescheiden bzw. irreführend.
Es gibt keine detaillierte Ablaufbeschreibung, nur ein kurzes Youtube-
Video, in dem ein Möchtegern-Model sein Smartphone hochhebt, dann gurgelt
das Röhrchen verpackt und das Kit in der Sammelstelle abgibt und dann
Youtuber-esque in die Kamera grinst.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Alles in allem zeigt sich, dass wieder absolute Anfänger diese Portale 
zusammengeklickt haben. Niemand denkt an den allgemeinen Fall, oder wie 
z.B. meine Mutter zu einem Test kommen soll.&lt;br /&gt;
Das ist vermutlich auch mit ein Grund, warum die Skepsis in der Bevölkerung
steigt.&lt;br /&gt;
Es wäre mit wenigen zusätzlichen Aufwänden möglich gewesen, die Prozedur 
so auszubauen, dass man einen wesentlich größeren Rahmen abdecken kann.&lt;/p&gt;

&lt;h3 id=&quot;antigen-test-im-container&quot;&gt;Antigen-Test im Container&lt;/h3&gt;

&lt;p&gt;An vielen Plätzen in Wien wurden Test-Container abgestellt, wo die 
Menschen auch ohne Anmeldung einen Covid-Test machen können.
Ich nutzte das Angebot am Reumannplatz bei der Apotheke.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/covid-test-container.jpg&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/covid-test-container-02.jpg&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Die dortige Prozedur sieht wie folgt aus:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Man reiht sich in die Schlange ein und wartet bis man dran ist.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Man zeigt seine &lt;a href=&quot;https://de.wikipedia.org/wiki/E-card_(Chipkarte)&quot;&gt;e-Card&lt;/a&gt;
vor und wird über diese authentifiziert.
&lt;img src=&quot;/blog/assets/img/covid-test-container-03.jpg&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Zusätzlich kann man seine Telefonnummer angeben, um per &lt;a href=&quot;https://de.wikipedia.org/wiki/Short_Message_Service&quot;&gt;SMS&lt;/a&gt;
informiert zu werden.&lt;/li&gt;
  &lt;li&gt;Ein freundlicher Mitarbeiter fragt nach dem gewünschten Test und führt ihn
dann sofort durch.&lt;br /&gt;
In meinem Fall wollte ich nur einen Antigen-Schnelltest per Abstrich der
Nasenschleimhaut machen.&lt;/li&gt;
  &lt;li&gt;Man verlässt die Box und wartet auf die Verständigung per SMS.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In meinem Fall dauerte das Warten 30 Minuten, da ein paar Personen vor mir
ein positiver Fall entdeckt wurde. Offenbar erfolgt dann eine Desinfektion
des Containers und den Wartenden wird mitgeteilt, dass eine 15 minütige Pause 
notwendig sei.
Doch als ich an der Reihe war, war ich in unter zwei Minuten fertig.&lt;/p&gt;

&lt;p&gt;Einziges Problem ist wieder der Online-Teil, denn die SMS liefert einen
elend langen Link zum Impfergebnis.&lt;br /&gt;
Hier hat man als Nicht-Smartphone-User keine andere Wahl, als einen PC
zu suchen und den Link Buchstaben für Buchstaben abzutippen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Also … ich bin froh, dass ich dreifach geimpft bin und offenbar keine
Covid-Infektion abbekommen habe. Denn wenn ich mich jeden zweiten Tag
um einen Test bemühen müsste, um arbeiten gehen zu dürfen, würde ich 
dezent durchdrehen.&lt;/p&gt;

&lt;p&gt;Dabei kann ich wiederum die fleißigen und hilfsbereiten Menschen an der 
Front für ihren vorbildlichen Einsatz nur loben.&lt;br /&gt;
In Erinnerung geblieben ist mir vor allem der junge Mann, der bei mir den
Nasenabstrich durchgeführt hatte und dabei sagte:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Sie haben aber eine sehr schöne Nase zum Testen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ach … so etwas Nettes hat schon lange keiner mehr zu mir gesagt …
oder … war das vielleicht eine Anspielung auf zu große Nasenlöcher?&lt;/p&gt;

&lt;p&gt;Wie auch immer, es war eine entspannte und angenehme Atmosphere im 
Test-Container. Und gleichzeitig sind mir auch die vielen Probleme 
anderer aufgefallen, vor allem, wenn Menschen nicht deutsch sprechen 
konnten oder die “falsche” E-Card dabei hatten.&lt;/p&gt;

&lt;p&gt;Bei all diesen kleinen Problemchen ist es eine wahre Kunst, trotzdem 
jedem weiteren Testkandidaten aufgeschlossen und freundlich zu begegnen
und dafür kann ich nur meine Anerkennung aussprechen.&lt;/p&gt;

&lt;p&gt;Doch … über die Softwareentwicklung kann ich leider nur enttäuscht
den Kopf schütteln.&lt;br /&gt;
Diese billigen “Copy&amp;amp;Paste” wie auch “Quick-and-Dirty” Lösungen verdrecken 
nicht nur das Freizeitinternet, sondern haben inzwischen auch die 
digitalen Amtswege infiziert.&lt;br /&gt;
Ich muss mit Bedauern zur Kenntnis nehmen, dass wir in Sachen Digitalisierung
nicht fähig sind, ordentliche Prozeduren für allgemeine Fälle aufzusetzen.&lt;/p&gt;

&lt;p&gt;Und trotzdem bin ich irgendwie froh, dass wir zumindest die Möglichkeit
haben uns weiter kostenlos auf das Virus testen zu lassen.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>uEFI: Graphics Output Protocol (GOP)</title>
   <link href="https://www.opengate.at/blog/2022/01/uefi-gop/"/>
   <published>2022-01-23T12:00:00+01:00</published>
   <updated>2022-01-23T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2022/01/uefi-gop</id>
   <category term="devel" />
   <summary type="text">Im klassischen PC BIOS aus den alten 
16-Bit Zeiten hatten wir den Interrupt 10h (INT 0x10) um den Grafikmodus 
zu ändern.

Mit uEFI 
wurde diese antiquierte 16-Bit Technik modernisiert und somit steht
mit dem Graphics Output Protocol (GOP) eine 
C-API der Firmware 
bereit, um Pixelgrafiken auf den Monitor zu bekommen.
</summary>
   <content type="html">&lt;p&gt;Im klassischen PC &lt;a href=&quot;https://de.wikipedia.org/wiki/BIOS&quot;&gt;BIOS&lt;/a&gt; aus den alten 
16-Bit Zeiten hatten wir den Interrupt 10h (INT 0x10) um den Grafikmodus 
zu ändern.&lt;/p&gt;

&lt;p&gt;Mit &lt;a href=&quot;https://de.wikipedia.org/wiki/Unified_Extensible_Firmware_Interface&quot;&gt;uEFI&lt;/a&gt; 
wurde diese antiquierte 16-Bit Technik modernisiert und somit steht
mit dem &lt;a href=&quot;https://wiki.osdev.org/GOP&quot;&gt;Graphics Output Protocol (GOP)&lt;/a&gt; eine 
&lt;a href=&quot;https://de.wikipedia.org/wiki/C_(Programmiersprache)&quot;&gt;C-API&lt;/a&gt; der Firmware 
bereit, um Pixelgrafiken auf den Monitor zu bekommen.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;In den glorreichen Zeiten, in denen “die coolen Jungs” ihr eigenes OS bauen 
wollten, starteten viele mit dem 512 Bytes großen Bootsektor-Code, wechselten
per &lt;code&gt;int 10h&lt;/code&gt; in den Grafikmodus und zeichneten ein paar verwegene&lt;br /&gt;
“You are hacked” Zeichen auf den Schirm.&lt;/p&gt;

&lt;p&gt;Das ganze auf eine Diskette gespielt und ins Laufwerk gelegt, ließ Papa 
am Abend erblassen, wenn er seine Excel-Zeitlisten in 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_95&quot;&gt;Windows 95&lt;/a&gt; 
befüllen wollte.&lt;/p&gt;

&lt;p&gt;Nun sterben langsam auch die letzten Firmware-Varianten aus, die noch ein 
BIOS CSM (Compatibility Support Module) enthalten.&lt;br /&gt;
Die Zukunft heißt (seit 10 bis 15 Jahren): uEFI.&lt;/p&gt;

&lt;h3 id=&quot;das-gop-protokoll&quot;&gt;Das GOP Protokoll&lt;/h3&gt;

&lt;p&gt;Über die GOP GUID (&lt;code&gt;9042a9de-23dc-4a38-96fb7aded080516a&lt;/code&gt;) erlangt man von
&lt;code&gt;BootServices-&amp;gt;LocateProtocol&lt;/code&gt; einen Pointer zum 
&lt;code&gt;EFI_GRAPHICS_OUTPUT_PROTOCOL&lt;/code&gt; Interface.&lt;/p&gt;

&lt;p&gt;Dieses stellt die Methoden &lt;code&gt;QueryMode()&lt;/code&gt;, &lt;code&gt;SetMode()&lt;/code&gt; und &lt;code&gt;Blt()&lt;/code&gt; bereit, 
sowie einen Pointer namens &lt;code&gt;Mode&lt;/code&gt; zu den Daten des aktuellen Modus.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Mode-&amp;gt;MaxMode&lt;/code&gt; gibt die Anzahl der verfügbaren Grafik-Modi zurück und nun 
kann man per Schleife von 0 bis &lt;code&gt;MaxMode&lt;/code&gt; zählen und diesen Parameter als &lt;code&gt;ID&lt;/code&gt; 
an &lt;code&gt;QueryMode()&lt;/code&gt; übergeben um Infos zum dahinter liegenden Grafikmodus zu 
erhalten.&lt;br /&gt;
Das wären:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Pixel-Höhe und -Breite des Grafikmodus&lt;/li&gt;
  &lt;li&gt;Art des Pixelformats
    &lt;ul&gt;
      &lt;li&gt;RGBX: 32 bit Wert mit dem Inhalt rot, grün, blau + unbenutztes Füllbyte&lt;/li&gt;
      &lt;li&gt;BGRX: 32 bit Wert mit dem Inhalt blau, grün, rot + unbenutztes Füllbyte&lt;/li&gt;
      &lt;li&gt;BitMask: In einer zusätzlichen Struktur wird beschrieben, welche Bits in
einem 32-bit Pixel den Farbkanälen rot, grün und blau zugeordnet sind.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Üblicherweise startet die Auflistung beim alten VGA-Standard 640 x 480 und 
wird dann zunehmend größer.&lt;/p&gt;

&lt;p&gt;Mit der Funktion &lt;code&gt;SetMode()&lt;/code&gt; kann dann in den Grafikmodus wechseln, wenn man die
gewünschte Index-&lt;code&gt;ID&lt;/code&gt; einsetzt.&lt;/p&gt;

&lt;p&gt;Am interessantesten ist dann die Funktion &lt;code&gt;Blt()&lt;/code&gt;, die Pixelpufferinhalte in die 
Video-Hardware übertragen kann.
Das funktioniert sogar in beide Richtungen, man kann also Pixel aus dem eigenen
Buffer in die Anzeige transferieren oder die angezeigten Pixel in den eigenen
Puffer kopieren lassen.&lt;/p&gt;

&lt;p&gt;Man kann also ein &lt;code&gt;Breite * Höhe&lt;/code&gt; großes Feld von &lt;code&gt;uint32_t&lt;/code&gt; Werten anlegen
und dann die Pixel je nach Modus setzen und das gesamte Frame per &lt;code&gt;Blt()&lt;/code&gt; 
anzeigen lassen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Das tolle an &lt;code&gt;UEFI&lt;/code&gt; ist, dass die C-API bereits mitgeliefert wird und somit kann 
man mit wenigen Zeilen einen Bootloader mit grafischen Menü zaubern.&lt;br /&gt;
Früher hätte man im BIOS dann per Assembler auf die Hardware-Adressen 
zugreifen müssen und eben genau dafür schrieben sich viele Entwickler ihre eigene
&lt;code&gt;Blt()&lt;/code&gt; Funktion.&lt;br /&gt;
Schön zu sehen, dass das nun obsolet und die neue Methode standardisiert ist.&lt;/p&gt;

&lt;p&gt;Nun existiert im GATE Framework auch eine 
&lt;a href=&quot;/blog/2022/01/framebuffers/&quot;&gt;Framebuffer-Implementierung&lt;/a&gt;,
die direkt unter EFI ausführbar ist und Grafiken auf den Monitor zeichnen kann.&lt;/p&gt;

&lt;p&gt;Und erneut bin ich erstaunt, wie einfach es ist, den PC “ohne Betriebssystem” 
zu betreiben.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Runnables</title>
   <link href="https://www.opengate.at/blog/2022/01/runnables/"/>
   <published>2022-01-22T12:00:00+01:00</published>
   <updated>2022-01-22T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2022/01/runnables</id>
   <category term="devel" />
   <summary type="text">Hinter der Magie von std::bind 
stecken eine Vielzahl von Hilfsklassen und C++ 
Template-Tricks, die jeden beliebigen Funktions- oder Methodenaufruf kapseln 
und frei mit Parametern kombinieren können.

In der C Welt gibt es 
(meines Wissen) nichts Vergleichbares in der stdlib.

Für die Ausführung von beliebigen Funktionsaufrufen stellt das GATE Framework
daher Runnables bereit.
</summary>
   <content type="html">&lt;p&gt;Hinter der Magie von &lt;a href=&quot;https://en.cppreference.com/w/cpp/utility/functional/bind&quot;&gt;&lt;code&gt;std::bind&lt;/code&gt;&lt;/a&gt; 
stecken eine Vielzahl von Hilfsklassen und &lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B&quot;&gt;C++&lt;/a&gt; 
Template-Tricks, die jeden beliebigen Funktions- oder Methodenaufruf kapseln 
und frei mit Parametern kombinieren können.&lt;/p&gt;

&lt;p&gt;In der &lt;a href=&quot;https://de.wikipedia.org/wiki/C_(Programmiersprache)&quot;&gt;C Welt&lt;/a&gt; gibt es 
(meines Wissen) nichts Vergleichbares in der &lt;code&gt;stdlib&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Für die Ausführung von beliebigen Funktionsaufrufen stellt das GATE Framework
daher &lt;code&gt;Runnables&lt;/code&gt; bereit.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;code&gt;std::bind&lt;/code&gt; verbindet eine Funktion oder eine Methode mit Parametern und gibt
einen &lt;a href=&quot;https://www.cprogramming.com/tutorial/functors-function-objects-in-c++.html&quot;&gt;Functor&lt;/a&gt; 
zurück, der bei dessen Aufruf, die “gebundene” Routine mit den “gebundenen”
Parameter aufruft.&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color:#B44;font-weight:bold&quot;&gt;&amp;lt;functional&amp;gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; foo(&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; a, &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; b)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; a + b;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;}
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; bar(&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; a, &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; b, &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; c)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; a + b + c;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;}
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; main()
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;auto&lt;/span&gt; f = std::bind(foo, &lt;span style=&quot;color:#00D&quot;&gt;33&lt;/span&gt;, &lt;span style=&quot;color:#00D&quot;&gt;44&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; result1 = f(); &lt;span style=&quot;color:#777&quot;&gt;// invokes: foo(33, 44);&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;auto&lt;/span&gt; g = std::bind(bar, &lt;span style=&quot;color:#00D&quot;&gt;33&lt;/span&gt;, &lt;span style=&quot;color:#00D&quot;&gt;44&lt;/span&gt;, std::placeholders::_1);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; result2 = g(&lt;span style=&quot;color:#00D&quot;&gt;55&lt;/span&gt;); &lt;span style=&quot;color:#777&quot;&gt;// invokes: bar(33, 44, 55)&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Man kann also einen Funktionsaufruf + Parameter konservieren und in einem 
anderen Kontext (also später oder in einem anderen &lt;a href=&quot;https://de.wikipedia.org/wiki/Thread_%28Informatik%29&quot;&gt;Thread&lt;/a&gt;) 
ausführen lassen.&lt;/p&gt;

&lt;p&gt;Die gesamte Mächtigkeit von &lt;code&gt;std::bind&lt;/code&gt; lässt sich aus meiner Sicht nicht auf
C-Routinen übertragen. Vor allem Template-Konstrukte wie &lt;code&gt;std::placeholders&lt;/code&gt;
gestalten sich zu schwierig, aber wenn man einen ganzen Aufruf “binden” will,
gibt es einen Weg:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Man erzeugt einen Speicherblock, der Kopien der originalen Parameter 
zwischenspeichert&lt;/li&gt;
  &lt;li&gt;Und man erzeugt eine Dispatcher-Funktion, die die Zielfunktion mit den 
Parametern aus dem Zwischenspeicher aufruft.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Da wir in C keine Parameter-Type-Deduction haben, müssen Makros für jede 
unterstützte Anzahl von Parametern geschrieben werden.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;typedef&lt;/span&gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;struct&lt;/span&gt; storage_class storage_t;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;typedef&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt;(* generic_func_t)(&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;typedef&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt;(* dispatcher_t)(storage_t &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt;* storage);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;struct&lt;/span&gt; storage_class
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;  generic_func_t funcptr;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  dispatcher_t   disp;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;*          params[&lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;];
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;};
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#define&lt;/span&gt; DECLARE_DISPATCHER_3(name, type1, type2, type3) \
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;typedef&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; (* name &lt;span style=&quot;color:#579&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;# _callback&lt;/span&gt;)(type1 a1, type2 a2, type3 a3); \
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;static&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; name &lt;span style=&quot;color:#579&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;# _dispatcher&lt;/span&gt; (storage_t &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt;* storage) \
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;{ \
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; ret; \
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;  name &lt;span style=&quot;color:#579&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;# _callback&lt;/span&gt; cb = &lt;span style=&quot;color:#069&quot;&gt;NULL&lt;/span&gt;; \
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;  type1 * ptr_arg1 = (type1 *)storage-&amp;gt;params[&lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;]; \
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;  type2 * ptr_arg2 = (type2 *)storage-&amp;gt;params[&lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;]; \
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;  type3 * ptr_arg3 = (type3 *)storage-&amp;gt;params[&lt;span style=&quot;color:#00D&quot;&gt;2&lt;/span&gt;]; \
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;    memcpy(&amp;amp;cb, &amp;amp;storage-&amp;gt;funcptr, &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;sizeof&lt;/span&gt;(cb)); \
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n21&quot; name=&quot;n21&quot;&gt;21&lt;/a&gt;&lt;/span&gt;  ret = cb(*ptr_arg1, *ptr_arg2, *ptr_arg3); \
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n22&quot; name=&quot;n22&quot;&gt;22&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; ret; \
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n23&quot; name=&quot;n23&quot;&gt;23&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Um jetzt so ein &lt;code&gt;storage_t&lt;/code&gt; zu allokieren und zu befüllen, benutzt man eine
&lt;code&gt;variadic function&lt;/code&gt;, in der die gewünschten Parameter als Paar von Pointer
und Größe übergeben werden.
z.B.: &lt;code&gt;storage_t* bind_storage(generic_func_t target, dispatcher_t disp, ...);&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Eine &lt;code&gt;int foo(int a, double b, void* c)&lt;/code&gt;, müsste also mit:&lt;br /&gt;
&lt;code&gt;bind_storage(target, disp, &amp;amp;a, sizeof(a), &amp;amp;b, sizeof(b), &amp;amp;c, sizeof(c), NULL);&lt;/code&gt;
erzeugt werden.&lt;/p&gt;

&lt;p&gt;Über das Pointer+Größen Paar kann die Funktion die Anzahl der Parameter 
ermitteln und dann ein überallokiertes &lt;code&gt;storage_t&lt;/code&gt; erzeugen, in dem ganz 
hinten Kopien der originalen Daten (&lt;code&gt;a, b, c&lt;/code&gt;) liegen und davor im &lt;code&gt;params&lt;/code&gt;
Feld Pointer zu diesen Kopien eingesetzt werden.&lt;/p&gt;

&lt;p&gt;Der oben definierte Dispatcher klappert dann bei seinem Aufruf das Array ab
und castet die Pointer in die korrekten Zieltypen, um dann die Zielfunktion
mit genau den Parametern aufzurufen, die sie braucht.&lt;/p&gt;

&lt;h3 id=&quot;problem-lebenszeit&quot;&gt;Problem: Lebenszeit&lt;/h3&gt;

&lt;p&gt;Das C-Makro und unsere hier vereinfachte &lt;code&gt;bind_storage&lt;/code&gt; Funktion kopieren die
Datentypen per &lt;code&gt;memcpy()&lt;/code&gt; und das funktioniert ausschließlich bei primitiven
Datentypen problemlos. Sobald der erste Pointer zum Einsatz kommt, stellt
sich die Frage wie lange er gültig ist.&lt;/p&gt;

&lt;p&gt;In C++ kann man solche Dispatcher auch per Templates generieren lassen, wo sie
Copy-Constructor zum Kopieren und Destructor-Aufrufe für Cleanups automatisch
einbauen können, doch in C fehlt dieses Feature.&lt;/p&gt;

&lt;p&gt;Im GATE-Framework wird ein solcher &lt;code&gt;storage_t&lt;/code&gt; Typ in einem &lt;code&gt;gate_runnable_t&lt;/code&gt;
Objekt eingebettet, der selbst mit einer Referenzzählung arbeitet.
Der Objekt-Inhalt könnte natürlich auch durch individuelle Dispatcher je
nach Anwendungsfall separat ausimplementiert werden, doch genau das erweist
sich als mühsam und fehleranfällig.&lt;/p&gt;

&lt;p&gt;Von daher werden komplexe Typen wohl ausschließlich nur in C++ zum Einsatz
kommen und in C verbleibt lediglich ein bestimmtes Nischenumfeld, in dem 
&lt;code&gt;Runnables&lt;/code&gt; gebraucht werden.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Während also die Nützlichkeit der Runnables stark an den Sprachstandard
gebunden sind, hat aber die Definition einer “Trägerschnittstelle” für 
mich einen wichtigen Mehrwert:&lt;/p&gt;

&lt;p&gt;Komponenten von unterschiedlichen Compilern können “Runnables” nun 
standardisiert austauschen.&lt;br /&gt;
Während ein &lt;code&gt;std::bind&lt;/code&gt; Ergebnis eines &lt;code&gt;MSVC&lt;/code&gt; unbenutzbar ist in einer 
MinGW Anwendung ist, kann ein &lt;code&gt;gate_runnable_t&lt;/code&gt; problemlos zwischen diesen
beiden Welten verschoben werden.&lt;/p&gt;

&lt;p&gt;Ein Microservice in einer Sprache A kann somit Aufrufe in seinen eigenen
Code durch eine Sprache B ermöglichen.&lt;br /&gt;
Denn genau das ist die geheime Superkraft von C:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Es ermöglicht Binärkompatibilität auf allen Ebenen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Es mag daher mühsam sein, Codes auf C abzubilden, doch am Ende bietet
es immer auch Vorteile, wenn man an verteilte Systeme denkt.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Chromebook</title>
   <link href="https://www.opengate.at/blog/2022/01/chromebook/"/>
   <published>2022-01-16T12:00:00+01:00</published>
   <updated>2022-01-16T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2022/01/chromebook</id>
   <category term="hardware" /><category term="software" />
   <summary type="text">Ein Päckchen kam verspätet unterm Weihnachtsbaum hervor:
Ein Lenovo Chromebook.

Als Entwickler muss man eben auch wissen, was es sonst noch so am Markt
gibt. Und die wichtigste Frage für mich war natürlich:


  Lässt sich das GATE Framework auch am Chromebook kompilieren?


</summary>
   <content type="html">&lt;p&gt;Ein Päckchen kam verspätet unterm Weihnachtsbaum hervor:
Ein Lenovo &lt;a href=&quot;https://de.wikipedia.org/wiki/Chromebook&quot;&gt;Chromebook&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Als Entwickler muss man eben auch wissen, was es sonst noch so am Markt
gibt. Und die wichtigste Frage für mich war natürlich:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Lässt sich das GATE Framework auch am Chromebook kompilieren?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Nachdem ich Google und &lt;a href=&quot;https://de.wikipedia.org/wiki/Android_%28Betriebssystem%29&quot;&gt;Android&lt;/a&gt;
datenschutztechnisch für den Schlund der Hölle halte, sind Chromebooks für 
mich das gleiche in dunkelrot.&lt;br /&gt;
However, um böse Geister bekämpfen zu können, muss man sie verstehen lernen,
und daher ist nun ein solches Modell mein Eigen geworden.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/chromebook_open.jpg&quot; alt=&quot;Chromebook-Updates&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Und ich muss sagen, dass “der kleine Laptop” eigentlich ein ganz nettes Gerät
ist und für seine primäre Aufgabe (schnell Mails und Websites durchgehen
zu können) sehr gut geeignet ist.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/chromebook_closed.jpg&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;230 Euro kostete mich dieses Einsteigergerät, wobei ich dumm war, und es im
Zuge diverser Weihnachtsaktionen vermutlich auch günstiger hätte bekommen 
können. Jedenfalls starten genau in diesem Preissegment auch andere 10-Zoll 
Windows Tablets und Kleinlaptops.&lt;/p&gt;

&lt;h3 id=&quot;setup&quot;&gt;Setup&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;WLAN ist der erste Punkt der eingerichtet werden muss, danach beginnt
ein langer Download von Updates&lt;br /&gt;
&lt;img src=&quot;/blog/assets/img/chromebook_01.jpg&quot; alt=&quot;Image&quot; /&gt;&lt;/li&gt;
  &lt;li&gt;Nun muss man seinen Google Account für den Login angeben oder einen
neuen Account anlegen lassen&lt;br /&gt;
&lt;img src=&quot;/blog/assets/img/chromebook_02.jpg&quot; alt=&quot;Image&quot; /&gt;&lt;br /&gt;
&lt;img src=&quot;/blog/assets/img/chromebook_03.jpg&quot; alt=&quot;Image&quot; /&gt;&lt;/li&gt;
  &lt;li&gt;Google will immer alles synchronisieren … zumindest wenn man diese
Einstellungen nicht deaktiviert&lt;br /&gt;
&lt;img src=&quot;/blog/assets/img/chromebook_04.jpg&quot; alt=&quot;Image&quot; /&gt;&lt;br /&gt;
&lt;img src=&quot;/blog/assets/img/chromebook_05.jpg&quot; alt=&quot;Image&quot; /&gt;&lt;br /&gt;
&lt;img src=&quot;/blog/assets/img/chromebook_06.jpg&quot; alt=&quot;Image&quot; /&gt;&lt;/li&gt;
  &lt;li&gt;Am Ende soll auch noch das Smartphone angebunden werden.
Google hat natürlich schon alle Daten gespeichert.    &lt;br /&gt;
&lt;img src=&quot;/blog/assets/img/chromebook_07.jpg&quot; alt=&quot;Image&quot; /&gt;&lt;/li&gt;
  &lt;li&gt;Und das war es auch schon.
&lt;img src=&quot;/blog/assets/img/chromebook_08.jpg&quot; alt=&quot;Image&quot; /&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;development-umgebung&quot;&gt;Development Umgebung&lt;/h3&gt;

&lt;p&gt;Ich hätte nicht gedacht, dass Chromebooks ihren eigenen Entwickler-Modus haben.
Doch tatsächlich existiert ein solcher und ist in Wahrheit ein 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt; &lt;a href=&quot;https://de.wikipedia.org/wiki/Docker_(Software)&quot;&gt;Docker&lt;/a&gt;
Container mit &lt;a href=&quot;https://de.wikipedia.org/wiki/Debian&quot;&gt;Debian&lt;/a&gt; 11, 
der per &lt;a href=&quot;https://de.wikipedia.org/wiki/X_Window_System&quot;&gt;X11-Server&lt;/a&gt; auch 
UI-tauglich ist.&lt;/p&gt;

&lt;p&gt;Somit lässt sich so gut wie jede Linux-Software installieren und ausführen,
bis hin zu den Android SDKs.&lt;/p&gt;

&lt;p&gt;Die Einrichtung erfolgt über:&lt;/p&gt;

&lt;p&gt;Einstellungen:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/chromebook_09.jpg&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Linux Umgebung installieren:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/chromebook_11.jpg&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Es öffnet sich die Shell mit einem Debian 11&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/chromebook_13.jpg&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Und all üblichen Tools von &lt;code&gt;apt&lt;/code&gt; bis zum &lt;code&gt;procfs&lt;/code&gt; sind vorhanden:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/chromebook_14.jpg&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Da ich keiner dieser Typen bin, die alle paar Minuten auf &lt;a href=&quot;https://de.wikipedia.org/wiki/Instagram&quot;&gt;Instagram&lt;/a&gt; 
ihre eigenen Fotos anschauen müssen und nach Kommentaren Ausschau halten, werden
solche “großen Smartphones mit Tastatur” nie meinen Alltag prägen.&lt;/p&gt;

&lt;p&gt;Ich verstehe aber, dass eben genau für diese Zielgruppe ein kleines handliches
Gerät wie ein Chromebook genau das richtige sein kann, um diese Bedürfnisse
zu erfüllen.&lt;/p&gt;

&lt;p&gt;Mit langen Akkulaufzeiten, der kurzen Bootdauer und einer auf das Web
angepassten Oberfläche ist mein Chromebook den üblichen 10/11 Zoll Windows
Laptops auf Intel Atom Basis in vielen Punkten überlegen.&lt;/p&gt;

&lt;p&gt;Würde nicht Google an jeder Stelle Daten absaugen wollen, könnte ich dieser
Hardware durchaus positiv gegenüber stehen.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Mandelbrot und Apfelmännchen</title>
   <link href="https://www.opengate.at/blog/2022/01/mandelbrot/"/>
   <published>2022-01-15T12:00:00+01:00</published>
   <updated>2022-01-15T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2022/01/mandelbrot</id>
   <category term="devel" /><category term="retro" />
   <summary type="text">Für meine Framebuffer Experimente 
brauchte irgend eine “anschaubare” Grafikausgabe, und dabei fiel mir spontan 
wieder das Apfelmännchen ein.

Dieses mathematisch errechnete Farbenspiel aus der Mandelbrot-Menge
tauchte und taucht in Schulen immer wieder als Programmierbeispiel
auf.

Und heute freue ich mich, dass ich diesen Code auch wieder mal
sinnvoll “recyclen” kann.

</summary>
   <content type="html">&lt;p&gt;Für meine &lt;a href=&quot;/blog/2022/01/framebuffers/&quot;&gt;Framebuffer Experimente&lt;/a&gt; 
brauchte irgend eine “anschaubare” Grafikausgabe, und dabei fiel mir spontan 
wieder das &lt;a href=&quot;https://de.wikipedia.org/wiki/Mandelbrot-Menge&quot;&gt;Apfelmännchen&lt;/a&gt; ein.&lt;/p&gt;

&lt;p&gt;Dieses mathematisch errechnete Farbenspiel aus der Mandelbrot-Menge
tauchte und taucht in Schulen immer wieder als Programmierbeispiel
auf.&lt;/p&gt;

&lt;p&gt;Und heute freue ich mich, dass ich diesen Code auch wieder mal
sinnvoll “recyclen” kann.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Der Code, den wir in Schulen zu Gesicht bekommen, sieht in etwa so aus:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;typedef&lt;/span&gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;struct&lt;/span&gt; 
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;unsigned&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt; r;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;unsigned&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt; g;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;unsigned&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt; b;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;} rgb_t;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt; set_pixel(&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; x, &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; y, rgb_t &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt;* color);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt; mandelbrot_render()
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;  rgb_t color;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; width = &lt;span style=&quot;color:#00D&quot;&gt;640&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; height = &lt;span style=&quot;color:#00D&quot;&gt;480&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; ix, iy, count;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;double&lt;/span&gt; x, y, qx, qy, temp;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;double&lt;/span&gt; xmin = -&lt;span style=&quot;color:#00D&quot;&gt;2&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;double&lt;/span&gt; xmax = &lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;double&lt;/span&gt; ymin = -&lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;double&lt;/span&gt; ymax = &lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n21&quot; name=&quot;n21&quot;&gt;21&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n22&quot; name=&quot;n22&quot;&gt;22&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;for&lt;/span&gt;(ix = &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;; ix &amp;lt; width; ix++)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n23&quot; name=&quot;n23&quot;&gt;23&lt;/a&gt;&lt;/span&gt;  {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n24&quot; name=&quot;n24&quot;&gt;24&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;for&lt;/span&gt;(iy = &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;; iy &amp;lt; height; iy++)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n25&quot; name=&quot;n25&quot;&gt;25&lt;/a&gt;&lt;/span&gt;    {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n26&quot; name=&quot;n26&quot;&gt;26&lt;/a&gt;&lt;/span&gt;      x = (&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;double&lt;/span&gt;)ix / (&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;double&lt;/span&gt;)width * (xmax - xmin) + xmin;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n27&quot; name=&quot;n27&quot;&gt;27&lt;/a&gt;&lt;/span&gt;      y = (&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;double&lt;/span&gt;)iy / (&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;double&lt;/span&gt;)height * (ymax - ymin) + ymin;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n28&quot; name=&quot;n28&quot;&gt;28&lt;/a&gt;&lt;/span&gt;      count = &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;; 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n29&quot; name=&quot;n29&quot;&gt;29&lt;/a&gt;&lt;/span&gt;      qx = x; 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n30&quot; name=&quot;n30&quot;&gt;30&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;      qy = y;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n31&quot; name=&quot;n31&quot;&gt;31&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;while&lt;/span&gt;((count &amp;lt; &lt;span style=&quot;color:#00D&quot;&gt;256&lt;/span&gt;) &amp;amp;&amp;amp; ((qx * qx + qy * qy) &amp;lt; &lt;span style=&quot;color:#00D&quot;&gt;4&lt;/span&gt;))
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n32&quot; name=&quot;n32&quot;&gt;32&lt;/a&gt;&lt;/span&gt;      {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n33&quot; name=&quot;n33&quot;&gt;33&lt;/a&gt;&lt;/span&gt;        count++;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n34&quot; name=&quot;n34&quot;&gt;34&lt;/a&gt;&lt;/span&gt;        temp = &lt;span style=&quot;color:#60E&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#60E&quot;&gt;.0&lt;/span&gt; * qx * qy + y;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n35&quot; name=&quot;n35&quot;&gt;35&lt;/a&gt;&lt;/span&gt;        qx = qx * qx - qy * qy + x;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n36&quot; name=&quot;n36&quot;&gt;36&lt;/a&gt;&lt;/span&gt;        qy = temp;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n37&quot; name=&quot;n37&quot;&gt;37&lt;/a&gt;&lt;/span&gt;      }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n38&quot; name=&quot;n38&quot;&gt;38&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n39&quot; name=&quot;n39&quot;&gt;39&lt;/a&gt;&lt;/span&gt;      color.r = &lt;span style=&quot;color:#00D&quot;&gt;256&lt;/span&gt; - (count * &lt;span style=&quot;color:#00D&quot;&gt;4&lt;/span&gt;) % &lt;span style=&quot;color:#00D&quot;&gt;256&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n40&quot; name=&quot;n40&quot;&gt;40&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;      color.g = &lt;span style=&quot;color:#00D&quot;&gt;256&lt;/span&gt; - (count * &lt;span style=&quot;color:#00D&quot;&gt;16&lt;/span&gt;) % &lt;span style=&quot;color:#00D&quot;&gt;256&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n41&quot; name=&quot;n41&quot;&gt;41&lt;/a&gt;&lt;/span&gt;      color.b = count % &lt;span style=&quot;color:#00D&quot;&gt;256&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n42&quot; name=&quot;n42&quot;&gt;42&lt;/a&gt;&lt;/span&gt;      set_pixel(ix, iy, &amp;amp;color);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n43&quot; name=&quot;n43&quot;&gt;43&lt;/a&gt;&lt;/span&gt;    }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n44&quot; name=&quot;n44&quot;&gt;44&lt;/a&gt;&lt;/span&gt;  }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n45&quot; name=&quot;n45&quot;&gt;45&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Gerechnet wird im Fensterbereich &lt;code&gt;(-2, -1)-(+1, +1)&lt;/code&gt; und abgebildet auf eine
RGB-Farbfläche von &lt;code&gt;640 x 480&lt;/code&gt; Pixel. Und dabei sieht man das bekannte
Haupt-Apfelmännchen.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/mandelbrot-0.gif&quot; alt=&quot;Mandelbrot 1&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Wenn man nun in das Bild hineinzoomt (also &lt;code&gt;xmin,ymin&lt;/code&gt; vergrößert und 
&lt;code&gt;xmax,ymax&lt;/code&gt; verkleinert), werden an den Farbübergängen interessante Strukturen
sichtbar.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/mandelbrot-1.gif&quot; alt=&quot;Mandelbrot 2&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Das kann man beliebig tief tun und man wird dabei immer auf ähnliche 
Strukturen in unterschiedlicher Verzerrung stoßen und vor allem
das Apfelmännchen wird man in kleineren Varianten ebenso immer wieder
mal antreffen.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/mandelbrot-2.gif&quot; alt=&quot;Mandelbrot 3&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Für Grafik-Tests könnte man natürlich auch ein Foto laden und anzeigen,
aber mir gefällt die Vorstellung, dass alles aus dem Code heraus generiert
wird.&lt;br /&gt;
Außerdem beeindruckt mich der verblüffend einfache Code, der solch ansehnliche
Bilder malen kann.&lt;/p&gt;

&lt;p&gt;Früher (um 2000) in der Schule nutzten wir das alte &lt;a href=&quot;https://de.wikipedia.org/wiki/Turbo_Pascal&quot;&gt;Turbo Pascal&lt;/a&gt;
unter &lt;a href=&quot;https://de.wikipedia.org/wiki/MS-DOS&quot;&gt;DOS&lt;/a&gt; und 
setzten 16 Farben auf 640x480 Pixel oder sogar 256 Farben im 
&lt;a href=&quot;https://en.wikipedia.org/wiki/Mode_X&quot;&gt;Mode X (320x200 Pixel)&lt;/a&gt; ein.&lt;br /&gt;
Heute dient mir das Beispiel als Vergleich, ob meine WinAPI, &lt;a href=&quot;https://de.wikipedia.org/wiki/Xlib&quot;&gt;XLIB&lt;/a&gt;, 
&lt;a href=&quot;https://de.wikipedia.org/wiki/OpenGL&quot;&gt;OpenGL&lt;/a&gt; und &lt;a href=&quot;https://wiki.osdev.org/GOP&quot;&gt;uEFI-GOP&lt;/a&gt;
Framebuffer-Implementierungen auch immer “gleich” aussehen.&lt;br /&gt;
(Manchmal verwechselte ich z.B. RGB und BGR, was die Farbpalette verdrehte.)&lt;/p&gt;

&lt;p&gt;Und mit ein paar Zoom- und Move-Faktoren im Code lässt sich mit Mausklicks
und Pfeiltasten ganz passabel durch so ein Apfelmännchen durchnavigieren.&lt;br /&gt;
Der Code ist nun im Demo-Projekt &lt;code&gt;gateframes&lt;/code&gt; verewigt.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Framebuffer</title>
   <link href="https://www.opengate.at/blog/2022/01/framebuffers/"/>
   <published>2022-01-09T12:00:00+01:00</published>
   <updated>2022-01-09T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2022/01/framebuffers</id>
   <category term="devel" />
   <summary type="text">Meine OpenGL Experimente und die 
gategames Demo-App sind zwar toll für Windows,
Linux und Android, 
jedoch kann ich diese Form der Grafikausgabe nie auf EFI,
FreeRTOS oder DOS
portieren.

Wenn man aber ein abstraktes Modell eines primitiven 2D-Bildspeichers hätte, 
in dem man Pixel setzen und Grafik-Untermengen hinein und herauskopieren kann,
dann hätte man einen Ansatz, den man viel leichter auf alle Formen von 
“Bildschirmen” portieren kann. (Mikrocontroller inklusive).

</summary>
   <content type="html">&lt;p&gt;Meine &lt;a href=&quot;https://de.wikipedia.org/wiki/OpenGL&quot;&gt;OpenGL&lt;/a&gt; Experimente und die 
&lt;code&gt;gategames&lt;/code&gt; Demo-App sind zwar toll für &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows&quot;&gt;Windows&lt;/a&gt;,
&lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt; und &lt;a href=&quot;https://de.wikipedia.org/wiki/Android_%28Betriebssystem%29&quot;&gt;Android&lt;/a&gt;, 
jedoch kann ich diese Form der Grafikausgabe nie auf &lt;a href=&quot;https://de.wikipedia.org/wiki/Unified_Extensible_Firmware_Interface&quot;&gt;EFI&lt;/a&gt;,
&lt;a href=&quot;https://de.wikipedia.org/wiki/FreeRTOS&quot;&gt;FreeRTOS&lt;/a&gt; oder &lt;a href=&quot;https://de.wikipedia.org/wiki/MS-DOS&quot;&gt;DOS&lt;/a&gt;
portieren.&lt;/p&gt;

&lt;p&gt;Wenn man aber ein abstraktes Modell eines primitiven 2D-Bildspeichers hätte, 
in dem man Pixel setzen und Grafik-Untermengen hinein und herauskopieren kann,
dann hätte man einen Ansatz, den man viel leichter auf alle Formen von 
“Bildschirmen” portieren kann. (Mikrocontroller inklusive).&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;vorgeschichte&quot;&gt;Vorgeschichte&lt;/h3&gt;

&lt;p&gt;Der Aufbau von UIs ist in jedem Betriebssystem grundlegend anders (trotz 
einiger Ähnlichkeiten). Ich behaupte mal, dass der Erfolg von 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Hypertext_Markup_Language&quot;&gt;HTML&lt;/a&gt; und der
Webbrowser auch damit begründet ist, dass UI-Designer nur einmal die Arbeit
haben, ihr Werk abzutippen und die Browser kümmern sich um die korrekte
Übersetzung in die Welt des Ziel-OS.&lt;/p&gt;

&lt;p&gt;Früher in den DOS Zeiten baute sich jede Anwendung ihr eigenes UI zusammen,
und zeichnete mehr oder weniger direkt in den Grafikkartenspeicher.&lt;/p&gt;

&lt;p&gt;Man stelle sich also vor, man hätte einen “abstrakten” Grafikspeicher 
(genannt Framebuffer) in seiner Bibliothek, der unter Windows ein Fenster mit
&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/gdi/windows-gdi&quot;&gt;GDI&lt;/a&gt; bemalt, 
unter Linux die &lt;a href=&quot;https://de.wikipedia.org/wiki/Xlib&quot;&gt;XLib&lt;/a&gt; befehligt und auf 
exotischen Plattformen wie früher direkt in den Video-RAM schreibt.&lt;/p&gt;

&lt;p&gt;Dann hätte man die Möglichkeit grafische Oberflächen universell portabel
zu gestalten.&lt;/p&gt;

&lt;h3 id=&quot;windows-und-gdi&quot;&gt;Windows und GDI&lt;/h3&gt;

&lt;p&gt;In Windows erzeugt man einfach ein Fenster mit 
&lt;a href=&quot;http://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-createwindowexw&quot;&gt;&lt;code&gt;CreateWindowEx&lt;/code&gt;&lt;/a&gt;
und eine “32 Bit pro Pixel” &lt;a href=&quot;http://docs.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-createdibsection&quot;&gt;DIB-Section&lt;/a&gt;.&lt;br /&gt;
Die DIB-Section ist dann unser Framebuffer, wo wir direkt auf die Bilddaten
zugreifen können.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;HWND hwnd_desktop = GetDesktopWindow();
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;HDC hdc_desktop = GetDC(hwnd_desktop);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;HDC hdc_framebuffer = CreateCompatibleDC(hdc_desktop);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;BITMAPINFO bitmapinfo;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;bitmapinfo.bmiHeader.biSize = &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;sizeof&lt;/span&gt;(BITMAPINFOHEADER);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;bitmapinfo.bmiHeader.biWidth = (LONG)framebuffer_width;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;bitmapinfo.bmiHeader.biHeight = (LONG)framebuffer_height;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;bitmapinfo.bmiHeader.biPlanes = &lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;bitmapinfo.bmiHeader.biBitCount = &lt;span style=&quot;color:#00D&quot;&gt;32&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;bitmapinfo.bmiHeader.biCompression = BI_RGB;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;bitmapinfo.bmiHeader.biSizeImage = &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;bitmapinfo.bmiHeader.biXPelsPerMeter = &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;bitmapinfo.bmiHeader.biYPelsPerMeter = &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;bitmapinfo.bmiHeader.biClrImportant = &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;bitmapinfo.bmiHeader.biClrUsed = &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;DWORD* ptr_framebuffer;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;HBITMAP hbmp_framebuffer = CreateDIBSection(hdc_framebuffer, 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  &amp;amp;bitmapinfo, DIB_RGB_COLORS, (&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;**)&amp;amp;ptr_framebuffer, &lt;span style=&quot;color:#069&quot;&gt;NULL&lt;/span&gt;, &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n21&quot; name=&quot;n21&quot;&gt;21&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n22&quot; name=&quot;n22&quot;&gt;22&lt;/a&gt;&lt;/span&gt;HGDIOBJ old_dc = SelectObject(hdc_framebuffer, hbmp_framebuffer);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n23&quot; name=&quot;n23&quot;&gt;23&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n24&quot; name=&quot;n24&quot;&gt;24&lt;/a&gt;&lt;/span&gt;ReleaseDC(hwnd_desktop, hdc_desktop);
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Man erzeugt also einen Device-Context kompatibel zum Desktop-Fenster 
(&lt;code&gt;hdc_framebuffer&lt;/code&gt;) und die DIB-Section (&lt;code&gt;hbmp_framebuffer&lt;/code&gt;) durch einen
BITMAP-Info-Header mit den Größenangaben. Dabei fällt einem der Daten-Pointer
(&lt;code&gt;ptr_framebuffer&lt;/code&gt;) in die Hände.&lt;/p&gt;

&lt;p&gt;Die größte Challenge ist der Aufbau der DIB-Section, die wie eine Windows
Bitmap aussieht. Die Bildzeilen verlaufen dort von &lt;em&gt;unten nach oben&lt;/em&gt;, und
damit ist Koordinate &lt;code&gt;(0, 0)&lt;/code&gt; (bzw. Pixel-Offset &lt;code&gt;0&lt;/code&gt;) die linke &lt;em&gt;untere&lt;/em&gt; Ecke
und &lt;code&gt;(0, Y-max)&lt;/code&gt; die linke &lt;em&gt;obere&lt;/em&gt; Ecke.&lt;br /&gt;
Viele andere Framebuffer (und auch mein GATE Framework) definieren &lt;code&gt;(0, 0)&lt;/code&gt; 
als &lt;em&gt;links-oben&lt;/em&gt; und verlaufen mit steigendem Y &lt;em&gt;nach unten&lt;/em&gt;.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;DWORD* ptr_pixel = ptr_framebuffer + (height - y - &lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;) * width + x;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;*ptr_pixel = (((DWORD)r) &amp;lt;&amp;lt; &lt;span style=&quot;color:#00D&quot;&gt;16&lt;/span&gt;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;           | (((DWORD)g) &amp;lt;&amp;lt; &lt;span style=&quot;color:#00D&quot;&gt;8&lt;/span&gt;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;           | (((DWORD)b));
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Und am Ende muss man per&lt;br /&gt;
&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-redrawwindow&quot;&gt;&lt;code&gt;RedrawWindow(hwnd, NULL, NULL, RDW_INTERNALPAINT | RDW_INVALIDATE)&lt;/code&gt;&lt;/a&gt;
nur das Neuzeichnen des gesamten Fensters auslösen.&lt;/p&gt;

&lt;p&gt;Im Fenster wird im &lt;a href=&quot;http://docs.microsoft.com/en-us/windows/win32/gdi/wm-paint&quot;&gt;WM_PAINT&lt;/a&gt; 
Event dann einfach per &lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-bitblt&quot;&gt;BitBlt()&lt;/a&gt; 
der aktuell “ungültige” Teil des Fenster mit den Daten aus der DIB-Section 
übermalt.&lt;/p&gt;

&lt;h3 id=&quot;xlib-und-pixmaps&quot;&gt;XLIB und Pixmaps&lt;/h3&gt;

&lt;p&gt;Mein erster Versuch mit der XLib und dem Zeichnen auf X11-Pixmaps lief über 
die Funktion &lt;a href=&quot;https://tronche.com/gui/x/xlib/utilities/XPutPixel.html&quot;&gt;XPutPixel()&lt;/a&gt; 
in einer Schleife. Das funktionierte zwar, doch für eine 640x480 Pixel Grafik 
brauchte mein Rechner mehrere Sekunden.&lt;br /&gt;
Oder anders gesagt: &lt;em&gt;Noch ineffizienter geht es nicht mehr&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Doch auch bei Pixmaps kann man den Datenpuffer selbst allokieren und dann die
RGB-Werte selbst in den Puffer schreiben. Womit man schon in wenigen 
Millisekunden eine ganze Szene in den Puffer gerendert hat.&lt;br /&gt;
So kann man dann die gesamte Pixmap in einem Schritt dann auf sein Fenster
am Monitor zeichnen lassen.&lt;/p&gt;

&lt;p&gt;Das funktioniert natürlich nur bei einer Farbtiefe von 24 oder 32 bit, wo in 
beiden Fällen ein 32 Bit breites &lt;code&gt;RGB&lt;/code&gt;-Array im Speicher liegt.
(Alle anderen historischen Bitmusterformen sind komplizierter umzurechnen.)&lt;/p&gt;

&lt;p&gt;Rein exemplarisch und vereinfacht, sieht das dann so aus:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color:#B44;font-weight:bold&quot;&gt;&amp;lt;X11/Xlib.h&amp;gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt; set_pixmap_pixel(&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;* image_data, 
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;unsigned&lt;/span&gt; x, &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;unsigned&lt;/span&gt; y, rgb_t &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt;* color)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;  uint32_t* ptr_pixels = (uint32_t)image_data;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  uint32_t* target_pixel = ptr_pixels[y * width + x];
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;  *target_pixel = (((uint32_t)color-&amp;gt;r) &amp;lt;&amp;lt; &lt;span style=&quot;color:#00D&quot;&gt;16&lt;/span&gt;)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;                | (((uint32_t)color-&amp;gt;g) &amp;lt;&amp;lt; &lt;span style=&quot;color:#00D&quot;&gt;8&lt;/span&gt;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;                | (((uint32_t)color-&amp;gt;b))
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;                ;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;}
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;XImage* create_x11_pixmap(...)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;unsigned&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; bytes_per_pixel = &lt;span style=&quot;color:#00D&quot;&gt;4&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;unsigned&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; padding = XBitmapPad(display);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;unsigned&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; bytes_per_line = width * bytes_per_pixel;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt;(bytes_per_line % padding != &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n21&quot; name=&quot;n21&quot;&gt;21&lt;/a&gt;&lt;/span&gt;    bytes_per_line += (padding - (bytes_per_line % padding));
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n22&quot; name=&quot;n22&quot;&gt;22&lt;/a&gt;&lt;/span&gt;  }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n23&quot; name=&quot;n23&quot;&gt;23&lt;/a&gt;&lt;/span&gt;  size_t image_size bytes_per_line * height;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n24&quot; name=&quot;n24&quot;&gt;24&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;* image_data = malloc(image_size);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n25&quot; name=&quot;n25&quot;&gt;25&lt;/a&gt;&lt;/span&gt;  XImage* image = XCreateImage(display, visual, depth, ZPixmap, 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n26&quot; name=&quot;n26&quot;&gt;26&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;, image_data, width, height, padding, &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n27&quot; name=&quot;n27&quot;&gt;27&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; image;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n28&quot; name=&quot;n28&quot;&gt;28&lt;/a&gt;&lt;/span&gt;}
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n29&quot; name=&quot;n29&quot;&gt;29&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n30&quot; name=&quot;n30&quot;&gt;30&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt; create_x11_window()
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n31&quot; name=&quot;n31&quot;&gt;31&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n32&quot; name=&quot;n32&quot;&gt;32&lt;/a&gt;&lt;/span&gt;  Display* display = XOpenDisplay(&lt;span style=&quot;color:#069&quot;&gt;NULL&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n33&quot; name=&quot;n33&quot;&gt;33&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; screen = XDefaultScreen(display);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n34&quot; name=&quot;n34&quot;&gt;34&lt;/a&gt;&lt;/span&gt;  Window root_window = XDefaultRootWindow(display);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n35&quot; name=&quot;n35&quot;&gt;35&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; depth = XDefaultDepth(display, screen);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n36&quot; name=&quot;n36&quot;&gt;36&lt;/a&gt;&lt;/span&gt;  Visual* visual = XDefaultVisual(display, screen);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n37&quot; name=&quot;n37&quot;&gt;37&lt;/a&gt;&lt;/span&gt;  Colormap colmap = XDefaultColormap(display, screen);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n38&quot; name=&quot;n38&quot;&gt;38&lt;/a&gt;&lt;/span&gt;  XSetWindowAttributes win_attribs = { &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt; };
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n39&quot; name=&quot;n39&quot;&gt;39&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n40&quot; name=&quot;n40&quot;&gt;40&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  win_attribs.colormap = colmap;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n41&quot; name=&quot;n41&quot;&gt;41&lt;/a&gt;&lt;/span&gt;  win_attribs.event_mask = StructureNotifyMask;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n42&quot; name=&quot;n42&quot;&gt;42&lt;/a&gt;&lt;/span&gt;  win_attribs.border_pixel = XBlackPixel(display, screen);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n43&quot; name=&quot;n43&quot;&gt;43&lt;/a&gt;&lt;/span&gt;  win_attribs.background_pixel = XWhitePixel(display, screen);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n44&quot; name=&quot;n44&quot;&gt;44&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;unsigned&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;long&lt;/span&gt; attr_mask = CWBackPixel | CWBorderPixel 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n45&quot; name=&quot;n45&quot;&gt;45&lt;/a&gt;&lt;/span&gt;                          | CWEventMask | CWColormap;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n46&quot; name=&quot;n46&quot;&gt;46&lt;/a&gt;&lt;/span&gt;  
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n47&quot; name=&quot;n47&quot;&gt;47&lt;/a&gt;&lt;/span&gt;  Window window = XCreateWindow(display, root_window, 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n48&quot; name=&quot;n48&quot;&gt;48&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;, &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;, width, height, &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;, depth, InputOutput, visual, 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n49&quot; name=&quot;n49&quot;&gt;49&lt;/a&gt;&lt;/span&gt;    attr_mask, &amp;amp;win_attribs);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n50&quot; name=&quot;n50&quot;&gt;50&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  XMapWindow(display, window);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n51&quot; name=&quot;n51&quot;&gt;51&lt;/a&gt;&lt;/span&gt;  XFlush(display);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n52&quot; name=&quot;n52&quot;&gt;52&lt;/a&gt;&lt;/span&gt;  ...
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n53&quot; name=&quot;n53&quot;&gt;53&lt;/a&gt;&lt;/span&gt;}
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n54&quot; name=&quot;n54&quot;&gt;54&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n55&quot; name=&quot;n55&quot;&gt;55&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt; render_x11_scene(...)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n56&quot; name=&quot;n56&quot;&gt;56&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n57&quot; name=&quot;n57&quot;&gt;57&lt;/a&gt;&lt;/span&gt;  ...
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n58&quot; name=&quot;n58&quot;&gt;58&lt;/a&gt;&lt;/span&gt;  XImage* image = create_x11_pixmap(...)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n59&quot; name=&quot;n59&quot;&gt;59&lt;/a&gt;&lt;/span&gt;  ...
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n60&quot; name=&quot;n60&quot;&gt;60&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;for&lt;/span&gt;(...)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n61&quot; name=&quot;n61&quot;&gt;61&lt;/a&gt;&lt;/span&gt;  {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n62&quot; name=&quot;n62&quot;&gt;62&lt;/a&gt;&lt;/span&gt;    ...
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n63&quot; name=&quot;n63&quot;&gt;63&lt;/a&gt;&lt;/span&gt;    set_pixmap_pixel(image_data, x, y, &amp;amp;color);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n64&quot; name=&quot;n64&quot;&gt;64&lt;/a&gt;&lt;/span&gt;    ...
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n65&quot; name=&quot;n65&quot;&gt;65&lt;/a&gt;&lt;/span&gt;  }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n66&quot; name=&quot;n66&quot;&gt;66&lt;/a&gt;&lt;/span&gt;  ...
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n67&quot; name=&quot;n67&quot;&gt;67&lt;/a&gt;&lt;/span&gt;  GC gc = XCreateGC(display, window, &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;, &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n68&quot; name=&quot;n68&quot;&gt;68&lt;/a&gt;&lt;/span&gt;  XSetGraphicsExposures(display, gc, &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n69&quot; name=&quot;n69&quot;&gt;69&lt;/a&gt;&lt;/span&gt;  XPutImage(display, window, gc, image, &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;, &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;, &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;, &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;, width, height);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n70&quot; name=&quot;n70&quot;&gt;70&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Man sieht wieder einmal, dass Windows und Linux bzw. X11 gar nicht so weit
auseinander liegen, was den Aufbau von GUIs intern anbelangt.
Denn in beiden kann man einen Framebuffer so einrichten, dass man ihn mit
einfachen 32-bit RGB Werten abfüllen kann.&lt;/p&gt;

&lt;p&gt;Wenn man jetzt noch Maus und Tastaturbehandlung hinzufügt, dann kann mit
einfachsten Mitteln GUIs für beide Plattformen bauen.
Dafür müsste man sich natürlich alle “üblichen” Controls wie Buttons,
Listen und Eingabefelder selbst zusammenstellen, doch das Ergebnis wäre
eine komplett Plattform-unabhängige UI.&lt;/p&gt;

&lt;p&gt;Einfache Apps (wie z.B.: zum Anzeigen von Fotos) kann man auf diese Weise 
in wenigen Kilobytes selbst erstellen, ohne auf Megabyte große
Frameworks zurückgreifen zu müssen.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Koroutinen Kontextwechsel</title>
   <link href="https://www.opengate.at/blog/2022/01/coroutines-3/"/>
   <published>2022-01-02T12:00:00+01:00</published>
   <updated>2022-01-02T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2022/01/coroutines-3</id>
   <category term="devel" />
   <summary type="text">Nach meinen Experimenten mit Koroutinen mit OS-Funktionen
und meinem Fehlschlag mit setjmp/longjump,
ist es an der Zeit, das Thema “neu zu denken”.

Denn jetzt, wo Assembler Patches im
GATE Projekt leicht möglich sind und mit UEFI
eine zur Zeit thread-lose Implementierung vor mir liegt, bekommen 
Koroutinen plötzlich eine 
neue Bedeutung.
</summary>
   <content type="html">&lt;p&gt;Nach meinen Experimenten mit &lt;a href=&quot;/blog/2021/09/coroutine-1/&quot;&gt;Koroutinen mit OS-Funktionen&lt;/a&gt;
und meinem &lt;a href=&quot;/blog/2021/09/coroutine-2/&quot;&gt;Fehlschlag mit setjmp/longjump&lt;/a&gt;,
ist es an der Zeit, das Thema “neu zu denken”.&lt;/p&gt;

&lt;p&gt;Denn jetzt, wo &lt;a href=&quot;/blog/2021/12/asm-cmake/&quot;&gt;Assembler&lt;/a&gt; Patches im
GATE Projekt leicht möglich sind und mit &lt;a href=&quot;https://de.wikipedia.org/wiki/Unified_Extensible_Firmware_Interface&quot;&gt;UEFI&lt;/a&gt;
eine zur Zeit thread-lose Implementierung vor mir liegt, bekommen 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Koroutine&quot;&gt;Koroutinen&lt;/a&gt; plötzlich eine 
neue Bedeutung.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Für &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows&quot;&gt;Windows&lt;/a&gt; und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt; habe ich mit Boardmitteln 
akzeptable Lösungen gefunden, um innerhalb eines Threads zwischen 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Aufrufstapel&quot;&gt;Callstacks&lt;/a&gt; hin und her zu hüpfen.&lt;/p&gt;

&lt;p&gt;In EFI-Apps gibt es keine &lt;a href=&quot;https://de.wikipedia.org/wiki/Thread_(Informatik)&quot;&gt;Threads&lt;/a&gt;, 
doch wenn man mehrere Callstacks anlegen könnte und zwischen denen hin- und 
herhüpfen könnte, dann wäre eine einfache Art von 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Multitasking#Kooperatives_Multitasking&quot;&gt;kooperativem Multitasking&lt;/a&gt;
geboren, mit der man z.B. einen Webserver dazu bringen könnte, mehrere 
Anfragen zu bearbeiten, oder man könnte UIs mit Background-Tasks aufwerten.&lt;/p&gt;

&lt;h3 id=&quot;callstacks-erzeugen&quot;&gt;Callstacks erzeugen&lt;/h3&gt;

&lt;p&gt;Normaler Datenspeicher, wie er von &lt;code&gt;malloc()&lt;/code&gt; zurückkommt, ist nicht automatisch
Stack-tauglich. Oft muss man dem OS erst mitteilen, dass man auch “Code-Adressen”
darauf nutzen möchte.&lt;/p&gt;

&lt;p&gt;EFI nutzt offenbar keinen Speicherschutz womit ein&lt;br /&gt;
&lt;code&gt;efi_sys_table-&amp;gt;BootServices-&amp;gt;AllocatePool(EfiLoaderData, mem_size, &amp;amp;ptr_mem);&lt;/code&gt;
ausreicht um Speicher für einen Callstack zu allokieren.&lt;/p&gt;

&lt;p&gt;Unter Windows braucht man APIs wie 
&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualalloc&quot;&gt;&lt;code&gt;VirtualAlloc()&lt;/code&gt;&lt;/a&gt;, 
&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualprotect&quot;&gt;&lt;code&gt;VirtualProtect()&lt;/code&gt;&lt;/a&gt; 
und &lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualfree&quot;&gt;&lt;code&gt;VirtualFree()&lt;/code&gt;&lt;/a&gt;
um Speicher mit den Protection-Flags &lt;code&gt;PAGE_EXECUTE_READWRITE&lt;/code&gt; auf die Nutzung als Stack vorzubereiten.&lt;/p&gt;

&lt;h3 id=&quot;zu-einem-neuen-callstack-springen&quot;&gt;Zu einem neuen Callstack springen&lt;/h3&gt;

&lt;p&gt;Hat man einen neuen Stack allokiert, muss man eigentlich nur noch das
Stack-Register auf dessen Ende setzen und kann dann eine weitere 
Funktion aufrufen, die in dem neuen Kontext laufen soll.&lt;br /&gt;
Die Funktion kann ganz ähnlich wie eine Thread-Entry-Funktion aussehen.&lt;/p&gt;

&lt;p&gt;Damit man beim Rücksprung aus der Funktion wieder zum alten Stack
zurückfinden kann, wird die Adresse des alten Stacks auf den
neuen Stack gepusht, um am Ende wieder zurückfinden zu können.&lt;/p&gt;

&lt;h4 id=&quot;x86-32-funktion-auf-neuem-stack-ausführen&quot;&gt;X86-32 Funktion auf neuem Stack ausführen&lt;/h4&gt;

&lt;div class=&quot;language-asm highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;; typedef void* (enty_function_t)(void* entry_param);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;mov eax, [stack_top_ptr]  ; stack-alloc-ptr + stack-size
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;mov ecx, [entry_param]
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;mov edx, [entry_function_ptr]
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;push ebp      ; backup old EBP on current stack
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;mov ebp, esp  ; backup of current stack
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;mov esp, eax  ; switch to new stack
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;push ebp      ; save old stack-ptr on new stack
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;push ecx      ; param for entry-function
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;call edx      ; call entry-function
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;add esp, 4    ; param cleanup
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;pop ebp       ; restore old stack-ptr
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;mov esp, ebp  ; switch back to old stack
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;pop ebp       ; restore old EBP
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h4 id=&quot;x86-64-funktion-auf-neuem-stack-ausführen&quot;&gt;X86-64 Funktion auf neuem Stack ausführen&lt;/h4&gt;

&lt;div class=&quot;language-asm highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;; typedef void* (enty_function_t)(void* entry_param);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;mov rax, [stack_top_ptr]
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;mov rcx, [entry_param]
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;mov rdx, [entry_function_ptr]
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;push rbp      ; backup old RBP on current stack
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;mov rbp, rsp  ; backup of current stack
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;mov rsp, rax  ; switch to new stack
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;and rsp, 0fffffffffffffff0h  ; align(16) new stack
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;sub rsp, 8    ; prepare call-alignment
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;push rbp      ; save old stack-ptr on new stack
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;sub rsp, 32   ; allocate x64 home space
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;call rdx      ; call function on foreign stack
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;add rsp, 32   ; deallocate x64 home space
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;pop rbp       ; restore old stack-ptr
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;mov rsp, rbp  ; switch back to old stack
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;pop rbp       ; restore old RBP
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h3 id=&quot;callstack-wechseln&quot;&gt;Callstack wechseln&lt;/h3&gt;

&lt;p&gt;Um dynamisch zwischen Callstacks wechseln zu können, braucht eine 
“Callstack-Snapshot” - Struktur, die einige &lt;code&gt;intptr_t&lt;/code&gt; bzw. &lt;code&gt;void*&lt;/code&gt; speichern 
kann, um Register des aktuellen Callstacks zu speichern. Und eben genau diese 
gesicherten Register werden dann von einem anderen Callstack-Snapshot geladen.&lt;/p&gt;

&lt;h4 id=&quot;x86-32-callstack-wechseln&quot;&gt;X86-32 Callstack wechseln&lt;/h4&gt;

&lt;div class=&quot;language-asm highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;;void* gate_win32_callstack_switch_x86(
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;;        gate_callstack_context_t* old_to_save, 
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;;        gate_callstack_context_t* new_to_load);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;gate_win32_callstack_switch_x86 PROC
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;  push ebp
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  mov ebp, esp
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;  mov ecx, [ebp + 8]  ; store-context
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  mov edx, [ebp + 12] ; load-context
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;  ;store current context to ptr in ECX
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;  mov DWORD PTR [ecx +  0], esp
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;  mov DWORD PTR [ecx +  4], ebp
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;  mov DWORD PTR [ecx +  8], ebx
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;  mov DWORD PTR [ecx + 12], esi
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;  mov DWORD PTR [ecx + 16], edi
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;  ;load new context from ptr in EDX
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  mov edi, DWORD PTR[edx + 16]
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n21&quot; name=&quot;n21&quot;&gt;21&lt;/a&gt;&lt;/span&gt;  mov esi, DWORD PTR[edx + 12]
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n22&quot; name=&quot;n22&quot;&gt;22&lt;/a&gt;&lt;/span&gt;  mov ebx, DWORD PTR[edx +  8]
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n23&quot; name=&quot;n23&quot;&gt;23&lt;/a&gt;&lt;/span&gt;  mov ebp, DWORD PTR[edx +  4]
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n24&quot; name=&quot;n24&quot;&gt;24&lt;/a&gt;&lt;/span&gt;  mov esp, DWORD PTR[edx +  0]
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n25&quot; name=&quot;n25&quot;&gt;25&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n26&quot; name=&quot;n26&quot;&gt;26&lt;/a&gt;&lt;/span&gt;  mov eax, 0    ; default-return: no switch
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n27&quot; name=&quot;n27&quot;&gt;27&lt;/a&gt;&lt;/span&gt;  cmp ecx, edx
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n28&quot; name=&quot;n28&quot;&gt;28&lt;/a&gt;&lt;/span&gt;  jz callstack_switch_x86_exit
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n29&quot; name=&quot;n29&quot;&gt;29&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n30&quot; name=&quot;n30&quot;&gt;30&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  ;if ecx != edx, we have switched, 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n31&quot; name=&quot;n31&quot;&gt;31&lt;/a&gt;&lt;/span&gt;  ;otherwise current context is only saved
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n32&quot; name=&quot;n32&quot;&gt;32&lt;/a&gt;&lt;/span&gt;  mov eax, edx  ; return: pointer to switched context
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n33&quot; name=&quot;n33&quot;&gt;33&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n34&quot; name=&quot;n34&quot;&gt;34&lt;/a&gt;&lt;/span&gt;callstack_switch_x86_exit:
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n35&quot; name=&quot;n35&quot;&gt;35&lt;/a&gt;&lt;/span&gt;  mov esp, ebp
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n36&quot; name=&quot;n36&quot;&gt;36&lt;/a&gt;&lt;/span&gt;  pop ebp
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n37&quot; name=&quot;n37&quot;&gt;37&lt;/a&gt;&lt;/span&gt;  ret
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n38&quot; name=&quot;n38&quot;&gt;38&lt;/a&gt;&lt;/span&gt;  ;EAX tells, if switch was performed
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n39&quot; name=&quot;n39&quot;&gt;39&lt;/a&gt;&lt;/span&gt;gate_win32_callstack_switch_x86 ENDP
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h4 id=&quot;x86-64-callstack-wechseln&quot;&gt;X86-64 Callstack wechseln&lt;/h4&gt;

&lt;div class=&quot;language-asm highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;;void* gate_win32_callstack_switch_x64(
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;;        gate_callstack_context_t* old_to_save, 
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;;        gate_callstack_context_t* new_to_load);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;gate_win32_callstack_switch_x64 PROC
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  push rbp
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;  mov rbp, rsp
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;  ; store current stack frame to ptr in RCX
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;  mov qword ptr [rcx +  0], rsp
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  mov qword ptr [rcx +  8], rbp
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;  mov qword ptr [rcx + 16], rbx
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;  mov qword ptr [rcx + 24], rsi
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;  mov qword ptr [rcx + 32], rdi
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;  mov qword ptr [rcx + 40], r12
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;  mov qword ptr [rcx + 48], r13
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;  mov qword ptr [rcx + 56], r14
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;  mov qword ptr [rcx + 64], r15
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;  ; load next stack frame from stored struct at ptr in RDX
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  mov r15, qword ptr [rdx + 64]
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n21&quot; name=&quot;n21&quot;&gt;21&lt;/a&gt;&lt;/span&gt;  mov r14, qword ptr [rdx + 56]
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n22&quot; name=&quot;n22&quot;&gt;22&lt;/a&gt;&lt;/span&gt;  mov r13, qword ptr [rdx + 48]
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n23&quot; name=&quot;n23&quot;&gt;23&lt;/a&gt;&lt;/span&gt;  mov r12, qword ptr [rdx + 40]
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n24&quot; name=&quot;n24&quot;&gt;24&lt;/a&gt;&lt;/span&gt;  mov rdi, qword ptr [rdx + 32]
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n25&quot; name=&quot;n25&quot;&gt;25&lt;/a&gt;&lt;/span&gt;  mov rsi, qword ptr [rdx + 24]
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n26&quot; name=&quot;n26&quot;&gt;26&lt;/a&gt;&lt;/span&gt;  mov rbx, qword ptr [rdx + 16]
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n27&quot; name=&quot;n27&quot;&gt;27&lt;/a&gt;&lt;/span&gt;  mov rbp, qword ptr [rdx +  8]
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n28&quot; name=&quot;n28&quot;&gt;28&lt;/a&gt;&lt;/span&gt;  mov rsp, qword ptr [rdx +  0]
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n29&quot; name=&quot;n29&quot;&gt;29&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n30&quot; name=&quot;n30&quot;&gt;30&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  mov rax, 0    ; default-return: no switch
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n31&quot; name=&quot;n31&quot;&gt;31&lt;/a&gt;&lt;/span&gt;  cmp rcx, rdx
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n32&quot; name=&quot;n32&quot;&gt;32&lt;/a&gt;&lt;/span&gt;  jz callstack_switch_x64_exit
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n33&quot; name=&quot;n33&quot;&gt;33&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n34&quot; name=&quot;n34&quot;&gt;34&lt;/a&gt;&lt;/span&gt;  ;if ecx != edx, we have switched, 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n35&quot; name=&quot;n35&quot;&gt;35&lt;/a&gt;&lt;/span&gt;  ;otherwise the context was only saved without a switch  
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n36&quot; name=&quot;n36&quot;&gt;36&lt;/a&gt;&lt;/span&gt;  mov rax, rdx  ; return: pointer to switched context
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n37&quot; name=&quot;n37&quot;&gt;37&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n38&quot; name=&quot;n38&quot;&gt;38&lt;/a&gt;&lt;/span&gt;callstack_switch_x64_exit:
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n39&quot; name=&quot;n39&quot;&gt;39&lt;/a&gt;&lt;/span&gt;  mov rsp, rbp
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n40&quot; name=&quot;n40&quot;&gt;40&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  pop rbp
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n41&quot; name=&quot;n41&quot;&gt;41&lt;/a&gt;&lt;/span&gt;  ret
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n42&quot; name=&quot;n42&quot;&gt;42&lt;/a&gt;&lt;/span&gt;  ;RAX tells, if switch was performed
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n43&quot; name=&quot;n43&quot;&gt;43&lt;/a&gt;&lt;/span&gt;gate_win32_callstack_switch_x64 ENDP
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Nachdem x64-EFI das gleiche ABI wie Windows X64 hat, konnte ich den 
Stack-Wechsel einfach unter Windows im &lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_C%2B%2B&quot;&gt;MSVC&lt;/a&gt;
Debugger testen und war fast erstaunt, dass das auch genau so funktioniert,
bevor ich die ersten Tests direkt als EFI-App erfolgreich ausführen konnte.&lt;br /&gt;
Interessant sind jetzt die noch nicht entdeckten Seiteneffekte.&lt;/p&gt;

&lt;p&gt;Meine aktuelle Koroutinen-Implementierung ist noch ein bisschen detailreicher
als hier beschrieben, da eine Routine beim &lt;code&gt;create()&lt;/code&gt; zu einem Dispatcher 
springt, der gleich wieder zum Aufrufer zurückwechselt und zur finale Routine
wird erst später wieder per &lt;code&gt;yield()&lt;/code&gt; hingewechselt.&lt;br /&gt;
Und obwohl oben im ASM-Code vorgesehen ist, dass man aus einem neuen Callstack
auch “einfach so” wieder zum Aufrufer zurückwechseln kann, ist das im
Endeffekt nicht vorgesehen, da der Aufrufer dann vielleicht nicht mehr 
existiert.&lt;br /&gt;
Man wechselt dann immer zu einer internen Scheduler-Routine, die alle anderen
verwaltet und eine “beendete” Routine deallokiert.&lt;/p&gt;

&lt;p&gt;Wie auch immer … hier geht es ja vorerst nur um das Konzept.&lt;br /&gt;
Und das scheint zumindest auf den ersten Blick zu funktionieren.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Ein frohes Neues...</title>
   <link href="https://www.opengate.at/blog/2022/01/happy-new-year/"/>
   <published>2022-01-01T12:00:00+01:00</published>
   <updated>2022-01-01T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2022/01/happy-new-year</id>
   <category term="general" />
   <summary type="text">Das neue Jahr ist angebrochen, doch stellt sich die Frage:


  Wohin soll die Reise gehen?


Doch beginnen wir am Anfang mit einem herzlichen:


  Prosit Neujahr!


</summary>
   <content type="html">&lt;p&gt;Das neue Jahr ist angebrochen, doch stellt sich die Frage:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Wohin soll die Reise gehen?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Doch beginnen wir am Anfang mit einem herzlichen:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Prosit Neujahr!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;In den letzten Tagen, als ich besorgt über die Welt nachdachte und dabei
wahllos ein paar Links folgte, bemerkte ich, dass neben all den vielen
Wirrungen auch viel Gutes auf dem Weg ist.&lt;/p&gt;

&lt;p&gt;Wissenschaft und Technik kann nicht alle Probleme unserer Zeit lösen,
doch sie kann einen entscheidenden Beitrag leisten.&lt;/p&gt;

&lt;h3 id=&quot;waldsterben-und-klimakrise&quot;&gt;Waldsterben und Klimakrise&lt;/h3&gt;

&lt;p&gt;Während meine Mutter immer noch traurig an die vielen abgeholzten erkranken
Wälder denkt, die sie seit ihrer Kindheit kannte, hat man in Afrika schon
lange erkannt bzw. wiederentdeckt, dass Bäume wahrlich “heilbringend” sind.&lt;/p&gt;

&lt;p&gt;Die steigenden Temperaturen haben auch Wüstengebiete vergrößert und daher 
arbeitet man in Afrika schon seit Jahren an der &lt;a href=&quot;https://de.wikipedia.org/wiki/Afrikas_Gr%C3%BCne_Mauer_im_Sahel&quot;&gt;grünen Mauer&lt;/a&gt;, 
pflanzt unentwegt Bäume und stellt fest, dass diese das Land heilen.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Chinas_Gr%C3%BCne_Mauer&quot;&gt;China beweist seit Jahrzehnten&lt;/a&gt;, 
dass man systematisch durch sinnvolle Bepflanzung karges Land in blühende 
Gärten verwandeln kann.&lt;br /&gt;
Und von Israel über Arabien bis nach Afrika arbeiten Ingenieure und 
Biotechniker an der Renaturierung von scheinbar wertlosen Böden.&lt;/p&gt;

&lt;p&gt;Und warum schaffen wir das in Europa nicht, sondern holzen weiter unsere
Wälder ab und zerstören mit Monokulturen die Böden?&lt;br /&gt;
Man darf die Natur eben nicht hirnlosen Kapitalmärkten überlassen, die 
nur billig Brandschatzen wollen, sondern braucht visionäre Ansichten.&lt;/p&gt;

&lt;h3 id=&quot;biologisch-verträgliche-elektrizität&quot;&gt;Biologisch-verträgliche Elektrizität&lt;/h3&gt;

&lt;p&gt;Ich bin nicht stolz auf meine &lt;a href=&quot;https://de.wikipedia.org/wiki/Lithium-Ionen-Akkumulator&quot;&gt;Lithium-Ionen-Zellen&lt;/a&gt;
und Akkupacks in Sachen Umwelt. Sie sind leider aktuell nur alternativlos.&lt;br /&gt;
Doch das ändert sich hoffentlich bald, denn anstatt mit vernichtenden Methoden
Lithium und Cobalt aus der Erde herauszubrechen, können wir in Zukunft unseren
Stromhunger mit 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Natrium-Ionen-Akkumulator&quot;&gt;Natrium-Ionen-Akkus&lt;/a&gt;
decken.&lt;/p&gt;

&lt;p&gt;Immer mehr Bereiche setzten zum Glück auf &lt;a href=&quot;https://de.wikipedia.org/wiki/Photovoltaik&quot;&gt;Photovoltaik&lt;/a&gt;
und nutzen die Kraft der Sonne anstatt sich mit CO2 oder radioaktiven Stoffen 
herumzuschlagen. Und mit einer Natrium-Batterie-Lösung als Puffer hätten wir 
endlich mal etwas gefunden, was aus breit verfügbaren Rohstoffen erzeugbar ist.&lt;/p&gt;

&lt;p&gt;Die Forschung geht munter weiter, was mich persönlich sehr freut.
Bleibt nur zu hoffen, dass auch hier die Menschen nicht an dumme 
Börsendiagramme denken, sondern an die Zukunft, wenn es um die Förderung
“der richtigen Technologien” geht.&lt;/p&gt;

&lt;h3 id=&quot;die-rückkehr-der-idealisten&quot;&gt;Die Rückkehr der Idealisten&lt;/h3&gt;

&lt;p&gt;Ich weiß nicht, ob Menschen wie &lt;a href=&quot;https://de.wikipedia.org/wiki/Elon_Musk&quot;&gt;Elon Musk&lt;/a&gt; 
“gute Absichten” haben oder nur für ihr Ego arbeiten. Tatsache ist jedoch, 
dass solche Idealisten mit entsprechender Finanzkraft “Gutes” ins Rollen 
bringen können.&lt;br /&gt;
Und vielleicht brauchen wir utopische Ziele wie den 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Bemannter_Marsflug&quot;&gt;Flug zum Mars&lt;/a&gt;
um die Forschung auf Trapp zu halten, wobei dann auch immer enorm hilfreiche 
Erkenntnisse für den Alltag abfallen.&lt;/p&gt;

&lt;p&gt;Doch wenn man sieht, wie angefangen mit 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Fridays_for_Future&quot;&gt;Fridays for Future&lt;/a&gt; immer
mehr Jugendliche wieder “etwas erreichen wollen”, während in den Jahrzehnten
zuvor alle nur den Status-Quo erhalten wollen, ja dann ist Optimismus
vorprogrammiert.&lt;/p&gt;

&lt;p&gt;Es wandelt sich nicht automatisch alles zum Guten, nur wenn Menschen plötzlich
Interesse für ein Thema verspüren, doch es ist allemal besser, wenn mehr
Personen für ihre Überzeugung einstehen, als dass man alles nur einem kleinen
Kreis von in der Regel überalterten Ewiggestrigen überlässt, die vor allem
an ihren Machtsesseln interessiert sind.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Das Jahr 2022 hat begonnen und trotz zahlreicher Krisen und Probleme, habe ich
ein ungewöhnlich positives Gefühl für die Zukunft, auch wenn sie rauer wird,
als in den Jahren zuvor.&lt;/p&gt;

&lt;p&gt;So lange ich nämlich sehen kann, dass an vielen Fronten für Veränderung und
Verbesserung gekämpft wird, bin ich zuversichtlich, dass wir auch die
“unguten” Seiten unserer Welt neu ausrichten werden.&lt;/p&gt;

&lt;p&gt;In diesem Sinne wünsche ich allen &lt;strong&gt;einen guten Start ins Jahr 2022&lt;/strong&gt;!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Das Jahr 2021</title>
   <link href="https://www.opengate.at/blog/2021/12/year-2021/"/>
   <published>2021-12-31T12:00:00+01:00</published>
   <updated>2021-12-31T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2021/12/year-2021</id>
   <category term="general" />
   <summary type="text">Ende 2020 haben wir gehofft, dass 2021 wieder “normal” werden würde.
Vielleicht hat genau der “Drang zur Normalität” eben diese verhindert.

Vieles hat sich geändert, damit alles gleich bleiben konnte und in
vielen Köpfen blieb trotzig alles gleich, damit sie sich von den 
anderen unterscheiden konnten.

Was ist also passiert in den letzten 365 Tagen?
</summary>
   <content type="html">&lt;p&gt;&lt;a href=&quot;/blog/2021/01/happy-new-year/&quot;&gt;Ende 2020&lt;/a&gt; haben wir gehofft, dass 2021 wieder “normal” werden würde.
Vielleicht hat genau der “Drang zur Normalität” eben diese verhindert.&lt;/p&gt;

&lt;p&gt;Vieles hat sich geändert, damit alles gleich bleiben konnte und in
vielen Köpfen blieb trotzig alles gleich, damit sie sich von den 
anderen unterscheiden konnten.&lt;/p&gt;

&lt;p&gt;Was ist also passiert in den letzten 365 Tagen?
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;das-leben-wurde-teurer&quot;&gt;Das Leben wurde teurer&lt;/h3&gt;

&lt;p&gt;Jahre lang hat mein großes Putenschnitzel mit Beilage (Salat oder Pommes) 
8,5 Euro zum Mitnehmen im Schnitzelladen an der Ecke gekostet. Doch seit 
Herbst wird mit 9,50 abgerechnet.&lt;br /&gt;
Die &lt;a href=&quot;https://de.wikipedia.org/wiki/Wien_Energie&quot;&gt;Wien-Energie&lt;/a&gt; erhöht zum 
Jahreswechsel die Strompreise von 9,9 Cent pro Kilowattstunde auf 14,5 Cent.&lt;br /&gt;
Und bei &lt;a href=&quot;https://de.wikipedia.org/wiki/AliExpress&quot;&gt;AliExpress&lt;/a&gt; sind die Preise 
auch um bis zu 50% gestiegen und da sind die Zusatzkosten beim Versand noch 
gar nicht eingerechnet. 100 Euro kostete mein &lt;a href=&quot;/blog/2021/05/rock-pi-x/&quot;&gt;RockPI-X&lt;/a&gt;
im letzten Mai, nun ist er unter 150 Euro gar nicht mehr zu bekommen.&lt;/p&gt;

&lt;p&gt;Ich habe das Glück, dass ich mit meinem Einkommen auskommen kann, doch was
machen meine Mitmenschen, die wegen der &lt;a href=&quot;https://de.wikipedia.org/wiki/Pandemie&quot;&gt;Pandemie&lt;/a&gt;
keinen Job mehr haben oder die in einem schlechteren Dienstverhältnis stehen?&lt;/p&gt;

&lt;h3 id=&quot;divergenz-der-gesellschaft&quot;&gt;Divergenz der Gesellschaft&lt;/h3&gt;

&lt;p&gt;Wenn nun auch im eigenen Bekanntenkreis die “Interpretation der Wahrheit”
immer größere Kreise zieht, muss ich mir echt Sorgen machen.&lt;br /&gt;
Sieht man im Fernsehen 5 betroffene Ärzte, die von der totalen Überfüllung
ihrer Abteilung berichten, hallt es sofort durch den Raum:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Typisch! Die wurden alle gekauft, damit sie Lügen verbreiten um uns
zur Impfung zu zwingen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;!! W-T-F !!&lt;/strong&gt; Wo lebe ich eigentlich?&lt;br /&gt;
Obwohl es absolut nicht meine Meinung ist, kann ich es verstehen, wenn 
Menschen gegen eine Impfpflicht demonstrieren gehen. Und damit meine ich 
nicht jene &lt;a href=&quot;https://de.wikipedia.org/wiki/Identit%C3%A4re_Bewegung_%C3%96sterreich&quot;&gt;Nazis und Identitären&lt;/a&gt;, 
die nur darauf pochen Krawall zu machen, sondern ich meine zu Recht besorgte Mitbürger.&lt;br /&gt;
Aber seit dem finstersten Mittelalter sind anständige Wissenschaftler,
Ärzte und Forscher nicht mehr so irrational beschimpft und verteufelt worden,
wie wir es aktuell erleben.&lt;/p&gt;

&lt;p&gt;Ich bin hier Zeuge einer fatalen geistigen Rückentwicklung der Gesellschaft
geworden, die mich offen gesagt schwer beunruhigt.&lt;br /&gt;
Selbstverständlich hat die Regierung enorm viele Fehler gemacht und auch ich
bin angepisst in Sachen Datenschutz und Chaos bei den Behörden … aber das 
ist doch kein Grund gegen den Staat aufzumarschieren und die Wissenschaft als
Ketzer an den Pranger zu stellen, nur weil sie uns die Wahrheit sagen,
die manche einfach nicht hören wollen.&lt;/p&gt;

&lt;p&gt;Und während einige im Blutrausch nach einem Bürgerkrieg verlangen (ja, das 
habe ich echt schon auf den Straßen vernehmen müssen), ist eine weitere
sehr liebe “Oma” aus der Nachbarschaft mit &lt;a href=&quot;https://de.wikipedia.org/wiki/COVID-19&quot;&gt;COVID-19&lt;/a&gt; 
verstorben. Wir waren nicht verwandt, aber ich habe sie trotzdem sehr gemocht
und vielleicht hätte ich sie noch ein paar Jahre länger erleben dürfen, hätte
das Virus ihrem in die Jahre gekommenen Körper nicht so zugesetzt.&lt;/p&gt;

&lt;p&gt;Ich gebe niemandem persönlich die Schuld an dem Tod. Aber ich bin froh
sagen zu können, dass ich durch meine Impfung die Gefahr reduzieren konnte.
Und ich wünsche mir, dass auch andere Mitbürger diesen kleinen Sticht mutig
hinnehmen, und dass wir aufhören alles nur aus Trotzigkeit abzulehnen.&lt;/p&gt;

&lt;h3 id=&quot;rückkehr-des-desktops&quot;&gt;Rückkehr des Desktops&lt;/h3&gt;

&lt;p&gt;Weil &lt;a href=&quot;https://de.wikipedia.org/wiki/Smartphone&quot;&gt;Smartphones&lt;/a&gt; für mich der 
Inbegriff der gesellschaftlichen Verblödung sind, und deren Technik nur wie
leichte Drogen die Menschen von der Realität ablenken, freue ich mich, dass 
Homeoffice und Co. dem PC eine Renaissance beschafft haben.&lt;br /&gt;
Man nutzt die Technik endlich wieder “zum Arbeiten” und zum Erreichen von 
Zielen und nicht um “die Zeit totzuschlagen”.&lt;/p&gt;

&lt;p&gt;Und unsere Jugend lernt auch immer mehr, die Technik zur Überwindung von 
Grenzen einzusetzen. Leider nicht alle, doch es ist ein Anfang.&lt;br /&gt;
Es sind zwar nicht alle Schulen auf dem neuesten Stand, aber es freut mich zu
hören, dass nun auch unsere Lehrkräfte notgedrungen mehr und mehr Technik 
ordentlich einsetzen.&lt;/p&gt;

&lt;p&gt;Natürlich frage ich mich: “Warum nicht schon früher?”, denn diese Skills 
hätten wir uns alle schon seit dem Jahr 2000 aneignen können, aber immerhin
geht es jetzt ordentlich los.&lt;/p&gt;

&lt;h3 id=&quot;-und-der-blog&quot;&gt;… und der Blog?&lt;/h3&gt;

&lt;p&gt;Die &lt;a href=&quot;https://de.wikipedia.org/wiki/Google_Search_Console&quot;&gt;Google Search Console&lt;/a&gt; 
verrät, welche Anfragen zu einem Webspace hingeleitet wurden und ich war 
äußerst überrascht, dass der Begriff “Peter Regung Spiderman englisch” zu 
meinem Beitrag zu “Far-From-Home” die häufigste Suchanfrage war, nur weil ich 
da “Peter Regung == Peter Tingle” aufgenommen hatte.&lt;br /&gt;
Doch auch andere Suchbegriffe zu &lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B&quot;&gt;C++&lt;/a&gt;, 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_PE&quot;&gt;WinPE&lt;/a&gt; und Hardware wie 
dem Lichee Pi tauchen dort auf.&lt;/p&gt;

&lt;p&gt;Zumindest weiß ich jetzt aber, dass dieses Online-Tagebuch nicht 
ausschließlich nur für mich selbst vorhanden ist und dass zumindest ein paar
Menschen da draußen etwas Nützliches daraus ableiten konnten.&lt;/p&gt;

&lt;p&gt;Und ob gleich das am Ende für mich keine wirkliche Rolle spielt, so ist es
dennoch ein weiterer Motivationsfaktor, wöchentlich das eine oder andere
Highlight hier zu verschriftlichen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;2021 war leider wieder ein Jahr der Verwirrungen und Verwerfungen.
Und dennoch haben wir im Endeffekt alles gut überstanden.&lt;br /&gt;
Wir haben zu essen und zu trinken, und wenn wir ein bisschen besonnener mit 
unseren Wünschen und Forderungen umgehen, werden wir feststellen, dass wir
weiter alles tun können, was uns voranbringt.&lt;br /&gt;
Jahrtausende haben Menschen glücklich gelebt, ohne jedes Quartal in ein 
anderes Land fliegen zu können, um damit angeben zu können.&lt;br /&gt;
Wir werden es auch mal aushalten, ein Jahr lang die Schönheiten unserer 
direkten Umgebung vorrangig genießen zu dürfen.&lt;/p&gt;

&lt;p&gt;Ich wünsche jedenfalls allen einen guten Rutsch ins neue Jahr,
und hoffe darauf, dass wir wieder näher zusammen kommen, im geistigen 
und gesellschaftlichen Sinne, und dass wir dabei trotzdem den nötigen
Abstand einhalten, um die Älteren und Schwächeren vor Krankheit zu schützen.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Corona Impfung - Teil 3</title>
   <link href="https://www.opengate.at/blog/2021/12/vaccination-3/"/>
   <published>2021-12-30T12:00:00+01:00</published>
   <updated>2021-12-30T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2021/12/vaccination-3</id>
   <category term="general" />
   <summary type="text">Während andere sich bei boost.org die aktuellen 
Version 1.78 holen um ihre C++ 
Programme aufzufrischen, war ich das dritte Mal im Austria-Center um 
meinen COVID-19 Schutz “boosten” zu lassen.

Fast könnte man sagen:


  Same procedure as last year.


… doch noch ist das Jahr nicht vorbei.

</summary>
   <content type="html">&lt;p&gt;Während andere sich bei &lt;a href=&quot;https://boost.org&quot;&gt;boost.org&lt;/a&gt; die aktuellen 
Version 1.78 holen um ihre &lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B&quot;&gt;C++&lt;/a&gt; 
Programme aufzufrischen, war ich das dritte Mal im Austria-Center um 
meinen COVID-19 Schutz “boosten” zu lassen.&lt;/p&gt;

&lt;p&gt;Fast könnte man sagen:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Same procedure as last year.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;… doch noch ist das Jahr nicht vorbei.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;anmeldung&quot;&gt;Anmeldung&lt;/h3&gt;

&lt;p&gt;Wieder mal meine Lieblingsaussage:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Manche sagen, Österreich sei in Sachen Digitalisierung noch
im Mittelalter.&lt;br /&gt;
Ich sage euch: Das stimmt nicht!&lt;br /&gt;
So weit sind wir noch lange nicht!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ok, vielleicht übertreibe ich ein bisschen, aber aus meiner kritischen Sicht
funktionieren alle “analogen” Schritte der Impfung (vor allem in 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Wien&quot;&gt;Wien&lt;/a&gt;) hervorragend, während alles, was 
man “online” tun können soll bzw. sollte, einfach schlecht gelöst ist.&lt;/p&gt;

&lt;p&gt;Irgendwann in den letzten Monaten wurde offenbar das Wiener Impfportal 
“geändert”. Damit brechen nicht nur Links, die man sich bei der letzten 
Anmeldung gespeichert hat, sondern auch der Login schwankt zwischen der 
Übernahme der alten Daten aus der früheren Registrierung und einer 
Neuregistrierung.&lt;/p&gt;

&lt;p&gt;Zuerst wird man mit Infos verwirrt, dass man der erneuten Datenerfassung
zustimmen soll um den Login im neuen Portal einzurichten und dann läuft 
man in eine 404 Seite.&lt;br /&gt;
Ich dachte anfangs echt, ich wäre auf einen Phishing-Versuch hereingefallen.
Doch bei einem weiteren Loginversuch, war man plötzlich “wieder im System”
eingeloggt.&lt;/p&gt;

&lt;p&gt;Hat man sich dann seinen Impftermin reserviert, bekommt man eine Liste von 
dem, was man mitnehmen soll. Also Impfticket (bei der Reservierung erhalten),
Impfpass, Ausweis und e-Card. Und: Die Einwilligungserklärung.&lt;/p&gt;

&lt;p&gt;Im früheren Impfportal war die verlinkt. Diesmal habe ich sie nicht gefunden.
Zwar kann man die Einwilligung auch vor Ort ausfüllen, aber warum?
Google hingegen findet bei einer Suche das benötigte PDF im 
&lt;code&gt;wp-content/uploads&lt;/code&gt; Folder.&lt;/p&gt;

&lt;p&gt;Also echt jetzt! Was soll das?&lt;br /&gt;
Kids von heute coden sich über’s Wochenende Itemshops für ihre 
Lieblingsspieleerweiterungen mit Userverwaltung und Bezahlservice zusammen 
und die “Profi-Softwareabteilung” von Österreichs größter Stadt scheitert am 
Anfügen eines Wordpress-Links an E-Mails oder auf der Hauptseite?&lt;/p&gt;

&lt;p&gt;Ich bin einfach nur enttäuscht.&lt;/p&gt;

&lt;h3 id=&quot;impfung-mit-zertifikat&quot;&gt;Impfung mit Zertifikat&lt;/h3&gt;

&lt;p&gt;Am &lt;a href=&quot;https://de.wikipedia.org/wiki/Austria_Center_Vienna&quot;&gt;Austria Center&lt;/a&gt; 
angekommen war die Prozedur genau so wie bei meinen Impfungen im Sommer. 
Nur dass ich diesmal ins Untergeschoss geleitet wurde, wo die Datenprüfung, 
das medizinische Gespräch, die Impfung und die Wartepause genau so stattfand, 
wie zuletzt.&lt;/p&gt;

&lt;p&gt;Ich vermutete, dass ich ziemlich alleine geimpft werden würde, wegen des
Termins mitten in den Weihnachtsfeiertagen, doch nein. Es war zwar weniger 
los, als im Hochsommer, doch permanent tröpfelten neue Personen durch die
Registrierungstische und Impfkabinen hindurch.&lt;/p&gt;

&lt;p&gt;Wegen der (aus meiner Sicht “dummen”) Entscheidung, dass nach Juni keine
Zertifikate automatisch an Geimpfte ausgestellt wurden, war ich das letzte
halbe Jahr auf meinen Impfpass angewiesen, den ich selbstverständlich die
3 oder 4 mal, wo ich ihn gebraucht hätte, nicht dabei hatte.&lt;br /&gt;
Denn in der Kantine meiner Firma darf man seit November ja nicht mal 
mehr das Mittagessen in der Box abholen, ohne dass man auf seinen Impfstatus
geprüft wird, während es im Supermarkt nebenan egal war und ist, ob man
überhaupt geimpft ist. (Echt bescheuert diese Politik!)&lt;/p&gt;

&lt;p&gt;Na jedenfalls gab es im Nebengebäude des Impfzentrums eine Büroeinrichtung,
die einem ein Zertifikat ausdruckt.
Dort musste ich etwa 15 Minuten in der Schlage stehen, bis mir einer
der dortigen Mitarbeiter ein Zertifikatsblatt erstellen und aushändigen
konnte.&lt;/p&gt;

&lt;p&gt;Nun kann ich also entweder meinen Impfpass oder den A4-Wisch nutzen, 
wenn ich mal ins Gasthaus gehen möchte.&lt;br /&gt;
&lt;img src=&quot;/blog/assets/img/vaccination-certificate-a4.gif&quot; alt=&quot;Vaccination certificate document&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Ich habe das Blatt eingescannt und nun kann ich es auch auf einem 
Nicht-Google-Mobiltelefon mitführen.&lt;br /&gt;
Falls - und das werde ich in den nächsten Tagen ausprobieren - der 
Scan “einfach so” akzeptiert wird, dann folgt meine nächste Frage
auf dem Fuße:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Wieso zur Hölle wird nicht jedem Mitbürger das 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Portable_Document_Format&quot;&gt;PDF&lt;/a&gt; 
per e-Mail zugestellt?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Anstatt dessen legt man diese “sensiblen” Daten in die exklusiven Hände
von Android-Apps, wo sie nur gemeinsam mit Werbeangeboten von 
Influencer-Hautcreme und Seminaren zu alternativer Magie abgerufen 
werden können.&lt;/p&gt;

&lt;h3 id=&quot;lob-an-alle-impf-teams&quot;&gt;Lob an alle Impf-Teams&lt;/h3&gt;

&lt;p&gt;Den fleißigen Bienchen in unseren Impfzentren muss ich aber erneut meinen Dank
und meine Bewunderung aussprechen. Denn ihr Service war schnell, zielgerichtet
und professionell.&lt;/p&gt;

&lt;p&gt;Sie sitzen dort (freiwillig) auch an den Feiertagen, bekommen vermutlich nicht
immer nur freundliche Gesichter zu sehen und sind dennoch stets hilfsbereit 
und bewahren ganz nebenbei unsere Gesundheit.&lt;/p&gt;

&lt;p&gt;Ich glaube nicht, dass die Gesellschaft (also wir alle) den Einsatz dieser
guten Geister entsprechend würdigen. Natürlich bin ich nicht der einzige,
der ihre Leistung schätzt, doch wenn man sich ansieht, wie aggressiv manche
Mitmenschen ihren selbst gezüchteten Hass genau auf diejenigen richten,
die nichts anderes tun als zu helfen, dann merkt man erst, wie unglaublich
wertvoll alle Arbeiten im medizinischen Bereich heute sind.&lt;/p&gt;

&lt;p&gt;Denn es ist nicht nur die professionelle Arbeit alleine, die uns Ärzte, 
Pflege- und Impfpersonal bis hin zum Zivildiener bereitstellen,
sondern es ist vor allem der besonnene und geduldige Umgang mit uns,
trotz vieler Störklänge aus der Bevölkerung, der meinen Respekt verdient.&lt;/p&gt;

&lt;p&gt;Und deshalb möchte ich hier nochmal ganz deutlich dokumentieren:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Danke an das gesamte medizinische Personal!&lt;br /&gt;
Ihr seid unsere Helden.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;moderna-booster-mit-erwarteter-reaktion&quot;&gt;Moderna Booster mit erwarteter Reaktion&lt;/h3&gt;

&lt;p&gt;Nun, die erste Impfung mit &lt;a href=&quot;https://de.wikipedia.org/wiki/COVID-19#Schutzimpfungen&quot;&gt;Moderna&lt;/a&gt; 
habe ich gar nicht gespürt, dafür hat mich die zweite unerwartet hart 
erwischt. Das lag vielleicht auch daran, dass ich dachte, ganz normal 
weiterarbeiten zu können.&lt;/p&gt;

&lt;p&gt;Auch für meinen 3. Impfstich waren Reaktionen im Sinne eines 24-48 stündigen
Krankheitgefühls prognostiziert.&lt;/p&gt;

&lt;p&gt;Ein paar Stunden nach der Impfung kamen dann Schlappheit und Kopfschmerzen auf
mich zu. Doch, damit hatte ich gerechnet und mich vorsorglich ins Bett gelegt.
Ich kann zwar nicht sagen, dass ich besonders gut geschlafen hätte, weil ich 
alle paar Stunden wieder aufgewacht bin, aber im Endeffekt habe ich die
Impfreaktion großteils “verschlafen”.&lt;/p&gt;

&lt;p&gt;Als ich am Folgetag dann wieder aufstand, waren die Kopfschmerzen noch spürbar
da, doch bereits eine Stunde später waren sie fast gänzlich verflogen.
Und am Abend konnte ich bereits wieder mit Kopfhörern und Musik durchs Zimmer
steppen, als wäre nichts gewesen.&lt;/p&gt;

&lt;p&gt;Kurz gesagt: Bis 24 Stunden nach der Impfung war Ruhe angesagt, danach ging der
Alltag wie gewohnt weiter.&lt;/p&gt;

&lt;p&gt;Es ist mir also weiter ein Rätsel, warum manche Menschen so unvernünftig sind,
und lieber wochenlang hustend und röchelnd im Fieberbett liegen wollen, nur
um sich trotzig ein Stichlein zu ersparen und damit nebenbei ein ungutes
Virus weiter verbreiten.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Die 3. Impfung ist erledigt und mir geht’s gut. Sehr gut.&lt;/p&gt;

&lt;p&gt;Jetzt hoffe ich weiter darauf, dass sich auch der Rest der Bevölkerung 
impfen lässt und damit dem Virus das Wasser abgräbt.
Damit wir eben nicht noch weitere Lockdowns brauchen und die ehrenwerten
Mitarbeiter in den Krankenhäusern die Entlastung erhalten, die sie schon
so lange redlich verdient haben.&lt;/p&gt;

&lt;h3 id=&quot;nachtrag&quot;&gt;Nachtrag&lt;/h3&gt;

&lt;p&gt;Falls irgend jemand aus meinem gescannten und hier hochgeladenen 
Zertifikats-Dokument den Schlüssel aus den verbliebenen Pixeln des QR-Codes 
wiederherstellen kann, möge mir derjenige bitte den Quellcode zum 
Algorithmus zukommen lassen. Danke! ;)&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Windows X64 Calling Convention</title>
   <link href="https://www.opengate.at/blog/2021/12/asm-x64/"/>
   <published>2021-12-26T12:00:00+01:00</published>
   <updated>2021-12-26T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2021/12/asm-x64</id>
   <category term="devel" />
   <summary type="text">Nach vielen Jahren komme ich endlich dazu: 
X64 Assembler.

Sich selbst ein paar “Features” hinzucoden ist ja kein Problem,
doch wenn ich mit C 
und C mit mir reden will, wird die Einhaltung der 
X64 Calling Convention
essentiell.
</summary>
   <content type="html">&lt;p&gt;Nach vielen Jahren komme ich endlich dazu: 
&lt;em&gt;X64 &lt;a href=&quot;https://de.wikipedia.org/wiki/Assemblersprache&quot;&gt;Assembler&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Sich selbst ein paar “Features” hinzucoden ist ja kein Problem,
doch wenn ich &lt;a href=&quot;https://de.wikipedia.org/wiki/C_(Programmiersprache)&quot;&gt;mit C&lt;/a&gt; 
und C mit mir reden will, wird die Einhaltung der 
&lt;a href=&quot;https://en.wikipedia.org/wiki/X86_calling_conventions#x86-64_calling_conventions&quot;&gt;X64 Calling Convention&lt;/a&gt;
essentiell.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;vorgeschichte-x86-32&quot;&gt;Vorgeschichte: x86-32&lt;/h3&gt;

&lt;p&gt;Im 32-Bit Modus war die Welt theoretisch kompliziert, doch praktisch dann 
wieder einfach. Es gab unter &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows&quot;&gt;Windows&lt;/a&gt; 
2 Aufruf-Konventionen, nämlich &lt;a href=&quot;https://de.wikipedia.org/wiki/Aufrufkonvention#cdecl&quot;&gt;&lt;code&gt;cdecl&lt;/code&gt;&lt;/a&gt; 
und &lt;a href=&quot;https://de.wikipedia.org/wiki/Aufrufkonvention#stdcall&quot;&gt;&lt;code&gt;stdcall&lt;/code&gt;&lt;/a&gt; und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt; gab sich generell nur mit 
&lt;code&gt;cdecl&lt;/code&gt; zufrieden.&lt;/p&gt;

&lt;p&gt;Alle Parameter einer Funktion wurden auf den Stack gepusht und innerhalb der
Funktion wurde dann der Frame-Pointer (Base-Pointer, bzw. &lt;code&gt;BP&lt;/code&gt; oder &lt;code&gt;EBP&lt;/code&gt;)
auf den Stack-Pointer (&lt;code&gt;SP&lt;/code&gt; oder &lt;code&gt;ESP&lt;/code&gt;) gesetzt und über diesen konnte man 
dann mit &lt;code&gt;[EBP + offset]&lt;/code&gt; auf übergebene Parameter und &lt;code&gt;[EBP - offset]&lt;/code&gt; auf
lokale Variablen am Stack zugreifen.
Ein paar Register mussten zusätzlich auf den Stack gepusht werden, weil sie
als &lt;code&gt;non-volatile&lt;/code&gt; gelten und aus der Sicht von außen nicht verändert werden
durften: &lt;code&gt;EBX&lt;/code&gt;, &lt;code&gt;ESI&lt;/code&gt; und &lt;code&gt;EDI&lt;/code&gt;.&lt;br /&gt;
Und am Ende wird &lt;code&gt;ESP&lt;/code&gt; wieder auf den &lt;code&gt;EBP&lt;/code&gt; zurückgesetzt und von dort
kann wieder das alte Stackframe zurück ge-POP-t werden.&lt;/p&gt;

&lt;p&gt;In einer &lt;code&gt;cdecl&lt;/code&gt; x86-32 Funktion sieht der Maschinen-Code &lt;em&gt;ohne Optimierungen&lt;/em&gt; 
so etwa wie folgt aus:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;int32_t foo(int32_t a, int32_t b, int32_t c)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;// PROLOG:&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;// asm PUSH EBP     ; save old stack frame&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;// asm MOV EBP, ESP ; base for new stack frame&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;  int32_t x;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  int32_t y;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;// asm SUB ESP, 8   ; alloc local stack for 2 ints (x, y)&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  x = a + b;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;// asm MOV EAX, [EBP + 8]   ; load a&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;// asm ADD EAX, [EBP + 12]  ; add b&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;// asm MOV [EBP - 4], EAX   ; store x&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;  y = x + c;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;// asm MOV EAX, [EBP - 4]   ; load x&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;// asm ADD EAX, [EBP + 16]  ; add c&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;// asm MOV [EBP - 8], EAX   ; save y&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; y;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n21&quot; name=&quot;n21&quot;&gt;21&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;// asm MOV EAX, [EBP - 8]   ; load y as return value&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n22&quot; name=&quot;n22&quot;&gt;22&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n23&quot; name=&quot;n23&quot;&gt;23&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;// EPILOG:&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n24&quot; name=&quot;n24&quot;&gt;24&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;// asm MOV ESP, EBP ; dealloc local stack&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n25&quot; name=&quot;n25&quot;&gt;25&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;// asm POP EBP      ; restore old stack frame&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n26&quot; name=&quot;n26&quot;&gt;26&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;// asm RET&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n27&quot; name=&quot;n27&quot;&gt;27&lt;/a&gt;&lt;/span&gt;}
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n28&quot; name=&quot;n28&quot;&gt;28&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n29&quot; name=&quot;n29&quot;&gt;29&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; main()
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n30&quot; name=&quot;n30&quot;&gt;30&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n31&quot; name=&quot;n31&quot;&gt;31&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;/*...*/&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n32&quot; name=&quot;n32&quot;&gt;32&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n33&quot; name=&quot;n33&quot;&gt;33&lt;/a&gt;&lt;/span&gt;  int32_t result = foo(&lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;, &lt;span style=&quot;color:#00D&quot;&gt;2&lt;/span&gt;, &lt;span style=&quot;color:#00D&quot;&gt;3&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n34&quot; name=&quot;n34&quot;&gt;34&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;// asm PUSH 3      ; add c to stack&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n35&quot; name=&quot;n35&quot;&gt;35&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;// asm PUSH 2      ; add b to stack&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n36&quot; name=&quot;n36&quot;&gt;36&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;// asm PUSH 1      ; add a to stack&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n37&quot; name=&quot;n37&quot;&gt;37&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;// asm CALL foo    ; call __cdecl function&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n38&quot; name=&quot;n38&quot;&gt;38&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;// asm ADD ESP, 12 ; remove a,b,c from stack&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n39&quot; name=&quot;n39&quot;&gt;39&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;// asm MOV [result], EAX&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n40&quot; name=&quot;n40&quot;&gt;40&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n41&quot; name=&quot;n41&quot;&gt;41&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;/*...*/&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n42&quot; name=&quot;n42&quot;&gt;42&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Innerhalb von &lt;code&gt;foo&lt;/code&gt; kann man über &lt;code&gt;EBP&lt;/code&gt; wie folgt adressieren:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;EBP Offset&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Element&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Beschreibung&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;EBP + 16&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;c&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;3. Parameter (zuerst gepusht)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;EBP + 12&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;b&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;2. Parameter&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;EBP + 8&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;a&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;1. Parameter (zuletzt gepusht)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt; &lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt; &lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Stack-Frame Grenze&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;EBP + 4&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;RET Adresse&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Rücksprung Adresse zum Aufrufer&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;EBP + 0&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;EBP Backup&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Gesicherter EBP des Aufrufers&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;EBP - 4&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;x&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;1. lokale Variable&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;EBP - 8&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;y&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;2. lokale Variable&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Vereinfacht lautet die Regel:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;EBP + 8 + arg_index * 4&lt;/code&gt; greift auf Funktionsparameter zu.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;EBP - 4 - var_index * 4&lt;/code&gt; greift auf lokale Variablen zu.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Andere Ausrichtungen wie für &lt;code&gt;double&lt;/code&gt; oder &lt;code&gt;int64&lt;/code&gt; verändern die Formel zwar,
aber hier geht es ja nur um die abstrakte Theorie.&lt;/p&gt;

&lt;h3 id=&quot;windows-x64-mit-home-space-shadow-space-&quot;&gt;Windows-X64 mit Home-Space, Shadow-Space …&lt;/h3&gt;

&lt;p&gt;Obwohl möglich, sieht die X64 Aufrufkonvention anders aus, als für X86-32,
denn hier wollen wir für den schnelleren Datenaustausch einige Parameter über 
Register laufen lassen.&lt;/p&gt;

&lt;p&gt;Alle Parameter kleiner 64 Bits werden auf 64 Bits ausgedehnt, und alles was
größer ist, wird per Pointer übergeben.&lt;/p&gt;

&lt;p&gt;Unter Windows werden daher die ersten 4 Parameter in &lt;code&gt;RCX&lt;/code&gt;, &lt;code&gt;RDX&lt;/code&gt;, &lt;code&gt;R8&lt;/code&gt; und 
&lt;code&gt;R9&lt;/code&gt; übergeben und der Rest auf den Stack ge-PUSH-t.&lt;br /&gt;
Ein Spezialfall sind &lt;code&gt;float&lt;/code&gt; und &lt;code&gt;double&lt;/code&gt; Werte, die in den &lt;code&gt;xmm&lt;/code&gt; Registern 
übergeben werden (was ich jetzt hier mal still und heimlich weglasse).&lt;/p&gt;

&lt;p&gt;Für &lt;code&gt;variadic/vararg&lt;/code&gt; Funktionen wäre diese Konvention schlecht, weil die 
über zusammenhängende Speicher funktionieren und keine Register kennen.&lt;br /&gt;
Und dafür gibt es einen interessanten Kompromiss:&lt;br /&gt;
Den &lt;em&gt;Home-Space&lt;/em&gt;, auch &lt;em&gt;Shadow-Space&lt;/em&gt; genannt.&lt;/p&gt;

&lt;p&gt;Man allokiert (== reserviert == überspringt) am Stack genau den Speicher, den
die Register der Parameter brauchen würden und überlässt es der aufgerufenen
Funktion, diesen Speicher zu nutzen.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Die Funktion könnte die 4 Parameter-Register in den Home-Space schreiben
und hätte dann ein Layout-Äquivalent zu 32-Bit &lt;code&gt;cdecl&lt;/code&gt;, und &lt;code&gt;stdarg.h&lt;/code&gt; 
Makros würden 1:1 damit funktionieren.&lt;/li&gt;
  &lt;li&gt;Die Funktion kann den Home-Space aber auch ignorieren und nur mit den
Registern arbeiten.&lt;/li&gt;
  &lt;li&gt;Und die Funktion kann die vier 64 Bit Slots des Home-Space auch nutzen um 
andere Daten dort abzulegen, quasi lokale Variablen, die aber außerhalb 
des Stackframes liegen.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;kein-formaler-frame-pointer&quot;&gt;Kein formaler Frame-Pointer&lt;/h4&gt;

&lt;p&gt;In der 32-Bit Welt zeigt das &lt;code&gt;EBP&lt;/code&gt; Register immer genau auf die Adresse, wo 
das &lt;code&gt;EBP&lt;/code&gt; Register des Aufrufers gesichert wurde und 4 Bytes darüber liegt die
Rücksprungadresse zum Aufrufercode.&lt;br /&gt;
So kann man “standardisiert” über &lt;code&gt;EBP&lt;/code&gt; die Aufrufkette rückverfolgen
(so lange nicht das Feature “Omit Frame Pointers” (&lt;code&gt;/Oy&lt;/code&gt;) aktiviert ist).&lt;/p&gt;

&lt;p&gt;Das 64 Bit ABI kennt keinen fixen Frame-Pointer. Es ist nicht verboten &lt;code&gt;RBP&lt;/code&gt;
weiter so zu benutzen, aber der C/C++ Compiler generiert Parameter und lokale 
Variablen-Zugriffe häufig mit &lt;code&gt;[RSP + Offset]&lt;/code&gt;.&lt;br /&gt;
Das ist zwar sehr effizient und kann vom Compiler hoch optimiert werden, 
aber macht es verdammt schwer nachzuvollziehen, was wirklich abgeht, da alles
relativ zum aktuellen Stack-Pointer passiert.&lt;/p&gt;

&lt;p&gt;Will man &lt;code&gt;RBP&lt;/code&gt; statt &lt;code&gt;RSP&lt;/code&gt; nutzen, so wird empfohlen, &lt;code&gt;RBP&lt;/code&gt; zu sichern und
auf RSP zeigen zu lassen. Letztendlich ist es dann aber auch schon egal, ob
man &lt;code&gt;RBP + offset&lt;/code&gt; oder &lt;code&gt;RSP + offset&lt;/code&gt; schreibt.&lt;/p&gt;

&lt;h4 id=&quot;sicherung-von-nicht-flüchtigen-registern&quot;&gt;Sicherung von “nicht-flüchtigen” Registern&lt;/h4&gt;

&lt;p&gt;Folgende Register gelten unter x64 als “non-volatile” (also “nicht-flüchtig) 
und müssen gesichert werden, bevor man sie verändern darf:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;RBP, RBX, RSI, RDI, R12, R13, R14, R15&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Man &lt;code&gt;PUSH&lt;/code&gt;t sie daher am Beginn der Funktion auf den Stack und holt sie
am Ende vor dem &lt;code&gt;RET&lt;/code&gt; mit &lt;code&gt;POP&lt;/code&gt; wieder zurück.
Wenn man die Register nicht anfasst, braucht man sie natürlich auch nicht
sichern.&lt;/p&gt;

&lt;h4 id=&quot;verflixtes-16-byte-alignment&quot;&gt;Verflixtes 16-Byte Alignment&lt;/h4&gt;

&lt;p&gt;Um übelsten finde ich die 16-Byte Ausrichtung des Stacks, die notwendig ist, 
damit 128-Bit Operationen performant funktionieren.&lt;br /&gt;
Je nach Anzahl der Parameter, Variablen und gesicherten Registern, müssen
im Stack Lücken gelassen werden, damit die &lt;code&gt;RSP&lt;/code&gt; Adresse &lt;strong&gt;vor&lt;/strong&gt; einem 
&lt;code&gt;CALL&lt;/code&gt; immer ein genaues Vielfaches von 16 Byte ist.&lt;/p&gt;

&lt;p&gt;Beim Funktionsaufruf mit kleiner-gleich 4 Parametern, müssten wir 32 Bytes für 
den Home-Space vom Stack abziehen (was automatisch 16-Byte ausgerichtet ist). 
Bei 5 Parametern wird zuerst eine 8-Byte Lücke gelassen, dann der letzte
Parameter gePUSHt und am Ende werden 32 Bytes Home-Space abgezogen.
Bei 6 Parametern werden die letzten 2 Parameter gePUSHT und 
32 Bytes Home-Space abgezogen … usw.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Fazit: Eine &lt;strong&gt;ungerade&lt;/strong&gt; Parameteranzahl &lt;code&gt;&amp;gt;= 5&lt;/code&gt; erfordert 
eine Ausrichtung vor dem &lt;code&gt;CALL&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Innerhalb der Funktion hat &lt;code&gt;CALL&lt;/code&gt; die Rücksprungadresse auf den Stack gelegt,
womit dieser nicht ausgerichtet ist.
Entweder lässt man eine ungerade Summe von Register-&lt;code&gt;PUSH&lt;/code&gt; + lokalen Variablen
den Stack ausrichten, oder man addiert 8 Bytes zu &lt;code&gt;RSP&lt;/code&gt;, damit der Stack
ausgerichtet ist und arbeitet dann mit einer geraden Anzahl an 
&lt;code&gt;PUSH&lt;/code&gt; + lokalen Variablen weiter.&lt;br /&gt;
Am Ende muss &lt;code&gt;RSP&lt;/code&gt; wieder durch 16 ohne Rest teilbar sein, damit ein
weiterer Funktions-&lt;code&gt;CALL&lt;/code&gt; problemlos stattfinden kann.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Fazit: Im Prolog braucht also eine &lt;strong&gt;gerade&lt;/strong&gt; Anzahl von &lt;code&gt;PUSH&lt;/code&gt; + lokalen 
64-bit Variablen eine Ausrichtung, weil die Rücksprung-Adresse die 
Stack-Ausrichtung verschiebt.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Und genau das macht es dann so f*cking kompliziert, die Adressen der
Variablen und der Parameter zu bestimmen.
Was für ein Glück, dass in C/C++ der Compiler diesen Job übernimmt.&lt;/p&gt;

&lt;h4 id=&quot;x64-beispiel&quot;&gt;x64 Beispiel&lt;/h4&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;int64_t foo(int64_t a, int64_t b, int64_t c, 
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;            int64_t d, int64_t e)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;// PROLOG:&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  int64_t x;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;  int64_t y;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;// asm SUB RSP, 24  ; alloc local stack frame &lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;//                  ; for 2 int64 (x, y) + alignment&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  x = a + b + c + d;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;// asm MOV RAX, RCX        ; load a&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;// asm ADD RAX, RDX        ; add b&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;// asm ADD RAX, R8         ; add c&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;// asm ADD RAX, R9         ; add d&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;// asm MOV [RSP + 8], RAX ; store x&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;  y = x + e;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;// asm MOV RAX, [RSP + 8]               ; load x&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;// asm ADD RAX, [RSP + 24 + 8 + 32]     ; add e&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;// asm MOV [RSP + 0], RAX               ; save y&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n21&quot; name=&quot;n21&quot;&gt;21&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n22&quot; name=&quot;n22&quot;&gt;22&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; y;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n23&quot; name=&quot;n23&quot;&gt;23&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;// asm MOV RAX, [RSP + 0]  ; load y as return value&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n24&quot; name=&quot;n24&quot;&gt;24&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n25&quot; name=&quot;n25&quot;&gt;25&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;// EPILOG:&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n26&quot; name=&quot;n26&quot;&gt;26&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;// asm SUB RSP, 24  ; dealloc local stack frame&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n27&quot; name=&quot;n27&quot;&gt;27&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;// asm RET&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n28&quot; name=&quot;n28&quot;&gt;28&lt;/a&gt;&lt;/span&gt;}
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n29&quot; name=&quot;n29&quot;&gt;29&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n30&quot; name=&quot;n30&quot;&gt;30&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; main()
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n31&quot; name=&quot;n31&quot;&gt;31&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n32&quot; name=&quot;n32&quot;&gt;32&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;/*...*/&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n33&quot; name=&quot;n33&quot;&gt;33&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n34&quot; name=&quot;n34&quot;&gt;34&lt;/a&gt;&lt;/span&gt;  int64_t result = foo(&lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;, &lt;span style=&quot;color:#00D&quot;&gt;2&lt;/span&gt;, &lt;span style=&quot;color:#00D&quot;&gt;3&lt;/span&gt;, &lt;span style=&quot;color:#00D&quot;&gt;4&lt;/span&gt;, &lt;span style=&quot;color:#00D&quot;&gt;5&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n35&quot; name=&quot;n35&quot;&gt;35&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;// asm SUB RSP, 8  ; prepare CALL-alignment&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n36&quot; name=&quot;n36&quot;&gt;36&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;// asm PUSH 5      ; add e to stack&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n37&quot; name=&quot;n37&quot;&gt;37&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;// asm MOV R9, 4   ; put d in register&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n38&quot; name=&quot;n38&quot;&gt;38&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;// asm MOV R8, 3   ; put c in register&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n39&quot; name=&quot;n39&quot;&gt;39&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;// asm MOV RDX, 2  ; put b in register&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n40&quot; name=&quot;n40&quot;&gt;40&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;// asm MOV RCX, 1  ; put a in register&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n41&quot; name=&quot;n41&quot;&gt;41&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;// asm SUB RSP, 32 ; alloc home space (4 * 64-Bits)&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n42&quot; name=&quot;n42&quot;&gt;42&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;// asm CALL foo    ; call function&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n43&quot; name=&quot;n43&quot;&gt;43&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;// asm ADD RSP, 48 ; dealloc (home space + arg 5 + alignment)&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n44&quot; name=&quot;n44&quot;&gt;44&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;// asm MOV [result], EAX&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n45&quot; name=&quot;n45&quot;&gt;45&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n46&quot; name=&quot;n46&quot;&gt;46&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;/*...*/&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n47&quot; name=&quot;n47&quot;&gt;47&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;In &lt;code&gt;main&lt;/code&gt; brauchen 5 Parameter zusätzliche 8-Bytes um das 16-Byte Alignment 
einzuhalten. Das gleiche passiert in &lt;code&gt;foo&lt;/code&gt;, wo der RET-Adresse + 2 Variablen
ebenfalls noch 8-Bytes fehlen, damit &lt;code&gt;RSP&lt;/code&gt; am Ende wieder korrekt 
ausgerichtet ist.&lt;/p&gt;

&lt;p&gt;Innerhalb von &lt;code&gt;foo&lt;/code&gt; kann man dann so adressieren:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;RSP Offset&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Element&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Beschreibung&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;RSP + 72&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt; &lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Lücke für Stack Ausrichtung&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;RSP + 64&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;e&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;5. Parameter&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;RSP + 56&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;d / R9&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Home für 4. Parameter&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;RSP + 48&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;c / R8&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Home für 3. Parameter&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;RSP + 40&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;b / RDX&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Home für 2. Parameter&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;RSP + 32&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;a / RCX&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Home für 1. Parameter&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt; &lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt; &lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Stack-Frame Grenze&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;RSP + 24&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;RET Adresse&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Rücksprung Adresse zum Aufrufer&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;RSP + 16&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt; &lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Lücke für Stack Ausrichtung&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;RSP + 8&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;x&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;1. lokale Variable&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;RSP + 0&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;y&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;2. lokale Variable&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;X86-32 war nie “schön”, aber es war User-freundlich. Wir konnten mit &lt;code&gt;EBP&lt;/code&gt;
manuell ein paar ASM-Zeilen schreiben, die den OS-Standards entsprachen.&lt;/p&gt;

&lt;p&gt;Bei X86-64 merkt man deutlich, dass die Calling Convention nicht mehr
auf “Handarbeit” ausgelegt ist.&lt;br /&gt;
Ein Compiler kann die nötigen Offsets schnell berechnen, wenn sich ein
Register oder eine Variable einschleicht.
Doch wenn man das selbst im Kopf machen muss, wird einem leicht schwindelig.&lt;/p&gt;

&lt;p&gt;Andere ASM-Beispiele liegen im 
&lt;a href=&quot;https://codeberg.org/GateNetwork/gate-blog-classroom/src/branch/main/asm/asm_support_in_cmake/&quot;&gt;BLOG-Classroom&lt;/a&gt;.&lt;br /&gt;
Und ein paar andere “coole” Blogger haben auch schöne Artikel dazu geschrieben:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://devblogs.microsoft.com/oldnewthing/20160623-00/?p=93735&quot;&gt;The Old New Thing: Home Space&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://devblogs.microsoft.com/oldnewthing/20130906-00/?p=3303&quot;&gt;The Old New Thing: Stack Tracing&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://devblogs.microsoft.com/oldnewthing/20190111-00/?p=100685&quot;&gt;The Old New Thing: Red Zone&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://sonictk.github.io/asm_tutorial/&quot;&gt;ASM-Tutorial von sonictk&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In Linux (und &lt;a href=&quot;https://de.wikipedia.org/wiki/Berkeley_Software_Distribution#Die_Projekte_NetBSD,_FreeBSD_und_OpenBSD&quot;&gt;BSD&lt;/a&gt; 
und SysV) sieht die Sache ein bisschen anders aus. Man nutzt 6 Register für 
Parameter, keinen Home-Space, dafür müssen &lt;code&gt;vararg&lt;/code&gt; Funktionen ihre Parameter 
in einen Zwischenspeicher umkopieren, aber das verflixte Alignment ist auch 
dort notwendig.&lt;/p&gt;

&lt;p&gt;… aber das ist eine andere Geschichte.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Stille (an Tag und) Nacht</title>
   <link href="https://www.opengate.at/blog/2021/12/merry-x-mas/"/>
   <published>2021-12-25T12:00:00+01:00</published>
   <updated>2021-12-25T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2021/12/merry-x-mas</id>
   <category term="general" />
   <summary type="text">
  Wir hatten alle bis zum Abend gewartet, bis alle von der Arbeit
heim kamen, und dann wurden endlich die Updates verteilt.
Es war ein buntes Treiben voller Überraschungen.

  Dann wurden die kleinen Server alle in den Ruhezustand versetzt,
und die größeren erzählten sich noch Geschichten bis tief in die Nacht,
bis auch sie dem Timeout zum Shutdown folgten.

</summary>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;Wir hatten alle bis zum Abend gewartet, bis alle von der Arbeit
heim kamen, und dann wurden endlich die Updates verteilt.&lt;br /&gt;
Es war ein buntes Treiben voller Überraschungen.&lt;/p&gt;

  &lt;p&gt;Dann wurden die kleinen Server alle in den Ruhezustand versetzt,
und die größeren erzählten sich noch Geschichten bis tief in die Nacht,
bis auch sie dem Timeout zum Shutdown folgten.
&lt;!--more--&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;hr /&gt;

&lt;p&gt;Wie üblich läuft bei einem Nerd wie mir der kleine Server Cluster
de facto das ganze Jahr im Wohnzimmer durch.&lt;/p&gt;

&lt;p&gt;Es gibt aber diesen einen Abend, an dem man schon als Kind gelernt hat,
dass er etwas Besonderes ist. Ein Abend an dem man auch an jene denkt, 
die nicht mehr da sind.&lt;br /&gt;
Und dann kommt der Moment, wenn man die berühmte Schweigeminute durchhält,
wo es einfach nur still ist.&lt;/p&gt;

&lt;p&gt;Ich habe mir vor vielen Jahren angewöhnt, am Weihnachtsabend, genauer gesagt
nach Mitternacht, diese
menschliche Tradition auch auf die Technik zu übertragen.&lt;br /&gt;
Ohne einen technischen Vorwand werden alle Systeme heruntergefahren,
die Smartphones werden ausgeschaltet auch das Licht und Heizung sind
“OFF”.&lt;br /&gt;
Die Nachbarn sind auch schon alle im Bett (oder einfach nur lautlos).&lt;/p&gt;

&lt;p&gt;Das ist der Moment, in dem es sogar in der Großstadt muxmäuschenstill wird.&lt;/p&gt;

&lt;p&gt;Jetzt kann man eine Weile in die einsame Flamme einer zuvor angezündeten 
Kerze blicken. Anfangs gehen einem noch tausend Gedanken durch den Kopf.
Bilder von Verwandten, Freunden und Kollegen tauchen auf und verschwinden 
wieder. Und wenn man das eine Weile lang fortführt, wird es auch im eigenen
Schädel ruhiger, man könnte fast sagen: klarer.&lt;/p&gt;

&lt;p&gt;Irgendwann stellt sich eine Entspanntheit ein, die ich als sehr angenehm 
empfinde. Viel intensiver hört man plötzlich das Bellen eines Hundes von der
anderen Straßenseite, oder wenn zu später Stunde ein einzelnes Auto in die
Gasse biegt.&lt;/p&gt;

&lt;p&gt;Dann merkt man, dass es genug ist. Genug für diesen Tag, genug für dieses
Jahr, bläst die Kerze aus, dreht sich um und legt sich ins Bett.
Man liegt viel gerader und regungsloser da als sonst, es juckt auch weniger
auf der Haut und man muss sich nicht wie sonst üblich irgendwo kratzen.&lt;/p&gt;

&lt;p&gt;Und dann wacht man am nächsten Tag ganz zwanglos auf. Es ist anders als 
sonst. Kein Surren von Lüftern und keine Gehupe von der Straße.&lt;/p&gt;

&lt;p&gt;Man steht auf, blickt durchs Fenster, sieht kaum Menschen, und es ist weiter
ruhig. 
Man steht in der Mitte seiner Wohnung, blickt sich um, sieht was man alles
angehäuft hat, was alles da ist und regungslos zurückblickt.&lt;/p&gt;

&lt;p&gt;Es gibt keinen Drang, keinen Zwang etwas zu tun. Alles besteht auch, ohne
dass es bewegt werden muss.
Und das ist der Moment, wo mir spontan die Zeilen&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Und Gott sah, dass es gut war.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;einfallen.&lt;/p&gt;

&lt;p&gt;Und dann keimt die gewohnte Normalität wieder auf. Geräte werden 
eingeschaltet, 1 nicht durchgekommener Anruf scheint auf, Ideen und Gedanken
springen an … denn es ist inzwischen Mittag und alles ist erwacht.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Manchmal muss man einen Motor erst abstellen, um ihn wahrnehmen zu können.
Und manchmal muss man eine Uhr erst anhalten, um ihr Ziffernblatt genau 
betrachten zu können.&lt;/p&gt;

&lt;p&gt;Auch so etwas kann Weihnachten einem ermöglichen.&lt;br /&gt;
Einen kurzen Moment der Stille, der die Grenzen von Schall und Rauch 
überwinden kann.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;strong&gt;Frohe Weihnachten!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/e-christmas-tree.jpg&quot; alt=&quot;X-mas tree&quot; /&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Assembler Module mit CMake</title>
   <link href="https://www.opengate.at/blog/2021/12/asm-cmake/"/>
   <published>2021-12-19T12:00:00+01:00</published>
   <updated>2021-12-19T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2021/12/asm-cmake</id>
   <category term="devel" />
   <summary type="text">So wie es in Star Trek heißt

  Space, the final frontier.


so heißt es dann auch gerne in der Software-Entwicklung:

  Assembler, 
the final frontier.


Bleibt nur die Frage offen, wie man diese letzte Grenze dann 
auch in CMake überwindet.

</summary>
   <content type="html">&lt;p&gt;So wie es in &lt;a href=&quot;https://de.wikipedia.org/wiki/Star_Trek&quot;&gt;Star Trek&lt;/a&gt; heißt&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;Space, the final frontier.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;so heißt es dann auch gerne in der Software-Entwicklung:&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Assemblersprache&quot;&gt;Assembler&lt;/a&gt;, 
the final frontier.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Bleibt nur die Frage offen, wie man diese letzte Grenze dann 
auch in &lt;a href=&quot;https://de.wikipedia.org/wiki/CMake&quot;&gt;CMake&lt;/a&gt; überwindet.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Das GATE Projekt soll eigentlich frei von Hardware-Spezialitäten sein,
lediglich die “notwendigen” &lt;a href=&quot;https://de.wikipedia.org/wiki/Betriebssystem&quot;&gt;OS&lt;/a&gt; 
APIs der wichtigsten Hersteller sollen gesammelt und abstrahiert werden.&lt;br /&gt;
Assembler Codes haben da keinen Platz und sind auch in anderen Libs wie
&lt;a href=&quot;https://de.wikipedia.org/wiki/OpenSSL&quot;&gt;OpenSSL&lt;/a&gt; / &lt;a href=&quot;https://de.wikipedia.org/wiki/LibreSSL&quot;&gt;libreSSL&lt;/a&gt;
usw. bewusst abgeschaltet.&lt;/p&gt;

&lt;p&gt;Eine kleine Ausnahme gibt es, wenn es um die CPU-ID geht, die man mit
Inline-Assembler auslesen kann … aber schon da gibt es das typische
&lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_C%2B%2B&quot;&gt;MSVC&lt;/a&gt; &lt;a href=&quot;https://de.wikipedia.org/wiki/X64&quot;&gt;X64&lt;/a&gt;
Problem, dass dort nämlich kein Inline-Assembler unterstützt wird.&lt;/p&gt;

&lt;p&gt;Mit der &lt;a href=&quot;https://de.wikipedia.org/wiki/Unified_Extensible_Firmware_Interface&quot;&gt;EFI&lt;/a&gt; 
Plattform gibt es nun aber einen Sonderfall, wo es um den Nachbau von 
&lt;a href=&quot;https://de.wikipedia.org/wiki/C_(Programmiersprache)&quot;&gt;C&lt;/a&gt;-APIs geht, 
namentlich &lt;a href=&quot;https://en.wikipedia.org/wiki/Setjmp.h&quot;&gt;&lt;code&gt;setjmp()&lt;/code&gt; und &lt;code&gt;longjmp()&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Diese Funktionen lassen sich nicht mit reinem C nachbauen. Doch diese sind
in der &lt;code&gt;gnuefi&lt;/code&gt; Bibliothek als &lt;code&gt;.s&lt;/code&gt; Assembler Dateien beigelegt.&lt;/p&gt;

&lt;p&gt;Blöd ist nur, dass ich primär unter Windows mit dem &lt;code&gt;MSVC&lt;/code&gt; arbeite, 
wo mir erstens die &lt;code&gt;.s&lt;/code&gt; Dateien nichts bringen und zweitens &lt;code&gt;CMake&lt;/code&gt;
diese Dateien nicht automatisch mitbaut.&lt;/p&gt;

&lt;h3 id=&quot;gnu-assembler-support-für-cmake&quot;&gt;GNU Assembler Support für CMake&lt;/h3&gt;

&lt;p&gt;Im Netz findet man schnell die Info, dass man &lt;code&gt;ASM&lt;/code&gt; als Sprache im &lt;code&gt;CMake&lt;/code&gt;
Projekt angeben soll, also z.B.&lt;br /&gt;
&lt;code&gt;project(my_project C ASM)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Dann werden noch &lt;code&gt;*.s&lt;/code&gt; Dateien hinzugefügt und man erhält:&lt;/p&gt;

&lt;div class=&quot;language-cmake highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt; project(my_project C ASM)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt; file(GLOB MY_ASM_SOURCES
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;   &amp;quot;path/to/*.s&amp;quot;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt; )
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt; file(GLOB MY_C_SOURCES
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;   &amp;quot;path/to/*.c&amp;quot;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt; )
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt; 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt; add_library(my_project
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;   ${MY_ASM_SOURCES}
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;   ${MY_C_SOURCES}
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt; )
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;CMake generiert dann Make-Files, die die &lt;code&gt;.s&lt;/code&gt; Assembler Dateien kompilieren
und zur Zielbibliothek (oder Executable) hinzufügen.&lt;/p&gt;

&lt;h3 id=&quot;msvc-assembler-support-für-cmake&quot;&gt;MSVC Assembler Support für CMake&lt;/h3&gt;

&lt;p&gt;In Visual Studio kann man manuell den &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Macro_Assembler&quot;&gt;MASM&lt;/a&gt; 
Support aktivieren, in dem man das Projekt auswählt, und dann unter 
&lt;code&gt;Project&lt;/code&gt; -  &lt;code&gt;Build Customizations&lt;/code&gt; klickt und dort die &lt;code&gt;masm&lt;/code&gt; Zeile anhakt. 
Ab dann werden alle &lt;code&gt;.asm&lt;/code&gt; Dateien an den Assembler Compiler weitergereicht.&lt;/p&gt;

&lt;p&gt;Für &lt;code&gt;CMake&lt;/code&gt; gibt es beim MSVC einen eigenen MASM Token, der da lautet:&lt;br /&gt;
&lt;code&gt;ASM_MASM&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Somit muss man nur noch die unter &lt;a href=&quot;https://de.wikipedia.org/wiki/MS-DOS&quot;&gt;DOS&lt;/a&gt; 
und Windows üblichen &lt;code&gt;.asm&lt;/code&gt; Dateien in &lt;code&gt;CMakeLists.txt&lt;/code&gt; aufnehmen:&lt;/p&gt;

&lt;div class=&quot;language-cmake highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt; project(my_project C ASM_MASM)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt; file(GLOB MY_ASM_SOURCES
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;   &amp;quot;path/to/*.asm&amp;quot;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt; )
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt; file(GLOB MY_C_SOURCES
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;   &amp;quot;path/to/*.c&amp;quot;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt; )
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt; 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt; add_library(my_project
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;   ${MY_ASM_SOURCES}
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;   ${MY_C_SOURCES}
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt; )
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h3 id=&quot;masm-funktionen-für-c-schreiben&quot;&gt;MASM Funktionen für C schreiben&lt;/h3&gt;

&lt;p&gt;Nun beginnt für mich der harte Kampf die AT&amp;amp;T Assemblercodes nach MASM zu 
portieren. Denn da der AT&amp;amp;T Syntax bei GNU und GCC vorherrscht und auch die
&lt;code&gt;setjmp()&lt;/code&gt; und &lt;code&gt;longjmp()&lt;/code&gt; Codes der &lt;code&gt;gnu-efi&lt;/code&gt; Bibliothek so geschrieben sind,
müssen fast alle Codezeilen “umgedreht” werden, damit sie MASM-tauglich werden.&lt;/p&gt;

&lt;p&gt;Warum MASM ein &lt;code&gt;Operator Ziel, Quell&lt;/code&gt; Schema verfolgt und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/ASM86&quot;&gt;AT&amp;amp;T&lt;/a&gt; umgekehrt &lt;code&gt;Operator Quelle, Ziel&lt;/code&gt;
nutzt und es da keinen Standard gibt, stört mich damals wie heute.&lt;/p&gt;

&lt;p&gt;So sehen jedenfalls meine vorläufigen Bemühungen aus:&lt;/p&gt;

&lt;div class=&quot;language-asm highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;.CODE
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;PUBLIC _setjmp
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;_setjmp PROC
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;  ; RCX hold pointer to jmp_buf 
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  pop rdx   ; RET address
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;  push rdx
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;  mov rax, 0
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  mov [rcx + 00h], rsp  ; Frame
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;  mov [rcx + 08h], rbx                
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;  mov [rcx + 10h], rsp
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;  mov [rcx + 18h], rbp
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;  mov [rcx + 20h], rsi
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;  mov [rcx + 28h], rdi
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;  mov [rcx + 30h], r12
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;  mov [rcx + 38h], r13
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;  mov [rcx + 40h], r14
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;  mov [rcx + 48h], r15
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  mov [rcx + 50h], rdx ; RIP
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n21&quot; name=&quot;n21&quot;&gt;21&lt;/a&gt;&lt;/span&gt;  ; currently, skip following fields in jmp_buf
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n22&quot; name=&quot;n22&quot;&gt;22&lt;/a&gt;&lt;/span&gt;  ret
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n23&quot; name=&quot;n23&quot;&gt;23&lt;/a&gt;&lt;/span&gt;_setjmp ENDP
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n24&quot; name=&quot;n24&quot;&gt;24&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n25&quot; name=&quot;n25&quot;&gt;25&lt;/a&gt;&lt;/span&gt;PUBLIC longjmp
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n26&quot; name=&quot;n26&quot;&gt;26&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n27&quot; name=&quot;n27&quot;&gt;27&lt;/a&gt;&lt;/span&gt;longjmp PROC
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n28&quot; name=&quot;n28&quot;&gt;28&lt;/a&gt;&lt;/span&gt;  mov rbx, [rcx + 08h]
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n29&quot; name=&quot;n29&quot;&gt;29&lt;/a&gt;&lt;/span&gt;  mov rsp, [rcx + 10h]
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n30&quot; name=&quot;n30&quot;&gt;30&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  mov rbp, [rcx + 18h]
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n31&quot; name=&quot;n31&quot;&gt;31&lt;/a&gt;&lt;/span&gt;  mov rsi, [rcx + 20h]
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n32&quot; name=&quot;n32&quot;&gt;32&lt;/a&gt;&lt;/span&gt;  mov rdi, [rcx + 28h]
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n33&quot; name=&quot;n33&quot;&gt;33&lt;/a&gt;&lt;/span&gt;  mov r12, [rcx + 30h]
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n34&quot; name=&quot;n34&quot;&gt;34&lt;/a&gt;&lt;/span&gt;  mov r13, [rcx + 38h]
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n35&quot; name=&quot;n35&quot;&gt;35&lt;/a&gt;&lt;/span&gt;  mov r14, [rcx + 40h]
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n36&quot; name=&quot;n36&quot;&gt;36&lt;/a&gt;&lt;/span&gt;  mov r15, [rcx + 48h]
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n37&quot; name=&quot;n37&quot;&gt;37&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n38&quot; name=&quot;n38&quot;&gt;38&lt;/a&gt;&lt;/span&gt;  mov r8, [rcx + 50h] ; RIP
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n39&quot; name=&quot;n39&quot;&gt;39&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n40&quot; name=&quot;n40&quot;&gt;40&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  mov eax, edx
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n41&quot; name=&quot;n41&quot;&gt;41&lt;/a&gt;&lt;/span&gt;  and rax, 0ffffffffh
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n42&quot; name=&quot;n42&quot;&gt;42&lt;/a&gt;&lt;/span&gt;  cmp eax, 0
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n43&quot; name=&quot;n43&quot;&gt;43&lt;/a&gt;&lt;/span&gt;  jne longjmp_exit
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n44&quot; name=&quot;n44&quot;&gt;44&lt;/a&gt;&lt;/span&gt;  mov eax, 1
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n45&quot; name=&quot;n45&quot;&gt;45&lt;/a&gt;&lt;/span&gt;longjmp_exit:
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n46&quot; name=&quot;n46&quot;&gt;46&lt;/a&gt;&lt;/span&gt;  jmp r8
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n47&quot; name=&quot;n47&quot;&gt;47&lt;/a&gt;&lt;/span&gt;longjmp ENDP
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Der erste Schritt ist also getan.
Die in Assembler implementierten &lt;code&gt;setjmp()&lt;/code&gt; und &lt;code&gt;longjmp()&lt;/code&gt; Symbole erlauben mir
nun weitere Bibliotheken wie &lt;a href=&quot;https://de.wikipedia.org/wiki/Lua&quot;&gt;LUA&lt;/a&gt; oder 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Libjpeg&quot;&gt;libjpeg&lt;/a&gt; auch für native EFI-Apps zu 
nutzen.&lt;/p&gt;

&lt;p&gt;Das Potential ist aber weit größer.&lt;br /&gt;
Denn mit Assembler-Fragmenten kann ich nun auch zu anderen Stacks springen
und z.B. &lt;a href=&quot;https://de.wikipedia.org/wiki/Koroutine&quot;&gt;Koroutinen&lt;/a&gt; ohne 
OS-Support implementieren.&lt;/p&gt;

&lt;p&gt;Aber … bis das lauffähig sein wird, vergeht vermutlich noch einige Zeit.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Wie CONAN OpenSSL sprengt</title>
   <link href="https://www.opengate.at/blog/2021/12/conan-links/"/>
   <published>2021-12-18T12:00:00+01:00</published>
   <updated>2021-12-18T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2021/12/conan-links</id>
   <category term="devel" /><category term="software" />
   <summary type="text">Manche Geschichten aus dem Programmierer-Alltag sind so kurios, dass sie
es verdienen dokumentiert zu werden.

Und eine davon ist die Geschichte vom CONAN 
Build-Pfad, der das Compilieren von OpenSSL
gebrochen hat.
</summary>
   <content type="html">&lt;p&gt;Manche Geschichten aus dem Programmierer-Alltag sind so kurios, dass sie
es verdienen dokumentiert zu werden.&lt;/p&gt;

&lt;p&gt;Und eine davon ist die Geschichte vom &lt;a href=&quot;https://docs.conan.io/&quot;&gt;CONAN&lt;/a&gt; 
Build-Pfad, der das Compilieren von &lt;a href=&quot;https://de.wikipedia.org/wiki/OpenSSL&quot;&gt;OpenSSL&lt;/a&gt;
gebrochen hat.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Mit &lt;code&gt;OpenSSL&lt;/code&gt; verbindet mich eine emotionale Hassliebe.
Einerseits war diese Bibliothek früher die einzige und gleichsam beste 
Möglichkeit, Kryptographie von &lt;a href=&quot;https://de.wikipedia.org/wiki/Transport_Layer_Security&quot;&gt;SSL bis TLS&lt;/a&gt;
in sein Projekt zu bekommen und andererseits hat &lt;code&gt;OpenSSL&lt;/code&gt; das aus meiner 
bescheuertste Build-System überhaupt.&lt;/p&gt;

&lt;p&gt;Denn wenn man für ein Projekt in Programmiersprache A (also 
&lt;a href=&quot;https://de.wikipedia.org/wiki/C_(Programmiersprache)&quot;&gt;C&lt;/a&gt;) eine 
Hilfssprache B braucht (also &lt;a href=&quot;https://de.wikipedia.org/wiki/Perl_(Programmiersprache)&quot;&gt;Perl&lt;/a&gt;), 
dann läuft etwas gehörig schief.&lt;br /&gt;
Der Nachfolger &lt;a href=&quot;https://de.wikipedia.org/wiki/LibreSSL&quot;&gt;libreSSL&lt;/a&gt; beweist 
außerdem, dass es auch ohne solche Kunstgriffe geht, und man nicht per 
Perl-Script alle Header anpassen muss.&lt;/p&gt;

&lt;h3 id=&quot;neulich-in-der-firma-&quot;&gt;Neulich in der Firma …&lt;/h3&gt;

&lt;p&gt;Eine neue Buildplattform kam hinzu und damit mussten diverse 3rd-Party-Libs
eben für diese Plattform neu gebaut werden.&lt;br /&gt;
Da gibt es immer wieder ein paar Problemchen, die man mit diversen Tricks,
Compilerswitches und Environment-Variablen lösen muss.&lt;/p&gt;

&lt;p&gt;Doch beim Bauen einer statischen Version von &lt;code&gt;OpenSSL&lt;/code&gt; unter Windows trat 
plötzlich folgender Fehler auf:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt; .\crypto\cversion.c(82): warning C4129: &apos;c&apos;: unrecognized character escape sequence
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt; .\crypto\cversion.c(82): error C2022: &apos;289&apos;: too big for character
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt; .\crypto\cversion.c(82): warning C4129: &apos;i&apos;: unrecognized character escape sequence
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Und was steht in Zeile 82 ?&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt; *SSLeay_version(&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; t)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt; {
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;   ...
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;   &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt; (t == SSLEAY_CFLAGS) {
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt; &lt;span style=&quot;color:#579&quot;&gt;#ifdef&lt;/span&gt; CFLAGS
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;     &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; (CFLAGS);    &lt;span style=&quot;color:#777&quot;&gt;/* &amp;lt;-- line 82 */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt; &lt;span style=&quot;color:#579&quot;&gt;#else&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;     &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; (&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;compiler: information not available&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt; &lt;span style=&quot;color:#579&quot;&gt;#endif&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;   }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;   ...
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt; }
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Und &lt;code&gt;CFLAGS&lt;/code&gt; sollte die Compiler-Switches enthalten, die zum Bauen des 
Projektes benutzt werden.&lt;/p&gt;

&lt;p&gt;Jetzt gibt es zahlreiche andere Pipelines, die nie ein Problem mit dem Code
hatten, also warum schlägt das plötzlich bei einer einzelnen Pipeline fehlt?&lt;/p&gt;

&lt;h3 id=&quot;vorsicht-mit-windows-dateisystempfaden&quot;&gt;Vorsicht mit Windows Dateisystempfaden!&lt;/h3&gt;

&lt;p&gt;Der Compiler-Aufruf beinhaltet neben zahlreichen Steuer-Makros wie 
&lt;code&gt;-DOPENSSL_NO_SSL2&lt;/code&gt;, &lt;code&gt;-DSHA1_ASM&lt;/code&gt; usw. auch den Parameter&lt;br /&gt;
&lt;code&gt;-IC:\conan_cache\441b83\1\include&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Und dabei handelt es sich um den Include-Pfad einer CONAN-Abhängigkeit,
dessen Unterverzeichnis durch einen &lt;a href=&quot;https://de.wikipedia.org/wiki/Hashfunktion&quot;&gt;Hash&lt;/a&gt; 
von &lt;code&gt;CONAN&lt;/code&gt; generiert wird.&lt;/p&gt;

&lt;p&gt;Tja … und ein &lt;code&gt;\c&lt;/code&gt; von &lt;code&gt;\conan_cache&lt;/code&gt; und  &lt;code&gt;\i&lt;/code&gt; von &lt;code&gt;\include&lt;/code&gt; erklären
die Warnungen, die ich bei weiterer Analyse auch in anderen Windows-Builds
finden konnte.&lt;/p&gt;

&lt;p&gt;Aber &lt;code&gt;\441b83&lt;/code&gt; ist ein lustiger Zufall, denn Backslash + 3-Ziffern sind in
C eine &lt;a href=&quot;https://de.wikipedia.org/wiki/Oktalsystem&quot;&gt;Oktalzahl&lt;/a&gt; und &lt;code&gt;\441&lt;/code&gt; wird 
im Dezimalsystem dann zur &lt;code&gt;289&lt;/code&gt;.&lt;br /&gt;
Und &lt;code&gt;289&lt;/code&gt; ist wiederum für ein Byte zu viel (weil größer 255) und so erklärt
sich dann auch der Fehler mit dem String, der den Build abbricht.&lt;/p&gt;

&lt;p&gt;Da die &lt;code&gt;CONAN&lt;/code&gt; Hashes für die Builds einen quasi zufälligen Charakter haben,
hatten wir bei den anderen Build-Pipelines einfach Glück und die erzeugten
Strings hatten einfach “lustige” Zeichen in sich und generierten weitere
Warnungen, doch wenn der Hash mit der Ziffer &lt;code&gt;4&lt;/code&gt; beginnt und zwei weitere
Ziffern folgen, hört der Spaß beim C-Compiler auf.&lt;/p&gt;

&lt;h3 id=&quot;lösung-cflags-unter-windows-ausblenden&quot;&gt;Lösung: CFLAGS unter Windows ausblenden&lt;/h3&gt;

&lt;p&gt;Ich passe nur ungern 3rd-Party Codes an, aber um das Problem “schnell” aus
dem Weg zur räumen, habe ich einfach ein lokales Patch-File erstellt,
welches die Zeilen:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt; &lt;span style=&quot;color:#579&quot;&gt;#if&lt;/span&gt; defined(WIN32) &amp;amp;&amp;amp; defined(CFLAGS)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt; &lt;span style=&quot;color:#579&quot;&gt;#  undef&lt;/span&gt; CFLAGS
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt; &lt;span style=&quot;color:#579&quot;&gt;#endif&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;implantiert.&lt;br /&gt;
Denn schließlich kann in jeder künftigen &lt;code&gt;CONAN&lt;/code&gt; basierten Pipeline wieder
so ein lustiges Hash-Unterverzeichnis entstehen. Und ungewollte Backslashes 
in Strings aus dem Dateisystem sind hier generell ein Problem.&lt;/p&gt;

&lt;p&gt;Meines Erachtens wird diese Versions-API nirgends produktiv “benutzt”, sie
dient nur der Rückverfolgung des Bauprozesses der Bibliothek.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;What - the - fu** …&lt;/p&gt;

&lt;p&gt;Nach unzähligen Jahren in der Softwareentwicklung vergeht kein Jahr, 
wo mir nicht wieder zig neue Varianten von Build-Systemen unterkommen,
die durch Seiteneffekte den Quellcode vernudeln können.&lt;br /&gt;
&lt;code&gt;CONAN&lt;/code&gt; Builds unter Windows, deren Dateipfade in Strings ins Programm 
geprägt werden, sind also wieder “so eine Abart”, die ich in Zukunft zu 
meiden versuchen werde.&lt;/p&gt;

&lt;p&gt;Nun … ich muss sie bei meinen Codes nicht meiden, weil ich auch noch nie
&lt;code&gt;CFLAGS&lt;/code&gt; als String wo aufgenommen hätte. Aber ich werde nun bei weiteren
Bibliotheken aus dem Unix Umfeld genauer aufpassen, dass sie keinen Schaden
anrichten, wenn sie in Windows übernommen werden.&lt;/p&gt;

&lt;p&gt;Denn, wer weiß schon, ob nicht irgend wo anders schon mal ein &lt;code&gt;\0&lt;/code&gt; aus einem 
Dateipfad in einem Codefragment “versehentlich” eine Backdoor aufgemacht hat,
wenn ein &lt;code&gt;std::string::size()&lt;/code&gt; dann plötzlich was anderes zurückgibt,
als ein &lt;code&gt;strlen()&lt;/code&gt; auf den gleichen &lt;code&gt;char&lt;/code&gt; Puffer ….&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Und die Moral von der Geschicht’:&lt;br /&gt;
CONAN Pfade speichern darf man nicht!&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>Dark-Mode für Win32 im Menü</title>
   <link href="https://www.opengate.at/blog/2021/12/dark-mode-again/"/>
   <published>2021-12-12T12:00:00+01:00</published>
   <updated>2021-12-12T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2021/12/dark-mode-again</id>
   <category term="devel" />
   <summary type="text">Nachdem mich die Sache mit dem halbherzigen 
Dark-Mode für Win32 Apps nicht
mehr gut schlafen lässt, habe ich gezielt nach Möglichkeiten gesucht, weitere
UI Elemente schwarz zu färben.

Einer der störrischen Kandidaten ist die Windows Menüzeile, die durch 
einige nicht-offizielle APIs beeinflusst werden kann.

</summary>
   <content type="html">&lt;p&gt;Nachdem mich die Sache mit dem halbherzigen 
&lt;a href=&quot;/blog/2021/08/dark-mode-win32/&quot;&gt;Dark-Mode für Win32&lt;/a&gt; Apps nicht
mehr gut schlafen lässt, habe ich gezielt nach Möglichkeiten gesucht, weitere
UI Elemente schwarz zu färben.&lt;/p&gt;

&lt;p&gt;Einer der störrischen Kandidaten ist die Windows Menüzeile, die durch 
einige nicht-offizielle APIs beeinflusst werden kann.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;UI Control lassen sich oft durch bestimmte Fensternachrichten dazu bringen,
“ihre Selbstdarstellung” abzuändern. “Owner-Drawn” ist eines der 
Schlüsselworte hierfür, und so kann man sich im Notfall fast alle Controls
so “hinpatchen”, dass sie zum dunklen Design passen.&lt;/p&gt;

&lt;p&gt;Die Windows Menüzeile ist aber so ein ganz spezieller Sonderfall, der nicht
von den regulären dokumentierten Nachrichten beeinflusst werden kann.&lt;/p&gt;

&lt;p&gt;Eine geniale Zusammenfassung dazu hat 
&lt;a href=&quot;https://github.com/adzm/win32-custom-menubar-aero-theme&quot;&gt;github.com/adzm/win32-custom-menubar-aero-theme&lt;/a&gt;
veröffentlicht, und eben diese Methode setze ich nun auch ein. 
Und da der Beispielcode so etwas von selbsterklärend ist, brauche ich das hier
nicht nochmal durchkauen.&lt;/p&gt;

&lt;p&gt;In &lt;a href=&quot;https://github.com/adzm/win32-custom-menubar-aero-theme/blob/main/UAHMenuBar.h&quot;&gt;UAHMenuBar.h&lt;/a&gt;
findet man die speziellen Fensternachrichten und die &lt;code&gt;struct&lt;/code&gt; Deklarationen, in denen 
zusätzlich Daten gespeichert sind.&lt;/p&gt;

&lt;p&gt;Und in &lt;a href=&quot;https://github.com/adzm/win32-custom-menubar-aero-theme/blob/main/UAHMenuBar.cpp&quot;&gt;UAHMenuBar.cpp&lt;/a&gt;
wird demonstriert, wie man in der Nachricht &lt;code&gt;WM_UAHDRAWMENUITEM&lt;/code&gt; einen 
Menü-Eintrag selbst kolorieren kann.&lt;/p&gt;

&lt;p&gt;Mein Anpassung besteht nun nur noch aus der Abfrage, ob der Dark-Mode 
aktiviert ist. 
Wenn dem so ist, sollen die Fensternachrichten alles selbst zeichnen und dafür
Dark-Mode-konforme Farben nutzen.
Ohne Dark-Mode wird einfach die 
&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-defwindowproca&quot;&gt;DefWindowProc&lt;/a&gt; aufgerufen&lt;/p&gt;

&lt;p&gt;Eine wichtige Frage ist noch:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Wo bekommt man die korrekten Farbinformationen her?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Nun, meine Versuche mit &lt;code&gt;UxGetImmersiveColorTypeFromName()&lt;/code&gt; brachten keine 
guten Ergebnisse.&lt;br /&gt;
Mir fehlt ein Mapping von “Menü-Hintergrundfarbe” auf einen &lt;code&gt;ImmersiveXYZ&lt;/code&gt; 
Theme-Color-Namen und alles, was sich “vernünftig” anhörte hat leider nicht 
gepasst.&lt;/p&gt;

&lt;p&gt;Von daher ist meine vorläufige Strategie, die aktuellen Dark-Mode Farben aus
einem Explorer-Screen-Shot zu extrahieren und die RGB-Werte hard-coded 
aufzunehmen.&lt;/p&gt;

&lt;p&gt;Das gefällt mir zwar nicht wirklich, aber es ist zumindest eine 
vorläufige Lösung.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ich bleibe dabei:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Microsoft hätte einfach bei der Anwendung des &lt;code&gt;Explorer&lt;/code&gt; oder 
&lt;code&gt;DarkMode_Explorer&lt;/code&gt; Theme-Namens per &lt;code&gt;UxSetWindowTheme()&lt;/code&gt; die Controls 
dunkel zeichnen sollen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Dann wären uns solche Hacks erspart geblieben.&lt;/p&gt;

&lt;p&gt;However… bis ich mit der Dark-Mode Sache zufrieden bin, werden wohl noch
einige Code-Änderungen durchs Land ziehen.&lt;/p&gt;

&lt;p&gt;Obwohl ich den Menü-Code im Zuge des GATE Frameworks nun ausprobiert habe,
werde ich diese Stellen nur optional in ein Kompilat fließen lassen.&lt;br /&gt;
Denn da diese Nachrichten nicht dokumentiert sind und mit Zeigern auf
private Strukturen gearbeitet wird, ist nicht auszuschließen, 
dass der Code dann beim nächsten Windows Release zu Crashes führt.&lt;/p&gt;

&lt;p&gt;Eine mögliche Lösung wäre natürlich, den Code per Registry-Key aktiveren
und deaktivieren zu können.&lt;/p&gt;

&lt;p&gt;Na, mal sehen, für was ich mich am Ende entscheiden werde ….&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>POCO M3 Pro</title>
   <link href="https://www.opengate.at/blog/2021/12/poco-m3/"/>
   <published>2021-12-11T12:00:00+01:00</published>
   <updated>2021-12-11T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2021/12/poco-m3</id>
   <category term="hardware" />
   <summary type="text">Nein, nein, nein! Ich gebe mein Lumia 950 
Windows Phone 
nicht auf. Es funktioniert super und das bleibt auch so.

Aber … auch mir bleibt nicht erspart, dass die Welt eine andere Richtung
eingeschlagen hat, und deshalb musste ich mir jetzt auch wieder mal ein
Android
Telefon kaufen.

Und meine Wahl ist auf ein Poco M3
gefallen.
</summary>
   <content type="html">&lt;p&gt;Nein, nein, nein! Ich gebe mein Lumia 950 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_Phone&quot;&gt;Windows Phone&lt;/a&gt; 
nicht auf. Es funktioniert super und das bleibt auch so.&lt;/p&gt;

&lt;p&gt;Aber … auch mir bleibt nicht erspart, dass die Welt eine andere Richtung
eingeschlagen hat, und deshalb musste ich mir jetzt auch wieder mal ein
&lt;a href=&quot;https://de.wikipedia.org/wiki/Android_(Betriebssystem)&quot;&gt;Android&lt;/a&gt;
Telefon kaufen.&lt;/p&gt;

&lt;p&gt;Und meine Wahl ist auf ein &lt;a href=&quot;https://de.wikipedia.org/wiki/Smartphones_von_Poco#Poco_M3&quot;&gt;Poco M3&lt;/a&gt;
gefallen.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;typisch-android&quot;&gt;Typisch Android&lt;/h3&gt;

&lt;p&gt;Kurz gesagt, das Smartphone ist genau so ein Dreck, wie ich es von einem
Android Gerät erwartet hatte.&lt;br /&gt;
Über zwei Stunden war ich damit beschäftigt, sinnlose Apps, 
Werbung-verseuchte Spiele und Vollzugriffsrechte zu entfernen.&lt;/p&gt;

&lt;p&gt;Das war schon bei meinem Sony Xperia XA2 vor 3 Jahren ein Krampf und 
die Kontaminierung des Betriebssystems und der Apps mit Online-Diensten
ist leider noch viel schlimmer geworden.&lt;/p&gt;

&lt;p&gt;Ich konnte aber durch die manuelle Installation von &lt;a href=&quot;https://en.wikipedia.org/wiki/Android_application_package&quot;&gt;APKs&lt;/a&gt;
einen Teil des Google-Drecks umgehen und somit ein halbwegs benutzbares 
Telefon zu erhalten.&lt;br /&gt;
&lt;a href=&quot;https://apkpure.com/&quot;&gt;apkpure.com&lt;/a&gt; ermöglichte mir den Download der
notwendigen Software ohne Google-Play, das ohne Online-Account gar
nicht mehr benutzt werden kann.&lt;/p&gt;

&lt;p&gt;Selbst Microsoft lässt den Anwender kostenlose Apps ohne Online-Accounts
installieren und ich verstehe nicht, warum man Google nicht auch zu 
einer solchen Prozedur zwingen kann.&lt;/p&gt;

&lt;h3 id=&quot;tolle-hardware&quot;&gt;Tolle Hardware&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/poco-m3-pro.jpg&quot; alt=&quot;POCO M3 Pro&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Wenn man von diesem Abschaum von Android 11 Betriebssystem absieht, ist das 
Poco M3 Pro ein gutes Gerät.
Die Bedienung ist flüssig und nachdem ich ohnehin keine Spielchen auf dem
Telefon laufen lassen werde, kann ich mir nicht vorstellen, an die 
Leistungsgrenzen zu stoßen.&lt;/p&gt;

&lt;p&gt;Schöne Bilder macht auch die Kamera. 
In der Standardeinstellung werden 12 Megapixel (2992 x 4000) in einem Bild 
untergebracht. Das ist tatsächlich weniger, als die 20 Megapixel (3008 x 5344)
meines Lumia 950, doch wenn ich mein Mainboard bei schlechter 
Zimmerbeleuchtung abfotografiere, sieht man bereits, dass das POCO M3 Pro eine
etwas bessere Qualität bei den Farben produzieren kann.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/photo-compare-lumia-poco.jpg&quot; alt=&quot;Photo Compare Lumia Poco&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Man kann auch auf 48 MegaPixel hochschalten, aber hilfreich ist das nicht. 
Man erhält dann zwar mit 6000 x 8000 Pixel eine 4-mal so große Datei 
(13 MB statt 3.5 MB), doch das Bild ist weder schärfer noch qualitativ besser.
Vielleicht hilft einem der Modus für Naturaufnahmen, aber mein Mainboard sieht
exakt gleich aus, es sind quasi nur die Pixel verdoppelt worden und das ganze
sieht dann auch ziemlich künstlich und berechnet aus.&lt;/p&gt;

&lt;p&gt;Mit 5000 Milliamperestunden habe ich einen frischen Akku, der mein Lumia 950
um Längen überholen kann. Denn während dem Windows Phone auch im Leerlauf nach
zwei Tagen der Saft ausgeht, schafft es das POCO Phone in 2 Tagen nur etwa
ein Drittel des Akkus aufzubrauchen.&lt;/p&gt;

&lt;p&gt;Natürlich ist der neue Akku mit dem 4 Jahre alten kaum zu vergleichen und 
vielleicht werde ich auch dem Windows Phone noch mal einen Ersatzakku besorgen,
aber meine Befürchtung, dass das neue M3 keine 2 Tage übersteht, waren
unbegründet.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Mein Sony Xperia ist fast 4 Jahre lang nur am Schreibtisch gelegen und eine 
SIM-Karte hat das Gerät nie kennenlernen dürfen. Es war eben nur ein 
Testsystem für Android-Codes.&lt;/p&gt;

&lt;p&gt;Das Poco M3 wird voraussichtlich mein künftiges Standard-Telefon werden,
und aktuell nutze ich es mit meiner Zweit-Sim-Karte zum Experimentieren.
Denn irgendwann werden auch die E-Mail Dienste meines Lumia 950 wegen
Zertifikaten und anderen Problemchen nicht mehr ordentlich laufen und 
dann ist diese Ära endgültig vorbei.&lt;/p&gt;

&lt;p&gt;Lieber wäre es mir gewesen, &lt;a href=&quot;/blog/2020/11/pinephone/&quot;&gt;mein PinePhone&lt;/a&gt; 
als Hauptgerät zu nutzen, doch trotz der guten werbefreien Software, hat es 
extrem schlechte Lautsprecher, was es für unterwegs leider untauglich macht.&lt;/p&gt;

&lt;p&gt;Ich sollte jetzt eigentlich glücklich mit meinem neuen Gerät sein … 
aber der elende verseuchte Android-Scheißhaufen hat mir die Freude gehörig 
vernichtet.&lt;br /&gt;
Es ist für mich einfach unfassbar, dass ein Großteil der Menschheit diesen
Mist freiwillig einsetzt und dieser digitalen Datenversklavung bedenkenlos
zustimmt.&lt;/p&gt;

&lt;h3 id=&quot;nachtrag&quot;&gt;Nachtrag&lt;/h3&gt;

&lt;p&gt;Nur noch ein Wort zu Android:&lt;br /&gt;
Es ist nicht so, dass ich das gesamte Android-Konzept verteufele.
Mich treibt nur zur Weißglut, dass Apps für dieses System eine absolute
Abhängigkeit zu Google-Diensten haben. Und das stört mich eben enorm.&lt;/p&gt;

&lt;p&gt;Und wer einmal den Datenverkehr seines Routers mitverfolgt hat, weiß,
wie viele Daten diese Geräte abstrahlen.
Windows ist hier auch kein Engel, aber gegen Google ist das nichts …
… und niemand tut was dagegen. Es ist einfach furchtbar!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>EFI Shell mit QEMU</title>
   <link href="https://www.opengate.at/blog/2021/12/efi-qemu/"/>
   <published>2021-12-05T12:00:00+01:00</published>
   <updated>2021-12-05T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2021/12/efi-qemu</id>
   <category term="software" />
   <summary type="text">Wenn man EFI 
Apps entwickelt, möchte man sie natürlich auch testen. 
Natürlich kann man jedes neue .efi Binary auf einen USB-Stick kopieren und 
auf einem realen PC über die EFI-Shell ausführen, aber “effizient” ist das nicht.

Der Emulator QEMU bietet mit dem 
TianoCore OVMF 
(Open Virtual Machine Firmware) Paket die Möglichkeit, eine EFI Shell Sitzung 
oder eine EFI-Boot auf dem lokalen System schnell nachzustellen.

</summary>
   <content type="html">&lt;p&gt;Wenn man &lt;a href=&quot;https://de.wikipedia.org/wiki/Unified_Extensible_Firmware_Interface&quot;&gt;EFI&lt;/a&gt; 
Apps entwickelt, möchte man sie natürlich auch testen. 
Natürlich kann man jedes neue &lt;code&gt;.efi&lt;/code&gt; Binary auf einen USB-Stick kopieren und 
auf einem realen PC über die EFI-Shell ausführen, aber “effizient” ist das nicht.&lt;/p&gt;

&lt;p&gt;Der Emulator &lt;a href=&quot;https://de.wikipedia.org/wiki/QEMU&quot;&gt;QEMU&lt;/a&gt; bietet mit dem 
&lt;a href=&quot;https://en.wikipedia.org/wiki/TianoCore_EDK_II&quot;&gt;TianoCore&lt;/a&gt; OVMF 
(Open Virtual Machine Firmware) Paket die Möglichkeit, eine EFI Shell Sitzung 
oder eine EFI-Boot auf dem lokalen System schnell nachzustellen.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Um eine fertige &lt;code&gt;.efi&lt;/code&gt; x64-App-Datei schnell testen zu können, braucht man 
folgende Zutaten:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Eine QEMU Installation mit dem &lt;code&gt;qemu-system-x86_64&lt;/code&gt; Emulator&lt;/li&gt;
  &lt;li&gt;Eine Firmware-Datei mit EFI-Shell Support wie z.B. in &lt;code&gt;OVMF.fd&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Die Linux &lt;code&gt;mtools&lt;/code&gt; um per Script ein virtuelles USB-Stick-Image zu basteln&lt;/li&gt;
  &lt;li&gt;Und ein Script, welches alle Aufrufe zusammenfasst.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;qemu&quot;&gt;QEMU&lt;/h3&gt;

&lt;p&gt;Den System Emulator QEMU findet man auf &lt;a href=&quot;https://www.qemu.org/download/&quot;&gt;qemu.org&lt;/a&gt; 
zum Download, aber als OpenSource-Projekt kann man ihn auch direkt aus den
Quellcodes bauen lassen.&lt;/p&gt;

&lt;p&gt;Am einfachsten läuft die Installation jedoch über das Paketmanagement des 
Betriebssystems:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_10&quot;&gt;Windows&lt;/a&gt;: 
&lt;code&gt;winget install SoftwareFreedomConservancy.QEMU&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Debian / &lt;a href=&quot;https://de.wikipedia.org/wiki/Ubuntu&quot;&gt;Ubuntu&lt;/a&gt;: 
&lt;code&gt;sudo apt install qemu&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;tianocore-open-virtual-machine-firmware-ovmf&quot;&gt;TianoCore Open Virtual Machine Firmware (OVMF)&lt;/h3&gt;

&lt;p&gt;Eigentlich brauchen wir nur eine Datei namens &lt;code&gt;OVMF.fd&lt;/code&gt;, die aus dem TianoCore
Projekt heraus gebildet wurde, damit wir eine virtuelle Maschine starten können,
die von einem virtuellen USB Stick aus unsere App als &lt;code&gt;BOOTX64.EFI&lt;/code&gt; startet.&lt;/p&gt;

&lt;p&gt;Entweder sucht man sich dafür in den Weiten des Internet eine &lt;code&gt;OVMF.fd&lt;/code&gt;, oder
man klont sich das &lt;a href=&quot;https://github.com/tianocore/edk2&quot;&gt;TianoCore GIT Projekt&lt;/a&gt; 
und startet dessen Build-Prozess.&lt;/p&gt;

&lt;p&gt;Eine hervorragende Anleitung dazu, die auch bei mir unter Windows in 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Windows-Subsystem_f%C3%BCr_Linux&quot;&gt;WSL&lt;/a&gt; (Ubuntu 18.04)
funktioniert hat, findet man unter&lt;br /&gt;
&lt;a href=&quot;https://fabianlee.org/2018/09/12/kvm-building-the-latest-ovmf-firmware-for-virtual-machines/&quot;&gt;fabianlee.org/2018/09/12/kvm-building-the-latest-ovmf-firmware-for-virtual-machines/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hier die Kommandos, die ich erfolgreich ausführen konnte:&lt;/p&gt;

&lt;div class=&quot;language-console highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;## script from fabianlee.org:
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;sudo apt-get install build-essential git uuid-dev iasl nasm python -y
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;sudo apt-get install iasl -y
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;mkdir -p uuefi; cd uuefi
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;git clone git://github.com/tianocore/edk2.git
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;cd edk2
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;git submodule update --init
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;source ./edksetup.sh
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;make -C BaseTools/
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;build -a X64 -t GCC5 -b RELEASE -p OvmfPkg/OvmfPkgX64.dsc
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Nach dem Durchlaufen der Build-Prozesse findet man unter
&lt;code&gt;Build/OvmfX64/RELEASE_GCC5/FV/OVMF.fd&lt;/code&gt; die Firmware-Datei, mit der man 
&lt;code&gt;QEMU&lt;/code&gt; zur Ausführung von EFI-Apps bringen kann.&lt;/p&gt;

&lt;h3 id=&quot;usb-stack-fat-image-mit-mtools&quot;&gt;USB-Stack FAT Image mit mtools&lt;/h3&gt;

&lt;p&gt;EFI braucht am Ende einen Datenträger, von dem gebootet werden kann.
Natürlich könnte man jetzt einen richtigen USB-Stick formatieren und
die Dateien einspielen und dann ein binäres Image davon ziehen, aber
das wäre extrem mühsam.&lt;/p&gt;

&lt;p&gt;Linux liefert aber mit den &lt;code&gt;mtools&lt;/code&gt; einige sehr nützlich Programme mit,
die Dateisysteme “offline” bearbeiten können, und wie üblich ist es dabei
egal, ob es um reale Datenträger, oder nur Image-Dateien geht.&lt;/p&gt;

&lt;p&gt;EFI erwartet eine &lt;a href=&quot;https://de.wikipedia.org/wiki/File_Allocation_Table&quot;&gt;FAT&lt;/a&gt; 
Partition, in der im Unterverzeichnis &lt;code&gt;/EFI/BOOT&lt;/code&gt; die Datei &lt;code&gt;BOOTX64.EFI&lt;/code&gt; 
liegt.&lt;br /&gt;
Ein schönes Beispiel findet man auf&lt;br /&gt;
&lt;a href=&quot;https://wiki.osdev.org/UEFI_App_Bare_Bones#Creating_the_FAT_image&quot;&gt;wiki.osdev.org/UEFI_App_Bare_Bones&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nachdem ich mit Windows und WSL arbeite, müssen die &lt;code&gt;mtools&lt;/code&gt; mit
&lt;code&gt;sudo apt install mtools&lt;/code&gt; zuvor installiert sein. 
Danach kann man folgendes &lt;a href=&quot;https://de.wikipedia.org/wiki/Stapelverarbeitungsdatei&quot;&gt;BATCH&lt;/a&gt; 
Script nutzen:&lt;/p&gt;

&lt;div class=&quot;language-batch highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;COPY path\to\built\efi-app.efi BOOTX64.EFI
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;wsl dd if=/dev/zero of=./efi-boot.img bs=1k count=2880
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;wsl mformat -i ./efi-boot.img -f 2880 ::
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;wsl mmd -i ./efi-boot.img ::/EFI
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;wsl mmd -i ./efi-boot.img ::/EFI/BOOT
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;wsl mcopy -i ./efi-boot.img ./BOOTX64.EFI ::/EFI/BOOT
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;In &lt;code&gt;efi-boot.img&lt;/code&gt; liegt dann ein Disketten-FAT-Image (hier mit 2.88 MB), in
welches die EFI-App als &lt;code&gt;BOOTX64.EFI&lt;/code&gt; integriert ist.
EFI-Apps sind ja normalerweise nicht mehrere Megabytes groß, womit das kleine
Laufwerk reicht. Wer mehr will, kann natürlich auch ganze virtuelle 
Festplatten mit &lt;a href=&quot;https://de.wikipedia.org/wiki/GUID_Partition_Table&quot;&gt;GUID-Partitionstabelle&lt;/a&gt;
und einer eigenen EFI-Partition anlegen.&lt;/p&gt;

&lt;p&gt;Da das &lt;code&gt;wsl&lt;/code&gt; Kommando die Linux-Prozesse so startet, dass das 
Arbeitsverzeichnis in WSL auf das Windows-Dateisystem zeigt, schreiben die
&lt;code&gt;mtools&lt;/code&gt; die Dateien in das Verzeichnis, in dem das BATCH Script ausgeführt
wurde.&lt;/p&gt;

&lt;h3 id=&quot;qemu-mit-efi-firmware-und-image-starten&quot;&gt;QEMU mit EFI-Firmware und Image starten&lt;/h3&gt;

&lt;p&gt;Das finale magische Kommando lautet:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;qemu-system-x86_64 -L OVMF_dir/ -pflash OVMF.fd -drive if=none,id=stick,format=raw,file=efi-boot.img -device nec-usb-xhci,id=xhci -device usb-storage,bus=xhci.0,drive=stick&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Wichtig ist, dass die &lt;code&gt;QEMU&lt;/code&gt; Programme im &lt;code&gt;PATH&lt;/code&gt; liegen und dass sowohl &lt;code&gt;OVMF.fd&lt;/code&gt; 
und &lt;code&gt;efi-boot.img&lt;/code&gt; (oder wie auch immer man die Dateien nennen möchte) über
die &lt;code&gt;qemu-system-x86_64&lt;/code&gt; Parameter erreichbar sind.&lt;/p&gt;

&lt;p&gt;Dann öffnet sich nämlich das Emulator-Fenster und wenn die eigene EFI-App 
richtig erstellt wurde, kann man ihren Output am Bildschirm sehen und daran
Freude haben.&lt;/p&gt;

&lt;p&gt;Ich habe mir daher meine gebaute &lt;code&gt;OVMF.fd&lt;/code&gt; fix zum Projekt hinzugefügt und 
lasse eine von MSVC fertig gebaute EFI APP mit folgendem Script bei mir 
ausführen:&lt;/p&gt;

&lt;div class=&quot;language-batch highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;@ECHO OFF
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;REM Starting in &amp;quot;\scripts&amp;quot;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;cd ..\bin
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;REM Cleanup output directory
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;rmdir /s /q efi_x64_env
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;mkdir efi_x64_env
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;REM Create EFI boot image
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;copy ..\build\msbuild_efi64\deploy\bin\Release\gatecli.efi ^
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;  .\efi_x64_env\BOOTX64.EFI
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;wsl dd if=/dev/zero of=./efi_x64_env/efi-boot.img bs=1k count=2880
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;wsl mformat -i ./efi_x64_env/efi-boot.img -f 2880 ::
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;wsl mmd -i ./efi_x64_env/efi-boot.img ::/EFI
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;wsl mmd -i ./efi_x64_env/efi-boot.img ::/EFI/BOOT
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;wsl mcopy -i ./efi_x64_env/efi-boot.img ^
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;  ./efi_x64_env/BOOTX64.EFI ::/EFI/BOOT
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;REM Start QEMU session
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;SET PATH=C:\Program Files\qemu;%PATH%
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;qemu-system-x86_64 ^
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;  -L OVMF_dir/ -pflash OVMF.fd -drive ^
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  if=none,id=stick,format=raw,file=.\efi_x64_env\efi-boot.img ^
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n21&quot; name=&quot;n21&quot;&gt;21&lt;/a&gt;&lt;/span&gt;  -device nec-usb-xhci,id=xhci ^
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n22&quot; name=&quot;n22&quot;&gt;22&lt;/a&gt;&lt;/span&gt;  -device usb-storage,bus=xhci.0,drive=stick
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Meine ersten Experimente waren echt mühsam. Jedes Kompilat wurde manuell auf
einen USB-Stick kopiert und dann wurde ein Test-Mainboard damit gestartet.&lt;/p&gt;

&lt;p&gt;Mit &lt;code&gt;QEMU&lt;/code&gt; und &lt;code&gt;mtools&lt;/code&gt; lässt sich eine EFI-App binnen Sekunden in einer 
virtuellen Umgebung testen und das ist einfach nur &lt;em&gt;geil&lt;/em&gt;!&lt;/p&gt;

&lt;p&gt;Mit diesem Werkzeug werde ich also noch einige Zeit verbringen.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Generische Sinus und Cosinus Implementierung</title>
   <link href="https://www.opengate.at/blog/2021/12/sine-cosine/"/>
   <published>2021-12-04T12:00:00+01:00</published>
   <updated>2021-12-04T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2021/12/sine-cosine</id>
   <category term="devel" />
   <summary type="text">Normalerweise verlässt man sich auf die 
C Standard Bibliothek, 
wenn man etwas Trigonometrisches braucht.

Aber was tut man, wenn man diese nicht parat hat, wie in einer nativen 
EFI App,
und auch kein Inline-Assembler 
vom Compiler unterstützt wird.
</summary>
   <content type="html">&lt;p&gt;Normalerweise verlässt man sich auf die 
&lt;a href=&quot;https://de.wikipedia.org/wiki/C-Standard-Bibliothek&quot;&gt;C Standard Bibliothek&lt;/a&gt;, 
wenn man etwas Trigonometrisches braucht.&lt;/p&gt;

&lt;p&gt;Aber was tut man, wenn man diese nicht parat hat, wie in einer nativen 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Unified_Extensible_Firmware_Interface&quot;&gt;EFI App&lt;/a&gt;,
und auch kein Inline-&lt;a href=&quot;https://de.wikipedia.org/wiki/Assemblersprache&quot;&gt;Assembler&lt;/a&gt; 
vom Compiler unterstützt wird.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Oft ist es einfach wichtig, den richtigen Begriff zu kennen und den Rest 
erledigt die Suchmaschine des Vertrauens.&lt;br /&gt;
Und da war doch was in der Mathe-Vorlesung zur Analysis:&lt;/p&gt;

&lt;h3 id=&quot;die-taylor-reihe&quot;&gt;Die Taylor-Reihe&lt;/h3&gt;

&lt;p&gt;Wenn wir von einer Funktion immer Ableitungen bilden und diese nach dem 
Taylorschein Lehrsatz aufsummieren, erhält man abstrakt:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;f(x) = f(x0) 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;     + f1(x0) * (x - x0) ^ 1 / 1! 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;     + f2(x0) * (x - x0) ^ 2 / 2!
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;     + ...
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;     + fn(x0) * (x - x0) ^ n / n!
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Und nachdem die Ableitungen von Sinus und Kosinus sich mit alternierendem 
Vorzeichen abwechseln (cos, -sin, -cos, sin, cos, …) und &lt;code&gt;sin(0) == 0&lt;/code&gt;
und &lt;code&gt;cos(0) == 1&lt;/code&gt; ist, haben wir in Schule folgende alternierende Annäherung 
kennen gelernt:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;sin(x) = 0 + x^1 / 1! - x^3 / 3! + x^5 / 5! - x^7 / 7! + ...
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;cos(x) = 1 - x^2 / 2! + x^4 / 4! - x^6 / 6! + x^8 / 8! - ...
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Zumindest, wenn &lt;code&gt;x&lt;/code&gt; ein Winkel in Radianten zwischen &lt;code&gt;-PI&lt;/code&gt; und &lt;code&gt;+PI&lt;/code&gt; ist.&lt;/p&gt;

&lt;p&gt;Die Taylor-Reihe wird um so genauer, je länger sie ist. 
Mathematiker können zeigen, dass wir nur ein paar Iterationen brauchen,
um ausreichend genau zu sein, damit wir damit ein bisschen rechnen können.
Siehe &lt;a href=&quot;https://dotancohen.com/eng/taylor-sine.php&quot;&gt;dotancohen.com/eng/taylor-sine.php&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Nachdem ich bei meinen Unit-Tests Genauigkeiten von mindestens 4 
Nachkommastellen haben wollte, musste ich die Iterationen bis 
&lt;code&gt;zu x^13&lt;/code&gt; erweitern.&lt;/p&gt;

&lt;h3 id=&quot;sinus-und-cosinus-selbst-implementieren&quot;&gt;Sinus und Cosinus selbst implementieren&lt;/h3&gt;

&lt;p&gt;Wenn in Embedded Plattformen was fehlt, dann fast alles. Und nachdem man sein
eigenes &lt;code&gt;malloc&lt;/code&gt; und  &lt;code&gt;free&lt;/code&gt; nachgebaut hat, folgen die mathematischen
Funktionen gänzlich ohne &lt;code&gt;math.h&lt;/code&gt;.&lt;br /&gt;
Aber, ein Code sagt mehr als 1000 Worte:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;static&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;double&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt; pi = &lt;span style=&quot;color:#60E&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color:#60E&quot;&gt;.14159265358979323846&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;static&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;double&lt;/span&gt; normalize(&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;double&lt;/span&gt; angle)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;while&lt;/span&gt;(angle &amp;lt;= pi) angle += pi;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;while&lt;/span&gt;(angle &amp;gt; pi) angle -= pi;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; angle;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;}
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;static&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;double&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt; n2 = &lt;span style=&quot;color:#60E&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#60E&quot;&gt;.0&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;static&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;double&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt; n3 = &lt;span style=&quot;color:#60E&quot;&gt;6&lt;/span&gt;&lt;span style=&quot;color:#60E&quot;&gt;.0&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;static&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;double&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt; n4 = &lt;span style=&quot;color:#00D&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#60E&quot;&gt;4&lt;/span&gt;&lt;span style=&quot;color:#60E&quot;&gt;.0&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;static&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;double&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt; n5 = &lt;span style=&quot;color:#00D&quot;&gt;12&lt;/span&gt;&lt;span style=&quot;color:#60E&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#60E&quot;&gt;.0&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;static&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;double&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt; n6 = &lt;span style=&quot;color:#00D&quot;&gt;72&lt;/span&gt;&lt;span style=&quot;color:#60E&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#60E&quot;&gt;.0&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;static&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;double&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt; n7 = &lt;span style=&quot;color:#00D&quot;&gt;504&lt;/span&gt;&lt;span style=&quot;color:#60E&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#60E&quot;&gt;.0&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;static&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;double&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt; n8 = &lt;span style=&quot;color:#00D&quot;&gt;4032&lt;/span&gt;&lt;span style=&quot;color:#60E&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#60E&quot;&gt;.0&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;static&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;double&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt; n9 = &lt;span style=&quot;color:#00D&quot;&gt;36288&lt;/span&gt;&lt;span style=&quot;color:#60E&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#60E&quot;&gt;.0&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;static&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;double&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt; n10 = &lt;span style=&quot;color:#00D&quot;&gt;362880&lt;/span&gt;&lt;span style=&quot;color:#60E&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#60E&quot;&gt;.0&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;static&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;double&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt; n11 = &lt;span style=&quot;color:#00D&quot;&gt;3991680&lt;/span&gt;&lt;span style=&quot;color:#60E&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#60E&quot;&gt;.0&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;static&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;double&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt; n12 = &lt;span style=&quot;color:#00D&quot;&gt;47900160&lt;/span&gt;&lt;span style=&quot;color:#60E&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#60E&quot;&gt;.0&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n21&quot; name=&quot;n21&quot;&gt;21&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;static&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;double&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt; n13 = &lt;span style=&quot;color:#00D&quot;&gt;622702080&lt;/span&gt;&lt;span style=&quot;color:#60E&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#60E&quot;&gt;.0&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n22&quot; name=&quot;n22&quot;&gt;22&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n23&quot; name=&quot;n23&quot;&gt;23&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;double&lt;/span&gt; approx_cos(&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;double&lt;/span&gt; value)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n24&quot; name=&quot;n24&quot;&gt;24&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n25&quot; name=&quot;n25&quot;&gt;25&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;double&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt; x = normalize(value);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n26&quot; name=&quot;n26&quot;&gt;26&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;double&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt; x3 = x * x * x;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n27&quot; name=&quot;n27&quot;&gt;27&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;double&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt; x5 = x3 * x * x;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n28&quot; name=&quot;n28&quot;&gt;28&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;double&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt; x7 = x5 * x * x;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n29&quot; name=&quot;n29&quot;&gt;29&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;double&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt; x9 = x7 * x * x;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n30&quot; name=&quot;n30&quot;&gt;30&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;double&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt; x11 = x9 * x * x;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n31&quot; name=&quot;n31&quot;&gt;31&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;double&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt; x13 = x11 * x * x;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n32&quot; name=&quot;n32&quot;&gt;32&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; x - x3 / n3 + x5 / n5 - x7 / n7 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n33&quot; name=&quot;n33&quot;&gt;33&lt;/a&gt;&lt;/span&gt;       + x9 / n9 - x11 / n11 + x13 / n13;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n34&quot; name=&quot;n34&quot;&gt;34&lt;/a&gt;&lt;/span&gt;}
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n35&quot; name=&quot;n35&quot;&gt;35&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n36&quot; name=&quot;n36&quot;&gt;36&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;double&lt;/span&gt; approx_sin(&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;double&lt;/span&gt; value)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n37&quot; name=&quot;n37&quot;&gt;37&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n38&quot; name=&quot;n38&quot;&gt;38&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;double&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt; x = normalize(value);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n39&quot; name=&quot;n39&quot;&gt;39&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;double&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt; x2 = x * x;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n40&quot; name=&quot;n40&quot;&gt;40&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;double&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt; x4 = x2 * x * x;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n41&quot; name=&quot;n41&quot;&gt;41&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;double&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt; x6 = x4 * x * x;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n42&quot; name=&quot;n42&quot;&gt;42&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;double&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt; x8 = x6 * x * x;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n43&quot; name=&quot;n43&quot;&gt;43&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;double&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt; x10 = x8 * x * x;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n44&quot; name=&quot;n44&quot;&gt;44&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;double&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt; x12 = x10 * x * x;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n45&quot; name=&quot;n45&quot;&gt;45&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt; - x2 / n2 + x4 / n4 - x6 / n6 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n46&quot; name=&quot;n46&quot;&gt;46&lt;/a&gt;&lt;/span&gt;       + x8 / n8 - x10 / n10 + x12 / n12;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n47&quot; name=&quot;n47&quot;&gt;47&lt;/a&gt;&lt;/span&gt;}
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n48&quot; name=&quot;n48&quot;&gt;48&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n49&quot; name=&quot;n49&quot;&gt;49&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;double&lt;/span&gt; approx_tan(&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;double&lt;/span&gt; value)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n50&quot; name=&quot;n50&quot;&gt;50&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n51&quot; name=&quot;n51&quot;&gt;51&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; approx_sin(value) / approx_cos(value);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n52&quot; name=&quot;n52&quot;&gt;52&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;So in etwa sieht der Kompatibilitäts-Layer im GATE Projekt aus, der genau
für solche Spezialfälle aktiviert werden kann. (z.B. bei EFI Apps.)&lt;/p&gt;

&lt;p&gt;Für den Arkussinus gibt es ebenfalls eine &lt;a href=&quot;https://de.wikipedia.org/wiki/Arkussinus_und_Arkuskosinus#Reihenentwicklungen&quot;&gt;Reihenentwicklung&lt;/a&gt;
und der Arkuskosinus sollte mit &lt;code&gt;acos(x) = PI / 2.0 - asin(x)&lt;/code&gt; erreicht 
werden können.&lt;/p&gt;

&lt;p&gt;Wenn nötig, kann man dann auch die “echten” C Funktionen so nachbauen,
und genau das musste ich tun, um diverse Fremdbibliotheken durch den
Linker zu bekommen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Wenn man “normale” Bibliotheken in diverse embedded Umgebungen einpflanzen
möchte, passiert es, dass es keine C-Lib Implementierung gibt. Und dann 
tauchen zahlreiche “undefinierte Symbole” beim Linken auf.&lt;br /&gt;
Und das kann auch &lt;code&gt;sin()&lt;/code&gt;, &lt;code&gt;cos()&lt;/code&gt; und ihre Geschwister treffen.&lt;/p&gt;

&lt;p&gt;Genau dafür ist es gut, dass man eine primitive Implementierung parat hat,
damit man fortsetzen kann.&lt;br /&gt;
Selbstverständlich sollte immer eine ordentliche Mathematik-Bibliothek
im finalen Kompilat landen, die auf die Plattform optimiert ist.&lt;/p&gt;

&lt;p&gt;… doch leider ist das eben nicht immer möglich.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>UEFI Apps erstellen</title>
   <link href="https://www.opengate.at/blog/2021/11/efi-apps/"/>
   <published>2021-11-28T12:00:00+01:00</published>
   <updated>2021-11-28T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2021/11/efi-apps</id>
   <category term="devel" />
   <summary type="text">Der Traum meiner Kindheit rückt wieder näher: “Mein eigenes OS”

Vor etwas über 20 Jahren hatten einige Idealisten wie ich noch die Idee,
mit BIOS Interrupts und ein paar 
Assemblerzeilen Programme zu
schreiben, die kein OS brauchten und direkt von der 
Diskette booten konnten.

Heute ist die Sache viel einfacher, denn heute haben wir 
UEFI.
</summary>
   <content type="html">&lt;p&gt;Der Traum meiner Kindheit rückt wieder näher: &lt;em&gt;“Mein eigenes &lt;a href=&quot;https://de.wikipedia.org/wiki/Betriebssystem&quot;&gt;OS&lt;/a&gt;”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Vor etwas über 20 Jahren hatten einige Idealisten wie ich noch die Idee,
mit &lt;a href=&quot;https://de.wikipedia.org/wiki/BIOS&quot;&gt;BIOS&lt;/a&gt; Interrupts und ein paar 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Assemblersprache&quot;&gt;Assemblerzeilen&lt;/a&gt; Programme zu
schreiben, die kein OS brauchten und direkt von der 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Diskette&quot;&gt;Diskette&lt;/a&gt; booten konnten.&lt;/p&gt;

&lt;p&gt;Heute ist die Sache viel einfacher, denn heute haben wir 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Unified_Extensible_Firmware_Interface&quot;&gt;UEFI&lt;/a&gt;.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Viele Sicherheitsprobleme entstehen auf Grund der Komplexität von modernen
Betriebssystemen. Ein offener &lt;a href=&quot;https://de.wikipedia.org/wiki/Webserver&quot;&gt;Webserver&lt;/a&gt; 
Port lässt dann über eine ungenutzte Zusatzfunktion Viren hereinströmen, 
wo man sich immer fragt:&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;Wieso war diese Funktion überhaupt da?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Und dann haben wir &lt;a href=&quot;https://de.wikipedia.org/wiki/Mikrocontroller&quot;&gt;Mikrocontroller&lt;/a&gt; 
wie den ESP32, der von solchen Problemen zwar nicht grundsätzlich verschont 
ist, der aber trotzdem einfache Dienst anbieten kann, die eben nicht durch
Trillionen von Seiteneffekten kontaminiert werden.&lt;/p&gt;

&lt;p&gt;Warum haben wir das nicht auch auf der PC Plattform?&lt;/p&gt;

&lt;h3 id=&quot;efi-apps-als-lösung&quot;&gt;EFI Apps als Lösung&lt;/h3&gt;

&lt;p&gt;Das &lt;em&gt;Extensible Firmware Interface&lt;/em&gt; ist mehr als nur ein neues BIOS, denn es
stellt eine wesentlich breitere Menge an Diensten bereit, als das alte BIOS,
das lediglich einen Textbildschirm, eine Tastatur, Disketten und max. 8 GB
Festplatten ansprechen konnte.&lt;/p&gt;

&lt;p&gt;Es fügt nämlich Netzwerke, &lt;a href=&quot;https://de.wikipedia.org/wiki/Transmission_Control_Protocol&quot;&gt;TCP&lt;/a&gt;, 
&lt;a href=&quot;https://de.wikipedia.org/wiki/User_Datagram_Protocol&quot;&gt;UDP&lt;/a&gt;, 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Serielle_Schnittstelle&quot;&gt;serielle Ports&lt;/a&gt; und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Dateisystem&quot;&gt;Dateisysteme&lt;/a&gt; hinzu und damit haben
 wir eine Basis, mit der man ganz ohne ein Betriebssystem Code ausführen kann.&lt;br /&gt;
Man kompiliert sich ein EFI-Binary, packt es auf einen USB-Stick, bootet
in die EFI-Shell, wechselt auf den USB-Datenträger und führt die Datei
aus.&lt;br /&gt;
Und liegt die Datei im “richtigen” Verzeichnis, wird sie vom EFI Bootloader
automatisch gestartet.&lt;/p&gt;

&lt;h3 id=&quot;gnu-efi-und-der-msvc&quot;&gt;GNU-EFI und der MSVC&lt;/h3&gt;

&lt;p&gt;Das Projekt &lt;a href=&quot;https://sourceforge.net/projects/gnu-efi/&quot;&gt;GNU-EFI&lt;/a&gt; liefert alle
notwendigen Header und statischen Code, um primitive EFI-Anwendungen 
programmieren zu können.&lt;br /&gt;
Während die meisten Beispiele im Netz dazu für &lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt;
bzw. den &lt;a href=&quot;https://de.wikipedia.org/wiki/GNU_Compiler_Collection&quot;&gt;GCC&lt;/a&gt; 
ausgelegt sind, unterstützt auch Microsoft’s 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_C%2B%2B&quot;&gt;MSVC&lt;/a&gt; das EFI-Format als 
Zielplattform und mit ein paar Anpassungen, kann er &lt;code&gt;gnu-efi&lt;/code&gt; auch benutzen.&lt;/p&gt;

&lt;p&gt;Das ist auch kein Wunder, schließlich hat Microsoft den EFI-Standard 
mitdefiniert und dabei das unter Windows übliche 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Portable_Executable&quot;&gt;PE-Format&lt;/a&gt; in EFI etabliert.&lt;/p&gt;

&lt;p&gt;Man braucht also nur vom Subsystem &lt;code&gt;WINDOWS&lt;/code&gt; bzw. &lt;code&gt;CONSOLE&lt;/code&gt; zu 
&lt;code&gt;EFI_APPLICATION&lt;/code&gt; wechseln und kann loslegen.&lt;br /&gt;
… allerdings muss man sich dafür von der C-Runtime und vielen hilfreichen
Funktionen angefangen bei &lt;a href=&quot;https://www.cplusplus.com/reference/cstdlib/malloc/&quot;&gt;&lt;code&gt;malloc()&lt;/code&gt;&lt;/a&gt;
verabschieden.&lt;br /&gt;
Und &lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B&quot;&gt;C++&lt;/a&gt; muss auch weichen … außer 
man hat eine Strategie für C++ ohne Exceptions und &lt;code&gt;RTTI&lt;/code&gt;, was schwierig 
aber nicht gänzlich unmöglich ist.&lt;/p&gt;

&lt;h3 id=&quot;cmake-efi-einstellungen-für-msvc&quot;&gt;CMake EFI Einstellungen für MSVC&lt;/h3&gt;

&lt;p&gt;Folgende Compiler Flags sind für EFI hilfreich und können in 
&lt;a href=&quot;https://de.wikipedia.org/wiki/CMake&quot;&gt;CMake&lt;/a&gt; definiert werden:&lt;br /&gt;
(Die C-Flags sind auch für C++ notwendig unter &lt;code&gt;CMAKE_CXX_FLAGS&lt;/code&gt;)&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;string (REPLACE &quot;/DWIN32&quot; &quot;&quot; CMAKE_C_FLAGS ${CMAKE_C_FLAGS})&lt;/code&gt;&lt;br /&gt;
Das &lt;code&gt;WIN32&lt;/code&gt; Symbol sollte verschwinden, damit keine Makros davon 
irritiert werden.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;string (REPLACE &quot;/D_WINDOWS&quot; &quot;&quot; CMAKE_C_FLAGS ${CMAKE_C_FLAGS})&lt;/code&gt;&lt;br /&gt;
Auch das automatisch generierte &lt;code&gt;_WINDOWS&lt;/code&gt; Symbol sollte weg.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;string (REPLACE &quot;/EHsc&quot; &quot;&quot; CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;string (REPLACE &quot;/EHs&quot; &quot;&quot; CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;string (REPLACE &quot;/EHa&quot; &quot;&quot; CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})&lt;/code&gt;&lt;br /&gt;
C++ muss auf jegliche Art von Exceptions verzichten.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;set(CMAKE_C_FLAGS &quot;${CMAKE_C_FLAGS} /Gm-&quot;)&lt;/code&gt;&lt;br /&gt;
Einstellung: &lt;code&gt;Enable Minimal Rebuild&lt;/code&gt; sollte deaktiviert sein.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;set(CMAKE_C_FLAGS &quot;${CMAKE_C_FLAGS} /GS-&quot;)&lt;/code&gt;&lt;br /&gt;
Security Checks müssen deaktiviert sein, weil sie auf die 
C-Runtime verweisen.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;set(CMAKE_C_FLAGS &quot;${CMAKE_C_FLAGS} /GR-&quot;)&lt;/code&gt;&lt;br /&gt;
Run-Time Type Information (RTTI) braucht auch eine Runtime, die wir unter
EFI nicht haben&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;set(CMAKE_C_FLAGS &quot;${CMAKE_C_FLAGS} /TC&quot;)&lt;/code&gt;&lt;br /&gt;
Die Option “Compile As: Compile As C Code” hilft bei nur-C Projekten&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;set(CMAKE_C_FLAGS &quot;${CMAKE_C_FLAGS} /Gs16384&quot;)&lt;/code&gt;&lt;br /&gt;
Diese Geheimoption lässt alle Stackvariablen 16 KB statt nur 4 KB groß sein.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Die nachfolgenden Linker-Flags sind ganz besonders wichtig:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;set(CMAKE_EXE_LINKER_FLAGS &quot;${CMAKE_EXE_LINKER_FLAGS} /NODEFAULTLIB&quot;)&lt;/code&gt;&lt;br /&gt;
Die C-Runtime und alle anderen Windows-Lasten werden nicht automatisch gelinkt&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;set(CMAKE_EXE_LINKER_FLAGS &quot;${CMAKE_EXE_LINKER_FLAGS} /MANIFEST:NO&quot;)&lt;/code&gt;&lt;br /&gt;
Ein Windows-Manifest braucht man in EFI auch nicht.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;set(CMAKE_EXE_LINKER_FLAGS &quot;${CMAKE_EXE_LINKER_FLAGS} /SUBSYSTEM:EFI_APPLICATION&quot;)&lt;/code&gt;&lt;br /&gt;
Und ohne dem EFI-Subsystem bekommen wir sowieso keine EFI App heraus.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;set(CMAKE_EXE_LINKER_FLAGS &quot;${CMAKE_EXE_LINKER_FLAGS} /OPT:REF&quot;)&lt;/code&gt;&lt;br /&gt;
Nicht benutzte Funktionen im Code sollen weg-optimiert werden.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;set(CMAKE_EXE_LINKER_FLAGS &quot;${CMAKE_EXE_LINKER_FLAGS} /ENTRY:efi_main&quot;)&lt;/code&gt;&lt;br /&gt;
Wir setzen explizit einen anderen Einsprungpunkt namens &lt;code&gt;efi_main&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;set(CMAKE_EXE_LINKER_FLAGS &quot;${CMAKE_EXE_LINKER_FLAGS} /NXCOMPAT:NO&quot;)&lt;/code&gt;&lt;br /&gt;
Auf die Data Execution Protection wollen wir uns auch nicht berufen.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;set(CMAKE_EXE_LINKER_FLAGS &quot;${CMAKE_EXE_LINKER_FLAGS} /DYNAMICBASE:NO&quot;)&lt;/code&gt;&lt;br /&gt;
Und zufällige Adressen (als Schutz gegen Windows-Viren) sind unter EFI 
ebenfalls nicht notwendig bzw. nicht möglich.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Man kann jetzt noch weitere Wichteleien anfügen, wie dass &lt;code&gt;.efi&lt;/code&gt; und nicht
&lt;code&gt;.exe&lt;/code&gt; am Ende herauskommt … aber die genannten Einstellungen sollten
für den Kompilier- und Link-Vorgang ausreichen, damit man das erste 
Testprojekt bauen kann.&lt;/p&gt;

&lt;p&gt;Die &lt;code&gt;gnu-efi&lt;/code&gt; Bibliothek (und auch alle anderen Libs) müssen natürlich
statisch zur EFI-App gelinkt werden.
(Soetwas wie DLLs gibt es in EFI-Apps nicht.)&lt;/p&gt;

&lt;h3 id=&quot;runtime-und-stack-spezialitäten&quot;&gt;Runtime und Stack-Spezialitäten&lt;/h3&gt;

&lt;p&gt;Nachdem keine C-Runtime vorhanden ist, fallen Funktionen für Trigonometrie
und Rundungen weg. Das schränkt den Handlungsspielraum ein und man müsste
diese Routinen per Assembler oder C selbst nachbauen, wenn man andere C
Libs nutzen möchte, die darauf verweisen.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;malloc&lt;/code&gt; und &lt;code&gt;free&lt;/code&gt; sind vermutlich die wichtigsten Utensilien, doch zum
Glück stellt EFI mit seinen “BootServices” auch einfache Blockallokierungs-
Routinen bereit, die man als &lt;code&gt;malloc&lt;/code&gt; Ersatz nutzen kann.&lt;/p&gt;

&lt;p&gt;Erste Link-Test liefern gerne Fehler, wie&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;code&gt;error LNK2019: unresolved external symbol __chkstk&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;error LNK2019: unresolved external symbol __fltused&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;code&gt;_chkstk&lt;/code&gt; ist ein interessanter Funktionsaufruf, den der Compiler automatisch
einfügt, wenn ein Stackframe über 4 KB groß wird. Der Aufruf soll unter Windows
eine Memory-Exception auflösen, wenn der aktuell allokierte Stack ausgeht, 
worauf das OS den Stack nach Möglichkeit vergrößert.&lt;br /&gt;
Und nachdem &lt;code&gt;_chkstk&lt;/code&gt; in der C Runtime implementiert ist, fehlt sie unter EFI.
Ich weiß nicht, wieviel Stack in EFI generell zur Verfügung steht, aber das 
Compilerflag &lt;code&gt;/Gs16384&lt;/code&gt; erhöht die Toleranzgrenze auf 16 KB … und man könnte
es noch höher drehen.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;_fltused&lt;/code&gt; ist eine andere globale CRT Variable in Bezug auf 
Fließkommarechnungen, die im MSVC offenbar darauf zugreifen wollen.
Ein “schneller Fix” dafür ist einfach ein:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;extern&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; _fltused = &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;womit wir die Variable formal im Programm haben. (Ich fürchte aber, dass 
diverse weitere Fließkomma-Operationen Patches bräuchten, so bald man sie 
einsetzt.)&lt;/p&gt;

&lt;h3 id=&quot;efi_main-und-efi_system_table&quot;&gt;efi_main und EFI_SYSTEM_TABLE&lt;/h3&gt;

&lt;p&gt;Der EFI-Einsprungpunkt bekommt ein &lt;code&gt;HANDLE&lt;/code&gt; zur laufenden App und einen 
Pointer zur &lt;code&gt;EFI_SYSTEM_TABLE&lt;/code&gt;, die jede Menge Pointer zu Unterobjekten und
Funktionen enthält, mit denen man programmieren kann.&lt;/p&gt;

&lt;p&gt;Zusätzlich bietet die &lt;code&gt;gnu-efi/efilib.h&lt;/code&gt; einige Funktionen an, die so ähnlich 
wie die C-Runtime aussehen, z.B.: &lt;code&gt;Print()&lt;/code&gt; als Alternative zu &lt;code&gt;printf()&lt;/code&gt;.
Die meisten dieser Routinen sind aber nur Wrapper zur Funktionstabelle, 
die mit der &lt;code&gt;EFI_SYSTEM_TABLE&lt;/code&gt; übermittelt wurde.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color:#B44;font-weight:bold&quot;&gt;&amp;lt;efi.h&amp;gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color:#B44;font-weight:bold&quot;&gt;&amp;lt;efilib.h&amp;gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;extern&lt;/span&gt; EFI_STATUS efi_main(EFI_HANDLE efi_handle, EFI_SYSTEM_TABLE* sys_tbl)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;  UINTN efi_event;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  InitializeLib(efi_handle, sys_tbl);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;  Print(L&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Hello World&lt;/span&gt;&lt;span style=&quot;color:#b0b&quot;&gt;\n&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;  sys_tbl-&amp;gt;ConIn-&amp;gt;Reset(sys_tbl-&amp;gt;ConIn, FALSE);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  sys_tbl-&amp;gt;BootServices-&amp;gt;WaitForEvent(&lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;, &amp;amp;sys_tbl-&amp;gt;ConIn-&amp;gt;WaitForKey, &amp;amp;efi_event);  
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; EFI_SUCCESS;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Ein gutes und vollständiges Beispiel findet man unter 
&lt;a href=&quot;https://github.com/utshina/uefi-simple&quot;&gt;uefi-simple&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ich habe mir die Mühe gemacht und &lt;code&gt;gate/memalloc&lt;/code&gt; und &lt;code&gt;gate/stream&lt;/code&gt; mit einer
EFI-Implementierung versehen. &lt;code&gt;gate/threads&lt;/code&gt; und &lt;code&gt;gate/sychronization&lt;/code&gt; nutzen
die Dummy-Implementierung aus meinem DOS-Layer und schon konnte ich die
erste GATE basierte App für EFI erstellen.&lt;/p&gt;

&lt;p&gt;Es handelt sich dabei zwar nur um Unit-Tests für GATE-CORE Routinen, aber 
sie demonstrierten auf meinem Test-EFI-Mainboard, dass die Speicherverwaltung
und Textausgabe bereits korrekt funktionieren.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Und jetzt bin ich echt aufgegeilt.&lt;/em&gt;&lt;br /&gt;
Denn über &lt;code&gt;systbl-&amp;gt;BootServices-&amp;gt;LocateProtocol&lt;/code&gt; lassen sich über 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Globally_Unique_Identifier&quot;&gt;GUIDs&lt;/a&gt; Protokolle 
wie TCP und UDP einbinden, womit man über einen angeschlossenen
Netzwerkadapter Daten verschicken kann …&lt;br /&gt;
… und all das ohne ein Betriebssystem.&lt;br /&gt;
Boah, das nenne ich mal Freiheit und Abenteuer-Feeling!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>33 % Unvernunft</title>
   <link href="https://www.opengate.at/blog/2021/11/corona-again/"/>
   <published>2021-11-27T12:00:00+01:00</published>
   <updated>2021-11-27T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2021/11/corona-again</id>
   <category term="general" />
   <summary type="text">
  Liebes Corona-Tagebuch!
Lockdown 4 läuft und ich bin jetzt im Dauer-Homeoffice, bis die 
Kontrollen gegen geimpfte Bürger wie mich beendet sind.


</summary>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;Liebes Corona-Tagebuch!&lt;br /&gt;
Lockdown 4 läuft und ich bin jetzt im Dauer-Homeoffice, bis die 
Kontrollen &lt;em&gt;gegen&lt;/em&gt; geimpfte Bürger wie mich beendet sind.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Also, ich lebe seit meiner zweiten Impfung sicher und sorgenfrei und wäre
guter Dinge gewesen, dass alles wieder besser wird.&lt;br /&gt;
Das Tragen von FFP2-Masken ist in den öffentlichen Verkehrsmitteln Standard
geworden, und während mir am Anfang letzten Jahres das Atmen schwerer vorkam,
merke ich das Teil inzwischen nicht mehr.&lt;br /&gt;
Es ist sogar angenehm, jetzt wo es wieder kalt wird, wenn der Mund-Nasenschutz
einem das Gesicht wärmt.&lt;/p&gt;

&lt;h3 id=&quot;bitte-geht-alle-impfen&quot;&gt;Bitte! Geht alle impfen!&lt;/h3&gt;

&lt;p&gt;Aber … ist das nicht komisch?&lt;br /&gt;
Hatte man uns nicht versprochen, dass die Pandemie schon vorbei sei?&lt;/p&gt;

&lt;p&gt;Tja, wenn sich alle Mitbürger an die Regeln gehalten hätten,
wäre es vielleicht schon so weit.&lt;br /&gt;
Doch wieder jede Vernunft mussten alle im Sommerurlaub ins Ausland
fahren und dabei haben sie in engen Bussen und Flugzeugen jede Menge Viren
gezüchtet und an die Restbevölkerung verteilt.&lt;/p&gt;

&lt;p&gt;Und dort weigert sich jetzt ein Drittel zur Impfung zu gehen, einfach nur 
um wie ein trotziges Kleinkind “Nein” sagen zu können.&lt;br /&gt;
Eben diese Personen verstopfen nun mehrheitlich unsere Krankenhäuser und
Intensivstationen, womit wieder mehr Menschen als je zuvor in Österreich
an &lt;a href=&quot;https://de.wikipedia.org/wiki/COVID-19&quot;&gt;COVID-19&lt;/a&gt; erkranken und
teils auch daran sterben.&lt;/p&gt;

&lt;p&gt;Neu hinzugekommen ist eine Statistik von einer großen Anzahl an Menschen, die 
OHNE Corona verstorben sind, aber nur deshalb, weil sie keine Behandlung 
erhalten haben, da Krankenhäuser wegen Corona-Patienten überfüllt waren.&lt;/p&gt;

&lt;p&gt;Es ist also gerade ein verdammt schlechter Zeitpunkt, einen Herzinfarkt zu
bekommen … weil für so etwas haben die Krankenhäuser gerade keinen Termin frei.
Und von der seit zwei Jahre andauernden Überbelastung des medizinischen 
Personals will offenbar auch niemand etwas wissen, obwohl es genau diese 
Helden sind, die uns Tag täglich ohne Dank das Leben retten.&lt;/p&gt;

&lt;p&gt;Ein Fall im Bekanntenkreis machte die Situation deutlich:&lt;br /&gt;
Es war eine Operation notwendig und danach erfolgte eine Ansteckung mit COVID
im Krankenhaus. Dies wurde zum gefürchteten Long-COVID und damit eröffnete
sich ein Leidensweg, der noch lange nicht überstanden ist.&lt;/p&gt;

&lt;p&gt;Zur Impfung oder diversen Regierungsentscheidungen kann man durchaus kritisch
stehen, aber wenn es um den Zusammenbruch der medizinischen Versorgung geht,
dann hat &lt;em&gt;JEDER&lt;/em&gt; die &lt;em&gt;PFLICHT&lt;/em&gt; alles zu unternehmen, um das System zu 
schützen. Und das heißt: &lt;strong&gt;Sofort impfen gehen!&lt;/strong&gt;&lt;/p&gt;

&lt;h3 id=&quot;2g-bald-1g-am-arbeitsplatz&quot;&gt;2G (bald 1G) am Arbeitsplatz&lt;/h3&gt;

&lt;p&gt;Hmm … man könnte sich fast darüber lustig machen:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Die Regierung verlangt ab November 2021 2G für alle Arbeitsplätze.&lt;br /&gt;
Das ist ein Rückschritt, wir haben doch schon &lt;a href=&quot;https://de.wikipedia.org/wiki/5G&quot;&gt;5G Netze&lt;/a&gt;
ausgebaut und jetzt wollen die wieder &lt;a href=&quot;https://de.wikipedia.org/wiki/Global_System_for_Mobile_Communications&quot;&gt;GSM&lt;/a&gt;
erzwingen?  😛 … 😉&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Aber eigentlich pisst mich das an.
Zwar bin ich geimpft und ich halte mich an alle Regeln, will aber nicht 
permanent meinen Impfpass mitnehmen müssen. Nun drohen Strafen zwischen 
500 und 3000 Euro, sollte eine Kontrolle am Arbeitsplatz stattfinden.&lt;br /&gt;
Und das kann jederzeit passieren.&lt;/p&gt;

&lt;p&gt;Ein Monat vor meiner 2. Impfung wurde die automatische “analoge” Zustellung
von Impfzertifikaten einfach abgeschafft. Und weil ich auf gar keinen Fall 
einer schlecht geschriebenen Android-App meine persönlichen Daten aushändigen 
will, habe ich auch keinen “grünen Pass” oder ein Impfzertifikat erhalten.&lt;/p&gt;

&lt;p&gt;Die Geschichte mag durchaus “meine Schuld” sein, denn ich habe vor ein 
paar Jahren nicht ohne Grund alle Dienste beendet, die auf diese 
unerträglichen und unsicheren Smartphone-Lösungen umgestiegen sind.
Die Alternative war damals ein digitales Zertifikat auf meiner 
&lt;a href=&quot;https://de.wikipedia.org/wiki/E-card_(Chipkarte)&quot;&gt;e-Card&lt;/a&gt;, 
das samt Kartenleser perfekt funktioniert hatte …. bis ausgerechnet 
mit Beginn der Pandemie dieser Dienst ersatzlos eingestellt wurde.&lt;/p&gt;

&lt;p&gt;Ich kann also überhaupt keine amtlichen Angelegenheiten mehr online 
regeln und das bleibt bei mir auch so, bis &lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt;
Smartphones wie mein &lt;a href=&quot;https://de.wikipedia.org/wiki/PinePhone&quot;&gt;PinePhone&lt;/a&gt;
unterstützt werden. Und ich laufe in der Pandemie auch sicher nicht
spaßhalber zu Ämtern und setze mich dort auf die Wartebank.&lt;/p&gt;

&lt;p&gt;Mir persönlich tut das nicht weh, und wenn ich ohne grünen Pass nicht 
rausgehen darf, ist das lediglich ein Gewinn für China und Deutschland, 
denn nun wird alles nur noch im Ausland bestellt.&lt;/p&gt;

&lt;p&gt;All das hat mir die Entscheidung sehr leicht gemacht:&lt;br /&gt;
&lt;em&gt;Ich steige um auf permanentes Home-Office.&lt;/em&gt;&lt;br /&gt;
Und das bedeutet vor allem, dass ich länger schlafen kann und nicht mehr
1 Stunde Busfahrt pro Tag verliere.&lt;/p&gt;

&lt;p&gt;Dass jetzt Arbeitnehmer mit Strafen bedroht werden, wenn sie 
keinen Impf- oder Testnachweis zu jeder Zeit vorzeigen können, ist aber 
trotzdem absolut nicht korrekt.&lt;br /&gt;
Anstatt dass die Schuldigen der jüngsten COVID-Ausbrüche zu Rechenschaft 
gezogen werden, werden damit geimpfte Bürger wie ich bestraft.&lt;br /&gt;
Nö, das ist nicht korrekt!&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Das aktuelle Hochschnellen der COVID-Ausbrüche hat zumindest einen 
“positiven” Aspekt: Es haben sich wieder mehr Menschen zur Impfung gemeldet.
Und auch meine 3. Impfung ist bereits auf Ende Dezember fixiert.&lt;/p&gt;

&lt;p&gt;Leider gleicht das die sinnlosen Toten, die wegen Krankenhausüberfüllung
nicht behandelt werden konnten, nicht aus. Zu spät is eben zu spät.&lt;/p&gt;

&lt;p&gt;Da wir erst zwei Drittel der Bevölkerung geimpft haben, kann ich nur 
hoffen, dass ein Großteil des offenen Drittels noch zur Vernunft gelangen 
und eine Impfung durchführen lässt.&lt;br /&gt;
Die Impfung rettet Leben und ist unsere beste Chance die Pandemie so bald
wie möglich hinter uns bringen. Und jede verweigerte Impfung zieht die 
ganze Sache unnötig für alle in die Länge.&lt;/p&gt;

&lt;p&gt;Von daher nochmal:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Geht bitte endlich alle impfen!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;nachtrag&quot;&gt;Nachtrag&lt;/h3&gt;

&lt;p&gt;Endlich habe ich mit &lt;a href=&quot;https://de.wikipedia.org/wiki/Florian_Klenk&quot;&gt;Florian Klenk&lt;/a&gt; 
jemanden gefunden, der “meine Sprache” spricht, wenn er ganz ungeniert fragt:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Warum gibt es keine Werbung für die Impfung auf Pornhub?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;iframe width=&quot;640&quot; height=&quot;360&quot; src=&quot;/blog/redirect.html?https%3A%2F%2Fwww.youtube-nocookie.com%2Fembed%2FQt5LTkFd8ao%3Fstart%3D893&quot; frameborder=&quot;1&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
</content>
 </entry>
 
 <entry>
   <title>Pokemon D/P Remakes</title>
   <link href="https://www.opengate.at/blog/2021/11/pokemon-dp/"/>
   <published>2021-11-21T12:00:00+01:00</published>
   <updated>2021-11-21T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2021/11/pokemon-dp</id>
   <category term="retro" /><category term="entertainment" />
   <summary type="text">Da ist er also wieder. Dieser Moment, der alle paar Jahre kommt, wenn ich 
wieder für kurze Zeit zum Kind werde und einer zwanzig Jahre alten Tradition
nachkomme: Die neueste Pokemon 
Edition wird gekauft und durchgespielt.

Mit “strahlender Diamant” und “leuchtende Perle” sind am Freitag die Remakes
der alten Diamant/Perle 
Editionen aus dem Jahr 2007 (damals am Nintendo DS )
für die aktuelle Nintendo Switch 
erschienen.

</summary>
   <content type="html">&lt;p&gt;Da ist er also wieder. Dieser Moment, der alle paar Jahre kommt, wenn ich 
wieder für kurze Zeit zum Kind werde und einer zwanzig Jahre alten Tradition
nachkomme: Die neueste &lt;a href=&quot;https://de.wikipedia.org/wiki/Pok%C3%A9mon-Spiele&quot;&gt;Pokemon&lt;/a&gt; 
Edition wird gekauft und durchgespielt.&lt;/p&gt;

&lt;p&gt;Mit “strahlender Diamant” und “leuchtende Perle” sind am Freitag die Remakes
der alten &lt;a href=&quot;https://de.wikipedia.org/wiki/Pok%C3%A9mon_Diamant-_und_Perl-Edition&quot;&gt;Diamant/Perle&lt;/a&gt; 
Editionen aus dem Jahr 2007 (damals am &lt;a href=&quot;https://de.wikipedia.org/wiki/Nintendo_DS&quot;&gt;Nintendo DS&lt;/a&gt; )
für die aktuelle &lt;a href=&quot;https://de.wikipedia.org/wiki/Nintendo_Switch&quot;&gt;Nintendo Switch&lt;/a&gt; 
erschienen.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;blockquote&gt;
  &lt;p&gt;Könnt ihr euch erinnern, damals am Schulhof ?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ich nämlich nicht, da ich ja vor den ersten 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Pok%C3%A9mon_Rote_und_Blaue_Edition&quot;&gt;Rot/Blau Editionen&lt;/a&gt;
meinen &lt;a href=&quot;https://de.wikipedia.org/wiki/Game_Boy#Game_Boy_Color&quot;&gt;Gameboy&lt;/a&gt;
verkauft hatte.&lt;br /&gt;
Erst mit 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Pok%C3%A9mon_Goldene_und_Silberne_Edition#Pok%C3%A9mon_Goldene_Edition_HeartGold_und_Pok%C3%A9mon_Silberne_Edition_SoulSilver&quot;&gt;HeartGold/SoulSilver&lt;/a&gt;
um 2010 fand wieder ein originaler &lt;a href=&quot;https://de.wikipedia.org/wiki/Nintendo_DS&quot;&gt;Nintendo DS&lt;/a&gt;
den Weg in meine Hände und dann wurde Pokemon Diamant selbstverständlich 
sofort nachgeholt.&lt;br /&gt;
(Die kurzen zwischenzeitlichen &lt;a href=&quot;https://de.wikipedia.org/wiki/Emulator&quot;&gt;Emulator&lt;/a&gt;
Probiererei sind kaum der Rede wert.)&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/pokemon-dp-intro.jpg&quot; alt=&quot;Pokemon DP Remake Intro&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;nostalgie-und-schöne-grafik&quot;&gt;Nostalgie und schöne Grafik&lt;/h3&gt;

&lt;p&gt;Das Problem für mich als “gealtertem” Pokemonfan ist die Tatsache, dass mir 
Neuerungen eher weniger zusagen.&lt;br /&gt;
Letztendlich bedeutet Pokemon für mich: 8 Arenaleiter besiegen, dann die 
Liga schaffen und danach den Pokedex vervollständigen. Aus.&lt;/p&gt;

&lt;p&gt;Seitdem der Pokedex auf Grund der Fülle an Pokemon nicht mehr im Zentrum 
steht und “seltsame” Instagram-Blödeleien wie Fotoshootings zum Spielverlauf 
gehören, sind neue Editionen eher ein Durchspielpflicht als eine 
Leidenschaft geworden.&lt;/p&gt;

&lt;p&gt;Doch die Remakes holen mich mit den Soundtracks “von damals” voll ab und
obgleich ich vor 10 Jahren auch kein Kind mehr war, fühle ich wieder ein
bisschen kindliche Lebensfreude in unserer aktuell etwas tristen Welt,
wenn die Melodie von “Route 201” ertönt.&lt;/p&gt;

&lt;iframe width=&quot;640&quot; height=&quot;360&quot; src=&quot;/blog/redirect.html?https%3A%2F%2Fwww.youtube-nocookie.com%2Fembed%2FsAIXpLSiXa0&quot; frameborder=&quot;1&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;

&lt;p&gt;Und wer sich noch an die Pixelgrafik des original Gameboy (oder im Emulator) 
erinnern kann, der wird mit jeder neuen Plattform ein noch beeindruckenderes
Grafikspektakel erleben.&lt;/p&gt;

&lt;p&gt;Inzwischen sehen die menschlichen Figuren viel besser und lebendiger aus,
als es in den ersten &lt;a href=&quot;https://de.wikipedia.org/wiki/Pok%C3%A9mon_(Anime)&quot;&gt;Anime Staffeln&lt;/a&gt;
der Fall war.&lt;br /&gt;
Kurz gesagt: Ich liebe dieses Remake.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/pokemon-dp-battle.jpg&quot; alt=&quot;Pokemon DP Remake Battle&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Ich habe erst ein paar Stunden hinter mich gebracht, aber weiß natürlich 
noch ungefähr, was auf mich zukommen wird. Die Stories der legendären Pokemon
wurde meines Erachtens mit jeder Generation etwas besser und die vierte
mochte ich auch damals schon sehr. Von daher bin ich gespannt, ob es
im Remake ein paar neue Adaptionen gibt, die wieder etwas mehr Mythologie
ins Pokemon-Universum bringen.&lt;br /&gt;
Im Remake der 3. Generation (OR/AS) ist das den Machern jedenfalls 
total gelungen, folglich habe ich auch hier eine hohe Erwartung.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Bisher habe ich nur einen Nachteil bemerkt: Am Tag der Veröffentlichung 
muss bereits ein fettes Update heruntergeladen werden, bevor das Spiel
voll funktionsfähig wird. Typisch Software von heute!&lt;br /&gt;
Aber sonst liebe ich den Titel.&lt;/p&gt;

&lt;p&gt;Mich würde mal interessieren, ob es vor dem digitalen Zeitalter auch
solche Jugend-Erinnerungs-Fixpunkte gab, wo sich alle 10 bis 20 Jahre
etwas Altes in neuem Stil wiederholte.&lt;br /&gt;
Bei Kleidung und Mode kann ich mir das vorstellen, aber gab es sonst
noch was Vergleichbares?&lt;/p&gt;

&lt;p&gt;Wie auch immer, Pokemon ist bei mir jetzt schon 20 Jahre immer “nebenbei”
präsent und alle paar Jahre wird dadurch ein Nostalgie-Flash abgeworfen, 
den ich nicht mehr missen möchte.&lt;/p&gt;

&lt;p&gt;Ich bin gespannt, ob es in 10 Jahren immer noch solche Events geben wird,
und vor allem frage ich mich, ob sie mir wie heute noch ein zufriedenes
Grinsen ins Gesicht malen können.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Meine “leuchtende Perle” ist definitiv “kein Schuss in den Ofen”.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;nachtrag-28-nov-2021&quot;&gt;Nachtrag 28. Nov. 2021&lt;/h3&gt;

&lt;p&gt;Die Pokemon-Liga ist geschafft, ich bin nun “ein” Champ der Sinnoh Region
und glücklich damit.&lt;/p&gt;

&lt;p&gt;Allerdings war der Sieg unerwartet schwer, dann Cynthia, der vorherige Champ
machte mich mit ihrem Knakrack regelrecht fertig. Mein Team war (wie üblich 
bei mir) nicht strategisch ausgewählt und so blieb mir nichts anderes 
als so lange &lt;code&gt;Beleber&lt;/code&gt; und &lt;code&gt;Top-Tränke&lt;/code&gt; einzusetzen, bis dem gegnerischen
Pokemon die Attacken ausgingen.&lt;br /&gt;
Und das zog sich bis zu meinen letzten Reserven hin.&lt;/p&gt;

&lt;p&gt;Nun habe ich keinen Stress mehr und kann über Weihnachten mal sehen,
wie weit der PokeDex gefüllt werden kann.&lt;/p&gt;

&lt;p&gt;Wie auch immer, es ist schön, wenn man das Kind in einem selbst wieder mal 
zum Lachen gebracht hat.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>OpenCppCoverage in Docker</title>
   <link href="https://www.opengate.at/blog/2021/11/docker-cpp-coverage/"/>
   <published>2021-11-20T12:00:00+01:00</published>
   <updated>2021-11-20T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2021/11/docker-cpp-coverage</id>
   <category term="devel" /><category term="software" />
   <summary type="text">
  Wieso (zur Hölle) funktioniert OpenCppCoverage
eigentlich nicht in Windows Docker Containern?


Denn während man auf normalen Desktop Rechnern und Servern mit OpenCppCoverage
schöne Statistiken erhält, welche Codezeilen durchgelaufen sind (und welche 
nicht berührt wurden), erhalten wir mit dem selben Tool im Container die 
Meldung:


  cannot find the name of the module


</summary>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;Wieso (zur Hölle) funktioniert &lt;a href=&quot;http://github.com/OpenCppCoverage/OpenCppCoverage&quot;&gt;OpenCppCoverage&lt;/a&gt;
eigentlich nicht in Windows Docker Containern?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Denn während man auf normalen Desktop Rechnern und Servern mit OpenCppCoverage
schöne Statistiken erhält, welche Codezeilen durchgelaufen sind (und welche 
nicht berührt wurden), erhalten wir mit dem selben Tool im Container die 
Meldung:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;cannot find the name of the module&lt;/p&gt;
&lt;/blockquote&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;strong&gt;Spoiler:&lt;/strong&gt; Docker wird von OpenCppCoverage aktuell leider nicht unterstützt 
und es gibt aktuell keinen Workaround für das Problem.&lt;br /&gt;
&lt;strong&gt;Aber:&lt;/strong&gt; Vielleicht können wir dem Thema demnächst mal nachgehen und eine
Teillösung ausprobieren.&lt;/p&gt;

&lt;h3 id=&quot;vorgeschichte---neulich-in-der-firma-&quot;&gt;Vorgeschichte - Neulich in der Firma …&lt;/h3&gt;

&lt;p&gt;Der Chef will bunte Tortendiagramme, ob und wie viel unsere Unit-Tests den Code
wirklich abprüfen.&lt;br /&gt;
Manuell konnte man dies immer schon am Desktop-Rechner mit OpenCppCoverage mit
einem Plugin in &lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_Studio&quot;&gt;Visual Studio&lt;/a&gt; 
tun, doch eigentlich ist es ja viel einfacher, wenn am Build-Server beim 
Ausführen aller Tests auch ein Coverage-Report generiert wird.&lt;/p&gt;

&lt;p&gt;… tja, und der Build-Server baut eben auf &lt;a href=&quot;https://de.wikipedia.org/wiki/Docker_(Software)&quot;&gt;Docker&lt;/a&gt;
auf und dort wird jede Coverage mit dem Fehler &lt;code&gt;cannot find the name of the module&lt;/code&gt; abgewürgt.&lt;/p&gt;

&lt;h3 id=&quot;analyse&quot;&gt;Analyse&lt;/h3&gt;

&lt;p&gt;Der bzw. die OpenCppCoverage Entwickler haben ein kleines Test-Tool erstellt, 
welches das Problem aufzeigt:&lt;/p&gt;

&lt;p&gt;Benutzt wird die &lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/debug/debugging-functions&quot;&gt;Windows Debug API&lt;/a&gt;
und diese liefert normalerweise bei jedem Ladevorgang einer 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Dynamic_Link_Library&quot;&gt;DLL&lt;/a&gt; eine File-Handle 
(&lt;code&gt;hfile&lt;/code&gt;) zum geöffneten Modul.
So kann man dann Debug-Symbole aus dem Modul laden und die richtigen 
Quellcode-Zeilen zum ausgeführten Binärcode ausfindig machen.&lt;/p&gt;

&lt;p&gt;Unter Docker liefert die Debug-API (&lt;code&gt;WaitForDebugEvent()&lt;/code&gt;) aber offenbar 
nur &lt;code&gt;NULL&lt;/code&gt; für &lt;code&gt;hfile&lt;/code&gt;, was die weitere Code-Coverage verhindert.&lt;/p&gt;

&lt;p&gt;Ich habe daher mal ebenfalls ein Test-Projekt mit Debugging-API-Code
zusammengebastelt um das bei mir besser nachvollziehen zu können.
Die Quellcodes hierfür sind im 
&lt;a href=&quot;https://codeberg.org/GateNetwork/gate-blog-classroom/src/branch/main/c_cpp/win32_debug_logger&quot;&gt;CLASSROOM&lt;/a&gt; 
veröffentlicht.&lt;/p&gt;

&lt;p&gt;Und ja, &lt;code&gt;hfile&lt;/code&gt; ist tatsächlich &lt;code&gt;NULL&lt;/code&gt;, wenn man z.B. &lt;code&gt;cmd.exe&lt;/code&gt; damit 
debuggen möchte um seine Module im &lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/debug/debugging-events&quot;&gt;&lt;code&gt;LOAD_DLL_DEBUG_EVENT&lt;/code&gt;&lt;/a&gt;
zu erkennen.&lt;br /&gt;
Danach habe ich einen Ordner meines Hosts in den Container gemountet um andere
Tools zu testen und wieder war der &lt;code&gt;hfile&lt;/code&gt; Member auf &lt;code&gt;NULL&lt;/code&gt; gesetzt.&lt;/p&gt;

&lt;p&gt;Danach machte ich aber etwas ganz Verrücktes:&lt;br /&gt;
Ich erzeugte im Docker-Container einen Test Ordner auf Laufwerk &lt;code&gt;C:\test&lt;/code&gt;
und kopierte meine Test-Programme vom gemounteten Host-Ordner dort hin.&lt;/p&gt;

&lt;p&gt;Kaum startete ich den Debugging-Test, kamen auch schon die ersten korrekten
&lt;code&gt;hfile&lt;/code&gt; Werte, die mit &lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfinalpathnamebyhandlew&quot;&gt;&lt;code&gt;GetFinalPathNameByHandleW()&lt;/code&gt;&lt;/a&gt;
in einen Dateipfad umgewandelt werden konnten.&lt;br /&gt;
Die Pfad-Angaben sind im NT-Format, z.B.: &lt;code&gt;\\\\?\\c:\\path\\to\\module.dll&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;Teil-Lösung 1:&lt;/strong&gt; Man muss Dateien in einen Container-interne Ordner 
kopieren, damit die Debug-APIs gültige Werte liefern.
Denn mit Host-Volumes funktioniert es nicht.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Das Verhalten (wenngleich sehr verstörend) ist sogar nachvollziehbar, 
schließlich handelt es sich um “virtuelle Pfade”, die ins Dateisystem
von Docker “hineingehackt” werden. Dass die von manchen APIs anders
behandelt werden, ist zwar lästig, vielleicht aber auch 
sicherheitstechnisch notwendig.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Nachteil:&lt;/strong&gt; Dieser Workaround läuft letztendlich nicht mit allen Modulen.
&lt;code&gt;ntdll.dll&lt;/code&gt; ist da trotzdem ausgenommen, und Tools wie &lt;code&gt;cmd.exe&lt;/code&gt; und andere
System-DLLs liegen grundsätzlich an einem Ort, der aus anderen Docker
Layern zusammengeklebt ist. Die kann man da nicht weg kopieren und somit 
fehlen ihre Daten.&lt;br /&gt;
… aber für die Code-Coverage wäre das egal, da interessieren wir uns ja 
für “unseren” Code und nicht für fremde System-DLLs.&lt;/p&gt;

&lt;h3 id=&quot;imagepath-im-remote-prozess&quot;&gt;ImagePath im Remote-Prozess&lt;/h3&gt;

&lt;p&gt;Wenn es uns weiters um den Image-Pfad eines geladenen Moduls geht, gibt es
noch eine weiter Möglichkeit:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-load_dll_debug_info&quot;&gt;LOAD_DLL_DEBUG_INFO&lt;/a&gt;
führt nämlich noch die Member &lt;code&gt;lpImageName&lt;/code&gt; und &lt;code&gt;fUnicode&lt;/code&gt; mit sich.&lt;br /&gt;
&lt;code&gt;lpImageName&lt;/code&gt; hält die Speicheradresse zu einem Pointer zu einem String mit 
dem Pfad des Moduls. Dieser Parameter ist zwar nur optional befüllt, doch in
meinen Tests war er auch im Docker Container stets ausgefüllt.&lt;/p&gt;

&lt;p&gt;Das Problem ist nur, der Pointer verweist auf Speicher im Remote-Prozess.
Wir müssen daher mit der &lt;a href=&quot;https:///docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-readprocessmemory&quot;&gt;ReadProcessMemory&lt;/a&gt;
Zeichen für Zeichen herauspicken.&lt;/p&gt;

&lt;p&gt;Mein Demo-Code hierfür sieht etwa so aus:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;static&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; print_remote_image_path(HANDLE hProcess, &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;* lpImageName, &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; unicode)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; chars_printed = &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt;* remote_address = &lt;span style=&quot;color:#069&quot;&gt;NULL&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  SIZE_T returned = &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;  SIZE_T char_len = unicode ? &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;sizeof&lt;/span&gt;(wchar_t) : &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;sizeof&lt;/span&gt;(&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  wchar_t buffer[&lt;span style=&quot;color:#00D&quot;&gt;4&lt;/span&gt;] = { &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt; };
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt;* ptr_char = (&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt;*)&amp;amp;buffer[&lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;];
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt;(ReadProcessMemory(hProcess, lpImageName, &amp;amp;remote_address, &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;sizeof&lt;/span&gt;(remote_address), &amp;amp;returned))
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;  {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt;(remote_address != &lt;span style=&quot;color:#069&quot;&gt;NULL&lt;/span&gt;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;    {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;while&lt;/span&gt;(ReadProcessMemory(hProcess, remote_address, ptr_char, char_len, &amp;amp;returned))
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;      {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;        &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt;(unicode)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;        {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;          &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt;(buffer[&lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;] == &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;) &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;break&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;          wprintf(L&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;%c&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, buffer[&lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;]);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;        }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n21&quot; name=&quot;n21&quot;&gt;21&lt;/a&gt;&lt;/span&gt;        &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;else&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n22&quot; name=&quot;n22&quot;&gt;22&lt;/a&gt;&lt;/span&gt;        {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n23&quot; name=&quot;n23&quot;&gt;23&lt;/a&gt;&lt;/span&gt;          &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt;(*ptr_char == &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;) &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;break&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n24&quot; name=&quot;n24&quot;&gt;24&lt;/a&gt;&lt;/span&gt;          printf(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;%c&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, *ptr_char);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n25&quot; name=&quot;n25&quot;&gt;25&lt;/a&gt;&lt;/span&gt;        }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n26&quot; name=&quot;n26&quot;&gt;26&lt;/a&gt;&lt;/span&gt;        remote_address += char_len;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n27&quot; name=&quot;n27&quot;&gt;27&lt;/a&gt;&lt;/span&gt;        ++chars_printed;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n28&quot; name=&quot;n28&quot;&gt;28&lt;/a&gt;&lt;/span&gt;      }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n29&quot; name=&quot;n29&quot;&gt;29&lt;/a&gt;&lt;/span&gt;    }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n30&quot; name=&quot;n30&quot;&gt;30&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n31&quot; name=&quot;n31&quot;&gt;31&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; chars_printed;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n32&quot; name=&quot;n32&quot;&gt;32&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Man lädt also zuerst den Pointer zum String über die Adresse in &lt;code&gt;lpImageName&lt;/code&gt;,
und je nachdem, ob es ein Unicode oder ANSI String ist, wird Byte für Byte
aus der Zieladresse gezogen, bis wir einen &lt;code&gt;\0&lt;/code&gt; Terminator finden, 
welcher das Ende des String andeutet.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;Teil-Lösung 2:&lt;/strong&gt; Wir extrahieren den Pfad des geladenen Moduls aus dem 
Zielprozess und öffnen das Modul manuell.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Nachteil&lt;/strong&gt;: Der Parameter ist als “optional” markiert und ich weiß auch 
noch nicht, ob dieser Pfad und die manuelle Öffnung dann für eine Coverage 
benutzt werden kann.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Die schnellere Lösung war es natürlich, mit dem &lt;a href=&quot;https://de.wikipedia.org/wiki/GNU_Compiler_Collection&quot;&gt;GCC&lt;/a&gt;
und anderen Tools eine vergleichbare Code-Coverage unter &lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt;
laufen zu lassen.&lt;br /&gt;
Es ist generell ärgerlich, dass unter Windows viele OpenSource-Tools bis 
heute Kinderkrankheiten haben und nur sündteure “Enterprise-Produkte”
Abhilfe versprechen.&lt;/p&gt;

&lt;p&gt;Wie auch immer … es wäre mal ein netter Sidequest, den OpenCppCoverage
Code zu studieren und vielleicht lassen sich die beiden beschriebenen 
Teillösungen dazu nutzen, auch mit diesem eigentlich großartigen Tool
neue Coverage-Reports unter Windows Docker Containern erstellen zu lassen.&lt;/p&gt;

&lt;p&gt;… mal sehen, was die Zukunft bringt.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Raspberry Pi Zero 2 W</title>
   <link href="https://www.opengate.at/blog/2021/11/rpi-zero-2-w/"/>
   <published>2021-11-14T12:00:00+01:00</published>
   <updated>2021-11-14T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2021/11/rpi-zero-2-w</id>
   <category term="hardware" />
   <summary type="text">
  Wenn man für 10 Dollar 1 mal 1 GHz bekommt, dann bekommt man für 15 Dollar …
… 4 x 1 GHz.


So ist es zumindest beim neuen Raspberry Pi 
Zero 2 W, der seit kurzem verfügbar ist.
Den musste ich selbstverständlich haben.

</summary>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;Wenn man für 10 Dollar 1 mal 1 GHz bekommt, dann bekommt man für 15 Dollar …&lt;br /&gt;
… 4 x 1 GHz.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So ist es zumindest beim neuen &lt;a href=&quot;https://de.wikipedia.org/wiki/Raspberry_Pi&quot;&gt;Raspberry Pi&lt;/a&gt; 
Zero 2 W, der seit kurzem verfügbar ist.&lt;br /&gt;
Den musste ich selbstverständlich &lt;em&gt;haben&lt;/em&gt;.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/raspberry-pi-zero-2.jpg&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Wenn man 2 &lt;a href=&quot;https://de.wikipedia.org/wiki/SD-Karte&quot;&gt;SD Karten&lt;/a&gt; oder 3 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Nintendo_Switch&quot;&gt;Nintendo-Switch&lt;/a&gt; Module 
nebeneinander legt, bekommt man in etwa die Ausmaße eines 
&lt;a href=&quot;https://www.raspberrypi.com/products/raspberry-pi-zero-2-w/&quot;&gt;Raspberry PI Zero&lt;/a&gt;.&lt;br /&gt;
Und wenn man bedenkt, dass auf dieser Größe ein ganzer PC sitzt, der mit einem
Gigahertz getaktet war, dann ist das bereits mehr als großartig.&lt;/p&gt;

&lt;p&gt;Mit dem PI Zero 2 findet auf der gleichen Größe nun ein 4-Kern Prozessor Platz,
der auch die Rechenleistung des Winzlings vervierfachen kann.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/raspberry-pi-zero-2-back.jpg&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;nachteil-512-mb-zu-wenig-zum-kompilieren&quot;&gt;Nachteil: 512 MB zu wenig zum Kompilieren&lt;/h3&gt;

&lt;p&gt;Die Freude wird leider nur dadurch etwas getrübt, dass der RAM mit 512 MB 
leider genau so klein geblieben ist, wie im Vorgängermodell.&lt;br /&gt;
Und dass ist (für mich) tatsächlich ein größeres Problem, denn gerade beim 
Kompilieren von Software bedeutet jeder zusätzliche Kern die Notwendigkeit
von zusätzlichem RAM.&lt;/p&gt;

&lt;p&gt;Bereits auf meinem Raspberry PI 2 mit 1 GB RAM musste ich das Kompilieren auf
1-2 Kerne reduzieren, weil ansonsten zu viel RAM von den Prozessen parallel
in Anspruch genommen wird, was das System instabil werden lassen kann.&lt;/p&gt;

&lt;p&gt;Der RPi Zero kam mit einem Kern und den 512 MB zurecht, brauchte aber ewig.
Hier hätte der RPi Zero 2 mit 4 Kernen hart zuschlagen können, doch wegen 
des zu geringen RAMs muss ich auch darauf den Compiler auf einen Kern 
herunterdrosseln.&lt;/p&gt;

&lt;h3 id=&quot;vorteil-embedded-software&quot;&gt;Vorteil: Embedded Software&lt;/h3&gt;

&lt;p&gt;Wenn man aber mit embedded-Diensten arbeitet, die wenig RAM fressen, wie
z.B. schlanke Webserver, dann hat man mit dem Zero 2 seine Freude.&lt;/p&gt;

&lt;p&gt;Denn während zB.: &lt;a href=&quot;https://de.wikipedia.org/wiki/Transport_Layer_Security&quot;&gt;TLS/SSL&lt;/a&gt; 
Verbindungen auf dem Zero 1 single-threaded zum verzögerten Seitenaufbau 
führten, helfen die zusätzlichen Kerne des Zero 2 die Rechenlast besser 
abzufangen.&lt;br /&gt;
So lange man also die RAM Nutzung reduzieren kann, bedeutet das Modell
also einen deutlichen Performance-Gewinn.&lt;/p&gt;

&lt;p&gt;Das fällt auch bei Tools wie &lt;a href=&quot;https://de.wikipedia.org/wiki/Webmin&quot;&gt;&lt;code&gt;webmin&lt;/code&gt;&lt;/a&gt; 
auf, wenn im Hintergrund ein anderer Dienst werkt. Beim RPi Zero 1 
verlangsamte sich unmittelbar die Webseite und genau das passierte mir beim 
RPi Zero 2 nun nicht mehr (bzw. seltener).&lt;/p&gt;

&lt;h3 id=&quot;stromaufnahme&quot;&gt;Stromaufnahme&lt;/h3&gt;

&lt;p&gt;Die wichtigste Frage für mich war:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Kann ich den Zero 2 vom USB Anschluss meines PCs betreiben.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Die grundsätzlich Antwort: Ja, aber.&lt;/p&gt;

&lt;p&gt;Da die Empfehlung bei 1 - 2 Ampere für das Netzteil liegt, reichen die 500 mA
von USB 2 nicht vollständig.&lt;br /&gt;
Ein GUI Betrieb mit Browser wird also nicht möglich sein.&lt;br /&gt;
Doch wenn man den Zero 2 als Webserver für Sensoren nutzt und die Software 
keine langen CPU Spitzen produziert, ist der USB Betrieb durchaus denkbar.&lt;/p&gt;

&lt;p&gt;Zumindest in meinen Test klappte das Hochfahren vom schwachen PC-USB-Port aus
immer problemlos und dabei kommt ja auch eine “üblich” Auslastung zusammen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Der Raspberry Pi ist und bleibt meine Lieblingsplattform unter den 
&lt;a href=&quot;https://de.wikipedia.org/wiki/System-on-a-Chip&quot;&gt;SoCs (System-onC-hip)&lt;/a&gt;. 
Das liegt grundsätzlich am geringen Stromverbrauch im Verhältnis zur 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Allwinner_Technology&quot;&gt;Allwinner&lt;/a&gt; Konkurrenz 
und natürlich auch an der guten Softwareunterstützung.&lt;/p&gt;

&lt;p&gt;Mit dem Zero 2 wurde die Pi Familie um ein nützliches Geschwisterchen 
erweitert, das überall dort eingesetzt werden kann, wo es für Zero 1
knapp wurde.&lt;/p&gt;

&lt;p&gt;Mit Flagschiffen wie dem Raspberry Pi 4 kann der kleine Zero 2 aber 
natürlich nicht mithalten … aber das hat auch keiner von ihm verlangt.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Windows Auto-Login Passwort auslesen</title>
   <link href="https://www.opengate.at/blog/2021/11/win32-stored-password/"/>
   <published>2021-11-13T12:00:00+01:00</published>
   <updated>2021-11-13T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2021/11/win32-stored-password</id>
   <category term="devel" />
   <summary type="text">Da schaue ich in eine lange nicht genutzte Mailbox und finde dort die
Quellen eines Windows 
Programms, das ich vor über 10 Jahren schnell schreiben musste.
Es sollte folgendes Problem lösen:


  Das Auslesen des Auto-Login Default-Passworts eines angemeldeten Accounts.


</summary>
   <content type="html">&lt;p&gt;Da schaue ich in eine lange nicht genutzte Mailbox und finde dort die
Quellen eines &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows&quot;&gt;Windows&lt;/a&gt; 
Programms, das ich vor über 10 Jahren schnell schreiben musste.
Es sollte folgendes Problem lösen:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Das Auslesen des Auto-Login Default-Passworts eines angemeldeten Accounts.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;auto-login-aber-passwort-vergessen&quot;&gt;Auto-Login, aber Passwort vergessen&lt;/h3&gt;

&lt;p&gt;Wozu sollte man ein Passwort auslesen wollen, wenn der Account bereits
angemeldet ist?&lt;/p&gt;

&lt;p&gt;Tja, man stelle sich vor, man hätte ein Passwort auf Industrie-Terminals
gesetzt, das beim Start zum automatischen Login benutzt wird.&lt;br /&gt;
Dieses Passwort wurde vergessen, da es im Windows Deployment-Image integriert
war.&lt;br /&gt;
Und dann muss man plötzlich versuchen, diese Terminals “remote” zu 
administrieren, wofür man das Passwort wieder braucht.&lt;br /&gt;
Zum Glück steht noch ein verstaubtes Demo-Gerät mit automatischem Login im
&lt;em&gt;firmen-eigenen Museum&lt;/em&gt;. Vielleicht kann man das Passwort dort irgendwie
&lt;em&gt;extrahieren&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Dieses Passwort wurde leider nicht einfach in der Registry unter 
&lt;code&gt;SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon&lt;/code&gt; in &lt;code&gt;DefaultPassword&lt;/code&gt;
abgelegt, sondern über System-Tools wie &lt;code&gt;netplwiz&lt;/code&gt; intern gesetzt.&lt;/p&gt;

&lt;p&gt;Wo wird also ein solches “verschlüsseltes” Passwort gespeichert?&lt;/p&gt;

&lt;h3 id=&quot;lösung-lsaretrieveprivatedata&quot;&gt;Lösung: LsaRetrievePrivateData&lt;/h3&gt;

&lt;p&gt;Windows kann Schlüssel-Wert Paare verdeckt speichern und wenn der automatische
Login auf einem System aktiviert wird, dann wird das Passwort im Feld
&lt;code&gt;DefaultPassword&lt;/code&gt; gespeichert.&lt;br /&gt;
Um es wieder auszulesen nutzt man folgenden Weg:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/ntsecapi/nf-ntsecapi-lsaopenpolicy&quot;&gt;&lt;code&gt;LsaOpenPolicy(NULL, &amp;amp;attribs, POLICY_ALL_ACCESS, &amp;amp;lsa_handle)&lt;/code&gt;&lt;/a&gt;&lt;br /&gt;
öffnet ein &lt;code&gt;LSA_HANDLE&lt;/code&gt; Objekt&lt;/li&gt;
  &lt;li&gt;Man erzeugt eine &lt;code&gt;LSA_UNICODE_STRING&lt;/code&gt; Struktur und lässt es auf einen 
&lt;code&gt;wchar_t&lt;/code&gt; Datenpuffer verweisen, in dem &lt;code&gt;DefaultPassword&lt;/code&gt; enthalten ist.&lt;/li&gt;
  &lt;li&gt;Und dann ruft man&lt;br /&gt;
&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/ntsecapi/nf-ntsecapi-lsaretrieveprivatedata&quot;&gt;&lt;code&gt;LsaRetrievePrivateData(lsa_handle, &amp;amp;key, &amp;amp;ptr_value)&lt;/code&gt;&lt;/a&gt; 
auf, welchem die String-Struktur als &lt;code&gt;key&lt;/code&gt; übergeben wird.&lt;/li&gt;
  &lt;li&gt;Der zurückgegebene Pointer (&lt;code&gt;ptr_value&lt;/code&gt;) hält eine neue Unicode-String
Datenstruktur, wo das entschlüsselte Passwort enthalten sein sollte,
oder eben nicht, wenn keines existiert.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Der Aufruf muss unter Administrator-Rechten erfolgen, ansonsten wird 
der Zugriff verwehrt.&lt;br /&gt;
(Zum Glück hatte der Account damals auch Admin-Rechte.)&lt;/p&gt;

&lt;p&gt;Der Beispiel-Quellcode ist nun auch im 
&lt;a href=&quot;https://codeberg.org/GateNetwork/gate-blog-classroom/src/branch/main/c_cpp/win32_default_password_reader/&quot;&gt;BLOG Classroom&lt;/a&gt;
verfügbar.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Wenn ich es richtig verstehe, wurden klassische Tools wie 
&lt;code&gt;netplwiz&lt;/code&gt; bzw. der Aufruf &lt;code&gt;control userpasswords2&lt;/code&gt; auf Windows 10 
deaktiviert, mit dem man zur UI kam, wo man den automatischen Login 
aktivieren und das zu verschlüsselnde Passwort eintippen konnte.&lt;/p&gt;

&lt;p&gt;Das Codeschnipsel ist also kein “Sicherheitsbruch” mehr und er hatte
(wenn ich mich nicht irre) auch nur im Nicht-Domänen-Betrieb funktioniert.&lt;/p&gt;

&lt;p&gt;Die alten Windows XP und Windows 7 Terminals, an denen ich damals arbeitete,
existieren (hoffentlich) nicht mehr, aber ich möchte diesen Aufruf trotzdem
dokumentieren.&lt;br /&gt;
Wenn also jemand ein Passwort zu einem Autologin braucht, das nicht im
Klartext in der Registry steht, dann hat man zumindest einen Ansatz.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>GCC Link Time Optimization (LTO)</title>
   <link href="https://www.opengate.at/blog/2021/11/lto/"/>
   <published>2021-11-07T12:00:00+01:00</published>
   <updated>2021-11-07T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2021/11/lto</id>
   <category term="devel" />
   <summary type="text">Ich arbeite auf dem Raspberry Pi
und anderen Linux-Umgebung ja schon 
lange mit Debian 10 (Buster) und 
neuerdings auch auf Debian 11 (Bullseye).

Doch als ich spaßhalber einen GCC
6.3 Build des GATE Frameworks unter Debian 9 (Stretch) anfachte, 
tauchten jede Menge Fehler folgender Art auf:


  plugin needed to handle lto object


Und dann meinte auch noch MinGW:


  undefined reference to `strndup’


</summary>
   <content type="html">&lt;p&gt;Ich arbeite auf dem &lt;a href=&quot;https://de.wikipedia.org/wiki/Raspberry_Pi&quot;&gt;Raspberry Pi&lt;/a&gt;
und anderen &lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt;-Umgebung ja schon 
lange mit &lt;a href=&quot;https://de.wikipedia.org/wiki/Debian&quot;&gt;Debian&lt;/a&gt; 10 (Buster) und 
neuerdings auch auf Debian 11 (Bullseye).&lt;/p&gt;

&lt;p&gt;Doch als ich spaßhalber einen &lt;a href=&quot;https://de.wikipedia.org/wiki/GNU_Compiler_Collection&quot;&gt;GCC&lt;/a&gt;
6.3 Build des GATE Frameworks unter Debian 9 (Stretch) anfachte, 
tauchten jede Menge Fehler folgender Art auf:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;plugin needed to handle lto object&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Und dann meinte auch noch &lt;a href=&quot;https://de.wikipedia.org/wiki/MinGW&quot;&gt;MinGW&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;undefined reference to `strndup’&lt;/p&gt;
&lt;/blockquote&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;zwei-gcc-probleme&quot;&gt;Zwei GCC Probleme&lt;/h3&gt;

&lt;h4 id=&quot;mingw--libressl--missing-strndup&quot;&gt;MinGW + libressl == missing &lt;code&gt;strndup&lt;/code&gt;&lt;/h4&gt;

&lt;p&gt;Als ich vor einem halben Jahr auf &lt;a href=&quot;/blog/2021/05/gcc-exe-size/&quot;&gt;Link-Time-Optimization&lt;/a&gt;
(&lt;code&gt;LTO&lt;/code&gt;) in den GCC Build umgestiegen bin, tat ich das nur im GATE Development 
Branch und der löst beim &lt;code&gt;git push&lt;/code&gt; auf &lt;a href=&quot;https://de.wikipedia.org/wiki/Bitbucket&quot;&gt;BitBucket&lt;/a&gt;
keine Build-Pipeline aus.&lt;/p&gt;

&lt;p&gt;Und seitdem ich neulich einen Pull-Request zur &lt;code&gt;master&lt;/code&gt; Pipeline absetzte, 
krachte es beim Linken von einigen &lt;a href=&quot;https://de.wikipedia.org/wiki/Template_(C%2B%2B)&quot;&gt;C++ Templates&lt;/a&gt;
und immer wieder in der &lt;a href=&quot;https://de.wikipedia.org/wiki/LibreSSL&quot;&gt;libressl&lt;/a&gt;, 
wenn mit &lt;code&gt;MinGW&lt;/code&gt; unter &lt;a href=&quot;/blog/2021/02/win-linux/&quot;&gt;Linux auch Windows-Binärdateien&lt;/a&gt; 
gebaut werden.&lt;/p&gt;

&lt;p&gt;Offenbar werden einige Symbole durch die &lt;code&gt;LTO&lt;/code&gt; entfernt, denn ist diese abgeschaltet,
produziert &lt;code&gt;MinGW&lt;/code&gt; brav Windows EXEn.&lt;/p&gt;

&lt;h4 id=&quot;gcc-kleiner-7-kann-lto-nicht-so-richtig&quot;&gt;GCC kleiner 7 kann LTO nicht so richtig&lt;/h4&gt;

&lt;p&gt;Das “älteste” Linux, mit dem ich so arbeite ist Ubuntu 18.04 in WSL und das 
setzt den GCC 7.5 ein. Und meine Raspberry PIs mit Debian 10 kompilieren mit 
dem GCC 8.3.&lt;br /&gt;
Und alle konnten sie mit dem &lt;code&gt;-flto&lt;/code&gt; Switch problemlos umgehen.&lt;/p&gt;

&lt;p&gt;Doch da wir in der Firma auch mit Debian 8 und 9 arbeiteten und ich eher 
zufällig entdeckte, dass unter &lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_Server_2022&quot;&gt;Windows 2022&lt;/a&gt;
 ein &lt;code&gt;wsl install -d debian&lt;/code&gt; plötzlich wieder Debian 9 ausrollt (während im 
 Windows Store mit Debian 10 und neuer gehandelt wird), war klar, dass ich 
 mit dem älteren Compiler experimentieren wollte.&lt;/p&gt;

&lt;p&gt;Und bei jeder einzelnen &lt;code&gt;.c&lt;/code&gt; oder &lt;code&gt;.cpp&lt;/code&gt; Datei kam die Meldung:&lt;br /&gt;
&lt;code&gt;plugin needed to handle lto object.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Es sieht also so aus, dass GCC 6.3 mit &lt;code&gt;-flto&lt;/code&gt; nicht leben kann, denn ohne
diesen Zusatz funktioniert alles problemlos.&lt;/p&gt;

&lt;h3 id=&quot;lösung-lto-abschalten&quot;&gt;Lösung: LTO abschalten&lt;/h3&gt;

&lt;p&gt;Oh Mann! Ich habe unzählige Kombinationen ausprobiert, doch keine konnte 
alle Probleme beseitigen und so blieb mir nichts anderes übrig, als folgendes
in &lt;code&gt;CMakeLists.txt&lt;/code&gt; einzutragen:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;  # standard GCC flags
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  set(CMAKE_C_FLAGS_RELEASE &amp;quot;${CMAKE_C_FLAGS_RELEASE} -s -fdata-sections -ffunction-sections&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  set(CMAKE_CXX_FLAGS_RELEASE &amp;quot;${CMAKE_CXX_FLAGS_RELEASE} -s -fdata-sections -ffunction-sections&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  set(CMAKE_EXE_LINKER_FLAGS_RELEASE &amp;quot;${CMAKE_EXE_LINKER_FLAGS_RELEASE} -s -Wl,--gc-sections&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;  set(CMAKE_MODULE_LINKER_FLAGS_RELEASE &amp;quot;${CMAKE_MODULE_LINKER_FLAGS_RELEASE} -s -Wl,--gc-sections&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  set(CMAKE_SHARED_LINKER_FLAGS_RELEASE &amp;quot;${CMAKE_SHARED_LINKER_FLAGS_RELEASE} -s -Wl,--gc-sections&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;  if(NOT MINGW AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 7.0)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;    # special GCC LTO + optimization flags
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;    string(REPLACE &amp;quot;-O3&amp;quot; &amp;quot;&amp;quot; CMAKE_C_FLAGS_RELEASE &amp;quot;${CMAKE_C_FLAGS_RELEASE}&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;    string(REPLACE &amp;quot;-O3&amp;quot; &amp;quot;&amp;quot; CMAKE_CXX_FLAGS_RELEASE &amp;quot;${CMAKE_CXX_FLAGS_RELEASE}&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;    set(CMAKE_C_FLAGS_RELEASE &amp;quot;${CMAKE_C_FLAGS_RELEASE} -flto -Os&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;    set(CMAKE_CXX_FLAGS_RELEASE &amp;quot;${CMAKE_CXX_FLAGS_RELEASE} -flto -Os&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;    set(CMAKE_EXE_LINKER_FLAGS_RELEASE &amp;quot;${CMAKE_EXE_LINKER_FLAGS_RELEASE} -flto&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;    set(CMAKE_MODULE_LINKER_FLAGS_RELEASE &amp;quot;${CMAKE_MODULE_LINKER_FLAGS_RELEASE} -flto&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;    set(CMAKE_SHARED_LINKER_FLAGS_RELEASE &amp;quot;${CMAKE_SHARED_LINKER_FLAGS_RELEASE} -flto&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;  endif()
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;endif()
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Wenn also der MinGW oder ein anderer GCC kleiner 7 eingesetzt wird, dann soll
keine Link Time Optimization stattfinden.&lt;br /&gt;
Ob diese Lösung korrekt ist, weiß ich nicht, sie entspricht nur meiner 
Beobachtung aus der Debian/Ubuntu Serie.&lt;/p&gt;

&lt;p&gt;Es gibt Hinweise, dass in älteren Linux-Distributionen die bin-utilities &lt;code&gt;LTO&lt;/code&gt; 
nicht nativ unterstützen und dafür andere Varianten von &lt;code&gt;/usr/bin/ar&lt;/code&gt; und 
&lt;code&gt;/usr/bin/ranlib&lt;/code&gt; bräuchten. Man könnte in CMake die Aufrufe durch &lt;code&gt;gcc-ar&lt;/code&gt; und
&lt;code&gt;gcc-ranlib&lt;/code&gt; ersetzen, doch das hat bei mir nie vollständig funktioniert.
Keine Ahnung warum, aber &lt;a href=&quot;http://ostack.cn/?qa=729940/&quot;&gt;hier ist die Anleitung&lt;/a&gt;,
die ich dazu gefunden habe.&lt;/p&gt;

&lt;p&gt;Mein MinGW ist neuer als 7.0 und kann &lt;code&gt;LTO&lt;/code&gt;, doch der stößt sich an anderen 
Flags wie z.B. &lt;code&gt;-s&lt;/code&gt;, &lt;code&gt;-Os&lt;/code&gt; oder &lt;code&gt;-Wl,--gc-sections&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Ich konnte alle C++ Template Probleme durch die Entfernung von &lt;code&gt;-s&lt;/code&gt; usw.
beheben, wobei &lt;code&gt;-flto&lt;/code&gt; bestehen blieb. Doch &lt;code&gt;strndup&lt;/code&gt; blieb stets als 
“undefiniert” übrig und ließ den Übersetzungsvorgang abbrechen.&lt;/p&gt;

&lt;p&gt;Folgende Pseudo-Erklärung reime ich mir dazu zusammen:&lt;br /&gt;
&lt;code&gt;strndup&lt;/code&gt; ist eine &lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt; Erweiterung, 
die unter Windows fehlt. &lt;code&gt;libressl&lt;/code&gt; erkennt das und fügt eine 
Kompatibilitäts-Implementierung hinzu. Dort wird &lt;code&gt;strndup&lt;/code&gt; zwar implementiert,
doch es gibt keine Deklaration in einem Header, die darauf verweise würde.&lt;br /&gt;
Und somit dürfte die Funktion auch als unsichtbar gelten, wenn &lt;code&gt;LTO&lt;/code&gt; alle
Module am Ende des Linkens zusammenfasst, schließlich wird das Symbol
offiziell nicht in andere Module “importiert”, aber dort sehr wohl genutzt.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Hmm … ich bin etwas angepisst.&lt;/p&gt;

&lt;p&gt;Die Experimente haben mich einige Stunden gekostet und am Ende bin ich daran
gescheitert. Vielleicht gibt es eine Kombination, die &lt;code&gt;LTO&lt;/code&gt; in statischen 
Bibliotheken wie &lt;code&gt;libressl&lt;/code&gt; unter MinGW gefügig machen und vielleicht kann 
man auch die Toolchain unter GCC kleiner 7 mit dem korrekten &lt;code&gt;LTO&lt;/code&gt; Plugin 
füttern.&lt;/p&gt;

&lt;p&gt;Aber ich fand es am Ende einfacher, diese Features auf jenen Plattformen 
auszuschalten, damit ich mich um wichtigere Dinge kümmern kann.&lt;/p&gt;

&lt;p&gt;Dass &lt;code&gt;LTO&lt;/code&gt; unter Linux mit dem GCC erst seit kurzem vernünftig funktioniert,
finde ich etwas komisch. Schließlich nutzen Intel und der 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_C%2B%2B&quot;&gt;MSVC&lt;/a&gt; diese Technik schon seit
2 Jahrzehnten um die effizientesten Binaries zu erzeugen.&lt;/p&gt;

&lt;p&gt;Tja, beim GCC war früher eben doch nicht alles besser …&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Letztes Windows 7 Update</title>
   <link href="https://www.opengate.at/blog/2021/11/win7-update/"/>
   <published>2021-11-06T12:00:00+01:00</published>
   <updated>2021-11-06T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2021/11/win7-update</id>
   <category term="software" />
   <summary type="text">Die letzten Jahre war eine Parallelinstallation von Windows 7
neben Windows 10 für mich “normal” auf meinen PCs und Laptops, denn für 
Visual Studio 2005 
und ein paar ältere Design-Tests ist dieses Setup gut geeignet, wenn man nicht
gleich auf eine VM 
wechseln will.

Die ewig dauernden Updates sind aber sehr nervig, also wurde es Zeit eine 
“finale” Windows 7 WIM Datei mit allen Updates zu bauen, damit künftige 
Installationen des abgekündigten Systems “out-of-the-box” laufen.
</summary>
   <content type="html">&lt;p&gt;Die letzten Jahre war eine Parallelinstallation von &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_7&quot;&gt;Windows 7&lt;/a&gt;
neben Windows 10 für mich “normal” auf meinen PCs und Laptops, denn für 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_Studio#Version_2005&quot;&gt;Visual Studio 2005&lt;/a&gt; 
und ein paar ältere Design-Tests ist dieses Setup gut geeignet, wenn man nicht
gleich auf eine &lt;a href=&quot;https://de.wikipedia.org/wiki/Virtuelle_Maschine&quot;&gt;VM&lt;/a&gt; 
wechseln will.&lt;/p&gt;

&lt;p&gt;Die ewig dauernden Updates sind aber sehr nervig, also wurde es Zeit eine 
“finale” Windows 7 WIM Datei mit allen Updates zu bauen, damit künftige 
Installationen des abgekündigten Systems “out-of-the-box” laufen.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Dabei bin ich wie folgt vorgegangen:&lt;/p&gt;

&lt;h3 id=&quot;erster-download-der-updates&quot;&gt;Erster Download der Updates&lt;/h3&gt;

&lt;p&gt;Der &lt;a href=&quot;https://download.wsusoffline.net/&quot;&gt;WSUS Offline Updater&lt;/a&gt; ist ein Tool 
zum reinen Download von Windows Updates, um sie “offline” in ein Windows
Image (wie z.B. die Installations-DVD) integrieren zu können.&lt;/p&gt;

&lt;p&gt;Da der Windows 7 Support offiziell schon abgelaufen ist und neue Versionen
die Downloads nicht mehr unterstützen, nutzt man eine ältere Variante,
wie z.B. v11.9 aus dem Jahr 2020, wo die letzten Windows 7 Updates
eingetragen sind.&lt;/p&gt;

&lt;p&gt;Am Ende hat man dann ein Verzeichnis mit allen &lt;code&gt;.cab&lt;/code&gt; Dateien aus den
unterschiedlichen Knowledge-Base Patches von Microsoft, die man
integrieren kann.
Natürlich kann man sich die nötigen Updates auch selbst über den 
&lt;a href=&quot;https://www.catalog.update.microsoft.com&quot;&gt;Microsoft Update Catalog&lt;/a&gt;
herunter laden, wo alle Dateien jedoch als &lt;code&gt;.msu&lt;/code&gt; vorliegen, doch das 
spielt für die Integration keine Rolle.&lt;/p&gt;

&lt;h3 id=&quot;integration-per-dism-und-test-setup&quot;&gt;Integration per DISM und Test-Setup&lt;/h3&gt;

&lt;p&gt;Nun wird eine Windows 7 SP 1 DVD hergenommen und die 
&lt;code&gt;sources\install.wim&lt;/code&gt; zur Bearbeitung auf die Platte kopiert.
Für gewöhnlich sind mehrere Windows-Installationen 
(Basic, Home, Professional, Ultimate) in einer WIM Datei untergebracht,
doch da ich nur die Professional Variante brauche (Index 3),
habe ich (anfangs) nur dieses Image aktualisiert.&lt;br /&gt;
Welches Image auf welchen Index liegt, kann man per&lt;br /&gt;
&lt;code&gt;dism /Get-ImageInfo /ImageFile:path\to\install.wim&lt;/code&gt; auslesen,
oder in &lt;a href=&quot;https://de.wikipedia.org/wiki/7-Zip&quot;&gt;7zip&lt;/a&gt; über die erste 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Extensible_Markup_Language&quot;&gt;XML&lt;/a&gt; Datei 
ausforschen, die man beim Öffnen der &lt;code&gt;.wim&lt;/code&gt; Datei sieht.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;dism /Mount-Wim /WimFile:d:\install.wim /Index:3 /MountDir:d:\mount&lt;/code&gt;&lt;br /&gt;
lädt das Image und&lt;br /&gt;
&lt;code&gt;dism /Image:d:\mount /Add-Package /PackagePath:d:\path\to\updates&lt;/code&gt;&lt;br /&gt;
versucht, alle &lt;code&gt;.cab&lt;/code&gt; und &lt;code&gt;.msu&lt;/code&gt; Dateien zu integrieren.&lt;/p&gt;

&lt;p&gt;Am Ende werden mit&lt;br /&gt;
&lt;code&gt;dism /Unmount-Wim /MountDir:d:\mount /commit&lt;/code&gt;&lt;br /&gt;
alle Updates in die WIM-Datei zurückgeschrieben.&lt;/p&gt;

&lt;p&gt;Falls es eine Datei namens &lt;code&gt;sources\ei.cfg&lt;/code&gt; auf der Setup-DVD gibt,
kann man diese löschen oder diese umbenennen.
Denn in ihr steht festgelegt, welche Windows Variante installiert 
werden soll. Fehlt die Datei, fragt Windows Setup den User, ob er
nun Basic, Home, Professional oder Ultimate installieren möchte.&lt;/p&gt;

&lt;p&gt;Für eine Testinstallation, kann man mit Tools wie &lt;code&gt;oscdimg&lt;/code&gt; wieder ein
ISO erstellen um es in einer VM zu nutzen.&lt;br /&gt;
Ich habe hingegen meinen &lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_Deployment_Services&quot;&gt;Windows Deployment Server&lt;/a&gt;
benutzt, um das angepasste Windows-Setup per Netzwerk Boot zu starten 
und Windows 7 in einer Test-VM aufzusetzen.&lt;/p&gt;

&lt;h3 id=&quot;windows-update-und-fehlende-komponenten&quot;&gt;Windows Update und fehlende Komponenten&lt;/h3&gt;

&lt;p&gt;Meine Testinstallation startete zwar korrekt, allerdings war das integrierte
Windows Update nicht mehr lauffähig, da zu alt.
Dafür war es notwendig, die neueste Windows Update Agent Komponente manuell 
nachzuinstallieren. Die aktuelle Version ist 7.6 und man findet sie unter
&lt;a href=&quot;https://docs.microsoft.com/en-us/troubleshoot/windows-client/deployment/update-windows-update-agent&quot;&gt;docs.microsoft.com/en-us/troubleshoot/windows-client/deployment/update-windows-update-agent&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Die zur Zeit des Postings gültigen Download Links sind:&lt;br /&gt;
&lt;a href=&quot;http://download.windowsupdate.com/windowsupdate/redist/standalone/7.6.7600.320/windowsupdateagent-7.6-x64.exe&quot;&gt;Download Windows 7 Update Agent 7.6 X64&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://download.windowsupdate.com/windowsupdate/redist/standalone/7.6.7600.320/windowsupdateagent-7.6-x86.exe&quot;&gt;Download Windows 7 Update Agent 7.6 X86&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nach der Installation + Neustart kann Windows Setup nach fehlenden 
Aktualisierungen suchen, und da findet man tatsächlich noch einiges.
Vor allem viele nicht-kritische Updates werden nach der Suche aufgelistet.&lt;/p&gt;

&lt;p&gt;Ich habe mir dann die Mühe gemacht all diese Updates manuell per Update 
Catalog herunterzuladen und habe dann die obigen &lt;code&gt;dism&lt;/code&gt; Schritte erneut 
ausgeführt um das Windows Image auch mit den letzten Updates und Features 
zu füllen.&lt;/p&gt;

&lt;p&gt;Am Ende hatte ich so eine halbwegs fertig-gepatchte &lt;code&gt;.wim&lt;/code&gt; Datei, die ich 
für meine künftigen Installationen nutzen kann.&lt;/p&gt;

&lt;p&gt;Und mit Tools wie &lt;code&gt;oscdimg&lt;/code&gt; kann man dann mit den Dateien der Windows-7 DVD
samt der neuen &lt;code&gt;install.wim&lt;/code&gt; wieder ein ISO Image erzeugen.&lt;br /&gt;
Im nachfolgenden Beispiel liegen die DVD-Dateien unter &lt;code&gt;c:\win7dvd&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;oscdimg -m -o -u2 -udfver102 -bootdata:2#p0,e,bc:\win7dvd\boot\etfsboot.com#pEF,e,bc:\win7dvd\efi\microsoft\boot\efisys.bin c:\win7dvd c:\win7-dvd-image.iso&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Und ja, der &lt;code&gt;-bootdata&lt;/code&gt; Parameter ist wirklich eine solche lange Wurst, wo 
die Einträge für BIOS und EFI mit &lt;code&gt;#&lt;/code&gt; getrennt werden und der Dateipfad 
einfach hinter dem &lt;code&gt;,b&lt;/code&gt; angefügt wird.&lt;/p&gt;

&lt;h3 id=&quot;erkannte-probleme&quot;&gt;Erkannte Probleme&lt;/h3&gt;

&lt;h4 id=&quot;manche-cab-oder-msu-dateien-lassen-sich-nicht-integrieren&quot;&gt;Manche CAB oder MSU Dateien lassen sich nicht integrieren&lt;/h4&gt;

&lt;p&gt;Leider geht nicht jede Update-Installation gut aus. Denn manche &lt;code&gt;.cab&lt;/code&gt; oder
&lt;code&gt;.msu&lt;/code&gt; Dateien versetzen das Image in einen Zustand, in dem keine weiteren
Updates mehr integriert werden können.&lt;br /&gt;
In diesem Fall bricht dann die Integration ab und alle folgenden Updates
können nicht mehr eingespielt werden.&lt;/p&gt;

&lt;p&gt;Hier bleibt einem nichts anderes übrig, als das &lt;code&gt;dism&lt;/code&gt; Logfile durchzugehen
und das letzte störrische Update zu finden.
Dann darf man wieder von vorne mit einer jungfräulichen &lt;code&gt;.wim&lt;/code&gt; Datei anfangen
und diese erneut aktualisieren, wobei das störende Update einfach 
übersprungen wird.&lt;/p&gt;

&lt;p&gt;Das bewirkt dann am Ende zwar, dass ein paar Updates fehlen und in der 
fertigen Installation eben genau dieses übersprungenen Update wieder gefunden 
werden … aber mit diesem Manko lässt sich leben lernen.&lt;/p&gt;

&lt;p&gt;Es ist kein Problem nach einem Setup noch 10 weitere fehlende Updates 
einspielen zu müssen, denn ohne die Integration wären es sonst 300 Updates, 
die alle erst mal heruntergeladen werden müssten.&lt;/p&gt;

&lt;h4 id=&quot;hyper-v-unterstützt-windows-7-nicht-in-gen-2-vms&quot;&gt;Hyper-V unterstützt Windows 7 nicht in Gen-2-VMs&lt;/h4&gt;

&lt;p&gt;Eigentlich wollte ich auch &lt;code&gt;UEFI&lt;/code&gt; Installation mit &lt;a href=&quot;https://de.wikipedia.org/wiki/Hyper-V&quot;&gt;Hyper-V&lt;/a&gt;
testen. Unter Windows 10 startet ein Windows 7 ISO Image zwar in einer 
“Generation-2 VM”, friert aber schon im Boot Screen ein.&lt;/p&gt;

&lt;p&gt;Man kann allerdings auf 
&lt;a href=&quot;https://docs.microsoft.com/en-us/windows-server/virtualization/hyper-v/plan/should-i-create-a-generation-1-or-2-virtual-machine-in-hyper-v#windows-guest-operating-system-support&quot;&gt;docs.microsoft.com&lt;/a&gt;
nachlesen, dass Hyper-V in Windows 10 die Windows 7 Gastinstallationen nur in 
“Generation 1” VMs (also im BIOS Modus) unterstützt. &lt;code&gt;UEFI&lt;/code&gt; Support in Hyper-V 
(“Generation 2”) gibt es erst für Gäste ab Windows 8 bzw. Server 2012.&lt;/p&gt;

&lt;p&gt;Schade eigentlich, denn Windows 7 ist an sich sehr wohl &lt;code&gt;UEFI&lt;/code&gt; tauglich.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Nun, ich weiß nicht, wie lange ich Windows 7 noch am Leben erhalten werde, 
denn seine aktive Nutzung ist bei mir seit 2017 stark zurückgegangen.
Eigentlich sind es nur noch &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_CE&quot;&gt;Windows-CE&lt;/a&gt;
Experimente, die mich in diese ältere Installation booten lassen.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/win7-end.png&quot; alt=&quot;Win7-support-end&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Früher oder später wird das ganze nur noch eine VM sein, doch aktuell sind
meine &lt;a href=&quot;https://de.wikipedia.org/wiki/Intel_Atom&quot;&gt;Intel Atom&lt;/a&gt; Systeme zu 
schwach, als dass man mit Windows 7 flüssig darauf arbeiten oder kompilieren 
könnte.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Marvel, Squid-Game, usw.</title>
   <link href="https://www.opengate.at/blog/2021/10/movie-review/"/>
   <published>2021-10-31T12:00:00+01:00</published>
   <updated>2021-10-31T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2021/10/movie-review</id>
   <category term="entertainment" />
   <summary type="text">Alles passiert bei mir verzögert, da ich nicht ins Kino gehen kann bzw. will
bzw. darf, doch zumindest Black Widow
ist vor ein paar Wochen auf dem Streaming Dienst 
Disney Plus erschienen.

Und dann kam noch völlig unerwartet eine Überraschung aus Korea names
Squid Game.

Zeit für ein Movie und Serien-Review.
</summary>
   <content type="html">&lt;p&gt;Alles passiert bei mir verzögert, da ich nicht ins Kino gehen kann bzw. will
bzw. darf, doch zumindest &lt;a href=&quot;https://de.wikipedia.org/wiki/Black_Widow_(Film)&quot;&gt;Black Widow&lt;/a&gt;
ist vor ein paar Wochen auf dem Streaming Dienst 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Disney%2B&quot;&gt;Disney Plus&lt;/a&gt; erschienen.&lt;/p&gt;

&lt;p&gt;Und dann kam noch völlig unerwartet eine Überraschung aus Korea names
&lt;a href=&quot;https://de.wikipedia.org/wiki/Squid_Game&quot;&gt;Squid Game&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Zeit für ein Movie und Serien-Review.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;black-widow&quot;&gt;Black Widow&lt;/h3&gt;

&lt;p&gt;Ich sehe &lt;a href=&quot;https://de.wikipedia.org/wiki/Scarlett_Johansson&quot;&gt;Scarlett Johansson&lt;/a&gt;
wirklich sehr sehr gerne zu, bei allem was sie macht.&lt;br /&gt;
Und dass mir ihre Rolle als Black Widow ganz besonders zugesagt hat, 
ist auch kein Geheimnis.&lt;/p&gt;

&lt;p&gt;Und jetzt, nach ihrem offiziellen Film-Tod in &lt;a href=&quot;https://de.wikipedia.org/wiki/Avengers:_Endgame&quot;&gt;Avengers Endgame&lt;/a&gt;
liegt ihr Solo-Film “Black Widow” als Prequel auf dem Tisch …
… und ich weiß einfach nicht, was ich damit anfangen soll.&lt;/p&gt;

&lt;p&gt;Ich glaube, ich bin genetisch nicht dazu in der Lage, den Film schlecht zu
finden, und finde einige Figuren und deren Darstellung auch gut gelungen.
Aber W-T-F … was war denn das für eine Story?&lt;/p&gt;

&lt;p&gt;Mein größtes Problem ist vor allem, dass die heldenhafte Figur der 
Natasha Romanoff aus Avengers Endgame, im Nachhinein belangloser wird und das 
liegt an einer - aus meiner Sicht - sehr herbei konstruierten Nebengeschichte,
die man in früheren Filmen hätte einleiten müssen.&lt;/p&gt;

&lt;p&gt;Es wirkt leider sehr künstlich, wenn man eine Figur aus Filmen kennt, die 
wenig Hintergrund hat und darüber nie gesprochen wird, und dann kommt eine
verschränkte Verschwörung zum Vorschein, die das Weltgeschehen ändert …&lt;/p&gt;

&lt;p&gt;Also … belassen wir es dabei: Ich mag die Figure Black Widow, selbst wenn
sie in seltsame Kulissen hineingeschrieben wird, die eigentlich nur dazu da
sind, andere Charaktere einzuführen.&lt;/p&gt;

&lt;h3 id=&quot;marvels-what-if&quot;&gt;Marvel’s: What If&lt;/h3&gt;

&lt;p&gt;Die animierte Serie &lt;a href=&quot;https://de.wikipedia.org/wiki/What_If%E2%80%A6%3F&quot;&gt;What If&lt;/a&gt; 
ist eine kleine “Avengers-Phase” in andersartigen Paralleluniversen.&lt;/p&gt;

&lt;p&gt;Mit jeder Episode wird ein neuer “alternativer” Held eingeführt, damit 
im Staffelfinale alle gemeinsam den größten Bösewicht bekämpfen können.&lt;/p&gt;

&lt;p&gt;Und hier bin ich echt dankbar, dass die Serie animiert ist und nicht real
abgedreht wurde. Denn so kann man die Serie viel leichter isoliert von
Marvels “Cinematic” Universe trennen und man erlebt keine W-T-F Momente,
wenn z.B. plötzlich Zombie-infizierte Avengers durchs Bild laufen und 
den Passanten die Arme abbeißen, oder &lt;a href=&quot;https://en.wikipedia.org/wiki/Thanos&quot;&gt;Thanos&lt;/a&gt;
zum gutmütigen Saufkumpanen an der Bar wird.&lt;/p&gt;

&lt;p&gt;Da mit &lt;a href=&quot;https://de.wikipedia.org/wiki/Loki_(Fernsehserie)&quot;&gt;Loki&lt;/a&gt; und der 
Einführung des Multiversums sprichwörtlich “alles” möglich ist, bin ich 
grundsätzlich solchen “Veränderungen” von Stories gegenüber skeptisch, 
aber mit der Machart hat mich Marvel überzeugt.&lt;/p&gt;

&lt;p&gt;Und so konnte ich die Serie einfach zwischendurch genießen, 
ohne alles in Frage stellen zu müssen.&lt;/p&gt;

&lt;h3 id=&quot;shang-chi-und-eternals&quot;&gt;Shang-Chi und Eternals&lt;/h3&gt;

&lt;p&gt;Dass &lt;a href=&quot;https://de.wikipedia.org/wiki/Shang-Chi_and_the_Legend_of_the_Ten_Rings&quot;&gt;Shang-Chi&lt;/a&gt; 
ins Streaming kommt, dauert noch etwas, aber zumindest habe ich bisher so 
einiges Gutes über den nächsten Marvel Film gehört. 
Und Anfang November startet auch &lt;a href=&quot;https://de.wikipedia.org/wiki/Eternals_(Film)&quot;&gt;Eternals&lt;/a&gt; 
in den Kinos.
Nachdem aber immer noch die für mich unerträgliche Registrierungspflicht
aufrecht ist, werde ich wohl auch hier noch lange warten müssen, 
bis ich diesen Film zu Hause sehen kann.&lt;/p&gt;

&lt;p&gt;Ich bin gespannt, wie sich diese neuen Filme ins gerade geöffnete Multiversum
einfügen werden, habe aber auch etwas Angst, ob Marvel sich da nicht etwas
verfahren hat, so viele neue Stränge aufzumachen.&lt;br /&gt;
However … bisher habe sie es aber immer geschafft wieder alles zu vereinen,
und darauf hoffe ich auch heute.&lt;/p&gt;

&lt;h3 id=&quot;squid-game&quot;&gt;Squid Game&lt;/h3&gt;

&lt;p&gt;Und dann kommt so “ganz nebenläufig” auf &lt;a href=&quot;https://de.wikipedia.org/wiki/Netflix&quot;&gt;Netflix&lt;/a&gt;
eine neue koreanische Serie namens “Squid-Game” auf die Empfehlungsliste.&lt;br /&gt;
Es war tatsächlich das Titelbild mit den “komisch rot bzw. rosa-farbenen 
Jumpsuits”, das mein Interesse geweckt hat.&lt;/p&gt;

&lt;p&gt;Die erste Folge wirkte etwas befremdlich und ich fühlte sich wie eine billiges
Sozialdrama an. Doch dann begann “das Spiel”, und ab da konnte ich mich nicht 
mehr dem Drang entziehen, wissen zu wollen, wie es ausgeht.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Achtung Spoiler&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Wenn man armen von Existenzängsten bedrohten Menschen ein Glücksspiel anbietet,
stellt man fest, dass viele gerne darauf einsteigen. Schließlich hat man 
nichts zu verlieren.&lt;br /&gt;
Doch die Formel in Squid-Game ist brutal: Wer verliert, der stirbt.&lt;/p&gt;

&lt;p&gt;Und tatsächlich wartet die Serie bis zur letzten Folge um zu erklären, wie
denn überhaupt ein solches Spiel nach dem Vorbild von 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Takeshi%E2%80%99s_Castle&quot;&gt;Takeshi’s Castle&lt;/a&gt;
mit hohem Sterberisiko in unserer Welt möglich sein soll.&lt;/p&gt;

&lt;p&gt;Ein bisschen hat mich die ganze Sache an den Film &lt;a href=&quot;https://de.wikipedia.org/wiki/Cube_(Film)&quot;&gt;Cube&lt;/a&gt;
erinnert, doch während man in Cube nie wirklich den Grund für die 
Tötungsmaschinerie erfährt, schildert Squid-Game einen leider fast 
realistischen von &lt;a href=&quot;https://de.wikipedia.org/wiki/Dekadenz&quot;&gt;Dekadenz&lt;/a&gt; 
geprägten Hintergrund.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Während Marvel für mich aktuell so “dahinplätschert”, hat mich Squid-Game
ob geringer Erwartungen total positiv überrascht.&lt;br /&gt;
Wer kein Problem mit unerwartet viel Blut hat, darf sich ein Wochenende
lang durch die groteske Geschichte &lt;a href=&quot;https://de.wikipedia.org/wiki/Binge_Watching&quot;&gt;durch-bingen&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Rotes Licht, grünes Licht!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;nachtrag&quot;&gt;Nachtrag&lt;/h3&gt;

&lt;p&gt;Das geilste ist, dass man sich die Squid-Game Outfits alle auch bestellen 
kann, und als Masken-Fan, musste ich die 3 Aufseher- und die Game-Master
Masken sofort in den Einkaufswagen legen.&lt;/p&gt;

&lt;p&gt;Inzwischen sind sie angekommen …&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/squid-game-masks.jpg&quot; alt=&quot;Squid-Game Masks&quot; /&gt;&lt;/p&gt;

&lt;p&gt;… und ich überlege noch, ob ich mal meine Nachbarn damit auf dunklem Flur
erschrecken soll.&lt;br /&gt;
Naja … besser nicht. 😛&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Windows Image Cleanup</title>
   <link href="https://www.opengate.at/blog/2021/10/image-cleanup/"/>
   <published>2021-10-30T13:00:00+02:00</published>
   <updated>2021-10-30T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2021/10/image-cleanup</id>
   <category term="software" />
   <summary type="text">Windows wird immer 
langsamer und träger. Schuld daran sind unnötige Apps, die man “schnell” 
ausprobieren wollte, aber leider fallen auch Windows Updates darunter.

Bevor man sich also eine weitere verlangsamende App herunterlädt, die 
behauptet, sie würde beschleunigen, kann man mit 
dism 
und Windows PE 
auch einiges erreichen.
</summary>
   <content type="html">&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_10&quot;&gt;Windows&lt;/a&gt; wird immer 
langsamer und träger. Schuld daran sind unnötige Apps, die man “schnell” 
ausprobieren wollte, aber leider fallen auch Windows Updates darunter.&lt;/p&gt;

&lt;p&gt;Bevor man sich also eine weitere verlangsamende App herunterlädt, die 
behauptet, sie würde beschleunigen, kann man mit 
&lt;a href=&quot;https://docs.microsoft.com/en-us/windows-hardware/manufacture/desktop/what-is-dism&quot;&gt;&lt;code&gt;dism&lt;/code&gt;&lt;/a&gt; 
und &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_PE&quot;&gt;Windows PE&lt;/a&gt; 
auch einiges erreichen.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Windows Updates sichern stets das, was sie ersetzen.
Im Laufe des Support-Zyklus einer Windows Version wird fast das gesamte 
Betriebssystem einmal ausgetauscht.&lt;br /&gt;
Man startet mit einer 10 GB Installation und auch ohne neue Apps hat
man ein paar Jahre später plötzlich 20, 30 oder 40 GB voll.&lt;/p&gt;

&lt;p&gt;In Zeiten von Windows XP und Server 2003 hätte ich dann einen Slipstream-
Integration aller Updates + Neuinstallation empfohlen, womit man das
“neueste” Windows inklusive Updates aber ohne Dreck von gestern hat.
Siehe &lt;a href=&quot;/blog/2018/12/nlite/&quot;&gt;nLite&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Seit Vista und &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_7&quot;&gt;Windows 7&lt;/a&gt; 
sind Komponenten und Updates strukturierter gespeichert und es wurde auch 
eine verbesserte “Festplattenbereinigung” nachgeliefert, mit der man auch 
den Update-Store bereinigen konnte.&lt;/p&gt;

&lt;p&gt;Doch solche UI-Tools findet man z.B. auf den Server-Core Varianten leider
nicht.&lt;/p&gt;

&lt;p&gt;Ab &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_8&quot;&gt;Windows 8&lt;/a&gt; und vor 
allem mit Windows 10 sind dann jede Menge sehr hilfreiche
Funktionen in das Tool &lt;code&gt;dism&lt;/code&gt; und die DISM-API eingeflossen.&lt;/p&gt;

&lt;p&gt;Neben der früher geschilderten &lt;a href=&quot;/blog/2021/03/restorehealth/&quot;&gt;RestoreHealth-Funktion&lt;/a&gt; 
gefällt mir auch besonders:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;dism /Image:C:\ /Cleanup-Image /StartComponentCleanup /ResetBase
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Denn dieses Kommando veranlasst Windows seinen Update-Store aufzuräumen und 
alle früheren Komponenten Versionen und Update-Backups zu löschen. Man kann
danach zwar keine Updates mehr zurücknehmen, hat aber ein schlankeres 
Windows, mehr Festplattenplatz und vielleicht sogar ein paar 
Performancegewinne (je nach tragweite).&lt;/p&gt;

&lt;p&gt;Das ganze funktioniert aber nur, wenn die Windows Installation nicht läuft.
Die Lösung: Man bootet Windows PE und startet &lt;code&gt;dism&lt;/code&gt; von dort aus.&lt;/p&gt;

&lt;p&gt;Da Windows PE auch die Basis einer jeden Windows Installationsmediums ist,
startet man einfach dieses und wählt dort die Computer-Reparatur-Werkzeuge.
Dort kann man ein Konsolenfenster öffnen und muss jetzt nur noch herausfinden,
welchen Laufwerksbuchstaben Windows PE der normalen Windows-Installation 
zugeorndnet hat. Das kann &lt;code&gt;c:\&lt;/code&gt; sein, aber auch etwas höheres, falls mehrere
Festplatten oder Partitionen im System vorhanden sind.&lt;/p&gt;

&lt;p&gt;Nun startet man &lt;code&gt;dism&lt;/code&gt; mit dem korrekten Laufwerk 
… und dann kann man was anderes tun, denn der Schritt kann von 10 Minuten bis
über eine Stunde dauern.&lt;/p&gt;

&lt;p&gt;Unter Windows PE braucht &lt;code&gt;dism&lt;/code&gt; ein “Scratch-Directory” für temporäre Dateien,
doch dafür kann man auch das Laufwerk der Windows-Installation angeben, wenn 
darauf ein paar Gigabytes frei sind.&lt;/p&gt;

&lt;p&gt;Das finale Kommando lautet damit z.B.:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;dism /Image:C:\ /ScratchDir:C:\Scratch /Cleanup-Image /StartComponentCleanup /ResetBase
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Mein Beispiel war meine Server 2016 Backup-Installation. Die startete mit 
10 GB und wuchs dann mit Windows Updates bis auf 24 GB an.&lt;/p&gt;

&lt;p&gt;Ein &lt;code&gt;dism Cleanup-Image&lt;/code&gt; verkleinerte die Installation auf 15 GB.&lt;br /&gt;
Das dauerte auf meinem Intel Atom zwar zwei Stunden, aber das war es wert.&lt;/p&gt;

&lt;p&gt;Ein &lt;code&gt;Cleanup-Image&lt;/code&gt; optimiert nicht nur die eigene Installation, es reduziert 
auch Images, die per &lt;a href=&quot;/blog/2018/10/sysprep/&quot;&gt;SYSPREP&lt;/a&gt; auf 
ein Deployment vorbereitet werden.&lt;/p&gt;

&lt;p&gt;Dass man parallel mit &lt;code&gt;dism&lt;/code&gt; auch Treiber oder andere Windows Features
installieren und deinstallieren kann, ist natürlich auch kein Geheimnis.&lt;/p&gt;

&lt;p&gt;Wenn ich bedenke, wie wenig &lt;code&gt;dism&lt;/code&gt; in Windows 7 konnte und es mit heute 
vergleiche, zeigt sich diesmal:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Früher war doch nicht alles besser.&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>Es ist eine Schande</title>
   <link href="https://www.opengate.at/blog/2021/10/national-holiday/"/>
   <published>2021-10-26T13:00:00+02:00</published>
   <updated>2021-10-26T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2021/10/national-holiday</id>
   <category term="general" />
   <summary type="text">
  Österreich ist frei …


… von jeder Art von Anstand.

Heute ist Nationalfeiertag
und ich kann nichts weiter tun als mich für die Vertreter meines Landes 
gehörig zu schämen.
</summary>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;Österreich ist frei …&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;… von jeder Art von Anstand.&lt;/p&gt;

&lt;p&gt;Heute ist &lt;a href=&quot;https://de.wikipedia.org/wiki/Nationalfeiertag_(%C3%96sterreich)&quot;&gt;Nationalfeiertag&lt;/a&gt;
und ich kann nichts weiter tun als mich für die Vertreter meines Landes 
gehörig zu schämen.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;In &lt;a href=&quot;https://www.southpark.de/folgen/egyait/south-park-eine-hohle-bar-staffel-16-ep-9&quot;&gt;Folge 9 aus Staffel 16&lt;/a&gt;
der Serie &lt;a href=&quot;https://de.wikipedia.org/wiki/South_Park&quot;&gt;South Park&lt;/a&gt; mit dem 
sprechenden Titel “Raising the Bar” (deutsch: Ein hohle Bar) ging es darum, 
was passiert, wenn “das Niveau” der Menschen und der Medien stets gesenkt wird.&lt;br /&gt;
Aus heutiger Sicht erscheint mir diese Episode wie eine 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Parabel_(Sprache)&quot;&gt;Parabel&lt;/a&gt; 
zur aktuellen Lage der Nation.&lt;/p&gt;

&lt;p&gt;Während man sich z.B. im Spitzensport bemüht stets besser zu werden, in dem 
man sprichwörtlich “die Latte höher legt”, findet in der Politik offenbar
ein gegenteiliger Prozess statt:&lt;br /&gt;
Man redet sich ein, dass schon immer alle korrupt waren und es deshalb 
ohnehin egal ist.&lt;/p&gt;

&lt;p&gt;In den vergangenen 20 Jahren hätte Österreich 5 Legislaturperioden von 5 Jahren
(anfangs waren es nur 4 Jahre) haben sollen.
Geworden sind es 7 und nur 2 mal wurde der Koalitions-Pakt eingehalten, 
für den wir Steuerzahler kräftig in die Tasche greifen dürfen:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Regierung&lt;/th&gt;
      &lt;th style=&quot;text-align: right&quot;&gt;Bruch&lt;/th&gt;
      &lt;th&gt;Pseudo-Motto&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;2000 - 2002&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;Ja&lt;/td&gt;
      &lt;td&gt;Wir sehen uns in Knittelfeld&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;2002 - 2006&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;Nein&lt;/td&gt;
      &lt;td&gt;Händ’ falten, Goschn halten&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;2006 - 2008&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;Ja&lt;/td&gt;
      &lt;td&gt;Willi sagt: Es reicht!&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;2008 - 2013&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;Nein&lt;/td&gt;
      &lt;td&gt;Ohne-Wachteleier-Koalition&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;2013 - 2017&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;Ja&lt;/td&gt;
      &lt;td&gt;Zug fährt ab&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;2017 - 2019&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;Ja&lt;/td&gt;
      &lt;td&gt;A b’soffene G’schicht&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;2019 - 2022?&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;Bald?&lt;/td&gt;
      &lt;td&gt;Es gilt die Unschuldsvermutung&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Als Bundespräsident &lt;a href=&quot;https://de.wikipedia.org/wiki/Alexander_Van_der_Bellen&quot;&gt;Alexander Van der Bellen&lt;/a&gt;
den &lt;a href=&quot;https://de.wikipedia.org/wiki/Ibiza-Aff%C3%A4re&quot;&gt;Ibiza-Skandal&lt;/a&gt; mit den Worten&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;So sind wir nicht!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;kommentierte, war das Kind schon in den Brunnen gefallen.&lt;br /&gt;
Denn da hat es angefangen, dass niemand Verantwortung übernehmen wollte, 
und eine Pressekonferenz nach der anderen gegeben wurde, in der nicht der 
schändliche Inhalt des Videos kritisiert wurde, sondern dessen Entstehung.&lt;/p&gt;

&lt;p&gt;Wenn man sich nur scheinbar entschuldigt, um im Folgesatz eine 
Täter-Opfer-Umkehr zu skizzieren, wird die Entschuldigung entwertet.&lt;br /&gt;
Man stelle sich z.B.: vor, ein Vergewaltiger sagt:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ja, es tut mir leid, ich hätte sie nicht zwingen sollen.&lt;br /&gt;
Aber sie wollte es ja eigentlich so.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ein jeder wird mir zustimmen, dass der zweite Satz deutlich zeigt, dass keine
Schuld und keine Reue beim Täter eingestanden wird.&lt;br /&gt;
Und genau so war es bei unseren damaligen Vizekanzler.&lt;/p&gt;

&lt;p&gt;2021 setzt einen drauf und es heißt jetzt unverblümt:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Die Justiz ist korrupt (weil sie gegen uns ermittelt).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;What-the-fuck?&lt;br /&gt;
Also ganz ehrlich … hier bin ich wirklich ratlos.&lt;/p&gt;

&lt;p&gt;Dass “meine” Regierung, die von mir mitbezahlt wird und die “meine” Verfassung
schützen soll, jetzt die Legitimität der Justiz angreift um das eigene 
Verschulden von &lt;a href=&quot;https://de.wikipedia.org/wiki/%C3%96VP-Korruptionsaff%C3%A4re&quot;&gt;nachgewiesener Korruption&lt;/a&gt;
umzudeuten, ist einfach nur pervers.&lt;/p&gt;

&lt;p&gt;Niemand bestreitet aktuell die Echtheit der veröffentlichten 
Chat-Nachrichten, wo Umfragen und damit Wahlmanipulation besprochen wird und 
dass die Sache über das Finanzministerium “abgerechnet” wurde.&lt;br /&gt;
Und niemand bestreitet zur Zeit, dass die Verhinderung der Einrichtung von
Nachmittagsbetreuungsstätten für Kinder nur deshalb zu Fall gebracht wurde, 
damit man dem politischen Vorgänger “eins auswischen konnte”.&lt;/p&gt;

&lt;p&gt;Die Redaktion der &lt;a href=&quot;https://de.wikipedia.org/wiki/Der_Standard&quot;&gt;Zeitung Standard&lt;/a&gt; 
hat die Chats in einem Video kurz zusammengefasst:&lt;/p&gt;

&lt;iframe width=&quot;640&quot; height=&quot;360&quot; src=&quot;/blog/redirect.html?https%3A%2F%2Fwww.youtube-nocookie.com%2Fembed%2F122iUqsCZU8&quot; frameborder=&quot;1&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;

&lt;blockquote&gt;
  &lt;p&gt;Selbstverständlich gilt immer die Unschuldsvermutung.
Das war bei &lt;a href=&quot;https://de.wikipedia.org/wiki/Lucona&quot;&gt;Lucona&lt;/a&gt; anfangs auch so.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Und trotzdem stellen sich führende Persönlichkeiten aus Bund und Ländern 
vor die Kamera und konstruieren zielgerichtet eine Verschwörung gegen 
die eigene Partei.&lt;/p&gt;

&lt;p&gt;WOW. Danke an die Politik! Jetzt habt ihr es wirklich geschafft!&lt;/p&gt;

&lt;p&gt;Wer soll euch denn jetzt auch nur irgend welche Kompetenzen zuordnen, damit
ihr unser Land regieren dürft?&lt;br /&gt;
Was sagen wir denn jetzt den immer größer werdenden Gruppen von 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Reichsb%C3%BCrgerbewegung&quot;&gt;Reichsbürgern&lt;/a&gt; und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Neonazismus&quot;&gt;Neonazis&lt;/a&gt;, die immer selbstbewusster
durch die Straßen marschieren?&lt;br /&gt;
Was sagen wir den Verschwörungstheoretikern, die eine Chip-Implantation 
der Regierung in jeder Impfspritze daherfabulieren?&lt;/p&gt;

&lt;p&gt;Es ist schwer jemand anderen der Falschaussage zu bezichtigen, 
wenn man selbst nicht die Wahrheit spricht.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Ich habe gehört: Früher war Österreich&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;ein Land der Musik&lt;/li&gt;
  &lt;li&gt;ein Land der Dichter und Autoren&lt;/li&gt;
  &lt;li&gt;ein Land des Dialogs zwischen Ost und West&lt;/li&gt;
  &lt;li&gt;und ein Garant für Rechtsstaatlichkeit&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Und was assoziiert die Welt heute mit uns?&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Bei denen waren nur die Pferde und nicht 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Waldheim-Aff%C3%A4re#Kunst&quot;&gt;ihre Reiter&lt;/a&gt; 
bei der &lt;a href=&quot;https://de.wikipedia.org/wiki/Waffen-SS&quot;&gt;Waffen-SS&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;Die sperren ihre &lt;a href=&quot;https://de.wikipedia.org/wiki/Entf%C3%BChrung_von_Natascha_Kampusch&quot;&gt;Kinder in Kellern&lt;/a&gt; 
ein und betreiben &lt;a href=&quot;https://de.wikipedia.org/wiki/Josef_Fritzl&quot;&gt;Inzest&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;Die tarnen den &lt;a href=&quot;https://de.wikipedia.org/wiki/Hitlergru%C3%9F#K%C3%BChnengru%C3%9F&quot;&gt;Kühnengruß&lt;/a&gt; 
mit einer Bierbestellung.&lt;/li&gt;
  &lt;li&gt;Die wollen Asylwerber “konzentriert an einem Ort halten”, Zitat 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Herbert_Kickl#Bundesminister_f%C3%BCr_Inneres&quot;&gt;H. Kickl&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;Sie verkaufen ihr Hab und Gut an russische Oligarchen auf 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Ibiza-Aff%C3%A4re&quot;&gt;Ibiza&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Und sie bezahlen 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Sebastian_Kurz#Ermittlungen_wegen_Korruption,_manipulierter_Umfragen_und_Betrugs&quot;&gt;Umfragenfälschungen&lt;/a&gt;
mit Mitteln aus der Korruptionsbekämpfung.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Und dann heißt es: Das sei doch alles nicht so schlimm und “eh normal” ?&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ich schäme mich.&lt;/p&gt;

&lt;p&gt;Nicht nur für die handelnden Akteure, sondern auch für alle Mitmenschen, 
die der Aufklärung mit billiger Propaganda entgegenwirken und die die 
kritische Sachlage dazu missbrauchen wollen, ihre antidemokratischen 
Meinungen zu verbreiten.&lt;/p&gt;

&lt;p&gt;Skandale gab es immer schon. Und jeder Verbrecher hat zu jeder Zeit versucht,
seine Schuld abzuwälzen oder klein zu reden.&lt;br /&gt;
Doch warum stören sich immer weniger Menschen daran und halten es für normal?
Die heutige Zeit des Medien- und Informationsüberflusses bewirkt damit leider
zusätzlich, dass Aufklärung gebremst und teils auch verhindert wird.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Ich wünschte, ich wüsste eine Lösung dagegen.&lt;br /&gt;
… aber selbst der neueste C++ Standard kann absichtlich hervorgerufene 
Datenkorruptionen nicht verhindern.&lt;/p&gt;

&lt;p&gt;Letztendlich ist es leider genau so, wie es seinerzeit im 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Elisabeth_(Musical)&quot;&gt;Muscial “Elisabeth”&lt;/a&gt;
besungen wurde, und was ich hiermit nur zitieren kann:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Na und wenn schon!&lt;br /&gt;
Wir sitzen im Kaffeehaus rum.&lt;br /&gt;
Und erwarten gähnend die Apokalypse.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;video controls=&quot;&quot;&gt;
  &lt;source src=&quot;/blog/assets/video/elisabeth-apokalypse.mp4&quot; type=&quot;video/mp4&quot; /&gt;
  Your browser does not support the HTML5 VIDEO tag.
&lt;/video&gt;

&lt;p&gt;Trotzdem wünsche ich allen Mitbürgern einen schönen Feiertag,
und etwas Zeit zum Nachdenken.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;PS: Botschaft an mich selbst in 10 Jahren:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Und? Wie ist die Sache ausgegangen?&lt;br /&gt;
Denkst du immer noch mit Kopfschütteln and diese Zeit zurück?&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>Raspberry PI im Akkubetrieb</title>
   <link href="https://www.opengate.at/blog/2021/10/rpi-ups/"/>
   <published>2021-10-24T13:00:00+02:00</published>
   <updated>2021-10-24T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2021/10/rpi-ups</id>
   <category term="hardware" />
   <summary type="text">Das “RPi-PowerPack” ist ein Board mit einem LiPo Akku,
der einen Raspberry PI 2 und 3 B 
eine Zeit lang bestromen kann.

Doch diese Board hat einen unguten Fehler:
Beim Umschalten zwischen externem Aufladen und reinem Akkubetrieb,
gibt es einen kurzen Stromaussetzer, der einen ungewollten Reboot
(und eventuell Datenverlust) einleitet.
</summary>
   <content type="html">&lt;p&gt;Das “RPi-PowerPack” ist ein Board mit einem &lt;a href=&quot;https://de.wikipedia.org/wiki/Lithium-Polymer-Akkumulator&quot;&gt;LiPo Akku&lt;/a&gt;,
der einen &lt;a href=&quot;https://de.wikipedia.org/wiki/Raspberry_Pi&quot;&gt;Raspberry PI&lt;/a&gt; 2 und 3 B 
eine Zeit lang bestromen kann.&lt;/p&gt;

&lt;p&gt;Doch diese Board hat einen unguten Fehler:&lt;br /&gt;
Beim Umschalten zwischen externem Aufladen und reinem Akkubetrieb,
gibt es einen kurzen Stromaussetzer, der einen ungewollten Reboot
(und eventuell Datenverlust) einleitet.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/rpi-powerpack-01.jpg&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Wenn es nur darum ginge, einen Raspberry PI mit Akkustrom zu betreiben,
dann hätte das Board alles richtig gemacht.&lt;/p&gt;

&lt;p&gt;Die 3.7 Volt des LiPo Akkus werden auf 5 V hochge-boost-et und per 
USB Kabel in den RPi eingespeist.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/rpi-powerpack-02.jpg&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Doch wenn man das Board selbst an eine Stromversorgung anschließt um den
Akku aufzuladen, kommt es zum ungewollten Reboot des Boards.&lt;/p&gt;

&lt;p&gt;Dieses Problem haben auch schon einige andere Bastler erkannt und festgestellt,
dass es an einem zu klein dimensionierten 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Kondensator_(Elektrotechnik)&quot;&gt;Kondensator&lt;/a&gt; liegt.&lt;/p&gt;

&lt;p&gt;Da die Stromunterbrechung nur kurz beim Umschalten des Ladechips auftritt, 
kann ein Kondensator mit höherer Kapazität diese Manko beheben, womit aus
dem “PowerPack” eine 
&lt;a href=&quot;https://en.wikipedia.org/wiki/Uninterruptible_power_supply&quot;&gt;UPS (Uninterrupted Power Supply)&lt;/a&gt;,
zu deutsch USV (unterbrechungsfreie Stromversorgung), wird.&lt;/p&gt;

&lt;p&gt;Mit 220 &lt;a href=&quot;https://de.wikipedia.org/wiki/Farad&quot;&gt;Millifarad&lt;/a&gt; sollte das 
Schlimmste überwunden werden, und dafür gibt es sogar eine 3D-Druck-bare 
&lt;a href=&quot;https://www.thingiverse.com/thing:3180298&quot;&gt;Halterung auf Thingiverse&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Doch ich bin skeptisch, ob 220 mF wirklich ausreichen, wenn man weitere Geräte
angeschlossen hat und der R-Pi unter Volllast steht. 
Und deshalb habe ich meinen stärksten Kämpfer aus der Kondensator-Schachtel 
geholt: &lt;em&gt;Einen 5.5V 4F Super-Kondensator&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Diese Teile können wirklich viel Strom speichern und sind damit theoretisch
18 mal stärker als die 220 mF Variante.&lt;/p&gt;

&lt;p&gt;Man lötet die Plus und Minus-Pole des zusätzlichen Stützkondensators einfach 
beim obersten der kleinen SMD-Kondensatoren am Board dazu und hat somit die 
Kapazität um ein Vielfaches gesteigert.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/rpi-powerpack-03.jpg&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Ein paar Tropfen aus der Heißklebepistole sorgen dafür, dass der Kondensator
und seine Verkabelung fixiert sind und schon kann man seine neue 
Raspberry-Pi UPS in Betrieb nehmen.&lt;/p&gt;

&lt;p&gt;Nun kann der R-Pi je nach Auslastung die eine oder andere Stunde frei im
Raum herumgetragen werden, bevor er wieder ans USB Netzteil gesteckt werden 
muss. Ohne Stromunterbrechung und Reboot kann man das Gerät nun z.B. zu 
einem Sensor oder einer &lt;a href=&quot;https://de.wikipedia.org/wiki/Mikrocontroller&quot;&gt;MCU&lt;/a&gt; 
im Nebenzimmer tragen, dort Daten abholen lassen und sorgenfrei wieder 
zurückkehren.&lt;/p&gt;

&lt;p&gt;Auch ein auf den R-Pi draufgesetztes LCD-Display kann so problemlos 
mitbestromt werden.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Mit der Kapazität habe ich es wohl etwas übertrieben. Ich hätte auch einen 
670 mF Kondensator in der Kiste gehabt, aber hey … überdimensionierte
Kondensatoren schaden hier nicht, unterdimensionierte sehr wohl.&lt;/p&gt;

&lt;p&gt;Ein Nebeneffekt ist, dass das RPI noch für 1 bis 2 Sekunden nach Abschaltung
Strom aus dem Kondensator ziehen kann, bis er ausfällt. Aber es ist generell
eine schlechte Idee den RPi nicht korrekt herunterzufahren, bevor man ihm den
Strom entzieht.&lt;/p&gt;

&lt;p&gt;Aber ich freue mich, dass man mit 5 cm Draht, einem Kondensator und zwei
Lötzinntropfen einen “Konstruktionsfehler” so leicht beheben kann.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Unit Tests</title>
   <link href="https://www.opengate.at/blog/2021/10/unit-tests/"/>
   <published>2021-10-23T13:00:00+02:00</published>
   <updated>2021-10-23T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2021/10/unit-tests</id>
   <category term="devel" />
   <summary type="text">
  Unit tests 
sind in der Entwicklung ein notwendiges Übel, weil die
Vorgesetzten es als Funktionsbeweis haben wollen.


So habe ich es viele Jahre gesehen und auch heute erscheinen mir manche
Testanforderungen nur als lästige Bürokratie, die selten wirklich etwas
“abtestet”.

Doch nun beweist mir meine eigene Fehlbarkeit, dass Unit Tests
IMMER eine Existenzberechtigung haben.
</summary>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Modultest&quot;&gt;Unit tests&lt;/a&gt; 
sind in der Entwicklung ein notwendiges Übel, weil die
Vorgesetzten es als Funktionsbeweis haben wollen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So habe ich es viele Jahre gesehen und auch heute erscheinen mir manche
Testanforderungen nur als lästige Bürokratie, die selten wirklich etwas
“abtestet”.&lt;/p&gt;

&lt;p&gt;Doch nun beweist mir meine eigene Fehlbarkeit, dass Unit Tests
&lt;em&gt;IMMER&lt;/em&gt; eine Existenzberechtigung haben.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Es gibt einen Grund, warum ich Unit Tests immer etwas skeptisch gegenüberstand:
In meiner Welt sind Codes ziemlich System-spezifisch und nur relativ schwer
in Tests zu fassen.&lt;/p&gt;

&lt;p&gt;Wie soll ich denn z.B. direkte Festplattenzugriffe “effektiv” abtesten.
Oder wie soll die korrekte Funktion eines &lt;a href=&quot;https://de.wikipedia.org/wiki/Windows-Systemdienst&quot;&gt;Windows-Service&lt;/a&gt;
Starts oder eines &lt;a href=&quot;https://de.wikipedia.org/wiki/Daemon&quot;&gt;Linux-Daemon&lt;/a&gt; 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Fork_(Unix)&quot;&gt;Forks&lt;/a&gt; verifiziert werden?&lt;br /&gt;
Da kann man gleich &lt;code&gt;return true&lt;/code&gt; schreiben, denn die “echten” Fehler findet 
man nur beim Debugging oder in Crash-Reports.&lt;/p&gt;

&lt;p&gt;Das ist in vielen Business-Anwendungen anders, wo im Endeffekt immer nur 
Daten hin und her-konvertiert werden. Denn da kann man einen künstlichen
Input und erwarteten Output “leicht” durch die selbst geschriebene Funktion
jagen und vergleichen. Ein solcher Unit test wird dann schnell Fehler 
in Algorithmen und Mappings aufzeigen können.&lt;/p&gt;

&lt;p&gt;Doch genau das ist bei System-nahen Routinen weniger einfach und wenn
das Abtesten den 10-fachen Aufwand des Quellenschreibens ausmacht,
schwindet meine Motivation dafür deutlich.&lt;/p&gt;

&lt;h3 id=&quot;interface-stabilität-und-regression-tests&quot;&gt;Interface-Stabilität und Regression Tests&lt;/h3&gt;

&lt;p&gt;Wenn man eine Schnittstelle auf mehreren Plattformen implementiert um 
dadurch eine OS-Abstraktion zu erhalten, ist es essentiell, dass die
Schnittstelle auf jeder Plattform das exakt gleiche Verhalten aufweist
und sich dieses über die Zeit auch nicht ändert.&lt;/p&gt;

&lt;p&gt;Schnell kann es passieren, man mal meint:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ich füge da ein kleines Feature hinzu, aber das ist ungefährlich,
es ändert sich nichts für bestehenden Code.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Und 1 Monat später hat man den A*sch offen, weil sich dennoch Seiteneffekte
ergeben haben und die Resultate einfach nicht mehr stimmen.&lt;/p&gt;

&lt;p&gt;Problematisch sind auch nicht konkret dokumentierte Erwartungen gegenüber
Funktionen und Daten.&lt;br /&gt;
Mir ist nämlich folgendes passiert:&lt;/p&gt;

&lt;p&gt;Die &lt;code&gt;gate_atomic_*&lt;/code&gt; Funktionen stellen atomare Integer-Operationen bereit 
und wurden zuerst für Windows implementiert, wo die 
&lt;a href=&quot;http://docs.microsoft.com/en-us/windows/win32/sync/interlocked-variable-access&quot;&gt;Interlocked-APIs&lt;/a&gt;
zum Einsatz kamen. Einige davon geben als Return-Value den aktuellen Wert 
einer Variable zurück, andere geben den Wert vor der Operation zurück.&lt;/p&gt;

&lt;p&gt;Als dann später die &lt;a href=&quot;https://de.wikipedia.org/wiki/GNU_Compiler_Collection&quot;&gt;GCC&lt;/a&gt; 
Implementierung folgte, nahm ich bei einigen Funktionen ein Verhalten 
identisch zu Windows an und implementierte es auch so. Doch leider arbeitet 
der GCC hier teilweise anders.&lt;/p&gt;

&lt;p&gt;Genau an der Stelle hätte nun ein ordentlicher Unit Test sofort ein 
Interface-Problem angezeigt. Doch ohne diesen Test verbrachte ich Monate
später zahlreiche Stunden um einen Crash zu verstehen, der sich aus 
falsch interpretierten atomic-Aufrufen ergeben hatte.&lt;/p&gt;

&lt;p&gt;Lektion gelernt: &lt;strong&gt;Immer Tests schreiben!&lt;/strong&gt;&lt;/p&gt;

&lt;h3 id=&quot;test-frameworks&quot;&gt;Test Frameworks&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Boost_(C%2B%2B-Bibliothek)&quot;&gt;BOOST&lt;/a&gt; bietet mit 
seinem Test-Framework ein großes Set an Makros und Funktionen,
um eigene Tests effizient schreiben und ausführen zu können.&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color:#B44;font-weight:bold&quot;&gt;&amp;lt;boost/test/unit_test.hpp&amp;gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;BOOST_AUTO_TEST_CASE(test_name)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; expected_value = &lt;span style=&quot;color:#00D&quot;&gt;42&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; received_value;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  BOOST_REQUIRE_NO_THROW(
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;    received_value = func_to_be_tested();
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;  );
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  BOOST_CHECK_EQUAL(received_value, received_value);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Test Cases werden über die Makros zu Klassen und Methoden und 
während &lt;code&gt;REQUIRE&lt;/code&gt; Makros per Exception einen Test abbrechen, laufen
&lt;code&gt;CHECK&lt;/code&gt; Makros einfach durch, zählen aber Fehler mit, damit man sie am
Ende gesammelt ausgeben kann.&lt;/p&gt;

&lt;h3 id=&quot;gate-implementierung&quot;&gt;GATE Implementierung&lt;/h3&gt;

&lt;p&gt;In &lt;a href=&quot;https://de.wikipedia.org/wiki/C_(Programmiersprache)&quot;&gt;C&lt;/a&gt; hat man das 
Problem, dass man keine &lt;a href=&quot;https://de.wikipedia.org/wiki/Ausnahmebehandlung&quot;&gt;Exceptions&lt;/a&gt;
kennt und nicht eine Funktion “einfach so” abbrechen kann und danach 
zurückspringen kann. (Ich lasse &lt;a href=&quot;https://en.wikipedia.org/wiki/Setjmp.h&quot;&gt;setjmp/longjmp&lt;/a&gt;
hier mal bewusst weg.)&lt;/p&gt;

&lt;p&gt;Daher definiere ich eine Test-Routine als Funktion, die einen Boolean
zurückgibt und nur beim vollständigen Durchlauf mit &lt;code&gt;return true&lt;/code&gt; endet.
Fehler führen zu einem &lt;code&gt;return false&lt;/code&gt;.
Auf diese Weise kann man zumindest auf einer Ebene auch &lt;code&gt;REQUIRE&lt;/code&gt; und 
&lt;code&gt;CHECK&lt;/code&gt; Makros etablieren.&lt;/p&gt;

&lt;p&gt;Nun müssen ein paar Funktionen definiert werden, die Tests und Fehler
hochzählen und einem registriertem Test zuordnen können. Dafür reichen
einfache globale Variablen, denn jede Test-Funktion muss am Anfang ihren
Namen registrieren und alle nachfolgenden Zählungen werden so lange dem
Test zugeordnet, bis ein anderer Test startet.&lt;br /&gt;
Wie in &lt;code&gt;BOOST&lt;/code&gt; kann immer nur ein Test gleichzeitig laufen.&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#define&lt;/span&gt; GATE_TEST_STR(expression) &lt;span style=&quot;color:#579&quot;&gt;#expression&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#define&lt;/span&gt; GATE_TEST_UNIT_BEGIN(name) \
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  gate_test_unit_begin(GATE_TEST_STR(name), __FILE__, __LINE__)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#define&lt;/span&gt; GATE_TEST_UNIT_END \
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color:#069&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#define&lt;/span&gt; GATE_TEST_CHECK(expression) \
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;do&lt;/span&gt; \
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  { \
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;    gate_test_count_test(); \
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt;( ! (expression) ) \
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;    { \
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;      gate_test_count_error(); \
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;      gate_test_error_message( GATE_TEST_STR(expression), \
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;        __FILE__, __LINE__ ); \
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;    } \
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;  } &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;while&lt;/span&gt;(&lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#define&lt;/span&gt; GATE_TEST_REQUIRE(expression) \
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n21&quot; name=&quot;n21&quot;&gt;21&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;do&lt;/span&gt; \
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n22&quot; name=&quot;n22&quot;&gt;22&lt;/a&gt;&lt;/span&gt;  { \
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n23&quot; name=&quot;n23&quot;&gt;23&lt;/a&gt;&lt;/span&gt;    gate_test_count_test(); \
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n24&quot; name=&quot;n24&quot;&gt;24&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt;( ! (expression) ) \
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n25&quot; name=&quot;n25&quot;&gt;25&lt;/a&gt;&lt;/span&gt;    { \
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n26&quot; name=&quot;n26&quot;&gt;26&lt;/a&gt;&lt;/span&gt;      gate_test_count_error(); \
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n27&quot; name=&quot;n27&quot;&gt;27&lt;/a&gt;&lt;/span&gt;      gate_test_error_message( GATE_TEST_STR(expression), \
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n28&quot; name=&quot;n28&quot;&gt;28&lt;/a&gt;&lt;/span&gt;        __FILE__, __LINE__ ); \
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n29&quot; name=&quot;n29&quot;&gt;29&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color:#069&quot;&gt;false&lt;/span&gt;; \
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n30&quot; name=&quot;n30&quot;&gt;30&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;    } \
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n31&quot; name=&quot;n31&quot;&gt;31&lt;/a&gt;&lt;/span&gt;  } &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;while&lt;/span&gt;(&lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;)
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Mit diesem Set an Makros, kann man schon seinen ersten Test schreiben:&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color:#B44;font-weight:bold&quot;&gt;&amp;quot;gate/test.h&amp;quot;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;gate_result_t func_to_be_tested(&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt;* ptr_output);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;static&lt;/span&gt; gate_bool_t test_someting()
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; expected_value = &lt;span style=&quot;color:#00D&quot;&gt;42&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; received_value;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  GATE_TEST_UNIT_BEGIN(test_someting);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;  GATE_TEST_REQUIRE(
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;    GATE_RESULT_OK == func_to_be_tested(&amp;amp;received_value)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;  );
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;  GATE_TEST_CHECK(received_value == expected_value);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;  GATE_TEST_UNIT_END;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Das ganze steht noch am Anfang und wird sicher noch einige Updates erfahren.
Und wenn man die Ergebnisse am Ende in einem handelsüblichen Format, wie
z.B. &lt;a href=&quot;https://de.wikipedia.org/wiki/JUnit&quot;&gt;JUnit als XML&lt;/a&gt; ausgibt, dann kann 
man auch bestehende Tools zur Überprüfung und Anzeige der eigenen Ergebnisse 
einsetzen.&lt;/p&gt;

&lt;p&gt;Natürlich würde es auch Sinn machen, hier auf eine bestehende Lösung zu
vertrauen und im Beruf sehe ich das als unbedingt notwendig.&lt;/p&gt;

&lt;p&gt;Doch im GATE Projekt geht es mir ja auch darum zu lernen, wie man solche
Frameworks selbst aufbaut und unabhängig von Megabyte großen Runtimes auch
zu annehmbaren Ergebnissen kommen kann.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Mini-UPS</title>
   <link href="https://www.opengate.at/blog/2021/10/mini-ups/"/>
   <published>2021-10-17T13:00:00+02:00</published>
   <updated>2021-10-17T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2021/10/mini-ups</id>
   <category term="hardware" />
   <summary type="text">Stromausfälle sind in Wien verdammt selten. 
Das passiert vielleicht alle 10 Jahre mal, wenn ein Stromzähler getauscht werden muss. 
Ansonsten kann ich mich an keine Unterbrechung erinnern.

Aber … was wäre wenn? Und wäre es nicht toll, wenn man ein Gerät an einen 
anderen Ort versetzen kann ohne seinen Betrieb zu unterbrechen?

Die Lösung heißt UPS (Uninterrupted Power Supply) 
bzw. Unterbrechungsfreie Strom-Versorgung (USV).
</summary>
   <content type="html">&lt;p&gt;Stromausfälle sind in &lt;a href=&quot;https://de.wikipedia.org/wiki/Wien&quot;&gt;Wien&lt;/a&gt; verdammt selten. 
Das passiert vielleicht alle 10 Jahre mal, wenn ein Stromzähler getauscht werden muss. 
Ansonsten kann ich mich an keine Unterbrechung erinnern.&lt;/p&gt;

&lt;p&gt;Aber … was wäre wenn? Und wäre es nicht toll, wenn man ein Gerät an einen 
anderen Ort versetzen kann ohne seinen Betrieb zu unterbrechen?&lt;/p&gt;

&lt;p&gt;Die Lösung heißt &lt;a href=&quot;https://de.wikipedia.org/wiki/Unterbrechungsfreie_Stromversorgung&quot;&gt;UPS (Uninterrupted Power Supply)&lt;/a&gt; 
bzw. &lt;em&gt;Unterbrechungsfreie Strom-Versorgung&lt;/em&gt; (USV).
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;22-watt-aus-dem-akku&quot;&gt;22 Watt aus dem Akku&lt;/h3&gt;

&lt;p&gt;Und wieder einmal findet man im Land der aufgehenden Sonne die 
kostengünstigste Lösung, wo man für etwa 12 Euro einen 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Lithium-Ionen-Akkumulator&quot;&gt;Lithium-Ionen Akku&lt;/a&gt; 
mit 12V und 2 Ampere zwischen das Netzteil und z.B. einen Router stecken kann.&lt;/p&gt;

&lt;p&gt;Bei der geringen Stromaufnahme hält der Akku den Router für mindestens eine
Stunde problemlos am Laufen. 
Natürlich gibt es diesen Mini-UPS Typ auch für 9V und 5V Geräte.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/mini-ups-12v.jpg&quot; alt=&quot;Mini-UPS-12V&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Für mich ist der kleine Stromspeicher für den Internet-Zugang relevant.
Sollte plötzlich der Strom weg sein könnte ich schnell auf meinen voll 
geladenen Laptop ausweichen, der mich ein paar Stunden arbeiten lässt, doch 
ohne Internet wird das langweilig.&lt;br /&gt;
Die UPS lässt mich also noch im Internet nachsehen, 
warum die Welt gerade untergeht.&lt;/p&gt;

&lt;h3 id=&quot;leider-noch-kein-itx-support&quot;&gt;Leider noch kein ITX Support&lt;/h3&gt;

&lt;p&gt;Meine &lt;a href=&quot;https://de.wikipedia.org/wiki/Mini-ITX&quot;&gt;ITX&lt;/a&gt; Mainboards brauchen nie 
über 20 Watt und werden alle durch 12 V Netzteile gespeist. Da lag die 
Überlegung nahe auch sie durch eine Mini-UPS abzusichern.&lt;/p&gt;

&lt;p&gt;Doch da haben mir die Hersteller einen kleinen Strich durch die Rechnung 
gemacht. Mir ist bisher nicht aufgefallen, dass es bei den typischen runden 
DC-Stromsteckern Abweichungen gibt.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Geräte wie Router nutzen oft einen Stecker mit 5.5 mm Außendurchmesser 
und 2.1 mm Innendurchmesser.&lt;/li&gt;
  &lt;li&gt;Doch meine ITX Mainboards und ihre Netzteile erwarten einen Stecker, der
innen 2.5 mm Hohlraum aufweisen muss.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Und nachdem die Mini-UPS nur mit 2.1 mm Stecker geliefert wird, kann ich
sie auch nicht mit Gewalt in die Buchse des Mainboards bekommen.&lt;/p&gt;

&lt;p&gt;Doch die Lösung ist einfach: Wir bestellen solche Stecker einfach nach
und in ein paar Wochen wird das Experiment voraussichtlich starten,
in dem ich dann auch ein ITX Mainboard von der UPS aus betreibe.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Tja, geniale Dinger, diese kleinen Stromspeicher. Jetzt kann ich erstmals
problemlos durch die Wohnung laufen und den besten Ort für meinen 
&lt;a href=&quot;https://de.wikipedia.org/wiki/5G&quot;&gt;5G Empfang&lt;/a&gt; suchen.&lt;/p&gt;

&lt;p&gt;Gespannt bin ich vor allem, ob die ITX Boards damit starten können … denn
beim Einschalten halte ich es zumindest für möglich, dass eine Stromspitze entsteht,
die der Akku nicht stabil liefern kann.&lt;/p&gt;

&lt;h3 id=&quot;nachtrag&quot;&gt;Nachtrag&lt;/h3&gt;

&lt;p&gt;Und ja, es funktioniert! Mit dem richtigen Stecker kann die Mini-UPS-Box 
auch meine Intel Atom ITX-Boards zumindest für 5 Minuten bestromen. Das ist 
zwar nicht viel, aber einen kurzen Stromausfall kann ich somit überwinden.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Pixel Fonts</title>
   <link href="https://www.opengate.at/blog/2021/10/pixel-fonts/"/>
   <published>2021-10-16T13:00:00+02:00</published>
   <updated>2021-10-16T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2021/10/pixel-fonts</id>
   <category term="devel" />
   <summary type="text">Schriftarten (auch “Fonts” genannt) 
sind heute eine komplexe Sache. Alles ist vektorisiert und die Zeichen 
orientieren sich an mehreren Linien um Schleifen Punkte und Striche
auf der richtigen Höhe im Verhältnis zu den anderen Zeichen zu setzen.

Früher hatten wir feste Schriftarten, die es in ein paar Größen gab und in 
denen Zeichen für Zeichen und Pixel für Pixel fix gespeichert waren.
Denn so etwas kann man nämlich sehr leicht selbst implementieren.
</summary>
   <content type="html">&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Font_(Informationstechnik)&quot;&gt;Schriftarten (auch “Fonts” genannt)&lt;/a&gt; 
sind heute eine komplexe Sache. Alles ist vektorisiert und die Zeichen 
orientieren sich an mehreren Linien um Schleifen Punkte und Striche
auf der richtigen Höhe im Verhältnis zu den anderen Zeichen zu setzen.&lt;/p&gt;

&lt;p&gt;Früher hatten wir feste Schriftarten, die es in ein paar Größen gab und in 
denen Zeichen für Zeichen und Pixel für Pixel fix gespeichert waren.&lt;br /&gt;
Denn so etwas kann man nämlich sehr leicht selbst implementieren.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Als Minimalist bin ich immer wieder schockiert, wenn man die Aufgabe:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Wir müssen auf ein Foto noch eine Information wie Ort und Datum draufdrucken.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;so interpretiert, dass man eine zig-MB große Library mit unnötig komplexen
Schriftarten und deren Lizenzen an sein Programm binden muss.&lt;/p&gt;

&lt;p&gt;Ich verstehe natürlich, dass man in Falle der Internationalisierung nicht für
jedes Zeichen von Runen bis Hieroglyphen alles selbst implementieren kann,
doch gerade bei diesen 0815 Tasks wie z.B.: Datum auf ein Bild draufschreiben,
hat man das auch selbst in einigen Minuten implementiert und damit jede 
Menge Abhängigkeiten gespart.&lt;/p&gt;

&lt;p&gt;Und daher findet sich eine solche Pixel-Font auch im GATE Projekt.&lt;/p&gt;

&lt;h3 id=&quot;pixel-bits-als-c-struct&quot;&gt;Pixel Bits als C struct&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/C_(Programmiersprache)&quot;&gt;C&lt;/a&gt; unterstützt ein 
Feature, auf das gerne vergessen wird: &lt;em&gt;Bitfelder&lt;/em&gt;.&lt;br /&gt;
Man kann in einer Struktur bei einem Integer angeben, wie viele Bits dieser
belegen soll. Der Compiler legt dann die Bits in einen Datenblock zusammen
und holt bei Zugriffen genau die richtigen Bits heraus.&lt;/p&gt;

&lt;p&gt;Das kann man natürlich mit &lt;code&gt;AND&lt;/code&gt; und &lt;code&gt;OR&lt;/code&gt; Verknüpfungen auch selbst tun, 
doch mit Bitfeldern arbeiten wir so, als hätten wir einen Integer und der
Compiler erledigt den Rest.&lt;/p&gt;

&lt;p&gt;Das tolle dabei ist: Wir können dann mit einer &lt;code&gt;struct&lt;/code&gt; quasi “Bits malen”,
ohne kryptische Hex-Zahlen einsetzen zu müssen. Und wenn man ein Bit mit
einem sichtbaren Pixel gleichsetzt, kann man so ein Zeichen visuell in
Sourcecode abbilden.&lt;/p&gt;

&lt;p&gt;Aus Byte-Sicht “schöne” Ausmaße hat eine 8x8 Pixel Schrift.
Man definiert eine C &lt;code&gt;struct&lt;/code&gt; für die Bit-Member einer Zeile
und erstellt daraus ein C-Array von Zeilen um einen Buchstaben
darstellen zu können:&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;typedef&lt;/span&gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;struct&lt;/span&gt; gate_font_char_row8_bits
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;unsigned&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt; c1 : &lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;unsigned&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt; c2 : &lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;unsigned&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt; c3 : &lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;unsigned&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt; c4 : &lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;unsigned&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt; c5 : &lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;unsigned&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt; c6 : &lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;unsigned&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt; c7 : &lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;unsigned&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt; c8 : &lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;} gate_font_char_row8_bits_t;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;static&lt;/span&gt; gate_font_char_row8_bits_t &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt; font8x8_A[&lt;span style=&quot;color:#00D&quot;&gt;8&lt;/span&gt;] = {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;  { &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;,&lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;,&lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;,&lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;,&lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;,&lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;,&lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;,&lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt; },
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;  { &lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;,&lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;,&lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;,&lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;,&lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;,&lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;,&lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;,&lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt; },
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;  { &lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;,&lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;,&lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;,&lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;,&lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;,&lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;,&lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;,&lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt; },
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;  { &lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;,&lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;,&lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;,&lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;,&lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;,&lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;,&lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;,&lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt; },
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;  { &lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;,&lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;,&lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;,&lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;,&lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;,&lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;,&lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;,&lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt; },
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;  { &lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;,&lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;,&lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;,&lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;,&lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;,&lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;,&lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;,&lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt; },
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  { &lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;,&lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;,&lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;,&lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;,&lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;,&lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;,&lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;,&lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt; },
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n21&quot; name=&quot;n21&quot;&gt;21&lt;/a&gt;&lt;/span&gt;  { &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;,&lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;,&lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;,&lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;,&lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;,&lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;,&lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;,&lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt; }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n22&quot; name=&quot;n22&quot;&gt;22&lt;/a&gt;&lt;/span&gt;};
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Man braucht zwar etwas Augen-Übung, aber dann kann man erkennen, dass
die &lt;code&gt;1&lt;/code&gt; Bits den Buchstaben &lt;code&gt;A&lt;/code&gt; im Beispiel formen.&lt;/p&gt;

&lt;p&gt;Jede &lt;code&gt;gate_font_char_row8_bits_t&lt;/code&gt; Zeile belegt ein Byte (also 8 Bits), womit
man die Struct auch nach &lt;code&gt;unsigned char&lt;/code&gt; casten kann.&lt;/p&gt;

&lt;p&gt;Und wenn man nun noch zwei Schleifen baut, die für &lt;code&gt;y&lt;/code&gt; und &lt;code&gt;x&lt;/code&gt; von 0 bis 8 
laufen, reicht ein &lt;code&gt;set_pixel()&lt;/code&gt; Aufruf um jene Pixel zu zeichnen, wo das 
aktuelle Bit auf &lt;code&gt;1&lt;/code&gt; steht.&lt;br /&gt;
… fertig ist der Font-Renderer.&lt;/p&gt;

&lt;p&gt;Mit dem Bitfield-Trick lassen sich somit Schriftarten ganz leicht direkt in
den C Code einbetten.&lt;br /&gt;
Und das machen einige andere Libs 
(z.B.: aus der &lt;a href=&quot;https://de.wikipedia.org/wiki/Arduino_(Plattform)&quot;&gt;Arduino&lt;/a&gt; Welt)
ebenfalls so.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ich finde es schade und teilweise dumm, dass Entwickler heute lieber 3
Tage im Netz nach einer Bibliothek suchen, die ein Datum auf ein Rasterbild
schreiben kann, nur weil der Code per Copy &amp;amp; Paste integriert werden soll
und dann eine 200 MB Runtime im Schlepptau hängt.&lt;/p&gt;

&lt;p&gt;Es stimmt schon, dass nicht jeder das Rad neu erfinden soll, aber die
Tatsache, dass so gut wie niemand mehr weiß und wissen möchte, wie man
solche einfachen Aufgaben selbst löst, ist das andere Extrem, das
ebenso schlecht einwirkt.&lt;/p&gt;

&lt;p&gt;Ich füge meine Zeichen von A bis Z in groß und klein daher ins GATE Framework 
ein und wenn man diese Pixel-Font in einer App nicht benutzt, merkt das der 
Compiler und nimmt den Inhalt der statischen Bibliothek auch nicht weiter auf.&lt;/p&gt;

&lt;p&gt;Jetzt kann ich z.B. die Fotos meiner Webcam, die als Sicherheitskamera
umfunktioniert wurde, sofort mit Infos “signieren”, bevor sie ins Netz geschickt
werden, ohne dass ich eine Font oder Zusatz-Lib mit ausliefern muss.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>IDE Adapter und Alternativen</title>
   <link href="https://www.opengate.at/blog/2021/10/ide-adapters/"/>
   <published>2021-10-10T13:00:00+02:00</published>
   <updated>2021-10-10T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2021/10/ide-adapters</id>
   <category term="hardware" />
   <summary type="text">Ich dachte eigentlich, dass meine alten 
IDE (P-ATA oder auch ATAPI) 
Festplatten schon alle tot sind. Aber stimmt nicht, viele Festplatten 
funktionieren tatsächlich noch, und das nach 15 Jahren.

Trotzdem ersetze ich nun die unerträglich lauten und langsamen Teile 
durch Flash-Speicher Varianten.
</summary>
   <content type="html">&lt;p&gt;Ich dachte eigentlich, dass meine alten 
&lt;a href=&quot;https://de.wikipedia.org/wiki/ATA/ATAPI&quot;&gt;IDE (P-ATA oder auch ATAPI)&lt;/a&gt; 
Festplatten schon alle tot sind. Aber stimmt nicht, viele Festplatten 
funktionieren tatsächlich noch, und das nach 15 Jahren.&lt;/p&gt;

&lt;p&gt;Trotzdem ersetze ich nun die unerträglich lauten und langsamen Teile 
durch Flash-Speicher Varianten.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Ich habe ja schon vor zwei Jahren die ersten &lt;a href=&quot;/blog/2019/03/ide-ssd-hd/&quot;&gt;IDE-SSDs&lt;/a&gt; 
bestellt, deren Speicher “klein” genug war, damit meine alten Mainboards 
damit leben konnten.&lt;br /&gt;
Das funktioniert auch super auf &lt;a href=&quot;https://de.wikipedia.org/wiki/MS-DOS&quot;&gt;DOS&lt;/a&gt; und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_3.x&quot;&gt;Windows 3.X&lt;/a&gt; Systemen, macht aber 
auf 32-Bit Systemen manchmal Schwierigkeiten.&lt;/p&gt;

&lt;p&gt;Beim Start von &lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_9x&quot;&gt;Windows 95 und 98&lt;/a&gt; 
traten nach deren Installation Bluescreens auf, dass das Medium “read-only” 
und unbenutzbar sei.&lt;br /&gt;
Beim Reboot war die IDE-SSD dann gar nicht mehr detektierbar, nur eine
Stromunterbrechung machte das Gerät wieder betriebsbereit, bis Windows
es wieder verschwinden ließ.&lt;/p&gt;

&lt;p&gt;Also habe ich nach Alternativen gesucht, wie ich meine alten Boards mit 
modernen Speichermedien betreiben kann.&lt;/p&gt;

&lt;h3 id=&quot;compactflash-cf-karten-ide-adapter&quot;&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/CompactFlash&quot;&gt;CompactFlash&lt;/a&gt; (CF) Karten IDE Adapter&lt;/h3&gt;

&lt;p&gt;Zu ihrer Blütezeit (1995 - 2005) bin ich mit ihnen nie in Kontakt geraten und
danach wurden sie schnell durch &lt;a href=&quot;https://de.wikipedia.org/wiki/SD-Karte&quot;&gt;SD-Karten&lt;/a&gt;
ersetzt. Es handelt sich dabei ebenfalls um Flash-Speicher-Karten nur mit 
größerem Gehäuse und mit einem IDE-Bus.&lt;/p&gt;

&lt;p&gt;Man braucht also nur einen Adapter der die schmalen Pins ihres Anschlusses 
auf die üblichen 40-Pin IDE Stecker übersetzt und schon funktioniert eine 
CF-Karte wie eine Festplatte.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/ide-cf-card.jpg&quot; alt=&quot;CF-Card to IDE&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Da sie keiner mehr braucht, kosten die kleineren Modelle in Fernost mit
8 - 16 GB heute um die 10 Euro und der Adapter um die 2 Euro.&lt;/p&gt;

&lt;p&gt;Sie sind lautlos und schneller als herkömmliche mechanische Festplatten
aus dieser Zeit.&lt;/p&gt;

&lt;p&gt;Ein Nachteil ist, dass manche Adapter oder Karten sich im System fix
als “Removable-Drive” melden, womit Windows Caches deaktiviert, was
ihre Performance senkt. Andere Karten tun, als wären sie richtige
Festplatten … da muss man leider ein paar Hersteller ausprobieren,
oder mit der etwas niederen Geschwindigkeit leben lernen.&lt;/p&gt;

&lt;p&gt;Für mich ist die Lösung aber super, wenn ich kaputte oder zu laute
Festplatten meiner 15 bis 25 Jahre alten Nostalgie-Rechner ersetzen möchte.&lt;/p&gt;

&lt;h3 id=&quot;msata-nach-ide-adapter&quot;&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Serial_ATA#mini-SATA_(mSATA)&quot;&gt;mSATA&lt;/a&gt; nach IDE Adapter&lt;/h3&gt;

&lt;p&gt;mini-SATA SSDs (die Vorläufer von M.2-SSDs) im 32 GB Bereich findet man auch
schon ab 14 Euro. Legt man noch etwa 5 Euro drauf, bekommt man ein
2.5 Zoll Gehäuse dazu, das M-SATA in den 44-Pin Notebook IDE Standard
übersetzt.&lt;/p&gt;

&lt;p&gt;Das wiederum ist eine gute Lösung für Notebooks aus den Anfängen der 
2000er Jahre, in denen solche IDE Platten verbaut waren. Natürlich kann 
man auch nur reine Adapter-Platinen bestellen (ohne das schöne Gehäuse).&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/ide-msata.jpg&quot; alt=&quot;M-SATA to IDE&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Für normale PCs kann man für weitere 2 Euro noch einen 40-Pin IDE 
Adapter samt klassischem Molex Stromstecker bestellen und schon hat
man quasi eine “echte” neue Festplatte für die alte Hardware.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/ide-44-to-40.jpg&quot; alt=&quot;44-Pin IDE to 40-Pin&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Es gibt übrigens auch &lt;a href=&quot;https://de.wikipedia.org/wiki/M.2&quot;&gt;M.2&lt;/a&gt; to IDE Adapter,
nur ist IDE gemessen an SATA sehr langsam und es bringt daher aus meiner 
Sicht nichts, die besseren M.2 Chips in meine uralten PCs einzubauen. 
Streng genommen sind auch die M-SATA Varianten für meinen Anwendungszweck 
überdimensioniert.&lt;/p&gt;

&lt;h3 id=&quot;sd-karte-nach-ide-adapter&quot;&gt;SD-Karte nach IDE Adapter&lt;/h3&gt;

&lt;p&gt;So wie es für SATA-Ports Adapter zu SD-Karten gibt, existieren auch 
Konverter für IDE zu SD-Karten.&lt;/p&gt;

&lt;p&gt;Billige Adapter-Boards findet man heute in China schon um 7 Euro und 
nachdem Micro-SD-Karten im 16 GB Bereich auch schon um 2-3 Euro zu haben
sind, ist diese Variante am billigsten.&lt;/p&gt;

&lt;p&gt;Außerdem kann man alte SD-Karten aus Smartphones auf diese Weise als
Festplatten-Ersatz in antiken PCs recyclen.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/ide-sd-card.jpg&quot; alt=&quot;IDE to SD-Card&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Ich habe noch keine Langzeiterfahrung mit diesen Dingern, aber ich vermute
mal, dass dieses Medium denkbar ungünstig ist, um davon ein Betriebssystem
zu starten.&lt;br /&gt;
Denn die häufigen Zugriffe auf temporäre und Auslagerungsdateien wird die
Lebensdauer der Karten schnell ablaufen lassen.&lt;/p&gt;

&lt;p&gt;However … wenn man nur mal schnell seine alte Nostalgie-DOS-Umgebung 
aufleben lassen will, ist die SD-Karten-IDE-Festplatte vermutlich die
kostengünstigste Variante … und Ersatz-SD-Karten findet man heute wirklich
überall.&lt;/p&gt;

&lt;h3 id=&quot;3d-druck-vorlagen&quot;&gt;3D Druck Vorlagen&lt;/h3&gt;

&lt;p&gt;Damit CF- und SD-Adapter Platinen nicht einfach so im PC-Gehäuse herumpurzeln,
macht es Sinn, sie wo zu montieren.&lt;/p&gt;

&lt;p&gt;Wie so oft helfen ein 3D-Drucker und unsere geschätzten Bastler auf 
&lt;a href=&quot;https://www.thingiverse.com/&quot;&gt;Thingiverse&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Für CF-Karten Adapter findet man gleich ein paar Lösungen:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Einmal ein einfaches &lt;a href=&quot;https://www.thingiverse.com/thing:2355332&quot;&gt;3.5 Zoll Einschubgehäuse&lt;/a&gt;
mit dem man vorne am PC die Karte leicht wechseln kann.&lt;/li&gt;
  &lt;li&gt;Das gleiche gibt es auch für ein 
&lt;a href=&quot;https://www.thingiverse.com/thing:965843&quot;&gt;5.25 Zoll Einschubgehäuse&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Oder man nimmt gleich zwei CF-Adapter und verbaut sie gemeinsam in einem
&lt;a href=&quot;https://www.thingiverse.com/thing:2454774&quot;&gt;5.25 Zoll Einschubgehäuse&lt;/a&gt;
in seinem PC.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Für den SD-Karten Adapter hat sich jemand eine kreative Lösung einfallen 
lassen, wo hinten am PC eine 
&lt;a href=&quot;https://www.thingiverse.com/thing:3543297&quot;&gt;PCI- (oder ISA-) Slotblende&lt;/a&gt;
mit der Platine verbunden werden kann.&lt;/p&gt;

&lt;p&gt;Alternativ hat der SD-Adapter aber genau die Breite einer 2.5 Zoll 
Festplatte und kann somit auch auf eine 2.5 zu 3.5 Zoll Halterung
draufgeschraubt werden.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;So, wieder ist ein Nostalgie-Sonntag vorbei und ich genieße die Stille
von Flashmedien wirklich sehr.&lt;br /&gt;
Ich kann mir heute gar nicht mehr vorstellen, dass ich vor 20 Jahren
stundenlang neben den damaligen surrenden und knatternden Festplatten
saß und es mir nichts ausmachte.&lt;/p&gt;

&lt;p&gt;Heute will Opa aber seine Ruhe haben und trotzdem das DOS-Prompt aus 
“den guten alten Tagen” sehen. Und genau dafür sind diese IDE Adapter
ein wahrer Segen.&lt;/p&gt;

&lt;p&gt;Einen Aspekt gibt es übrigens noch: Man kann die Adapter auch benutzen,
um sie am zweiten IDE Port zu einem laufenden System (natürlich vor dem Boot)
dazu zu hängen.&lt;br /&gt;
So kann man auf ganz alte Systeme Daten kopieren, wo man sonst nur mit 
gebrannten CDs Daten einschleusen könnte.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>DOS Development</title>
   <link href="https://www.opengate.at/blog/2021/10/dos-devel/"/>
   <published>2021-10-09T13:00:00+02:00</published>
   <updated>2021-10-09T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2021/10/dos-devel</id>
   <category term="devel" /><category term="retro" />
   <summary type="text">OpenWatcom eröffnet mir also heute im 
Jahr 2021 ein Tor 30 Jahre zurück in die Vergangenheit, denn der Compiler 
unterstützt auch heute noch MS-DOS 
und Windows 3.x als Zielplattform.

Auf was muss man also achten, wenn man Programme für DOS schreiben will?
</summary>
   <content type="html">&lt;p&gt;&lt;a href=&quot;/blog/2021/10/watcom/&quot;&gt;OpenWatcom&lt;/a&gt; eröffnet mir also heute im 
Jahr 2021 ein Tor 30 Jahre zurück in die Vergangenheit, denn der Compiler 
unterstützt auch heute noch &lt;a href=&quot;https://de.wikipedia.org/wiki/MS-DOS&quot;&gt;MS-DOS&lt;/a&gt; 
und &lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_3.x&quot;&gt;Windows 3.x&lt;/a&gt; als Zielplattform.&lt;/p&gt;

&lt;p&gt;Auf was muss man also achten, wenn man Programme für DOS schreiben will?
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;ach--damals&quot;&gt;Ach … damals&lt;/h3&gt;

&lt;p&gt;Technisch betrachtet, war &lt;a href=&quot;https://de.wikipedia.org/wiki/Turbo_Pascal&quot;&gt;Turbo Pascal&lt;/a&gt; 
6.0 der erste “richtige” Compiler, den ich je besessen hatte, den mir ein 
Hobby-Informatiker aus der Nachbarschaft kopiert hatte.&lt;br /&gt;
Doch da mir diese Sprache so “fern” war, tauschte ich es quasi auf dem 
Schulhof gegen &lt;a href=&quot;https://de.wikipedia.org/wiki/QuickBASIC&quot;&gt;QuickBASIC&lt;/a&gt; 4.5.
Denn das abgespeckte QBasic von DOS kannte ich schon und dessen eingebaute 
“Befehlshilfe” lehrte mich damals meine ersten Programmiervokabel. 
QuickBASIC ließ mich dann die ersten EXE Dateien erzeugen.&lt;br /&gt;
Kurz danach folgte wegen der Schule wieder Pascal und dann kaufte ich mir 
Turbo-Assembler 4.0 um “DOS zu hacken”. (Meine parallelen &lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_Basic_Classic&quot;&gt;VB-4&lt;/a&gt;
Erlebnisse sind Teil einer anderen Geschichte.)&lt;/p&gt;

&lt;p&gt;Ich war damals schon von “antiker” Software mehr beeindruckt, als von moderner,
da die alten Programme auf meiner veralteten gebrauchten Hardware immer 
“hoch-performant” lief und Windows immer nur träge wirkte. 
Und &lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt; hat mich wegen seines 
Schneckentempos damals so abgeschreckt, dass ich es auch Jahre später immer 
noch nicht anfassen wollte.&lt;/p&gt;

&lt;p&gt;Es ist beeindruckend, was man damals in 64 KB großen Programmen alles
unterbringen konnte, wo heute zig Megabytes nicht ausreichen.&lt;/p&gt;

&lt;h3 id=&quot;realmode-dos-und-speichermodelle&quot;&gt;Realmode DOS und Speichermodelle&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B&quot;&gt;C und C++&lt;/a&gt; habe ich unter DOS damals 
nie kennen gelernt. Zwar stolperte ich auch über &lt;a href=&quot;https://en.wikipedia.org/wiki/Turbo_C%2B%2B&quot;&gt;Turbo C++&lt;/a&gt;, 
konnte damit aber nichts anfangen. Außerdem hielt ich damals ja alle Sprachen,
die Groß-Kleinschreibung unterschieden für pervers.&lt;/p&gt;

&lt;p&gt;Um 2009 fand ich parallel zu Watcom auch den &lt;a href=&quot;https://de.wikipedia.org/wiki/DJGPP&quot;&gt;DJGPP&lt;/a&gt;, 
eine &lt;a href=&quot;https://de.wikipedia.org/wiki/GNU_Compiler_Collection&quot;&gt;GCC&lt;/a&gt; Portierung 
für DOS, den ich aber (auch mangels einer für mich “einfachen” IDE dafür) 
nie betreiben konnte.&lt;/p&gt;

&lt;p&gt;Das Problem: &lt;em&gt;Für C++ ist DOS nicht gleich DOS.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Die ältesten Compiler (wie auch Turbo C/C++) sehen DOS als reine 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Real_Mode&quot;&gt;X86-Realmode&lt;/a&gt; Umgebung. 
Dort herrschen verschiedene Speichermodelle vor:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Name&lt;/th&gt;
      &lt;th&gt;Description&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Tiny&lt;/td&gt;
      &lt;td&gt;COM: nur 64 KB für Code, Daten und Stack&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Small&lt;/td&gt;
      &lt;td&gt;EXE: 1 x 64 KB Code, 1 x 64 KB Daten&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Medium&lt;/td&gt;
      &lt;td&gt;EXE: n x 64 KB Code, 1 x 64 KB Daten&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Compact&lt;/td&gt;
      &lt;td&gt;EXE: 1 x 64 KB Code, n x 64 KB Daten&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Large&lt;/td&gt;
      &lt;td&gt;EXE: n x 64 KB Code, n x 64 KB Daten&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Huge&lt;/td&gt;
      &lt;td&gt;EXE: n x 64 KB Code, bis zu 1 MB Daten&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Ein Segment kann im Real-Mode nur 64 KB groß sein und da es nur ein Code 
und ein Daten-Segment Register gibt (Das &lt;code&gt;ES&lt;/code&gt; Register zählt hier noch nicht),
muss man sich entscheiden, ob das Programm mehrere Segmente ansteuern können
soll oder nicht.&lt;/p&gt;

&lt;p&gt;Braucht man mehr als 64 KB Code, muss das &lt;code&gt;CS&lt;/code&gt; Register bei Sprüngen wechseln,
und Code-Pointer sind dann 32 bit breit und nutzt &lt;code&gt;FAR&lt;/code&gt; Calls, aber wenn 64 KB
reichen, hat man nur ein Code-Segment, die Code-Pointer sind 16 bit breit und
werden durch &lt;code&gt;NEAR&lt;/code&gt; Calls angesprungen.&lt;/p&gt;

&lt;p&gt;Bei den Daten verhält es sich ähnlich und weil größere Pointer mehr Rechenzeit
und Platz verbrauchen, musste der Entwickler schon beim Programmieren in etwa
wissen, gegen welches Speichermodell er kompilieren will.&lt;/p&gt;

&lt;p&gt;Dass C++ &lt;code&gt;std&lt;/code&gt; Allokatoren unter anderem auch ein Überbleibsel aus diesem 
Dilemma sind, ist heute schon in Vergessenheit geraten. Es macht eben einen 
Performance- und Reichweiten- Unterschied aus, ob ein &lt;code&gt;std::vector&lt;/code&gt; intern 
einen &lt;code&gt;NEAR&lt;/code&gt; oder &lt;code&gt;FAR&lt;/code&gt; Pointer &lt;code&gt;typedef&lt;/code&gt; nutzt. Und zusätzliche Allokatoren 
konnten diese Grenze überwinden.&lt;/p&gt;

&lt;h3 id=&quot;dos-protected-mode&quot;&gt;DOS Protected Mode&lt;/h3&gt;

&lt;p&gt;Die meisten C und C++ Compiler wechselten in den 90er Jahren zum 
&lt;a href=&quot;https://de.wikipedia.org/wiki/DOS_Protected_Mode_Interface&quot;&gt;DOS Protected Mode Interface&lt;/a&gt; 
und waren damit in der Lage ein 32-Bit Flat-Memory-Model zu nutzen. 
Und so konnten DOS-Programme (wie heutige Software) den ganzen verfügbaren 
RAM nutzen, sie nutzten 32-bit Pointer in genau einem Code und 
einem Datensegment und alles war gut.&lt;/p&gt;

&lt;p&gt;Das wahre Problem der Technik wurde vom Compiler gut versteckt: nämlich das
andauernde Hin- und Herwechseln zwischen Real-Mode und Protected-Mode.&lt;br /&gt;
Denn DOS Funktionen waren nicht 32-Bit tauglich und sobald z.B. eine Datei 
geöffnet wurde, musste:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;ein 32-Bit Aufruf den Prozessor in den 16-Bit Mode schalten,&lt;/li&gt;
  &lt;li&gt;ein &lt;a href=&quot;https://en.wikipedia.org/wiki/DOS_API&quot;&gt;DOS Interrupt&lt;/a&gt; aufgerufen 
werden und dessen Ergebnis zwischengespeichert werden,&lt;/li&gt;
  &lt;li&gt;in den Protected Mode zurück gewechselt werden,&lt;/li&gt;
  &lt;li&gt;und das Ergebnis in die 32-Bit Welt import werden.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Der ganze Zirkus war auch für Hardware-Interrupts notwendig, 
womit sicher einiges an Performance verloren ging.&lt;/p&gt;

&lt;p&gt;Doch DOS Spiele hatten keine andere Wahl, weil sie mit den segmentierten 
64 KB Blöcken einfach nicht auskamen. Deshalb findet man bei ihnen immer eine 
&lt;code&gt;dos4gw.exe&lt;/code&gt; Datei oder einen anderen 32-Bit Extender, 
der diese Funktion implementiert hat.&lt;/p&gt;

&lt;h3 id=&quot;cmake-für-watcom-dos-builds&quot;&gt;CMake für Watcom DOS Builds&lt;/h3&gt;

&lt;p&gt;Unglaublich, aber wahr: &lt;a href=&quot;https://de.wikipedia.org/wiki/CMake&quot;&gt;CMake&lt;/a&gt; 
unterstützt OpenWatcom. Im Standard werden zwar nur für NT Binaries erstellt, 
aber mit ein paar Klicks mehr, lässt sich der 64-Bit Compiler überzeugen am 
anderen Ende 16-Bit Code zu generieren.&lt;/p&gt;

&lt;p&gt;Am besten installiert man OpenWatcom 2 genau so wie vom Setup vorgeschlagen.
Damit landen alle Dateien in &lt;code&gt;C:\WATCOM&lt;/code&gt; und CMake findet alles selbstständig.&lt;/p&gt;

&lt;p&gt;Wenn man in der CMake GUI den Generator &lt;code&gt;Watcom WMAKE&lt;/code&gt; auswählt, muss man für
DOS-Builds die Option &lt;code&gt;Specify options for cross-compiling&lt;/code&gt; aktivieren.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/cmake-watcom-dos-01.png&quot; alt=&quot;CMAKE-Watcom-DOS-1&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Im folgenden Dialog genügt es beim Feld &lt;code&gt;Operating System&lt;/code&gt; einfach &lt;code&gt;DOS&lt;/code&gt; 
einzutragen, was der CMAKE-Variablen &lt;code&gt;CMAKE_SYSTEM_NAME&lt;/code&gt; entspricht.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/cmake-watcom-dos-02.png&quot; alt=&quot;CMAKE-Watcom-DOS-2&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Danach richtet CMAKE automatisch den Compiler ein.&lt;br /&gt;
Die wichtigsten CMAKE Variablen sind hier aufgelistet.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;CMAKE Variable&lt;/th&gt;
      &lt;th&gt;Value&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;CMAKE_AR:FILEPATH&lt;/td&gt;
      &lt;td&gt;C:/WATCOM/binnt64/wlib.exe&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;CMAKE_CXX_COMPILER&lt;/td&gt;
      &lt;td&gt;C:/WATCOM/binnt64/wcl386.exe&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;CMAKE_CXX_FLAGS&lt;/td&gt;
      &lt;td&gt;-w3 -bt=dos -xs&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;CMAKE_CXX_FLAGS_DEBUG&lt;/td&gt;
      &lt;td&gt;-d2&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;CMAKE_CXX_FLAGS_MINSIZEREL&lt;/td&gt;
      &lt;td&gt;-s -os -d0 -dNDEBUG&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;CMAKE_CXX_FLAGS_RELEASE&lt;/td&gt;
      &lt;td&gt;-s -ot -d0 -dNDEBUG&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;CMAKE_CXX_FLAGS_RELWITHDEBINFO&lt;/td&gt;
      &lt;td&gt;-s -ot -d1 -dNDEBUG&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;CMAKE_C_COMPILER&lt;/td&gt;
      &lt;td&gt;C:/WATCOM/binnt64/wcl386.exe&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;CMAKE_C_FLAGS&lt;/td&gt;
      &lt;td&gt;-w3 -bt=dos&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;CMAKE_C_FLAGS_DEBUG&lt;/td&gt;
      &lt;td&gt;-d2&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;CMAKE_C_FLAGS_MINSIZEREL&lt;/td&gt;
      &lt;td&gt;-s -os -d0 -dNDEBUG&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;CMAKE_C_FLAGS_RELEASE&lt;/td&gt;
      &lt;td&gt;-s -ot -d0 -dNDEBUG&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;CMAKE_C_FLAGS_RELWITHDEBINFO&lt;/td&gt;
      &lt;td&gt;-s -ot -d1 -dNDEBUG&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;CMAKE_EXE_LINKER_FLAGS&lt;/td&gt;
      &lt;td&gt;opt map system dos4g&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;CMAKE_EXE_LINKER_FLAGS_DEBUG&lt;/td&gt;
      &lt;td&gt;debug all&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO&lt;/td&gt;
      &lt;td&gt;debug all&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;CMAKE_LINKER&lt;/td&gt;
      &lt;td&gt;C:/WATCOM/binnt64/wlink.exe&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;CMAKE_MAKE_PROGRAM&lt;/td&gt;
      &lt;td&gt;wmake&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;CMAKE_MODULE_LINKER_FLAGS&lt;/td&gt;
      &lt;td&gt;opt map system dos4g&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;CMAKE_MODULE_LINKER_FLAGS_DEBUG&lt;/td&gt;
      &lt;td&gt;debug all&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO&lt;/td&gt;
      &lt;td&gt;debug all&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;CMAKE_SHARED_LINKER_FLAGS&lt;/td&gt;
      &lt;td&gt;opt map system dos4g&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;CMAKE_SHARED_LINKER_FLAGS_DEBUG&lt;/td&gt;
      &lt;td&gt;debug all&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO&lt;/td&gt;
      &lt;td&gt;debug all&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;CMAKE_SYSTEM_NAME&lt;/td&gt;
      &lt;td&gt;DOS&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Jetz braucht man nur noch in das Build-Verzeichnis zu wechseln und dort 
&lt;code&gt;wmake&lt;/code&gt; eintippen.&lt;br /&gt;
Da &lt;code&gt;wmake&lt;/code&gt; auch nur “die Watcom-Variante” von &lt;code&gt;make&lt;/code&gt; ist, funktionieren
auch die üblichen Verdächtigen wie:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;wmake clean&lt;/code&gt;: Löscht bisherige Build-Reste&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;wmake my_project&lt;/code&gt;: Baut nur das Projekt namens &lt;code&gt;my_project&lt;/code&gt; and dessen 
Abhängigkeiten.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Am Ende liegen im Output-Directory die entsprechenden DOS-EXE Dateien.&lt;/p&gt;

&lt;p&gt;Diese kann man dann unter Win64 mit Emulatoren wie &lt;a href=&quot;https://de.wikipedia.org/wiki/DOSBox&quot;&gt;DOSBOX&lt;/a&gt; 
ausführen, wenn man noch zusätzlich die Datei &lt;code&gt;dos4gw.exe&lt;/code&gt; ins 
Programmverzeichnis kopiert.&lt;/p&gt;

&lt;p&gt;Würde man in &lt;code&gt;CMAKE_MODULE_LINKER_FLAGS&lt;/code&gt; den Eintrag &lt;code&gt;dos4g&lt;/code&gt; durch &lt;code&gt;dos&lt;/code&gt;
ersetzen, wären reine 16-Bit DOS Programme möglich, doch das habe ich 
bisher noch nicht durch den Linker gebracht, da fehlen einige Symbole.&lt;/p&gt;

&lt;p&gt;However, für einen ersten Test reicht mir eine DOS-4GW Anwendungen vollkommen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Nostalgie pur! Ich fühle mich wieder wie ein glücklicher kleiner Junge in 
den 90ern. Ja damals, als man noch mit 3 Zeilen Basic-Code den unwissenden
Gymnasium-Professor in Verlegenheit bringen konnte. 😎&lt;/p&gt;

&lt;p&gt;Und trotzdem ärgere ich mich, dass ich erst heute, über 20 Jahre
zu spät, diese interessante Erfahrung machen durfte.&lt;br /&gt;
Es fehlte mir damals einfach an Software und Infos.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>3 Jahre Blog</title>
   <link href="https://www.opengate.at/blog/2021/10/blog-year-3/"/>
   <published>2021-10-06T13:00:00+02:00</published>
   <updated>2021-10-06T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2021/10/blog-year-3</id>
   <category term="general" /><category term="projects" />
   <summary type="text">3 Jahre hat diese Seite jetzt auf dem Buckel. 
Und ich glaube, damit ist es zum zeitlich längsten Webprojekt geworden, 
an dem ich je durchgehend aktiv gearbeitet habe.

Und langsam komme ich wieder an die Grenze des Erträglichen im
aktiven Testbetrieb mit jekyll serve.
</summary>
   <content type="html">&lt;p&gt;3 Jahre hat diese Seite jetzt auf dem Buckel. 
Und ich glaube, damit ist es zum zeitlich längsten Webprojekt geworden, 
an dem ich je durchgehend aktiv gearbeitet habe.&lt;/p&gt;

&lt;p&gt;Und langsam komme ich wieder an die Grenze des Erträglichen im
aktiven Testbetrieb mit &lt;code&gt;jekyll serve&lt;/code&gt;.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;450 &lt;a href=&quot;https://de.wikipedia.org/wiki/Markdown&quot;&gt;Markdown&lt;/a&gt; Posts und 12 “Dokus” 
müssen bei jeder Live-Änderung von &lt;a href=&quot;https://en.wikipedia.org/wiki/Jekyll_(software)&quot;&gt;Jekyll&lt;/a&gt;
in &lt;a href=&quot;https://de.wikipedia.org/wiki/Hypertext_Markup_Language&quot;&gt;HTML&lt;/a&gt; übersetzt 
werden, und das dauert auf meinem Rechner in 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Windows-Subsystem_f%C3%BCr_Linux&quot;&gt;WSL&lt;/a&gt; 
etwa 23 Sekunden.&lt;br /&gt;
Langsam muss ich mich daran gewöhnen die Option &lt;code&gt;--incremental&lt;/code&gt; beim Start
von &lt;code&gt;jekyll serve&lt;/code&gt; zu aktivieren, damit man wieder auf 3 Sekunden zurückfällt, 
doch dann werden Menüs und Index-Seiten nicht aktualisiert, 
sondern nur die gerade geänderte Seite.&lt;/p&gt;

&lt;p&gt;Parallel zum normalen Blog habe ich schon länger mit einem vereinfachten 
Design experimentiert, das als “Retro-BLOG” auch für ältere Browser wie den 
&lt;a href=&quot;https://en.wikipedia.org/wiki/Internet_Explorer_6&quot;&gt;Internet Explorer 6&lt;/a&gt; und 
älter geeignet ist.&lt;br /&gt;
Siehe &lt;a href=&quot;//opengate.at/retro-blog&quot;&gt;opengate.at/retro-blog&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Mit einem neuen &lt;code&gt;recommended&lt;/code&gt; Flag sind nun einige Artikel markiert, die mehr
mit einem Tutorial gemein haben, als mit üblichen wöchentlichen 
Erlebnisberichten, was mir so alles untergekommen ist.&lt;br /&gt;
Diese können im Menüpunkt &lt;a href=&quot;/blog/special/&quot;&gt;Spezielle Beiträge&lt;/a&gt; aufgelistet werden und
erleichtern (zumindest mir) die Suche nach relevanteren Themen.&lt;/p&gt;

&lt;p&gt;Mit der Freischaltung des &lt;a href=&quot;https://codeberg.org/GateNetwork/gate-blog-classroom/&quot;&gt;BLOG Classroom&lt;/a&gt;
als &lt;a href=&quot;https://de.wikipedia.org/wiki/Git&quot;&gt;GIT&lt;/a&gt; Repository habe ich jetzt auch
die Möglichkeit, Beispiel-Codes und Fragmente unabhängig vom GATE Projekt 
hochzuladen und im Blog zu referenzieren.
Viel ist da noch nicht drinnen … aber der Blog hat ja auch mal mit 
nur einem Beitrag angefangen.
URL: &lt;a href=&quot;https://codeberg.org/GateNetwork/gate-blog-classroom/&quot;&gt;codeberg.org/GateNetwork/gate-blog-classroom&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Blog Seiten können jetzt externe Links im Markdown-Kopf angeben, womit
diese Links gleich unterhalb der Titelzeile als Link angezeigt werden.
So kommt man schneller zu extern verlinkten Ressourcen, anstatt die 
Links immer erst aus dem Blog-Posting heraus suchen zu müssen.&lt;/p&gt;

&lt;p&gt;Parallel zum GATE Projekt sind nun auch ein paar Features zu den
Web-Services auf &lt;code&gt;opengate.at&lt;/code&gt; hinzugekommen.
Das wichtigste davon wird das Download-Service sein, das bei der 
Veröffentlichung der ersten GATE-Binaries eine große Rollen spielen soll.
Schließlich sollen Downloads nicht direkt stattfinden, sondern durch eine
Umleitung laufen, die Statistiken und Zugriffs-Limitierungen ermöglichen soll.&lt;/p&gt;

&lt;p&gt;Nachdem nun mehr und mehr Hürden aus dem Weg geräumt werden, hoffe ich ja doch,
dass ich Tools wie &lt;code&gt;gatecli&lt;/code&gt; und &lt;code&gt;vtxtedit&lt;/code&gt; auch mal wirklich fertigstellen
kann, ohne mich dafür schämen zu müssen.
Ein offenes Problem stellt aber immer noch &lt;a href=&quot;https://de.wikipedia.org/wiki/GTK_(Programmbibliothek)&quot;&gt;GTK&lt;/a&gt;
mit seinem Container-Resize Schema da, das sich leider immer noch nicht 
so verhält, wie es sein sollte.&lt;/p&gt;

&lt;p&gt;Und eine kleine Anekdote am Rande: Seit zwei Jahren schreibe ich Quartals-News
für die &lt;a href=&quot;//www.opengate.at/main/&quot;&gt;OpenGate-Hauptseite&lt;/a&gt;, die bis heute nicht 
veröffentlicht sind, weil sie keinen Sinn machen, so lange es dort keine 
Downloads gibt.&lt;br /&gt;
Hmm, das nennt man wohl schlechtes Release-Management.&lt;br /&gt;
&lt;em&gt;(Oder: Ich brauche einfach mehr Freizeit …)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In diesem Sinne:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Mach’ ma einfach mal weiter!&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>Server 2022 Update mit Fehlschlag</title>
   <link href="https://www.opengate.at/blog/2021/10/server-2022/"/>
   <published>2021-10-03T13:00:00+02:00</published>
   <updated>2021-10-03T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2021/10/server-2022</id>
   <category term="software" />
   <summary type="text">Seit August steht der Windows Server 2022
zur Installation bereit.
Basierend auf dem Kernel 21/H2 sollte er eigentlich Server 2021 heißen,
aber das war ja bei Server 2019 
mit 18/09 damals auch nicht anders.

Und ich möchte nun meinen Domain Controller 
von Server 2016
auf den “letzten Stand” bringen. Na mal sehen, ob Microsoft das hinbekommt.
</summary>
   <content type="html">&lt;p&gt;Seit August steht der &lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_Server_2022&quot;&gt;Windows Server 2022&lt;/a&gt;
zur Installation bereit.
Basierend auf dem Kernel 21/H2 sollte er eigentlich Server 2021 heißen,
aber das war ja bei &lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_Server_2019&quot;&gt;Server 2019&lt;/a&gt; 
mit 18/09 damals auch nicht anders.&lt;/p&gt;

&lt;p&gt;Und ich möchte nun meinen &lt;a href=&quot;https://de.wikipedia.org/wiki/Domain_Controller&quot;&gt;Domain Controller&lt;/a&gt; 
von &lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_Server_2016&quot;&gt;Server 2016&lt;/a&gt;
auf den “letzten Stand” bringen. Na mal sehen, ob Microsoft das hinbekommt.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;server-2016-zustand&quot;&gt;Server 2016 Zustand&lt;/h3&gt;

&lt;p&gt;Ich bin mit meinem inzwischen 3 Jahre durchlaufenden Server 2016 grundsätzlich
zufrieden. Die Performance ist eben so, wie man es von einem 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Intel_Atom&quot;&gt;Intel Atom&lt;/a&gt;
erwarten kann: Bescheiden. Er würde zwar im “Extended Support” noch weitere
5 Jahre “OK” sein, aber es gibt ein paar Dinge, die mir trotzdem nicht so ganz
gefallen.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Updates dauern ewig.&lt;br /&gt;
Das melden auch andere Seiten, dass Windows Updates in Server 2016 viel
länger brauchen (beim Suchen angefangen), als z.B. im Server 2019. Hier
erhoffe ich mir Verbesserungen&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/blog/2018/11/intel-hd-graphics-crash/&quot;&gt;Defekter Grafiktreiber&lt;/a&gt;.&lt;br /&gt;
Tja, seit 3 Jahren habe ich den Intel-Treiber explizit deaktivieren müssen,
damit ihn Windows-Update nicht erneuert und muss mit der Krücke von 
VGA-Kompatibilitätsteil leben. Zum Glück braucht ein Server keine Grafik, 
denn der “empfohlene” Treiber generiert sofort Bluescreens.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Docker_(Software)&quot;&gt;Docker&lt;/a&gt; Support.&lt;br /&gt;
Unter 2016 war das noch ein mühsames Unterfangen und die Images waren riesig.
Mit 2022 soll alles nochmals viel kleiner und performanter werden …
Na ich bin gespannt.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;upgrade-fehlschlag&quot;&gt;Upgrade Fehlschlag&lt;/h3&gt;

&lt;p&gt;Ein Domain Controller Update bereitet mir stets Sorgen. Zwar ist mir bisher 
noch keines misslungen, aber wenn was Schlimmes passiert, darf ich die Domäne 
entweder mühsam wiederherstellen oder neu aufsetzen … mit allen PCs dazu.&lt;/p&gt;

&lt;p&gt;Die Setup-&lt;a href=&quot;https://de.wikipedia.org/wiki/ISO-Abbild&quot;&gt;ISO&lt;/a&gt;-Datei als DVD 
Laufwerk eingebunden, startet man wie üblich &lt;code&gt;setup.exe&lt;/code&gt; und die 
Zustandsanalyse beginnt.&lt;br /&gt;
Bei mir kamen dann gleich drei Problempunkte:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Empfehlung: Server 2008 Schema ist veraltet.&lt;br /&gt;
Lösung: Ich habe die Domäne und den Forest auf den Server 2008 R2 
AD Standard gehoben.&lt;/li&gt;
  &lt;li&gt;Info: Active Directory Federation Services müssen nach dem Upgrade neu
installiert werden.&lt;br /&gt;
Gut, wer weiß, ob ich die überhaupt noch brauche…&lt;/li&gt;
  &lt;li&gt;Notwendig: &lt;code&gt;adprep&lt;/code&gt; muss das AD-Schema vorher aktualisieren.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
  &lt;p&gt;Active Directory on this domain controller does not contain 
Windows Server 2022 &lt;code&gt;ADPREP /FORESTPREP&lt;/code&gt; updates.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Dazu geht man ins DVD-Verzeichnis &lt;code&gt;d:\support\adprep&lt;/code&gt; und führt dort 
&lt;code&gt;adprep /forestprep&lt;/code&gt; mit Admin-Rechten aus.&lt;br /&gt;
Dort muss man das Update als “unumkehrbar” abnicken und eine Minute
warten, bis das Active Directory die Änderungen eingespielt hat.&lt;/p&gt;

&lt;p&gt;Wenn man nun den Windows-Setup Dialog mit der Info Meldung “Refresh”-t,
kommt &lt;em&gt;fast&lt;/em&gt; die gleiche Meldung nochmal:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Active Directory on this domain controller does not contain 
Windows Server 2022 &lt;code&gt;ADPREP /DOMAINPREP&lt;/code&gt; updates.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Jetzt wird also mit &lt;code&gt;adprep /domainprep&lt;/code&gt; die eigene Domäne auf Stand
gebracht.&lt;/p&gt;

&lt;p&gt;Tja und dann läuft Windows Setup …
außer natürlich, man hat ein Mainboard, dessen Grafikkarten-Treiber
das System einfrieren lässt …&lt;/p&gt;

&lt;p&gt;Dann versucht das System nämlich sich zurückzusetzen, scheitert dabei
und die ganze Installation ist beim Teufel.&lt;br /&gt;
Jetzt weiß ich also, wie man ein Upgrade versemmeln kann.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;FAIL !&lt;/strong&gt;&lt;/p&gt;

&lt;h3 id=&quot;neuinstallation-und-manuelles-ad-reset&quot;&gt;Neuinstallation und manuelles AD-Reset&lt;/h3&gt;

&lt;p&gt;Mit dem ISO per &lt;a href=&quot;https://de.wikipedia.org/wiki/Rufus_(Software)&quot;&gt;Rufus&lt;/a&gt; auf 
dem USB Stick startete ich also ein neues Server Setup mit neuer SSD für 
eine gänzlich jungfräuliche Installation.
Das funktionierte auch alles problemlos, bis es dann (so wie auch beim 
Server 2016) zum Windows Update des Grafik-Treibers kam und wie damals
löste ich das Problem per manueller Deaktivierung des Treibers im
“abgesicherten Startmodus”.&lt;/p&gt;

&lt;p&gt;Ärgerlich! Das Problem wurde also nicht behoben.&lt;/p&gt;

&lt;p&gt;Jetzt kam der ungute Teil. Mein zweiter Domain-Controller hielt keine
der &lt;a href=&quot;https://de.wikipedia.org/wiki/FSMO&quot;&gt;FSMO-Rollen&lt;/a&gt; und mein primäres 
System war ja tot.&lt;/p&gt;

&lt;p&gt;Was für ein Glück, dass ich vor vielen Jahren 
&lt;a href=&quot;http://docs.microsoft.com/en-us/windows/win32/adsi/active-directory-service-interfaces-adsi&quot;&gt;ADSI&lt;/a&gt; 
studiert hatte und die Attribute am verbliebenen DC selbst per 
ADSI-Edit Tool anpassen konnte:&lt;/p&gt;

&lt;p&gt;Angenommen, die eigene Domäne heißt &lt;code&gt;mydomain.net&lt;/code&gt;, dann findet man die 4
Objekte mit den FSMO-Attributen unter folgenden Namen:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Domain Master: &lt;code&gt;DC=mydomain,DC=net&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;RID Master: &lt;code&gt;CN=RID Manager$,CN=System,DC=mydomain,DC=net&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Infrastructure Master: &lt;code&gt;CN=Infrastructure,DC=mydomain,DC=net&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;PDC Emulator Master: &lt;code&gt;CN=Partitions,CN=Configuration,DC=carbis,DC=mydomain,DC=net&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Schema Master: &lt;code&gt;CN=Schema,CN=Configuration,DC=mydomain,DC=net&lt;/code&gt;&lt;br /&gt;
(dazu muss man sich zur separaten Schema-Partition verbinden)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Diese Objekte enthalten stets ein Attribut mit Namen &lt;code&gt;fSMORoleOwner&lt;/code&gt; und 
dieses hält dann Namen des früheren Domain Controllers, z.B.:
&lt;code&gt;CN=NTDS Settings,CN=Old-DC,CN=Servers,CN=Default-First-Site-Name,CN=Sites,CN=Configuration,DC=mydomain,DC=net&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Hier tauscht man den &lt;code&gt;Old-DC&lt;/code&gt; Eintrag durch den Namen des neuen gewünschten
Servers und startet neu. Jetzt ist der alte “sekundäre” Server zum primären 
aufgestiegen.&lt;br /&gt;
Diese Schritte kann man zwar nicht in der GUI, jedoch aber mit ein paar 
Kommandozeilen-Tools hinbekommen, die ich mir aber nie gemerkt habe, weil 
ich ja schon den “nativen Weg” kannte.&lt;br /&gt;
Am Ende kann man nun den alten Server in allen AD-GUIs entfernen.&lt;/p&gt;

&lt;p&gt;So konnte ich dann meinen neu aufgesetzten neuen DC in die Domäne aufnehmen,
ihn wieder zum DC “promoten” und am Ende die Rollen wieder zurückübertragen
(diesmal per GUI wie es sich gehört).&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ich bin total angepisst wegen dem Grafikkarten-Crash … und gleichzeitig
mit mir selbst zufrieden, dass der manuelle AD-Restore so problemlos ablief.&lt;/p&gt;

&lt;p&gt;Nun wissen wir also, dass Windows Setup ein großes Problem hat, wenn die
letzten Einrichtungsschritte fehlschlagen, denn zu diesem Zeitpunkt 
funktioniert das Zurückrollen offenbar nicht.&lt;br /&gt;
Ich vermute mal, es liegt daran, dass auch die 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Unified_Extensible_Firmware_Interface&quot;&gt;UEFI&lt;/a&gt;
Partition aktualisiert wurde und nicht mehr zurückgesetzt werden konnte, 
und so landet man in einem nicht-boot-baren Zustand.&lt;/p&gt;

&lt;p&gt;Aber, in Sachen Performance hat sich das Update voll und ganz ausgezahlt.
Das System regiert nun wesentlich schneller und auch Updates sind im
Gegensatz zu früher zügig eingespielt.&lt;/p&gt;

&lt;p&gt;Ich hoffe, das bleibt auch so …&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>OpenWatcom C/C++</title>
   <link href="https://www.opengate.at/blog/2021/10/watcom/"/>
   <published>2021-10-02T13:00:00+02:00</published>
   <updated>2021-10-02T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2021/10/watcom</id>
   <category term="devel" />
   <summary type="text">Der OpenWatcom C/C++ 
Compiler zählt nicht nur zu den ältesten seiner Art, er unterstützt auch 
noch die alten Plattformen wie Windows 3.X, 
OS/2 und 
DOS
neben Linux und 
WinNT.

Und er ist wahrlich “antiquiert” in Sachen Standards und std Support.
Kurz gesagt: Genau die richtige Umgebung für meine Experimente.

</summary>
   <content type="html">&lt;p&gt;Der &lt;a href=&quot;https://en.wikipedia.org/wiki/Watcom_C/C%2B%2B&quot;&gt;OpenWatcom C/C++&lt;/a&gt; 
Compiler zählt nicht nur zu den ältesten seiner Art, er unterstützt auch 
noch die alten Plattformen wie &lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_3.x&quot;&gt;Windows 3.X&lt;/a&gt;, 
&lt;a href=&quot;https://de.wikipedia.org/wiki/OS/2&quot;&gt;OS/2&lt;/a&gt; und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/MS-DOS&quot;&gt;DOS&lt;/a&gt;
neben &lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt; und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_NT&quot;&gt;WinNT&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Und er ist wahrlich “antiquiert” in Sachen Standards und &lt;code&gt;std&lt;/code&gt; Support.&lt;br /&gt;
Kurz gesagt: Genau die richtige Umgebung für meine Experimente.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Vor etwas über 10 Jahren wollte ich schon einmal mit diesem Compiler 
“ins Gespräch” kommen, doch da ich &lt;a href=&quot;https://de.wikipedia.org/wiki/CMake&quot;&gt;CMake&lt;/a&gt;
noch nicht kannte, wurden diese Pläne wieder auf Eis gelegt.&lt;/p&gt;

&lt;p&gt;Watcom C und C++ war offenbar recht beliebt im vergangenen Jahrtausend,
bevor Windows und Linux im Jahr 2000 so richtig durchstarteten. Denn mit
seiner Anbindung an die &lt;a href=&quot;https://en.wikipedia.org/wiki/DOS_extender&quot;&gt;DOS-Extender&lt;/a&gt;
APIs ermöglichte er 32-Programmierung unter DOS und war nebenbei recht beliebt
bei den Spiele-Entwicklern. Meine uralten Lieblinge wie 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Doom_2:_Hell_on_Earth&quot;&gt;DOOM&lt;/a&gt;, 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Duke_Nukem_3D&quot;&gt;Duke Nukem 3D&lt;/a&gt; und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Tomb_Raider_(1996)&quot;&gt;Tomb Raider&lt;/a&gt; wurden mit 
diesem Compiler übersetzt.&lt;/p&gt;

&lt;p&gt;2003 wurde Watcom C auf Open-Watcom umgetauft und kostenfrei verfügbar.
So lernte ich Version 1.9 etwa um 2010 kennen.&lt;br /&gt;
Inzwischern wurde ein Fork 2.0 abgespalten, der aber bis heute noch im
Beta-Stadium ist und stückweise weiterentwickelt wird.&lt;/p&gt;

&lt;h3 id=&quot;eigenheiten-von-openwatcom&quot;&gt;Eigenheiten von OpenWatcom&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Keine Function-Template Spezialisierungen.&lt;br /&gt;
Template Klassen und Strukturen können halbwegs normal spezialisiert werden.
Man kann auch rein generische Template-Funktionen schreiben, aber dort
führen Spezialisierungsversuche sofort zu Fehlern.&lt;/li&gt;
  &lt;li&gt;Kein vollständiges &lt;a href=&quot;https://de.wikipedia.org/wiki/Substitution_failure_is_not_an_error&quot;&gt;SFINAE&lt;/a&gt;&lt;br /&gt;
Also z.B. kein &lt;code&gt;enable_if&lt;/code&gt;. Der Compiler lässt ungültige Template 
Konstellationen also nicht weg (wie im Standard gefordert), 
sondern generiert Fehler.&lt;/li&gt;
  &lt;li&gt;Im Default keine nicht-globalen C &lt;code&gt;struct&lt;/code&gt; Initialisierung erlaubt.&lt;br /&gt;
&lt;code&gt;struct mystruct myvar = { var1, 2, 3.0 };&lt;/code&gt; innerhalb einer Funktion lehnt der
Compiler mal einfach so ab. Nur globale konstante Instanziierungen sind 
erlaubt. Das kann man zum Glück durch die Compiler Option &lt;code&gt;-aa&lt;/code&gt; ändern.&lt;/li&gt;
  &lt;li&gt;Keine anonymen &lt;code&gt;union&lt;/code&gt; Instanzen.&lt;br /&gt;
Ich nutze ja gerne &lt;code&gt;union&lt;/code&gt; in einem &lt;code&gt;struct&lt;/code&gt; und erwarte dann, dass jeder
&lt;code&gt;union&lt;/code&gt; Member wie ein Teil der &lt;code&gt;struct&lt;/code&gt; ansprechbar ist. Doch in Watcom
muss ein Instanzname benutzt werden. Das merkt man übelst, wenn man viel
Code mit &lt;a href=&quot;https://en.wikipedia.org/wiki/Variant_type_(COM)&quot;&gt;COM VARIANT&lt;/a&gt; 
Typen hat und die Kurzschreibweise erwartet.&lt;/li&gt;
  &lt;li&gt;Moderne Header sind zwar vorhanden, tragen aber nur wenige Zeilen mit
dem Inhalt
    &lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#777&quot;&gt;/* TODO: Implement me! */&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
    &lt;/div&gt;
    &lt;p&gt;in sich. Also kein C++11 oder C11 Support trotz existierender Header.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Und vieles mehr wird sich wahrscheinlich bei weiteren Experimenten noch ergeben.&lt;/p&gt;

&lt;h3 id=&quot;cmake-support-für-wmake&quot;&gt;CMake support für WMAKE&lt;/h3&gt;

&lt;p&gt;Ich hatte anfangs den schweren Fehler gemacht, dass ich absichtlich mit einer
älteren CMake-Variante experimentiert hatte um 32-bit EXEn zu erzeugen.&lt;/p&gt;

&lt;p&gt;Doch der CMake-Support für OpenWatcom ist über die Jahre viel besser geworden
und während ich mit der alten Version scheiterte, hatte ich keine Probleme,
den Windows 64-bit Compiler mit der neuesten Version von CMake dazu zu 
bekommen 32-Bit NT-Binaries auszuwerfen.&lt;/p&gt;

&lt;p&gt;CMake erzeugt dafür &lt;code&gt;wmake&lt;/code&gt;-Files, die mit dem &lt;code&gt;wmake&lt;/code&gt; Tool ganz analog zum
normalen &lt;code&gt;make&lt;/code&gt; Compiler und Linker Aufrufe durchführen um Projekte zu 
bauen. Man muss also nur ins Build-Verzeichnis springen und &lt;code&gt;wmake&lt;/code&gt; eintippen
um einen Build-Prozess loszutreten.&lt;/p&gt;

&lt;p&gt;OpenWatcom kommt auch mit einer eigenen &lt;a href=&quot;https://de.wikipedia.org/wiki/Integrierte_Entwicklungsumgebung&quot;&gt;IDE&lt;/a&gt;, 
eigenem Debugger und eigenem Projekt-Format. Aber ich ziehe es vor, alles 
über CMake laufen zu lassen. Und als Editor kann man schließlich immer auf 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_Studio_Code&quot;&gt;Visual Studio Code&lt;/a&gt; zurückgreifen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Mein nächstes Ziel ist kein Geheimnis: &lt;a href=&quot;https://de.wikipedia.org/wiki/MS-DOS&quot;&gt;DOS&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Ich frage mich, was notwendig ist, um die Codebase des GATE-Projektes für DOS
kompilierbar zu machen. Klar ist, dass viele Systemfunktionen, die aktuell nur
für Win32 und POSIX implementiert sind, noch krass angepasst werden müssen.
Aber generische Array, Map und Encoding Routinen (wie 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Extensible_Markup_Language&quot;&gt;XML&lt;/a&gt;, 
&lt;a href=&quot;https://de.wikipedia.org/wiki/JavaScript_Object_Notation&quot;&gt;JSON&lt;/a&gt; usw.) sollten
hoffentlich out-of-the-box laufen … außer die DOS-Speichersegmente behindern
meine aktuell gesetzten Puffergrößen.&lt;/p&gt;

&lt;p&gt;Genau hier wird es spannend, wie man Code so schreiben kann, dass er sich 
dynamisch an die Plattform anpasst.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Die Spiele mögen beginnen.&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>Build Server Marke Eigenbau</title>
   <link href="https://www.opengate.at/blog/2021/09/build-server/"/>
   <published>2021-09-26T13:00:00+02:00</published>
   <updated>2021-09-26T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2021/09/build-server</id>
   <category term="software" /><category term="projects" />
   <summary type="text">Java, 
Ruby, 
Python, 
dotNet … also, wie es aussieht, gibt 
es heute keinen einzigen Build-Server, der ordentlich (sprich effizient) 
programmiert ist, also in C 
oder C++.
Damit ist von GitLab über 
Jenkins bis zu 
TeamCity
keiner geeignet auf meinen Intel Atom
Servern zu Hause zu laufen.

Es kann doch nicht so schwer sein, einen CMake
Build in Docker anzustoßen.
Also bauen wir uns das selbst, so wie es sich gehört.
</summary>
   <content type="html">&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Java-Technologie&quot;&gt;Java&lt;/a&gt;, 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Ruby_(Programmiersprache)&quot;&gt;Ruby&lt;/a&gt;, 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Python_(Programmiersprache)&quot;&gt;Python&lt;/a&gt;, 
&lt;a href=&quot;https://de.wikipedia.org/wiki/.NET&quot;&gt;dotNet&lt;/a&gt; … also, wie es aussieht, gibt 
es heute keinen einzigen Build-Server, der ordentlich (sprich effizient) 
programmiert ist, also in &lt;a href=&quot;https://de.wikipedia.org/wiki/C_(Programmiersprache)&quot;&gt;C&lt;/a&gt; 
oder &lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B&quot;&gt;C++&lt;/a&gt;.&lt;br /&gt;
Damit ist von &lt;a href=&quot;https://de.wikipedia.org/wiki/GitLab&quot;&gt;GitLab&lt;/a&gt; über 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Jenkins_(Software)&quot;&gt;Jenkins&lt;/a&gt; bis zu 
&lt;a href=&quot;https://de.wikipedia.org/wiki/TeamCity&quot;&gt;TeamCity&lt;/a&gt;
keiner geeignet auf meinen &lt;a href=&quot;https://de.wikipedia.org/wiki/Intel_Atom&quot;&gt;Intel Atom&lt;/a&gt;
Servern zu Hause zu laufen.&lt;/p&gt;

&lt;p&gt;Es kann doch nicht so schwer sein, einen &lt;a href=&quot;https://de.wikipedia.org/wiki/CMake&quot;&gt;CMake&lt;/a&gt;
Build in &lt;a href=&quot;https://de.wikipedia.org/wiki/Docker_(Software)&quot;&gt;Docker&lt;/a&gt; anzustoßen.
Also bauen wir uns das selbst, so wie es sich gehört.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Tja und tatsächlich. Es funktioniert.&lt;/p&gt;

&lt;p&gt;Und weil die Details den Rahmen eines BLOG-Eintrags sprengen würden, wurde
das Thema zu den Nebenschauplatz-Dokus verlegt:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/blog/projects/build-server/&quot;&gt;Build Server Scripting&lt;/a&gt;&lt;/p&gt;

&lt;h3 id=&quot;diverse-erkenntnisse&quot;&gt;Diverse Erkenntnisse&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Server_Core&quot;&gt;Windows Server Core&lt;/a&gt; Image 
verdoppelt sich.&lt;br /&gt;
Ein übliches Server-Core Image liegt bei etwa 5 GB, doch nach der 
VS-BuildTools Installation meldet &lt;code&gt;docker image list&lt;/code&gt; Größen
von 9 bis 11 GB. Konkret wächst Visual Studio mit jeder Version
um ein 1 GB (von 2017 über 2019 bis 2022).&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code&gt;docker run&lt;/code&gt; kann keine Mehrfachbefehle für &lt;code&gt;cmd&lt;/code&gt; verkraften.&lt;br /&gt;
Ich bin an &lt;code&gt;cd subdir &amp;amp;&amp;amp; run_script.bat&lt;/code&gt; total gescheitert. Das klappt
wunderbar im &lt;code&gt;Dockerfile&lt;/code&gt; und auch so auf der Konsole, aber wenn man es
mit &lt;code&gt;docker run myimage cd subdir &amp;amp;&amp;amp; run_script.bat&lt;/code&gt; kombinieren möchte,
will es ums Verrecken nicht ausführen. Dabei habe ich unzählige 
Kombinationen von &lt;code&gt;ENTRYPOIN&lt;/code&gt; mit &lt;code&gt;cmd /s /c&lt;/code&gt; und mit jeder Form von
Anführungszeichen ausprobiert. So ein F*ck!&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code&gt;CMake&lt;/code&gt; ist nix für &lt;a href=&quot;https://de.wikipedia.org/wiki/Intel_Atom&quot;&gt;Intel Atom&lt;/a&gt;.&lt;br /&gt;
Gut, das wusste ich schon früher … aber bei meinen Experimenten
störte mich am meisten, dass &lt;code&gt;CMake&lt;/code&gt; für jeden seiner Tests, ob eine
Funktion existiert, ein separates Kompilat anfertigt. 
Und dank der &lt;a href=&quot;https://de.wikipedia.org/wiki/LibreSSL&quot;&gt;libReSSL&lt;/a&gt; gibt es 
davon zahlreiche, bevor das GATE Projekt übersetzt werden kann. 
3-5 Minuten dauert diese Testphase auf meinem Strom-Sparefroh-Rechner 
… und wenn man das 20 Mal machen muss, ist das kein Vergnügen.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Hyper-V&quot;&gt;Hyper-V&lt;/a&gt; Isolation auch für &lt;code&gt;docker build&lt;/code&gt;
Am Windows Server baut man normalerweise alles für die eigene
Windows Version. Dass &lt;code&gt;docker run --isolation=hyperv&lt;/code&gt; auch Container
von “fremden” Kernel Versionen starten kann, wusste ich bereits.
Aber nun konnte ich beobachten, dass &lt;code&gt;docker build --isolation=hyperv ...&lt;/code&gt;
auch solche Images erzeugen kann.&lt;br /&gt;
However … schnell ist das auf meiner Hardware allerdings nicht gewesen.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code&gt;CMake&lt;/code&gt; ist bei Studio 2017 nur in Version 3.12 integriert. Ich
musste daher eine neuere Version nachschießen. Das geht aber ganz leicht
per Download und Installation von 
https://github.com/Kitware/CMake/releases/download/v3.21.3/cmake-3.21.3-windows-x86_64.msi
:&lt;/p&gt;

    &lt;div class=&quot;language-dockerfile highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;RUN `
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;  curl -SL --output cmake.msi `
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  https://github.com/Kitware/CMake/.../cmake-3.21.3-windows-x86_64.msi `
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  &amp;amp;&amp;amp; msiexec.exe /i cmake.msi /quiet /qn `
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  &amp;amp;&amp;amp; del /q cmake.msi `
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;  &amp;amp;&amp;amp; setx PATH &amp;quot;C:\Program Files\cmake\bin;%PATH%&amp;quot;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Nun, ich bin zufrieden, das ich wieder mal ein Problem gelöst habe, das sonst
niemand als Problem klassifizieren würde.
Aber …&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;Frage: Warum leckt sich der Hund die Eier?&lt;br /&gt;
Antwort: Weil er es eben kann!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Und da mein &lt;a href=&quot;https://de.wikipedia.org/wiki/Domain_Controller&quot;&gt;Domain Controller&lt;/a&gt; 
ja sowieso den Großteil des Tages nichts zu tun hat, darf er nun täglich per 
Task-Scheduler einen GATE-Windows-Build durchrechnen.&lt;/p&gt;

&lt;p&gt;Ich freue mich, dass ich beweisen konnte, dass Buildserver auch 
“nur mit Wasser kochen”. Und sollte dennoch irgendwann mal der Auftrag auf
mich zukommen einen Build-Server ohne Build-Server aufzusetzen, 
habe ich bereits etwas Vorsprung.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>80486 heute?</title>
   <link href="https://www.opengate.at/blog/2021/09/80486/"/>
   <published>2021-09-25T13:00:00+02:00</published>
   <updated>2021-09-25T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2021/09/80486</id>
   <category term="hardware" /><category term="retro" />
   <summary type="text">Was war das für eine tolle Zeit, als man beim Einsetzen einer 
ISA Karte eine
Bluttransfusion brauchte, weil man sich an den Lötkontakten und den 
messerscharfen unbehandelten Platinenkanten die halbe Hand zerfetzt hatte.

Ja das war, als ich meinen damals schon veralten 486er PC
mit Erweiterungskarten stückweise “nutzbar” machen wollte.
</summary>
   <content type="html">&lt;p&gt;Was war das für eine tolle Zeit, als man beim Einsetzen einer 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Industry_Standard_Architecture&quot;&gt;ISA&lt;/a&gt; Karte eine
Bluttransfusion brauchte, weil man sich an den Lötkontakten und den 
messerscharfen unbehandelten Platinenkanten die halbe Hand zerfetzt hatte.&lt;/p&gt;

&lt;p&gt;Ja das war, als ich meinen damals schon veralten &lt;a href=&quot;https://de.wikipedia.org/wiki/Intel_80486&quot;&gt;486er PC&lt;/a&gt;
mit Erweiterungskarten stückweise “nutzbar” machen wollte.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Während mein damaliger 486er auch heute noch in meinem alten
Zimmer am Zweitwohnsitz steht, habe ich seinen kleinen Bruder für ein paar 
Tests wieder in den Dienst einberufen.&lt;/p&gt;

&lt;p&gt;Ich hatte einen Compaq &lt;a href=&quot;https://de.wikipedia.org/wiki/Intel_i486#i486DX&quot;&gt;486 DX-33&lt;/a&gt;
irgend wo vor der Verschrottung gerettet und ihn Ende der 90er Jahre zu einem
meiner Netzwerk-Experimentierkästen auserkoren.&lt;/p&gt;

&lt;p&gt;Das Gerät hat also knapp 30 Jahre auf dem Buckel und ich war überrascht,
dass es immer noch brav startete. Offenbar hat man damals Kondensatoren
für die Ewigkeit gebaut, denn auf meinen &lt;a href=&quot;https://de.wikipedia.org/wiki/Mini-ITX&quot;&gt;ITX&lt;/a&gt;
Boards um das Jahr 2005 musste ich schon den einen oder anderen 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Elektrolytkondensator&quot;&gt;Elko&lt;/a&gt; auslöten 
und ersetzen.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ich sag nur: #Früher-war-alles-besser.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/compaq-486-board.jpg&quot; alt=&quot;486-Board&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Nach dem Wegblasen und Wegwischen einer dicken Staubschicht, wurden 
Mainboard und CPU sichtbar.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/compaq-486-cpu.jpg&quot; alt=&quot;486-CPU&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Dieser Gerät war das einzige aus der damaligen Zeit, das schon über PS/2 Maus
und Tastaturanschlüsse verfügte, denn fast alle meine anderen Geräte vor dem
Jahr 2000 setzten noch auf den &lt;a href=&quot;https://de.wikipedia.org/wiki/DIN-Steckverbinder&quot;&gt;DIN-Stecker&lt;/a&gt;
und eine Maus über den COM-Port.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/compaq-486-backside.jpg&quot; alt=&quot;486-Backside&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Nach einigem Suchen konnte ich endlich auch noch eine ISA Netzwerk-Karte 
finden, die ich vermutlich schon damals in dem Gerät verbaut hatte. 
Diese Karte mit dem &lt;code&gt;RTL8019AS&lt;/code&gt; Chip konnte sowohl mit einem 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Ethernet#10-Mbit/s-Ethernet_mit_Koaxialkabel&quot;&gt;BCN-Kabel&lt;/a&gt;,
als auch mit heutigen &lt;a href=&quot;https://de.wikipedia.org/wiki/Ethernet#10-Mbit/s-Ethernet_mit_Twisted-Pair-Kabel&quot;&gt;RJ-45&lt;/a&gt;
Ethernet Kabeln umgehen … allerdings nur bis 10 MBit.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/nic-rtl8019as.jpg&quot; alt=&quot;RTL8019AS&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;atx-adapter&quot;&gt;ATX Adapter&lt;/h3&gt;

&lt;p&gt;Meine Frage war konkret:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Kann ich einen 486 heute überhaupt noch betreiben?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Denn da die heutigen &lt;a href=&quot;https://de.wikipedia.org/wiki/PC-Netzteil#ATX-Format&quot;&gt;ATX-Netzteile&lt;/a&gt; 
nicht mit den damaligen &lt;a href=&quot;https://de.wikipedia.org/wiki/PC-Netzteil#AT-Format&quot;&gt;AT-Netzteilen&lt;/a&gt;
kompatibel sind, stirbt mit dem Netzteil auch der Rest.&lt;/p&gt;

&lt;p&gt;Doch diese listigen Chinesen haben extra für Leute wie mich ATX zu AT Adapter 
auf ihre Bestellseiten gesetzt, und da konnte ich einfach nicht widerstehen.
Vor allem nicht bei einem Preis von 1-2 Euro pro Stück.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/atx-to-at-adapter.jpg&quot; alt=&quot;ATX to AT Adapter&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Grundsätzlich ist die Sache nicht schwer. Denn die üblichen Spannungen von
12 V, 5 V und 3.3 V gab es damals wie heute. Nur die Stecker zum Mainboard
sahen anders aus.&lt;/p&gt;

&lt;p&gt;Da man früher die PCs mit mechanischen Schaltern aus und einschalten musste,
sind aus dem Adapter zwei Kabelenden herausgeführt, deren Kurzschluss dem 
Netzteil die Bestromung befiehlt.&lt;br /&gt;
Man könnte die beiden Enden leicht mit einem Kippschalter verbinden, und im
Gehäuse verbauen (wenn man wollte).&lt;/p&gt;

&lt;p&gt;Als Netzteil musste wieder einer meiner alten ITX Spannungswandler
herhalten. Die vertragen ca. 90 - 120 Watt und damit in etwa genau das, 
was das alte 486er Netzteil auch lieferte.&lt;br /&gt;
Mein freies externes Netzteil war aber nur für 72 Watt zugelassen, 
weshalb ich mich dazu entschied, das Experiment mit dem Labornetzteil
durchzuführen.&lt;/p&gt;

&lt;h3 id=&quot;486-läuft-mit-atx-strom&quot;&gt;486 läuft mit ATX-Strom&lt;/h3&gt;

&lt;p&gt;Um die Stromaufnahme weiter zu reduzieren, ersetzte ich die 300 MB Festplatte
durch eine meiner &lt;a href=&quot;/blog/2019/03/ide-ssd-hd/&quot;&gt;IDE-SSDs&lt;/a&gt; mit 256 MB&lt;/p&gt;

&lt;p&gt;Und siehe da, es funktionierte.&lt;/p&gt;

&lt;p&gt;Nach einer kurzen Spitze von 3 Ampere bei 12 Volt beim Einschalten, lief der
486er problemlos an und verbrauchte je nach Aufgabe zwischen 1.9 und 2.3 
Ampere. Die alte mechanische Festplatte hätte da sicher noch 1-2 Ampere
draufgeschlagen. Mit einem 72 Watt Netzteil ist man also stark genug, 
so lange man keine weiteren Geräte wie CD-Laufwerke einbaut.&lt;/p&gt;

&lt;p&gt;Apropos Festplatte.&lt;br /&gt;
Die war etwas mühsam, denn das damalige BIOS konnte Festplatten nicht 
automatisch erkennen und erwartete die Eingabe der genauen Zylinder,
Kopf und Spuren-Anzahl.&lt;/p&gt;

&lt;p&gt;Was für ein Glück, dass mein altes &lt;a href=&quot;https://de.wikipedia.org/wiki/EPIA&quot;&gt;VIA-EPIA&lt;/a&gt;
ITX Mainboard daneben lag. Dort konnte ich im BIOS die IDE-SSD erkennen lassen 
und die geforderten Werte notieren.&lt;/p&gt;

&lt;p&gt;Zurück am 486 tippte ich die Werte ein um dann festzustellen, dass es
anfangs nicht funktionierte.&lt;br /&gt;
Ich musste den 486 vom Strom nehmen und neu einschalten, damit SSD 
und Board korrekt über die gespeicherten Werte mit einander reden konnten.&lt;/p&gt;

&lt;p&gt;Danach nutzte ich meine alten &lt;a href=&quot;https://de.wikipedia.org/wiki/MS-DOS&quot;&gt;DOS&lt;/a&gt; 
Disketten um die Festplatte zu partitionieren und im Anschluss 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_3.1&quot;&gt;Windows 3.1&lt;/a&gt; zu 
installieren.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Wieder mal ein Nostalgie Moment nach 20 Jahren, denn so lange hatte ich
das Gerät nicht mehr in Betrieb genommen.&lt;/p&gt;

&lt;p&gt;Was mich besonders freut ist die Tatsache, dass wir heute immer noch
Möglichkeiten haben die alte Hardware weiter zu betreiben. 
Es gibt bekanntlich auch heute noch Industriesysteme, die seit 20 Jahren
mit Software “von damals” täglich brav ihr Werk tun.&lt;/p&gt;

&lt;p&gt;Für Administratoren ist das zwar ein Alptraum, aber mir beweist das,
dass auch in der kurzlebigen IT ein Hauch von Dauerhaftigkeit zumindest
möglich ist.&lt;br /&gt;
Und sollte morgen ein EMP alle Computer hinwegraffen wollen, dann 
überleben vermutlich die alten Blechkisten von damals am ehesten das 
jüngste Gericht.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Fehlschlag: Stack Koroutinen</title>
   <link href="https://www.opengate.at/blog/2021/09/coroutine-2/"/>
   <published>2021-09-19T13:00:00+02:00</published>
   <updated>2021-09-19T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2021/09/coroutine-2</id>
   <category term="devel" />
   <summary type="text">Aus Fehlern lernt man bekanntlich am meisten, und deshalb möchte ich einen
meiner Irrtümer hier schildern.
Es begann mit der Idee:


  Man könnte doch einen Stack
durch diverse Funktionsaufrufe aufblasen und
dann per setjmp() “Einsprungpunkte” in den Stack setzen.
Wenn man dann noch einen Scheduler schreibt, der per longjmp() 
zwischen diesen Einsprungpunkten auswählen kann, dann hätte man:
Eine rein generische C Implementierung
für Koroutinen.


</summary>
   <content type="html">&lt;p&gt;Aus Fehlern lernt man bekanntlich am meisten, und deshalb möchte ich einen
meiner Irrtümer hier schildern.&lt;br /&gt;
Es begann mit der Idee:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Man könnte doch einen &lt;a href=&quot;https://de.wikipedia.org/wiki/Stapelspeicher&quot;&gt;Stack&lt;/a&gt;
durch diverse Funktionsaufrufe aufblasen und
dann per &lt;code&gt;setjmp()&lt;/code&gt; “Einsprungpunkte” in den Stack setzen.
Wenn man dann noch einen Scheduler schreibt, der per &lt;code&gt;longjmp()&lt;/code&gt; 
zwischen diesen Einsprungpunkten auswählen kann, dann hätte man:&lt;br /&gt;
Eine rein generische &lt;a href=&quot;https://de.wikipedia.org/wiki/C_(Programmiersprache)&quot;&gt;C Implementierung&lt;/a&gt;
für &lt;a href=&quot;https://de.wikipedia.org/wiki/Koroutine&quot;&gt;Koroutinen&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;strong&gt;Spoiler: Ich lag falsch.&lt;/strong&gt;&lt;br /&gt;
Naja, in kleinen Teilen lag ich fast richtig … doch leider nur im 
32 bit Debug-Modus, wo der Callstack schön und nicht normiert ist.&lt;br /&gt;
Ein Patent brauche ich auf meine Idee also nicht anmelden.&lt;/p&gt;

&lt;p&gt;Es hat sich nämlich ganz deutlich gezeigt, dass man mit 
&lt;a href=&quot;https://en.wikipedia.org/wiki/Setjmp.h&quot;&gt;&lt;code&gt;setjmp&lt;/code&gt; und &lt;code&gt;longjmp()&lt;/code&gt;&lt;/a&gt; im Stack 
nur “zurückspringen” kann, also in Richtung des Aufrufers.
Der andere Weg, also der Sprung in eine Unterfunktion klappt leider
nicht und führt zu Segmentation-Faults und Schlimmerem.&lt;/p&gt;

&lt;h3 id=&quot;idee-stack-aufteilung-per-setjmp&quot;&gt;Idee: Stack-Aufteilung per setjmp&lt;/h3&gt;

&lt;p&gt;Stellt euch vor, wer setzen in einer Funktion einen Anker mit &lt;code&gt;setjmp()&lt;/code&gt;
und rufen dann eine Funktion auf, die einen Datenblock auf dem Stack allokiert
und sich dann selbst aufruft.&lt;br /&gt;
Zuvor legen wir mit einem weiteren &lt;code&gt;setjmp&lt;/code&gt; einen Anker auf den aktuellen
Funktionsaufruf, bevor wir uns selbst aufrufen.&lt;br /&gt;
Und mit einem Counter würden wir sicherstellen, dass das nicht unendlich oft 
passiert und wir nach N-Aufrufen per &lt;code&gt;longjmp&lt;/code&gt; zum Ausgangspunkt zurückkehren.&lt;/p&gt;

&lt;p&gt;Da wir (theoretisch) aus keiner Funktion mit &lt;code&gt;return&lt;/code&gt; zurückgesprungen sind, 
sondern nur &lt;code&gt;longjmp&lt;/code&gt; dafür gebraucht haben, sollte der Stapelspeicher (Stack)
über uns (eigentlich unter uns) dann immer noch aufrecht sein.&lt;/p&gt;

&lt;p&gt;Nun könnten wir mit weiteren &lt;code&gt;longjmp&lt;/code&gt; Aufrufen zwischen den Stack-Teilen
hin und her springen und dort andere Funktionen aufrufen, da wir ja
stets einen “lokalen” Block allokiert hatten, der den Stack weiter 
aufgeblasen hat.&lt;br /&gt;
Die Funktionen in den Stack-Teilen sollten sich also gegenseitig nicht
stören, so lange ihre eigenen Allokationen kleiner als unser Block
sind.&lt;/p&gt;

&lt;p&gt;Ein Beispiel-Code sagt mehr als tausend Worte:&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color:#B44;font-weight:bold&quot;&gt;&amp;lt;setjmp.h&amp;gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;typedef&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;(*entry_point_function)(&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;* param);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;static&lt;/span&gt; jmp_buf &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;volatile&lt;/span&gt; origin;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;struct&lt;/span&gt; context
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;  jmp_buf &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;volatile&lt;/span&gt; anchor;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;  entry_point_function func;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;* func_param;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;};
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#define&lt;/span&gt; MAX_STACKS &lt;span style=&quot;color:#00D&quot;&gt;16&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#define&lt;/span&gt; MAX_STACK_SIZE &lt;span style=&quot;color:#00D&quot;&gt;16384&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;static&lt;/span&gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;struct&lt;/span&gt; context &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;volatile&lt;/span&gt; contexts[MAX_STACKS];
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;static&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt; stack_entry_point(&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; counter);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;static&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt; create_stack_partition(&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; counter)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n21&quot; name=&quot;n21&quot;&gt;21&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n22&quot; name=&quot;n22&quot;&gt;22&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;/* just reserve stack space */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n23&quot; name=&quot;n23&quot;&gt;23&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;volatile&lt;/span&gt; stack_buffer[MAX_STACK_SIZE];
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n24&quot; name=&quot;n24&quot;&gt;24&lt;/a&gt;&lt;/span&gt;  stack_entry_point(counter);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n25&quot; name=&quot;n25&quot;&gt;25&lt;/a&gt;&lt;/span&gt;}
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n26&quot; name=&quot;n26&quot;&gt;26&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n27&quot; name=&quot;n27&quot;&gt;27&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;static&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt; stack_entry_point(&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; counter)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n28&quot; name=&quot;n28&quot;&gt;28&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n29&quot; name=&quot;n29&quot;&gt;29&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;struct&lt;/span&gt; context &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;volatile&lt;/span&gt;* ptr_context = &amp;amp;contexts[counter];
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n30&quot; name=&quot;n30&quot;&gt;30&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt;(setjmp(ptr_context-&amp;gt;anchor) == &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n31&quot; name=&quot;n31&quot;&gt;31&lt;/a&gt;&lt;/span&gt;  {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n32&quot; name=&quot;n32&quot;&gt;32&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#777&quot;&gt;/* stack-entry-point registration completed */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n33&quot; name=&quot;n33&quot;&gt;33&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt;(counter &amp;gt; &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n34&quot; name=&quot;n34&quot;&gt;34&lt;/a&gt;&lt;/span&gt;    {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n35&quot; name=&quot;n35&quot;&gt;35&lt;/a&gt;&lt;/span&gt;      create_stack_partition(counter - &lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;);  
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n36&quot; name=&quot;n36&quot;&gt;36&lt;/a&gt;&lt;/span&gt;    }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n37&quot; name=&quot;n37&quot;&gt;37&lt;/a&gt;&lt;/span&gt;  }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n38&quot; name=&quot;n38&quot;&gt;38&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;else&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n39&quot; name=&quot;n39&quot;&gt;39&lt;/a&gt;&lt;/span&gt;  {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n40&quot; name=&quot;n40&quot;&gt;40&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;    &lt;span style=&quot;color:#777&quot;&gt;/* entry point from longjmp() */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n41&quot; name=&quot;n41&quot;&gt;41&lt;/a&gt;&lt;/span&gt;    ptr_context-&amp;gt;func(ptr_context-&amp;gt;func_param);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n42&quot; name=&quot;n42&quot;&gt;42&lt;/a&gt;&lt;/span&gt;  }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n43&quot; name=&quot;n43&quot;&gt;43&lt;/a&gt;&lt;/span&gt;  longjmp(origin, &lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n44&quot; name=&quot;n44&quot;&gt;44&lt;/a&gt;&lt;/span&gt;}
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n45&quot; name=&quot;n45&quot;&gt;45&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n46&quot; name=&quot;n46&quot;&gt;46&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt; scheduler()
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n47&quot; name=&quot;n47&quot;&gt;47&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n48&quot; name=&quot;n48&quot;&gt;48&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;/* set function-pointers in @contexts */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n49&quot; name=&quot;n49&quot;&gt;49&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;/* ... */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n50&quot; name=&quot;n50&quot;&gt;50&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;/* prepare stack */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n51&quot; name=&quot;n51&quot;&gt;51&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt;(setjmp(origin) == &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n52&quot; name=&quot;n52&quot;&gt;52&lt;/a&gt;&lt;/span&gt;  {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n53&quot; name=&quot;n53&quot;&gt;53&lt;/a&gt;&lt;/span&gt;    create_stack_partition(MAX_STACKS - &lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n54&quot; name=&quot;n54&quot;&gt;54&lt;/a&gt;&lt;/span&gt;  }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n55&quot; name=&quot;n55&quot;&gt;55&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n56&quot; name=&quot;n56&quot;&gt;56&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;/* longjmp into stack-partition */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n57&quot; name=&quot;n57&quot;&gt;57&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;/* ... */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n58&quot; name=&quot;n58&quot;&gt;58&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Jetzt muss man noch ein paar Details erweitern, z.B., dass am besten jede
Variable &lt;code&gt;volatile&lt;/code&gt; wird und der &lt;code&gt;stack_buffer&lt;/code&gt; am besten mit einer 
&lt;code&gt;for&lt;/code&gt; Schleife befüllt wird, weil der Compiler den Block trotz &lt;code&gt;volatile&lt;/code&gt;
gerne rausoptimiert … aber grundsätzlich “läuft das” … denkt man.&lt;/p&gt;

&lt;h3 id=&quot;problem--x86_32&quot;&gt;Problem != x86_32&lt;/h3&gt;

&lt;p&gt;Der &lt;a href=&quot;https://de.wikipedia.org/wiki/X86-Prozessor&quot;&gt;x86&lt;/a&gt; Befehlssatz im 32 Bit 
Modus erlaubt das tatsächlich. Wir könnten mit &lt;code&gt;setjmp&lt;/code&gt;/&lt;code&gt;longjmp&lt;/code&gt; tatsächlich 
Koroutinen bauen und mit ein paar Tricks auch manche Optimierungsfallen 
des Compiler umgehen.&lt;br /&gt;
Und ich wette, dass man auf x86-16bit und diversen &lt;a href=&quot;https://de.wikipedia.org/wiki/Mikrocontroller&quot;&gt;Mikrocontrollern&lt;/a&gt;
ebenfalls Erfolge sehen könnte.&lt;/p&gt;

&lt;p&gt;Doch andere Architekturen wie x86-64 oder ARM sind durchaus anders aufgebaut
und machen das Arbeiten mit &lt;code&gt;longjmp&lt;/code&gt; generell schwer.&lt;br /&gt;
Microsoft schreibt etwa in seine Dokumentation:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;In Microsoft C++ code on Windows, longjmp uses the same stack-unwinding 
semantics as exception-handling code. It is safe to use in the same 
places that C++ exceptions can be raised. However, this usage is not 
portable, and comes with some important caveats.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Tja, und da fängt wohl das Problem an, denn während unter 32-Bit das 
Exception-Handling von Funktion zu Funktion gesetzt werden musste, 
registrieren sich diese Handler heute über das OS um von dort
im Fehlerfall aufgerufen zu werden.&lt;br /&gt;
Durch meinen &lt;code&gt;longjmp&lt;/code&gt; nach der “Partitionierung” des Stacks zurück zur
Scheduler-Funktion wird also die Stackaufteilung zerstört.&lt;br /&gt;
Und dass dann eine Funktion in &lt;code&gt;ntdll.dll&lt;/code&gt; die Validität des
Stacks prüft, wenn ein weiterer &lt;code&gt;longjmp&lt;/code&gt; in ein Stack-Fragment erfolgt, 
ist für meine Zwecke natürlich schlecht&lt;br /&gt;
… aber es war ja auch nirgends definiert, dass das nicht so sein darf.&lt;/p&gt;

&lt;p&gt;Letztendlich sind meine Experimente mit “undefiniertem Verhalten” gelaufen.
Und bestimmt gibt es zahlreiche ähnliche Probleme auf weiteren Plattformen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Jetzt kenne ich also den Grund, warum &lt;a href=&quot;http://dieboostcppbibliotheken.de/boost.coroutine&quot;&gt;boost::coroutine&lt;/a&gt;
und andere Bibliotheken nicht ohne Assembler Code auskommen, um 
Ausführungskontexte zu sichern und wiederherzustellen.&lt;br /&gt;
Denn die hätten &lt;code&gt;setjmp&lt;/code&gt;/&lt;code&gt;longjmp&lt;/code&gt; ansonsten sicher auch gerne genutzt …&lt;/p&gt;

&lt;p&gt;Wie heißt es etwa im Film 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Das_Verm%C3%A4chtnis_der_Tempelritter&quot;&gt;Das Vermächtnis der Tempelritter&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Gescheitert bin ich nicht, ich kenne 2.000 Wege wie man Glühbirnen nicht 
bauen darf. Aber ein einziger hätte gereicht, damit es funktioniert.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Tja, schade. Ich hatte schon eine ganze Koroutinen Implementierung fertig,
die auf diesem Schema basiert.
Und laut einiger Tests hat die auch super funktioniert 
… aber eben nur unter Windows 32 bit und sonst nirgends.&lt;/p&gt;

&lt;p&gt;Ich habe das “Negativ-Beispiel” trotzdem in den “Class-Room” aufgenommen.
Denn wie schon gesagt: “Aus Fehlern lernt man.”&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Koroutinen</title>
   <link href="https://www.opengate.at/blog/2021/09/coroutine-1/"/>
   <published>2021-09-18T13:00:00+02:00</published>
   <updated>2021-09-18T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2021/09/coroutine-1</id>
   <category term="devel" />
   <summary type="text">Mit C++20 werden 
Koroutinen 
(#include &amp;lt;coroutine&amp;gt;) in den Sprachstandard aufgenommen.
Mich wundert aber, dass im nächsten C Standard (C2x)
von Koroutinen keine Rede ist.

Also habe ich mich mal in den Betriebssystemen umgesehen, wie man Koroutinen
selbst implementieren kann.
</summary>
   <content type="html">&lt;p&gt;Mit &lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B#C++20&quot;&gt;C++20&lt;/a&gt; werden 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Koroutine&quot;&gt;Koroutinen&lt;/a&gt; 
(&lt;a href=&quot;https://en.cppreference.com/w/cpp/language/coroutines&quot;&gt;&lt;code&gt;#include &amp;lt;coroutine&amp;gt;&lt;/code&gt;&lt;/a&gt;) in den Sprachstandard aufgenommen.
Mich wundert aber, dass im nächsten &lt;a href=&quot;https://en.wikipedia.org/wiki/C2x&quot;&gt;C Standard (C2x)&lt;/a&gt;
von Koroutinen keine Rede ist.&lt;/p&gt;

&lt;p&gt;Also habe ich mich mal in den Betriebssystemen umgesehen, wie man Koroutinen
selbst implementieren kann.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;vorgeschichte&quot;&gt;Vorgeschichte&lt;/h3&gt;

&lt;p&gt;Definition: Ich verstehe unter Koroutinen die Möglichkeit, einen 
“synchronen” Ausführungskontext anzuhalten und auf einen anderen zu wechseln.
Eigentlich meine ich damit eine Form des User-Mode-Thread-Scheduling.&lt;br /&gt;
Diverse “akademische” Spielereien, wo man selbst eine State-Machine 
implementiert und eine Funktion manuell in Stücke zerlegt und diese aufruft,
fällt für mich nicht unter das Sprachenkonstrukt “Koroutinen”, wenn gleich
man funktional damit das Gleiche machen kann.&lt;/p&gt;

&lt;p&gt;Ich möchte also mehrere Ausführungskontexte in einer logischen Einheit&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;starten (create)&lt;/li&gt;
  &lt;li&gt;gezielt aktivieren (switch_to)&lt;/li&gt;
  &lt;li&gt;beliebig zum nächsten Kontext wechseln (yield)&lt;/li&gt;
  &lt;li&gt;abwarten können (wait)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Persönlich gab es für mich noch nie einen Grund, bewusst Koroutinen 
einzusetzen, sie sind für mich eher nur Syntax-Zucker.&lt;br /&gt;
Ich gebe aber zu, dass es Konstellationen gibt (z.B. in Callback-Funktionen), 
wo es hilfreich sein kann, einfach auf einen anderen Callstack zu wechseln um 
dort etwas abzuarbeiten, ohne dass man gleich Kernel-Threads und 
Messagequeues dafür einsetzt.&lt;/p&gt;

&lt;h3 id=&quot;win32-fiber-api&quot;&gt;Win32 Fiber API&lt;/h3&gt;

&lt;p&gt;Windows kennt seit Win32/WinNT &lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/procthread/fibers&quot;&gt;Fibers&lt;/a&gt; 
(Fasern) als Untermenge von Threads (Faden). Ein Thread führt in der Regel 
genau einen Callstack mit sich, arbeitet also “eine Faser (=Fiber)” ab.
Man kann aber einen Thread in eine Fiber umwandeln und weitere Fibers 
erzeugen und dann per API zwischen diesen “Fasern” hin und herwechseln.
Es läuft immer nur ein aktiver Fiber in dem Thread, und alle anderen sind 
angehalten (werden also nicht ausgeführt).&lt;/p&gt;

&lt;p&gt;Mit dieser Technik kann man Koroutinen relativ einfach implementieren,
in dem man eine Scheduler-Fiber-Funktion nutzt, die sequentiell andere
registrierte Fiber-Koroutinen-Kontexte aktiviert.
Wenn eine Fiber-Koroutine zu einer anderen wechseln möchte, teilt sie
das über eine gemeinsame Variable mit und wechselt dann zur Scheduler-Fiber,
die die Anweisung korrekt umsetzt.&lt;/p&gt;

&lt;p&gt;Und wenn jetzt zu jeder Fiber noch ein &lt;code&gt;completed&lt;/code&gt; Flag gespeichert wird,
das beim Verlassen einer Koroutinen-Funktion gesetzt wird, dann kann man
auch ein &lt;code&gt;wait&lt;/code&gt; Feature implementieren, womit dann eine wartende Koroutine 
so lange nicht weiterläuft, bis die “erwartete” andere Routine fertig ist.&lt;/p&gt;

&lt;p&gt;Folgende Windows API sind sehr hilfreich:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-convertthreadtofiber&quot;&gt;ConvertThreadToFiber&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createfiber&quot;&gt;CreateFiber&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-switchtofiber&quot;&gt;SwitchToFiber&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-deletefiber&quot;&gt;DeleteFiber&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/winnt/nf-winnt-getfiberdata&quot;&gt;GetFiberData&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/winnt/nf-winnt-getcurrentfiber&quot;&gt;GetCurrentFiber&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Eigentlich gibt es dann noch die Funktion &lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-convertfibertothread&quot;&gt;ConvertFiberToThread&lt;/a&gt;
mit welcher man einen Fiber-Thread wieder zu einem normalen Thread machen kann.
Da diese Funktion aber erst mit Server 2003 eingeführt wurde und ich Koroutinen
sowieso Thread-technisch abkapseln möchte, starte ich einen eigenen Thread für 
eine Koroutinen-Session. Wird dieser beendet, sterben seine “Fasern” mit ihm
und ich muss mir keine Gedanken über COM-Aufrufe oder Ähnliches machen.&lt;/p&gt;

&lt;h3 id=&quot;linuxposix-ucontext&quot;&gt;Linux/POSIX ucontext&lt;/h3&gt;

&lt;p&gt;POSIX hatte mit dem &lt;code&gt;ucontext.h&lt;/code&gt; Header ebenfalls ein Werkzeug bereitgestellt,
mit dem man selbst einen Stack-Block allokieren und damit einen neuen 
Aufrufkontext erstellen und dann darauf hinwechseln kann.&lt;/p&gt;

&lt;p&gt;Auch hier kann man ganz analog zu Windows Fibers mehrere Aufrufkontexte als
Teil eines Threads erstellen und dann manuell zwischen diesen hin- und 
herwechseln.&lt;/p&gt;

&lt;p&gt;Die notwendigen APIs lauten:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.man7.org/linux/man-pages/man3/makecontext.3.html&quot;&gt;makecontext&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.man7.org/linux/man-pages/man3/swapcontext.3.html&quot;&gt;swapcontext&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.man7.org/linux/man-pages/man3/getcontext.3.html&quot;&gt;getcontext&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Interessant ist, dass man den zu nutzenden Stack-Speicher mit &lt;code&gt;malloc&lt;/code&gt; selbst
bereitstellen kann, es wäre aber auch erlaubt, einfach ein paar Kilobytes des
eigenen Stack-Frames für die Koroutine einzusetzen, in dem man einfach ein
&lt;code&gt;char coroutine_stack[16384]&lt;/code&gt; in die eigene Routine schreibt.&lt;br /&gt;
Aber um Stapelüberläufe zu verhindern, sollte man eher den ersten Weg gehen.&lt;/p&gt;

&lt;p&gt;Einen fetten Nachteil gibt es leider: &lt;code&gt;ucontext&lt;/code&gt; wurde nachträglich wieder
aus dem POSIX Standard entfernt. Linux hat dieses Feature großteils 
beibehalten, aber Systeme wie OpenBSD haben es aus seiner Implementierung
gestrichen.&lt;/p&gt;

&lt;p&gt;Meine vorläufig einzige Möglichkeit für Koroutinen auf solchen Systemen 
ist der Einsatz von “echten” Threads für jede Koroutine, die einfach
schlafen gelegt werden, wenn sie einen Kontext-Wechsel einfordern.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Am Ende verstehe ich das Problem, warum C++20 hier sein ganz eigenes
Koroutinen-Konzept in die Sprache einbaut und nicht auf Bibliotheken
zurückgreift:&lt;/p&gt;

&lt;p&gt;Andere Koroutinen-Implementierungen (wie &lt;a href=&quot;http://software.schmorp.de/pkg/libcoro.html&quot;&gt;lib coro&lt;/a&gt;) 
brauchen am Ende Assembler-Blöcke für jeden möglichen CPU-Typ, um Koroutinen 
auf jede Plattform bringen zu können, weil das OS diesen Support nicht 
immer bietet, und auch Mikrocontroller sind davon ausgeschlossen.&lt;/p&gt;

&lt;p&gt;Man müsste dieses Feature also in die Core-Language aufnehmen und gegen 
solche Änderungen sträubt sich C, weil es seine Einfachheit verlieren
könnte.&lt;/p&gt;

&lt;p&gt;C++ leistet sich diesen Luxus hingegen und wird (so meine Erwartung)
vermutlich damit den bestmöglichen Koroutinen-Support anbieten können,
den man sich vorstellen kann.&lt;/p&gt;

&lt;p&gt;Ein Problem wird es aber meines Erachtens immer geben: 
Bestehende Bibliotheken oder auch Betriebssysteme kennen das C++20
Koroutinen Modell nicht und wenn man diese mit nativen Funktionen
mischt, könnten mehrere Seiteneffekt auftreten.&lt;/p&gt;

&lt;p&gt;Man denke an native Warte-Routinen oder andere eigene oder systemspezifische
Implementierungen.
Von daher würde ich Koroutinen in der Systemprogrammierung auch weiter
nicht einsetzen … und das ist schon ein bisschen Schade.
Beschränkt man sich aber auf Mathematik und nur auf &lt;code&gt;std&lt;/code&gt; Implementierung,
haben Koroutinen sicher ein ordentliches Potential.&lt;/p&gt;

&lt;p&gt;Und ich kann mit meinen Implementierung in C zumindest ein bisschen auf
dieser Welle mitreiten, wohl wissend, dass diese Variante ebenso anfällig
für Seiteneffekt ist.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>GCC Problem: Statische Shared-Libs</title>
   <link href="https://www.opengate.at/blog/2021/09/gcc-static-sharing/"/>
   <published>2021-09-12T13:00:00+02:00</published>
   <updated>2021-09-12T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2021/09/gcc-static-sharing</id>
   <category term="devel" />
   <summary type="text">Da denkt man, statische Bibliotheken
(static libraries) wären stets “privat” für ihre Nutzer und nur dynamisch 
gelinkte Bibliotheken (shared libraries) würden ihr Dienstleistungsangebot 
öffentlich preisgeben.

Doch nicht so beim GCC.
Denn der spielt gerne Twitter und teilt auch Privates quer über 
Modulgrenzen hinweg, ohne dass jemand danach gefragt hätte.
</summary>
   <content type="html">&lt;p&gt;Da denkt man, &lt;a href=&quot;https://de.wikipedia.org/wiki/Programmbibliothek#Statische_Bibliotheken&quot;&gt;statische Bibliotheken&lt;/a&gt;
(static libraries) wären stets “privat” für ihre Nutzer und nur dynamisch 
gelinkte Bibliotheken (shared libraries) würden ihr Dienstleistungsangebot 
öffentlich preisgeben.&lt;/p&gt;

&lt;p&gt;Doch nicht so beim &lt;a href=&quot;https://de.wikipedia.org/wiki/GNU_Compiler_Collection&quot;&gt;GCC&lt;/a&gt;.&lt;br /&gt;
Denn der spielt gerne Twitter und teilt auch Privates quer über 
Modulgrenzen hinweg, ohne dass jemand danach gefragt hätte.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;neulich-in-der-firma&quot;&gt;Neulich in der Firma&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;Wir haben einen Bug in einer statischen Lib gefixt. Im Test funktioniert 
alles, doch im Programm zusammen mit anderen Bibliotheken ist es so, 
als würde der Patch einfach fehlen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Wie kann es sein, dass sich eine Bibliothek stets anders verhält, 
je nachdem in welchen Prozess sie geladen wird?&lt;/p&gt;

&lt;p&gt;Die Antwort ist eine neue Art vom 
&lt;a href=&quot;https://en.wikipedia.org/wiki/Multiple_inheritance#The_diamond_problem&quot;&gt;“Diamond of Death”&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;Zwei dynamische Bibliotheken linken eine bestimmte statische Bibliothek und
dann werden beide in einen Prozess genutzt.&lt;/p&gt;

&lt;p&gt;Wird nun ein Bug in einer Lib festgestellt, der aus der gemeinsamen statischen
Lib kommt und welcher sich in der zweiten shared-lib nicht bemerkbar macht,
wird oft nur die “fehlerhafte” Bibliothek samt der statischen korrigiert.
Man liefert am Ende nur eine Patch-Datei aus, weil man die zweite für OK hält.&lt;/p&gt;

&lt;p&gt;Doch nachdem in &lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt; grundsätzlich alle 
Funktionen einer Bibliothek öffentlich sind (außer man geht dagegen explizit 
vor), werden auch die statischen Funktionen in jeder &lt;code&gt;*.so&lt;/code&gt; Datei publiziert.&lt;/p&gt;

&lt;p&gt;Und wenn ein Prozess nun beide Libs lädt, ist plötzlich eine Funktion in zwei
Implementierungen vorhanden und der Prozess entscheidet sich eben für eine und
verwirft die andere.&lt;/p&gt;

&lt;p&gt;Was wir also eigentlich wollen ist, dass jede statische Bibliothek in ihrer 
Variante in einer dynamischen Bibliothek integriert ist, damit sie unabhängig 
von einander sind.&lt;/p&gt;

&lt;script src=&quot;/blog/assets/mermaid/mermaid.min.js&quot;&gt;&lt;/script&gt;
&lt;div class=&quot;mermaid&quot;&gt;
graph TD
    L1[Shared Lib #1&lt;br /&gt;shared_func1] --static_func--&amp;gt;S1(Private Static Lib&lt;br /&gt;Local Variant X&lt;br /&gt;static_func)
    L2[Shared Lib #2&lt;br /&gt;shared_func2] --static_func--&amp;gt;S2(Private Static Lib&lt;br /&gt;Local Variant Y&lt;br /&gt;static_func)

    P((Main&lt;br /&gt;Executable))
    P --shared_func1--&amp;gt; L1
    P --shared_func2--&amp;gt; L2
&lt;/div&gt;

&lt;h3 id=&quot;problem-ein-diamant&quot;&gt;Problem: Ein Diamant&lt;/h3&gt;

&lt;p&gt;Doch leider bekommen wir nur EINE gemeinsam benutzte Variante der statischen 
Bibliothek. Sie verhält sich also genau so wie eine dynamische Bibliothek.&lt;/p&gt;

&lt;script src=&quot;/blog/assets/mermaid/mermaid.min.js&quot;&gt;&lt;/script&gt;
&lt;div class=&quot;mermaid&quot;&gt;
graph TD
    S[\Public Static Lib&lt;br /&gt;static_func/]
    L1[Shared Lib #1&lt;br /&gt;shared_func1] --static_func--&amp;gt; S
    L2[Shared Lib #2&lt;br /&gt;shared_func2] --static_func--&amp;gt; S

    P((Main&lt;br /&gt;Executable))
    P --shared_func1--&amp;gt; L1
    P --shared_func2--&amp;gt; L2
&lt;/div&gt;

&lt;p&gt;Wenn man per &lt;code&gt;nm&lt;/code&gt; in die &lt;code&gt;.so&lt;/code&gt; Dateien hineinsieht, stellt man fest, dass 
die Funktionen der statischen Bibliothek von der dynamischen exportiert
werden.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;$ nm ./libshared_lib1.so
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;...
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;0000000000001139 T shared_lib1_function
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;0000000000001154 T static_lib_function
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h3 id=&quot;lösung-privatisierung&quot;&gt;Lösung: Privatisierung&lt;/h3&gt;

&lt;p&gt;Linux und der GCC machen es sich stets einfach und exportieren grundsätzlich
alles. Das kann man aber über die Compiler-Option &lt;code&gt;-fvisibility=hidden&lt;/code&gt; 
abschalten und dann deklariert man per 
&lt;code&gt;__attribute__ ((visibility (&quot;default&quot;)))&lt;/code&gt; nur genau die Funktionen als 
“öffentlich”, die man auch als solche benutzen will. 
Siehe &lt;a href=&quot;https://gcc.gnu.org/wiki/Visibility&quot;&gt;GCC-Doku&lt;/a&gt;&lt;/p&gt;

&lt;h3 id=&quot;alternative-lokales-laden&quot;&gt;Alternative: Lokales Laden&lt;/h3&gt;

&lt;p&gt;Wenn man mit &lt;a href=&quot;https://pubs.opengroup.org/onlinepubs/000095399/functions/dlopen.html&quot;&gt;&lt;code&gt;dlopen&lt;/code&gt;&lt;/a&gt;
arbeitet, kann man auch die Option &lt;code&gt;RTLD_LOCAL&lt;/code&gt; nutzen um dem Prozess das
Publizieren von geladenen Symbolen zu untersagen. Dann sollte jede Lib nur
ihre eigenen mitgebrachten Funktionen sehen und nichts von fremden &lt;code&gt;.so&lt;/code&gt; 
Dateien.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ich habe noch nie viel davon gehalten, wenn GCC Bibliotheken ihre gesamten 
Implementierungsdetails mitveröffentlichen. Das führt nur dazu, dass 
private APIs wie öffentliche behandelt werden und beim nächsten Update
regnet es dann unter Umständen &lt;a href=&quot;https://de.wikipedia.org/wiki/Schutzverletzung&quot;&gt;Seg-Faults&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Aber dass “Teil-Patches” durch spezielle statische Bibliotheks-Konstruktionen
plötzlich “verschwinden”, war mir bisher auch noch nie so deutlich 
aufgefallen.&lt;br /&gt;
Und schließlich kann es leicht passieren, dass eine statische “Utility-Lib”
in mehreren Komponenten zum Einsatz kommt, die unterschiedlich release-t 
werden. Wenn diese Komponenten in einem Prozessraum zusammenkommen, wird das
Chaos perfekt.&lt;/p&gt;

&lt;p&gt;Man muss also immer darauf achten, dass beim Update einer statischen Lib,
auch alle von dieser abhängigen dynamischen Bibliotheken re-release-t 
werden müssen. Oder man verhindert gleich von Anfang an, dass private 
statische Funktionen plötzlich öffentlich “geteilt” werden.&lt;/p&gt;

&lt;p&gt;Wie auch immer … solche störrischen Details sind stets lästig, weil man
dann lange nach neuen Alt-Bugs an falschen Stellen sucht.&lt;/p&gt;

&lt;p&gt;Also Obacht: Immer nur das notwendigste exportieren lassen.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>flock, lockf und LockFileEx</title>
   <link href="https://www.opengate.at/blog/2021/09/flock-lockf/"/>
   <published>2021-09-11T13:00:00+02:00</published>
   <updated>2021-09-11T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2021/09/flock-lockf</id>
   <category term="devel" />
   <summary type="text">Der “exklusive” Zugriff auf Dateien spaltet die Nation der Entwickler,
wenn es darum geht, wie, wann und wo dieses Kontrollmittel eingesetzt werden
soll.

Dateisperren sind eine recht alte Erfindung und deshalb wundert es mich,
wie uneinheitlich das Thema behandelt wurde.
</summary>
   <content type="html">&lt;p&gt;Der “exklusive” Zugriff auf Dateien spaltet die Nation der Entwickler,
wenn es darum geht, wie, wann und wo dieses Kontrollmittel eingesetzt werden
soll.&lt;/p&gt;

&lt;p&gt;Dateisperren sind eine recht alte Erfindung und deshalb wundert es mich,
wie uneinheitlich das Thema behandelt wurde.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;vorgeschichte-php&quot;&gt;Vorgeschichte: PHP&lt;/h3&gt;

&lt;p&gt;Es fing in einem &lt;a href=&quot;https://de.wikipedia.org/wiki/PHP&quot;&gt;PHP&lt;/a&gt; Kurs vor 20 Jahren 
(W-T-F wo ist die Zeit hingekommen) an. Ein Gästebuch für die Homepage sollte 
entstehen, aber ohne Datenbank, nur mit Textdateien. 
(Ja, so einen Blödsinn haben wir damals alle gemacht und fanden es “cool”.)&lt;/p&gt;

&lt;p&gt;Was passiert, wenn zwei Leute gleichzeitig auf “Senden” klicken und zwei
PHP-Prozesse Daten an eine Datei anfügen?&lt;br /&gt;
Unter Windows könnte einer einen Zugriffsfehler erhalten, oder beide 
schreiben ans gleiche Dateiende und überschreiben sich gegenseitig, was
vor allem unter Linux passieren kann.&lt;/p&gt;

&lt;p&gt;Damit das nicht geschieht, sollte man die Datei mit einer “atomaren”
Sperre (also einem “Lock”) belegen, wo ein Zugriff durchkommt und der andere 
so lange warten muss, bis der erste fertig ist, damit er ans Ende schreiben
kann. Und die PHP Funktion dafür heißt &lt;a href=&quot;https://www.php.net/manual/en/function.flock.php&quot;&gt;&lt;code&gt;flock()&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Das funktionierte damals tatsächlich recht gut, und man findet immer noch 
Web 1.0 PHP Codes, die genau so ihre Daten vor parallelen Zugriffen schützten:
Quasi ein &lt;a href=&quot;https://de.wikipedia.org/wiki/Mutex&quot;&gt;Mutex&lt;/a&gt; auf Dateiebene.&lt;/p&gt;

&lt;p&gt;Und ich nutze das auf &lt;code&gt;opengate.at&lt;/code&gt; teilweise heute auch noch so.&lt;/p&gt;

&lt;h3 id=&quot;win32&quot;&gt;Win32&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows&quot;&gt;Windows&lt;/a&gt; hat seit der 
&lt;a href=&quot;https://de.wikipedia.org/wiki/MS-DOS&quot;&gt;DOS&lt;/a&gt; Zeit die Möglichkeit bereitgestellt,
Dateien exklusiv öffnen zu lassen. Eigentlich hat Windows eher Probleme mit 
“geteilten”  Zugriffen und sperrt oft mehr, als man möchte.&lt;br /&gt;
Doch nachdem der &lt;a href=&quot;https://de.wikipedia.org/wiki/C_(Programmiersprache)&quot;&gt;C Standard&lt;/a&gt; 
eher dem &lt;a href=&quot;https://de.wikipedia.org/wiki/Unix&quot;&gt;Unix&lt;/a&gt; Modell folgt, findet man 
mehrheitlich “gemeinsam” nutzbare Dateien in den Quellen der C-Laufzeit bis 
hin zu den Anwendungsprogrammen unter Windows.&lt;br /&gt;
Anders gesagt: &lt;a href=&quot;https://www.cplusplus.com/reference/cstdio/fopen/&quot;&gt;&lt;code&gt;fopen()&lt;/code&gt;&lt;/a&gt; 
nutzt intern &lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea&quot;&gt;&lt;code&gt;CreateFile()&lt;/code&gt;&lt;/a&gt; 
mit allen möglichen &lt;code&gt;FILE_SHARE_&lt;/code&gt;-Flags.&lt;/p&gt;

&lt;p&gt;Wer etwas exklusiv sperren will, tut dies in der Regel mit 
&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-lockfileex&quot;&gt;&lt;code&gt;LockFileEx()&lt;/code&gt;&lt;/a&gt;
und kann damit einzelne Bereiche einer Datei gezielt für den exklusiven 
Bedarf sperren und danach wieder freigeben.&lt;/p&gt;

&lt;p&gt;Ist eine Datei über sein &lt;code&gt;HANDLE&lt;/code&gt; gesperrt, ist es egal, ob ein zweiter 
Prozess oder ein eigener zweiter Thread darauf zugreifen möchte, denn beide
werden fehlschlagen bzw. blockieren, bis die Sperre per 
&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-unlockfile&quot;&gt;&lt;code&gt;UnlockFile&lt;/code&gt;&lt;/a&gt;
freigegeben wurde.&lt;/p&gt;

&lt;p&gt;Um eine ganze Datei zu sperren kann man Offset &lt;code&gt;0&lt;/code&gt; und für die zu sperrende 
Länge ruhig  &lt;code&gt;0xffffffffffffffff&lt;/code&gt; angeben.
Die PHP Implementierung von &lt;code&gt;flock&lt;/code&gt; benutzt unter Windows auch genau diesen
Trick, wie man in &lt;code&gt;flock_compat.c&lt;/code&gt; im PHP Quellcode schön sehen kann.&lt;/p&gt;

&lt;h3 id=&quot;posix-bsd-und-linux&quot;&gt;POSIX, BSD und Linux&lt;/h3&gt;

&lt;p&gt;Wie “cool” wäre es, wenn &lt;code&gt;flock&lt;/code&gt; eine &lt;a href=&quot;https://de.wikipedia.org/wiki/Portable_Operating_System_Interface&quot;&gt;POSIX&lt;/a&gt;
API wäre und damit auf allen Unixvarianten verfügbar wäre. Doch leider ist das
nicht so und außerdem muss man hier genau wissen, was man eigentlich will.&lt;/p&gt;

&lt;p&gt;Denn während Windows Dateien wirklich sperrt (&lt;code&gt;ReadFile()&lt;/code&gt; und &lt;code&gt;WriteFile()&lt;/code&gt;
schlagen fehl), sind Locks in Linux so genannte “advistory locks” und 
funktionieren sperrend nur beim Aufruf Sperrfunktionen selbst und nicht
bei &lt;code&gt;read()&lt;/code&gt; und &lt;code&gt;write()&lt;/code&gt;.&lt;br /&gt;
Alle Prozesse müssen also einen Lock anfordern um zu warten bis ein anderer
eine Sperre aufgibt.&lt;/p&gt;

&lt;p&gt;Jetzt gibt es zwei APIs dafür:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;flock&lt;/code&gt; ist eine &lt;a href=&quot;https://de.wikipedia.org/wiki/Berkeley_Software_Distribution&quot;&gt;BSD&lt;/a&gt; 
API, die aber auch in &lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt; und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Android_(Betriebssystem)&quot;&gt;Android&lt;/a&gt; 
normalerweise enthalten ist und wirkt auf einen geöffneten Dateideskriptor. 
&lt;code&gt;flock&lt;/code&gt; sperrt dabei die gesamte Datei und egal ob zwei Prozesse oder zwei 
Threads die gleiche Datei öffnen und sperren, nur ein Thread in einem 
Prozess kann einen exklusiven Lock zu einem Zeitpunkt halten.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;lockf&lt;/code&gt; ist eine &lt;code&gt;POSIX&lt;/code&gt; API und stellt Sperren für Bereiche innerhalb 
einer Datei bereit (also wie &lt;code&gt;LockFileEx&lt;/code&gt;).
Die Sperren wirken aber nur auf Prozess-Ebene, wenn also zwei Threads einen
exklusiven Lock auf die gleiche Datei anfordern, bekommen beide einen und
dann sind Korruptionen meist die Folge.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;“Mandatory locks” wie unter Windows sind in &lt;code&gt;POSIX&lt;/code&gt; nicht spezifiziert, wenn 
gleich man unter Linux (ohne Garantien) auch an so etwas herankommen kann.
Standard ist das dann aber keiner.&lt;/p&gt;

&lt;h3 id=&quot;gate-implementierung&quot;&gt;GATE Implementierung&lt;/h3&gt;

&lt;p&gt;Tja, der kleinste gemeinsame Nenner ist für mich ein Lock auf eine gesamte
Datei, der sowohl Thread-sicher als auch Prozess-sicher sein soll.&lt;/p&gt;

&lt;p&gt;Und das erreiche ich unter Windows mit &lt;code&gt;LockFileEx&lt;/code&gt; und unter BSD und Linux 
mit &lt;code&gt;flock&lt;/code&gt;. Sollte aber &lt;code&gt;flock&lt;/code&gt; nicht unterstüzt werden, hätte ich im
Platform-Support-Layer auch einen Fallback parat, der &lt;code&gt;lockf&lt;/code&gt; nutzt um 
&lt;code&gt;flock&lt;/code&gt; zumindest auf Prozessebene zu simulieren.&lt;/p&gt;

&lt;p&gt;Aktiv eingesetzt wird das Feature bei Logdateien. Denn so können mehrere
Threads und Prozesse in eine Datei schreiben 
ohne sich gegenseitig zu stören.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Dateisperren kommen häufiger zum Einsatz, als man glaubt. 
&lt;a href=&quot;https://conan.io/&quot;&gt;CONAN&lt;/a&gt; setzt beispielsweise Lock-Dateien für die 
Integrität seines Caches ein, damit nicht zwei CONAN Prozesse das gleiche 
Projekt parallel neu bauen können.&lt;/p&gt;

&lt;p&gt;Das Schöne an Lockdateien ist, dass sie wesentlich schneller sein können,
als wenn man alles über monolithische Zusatzdienste leitet, die dann
system-weite Mutexe einsetzen.&lt;/p&gt;

&lt;p&gt;Und dennoch bin ich enttäuscht, dass &lt;code&gt;flock&lt;/code&gt; nicht Teil von &lt;code&gt;POSIX&lt;/code&gt; ist
und generell wieder bei jedem Unix-Derivat die Raterei anfängt, welche
der Funktionen “aus Gottes Gnaden” vorhanden ist.&lt;br /&gt;
Android kann z.B. nur &lt;code&gt;flock&lt;/code&gt; und kein &lt;code&gt;lockf&lt;/code&gt; … es ist echt komisch.&lt;/p&gt;

&lt;p&gt;However … Dateisperren: Check.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Apache und PHP unter WSL</title>
   <link href="https://www.opengate.at/blog/2021/09/wsl-apache2/"/>
   <published>2021-09-06T13:00:00+02:00</published>
   <updated>2021-09-06T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2021/09/wsl-apache2</id>
   <category term="software" />
   <summary type="text">Wenn ich PHP Scripts für den Webspace bei 
mir zu Hause ausprobieren will, dann helfen mir leider der 
IIS oder 
Jana wenig. Denn schließlich möchte 
ich ja die dortige Apache2
Umgebung mit seinen typischen .htaccess Dateien genau nachstellen.

Früher hätte ich jetzt auf einen Linux
Rechner oder eine VM 
ausweichen müssen, doch heute erlaubt mir das 
Windows Subsystem für Linux
das gleiche “Feeling” ohne Zusatzaufwand.
</summary>
   <content type="html">&lt;p&gt;Wenn ich &lt;a href=&quot;https://de.wikipedia.org/wiki/PHP&quot;&gt;PHP&lt;/a&gt; Scripts für den Webspace bei 
mir zu Hause ausprobieren will, dann helfen mir leider der 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Internet_Information_Services&quot;&gt;IIS&lt;/a&gt; oder 
&lt;a href=&quot;/blog/2021/08/janaserver/&quot;&gt;Jana&lt;/a&gt; wenig. Denn schließlich möchte 
ich ja die dortige &lt;a href=&quot;https://de.wikipedia.org/wiki/Apache_HTTP_Server&quot;&gt;Apache2&lt;/a&gt;
Umgebung mit seinen typischen &lt;code&gt;.htaccess&lt;/code&gt; Dateien genau nachstellen.&lt;/p&gt;

&lt;p&gt;Früher hätte ich jetzt auf einen &lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt;
Rechner oder eine &lt;a href=&quot;https://de.wikipedia.org/wiki/Virtuelle_Maschine&quot;&gt;VM&lt;/a&gt; 
ausweichen müssen, doch heute erlaubt mir das 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Windows-Subsystem_f%C3%BCr_Linux&quot;&gt;Windows Subsystem für Linux&lt;/a&gt;
das gleiche “Feeling” ohne Zusatzaufwand.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Den für mich größten Vorteil von &lt;code&gt;WSL&lt;/code&gt; kann ich immer wieder nur aufs 
Neue betonen:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ich kann in EINEM Dateisystem parallel für Windows und Linux entwickeln.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_Studio&quot;&gt;Visual Studio&lt;/a&gt; 
(&lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_Studio_Code&quot;&gt;Code&lt;/a&gt;) läuft unter Windows 
als Editor, Linux-Builds oder &lt;a href=&quot;https://en.wikipedia.org/wiki/Jekyll_(software)&quot;&gt;Jekyll/Ruby&lt;/a&gt;
Scripts laufen in der WSL Shell.&lt;br /&gt;
Es ist einfach &lt;em&gt;genial&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Das geht natürlich auch mit dem Apache2 &lt;a href=&quot;https://de.wikipedia.org/wiki/Hypertext_Transfer_Protocol&quot;&gt;HTTP&lt;/a&gt;
Server und dem &lt;a href=&quot;https://de.wikipedia.org/wiki/PHP&quot;&gt;PHP&lt;/a&gt; Modul.&lt;br /&gt;
So sieht meine Installation dafür aus:&lt;/p&gt;

&lt;h3 id=&quot;wsl-apache-installation-unter-ubuntu-204&quot;&gt;WSL Apache Installation unter Ubuntu 20.4&lt;/h3&gt;

&lt;p&gt;Auf meinem WSL Ubuntu 20.4 sieht die Installation so aus:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;sudo apt install apache2&lt;/code&gt;&lt;br /&gt;
Apache2 Webserver wird installiert.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;sudo apt install php&lt;/code&gt;&lt;br /&gt;
Der PHP Interpreter wird installiert.
Dabei sieht man auch die Version, die die Distribution anbietet
(in meinem Fall 7.4) was man sich für später merken sollte.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;sudo apt install libapache2-mod-php&lt;/code&gt;&lt;br /&gt;
Das PHP Modul für Apache2 sorgt dafür, dass der Webserver PHP
nutzen kann.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;sudo a2enmod php7.4&lt;/code&gt;&lt;br /&gt;
Jetzt muss das PHP Modul aktiviert werden. Im Netz findet man
auch nur &lt;code&gt;sudo a2enmod php&lt;/code&gt;, was aber wegen der Version nicht
immer funktioniert. Im Zweifelsfall listet aber ein kurzes
&lt;code&gt;sudo a2enmod&lt;/code&gt; alle Module auf und fragt dann, welches man wirklich
aktivieren möchte.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;sudo a2enmod rewrite&lt;/code&gt;&lt;br /&gt;
Ich brauche zusätzlich ein aktiviertes &lt;code&gt;rewrite&lt;/code&gt; Modul um per &lt;code&gt;.htaccess&lt;/code&gt; 
ein paar Sonderfälle definieren zu können.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Als nächstes werden die Apache Konfigurationsdateien angepasst, damit ich 
von WSL aus auf meine Dateien im Windows-Laufwerk zugreifen kann.
Meine Daten liegen in Windows auf &lt;code&gt;D:\devel\projects\opengate&lt;/code&gt; und der Pfad 
ist dann unter WSL als &lt;code&gt;/mnt/d/devel/projects/opengate&lt;/code&gt; eingebunden.&lt;/p&gt;

&lt;p&gt;Zuerst erlauben wir &lt;code&gt;.htaccess&lt;/code&gt; und die Dateiauflistung des Zielverzeichnisses
in der Datei &lt;code&gt;/etc/apache2/apache2.conf&lt;/code&gt;. Dort fügt man einfach folgende Zeilen an:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&amp;lt;Directory /mnt/d/devel/projects/opengate/&amp;gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;  Options Indexes FollowSymLinks
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  AllowOverride All
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  Require all granted
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;&amp;lt;/Directory&amp;gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Und dann ändert man das Standard-Root-Verzeichnis des Webservers auf das
eigene Verzeichnis um.&lt;br /&gt;
Das kann man in der Datei&lt;br /&gt;
&lt;code&gt;/etc/apache2/sites-enabled/000-default.conf&lt;/code&gt; editieren, in dem man den 
Eintrag &lt;code&gt;DocumentRoot&lt;/code&gt; von seinem Standard &lt;code&gt;/var/www/html&lt;/code&gt; abändert.&lt;br /&gt;
Bei mir sieht das dann so aus:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&amp;lt;VirtualHost: *:80&amp;gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;  # Andere Einstellungen und Kommentare
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  DocumentRoot /mnt/d/devel/projects/opengate
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  # ... weitere Einstellungen und Kommentare
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;&amp;lt;/VirtualHost&amp;gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Tja und wenn man den Webserver dann startet mit&lt;br /&gt;
&lt;code&gt;sudo service apache2 start&lt;/code&gt; oder nach einer weiter Änderung mit&lt;br /&gt;
&lt;code&gt;sudo service apache2 restart&lt;/code&gt; neu gestartet hat, dann sollte man im Browser
unter &lt;code&gt;http://127.0.0.1/&lt;/code&gt; auch schon die eigene Seite sehen (falls mit 
&lt;code&gt;index.html&lt;/code&gt; gearbeitet wird), oder zumindest eine Verzeichnisauflistung 
auftauchen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Das tolle an WSL ist, dass die Dienste nicht automatisch starten und ich beim
nächsten PC-Neustart keine Ressourcen verliere. Natürlich muss ich immer per
&lt;code&gt;service apache2 start&lt;/code&gt; Starthilfe leisten, wenn ich wieder was austesten
will, aber das kommt ja nur gelegentlich bis selten vor.&lt;/p&gt;

&lt;p&gt;Apache im WSL ist so was von angenehm unkompliziert, vor allem wenn ich es
mit der Installation von IIS + PHP vergleiche. Das war nämlich schon immer 
ein Krampf. Heute gibt es zwar Webinstaller usw. die das vereinfachen, aber
Anpassungen von Berechtigungen und Ausführungseinstellungen sind immer noch
umständlich hinzubekommen.&lt;/p&gt;

&lt;p&gt;Von daher mal ein großes Lob an WSL, was mir den ganzen Zirkus ohne 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Docker_(Software)&quot;&gt;Docker&lt;/a&gt; und VMs in 
wenigen Minuten ermöglicht.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>ITX Gehäuse selbstgedruckt</title>
   <link href="https://www.opengate.at/blog/2021/09/itx-case-print/"/>
   <published>2021-09-05T13:00:00+02:00</published>
   <updated>2021-09-05T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2021/09/itx-case-print</id>
   <category term="hardware" />
   <summary type="text">Aus vergangenen Tagen habe ich einige ITX PC Gehäuse
in denen meine Test-Notfall- und Backupboards verbaut sind. Die liegen etwas bei Größen
von 32x27x7 cm und bieten auch für 3.5 Zoll Festplatten Platz.

Mini-ITX Boards sind aber nur 17x17 cm lang und breit. Und 2.5 SSDs oder
M2 Chips viel kleiner geworden sind, fragte ich mich, ob ich nicht auch
mit einem viel kleineren Gehäuse auskommen kann.
</summary>
   <content type="html">&lt;p&gt;Aus vergangenen Tagen habe ich einige &lt;a href=&quot;https://de.wikipedia.org/wiki/Mini-ITX&quot;&gt;ITX PC Gehäuse&lt;/a&gt;
in denen meine Test-Notfall- und Backupboards verbaut sind. Die liegen etwas bei Größen
von 32x27x7 cm und bieten auch für 3.5 Zoll Festplatten Platz.&lt;/p&gt;

&lt;p&gt;Mini-ITX Boards sind aber nur 17x17 cm lang und breit. Und 2.5 SSDs oder
M2 Chips viel kleiner geworden sind, fragte ich mich, ob ich nicht auch
mit einem viel kleineren Gehäuse auskommen kann.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Meine gefundene Lösung heißt: &lt;a href=&quot;https://de.wikipedia.org/wiki/3D-Druck&quot;&gt;3D Druck&lt;/a&gt;
des kleinst möglichen Gehäuses von &lt;a href=&quot;https://www.thingiverse.com&quot;&gt;Thingiverse&lt;/a&gt; 
von User &lt;a href=&quot;https://www.thingiverse.com/thing:1894652&quot;&gt;Daduck748&lt;/a&gt;.&lt;br /&gt;
Dabei handelt es sich um ein 18x18x5 cm großes ITX-Gehäuse, welches mir nur 
einen Bruchteil der sonst üblichen Blöcke an Platz raubt. Der Stromadapter
ist dabei natürlich extern zu betreiben.&lt;/p&gt;

&lt;p&gt;Folgende Voraussetzung brauchte man für das Gehäuse:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Ausgelegt für unter 60 Watt:&lt;br /&gt;
Meine &lt;a href=&quot;https://de.wikipedia.org/wiki/Intel_Atom9&quot;&gt;Intel Atom&lt;/a&gt; Boards kommen 
selten über 15 Watt mit SSD Betrieb und selbst mit richtigen Festplatten 
werden 25 Watt nicht überschritten.
Wer aber mehrere Laufwerke braucht und dann USB-Geräteorgien veranstalten
will kann hier aufhören weiterzulesen.&lt;/li&gt;
  &lt;li&gt;Minimalistisches Mainboard Netzteil:&lt;br /&gt;
Sie heißen auch “PICO-PSU” (Pico Power Supply Unit) und werden direkt ans 
Mainboard angesteckt. Das spart den Platz eines gesamten Netzteils weg
und man findet sie im Land der Mitte schon ab 15 Euro.
&lt;img src=&quot;/blog/assets/img/pico-psu.jpg&quot; alt=&quot;Pico-PSU&quot; /&gt;&lt;/li&gt;
  &lt;li&gt;60 Watt Strom-Adapter mit 12 Volt Spannung:&lt;br /&gt;
Die Pico-PSUs werden alle mit 12 V betrieben, folglich braucht man noch
ein externes Netzteil, das die Steckdose mit dem Board kompatibel macht.
Auch diese Teile bekommt man als Power-Supply-Adapter beim fernöstlichen
Händler ab 10 Euro pro Stück. Sie müssen den Strom nur über die üblichen
runden DC-Stecker liefern, aber ich habe noch keine gesehen, die andere
Steckerformate nutzen. Wichtig ist auch die übliche Konvention, dass in
der Mitte Strom geliefert wird und außen am Stecker GROUND liegt.
&lt;img src=&quot;/blog/assets/img/power-adapter-12v.jpg&quot; alt=&quot;12V-Power-Adapter&quot; /&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Solid-State-Drive&quot;&gt;SSD&lt;/a&gt;, eSATA oder M2:&lt;br /&gt;
Je weniger Platz der Datenträger braucht, um so besser. Zwar sind auf dem
Gehäuse-Druck auch Löcher für die Befestigung einer 2.5 Zoll Platte 
vorgesehen, doch wegen der geringen Höhe kollidiert das zumindest bei 
meinen Boards mit dem CPU Kühler. Ich musste die SSD einfach ins Gehäuse
ohne Fixierung “hineinlegen”. Das ist bei mir kein Problem, aber mit einem
noch kleinerem mSATA oder M2 Chip wäre das noch eleganter gelöst gewesen
und die SATA Kabel hätte man sich auch erspart.&lt;/li&gt;
  &lt;li&gt;PC-Schrauben:&lt;br /&gt;
Tja und final braucht man noch ein paar übliche PC-Schrauben um das Board
am Gehäuse zu fixieren und den Deckel zu fixieren.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Der Druck dauerte auf meinem &lt;a href=&quot;/blog/2019/01/ender-3/&quot;&gt;Ender-3&lt;/a&gt; 
etwas über einen Tag. Unter 10 Stunden für den Deckel und unter 16 Stunden
für die restliche Box. Doch im Vergleich zu einer Bestellung mit Zulieferung
war das immer noch verdammt schnell.
Und wenn man den Druck halbwegs gut plant, z.B. Deckel über Nacht und den
Rest dann am Morgen, dann hat man Folgetag um Mitternacht sein Gehäuse fertig.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/itx-case-printed-01.jpg&quot; alt=&quot;ITX-Case-01&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Mein früherer Mini-Server aus dem Jahr 2011 (ein D2700MUD) bietet leider
weder M2 noch mSATA Support, also ware eine normale 2.5 Zoll SSD die einzige
Alternative. Und trotzdem passte alles halbwegs in die kleine Schachtel.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/itx-case-printed-03.jpg&quot; alt=&quot;ITX-Case-03&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Am Ende musste ich nur noch zwei Kabel an einen Druckschalter anlöten und 
mit Doppelklebeband hinten neben den Steckern fixieren. Das andere Ende ging
zu den Power-Pins am Board. So kann ich das Teil “wie üblich” einschalten.&lt;/p&gt;

&lt;p&gt;Ein störendes Detail befand sich hinten auf der Anschlussleiste meines Boards.
Die (vollkommen sinnlosen) 3 Audiobuchsen sind blöderweise um 2 Millimeter
zu hoch, womit sich der Deckel nicht mehr schließen lässt.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Sorry, aber wer hat je den Line-In eines Mainboards benutzt? 
Dieser 3. Audio-Anschluss ist spätestens seit dem Ende der analogen
TV-Karten vollkommen sinnlos geworden und eben solche Karten haben in
ein ITX-Geräte nie hinein gepasst 
… also wozu wurde dieser Anschluss verbaut ???&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ich musste also 1x2 cm vom Deckel “wegschneiden”, damit der Metallblock
aus dem Deckel herausragen konnte.&lt;br /&gt;
Zum Glück schneidet aber mein Lötkolben durch den mit PLA Filament gedruckten
Deckel wie ein Messer durch Butter.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/itx-case-printed-04.jpg&quot; alt=&quot;ITX-Case-04&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ich bin recht zufrieden und werde das Gehäuse nun weiter nutzen.&lt;br /&gt;
Falls ich wieder mal eines ausdrucken wollen würde, dann würde meine Wahl
auf ein etwas höheres Modell fallen, um Platzproblemen aus dem Weg zu gehen.&lt;/p&gt;

&lt;p&gt;Natürlich wirkt das Gehäuse “billig” wegen seiner Plastiknatur, aber es ist
funktional und reicht für meine Zwecke aus.
Unter Last wird es wegen der passiven Kühlung schon recht warm da drinnen
(bis zu 70 Grad), doch das liegt innerhalb der Toleranzgrenzen.&lt;/p&gt;

&lt;p&gt;Ich denke aber trotzdem darüber nach, noch einen kleinen Lüfter einzusetzen,
der zumindest die Luft etwas durchwirbeln soll. Schließlich sollen die Chips
ja nicht andauernd in der Sauna sitzen müssen.&lt;/p&gt;

&lt;p&gt;Hmm … ein PC Gehäuse selbst “ausdrucken”.&lt;br /&gt;
Genial was heute möglich ist.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;So etwas hätte es früher einfach nicht gegeben!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;nachtrag-gehäuse-nr-2&quot;&gt;Nachtrag: Gehäuse Nr. 2&lt;/h3&gt;

&lt;p&gt;Ein Gehäuse war nicht genug. In den Folgetagen wollte ich noch ein zweites 
größeres ausprobieren. Meine Wahl fiel auf das 
&lt;a href=&quot;https://www.thingiverse.com/thing:1899854&quot;&gt;Screwless &amp;amp; silent mini ITX computer case&lt;/a&gt;,
das aus zwei zusammensteckbaren Hälften besteht.&lt;br /&gt;
Das Vorderteil kann dabei in Ausnehmungen des Hinterteil “einrasten” und 
hält so das Gehäuse stabil zusammen, ohne dass eine einzige Schraube notwendig 
wäre.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/itx-case-printed-05.jpg&quot; alt=&quot;ITX-Case-05&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Die Ausnehmung für einen Lüfter habe ich noch nicht befüllt, weil ich 
die passende Größe gar nicht besitze. Es stört mich aber auch nicht, wenn das
Teil offen bleibt, womit auch durch Passiv-Kühlung genug Luft durchströmen
kann.&lt;br /&gt;
Doch … zugegeben … hätte ich auf dieses Detail besser geachtet, wäre
meine Wahl vielleicht doch auf ein Modell gefallen, wofür ich die richtige
Lüftergröße zu Hause habe.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/itx-case-printed-06.jpg&quot; alt=&quot;ITX-Case-06&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Hier konnte ich endlich die originale Blende zwischen die Anschlüsse und das
Gehäuse klemmen, womit der Bereich nun besser geschützt ist.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/itx-case-printed-07.jpg&quot; alt=&quot;ITX-Case-07&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Die Druckzeit ging allerdings auf fast zwei Tage hoch, denn jedes Einzelteil 
brauchte an die 20 Stunden.&lt;br /&gt;
Mit der Lösung bin ich nun aber noch mehr zufrieden und das vorherige 
Gehäuse darf nun für ein weiteres meiner ITX-Board herhalten, wo es noch
besser passt.&lt;/p&gt;

&lt;p&gt;Hmm … ich frage mich, ob ich überhaupt je wieder ein ITX-Gehäuse wo
kaufen muss, denn die Druckoption ist für mich eine echte Alternative geworden.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>E3930 GPIO mit Linux</title>
   <link href="https://www.opengate.at/blog/2021/08/e3930-gpio/"/>
   <published>2021-08-28T13:00:00+02:00</published>
   <updated>2021-08-28T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2021/08/e3930-gpio</id>
   <category term="devel" /><category term="hardware" />
   <summary type="text">In meinem Intel Atom Kraftwerk 
wurde ein neuer Reaktor ans Netz angeschlossen. Und zwar ein Intel Atom E3930
im Supermicro A2SAV-2C-L Mainboard.

Denn seit 3 Jahren arbeitet dessen größerer Bruder E3940 als Server bei mir 
und deshalb wagte nie ich sein “spezielles” Feature auszuprobieren.
Beide Boards haben einen 10-Pin Header, über den 8 GPIO
Kontakte frei nach außen geleitet sind.
</summary>
   <content type="html">&lt;p&gt;In meinem &lt;a href=&quot;https://de.wikipedia.org/wiki/Intel_Atom&quot;&gt;Intel Atom&lt;/a&gt; Kraftwerk 
wurde ein neuer Reaktor ans Netz angeschlossen. Und zwar ein Intel &lt;a href=&quot;https://ark.intel.com/content/www/de/de/ark/products/96486/intel-atom-x5-e3930-processor-2m-cache-up-to-1-80-ghz.html&quot;&gt;Atom E3930&lt;/a&gt;
im Supermicro &lt;a href=&quot;https://www.supermicro.com/en/products/motherboard/A2SAV-2C-L&quot;&gt;A2SAV-2C-L Mainboard&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Denn seit 3 Jahren arbeitet dessen größerer Bruder E3940 als Server bei mir 
und deshalb wagte nie ich sein “spezielles” Feature auszuprobieren.&lt;br /&gt;
Beide Boards haben einen 10-Pin Header, über den 8 &lt;a href=&quot;https://de.wikipedia.org/wiki/GPIO&quot;&gt;GPIO&lt;/a&gt;
Kontakte frei nach außen geleitet sind.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;strong&gt;WARNUNG:&lt;/strong&gt; Wer Pins am &lt;a href=&quot;https://de.wikipedia.org/wiki/Hauptplatine&quot;&gt;Mainboard&lt;/a&gt; 
kurzschließt kann das Board zerstören. Also bitte meine beschriebenen Schritte
NICHT nachmachen bzw. nur mit größter Sorgfalt auf eigene Gefahr probieren.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Angefangen hatte es furchtbar, denn die Lieferung des Boards war ein Alptraum,
und ich hatte die Hoffnung schon aufgegeben es zu erhalten.&lt;br /&gt;
Warum sind “einige” Paketdienste in der Lage die Päckchen in einen Shop zu
bringen und darüber zu informieren und andere geben es irgend jemandem im
Wohnblock und finden nicht einmal die Zeit, eine Benachrichtigung an den
eigentlichen Empfänger abzusetzen?&lt;br /&gt;
Naja … am Ende mit einigem Herumsuchen hatte ich das Board dann doch
in meinen Händen.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/mainboard-a2sav-2c-l.jpg&quot; alt=&quot;Mainboard A2SAV-2C-L&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Schon eine Woche zuvor hatte ich mit der Suche im Netz begonnen und gehofft,
etwas über die GPIO Ansteuerung zu finden. Doch leider Fehlanzeige.&lt;/p&gt;

&lt;p&gt;Im Mainboard-Handbuch stehen die absoluten Adressen der Pins zwar beschrieben,
doch wenn man keinen &lt;a href=&quot;https://de.wikipedia.org/wiki/Ger%C3%A4tetreiber&quot;&gt;Kernel-Treiber&lt;/a&gt; 
schreibt, hilft einem das nicht. Die Frage war:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Wie kommt man im &lt;a href=&quot;https://de.wikipedia.org/wiki/Betriebssystem&quot;&gt;User-Mode&lt;/a&gt; 
da dran?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;linux-sysfs-löst-alle-probleme&quot;&gt;Linux sysfs löst alle Probleme&lt;/h3&gt;

&lt;p&gt;Wenn &lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt; eines wirklich gut kann, 
dann ist es: alles in &lt;a href=&quot;https://de.wikipedia.org/wiki/Verzeichnisstruktur&quot;&gt;Dateipfade&lt;/a&gt; 
abbilden.&lt;/p&gt;

&lt;p&gt;Wenn wir die intern zugeordneten GPIO Pin Nummern kennen und &lt;code&gt;root&lt;/code&gt; Rechte 
haben, wird die Sache einfach:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Man schreibt die GPIO Nummer in die virtuelle Datei &lt;code&gt;/sys/class/gpio/export&lt;/code&gt;
und Linux legt darauf ein Unterverzeichnis mit weiteren “Steuerdateien” an,
die den Pin konfigurieren und Bits hinein- und herausschreiben.&lt;br /&gt;
z.B.: &lt;code&gt;echo &quot;123&quot; &amp;gt; /sys/class/gpio/export&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Im GPIO-Verzeichnis (z.B.: &lt;code&gt;/sys/class/gpio/gpio123&lt;/code&gt;) liegen die Dateien
&lt;code&gt;direction&lt;/code&gt; und &lt;code&gt;value&lt;/code&gt;, die man ebenfalls Beschreiben oder Auslesen kann.&lt;/li&gt;
  &lt;li&gt;Wenn man entweder &lt;code&gt;in&lt;/code&gt; oder &lt;code&gt;out&lt;/code&gt; in die &lt;code&gt;direction&lt;/code&gt; Datei schreibt,
schaltet man den Pin entweder auf Input oder Output, also Stromfluss lesen,
oder Strom ein/ausschalten.&lt;br /&gt;
z.B.: &lt;code&gt;echo &quot;in&quot; &amp;gt; /sys/class/gpio/gpio123/direction&lt;/code&gt;&lt;br /&gt;
oder: &lt;code&gt;echo &quot;out&quot; &amp;gt; /sys/class/gpio/gpio123/direction&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;In die &lt;code&gt;value&lt;/code&gt; Datei kann man jetzt entweder die Zahlen &lt;code&gt;1&lt;/code&gt; oder &lt;code&gt;0&lt;/code&gt; 
hineinschreiben um einen Output-Pin auf &lt;code&gt;high&lt;/code&gt; oder &lt;code&gt;low&lt;/code&gt; zu schalten,
was in der Regel &lt;code&gt;3.3&lt;/code&gt; oder &lt;code&gt;0 Volt&lt;/code&gt; bedeutet.&lt;br /&gt;
&lt;code&gt;echo &quot;0&quot; &amp;gt; /sys/class/gpio/gpio123/value&lt;/code&gt;&lt;br /&gt;
Oder man liest die Datei und erhält &lt;code&gt;1&lt;/code&gt; oder &lt;code&gt;0&lt;/code&gt;, wenn eine Spannung
am Pin anliegt.&lt;br /&gt;
&lt;code&gt;cat /sys/class/gpio/gpio123/value&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Braucht man den Pin nicht mehr, schreibt man seine Nummer in die Datei
&lt;code&gt;/sys/class/gpio/unexport&lt;/code&gt; und Linux entfernt das virtuelle Unterverzeichnis
wieder.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Diese Prozedur ist beim &lt;a href=&quot;https://de.wikipedia.org/wiki/Raspberry_Pi&quot;&gt;Raspberry PI&lt;/a&gt;
und all seinen &lt;a href=&quot;https://de.wikipedia.org/wiki/Arm-Architektur&quot;&gt;ARM&lt;/a&gt; 
Geschwistern bestens bekannt. Doch ob sie auch bei &lt;a href=&quot;https://de.wikipedia.org/wiki/X86-Prozessor&quot;&gt;X86&lt;/a&gt; 
Mainboards klappt, wusste ich bisher nicht.&lt;/p&gt;

&lt;h3 id=&quot;a2sav-2c-l-gpio-header&quot;&gt;A2SAV-2C-L GPIO Header&lt;/h3&gt;

&lt;p&gt;Ärgerlich ist, dass man wenig bis gar keine Infos zu diesem GPIO Header
findet (oder vielleicht suche ich falsch…).
Denn ich konnte nicht herausfinden, wie sich die 8 Pins am Mainboard in
die Linux GPIO Nummern abbilden.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/mainboard-gpio-pins.jpg&quot; alt=&quot;GPIO Pins&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Nach dem Hochfahren von Linux (&lt;a href=&quot;https://de.wikipedia.org/wiki/Debian&quot;&gt;Debian&lt;/a&gt; 
11) lieferten alle GPIO Pins gemäß Messung gegen Ground etwa &lt;code&gt;1.8 V&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Im &lt;code&gt;/sys/class/gpio&lt;/code&gt; findet man 4 “Chip” Geräte als Verzeichnisse, 
und die Dateien &lt;code&gt;label&lt;/code&gt;, &lt;code&gt;base&lt;/code&gt; (Start-Nummer) und &lt;code&gt;ngpio&lt;/code&gt; (Nummern-Anzahl ab 
Start) geben folgende Infos preis:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;/sys/class/gpio&lt;/th&gt;
      &lt;th style=&quot;text-align: right&quot;&gt;label&lt;/th&gt;
      &lt;th style=&quot;text-align: right&quot;&gt;base&lt;/th&gt;
      &lt;th style=&quot;text-align: right&quot;&gt;ngpio&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;gpiochip267&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;INT3452:03&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;267&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;43&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;gpiochip310&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;INT3452:02&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;310&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;47&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;gpiochip357&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;INT3452:01&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;357&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;77&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;gpiochip434&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;INT3452:00&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;434&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;78&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Wir haben also 4 GPIO Bänke, die GPIO PINs ab der Nummer 267 bereitstellen
und bis einschließlich zur Nummer 511 reichen.&lt;/p&gt;

&lt;p&gt;Also habe ich mir ein kleines Script geschrieben, das bei 267 startend 
immer 10 Pins auf &lt;code&gt;out&lt;/code&gt; und &lt;code&gt;low&lt;/code&gt; schaltet. Parallel dazu habe ich immer 
per Multimeter die Spannung am Pin gemessen.&lt;/p&gt;

&lt;p&gt;Und nach ein paar Iterationen kam ich bei den Pin-Nummern 318 bis 325 an,
die offenbar meinen Mainboard Pins zugeordnet waren.&lt;/p&gt;

&lt;p&gt;Die folgende Tabelle zeigt den Pin-Header von oben nach unten, wenn das 
Mainboard so liegt, dass “oben” LAN, USB und Displayanschlüsse liegen:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: right&quot;&gt;Nummer&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Links&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Rechts&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Nummer&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;-&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;3.3 V&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;0 V&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;-&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;325&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;GP0&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;GP4&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;321&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;324&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;GP1&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;GP5&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;320&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;323&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;GP2&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;GP6&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;319&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;322&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;GP3&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;GP7&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;318&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h3 id=&quot;input-geht-aber-keine-output-spannung-möglich&quot;&gt;Input geht, aber keine Output-Spannung möglich&lt;/h3&gt;

&lt;p&gt;Spannung lesen funktioniert, denn mit&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;echo &amp;quot;318&amp;quot; &amp;gt; /sys/class/gpio/export
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;echo &amp;quot;in&amp;quot; &amp;gt; /sys/class/gpio/gpio318/direction
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;cat /sys/class/gpio/gpio318/value
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;sieht man, ob der rechte untere Pin mit Ground verbunden ist, denn dann 
liefert &lt;code&gt;value&lt;/code&gt; eine &lt;code&gt;0&lt;/code&gt;. Ist er nicht verbunden oder gegen &lt;code&gt;3.3 Volt&lt;/code&gt; 
gezogen, sehen wir &lt;code&gt;1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Damit lässt sich schon ein Taster abfragen, der den Pin mit Ground verbindet.
Drückt jemand darauf, sieht man das an der &lt;code&gt;0&lt;/code&gt;, ansonsten kommt immer &lt;code&gt;1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Im Output Modus wird der Pin mit Ground verbunden. Leider schaltet er aber
nicht auf Spannung um, wenn man eine &lt;code&gt;1&lt;/code&gt; in &lt;code&gt;value&lt;/code&gt; schreibt.&lt;br /&gt;
Der Pin ist also immer &lt;code&gt;low&lt;/code&gt;, wenn er als Output-Pin betrieben wird.&lt;/p&gt;

&lt;p&gt;Das schränkt den Handlungsspielraum natürlich stark ein.&lt;br /&gt;
Aber eine Sache bekommt man trotzdem hin:&lt;/p&gt;

&lt;p&gt;Man nehme eine blaue &lt;a href=&quot;https://de.wikipedia.org/wiki/Leuchtdiode&quot;&gt;LED&lt;/a&gt;, die 
3.3 Volt verträgt (oder eine schwächere mit Vorwiederstand) und verbindet 
damit einen GPIO Pin mit 3.3 V auf POWER. Wenn man jetzt zwischen Input und
Output Modus umschaltet, geht die LED an und aus, denn im Output &lt;code&gt;low&lt;/code&gt; Modus 
fließt Strom mit 3.3 Volt vom POWER Pin zum GPIO Pin.&lt;br /&gt;
Schaltet man aber auf Input, fließt Strom mit 1.8 Volt, was die blaue
LED sprichwörtlich kalt lässt.&lt;br /&gt;
Es fließt also immer Strom durch die Leuchtdiode, nur im Input-Modus ist er 
zu schwach um gesehen zu werden.&lt;/p&gt;

&lt;p&gt;Nutzt man eine niedriger betreibbare rote LED im Input-Modus, kann man
erkennen, dass auch die 1.8 Volt ein ganz schwaches kleines Lichtpünktchen 
auslösen.&lt;/p&gt;

&lt;h3 id=&quot;vorsicht-reboot-möglich&quot;&gt;Vorsicht, Reboot möglich&lt;/h3&gt;

&lt;p&gt;Nur als kleine &lt;strong&gt;Warnung&lt;/strong&gt; am Rande:&lt;br /&gt;
Ich habe auch weitere Pins mal auf &lt;code&gt;0&lt;/code&gt; gesetzt und irgendwo ab Nr. 340 löste
mein Mainboard einen Reboot aus. Zwischen 360 und 511 passierte nichts
Bemerkbares mehr.&lt;/p&gt;

&lt;p&gt;Entweder liegt da so um Nr. 350 eine Verbindung zum Power oder Reset-Button 
oder eine andere Funktion löst den Reboot des Systems aus.&lt;br /&gt;
Man lernt jedenfalls daraus:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Wer irgendwelche unbekannten Pins abklopft, kann böse Überraschungen 
erleben. Also immer alles vor dem Experiment sichern!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Also, diese Spielerei hat mir viel Spaß gemacht. Ohne Infos und Dokus
wurden die Funktionen geschwind &lt;em&gt;“reverse engineered”&lt;/em&gt; und zumindest ein paar
Anwendungsmöglichkeiten festgestellt.&lt;/p&gt;

&lt;p&gt;Tatsächlich könnte man sich mit der LED eine primitive Anzeige basteln.
z.B.: ein Ping jede Minute und wenn die Gegenseite erreichbar ist, leuchtet 
die LED, andernfalls nicht, oder gerne auch umgekehrt.&lt;/p&gt;

&lt;p&gt;GPIO Pins am X86 PC Mainboard sollten aus meiner Sicht überall Pflicht sein.
Viele Intel CPUs und Chipsätze bringen dieses Feature mit, nur leider sind 
so gut wie nie Pins am Mainboard nach außen gelegt.&lt;/p&gt;

&lt;p&gt;In diesem Fall muss ich SuperMicro loben, weil sie zumindest ein paar Boards
mit dieser genialen Option ausgestattet haben.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>noexcept und constexpr</title>
   <link href="https://www.opengate.at/blog/2021/08/noexcept-constexpr/"/>
   <published>2021-08-22T13:00:00+02:00</published>
   <updated>2021-08-22T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2021/08/noexcept-constexpr</id>
   <category term="devel" />
   <summary type="text">noexcept und constexpr kamen mit C++11
in den Standard und sind zwei ganz tolle Features. Doch wegen der 
Abwärtskompatibilität bleibt mir deren Nutzung im GATE Projekt eigentlich 
verwehrt.

… oder eben nicht, wenn man ein bisschen trickst.
</summary>
   <content type="html">&lt;p&gt;&lt;code&gt;noexcept&lt;/code&gt; und &lt;code&gt;constexpr&lt;/code&gt; kamen mit &lt;a href=&quot;https://en.wikipedia.org/wiki/C%2B%2B11&quot;&gt;C++11&lt;/a&gt;
in den Standard und sind zwei ganz tolle Features. Doch wegen der 
Abwärtskompatibilität bleibt mir deren Nutzung im GATE Projekt eigentlich 
verwehrt.&lt;/p&gt;

&lt;p&gt;… oder eben nicht, wenn man ein bisschen trickst.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;throw--noexcept&quot;&gt;throw() != noexcept&lt;/h3&gt;

&lt;p&gt;Im &lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_C%2B%2B&quot;&gt;MSVC&lt;/a&gt; könnte man eigentlich
fragen: Wozu braucht man &lt;a href=&quot;https://en.cppreference.com/w/cpp/language/noexcept_spec&quot;&gt;&lt;code&gt;noexcept&lt;/code&gt;&lt;/a&gt;, 
wenn die &lt;code&gt;throw()&lt;/code&gt; &lt;a href=&quot;https://docs.microsoft.com/en-us/cpp/cpp/exception-specifications-throw-cpp?view=msvc-160&quot;&gt;Exception-Specification&lt;/a&gt; 
ohnehin schon Exception deaktiviert?&lt;/p&gt;

&lt;p&gt;Es war tatsächlich eine Microsoft-spezifische Erweiterung (oder genau genommen 
eine Reduktion), die bei einer Funktion mit &lt;code&gt;throw()&lt;/code&gt; Angabe das Generieren 
von Exception-spezifischem-Binärcode einfach weggelassen hat.&lt;br /&gt;
In &lt;code&gt;MSVC&lt;/code&gt; war also das Werfen einer Exception innerhalb einer &lt;code&gt;noexcept&lt;/code&gt;
Funktion “undefiniert” bzw. crash-reif, hat dafür aber schnell Code erzeugt,
weil Exceptions nicht behandelt wurden.&lt;/p&gt;

&lt;p&gt;Doch gemäß Standard muss auf Exception zur Laufzeit immer geachtet werden:
Doch &lt;a href=&quot;https://en.cppreference.com/w/cpp/language/noexcept_spec&quot;&gt;gemäß Standard&lt;/a&gt;
muss auf Exception zur Laufzeit immer geachtet werden:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;throw()&lt;/code&gt; ist eine Laufzeit Abweisung (Runtime) und sollte eigentlich immer 
eine Exception-Behandlung im Binärcode generieren und wenn in der Funktion 
eine nicht-erwartete Exception auftritt, muss &lt;code&gt;std::unexpected()&lt;/code&gt; aufgerufen
werden, wo man seinen eigenen Handler einsetzen könnte oder im Standardfall
&lt;code&gt;std::terminate()&lt;/code&gt; am Ende herauskommt.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;noexcept&lt;/code&gt; bewirkt während der Übersetzung (Compiling) eine Prüfung, ob
interner Code Exceptions wirft und gibt Warnungen aus, wenn eine 
&lt;code&gt;noexcept&lt;/code&gt; Funktion einen nicht-&lt;code&gt;noexcept&lt;/code&gt; Code nutzt.
Ignoriert man die Warnung landet man auch bei &lt;code&gt;std::terminate()&lt;/code&gt; bei einer
Exception aber zumindest ohne weitere Umwege und ohne viel Hintergrundcode.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;const--constexpr&quot;&gt;const &amp;lt;= constexpr&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;constexpr&lt;/code&gt; legt fest, dass der Wert eines Types schon beim Kompilieren
fix feststeht und das Ergebnis konstant bleibt und damit auch z.B. in 
Templates als Parameter genutzt werden kann.&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;template&lt;/span&gt;&amp;lt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; N&amp;gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;struct&lt;/span&gt; T { };
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt; i = &lt;span style=&quot;color:#00D&quot;&gt;42&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;T&amp;lt;i&amp;gt; not_compilable;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;constexpr&lt;/span&gt; j = &lt;span style=&quot;color:#00D&quot;&gt;42&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;T&amp;lt;j&amp;gt; compilable;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;(Typische Beispiele mit Compile-Time-Faktoriellen-Berechnungen mit &lt;code&gt;constexpr&lt;/code&gt; 
sind offen gesagt ein Hohn und deshalb lasse ich sie hier weg. Denn seit dem 
Jahr 2000 schaffen es fast alle Compiler solche Funktionen auch mit einem
normalen &lt;code&gt;const&lt;/code&gt; jeglichen Laufzeitcode wegzuoptimieren.)&lt;/p&gt;

&lt;p&gt;&lt;code&gt;constexpr&lt;/code&gt; garantiert, dass das Ergebnis einer Operation konstant ist 
und bleibt und im Idealfall finden wir bei dessen Nutzung im Binärcode dann 
ebenfalls nur mehr eine CPU Operation, die einen statischen Wert nutzt.
Der Compiler kann also den Aufruf einer Funktion vollständig wegoptimieren
und während das bei &lt;code&gt;const&lt;/code&gt; alleine ein Glücksspiel ist, haben wir bei 
&lt;code&gt;constexpr&lt;/code&gt; de facto eine Garantie für dieses Optimum.&lt;/p&gt;

&lt;h3 id=&quot;makros-für-gestern&quot;&gt;Makros für Gestern&lt;/h3&gt;

&lt;p&gt;Tja, und wenn man jetzt mit MSVC 2005 kompiliert, führen &lt;code&gt;noexcept&lt;/code&gt; und 
&lt;code&gt;constexpr&lt;/code&gt; zu Fehlern, da er sie einfach nicht kennt.&lt;/p&gt;

&lt;p&gt;Doch wenn man auf alten Compilern ein einfaches&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#define&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;noexcept&lt;/span&gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;throw&lt;/span&gt;()
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#define&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;constexpr&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;nutzt, werden zumindest ein paar modernere C++ Zeilen auch in antiken 
Varianten nutzbar. Sie generieren dort zwar nicht die gleichen guten 
Ergebnisse, gestatten aber zumindest eine formal korrekte Übersetzung.&lt;/p&gt;

&lt;p&gt;So kann also problemlos &lt;code&gt;noexcept&lt;/code&gt; an Funktionen angefügt werden und andere
Funktionen dürfen &lt;code&gt;constexpr&lt;/code&gt; beim Rückgabetyp angeben.&lt;/p&gt;

&lt;p&gt;Somit kann ich zumindest ein paar neue Ausdrücke im GATE Projekt unterbringen.
Die Nutzung von &lt;code&gt;constexpr&lt;/code&gt; Werten als Template-Parameter ist und bleibt 
aber leider weiter Tabu.&lt;/p&gt;

&lt;h3 id=&quot;spezialfall-msvc-2013-normalfall-ab-msvc-2015&quot;&gt;Spezialfall MSVC 2013, Normalfall ab MSVC 2015&lt;/h3&gt;

&lt;p&gt;Und hier lernen wir wieder mal über Code-Archäologie, wie Microsoft nur 
schleppend die neuen Standards umsetzte.&lt;br /&gt;
&lt;code&gt;noexcept&lt;/code&gt; wurde erst mit MSVC 2015 voll unterstützt, also brauchen ältere
MSVC Compiler also das obige Makro.&lt;/p&gt;

&lt;p&gt;Doch leider galt &lt;code&gt;noexcept&lt;/code&gt; als reserviertes Schlüsselwort und dessen Nutzung
war in MSVC 2013 per &lt;code&gt;#define&lt;/code&gt; deshalb nicht erlaubt.&lt;/p&gt;

&lt;p&gt;Dafür musste man das Makro &lt;code&gt;_ALLOW_KEYWORD_MACROS&lt;/code&gt; auf &lt;code&gt;1&lt;/code&gt; definieren um 
künstlich generierte Compiler-Fehler abzuwehren.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;constexpr&lt;/code&gt; haben in GATE aktuell keine große Bedeutung, da viele relevante 
Konstanten im C-Teil definiert sind und eigentlich nie über Funktionen
generiert werden.&lt;br /&gt;
Und für Integer-Konstanten in Templates gibt es ein besseres kompatibleres
Feature: nämlich &lt;code&gt;enum&lt;/code&gt;. Enum Werte sind Konstanten, Header-only-tauglich
und von C89 bis C++20 perfekt unterstützt. Ich ziehe daher ein 
&lt;code&gt;enum { abc = 42 };&lt;/code&gt; einem &lt;code&gt;constexpr int abc = 42&lt;/code&gt; vor.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;noexcept&lt;/code&gt; hingegen ist sehr nützlich um besonders auf älteren Compilern 
unnötigen Exception-Overhead zu reduzieren. Vor allem die Warnung bei 
Nichteinhaltung einer &lt;code&gt;noexcept&lt;/code&gt;-Aufrufkette hilft enorm um Code sauber 
zu halten.&lt;br /&gt;
Zwar sollten klassische &lt;code&gt;extern C&lt;/code&gt; Funktionen generell als &lt;code&gt;noexcept&lt;/code&gt; 
bzw. &lt;code&gt;throw()&lt;/code&gt; angenommen werden, doch gelegentlich wird dennoch im C++
Teil Exceptioncode generiert, der nie ausgeführt werden wird. Daher sollte
der Zusatz nie fehlen, wenn man keine Exceptions einsetzt.&lt;/p&gt;

&lt;p&gt;Gerade auf 32-bit Systemen, wo Exceptionhandler über Zugriffe auf das &lt;code&gt;F&lt;/code&gt;
Segment registriert werden, reduziert man so unnötig viel sinnlosen Code.&lt;/p&gt;

&lt;p&gt;Tja … was man nicht alles aus Assembler-Dumps lernen kann …&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>JanaServer2</title>
   <link href="https://www.opengate.at/blog/2021/08/janaserver/"/>
   <published>2021-08-21T13:00:00+02:00</published>
   <updated>2021-08-21T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2021/08/janaserver</id>
   <category term="software" /><category term="retro" />
   <summary type="text">Über ein Jahrzehnt war der Jana-Server 
mein bester Freund und Helfer. Denn während man normalerweise für 
HTTP,
Proxy, 
SMPT
und Dialer vier separate 
Softwarelösungen brauchte, brachte der kostenfreie Jana-Server alle
diese Features auf einen Windows
Rechner.
</summary>
   <content type="html">&lt;p&gt;Über ein Jahrzehnt war der &lt;a href=&quot;https://de.wikipedia.org/wiki/Jana-Server&quot;&gt;Jana-Server&lt;/a&gt; 
mein bester Freund und Helfer. Denn während man normalerweise für 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Hypertext_Transfer_Protocol_Secure&quot;&gt;HTTP&lt;/a&gt;,
&lt;a href=&quot;https://de.wikipedia.org/wiki/Proxy_(Rechnernetz)&quot;&gt;Proxy&lt;/a&gt;, 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Simple_Mail_Transfer_Protocol&quot;&gt;SMPT&lt;/a&gt;
und &lt;a href=&quot;https://de.wikipedia.org/wiki/Dialer&quot;&gt;Dialer&lt;/a&gt; vier separate 
Softwarelösungen brauchte, brachte der kostenfreie Jana-Server alle
diese Features auf einen &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows&quot;&gt;Windows&lt;/a&gt;
Rechner.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;vorgeschichte&quot;&gt;Vorgeschichte&lt;/h3&gt;

&lt;p&gt;Es war wie üblich im Jahr 2000: Man kaufte sich eine PC-Monatszeitschrift
und klickte sich sofort durch die Installer der beigelegten Heft-CD.&lt;/p&gt;

&lt;p&gt;Und da tauchte dann auch irgendwann der Titel “Jana-Server” auf und bewarb
ein damals noch durchaus relevantes Feature:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ein Proxy-Server, der automatisch eine Modem-Dialup-Verbindung herstellt,
wenn ein Client eine Anfrage an das Internet stellen will.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Und nachdem “auf dem Lande” damals von Breitband noch sehr lange keine Rede 
war, ich aber trotzdem schon meine ersten paar PCs im Zimmer hatte und mit 
allen das Internet erforschen wollte, wurde dieser “Jana-Server” meine 
Zugangslösung.&lt;br /&gt;
Kein Routing, keine Firewall, nur ein Jana-Server neben dem Modem und alle
anderen PCs im Haus hatten Jana als Proxy konfiguriert.&lt;/p&gt;

&lt;h3 id=&quot;funktionen&quot;&gt;Funktionen&lt;/h3&gt;

&lt;p&gt;Jana-Server ist ein privates Software-Projekt und steht unter (janaserver.de)[https://www.janaserver.de/]
zum Download bereit. Ursprünglich lauffähig ab &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_NT_4.0&quot;&gt;Windows NT 4.0&lt;/a&gt;, 
startet die aktuellste Version aus dem Jahr 2014 ab Windows 2000 bis zum neuesten 
Windows 10.&lt;/p&gt;

&lt;p&gt;Innerhalb des Dienstes lassen sich mehrere Protokolle aktivieren und das 
geschieht über ein Webinterface (auf &lt;code&gt;http://127.0.0.1:2506&lt;/code&gt; am Jana-Rechner).&lt;br /&gt;
Dieses Webinterface ist tatsächlich die &lt;a href=&quot;https://de.wikipedia.org/wiki/Achillesferse&quot;&gt;Achillesferse&lt;/a&gt;
des Projektes, da es auf die alten Webbrowser von damals ausgelegt ist und
auf modernsten Browsern nicht immer richtig funktioniert.&lt;br /&gt;
Doch zum Glück gibt es ja noch den Kompatibilitätsmodus im 
&lt;a href=&quot;https://en.wikipedia.org/wiki/Internet_Explorer&quot;&gt;Internet Explorer&lt;/a&gt; 11.&lt;/p&gt;

&lt;p&gt;Wenn man eine Wählverbindung eingerichtet hatte, konnte Jana diese
verwalten und nur dann ins Internet gehen, wenn auch wirklich jemand etwas
daraus wollte. Und das war damals wichtig, denn Telefon-Internet war teuer.&lt;/p&gt;

&lt;p&gt;Der eingebaute Proxy nahm also Anfragen aus dem internen Netz an und 
öffnete eine richtige Internet-Verbindung. Kamen 10 Minuten lang keine 
weitere Anfragen, legte der Dienst sprichwörtlich den Hörer wieder auf.&lt;/p&gt;

&lt;p&gt;Der interne Mail Server konnte E-Mail-Konten per Zeitintervall aus dem Netz
per &lt;a href=&quot;https://de.wikipedia.org/wiki/Post_Office_Protocol&quot;&gt;POP3&lt;/a&gt; oder 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Internet_Message_Access_Protocol&quot;&gt;IMAP&lt;/a&gt; abrufen 
und bei sich lokal speichern. Im internen Netz konfigurierte man dann Jana 
als Mail-Server und empfing seine zwischengespeicherten Briefe, was ebenso 
wieder Telefonkosten reduzierte. Beim Senden fungierte Jana als SMTP Gateway
und leitete alles and die öffentlichen SMTP Server im Netz weiter.&lt;/p&gt;

&lt;p&gt;Zusätzlich konnte man noch Verzeichnisse via HTTP freigeben und sogar 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Common_Gateway_Interface&quot;&gt;CGI Programme&lt;/a&gt; auf
dem Webserver laufen lassen.&lt;br /&gt;
So habe ich lange meine &lt;a href=&quot;https://de.wikipedia.org/wiki/PHP&quot;&gt;PHP-Experimente&lt;/a&gt;
durchgeführt und es gab sogar eine &lt;a href=&quot;https://de.wikipedia.org/wiki/Active_Server_Pages&quot;&gt;ASP&lt;/a&gt;
Variante dafür. Sie war zwar nicht ganz vollständig, aber man konnte damit 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_Basic_Script&quot;&gt;VBScript&lt;/a&gt; serverseitig 
ohne &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Internet_Information_Services&quot;&gt;Microsoft IIS&lt;/a&gt;
laufen lassen.&lt;/p&gt;

&lt;p&gt;Ein FTP Server durfte in der Gruppe auch nicht fehlen und dann gab es noch
ein paar Zusätze und “Sonderprotokolle”:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Domain_Name_System&quot;&gt;DNS&lt;/a&gt;&lt;br /&gt;
Damit man eigene PCs mit Namen versehen konnte, ansonsten auch nur ein 
“Proxy” zu echten DN-Servern im Internet.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Network_News_Transfer_Protocol&quot;&gt;NNTP&lt;/a&gt;&lt;br /&gt;
Ein “News-Server”, eigentlich ein besseres &lt;a href=&quot;https://de.wikipedia.org/wiki/Reddit&quot;&gt;Reddit&lt;/a&gt;
weil dezentral, es ist nur leider am Web-Smog erstickt.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/RealPlayer&quot;&gt;RealPlayer Proxy&lt;/a&gt;&lt;br /&gt;
Dieses Web-Audio/Video Protokoll kennt heute auch keiner mehr.
Ja damals, als Briefmarken-große 3-Minute-Clips noch “geil” waren.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/SOCKS&quot;&gt;Socks 4/5 Proxy&lt;/a&gt;&lt;br /&gt;
Heute kennt man nur noch HTTP-Proxies, doch für native Protokolle konnte
früher ein Socks-Proxy TCP und sogar UDP Pakete weiterleiten.&lt;br /&gt;
Damalige Programme ließen oft SOCKS Einstellungen zu, heute sieht man sie
kaum mehr.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Hätte es Jana nicht geben, wäre mein Interesse an Netzwerken und Protokollen
schon im Keim erstickt worden. Denn wer unter &lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt;
mal einen Proxy mit Dialer verbinden wollte, brauchte sich die nächsten 
Wochenenden sonst nichts mehr vornehmen, so fu**ing anstrengend und 
fehlerhaft war das damals.&lt;/p&gt;

&lt;p&gt;Erst viele Jahre später konnte ich mit Tools wie &lt;a href=&quot;https://de.wikipedia.org/wiki/Webmin&quot;&gt;Webmin&lt;/a&gt;
etwas Vergleichbares mit Linux hinbekommen.&lt;br /&gt;
Doch mit Jana schaffte man das in wenigen Minuten, wo unter Linux immer noch 
Stunden draufgingen.&lt;/p&gt;

&lt;p&gt;Daher ist und bleibt der Jana-Server auf der Liste meiner Software-Highlights 
ganz weit oben.&lt;/p&gt;

&lt;p&gt;Heute haben diese genialen Features leider an Wert verloren, weil das Internet
sowieso überall vertreten ist und all die “guten” separaten Dienste durch
Werbung-verseuchte Webseiten ersetzt wurden.&lt;/p&gt;

&lt;p&gt;Endlich kann ich wieder einmal sagen:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Früher war doch alles besser.&lt;br /&gt;
Damals mit dem Jana-Server!&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>Dark-Mode für Win32</title>
   <link href="https://www.opengate.at/blog/2021/08/dark-mode-win32/"/>
   <published>2021-08-15T13:00:00+02:00</published>
   <updated>2021-08-15T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2021/08/dark-mode-win32</id>
   <category term="devel" />
   <summary type="text">Etwa gleichzeitig mit der Netflix-Serie Dark
hat Microsoft in Windows 10
das Dunkle Design als Dark-Mode schrittweise eingeführt und mit jedem 
halbjährigen Update weiter ausgebaut.

Doch leider nur für UWP 
Apps und das pisst mich offen gesagt sehr an. Was bitte ist so schwer, dieses 
Design auch in die klassische WinAPI
zu übernehmen?
</summary>
   <content type="html">&lt;p&gt;Etwa gleichzeitig mit der Netflix-Serie &lt;a href=&quot;https://de.wikipedia.org/wiki/Dark_(Fernsehserie)&quot;&gt;Dark&lt;/a&gt;
hat Microsoft in &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_10&quot;&gt;Windows 10&lt;/a&gt;
das &lt;code&gt;Dunkle Design&lt;/code&gt; als &lt;code&gt;Dark-Mode&lt;/code&gt; schrittweise eingeführt und mit jedem 
halbjährigen Update weiter ausgebaut.&lt;/p&gt;

&lt;p&gt;Doch leider nur für &lt;a href=&quot;https://de.wikipedia.org/wiki/Universal_Windows_Platform&quot;&gt;UWP&lt;/a&gt; 
Apps und das pisst mich offen gesagt sehr an. Was bitte ist so schwer, dieses 
Design auch in die klassische &lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_Application_Programming_Interface&quot;&gt;WinAPI&lt;/a&gt;
zu übernehmen?
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Seit &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_3.1&quot;&gt;Windows 3.1&lt;/a&gt; kenne 
ich Windows so, dass man die Farben aller Elemente der UI einstellen kann. 
Und obwohl bereits Windows XP und seine Nachfolger mit “Themes” in dieses 
klassische Feature reingepfuscht haben, war es bis Windows 7 einigermaßen 
möglich, die UI-Farben nach Wunsch anzupassen und alle “guten” Programme 
konnten diese Einstellungen auslesen und anzeigen.&lt;/p&gt;

&lt;p&gt;Und dann kam die unseelige Trennung von Win32 und UWP mit &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_8&quot;&gt;Windows 8&lt;/a&gt;
und die beiden Darstellungen drifteten auseinander. Das mag an einigen Stellen
auch gut gewesen sein und die Reduktion von “Man kann alles einstellen” 
hin zu “man kann zwischen ein paar Designs wählen” ist eigentlich ein guter
Gedanke.&lt;/p&gt;

&lt;p&gt;Nun sind wir in Windows 10 mit zwei Designs angekommen, nämlich “Hell” (Light)
und “Dunkel” (Dark). Und offen gesagt finde ich das wirklich gut.
Keine selbst fabrizierten “grünen” oder “roten” Fensterrahmen, sondern
nur noch zwei gut abgestimmte Farbklänge.&lt;/p&gt;

&lt;p&gt;Und dann vergisst man diese auf Win32 zu übertragen? Warum ??&lt;/p&gt;

&lt;h3 id=&quot;explorer-theme-ist-ein-bisschen-schwarz&quot;&gt;Explorer Theme ist ein “bisschen schwarz”&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;SetWindowTheme(hwnd, L&quot;Explorer&quot;, NULL);&lt;/code&gt; hätte eigentlich “die Lösung”
sein können. Bzw. manchmal findet man auch den Token &lt;code&gt;DarkMode_Explorer&lt;/code&gt; im
Netz. Denn wenn man diese Funktion für jedes Fenster und jedes Control 
aufruft, dann müssten doch alle so aussehen, wie der Explorer, und der 
passt sich ja neuerdings brav an den Dark-Mode an.&lt;/p&gt;

&lt;p&gt;Leider kommt damit nur an einigen Stellen plötzlich ein bisschen schwarze 
Farbe zum Vorschein. So werden z.B.: die Scrollbalken in diversen Controls
plötzlich dunkel, während der restliche Hintergrund hell bleibt.&lt;/p&gt;

&lt;h3 id=&quot;undokumentierte-uxthemedll-apis&quot;&gt;Undokumentierte uxtheme.dll APIs&lt;/h3&gt;

&lt;p&gt;Im &lt;a href=&quot;https://github.com/ysc3839/win32-darkmode&quot;&gt;GitHub Project “win32-darkmode”&lt;/a&gt;
werden für die Verdunkelung einige nicht benannte Funktionen aus &lt;code&gt;uxtheme.dll&lt;/code&gt; 
über ihre fixe ID importiert. Man nutzt also&lt;br /&gt;
&lt;code&gt;FARPROC proc = GetProcAddress(hmodule, MAKEINTRESOURCEA(ordinal));&lt;/code&gt; zum Laden.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: right&quot;&gt;Ordinal&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Prototype&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;49&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;HTHEME OpenNcThemeData(HWND hWnd, LPCWSTR pszClassList)&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;94&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;DWORD GetImmersiveColorSetCount(void)&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;95&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;DWORD GetImmersiveColorFromColorSetEx(UINT dwImmersiveColorSet, UINT dwImmersiveColorType, bool bIgnoreHighContrast, UINT dwHighContrastCacheMode)&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;96&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;DWORD GetImmersiveColorTypeFromName(const WCHAR *name)&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;98&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;DWORD GetImmersiveUserColorSetPreference(bool bForceCheckRegistry, bool bSkipCheckOnFail)&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;100&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;WCHAR** GetImmersiveColorNamedTypeByIndex(UINT dwImmersiveColorType)&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;104&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;void RefreshImmersiveColorPolicyState(void)&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;106&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;BOOL GetIsImmersiveColorUsingHighContrast(IMMERSIVE_HC_CACHE_MODE mode)&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;132&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;BYTE ShouldAppsUseDarkMode(void)&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;133&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;BOOL AllowDarkModeForWindow(HWND hWnd, BOOL allow)&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;135&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;BOOL AllowDarkModeForApp(BOOL allow)&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;135&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;PREFERREDAPPMODE SetPreferredAppMode(PREFERREDAPPMODE appMode)&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;136&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;VOID FlushMenuThemes(void)&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;137&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;BOOL IsDarkModeAllowedForWindow(HWND hWnd)&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;138&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;BOOL ShouldSystemUseDarkMode(void)&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;139&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;BOOL IsDarkModeAllowedForApp(void)&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Und dann schalten APIs wie &lt;code&gt;SetPreferredAppMode()&lt;/code&gt; und &lt;code&gt;AllowDarkModeForWindow()&lt;/code&gt; 
(theoretisch) die App oder das Fenster in den Dark-Mode um, falls 
&lt;code&gt;ShouldSystemUseDarkMode()&lt;/code&gt; diesen auch als aktiviert meldet.&lt;br /&gt;
Ordinal 135 hat dabei schon einen Wandel erlebt, weil es vor Windows 10/19H1 
(Build 18362) als &lt;code&gt;AllowDarkModeForApp()&lt;/code&gt; nur einen Schalter umlegte und ab
19H1 mit &lt;code&gt;SetPreferredAppMode()&lt;/code&gt; per Enumeration mehr Optionen anbot.&lt;/p&gt;

&lt;p&gt;Das findet man aber alles unter &lt;a href=&quot;https://github.com/ysc3839/win32-darkmode&quot;&gt;github.com/ysc3839/win32-darkmode&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Doch leider reicht das immer noch nicht. Denn nun hat man zwar dunkle 
Buttons und dunkle Menüeinträge, doch die meisten Controls und die 
Menüzeile selbst bleiben weiß bzw. klassisch.&lt;/p&gt;

&lt;h3 id=&quot;eigene-farbanpassungen-tun-den-rest&quot;&gt;Eigene Farbanpassungen tun den Rest&lt;/h3&gt;

&lt;p&gt;Meine vorläufige Lösung sieht daher so aus (wie auch oft im Netz beschrieben),
dass man per &lt;code&gt;IsDarkModeAllowedForWindow()&lt;/code&gt; fragt, ob das Fenster in den 
Dark-Mode versetzt wurde und dann wird in der &lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/winmsg/window-procedures&quot;&gt;&lt;code&gt;WNDPROC&lt;/code&gt;&lt;/a&gt;
beim Zeichnen eine andere Text- und Hintergrundfarbe genutzt.&lt;/p&gt;

&lt;p&gt;Windows hat das schon seit seinen Anfängen vorgesehen und mit Messages wie
&lt;code&gt;WM_CTLCOLORBTN&lt;/code&gt;, &lt;code&gt;WM_CTLCOLOREDIT&lt;/code&gt;, &lt;code&gt;WM_CTLCOLORLISTBOX&lt;/code&gt;, &lt;code&gt;WM_CTLCOLORSCROLLBAR&lt;/code&gt;
&lt;code&gt;WM_CTLCOLORMSGBOX&lt;/code&gt;, &lt;code&gt;WM_CTLCOLORDLG&lt;/code&gt; und &lt;code&gt;WM_CTLCOLORSTATIC&lt;/code&gt; kann man
die Standardfarben von Controls in seinem Elternfenster abändern.&lt;br /&gt;
Man setzt also quasi im Fensterrahmen-Code die Farben der Kindelemente.&lt;/p&gt;

&lt;p&gt;Wenn man das nun auch noch mit den “richtigen” Farben des Dark-Mode tut
(siehe &lt;code&gt;GetImmersiveColorFromColorSetEx()&lt;/code&gt;), dann kommt man den Farben 
des dunklen Windows Explorers schon recht nahe. Nur die fu**ing 
Menüzeile bleibt leider weiter weiß.&lt;br /&gt;
Welche Farben jetzt aber die “richtigen” sind, habe ich noch nicht 
klar herausbekommen, denn die Text-Token sind alles andere als eindeutig.
In einem &lt;a href=&quot;https://social.msdn.microsoft.com/Forums/en-US/16b70775-d87e-42d3-aa8f-41d7d6888c66/how-to-get-colors-of-default-app-mode-quotdarkquot-in-my-win32-app?forum=windowsgeneraldevelopmentissues&quot;&gt;Forum-Artikel&lt;/a&gt;
liegt zwar ein schöner Demo-Code um alle aufzulisten, aber was daraus 
jetzt eine “richtige” Listbox darstellt ist nicht dokumentiert.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/dark-mode-vtxtedit.png&quot; alt=&quot;Dark-Mode vTxtEdit&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Andere Programme definieren das offenbar auch selbst und arbeiten generell
nur mit der öffentlichen Theme-API.
So können sie den Dark-Mode auch in Windows 7 selbst implementieren und per
Programm-Option ein und ausschalten.&lt;br /&gt;
Das ist eigentlich auch ein interessanter Ansatz, aber es sieht dann
zwangsläufig auch etwas anders aus im Vergleich zum System-Standard.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Wie schon gesagt … ich bin angepisst.&lt;/p&gt;

&lt;p&gt;Denn eben wegen solchen fehlenden APIs bringt man Entwickler dazu, ihre eigene
Variante nachzubauen … und die wird dann immer schlecht gewartet und 
produziert im Nachgang Fehler.&lt;/p&gt;

&lt;p&gt;Es wäre für MS leicht gewesen, den Dark-Mode auch auf die Standard-Controls
anzuwenden, am besten mit dem bekannten “Explorer” Theme. Aber nein.&lt;/p&gt;

&lt;p&gt;Und warum sind APIs wie &lt;code&gt;AllowDarkModeForWindow()&lt;/code&gt; undokumentiert und nicht
Teil der offiziellen API?&lt;br /&gt;
Ich verstehe es einfach nicht.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>CONAN und Remote Debugging</title>
   <link href="https://www.opengate.at/blog/2021/08/conan-remote-debugger/"/>
   <published>2021-08-14T13:00:00+02:00</published>
   <updated>2021-08-14T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2021/08/conan-remote-debugger</id>
   <category term="devel" /><category term="software" />
   <summary type="text">Neulich hat mich noch das Debugging in Visual Studio von CONAN
Projekten beschäftigt und eine einfache CMake
Variable löste das Rätsel.

Doch wie geht man das Problem unter 
Linux an?
Oder: Wie löst man das Abhängigkeitsproblem mit 
Visual Studio Code?
</summary>
   <content type="html">&lt;p&gt;Neulich hat mich noch das &lt;a href=&quot;/blog/2021/07/conan-msvc-debugger/&quot;&gt;Debugging in Visual Studio von CONAN&lt;/a&gt;
Projekten beschäftigt und eine einfache &lt;a href=&quot;https://de.wikipedia.org/wiki/CMake&quot;&gt;CMake&lt;/a&gt;
Variable löste das Rätsel.&lt;/p&gt;

&lt;p&gt;Doch wie geht man das Problem unter 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt; an?&lt;br /&gt;
Oder: Wie löst man das Abhängigkeitsproblem mit 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_Studio_Code&quot;&gt;Visual Studio Code&lt;/a&gt;?
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Das “normale” &lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_Studio&quot;&gt;Visual Studio&lt;/a&gt; 
bietet zwar seit einiger Zeit Linux Debugging an, aber man muss dafür eigene 
Projekte generieren, was mit &lt;code&gt;CMake&lt;/code&gt; aktuell schlecht bzw. gar nicht 
zusammenspielt.&lt;br /&gt;
Oder man hängt sich in ein bereits “vorbereitetes” &lt;code&gt;CMake&lt;/code&gt; Projekt via 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Secure_Shell&quot;&gt;SSH&lt;/a&gt; rein, aber genau das 
funktioniert wieder nicht mit Projekten, wo CMake seine Abhängigkeiten von 
&lt;a href=&quot;https://conan.io/&quot;&gt;CONAN&lt;/a&gt; hereinbekommt.&lt;/p&gt;

&lt;p&gt;Nachdem Visual Studio Code nun endlich auch am &lt;a href=&quot;https://de.wikipedia.org/wiki/Raspberry_Pi&quot;&gt;Raspberry PI&lt;/a&gt;
halbwegs stabil läuft, bin ich mehr und mehr von &lt;a href=&quot;https://de.wikipedia.org/wiki/Code::Blocks&quot;&gt;CodeBlocks&lt;/a&gt;
und &lt;a href=&quot;https://de.wikipedia.org/wiki/KDevelop&quot;&gt;K-Develop&lt;/a&gt; zu VS-Code 
übergegangen.&lt;br /&gt;
Das war anfangs mühsam weil diese “leere” IDE mit seinen zusammengestückelten
Tasks-Aufrufen den “richtigen” IDEs unterlegen war.&lt;br /&gt;
Langsam gewöhne mich aber daran und je länger man damit arbeitet um so eher
akzeptiert man diese Eigenheiten.&lt;/p&gt;

&lt;h3 id=&quot;das-conan-dependency-problem&quot;&gt;Das CONAN Dependency Problem&lt;/h3&gt;

&lt;p&gt;Wenn &lt;code&gt;CONAN&lt;/code&gt; unser &lt;code&gt;CMake&lt;/code&gt; aufruft um die Projektstrukturen zu generieren, 
werden Include- und Link-Pfade korrekt gesetzt und die Builds sollten damit 
auch super laufen. Doch wenn man das fertige Programm im &lt;a href=&quot;https://de.wikipedia.org/wiki/Debuggen&quot;&gt;Debugger&lt;/a&gt;
durchlaufen lassen will, schlägt der &lt;code&gt;CONAN&lt;/code&gt; Hammer wieder zu:&lt;br /&gt;
Alle abhängigen Komponenten (&lt;code&gt;*.dll&lt;/code&gt;, &lt;code&gt;*.so&lt;/code&gt;) liegen im &lt;code&gt;CONAN&lt;/code&gt; Cache und das
gebaute Programm steht alleine da.&lt;/p&gt;

&lt;p&gt;Die Lösung ist mit &lt;code&gt;conan install .... -g virtualrunenv&lt;/code&gt; diverse Scripts zu
generieren, die alle Abhängigkeiten in den Pfad (&lt;code&gt;PATH&lt;/code&gt;, &lt;code&gt;LD_LIBRARY_PATH&lt;/code&gt;, 
&lt;code&gt;DYLD_LIBRARY_PATH&lt;/code&gt;) laden können.&lt;/p&gt;

&lt;p&gt;Das Problem bei diversen IDEs und auch VS-Code ist, dass ein Debugging-Prozess
nichts von diesen &lt;code&gt;CONAN&lt;/code&gt; Script weis und das zu debuggende Programm falsch
startet und gleich wieder abbrechen muss.&lt;/p&gt;

&lt;h3 id=&quot;lösung-environment-in-den-debugger-importieren&quot;&gt;Lösung: Environment in den Debugger importieren&lt;/h3&gt;

&lt;p&gt;Wenn man nach einem ausgeführten &lt;code&gt;conan instal .... -g virtualrunenv&lt;/code&gt; gleich
im Anschluss &lt;code&gt;source activate_run.sh&lt;/code&gt; aufruft, hat man die notwendigen
Environment Variablen für eine Debugging-Session in der Shell gesetzt.
Man kann sich diesen Zustand z.B. per 
&lt;code&gt;echo LD_LIBRARY_PATH=$LD_LIBRARY_PATH &amp;gt; saved_paths.env&lt;/code&gt;
sichern.&lt;br /&gt;
Kaum ist die Ausführung abgeschlossen gehen die Variablen wieder verloren,
aber die &lt;code&gt;.env&lt;/code&gt; Datei bleibt.&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;launch.json&lt;/code&gt; kann man durch das Feld &lt;code&gt;envFile&lt;/code&gt; die zuvor gesicherten 
Variablen zurückholen und in der Debug-Session benutzen.
Und schon kann ein debug-tes Programm seine &lt;code&gt;CONAN&lt;/code&gt; Abhängigkeiten finden.&lt;/p&gt;

&lt;p&gt;Wenn das Programm auch eigene parallel geladene Libs laden können muss,
dann kann man diese Pfade auch selbst zusammenstellen und per Shell-Script
in der &lt;code&gt;env&lt;/code&gt; Datei anfügen. z.B.: mit&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;source activate_run.sh &amp;amp;&amp;amp; echo \
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;  LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/path/to/target/dir:/path/to/special/dir \
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  &amp;gt;my-conan.env
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Und so kann das ganze dann am Ende aussehen:&lt;/p&gt;
&lt;div class=&quot;language-json highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;t&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;s&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;k&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;s&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;j&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;s&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;o&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;n&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;2.0.0&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;tasks&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: [
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;    {
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;label&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;conan-install&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;shell&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;command&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: [
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;        &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;conan install ${workspaceFolder} -if ${workspaceFolder}/build&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;        &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt; &amp;amp;&amp;amp; conan install ${workspaceFolder} &lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;             &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;-if ${workspaceFolder}/build -g virtualrunenv&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;        &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt; &amp;amp;&amp;amp; source ${workspaceFolder}/build/activate_run.sh&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;        &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt; &amp;amp;&amp;amp; echo &lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;             &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;LD_LIBRARY_PATH=${workspaceFolder}/build/bin:$LD_LIBRARY_PATH &lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;             &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;&amp;gt;${workspaceFolder}/build/conan-libs.env&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;        &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt; &amp;amp;&amp;amp; echo DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH &lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;             &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;&amp;gt;&amp;gt;${workspaceFolder}/build/conan-libs.env&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;      ]
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;    },
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;    {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n21&quot; name=&quot;n21&quot;&gt;21&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;label&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;conan-build&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n22&quot; name=&quot;n22&quot;&gt;22&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;shell&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n23&quot; name=&quot;n23&quot;&gt;23&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;command&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: [ 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n24&quot; name=&quot;n24&quot;&gt;24&lt;/a&gt;&lt;/span&gt;        &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;conan build -if ${workspaceFolder}/build &lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n25&quot; name=&quot;n25&quot;&gt;25&lt;/a&gt;&lt;/span&gt;               &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;-bf ${workspaceFolder}/build &lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n26&quot; name=&quot;n26&quot;&gt;26&lt;/a&gt;&lt;/span&gt;               &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;-sf ${workspaceFolder} ${workspaceFolder}&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; ],
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n27&quot; name=&quot;n27&quot;&gt;27&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;problemMatcher&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: [ ],
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n28&quot; name=&quot;n28&quot;&gt;28&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;group&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n29&quot; name=&quot;n29&quot;&gt;29&lt;/a&gt;&lt;/span&gt;        &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;kind&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;build&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n30&quot; name=&quot;n30&quot;&gt;30&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;        &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;isDefault&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;color:#088&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n31&quot; name=&quot;n31&quot;&gt;31&lt;/a&gt;&lt;/span&gt;      }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n32&quot; name=&quot;n32&quot;&gt;32&lt;/a&gt;&lt;/span&gt;    }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n33&quot; name=&quot;n33&quot;&gt;33&lt;/a&gt;&lt;/span&gt;  ]
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n34&quot; name=&quot;n34&quot;&gt;34&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div class=&quot;language-json highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;l&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;u&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;n&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;c&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;h&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;j&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;s&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;o&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;n&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;0.2.0&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;configurations&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: [
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;    {
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;(gdb) Launch&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;cppdbg&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;request&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;launch&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;program&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;${workspaceFolder}/build/bin/my_binary&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;args&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: [],
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;stopAtEntry&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;color:#088&quot;&gt;false&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;cwd&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;${workspaceFolder}/build/bin&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;environment&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: [],
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;externalConsole&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;color:#088&quot;&gt;false&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;MIMode&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;gdb&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;setupCommands&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: [
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;        {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;          &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;description&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Enable pretty-printing for gdb&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;          &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;text&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;-enable-pretty-printing&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;          &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;ignoreFailures&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;color:#088&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n21&quot; name=&quot;n21&quot;&gt;21&lt;/a&gt;&lt;/span&gt;        },
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n22&quot; name=&quot;n22&quot;&gt;22&lt;/a&gt;&lt;/span&gt;      ],
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n23&quot; name=&quot;n23&quot;&gt;23&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#606&quot;&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;envFile&lt;/span&gt;&lt;span style=&quot;color:#404&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;${workspaceFolder}/build/conan-libs.env&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n24&quot; name=&quot;n24&quot;&gt;24&lt;/a&gt;&lt;/span&gt;    }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n25&quot; name=&quot;n25&quot;&gt;25&lt;/a&gt;&lt;/span&gt;  ]
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n26&quot; name=&quot;n26&quot;&gt;26&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Nun, Mission erfüllt. Wieder ein &lt;code&gt;CONAN&lt;/code&gt; Brocken aus dem Weg geräumt …
oder sagen wir mal, wir haben einen Workaround dafür gefunden.&lt;/p&gt;

&lt;p&gt;Mir wäre es lieber, es gäbe ein &lt;code&gt;CONAN&lt;/code&gt;-Plugin, dass sich um solche lästigen
Details automatisch kümmert, doch aktuell schafft man mit Boardmitteln
nur kleine Hello-World &lt;code&gt;CONAN&lt;/code&gt; Programme zu debuggen.&lt;br /&gt;
Sobald die Abhängigkeiten zunehmen bleibt einem (laut meinem aktuellen Stand)
nichts anderes übrig, als per Scripts alles so hinzubiegen, 
dass es halbwegs läuft.&lt;/p&gt;

&lt;p&gt;Das ist zwar aus meiner Sicht unbefriedigend … aber zumindest ist
es mal ein Anfang.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Windows Impersonation Bugs</title>
   <link href="https://www.opengate.at/blog/2021/08/impersonation/"/>
   <published>2021-08-08T13:00:00+02:00</published>
   <updated>2021-08-08T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2021/08/impersonation</id>
   <category term="devel" /><category term="retro" />
   <summary type="text">In seiner langen Geschichte hat Windows
leider immer wieder bewiesen, wie ein Feature zum Bug werden kann.

Dazu fällt mir immer eine Anekdote zum IIS
mit ActiveX ein und wie ich lernen 
musste, dass “Plugins” ein wahrer Teufel sein können.
</summary>
   <content type="html">&lt;p&gt;In seiner langen Geschichte hat &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows&quot;&gt;Windows&lt;/a&gt;
leider immer wieder bewiesen, wie ein Feature zum Bug werden kann.&lt;/p&gt;

&lt;p&gt;Dazu fällt mir immer eine Anekdote zum &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Internet_Information_Services&quot;&gt;IIS&lt;/a&gt;
mit &lt;a href=&quot;https://de.wikipedia.org/wiki/ActiveX&quot;&gt;ActiveX&lt;/a&gt; ein und wie ich lernen 
musste, dass “Plugins” ein wahrer Teufel sein können.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Ich hatte schon in meiner &lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_Basic_Classic&quot;&gt;Visual-Basic&lt;/a&gt; 
Zeit den Traum, die eigene Software durch Fremdkomponenten erweitern zu 
können. Das ging im klassischen VB natürlich nur durch &lt;code&gt;ActiveX&lt;/code&gt; Komponenten.&lt;/p&gt;

&lt;p&gt;Und nachdem Microsoft die VB6 IDE damals “teuer” verkaufte, erdachte ich mir
einen Weg, wie man das kostenlos (bzw. lizenzfrei) ebenso erreichen konnte,
und das war:
&lt;a href=&quot;https://archive.org/details/VB5CCE&quot;&gt;VB5CCE&lt;/a&gt;, 
Visual Basic 5 Control Creation Edition.&lt;/p&gt;

&lt;p&gt;Microsoft hatte so um das Jahr 1996/97 herum parallel zu Visual Basic 5
eine kostenfreie verkleinerte IDE herausgebracht, mit der man keine fertigen
Programme, sondern nur reine Active-X Controls entwickeln konnte.&lt;br /&gt;
Das war offenbar damals “der heiße Scheiß” für den Internet Information Server
und den &lt;a href=&quot;https://de.wikipedia.org/wiki/Internet_Explorer&quot;&gt;Internet Explorer&lt;/a&gt; 
4 und 5, die solche Active-X Controls herunterladen und ausführen konnten.&lt;/p&gt;

&lt;p&gt;Noch 5 Jahre später wurde die VB5CCE immer noch Heft-CDs beigelegt, um 
Programmieranfängern eine kostenfrei Übungsumgebung bereitstellen zu können.
Und eben da wurde ich (verspätet) ebenso darauf aufmerksam.&lt;/p&gt;

&lt;p&gt;ActiveX Controls (&lt;code&gt;*.ocx&lt;/code&gt; Dateien) mussten genau wie andere
&lt;a href=&quot;https://de.wikipedia.org/wiki/Component_Object_Model&quot;&gt;COM&lt;/a&gt; DLLs per 
&lt;code&gt;regsvr32&lt;/code&gt; registriert werden und obgleich VB5CEE einen Build nur zuließ,
wenn mindestens ein grafisches “Control” drinnen war, so gestattete es, dass
parallel auch eine beliebige Anzahl von nicht-grafischen Klassen ebenso
per COM exportiert werden durften.&lt;br /&gt;
So konnte man also “gratis” COM-Klassen implementieren und per VB5CCE
in nativen Code kompilieren.&lt;/p&gt;

&lt;h3 id=&quot;der-reverttoself-bug&quot;&gt;Der RevertToSelf Bug&lt;/h3&gt;

&lt;p&gt;Früher war Software noch effizient und mit Ressourcen wurde sparsam
umgegangen. Doch diese Stärke wurde beim IIS schnell zur Schwäche.
Denn auch dort dachte man, dass man in &lt;a href=&quot;https://de.wikipedia.org/wiki/Active_Server_Pages&quot;&gt;ASP&lt;/a&gt;
(dem Server-VB-Dialekt) native COM-Komponenten laden und ausführen kann.&lt;/p&gt;

&lt;p&gt;Der &lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_Script_Host&quot;&gt;Windows Scripting Host&lt;/a&gt; 
hatte es vorgemacht, wie aufwendige Funktionen in C++ oder VB geschrieben 
wurden und ASP-Script Code dann einfach Methoden der nativen Objekte aufrief.&lt;/p&gt;

&lt;p&gt;“Security” wurde bei Microsoft natürlich immer schon &lt;em&gt;GROSS&lt;/em&gt; geschrieben
(Vorsicht: Ironie) und so wurde jeder Thread im IIS mit APIs wie
&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/securitybaseapi/nf-securitybaseapi-impersonateloggedonuser&quot;&gt;&lt;code&gt;ImpersonateLoggedOnUser&lt;/code&gt;&lt;/a&gt; 
auf einen nicht privilegierten Account oder den per Web-Login übermittelten 
Account gesetzt, damit er auch keine kritischen Daten lesen kann, 
die ihn nichts angehen.&lt;/p&gt;

&lt;p&gt;Hatte nun aber ein kluger Entwickler in seinem über ASP eingebundenen 
COM-Plugin das Bedürfnis mehr Daten auszulesen, dann führte er einfach
den Aufruf &lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/securitybaseapi/nf-securitybaseapi-reverttoself&quot;&gt;&lt;code&gt;RevertToSelf&lt;/code&gt;&lt;/a&gt;
aus und schon hatte der Thread &lt;code&gt;LOCALSYSTEM&lt;/code&gt; Rechte … also die höchste 
Berechtigungsstufe überhaupt. Und am Domänencontroller war das noch schlimmer.&lt;/p&gt;

&lt;p&gt;Das kam daher, dass der IIS Host Dienst (wie die meisten Systemdienste)
als &lt;code&gt;LOCALSYSTEM&lt;/code&gt; ausgeführt wurde und ASP Aufgaben in seinen Threads
liefen. Die ASP-VBScript Schnittstellen waren damit natürlich auf den
Account beschränkt, mit dem der Thread “impersonated” wurde, doch
native Plugins konnten &lt;code&gt;LOCALSYSTEM&lt;/code&gt; mit einem Aufruf zurückerobern 
und dann recht viel Blödsinn damit anstellen.&lt;/p&gt;

&lt;h3 id=&quot;plugins-richtig-auslagern&quot;&gt;Plugins richtig auslagern&lt;/h3&gt;

&lt;p&gt;Aus diesem damals publik gewordenen Bug habe ich gelernt, dass Plugins
IMMER eine Bedrohung für ein System sind. Man muss Maßnahmen ergreifen,
dass kein ungeprüfter Fremdcode im Kontext der eigenen Anwendung 
ausgeführt werden darf.&lt;br /&gt;
Und das gilt erst Recht, wenn man &lt;a href=&quot;https://de.wikipedia.org/wiki/Windows-Systemdienst&quot;&gt;Dienste&lt;/a&gt;
(Services, Daemons) entwickelt.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;em&gt;Prozess-Isolation&lt;/em&gt;&lt;br /&gt;
Davon abgesehen, dass “Thread-Isolation” wie im obigen Beispiel nur
unter Windows funktioniert und damit nicht portierbar ist, gibt es 
auch andere Gründe im eigenen Prozessraum keinen (oder möglichst wenig)
Fremdcode auszuführen.&lt;br /&gt;
“Globale Zustände” wie Ausführungsprioritäten (&lt;code&gt;nice()&lt;/code&gt;), Zugriffsmasken 
(&lt;code&gt;umask()&lt;/code&gt;) oder regionale Einstellungen (&lt;code&gt;setlocale()&lt;/code&gt;) werden in Threads
gesetzt, strahlen aber (je nach OS und Implementierung) auf den ganzen 
Prozess aus und bringen dann andere Komponenten durcheinander.&lt;br /&gt;
Es macht also Sinn, hierfür einen eigenen Prozess zu starten, das Plugin
dort zu starten und z.B. über Pipes mit ihm zu “reden”.&lt;br /&gt;
Außerdem kann man Prozesse mit weniger Rechten starten, die dann keine
Chance haben, Privilegien zurückzuerobern.&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;Signaturprüfung&lt;/em&gt;&lt;br /&gt;
Damit Fremdcode nicht einfach “eingespeist” werden kann, sollte man vor
dem Laden eines Plugins eine Form von digitaler Signatur darin auslesen
und überprüfen.&lt;br /&gt;
Das kann auch über das Betriebssystem gemacht werden, setzt aber voraus,
dass Signaturschlüssel entsprechend installiert sind und die eigene
Laderoutine diese Prüfung auch nicht umgeht.&lt;br /&gt;
Oder man überlegt sich selbst so ein Schema und erwartet, dass die
Plugin-Binärdatei eine Signatur im Anhang hat, die man gegen seinen
eigenen Erwartungswert vor dem Laden prüft.&lt;br /&gt;
Dass das natürlich alles kryptographisch gut ausgearbeitet und geprüft
sein muss, versteht sich von selbst.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Es sind also wieder diese “typischen” Bugs von vor 20 Jahren, die mir auch
heute durch den Kopf gehen, wenn es um die Planung von neuer Software geht.
Und leider machen viele Architekten den Fehler, dass sie immer nur an 
Flexibilität denken um Software möglichst “erweiterbar” zu gestalten.&lt;/p&gt;

&lt;p&gt;Genau dann wiederholen sich solche Dinge wie damals und auch noch so 
moderne Software wird anfällig für Angriffe.&lt;/p&gt;

&lt;p&gt;Was das anbelangt, war weder früher noch heute alles besser.&lt;br /&gt;
Wir irren uns leider nur langsam voran.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>2. Impfung mit Nebenwirkungen</title>
   <link href="https://www.opengate.at/blog/2021/08/corona-vaccine-2/"/>
   <published>2021-08-07T13:00:00+02:00</published>
   <updated>2021-08-07T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2021/08/corona-vaccine-2</id>
   <category term="general" />
   <summary type="text">
  Liebes Corona-Tagebuch.
Am Dienstag habe ich meine zweite Impfung erhalten.
Und danach ist es mir echt dreckig gegangen.


Das gute daran ist, dass man bei mir nun sicher sagen kann, 
dass die Impfung gewirkt hat.
</summary>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;Liebes Corona-Tagebuch.&lt;br /&gt;
Am Dienstag habe ich meine zweite Impfung erhalten.
Und danach ist es mir echt dreckig gegangen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Das gute daran ist, dass man bei mir nun sicher sagen kann, 
dass die Impfung gewirkt hat.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;2-pilgerfahrt-zum-austria-center&quot;&gt;2. Pilgerfahrt zum Austria Center&lt;/h3&gt;

&lt;p&gt;Wie schon beim letzten Mal war auch meine 2. &lt;a href=&quot;https://de.wikipedia.org/wiki/COVID-19-Pandemie&quot;&gt;Corona COVID-19&lt;/a&gt;
Impfung im Austria-Center gebucht und so wie schon beim ersten Stich wurde 
ich quasi durchgewunken, lief wieder die Schlangenwege rund um die 
Registrierungscontainer durch, zeigte Anmelde-Formular und &lt;a href=&quot;https://de.wikipedia.org/wiki/E-card_(Chipkarte)&quot;&gt;e-Card&lt;/a&gt;
vor um meinen Impf-Sticker zu erhalten, der an den folgenden Stellen dann
in den Impfpass eingeklebt wurde.&lt;/p&gt;

&lt;p&gt;Eine weitere Dosis von &lt;a href=&quot;https://de.wikipedia.org/wiki/Moderna&quot;&gt;Moderna&lt;/a&gt; stand 
auf dem Menüplan.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/vaccination-cert2.jpg&quot; alt=&quot;Impfung-Moderna-2&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;70-haben-nachwirkungen&quot;&gt;70% haben Nachwirkungen&lt;/h3&gt;

&lt;p&gt;Die erste Impfung vor etwa einem Monat war nur im Arm etwas schmerzend für 2 
Tage zu spüren, hat mir aber keine richtigen Folgebeschwerden eingebracht hat.&lt;/p&gt;

&lt;p&gt;Da vor dem Impfstich noch ein Arzt letzte Fragen beantworten konnte, 
meinte ich nebenbei, dass ich in Erinnerung hätte, dass die zweite Impfung
mit stärkeren Nebenwirkungen verbunden sein kann.&lt;/p&gt;

&lt;p&gt;Die Antwort des Arztes war darauf:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;70% aller Geimpften reagieren mit Kopf- und Gliederschmerzen, wie auch
Schüttelfrost, doch das sollte nach spätestens zwei Tagen abklingen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Und ich dachte mir, dass das eher die Extrembeispiele waren und nachdem 
ich bei der ersten Impfung nichts verspürte, erwartete ich keine großen
Auswirkungen.&lt;/p&gt;

&lt;p&gt;5 Stunden später merkte ich zu Hause deutlich, wie “ein Nagel in meinem Kopf” 
spürbar zu wachsen begann. 
OK, Kopfschmerzen, Check. Die Nacht war dann recht unruhig, wenn jede Bewegung
im Bett führte dazu, dass “der Nagel im Kopf” ungut gegen mein Hirn wetzte.
Auch wurden meine schon lange bekannten Rückenscherzen immer “unsanfter” und
irgendwie wurde das Aufstehen und Hinsetzen in den Beinen mühsam.
Gut, Gliederschmerzen, Check.
Schüttelfrost hatte ich keinen, eher ein bisschen Saunafeeling in Sachen
Schwitzen … aber es ist Sommer und bei 28 Grad in der Wohnung passiert das 
auch ohne Impfung.&lt;/p&gt;

&lt;p&gt;Der folgende Tag hätte ein normaler Arbeitstag werden sollen, doch den musste
ich abblasen. Das Fieberthermometer zeigte 38 Grad an und der Nagel hatte
seine volle Größe im Schädel erreicht.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/clinical-thermometer.jpg&quot; alt=&quot;Clinical Thermometer&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Tatsächlich habe ich den Tag in Summe fast verschlafen, was bei mir mehr als
ungewöhnlich ist. Als ich gegen 23 Uhr dann wieder aufwachte, merkte ich 
bereits, dass der Nagel zu Schrumpfen begonnen hatte. Die Kopfschmerzen
waren zwar noch da, aber wesentlich erträglicher geworden.&lt;/p&gt;

&lt;p&gt;Am zweiten Tag nach der Impfung waren die meisten Nebenwirkungen wieder weg.
Der “Nagel” hatte sich ziemlich aufgelöst, Beine und Rücken “gingen” wieder so
halbwegs, nur etwas Müdigkeit war noch da.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Alles in allem also kein Drama. Im Winter kommt so etwas ja häufiger vor, 
dass man sich verkühlt und ein paar Tage der Kopf dröhnt.&lt;/p&gt;

&lt;p&gt;Aber ich gebe zu, dass mich die Nebenwirkungen der Impfung doch sehr 
überrascht haben. Ich hatte nicht mit Einschränkungen gerechnet, außer 
vielleicht mit etwas Schlappheit.&lt;/p&gt;

&lt;p&gt;Doch wenn ich es richtig verstanden habe, dann ist die Impfreaktion des
Körpers ein deutliches Zeichen dafür, dass die Impfung selbst sehr erfolgreich
war und mein Immunsystem auf das ungute Corona-Virus bestens vorbereitet ist.&lt;/p&gt;

&lt;p&gt;Ab sofort bin ich also voll immunisiert und darf wieder ohne separate Testung
zum Friseur gehen (so fern der Impfpass stets dabei ist).&lt;/p&gt;

&lt;p&gt;Etwas nachdenklich stimmt mich das Auffrischungs-Interval. Denn aktuell sind
Zahlen von um etwa 6-9 Monaten im Umlauf. Das bedeutet also, dass man fast 
jedes halbe Jahr eine Auffrischungsimpfung benötigen wird. Und wenn das 
bedeutet, dass ich jetzt 2 mal im Jahr eine zweitägige 
Impfreaktionsgenesungsphase brauche, dann stimmt mich das nicht gerade sehr 
zuversichtlich, dass COVID-19 bald verschwinden wird.&lt;/p&gt;

&lt;p&gt;Naja … mal sehen wie das weitergehen wird.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>PineTime mit FreeRTOS</title>
   <link href="https://www.opengate.at/blog/2021/08/pinetime/"/>
   <published>2021-08-01T13:00:00+02:00</published>
   <updated>2021-08-01T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2021/08/pinetime</id>
   <category term="hardware" />
   <summary type="text">Das Pine64 Projekt umfasst nicht nur
Laptops, Tablets und Smartphones.
Sogar Smart-Watches bieten die 
Macher mit Open-Source Software 
zum Kauf an.

Auch ich nenne eine solche PineTime nun 
mein Eigen und bin von der Idee positiv beeindruckt.
</summary>
   <content type="html">&lt;p&gt;Das &lt;a href=&quot;https://de.wikipedia.org/wiki/Pine64&quot;&gt;Pine64&lt;/a&gt; Projekt umfasst nicht nur
Laptops, Tablets und Smartphones.
Sogar &lt;a href=&quot;https://de.wikipedia.org/wiki/Smartwatch&quot;&gt;Smart-Watches&lt;/a&gt; bieten die 
Macher mit &lt;a href=&quot;https://de.wikipedia.org/wiki/Open_Source&quot;&gt;Open-Source&lt;/a&gt; Software 
zum Kauf an.&lt;/p&gt;

&lt;p&gt;Auch ich nenne eine solche &lt;a href=&quot;https://www.pine64.org/pinetime/&quot;&gt;PineTime&lt;/a&gt; nun 
mein Eigen und bin von der Idee positiv beeindruckt.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Da ich mir die “Entwickler-Variante” bestellt hatte, bekam ich eine 
nicht-versiegelte Smartwatch, damit ich sie mit dem ebenfalls 
mitbestelltem &lt;a href=&quot;https://pine64.com/product/pinetime-pogopin-jig/&quot;&gt;Pogopin-Jig&lt;/a&gt; 
an einen seriellen Debugger anschließen und im Falle eines “Totalschadens”
beim Softwareupdate wiederherstellen kann.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/pinetime-inside.jpg&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Die Idee dabei ist, dass man sich sein Watch so einrichtet, wie man sie 
haben will und am Ende selbst mit ein paar Tropfen Kleber die Rückseite 
mit dem Gehäuse fest verklebt (also versiegelt).&lt;/p&gt;

&lt;p&gt;Eine “fertige” PineTime kostet unter 30 Dollar oder man bestellt gleich
ein Dev-Kit mit einer versiegelten und einer offenen Smartwatch.
Mitgeliefert wird auch ein Ladesockel, der zwei Pins an der Rückseite
mit dem Ladestrom über USB verbindet.&lt;br /&gt;
Die Uhr wird dabei magnetisch am Sockel festgehalten, was zu einem 
stabilen Halt darauf führt.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/pinetime-outside.jpg&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Die Sache mit dem Debugger habe ich bisher noch nicht ausprobiert und 
möchte das auch nicht, so lange es nicht zwingend notwendig ist.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/pinetime-debugger.jpg&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Laut Info liegen neben dem Akku 4 Pins frei, auf die man einfach den
“Pogopin-Jig” drauf hält, der am anderen Ende mit einem seriellen TTL Modul
zum PC verbunden wird.&lt;br /&gt;
Ich bräuchte dazu aber jemanden, der mir das Teil hält, denn einhändig
werken klappt nicht gut und eine kleiner Wackler produziert dann
Kurzschlüsse und Resets.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/pinetime-debugging.jpg&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;daten-und-betrieb&quot;&gt;Daten und Betrieb&lt;/h3&gt;

&lt;p&gt;Ein 64 MHz &lt;a href=&quot;https://de.wikipedia.org/wiki/Arm_Cortex-M4&quot;&gt;ARM Cortex-M4F&lt;/a&gt; 
treibt die Uhr an und lässt auf dem 1.3 Zoll großen 240x240 Pixel Display 
anzeigen, was die Software wünscht. Im 38 x 40 x 11 Millimeter großen 
Gehäuse findet auch ein 180 mAh LiPo Akku Platz.&lt;/p&gt;

&lt;p&gt;Kommunizieren kann die PineTime über 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Bluetooth_Low_Energy&quot;&gt;Bluetooth 5 LE&lt;/a&gt;.
Auf der linken Seite hat sie einen Druckknopf, der gerne zum
Aktivieren der Anzeige genutzt wird.&lt;br /&gt;
Ansonsten kann man die Uhr auch rudimentär über Streichbewegungen und Tippen
am Touchscreen steuern, wenn die Software dies unterstützt.&lt;/p&gt;

&lt;p&gt;Meine schon etwas ältere Variante wurde mit der Firmware &lt;code&gt;InfiniTime&lt;/code&gt; v0.7 
ausgeliefert, ein auf &lt;a href=&quot;https://de.wikipedia.org/wiki/FreeRTOS&quot;&gt;FreeRTOS 10&lt;/a&gt; 
basierendes Grundsystem, das an die Hardware angepasst wurde.&lt;/p&gt;

&lt;p&gt;Da die Rückseite der Uhr mit Federkontakten die Ladepins mit der Platine 
verbindet, lässt sich das Gehäuse nicht ohne Hilfsmittel verschließen. 
Verkleben möchte ich die Uhr noch nicht, also habe ich sie einfach mit 
3 Gummibändern an den Ladesockel gefesselt.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/pinetime-online.jpg&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Mir macht die “technische Spielerei” damit ohnehin mehr Spaß, als sie am Arm
zu tragen und immer aufpassen zu müssen, dass man sie nicht versehentlich 
wo dagegen schmettert.&lt;/p&gt;

&lt;h3 id=&quot;firmware-update-über-bluetooth&quot;&gt;Firmware Update über Bluetooth&lt;/h3&gt;

&lt;p&gt;Mit der &lt;a href=&quot;https://de.wikipedia.org/wiki/Android_(Betriebssystem)&quot;&gt;Android&lt;/a&gt; App 
&lt;a href=&quot;https://play.google.com/store/apps/details?id=no.nordicsemi.android.mcp&quot;&gt;NRF Connect&lt;/a&gt; 
lässt sich jedes Bluetooth LE fähige Android Smartphone in einen 
PineTime-Firmware-Updater verwandeln.&lt;br /&gt;
(In der PineTime Doku findet man aber auch noch andere Apps zum Updaten.)&lt;/p&gt;

&lt;p&gt;Von meiner originalen alten Firmware 0.7 aus, sind 3 Updates erforderlich. 
Zuerst das Update der &lt;code&gt;InfiniTime&lt;/code&gt; App auf v1.0. Danach kann man den Boot-Loader
aktualisieren und am Ende wird noch die Recovery-Firmware auf den neuesten 
Stand gebracht.&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;NRF Connect&lt;/code&gt; findet man die PineTime (auch als &lt;code&gt;InfiniTime&lt;/code&gt; angezeigt) 
in der Regel schnell mit dem Bluetooth Scanner, wenn die Uhr aktiviert wird 
(linke Taste seitlich vom Display). Danach kann man sie “verbinden”.&lt;/p&gt;

&lt;p&gt;Etwas unscheinbar taucht dann oben in der Menüzeile neben 
“Devices” und “Disconnect” ein kleines rundes “DFU” (Digital Firmware Update) 
auf, das von zwei Pfeilen umkreist wird.&lt;br /&gt;
Genau darauf muss man Tippen um dann eine &lt;a href=&quot;https://de.wikipedia.org/wiki/ZIP-Dateiformat&quot;&gt;ZIP&lt;/a&gt;
Datei mit den Updates auswählen zu können.
Diese ZIP Dateien von &lt;code&gt;InifiniTime&lt;/code&gt; 1.0 findet man in der 
&lt;a href=&quot;https://github.com/JF002/InfiniTime/blob/develop/doc/gettingStarted/gettingStarted-1.0.md&quot;&gt;Getting-Started Dokumentation&lt;/a&gt;
etwa in der Mitte. Und genau in der Reihenfolge wie sie dort gelistet 
sind, sollten sie auf die Smartwatch übertragen werden.&lt;/p&gt;

&lt;p&gt;Die Übertragung lief bei mir mit 4 - 5 KB/s und dauerte zwischen 2 und 5
Minuten. Am besten legt man das Smartphone direkt neben die Uhr, um
Abbrüche zu vermeiden (was bei meinem ersten Versuch passierte).&lt;br /&gt;
Das initiale Update ist am größten, die beiden folgenden sind kleiner.
Am Ende jedes Updateschrittes startet die Uhr neu und braucht ein 
Weilchen, bis sie wieder voll einsatzfähig ist. Sobald die Uhrzeit angezeigt
wird, kann man das nächste Update starten.&lt;/p&gt;

&lt;p&gt;Final hat man dann &lt;code&gt;InfiniTime&lt;/code&gt; 1.0 und man kann neben einem sicheren 
Softwarestand auch schon ein paar Apps auf der Uhr nutzen, 
die unter v0.7 noch fehlten.&lt;/p&gt;

&lt;p&gt;Jetzt kann man einfach auf die &lt;a href=&quot;https://github.com/JF002/InfiniTime/releases&quot;&gt;InfiniTime Release&lt;/a&gt;
Seite wechseln und auch zur aller neuesten Haupt-Firmware wechseln
(aktuell ist das v 1.3).&lt;br /&gt;
Die ist auf GitHub leider oft unter dem Posting unter “Assets” versteckt.
Man nimmt einfach die &lt;code&gt;pinetime-mcuboot-app-dfu-X.Y.Z.zip&lt;/code&gt; der gewünschten 
Version und überträgt sie ebenfalls auf die Uhr.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Das schönste an der &lt;code&gt;PineTime&lt;/code&gt; ist, dass man mit &lt;code&gt;InfiniTime&lt;/code&gt; auch die 
gesamte Betriebssoftware einsehen und nach Belieben anpassen kann.&lt;br /&gt;
Ein solches Feature hat keine andere verbreitete Smartwatch und somit können
wir hier sicher sein (bzw. umsetzen), dass die Uhr keine geheimen Botschaften
über proprietäre Apps zu seinen Machern sendet.&lt;/p&gt;

&lt;p&gt;Ist einem der Stromverbrauch zu hoch, kann man Anzeigedauer und Intensität
auch selbst regeln. Will man mit anderen Apps kommunizieren, schreibt 
man sich einfach ein Plugin dafür.&lt;/p&gt;

&lt;p&gt;Das ist doch mal echt super und daher eine klare Empfehlung wert.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Das TAR Dateiformat</title>
   <link href="https://www.opengate.at/blog/2021/07/tar-format/"/>
   <published>2021-07-31T13:00:00+02:00</published>
   <updated>2021-07-31T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2021/07/tar-format</id>
   <category term="devel" /><category term="software" />
   <summary type="text">Ich bin (leider) nicht alt genug, als dass ich den Einsatz von 
Bandkassetten
zur Datenspeicherung live mitbekommen hätte. Disketten 
waren für mich von 1995 bis 2003 das “älteste” Medium.

Doch dank Unix und seinen 
Linux-Sprösslingen haben “Band-Archive” bzw. 
Tape-Archives, kurz TAR, 
als primitives Dateiformat bis heute überlebt.

Grund genug dieses Format selbst zu implementieren.
</summary>
   <content type="html">&lt;p&gt;Ich bin (leider) nicht alt genug, als dass ich den Einsatz von 
&lt;a href=&quot;https://en.wikipedia.org/wiki/Tape_drive&quot;&gt;Bandkassetten&lt;/a&gt;
zur Datenspeicherung live mitbekommen hätte. &lt;a href=&quot;https://de.wikipedia.org/wiki/Diskette&quot;&gt;Disketten&lt;/a&gt; 
waren für mich von 1995 bis 2003 das “älteste” Medium.&lt;/p&gt;

&lt;p&gt;Doch dank &lt;a href=&quot;https://de.wikipedia.org/wiki/Unix&quot;&gt;Unix&lt;/a&gt; und seinen 
Linux-Sprösslingen haben “Band-Archive” bzw. 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Tar_(Packprogramm)&quot;&gt;Tape-Archives, kurz TAR&lt;/a&gt;, 
als primitives Dateiformat bis heute überlebt.&lt;/p&gt;

&lt;p&gt;Grund genug dieses Format selbst zu implementieren.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Als Windows-Kind ist das &lt;a href=&quot;https://de.wikipedia.org/wiki/ZIP-Dateiformat&quot;&gt;ZIP&lt;/a&gt; 
Format für mich die absolute Nummer eins wenn es um die komprimierte 
Archivierung von Verzeichnissen geht. Denn seit &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_XP&quot;&gt;Windows XP&lt;/a&gt;
kann der Explorer diesen Dateityp ohne Zusatzprogramme öffnen und bearbeiten.&lt;/p&gt;

&lt;p&gt;Tatsächlich habe ich aber &lt;code&gt;TAR&lt;/code&gt; schon vor &lt;code&gt;ZIP&lt;/code&gt; genutzt, denn vor meinem 
Einstieg ins Internet gegen 2001 habe ich privat überhaupt keine “Archive” 
benutzt und alles unkomprimiert gespeichert.
(OK, die Disketten-Orgie mit &lt;a href=&quot;/blog/2018/11/win95-update/&quot;&gt;MSBACKUP&lt;/a&gt; 
sei hier mal schnell verdrängt.)&lt;/p&gt;

&lt;p&gt;Und es war wohl ein paar Jahre vor dem Jahrtausendwechsel, als ich meine erste
&lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt;-Test-Installation von den damals
üblichen PC-Heft-CDs aufsetzte.&lt;br /&gt;
Es kann sich heute keiner mehr vorstellen was für ein unerträglicher Krampf 
das mit Linux war, wo auf CD Nr.1 ein Basis-Linux per Start-Diskette auf 
den Rechner gewurschtelt wurde und auf CD Nr. 2. fand man dann jede Menge
“Archive”, die man manuell entpacken und kompilieren musste.&lt;/p&gt;

&lt;p&gt;Und so führte ich tatsächlich ein &lt;code&gt;tar -xf irgendwas.tar.gz&lt;/code&gt; wie im Heft 
beschrieben aus, lange bevor ich meine Dateien per Windows Explorer als ZIP 
verstaute.&lt;/p&gt;

&lt;h3 id=&quot;tar-selbst-gemacht&quot;&gt;TAR selbst gemacht&lt;/h3&gt;

&lt;p&gt;Kurz auf &lt;a href=&quot;https://www.gnu.org/software/tar/manual/html_node/Standard.html&quot;&gt;gnu.org/software/tar&lt;/a&gt;
geblickt:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;struct&lt;/span&gt; posix_header
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt; name[&lt;span style=&quot;color:#00D&quot;&gt;100&lt;/span&gt;];     &lt;span style=&quot;color:#777&quot;&gt;/* path: &amp;quot;path/to/file.txt&amp;quot; */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt; mode[&lt;span style=&quot;color:#00D&quot;&gt;8&lt;/span&gt;];       &lt;span style=&quot;color:#777&quot;&gt;/* octal file-mode bits */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt; uid[&lt;span style=&quot;color:#00D&quot;&gt;8&lt;/span&gt;];        &lt;span style=&quot;color:#777&quot;&gt;/* owner user id */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt; gid[&lt;span style=&quot;color:#00D&quot;&gt;8&lt;/span&gt;];        &lt;span style=&quot;color:#777&quot;&gt;/* owner group id */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt; size[&lt;span style=&quot;color:#00D&quot;&gt;12&lt;/span&gt;];      &lt;span style=&quot;color:#777&quot;&gt;/* octal file size */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt; mtime[&lt;span style=&quot;color:#00D&quot;&gt;12&lt;/span&gt;];     &lt;span style=&quot;color:#777&quot;&gt;/* octal unix timestamp */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt; chksum[&lt;span style=&quot;color:#00D&quot;&gt;8&lt;/span&gt;];     
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt; typeflag;      &lt;span style=&quot;color:#777&quot;&gt;/* &apos;0&apos;==file, &apos;5&apos;==directory, &apos;L&apos;==long-link */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt; linkname[&lt;span style=&quot;color:#00D&quot;&gt;100&lt;/span&gt;]; &lt;span style=&quot;color:#777&quot;&gt;/* &amp;quot;path/to/linked.file&amp;quot; */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt; magic[&lt;span style=&quot;color:#00D&quot;&gt;6&lt;/span&gt;];      &lt;span style=&quot;color:#777&quot;&gt;/* &amp;quot;ustar\0&amp;quot; */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt; version[&lt;span style=&quot;color:#00D&quot;&gt;2&lt;/span&gt;];    &lt;span style=&quot;color:#777&quot;&gt;/* &amp;quot;00&amp;quot; */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt; uname[&lt;span style=&quot;color:#00D&quot;&gt;32&lt;/span&gt;];     &lt;span style=&quot;color:#777&quot;&gt;/* owner user name */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt; gname[&lt;span style=&quot;color:#00D&quot;&gt;32&lt;/span&gt;];     &lt;span style=&quot;color:#777&quot;&gt;/* owner group name */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt; devmajor[&lt;span style=&quot;color:#00D&quot;&gt;8&lt;/span&gt;];
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt; devminor[&lt;span style=&quot;color:#00D&quot;&gt;8&lt;/span&gt;];
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt; prefix[&lt;span style=&quot;color:#00D&quot;&gt;155&lt;/span&gt;];
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;};
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Wie alt und primitiv TAR ist, sieht man schon an seinem Header, der immer 512 
Bytes groß sein muss und mit genau 100 Bytes für den Dateinamen beginnt.
Hmm … 100 Zeichen für einen ganzen Pfad? Da konnte selbst DOS mit 255 mehr.
Zahlen für Dateiattribute, Größe und Zeitstempel liegen als ASCII-formatierte
Oktalzahlen vor.&lt;/p&gt;

&lt;p&gt;Dass dieses Format aus der Unix-Welt stammt sieht man dann an der &lt;a href=&quot;https://de.wikipedia.org/wiki/Benutzerkennung&quot;&gt;&lt;code&gt;UID&lt;/code&gt;&lt;/a&gt;
und &lt;code&gt;GID&lt;/code&gt;, sowie weiteren 100 Zeichen für einen Link-Namen.
In den Anfängen von Unix waren auch dort die Dateisysteme nicht in der Lage, 
mehr als ein paar Zeichen pro Datei zu speichern und so empfand man ganze 100
Bytes als üppig dimensioniert.&lt;/p&gt;

&lt;p&gt;Doch wegen dieser Einfachheit lässt sich das Format mit wenigen C-Zeilen 
selbst implementieren.
Man füllt einen 512 Header aus, der die nachfolgende Datei beschreibt und 
danach werden einfach die Rohdaten hinten angestellt.
Ist die Dateigröße kein genaues Vielfaches von 512, dann müssen so viele
Null-Bytes nachgeschoben werden, bis ein 512er Block voll ist.
Und im Anschluss daran folgt der nächste Datei-Header der auch wieder von
den Rohdaten gefolgt wird.
Am Ende schreibt man dann noch genau ein Kilobyte Nullen daran (also zwei 
leere 512-Byte Blöcke) und die TAR Datei ist fertig.&lt;/p&gt;

&lt;p&gt;Auf zwei Dinge muss man aufpassen:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;TAR-interne Dateipfade müssen Slashes zur Pfadkomponententrennung nutzen&lt;/li&gt;
  &lt;li&gt;Und wir MÜSSEN eine Prüfsumme über den Header berechnen.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Die Prüfsumme ist mir bei der Implementierung sehr auf die Nerven gegangen.
Man muss dafür den Header voll ausfüllen und die Bytes der Prüfsumme “leer”
lassen. Und mit “leer” sind “Blank” also Leerzeichen (Space) notwendig.
Ich hatte den Bereich aber ausgenullt und wunderte mich dann, weshalb
&lt;a href=&quot;https://de.wikipedia.org/wiki/7-Zip&quot;&gt;7-Zip&lt;/a&gt; und das &lt;code&gt;tar&lt;/code&gt; Tool die Datei 
als korrupt zurückwiesen.&lt;/p&gt;

&lt;h3 id=&quot;lange-dateinamen&quot;&gt;Lange Dateinamen&lt;/h3&gt;

&lt;p&gt;Am meisten interessiert mich ja, wie Workarounds aussehen, um “historische”
Limits zu umgehen.&lt;br /&gt;
TAR löst das 100 Zeichen pro Datei-Limit durch die Möglichkeit von 
“Vendor-Extentions”. Und eine bekannte &lt;a href=&quot;https://de.wikipedia.org/wiki/GNU&quot;&gt;GNU&lt;/a&gt; 
Erweiterung dafür sind &lt;em&gt;LongLink&lt;/em&gt; Header.&lt;/p&gt;

&lt;p&gt;Man erstellt also einen üblichen 512-Byte Dateiheader, doch anstatt des 
Dateinamens steht in den ersten 13 Bytes der Token &lt;code&gt;././@LongLink&lt;/code&gt; und das
Header-Type Byte steht auf &lt;code&gt;L&lt;/code&gt;. Und das Größen-Feld wird auf die Länge 
des vollständigen Dateinamens gesetzt. Nach dem LongLink-Block kommt dann der 
Dateiname genau so wie bei den Rohdaten in 512-Byte Häppchen und der letzte 
Block muss dann auch wieder mit Nullen aufgefüllt werden.&lt;br /&gt;
Nun folgt der “richtige” Header unserer Datei, wo in den ersten 100 Zeichen 
der Anfang des Dateinamens abgebildet ist. Alle anderen Felder sind genau
so ein gesetzt, wie für die Rohdaten notwendig und danach werden ebenso
die Rohdaten (wieder mit 512-Byte Vervollständigung) angefügt.&lt;/p&gt;

&lt;p&gt;Man hat also quasi einen Präfix-Block + Meta-Daten und danach den eigentlichen
Datei-Header und die echten Daten, die zusammengefasst dann die endgültige
Datei beschreiben.&lt;/p&gt;

&lt;p&gt;Naja…. offen gesagt schon etwas primitiv … aber so ist das eben bei den
alten Dateiformaten.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Bisher hatte ich &lt;code&gt;TAR&lt;/code&gt; nur über Bibliotheken und &lt;a href=&quot;https://de.wikipedia.org/wiki/Kommandozeile&quot;&gt;CLI&lt;/a&gt;
Tools genutzt. Doch wenn man diesen Kuchen selbst backt, merkt man erst, 
wie krümelig er innen drinnen ist.&lt;/p&gt;

&lt;p&gt;Erweiterungen und “andere Interpretationen” gibt es leider einige und somit
ist man wohl besser beraten, eine fertig Lib zu nutzen, die alle Raffinessen
dafür bereits drauf hat.&lt;/p&gt;

&lt;p&gt;Doch wenn es nur darum geht, die eigenen Dateien schnell und unkompliziert
zu archivieren, so lege ich jedem ans Herz diesen Implementierungs-Tag mal
zu investieren.&lt;br /&gt;
Denn viele Libs und Tools sind heute mit Zusatzfunktionen und Abhängigkeiten
gespickt, die einem unkompliziertem Deployment im Wege stehen.&lt;/p&gt;

&lt;p&gt;Da ziehe ich dann mein 400 Zeilen Eigenfabrikat vor, das nur &lt;code&gt;stdio.h&lt;/code&gt; und 
&lt;code&gt;string.h&lt;/code&gt; braucht um &lt;code&gt;TAR&lt;/code&gt; Archive zu erzeugen.
Dann fährt noch die &lt;a href=&quot;https://de.wikipedia.org/wiki/Zlib&quot;&gt;ZLIB&lt;/a&gt; darüber und 
schon haben wir ein &lt;code&gt;TAR.GZ&lt;/code&gt;, so wie es im Buche steht.&lt;/p&gt;

&lt;p&gt;Wieder was gelernt und daher einen schönen Tag gehabt! 
So kann’s gerne weitergehen.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>VB6 und COM Spezialitäten</title>
   <link href="https://www.opengate.at/blog/2021/07/vb6-specials/"/>
   <published>2021-07-25T13:00:00+02:00</published>
   <updated>2021-07-25T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2021/07/vb6-specials</id>
   <category term="devel" /><category term="retro" />
   <summary type="text">20 Jahre liegen meine VB6
Zeiten zurück und trotzdem denke ich immer wieder gerne an damals zurück.
Die einfache Möglichkeit UIs mit Freude zu erstellen, konnte mir bis heute 
kein noch so moderner dotNet 
Editor wiederbringen.

Doch an die Limitierungen dieser Programmiersprache erinnere ich mich auch
noch … und auch, wie man sie “kreativ” umgehen musste.
</summary>
   <content type="html">&lt;p&gt;20 Jahre liegen meine &lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_Basic_Classic&quot;&gt;VB6&lt;/a&gt;
Zeiten zurück und trotzdem denke ich immer wieder gerne an damals zurück.&lt;br /&gt;
Die einfache Möglichkeit UIs mit Freude zu erstellen, konnte mir bis heute 
kein noch so moderner &lt;a href=&quot;https://de.wikipedia.org/wiki/.Net-Framework&quot;&gt;dotNet&lt;/a&gt; 
Editor wiederbringen.&lt;/p&gt;

&lt;p&gt;Doch an die Limitierungen dieser Programmiersprache erinnere ich mich auch
noch … und auch, wie man sie “kreativ” umgehen musste.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;64-bit-rechnungen-mit-currency&quot;&gt;64 Bit Rechnungen mit Currency&lt;/h3&gt;

&lt;p&gt;Das VB6 Datentypensystem basierte 1:1 auf &lt;a href=&quot;https://de.wikipedia.org/wiki/Component_Object_Model&quot;&gt;COM&lt;/a&gt;
VARIANT Datentypen, die wegen ihres Ursprungs unter &lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_3.x&quot;&gt;Windows 3.x&lt;/a&gt;
noch sehr 16-bit lastig waren.&lt;/p&gt;

&lt;p&gt;Nachdem &lt;code&gt;Integer&lt;/code&gt; in VB (wie auch &lt;code&gt;int&lt;/code&gt; im ursprünglichen C) nur 16-bit 
breit ist, fasst &lt;code&gt;Long&lt;/code&gt; unglaubliche 32 bit aus.&lt;br /&gt;
Dass irgendjemand mal 64-bit zum Rechnen braucht, war damals nicht 
vorstellbar, also gab es kein &lt;code&gt;LongerInt&lt;/code&gt;, &lt;code&gt;LongLong&lt;/code&gt; oder &lt;code&gt;BigInt&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Eine Zielgruppe gab es aber dennoch und zwar die förmlichen Menschen in
Banken und Finanzabteilungen. Die hatten kein Vertrauen in &lt;code&gt;Double&lt;/code&gt; 
in Bezug auf Rundungen und brauchten eine Festkommastellen Zahl, die 
Milliarden und Billiarden abbilden konnte.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Dim i64 As Currency&lt;/code&gt; war die Lösung, denn dieser Typ fasste 64 Bit und 
ist eine Festkommazahl dessen 64-Bit Wert fix durch &lt;code&gt;10 000&lt;/code&gt; dividiert
wird.
Die binäre Zahl &lt;code&gt;123 456&lt;/code&gt; wird dann als &lt;code&gt;12.3456&lt;/code&gt; dargestellt.&lt;/p&gt;

&lt;h3 id=&quot;lset-als-memcpy-ersatz&quot;&gt;LSet als memcpy() Ersatz&lt;/h3&gt;

&lt;p&gt;Das &lt;code&gt;LSet&lt;/code&gt; Statement kopiert den Inhalt eines Datentyps in einen anderen
und macht das ohne zu hinterfragen, ob die Typen stimmen. So habe ich gerne
Bytes herumkopiert&lt;/p&gt;

&lt;div class=&quot;language-vbnet highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;Private Type UI32
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;  Value As Long
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;End Type
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;Private Type UI32Bytes
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  Value0  As Byte
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;  Value1  As Byte
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  Value2  As Byte
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;  Value3  As Byte
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;End Type
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;Private Sub MemCpyUI32(ByRef src As UI32, ByRef dst As UI32Bytes)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;  LSet dst = src
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;End Sub
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h3 id=&quot;leere-arrys&quot;&gt;Leere Arrys&lt;/h3&gt;

&lt;p&gt;Um Arrays auf eine bestimmte Größe zu setzen, nutzt man&lt;/p&gt;
&lt;div class=&quot;language-vbnet highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;Dim strArray As String()
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;ReDim strArray(count - 1)
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Wer glaubt, dass ein einfaches &lt;code&gt;Dim var As String()&lt;/code&gt; ohne &lt;code&gt;ReDim&lt;/code&gt; ein leeres 
String-Feld erzeugt, der irrt leider. Es kommt nämlich eine nicht 
initialisierte Variable heraus, mit der Funktionen wie &lt;code&gt;UBound&lt;/code&gt; oder &lt;code&gt;LBound&lt;/code&gt; 
fehlschlagen.&lt;/p&gt;

&lt;p&gt;Ruft man aber &lt;code&gt;Split&lt;/code&gt; mit einem leeren String auf, kommt ein typisiertes
String-Array heraus, das kein Element beinhaltet, wo &lt;code&gt;Ubound&lt;/code&gt; also ohne Fehler
&lt;code&gt;-1&lt;/code&gt; liefert.&lt;/p&gt;

&lt;div class=&quot;language-vbnet highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;Function EmptyStringArray() As String()
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;  EmptyStringArray = Split(vbNullString)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;End Function
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Leere Byte-Arrays sind ebenso ein Problem, doch hier reicht die 
implizite Konvertierung eines leeren Strings aus&lt;/p&gt;

&lt;div class=&quot;language-vbnet highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;Function EmptyByteArray() As Byte()
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;    EmptyByteArray = vbNullString
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;End Function
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h3 id=&quot;globale-variablen-als-funktionen&quot;&gt;Globale Variablen als Funktionen&lt;/h3&gt;

&lt;p&gt;Klassen können mit &lt;code&gt;Property Get/Let/Set&lt;/code&gt; Routinen um Eigenschaften erweitert
werden, wo man syntaktisch glaubt, man würde eine Member-Variable setzen, 
aber in Wahrheit läuft eine Funktion, die Werte validieren und manipulieren
kann.&lt;/p&gt;

&lt;p&gt;Wenn man ein “Modul” in VB6 anfügt und dort Property Routinen implementiert,
erscheinen dieses Properties wie globale Variablen in allen anderen Modulen
und Klassen. Und das ist echt nett beim Debuggen.&lt;/p&gt;

&lt;div class=&quot;language-vbnet highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;Private secretX As String
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;Public Property Let GlobalX(ByVal value As String)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;    secretX = value + &amp;quot;_patch_added&amp;quot;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;End Property
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;Public Property Get GlobalX() As String
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;    GlobalX = secretX
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;End Property
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;Public Sub Main()
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;    GlobalX = &amp;quot;Hello-World&amp;quot;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;    MsgBox GlobalX
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;End Sub
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ich trauere ein bisschen um diese alten VB-Minihacks. Es hat mich damals
viel Zeit gekostet, sie herauszufinden … und heute sind sie wirtschaftlich
leider wertlos.&lt;/p&gt;

&lt;p&gt;Und trotzdem erinnere ich mich noch gerne daran zurück, als man quasi im
Abenteuer-Modus durch VB durchlief und immer wieder was Neues entdeckte.
Das musste dann gleich in irgend einem Web-Forum gepostet werden, auch 
wenn es sonst niemand interessiert hat, aber man war glücklich dabei.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>CONAN und der MSVC Debugger</title>
   <link href="https://www.opengate.at/blog/2021/07/conan-msvc-debugger/"/>
   <published>2021-07-24T13:00:00+02:00</published>
   <updated>2021-07-24T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2021/07/conan-msvc-debugger</id>
   <category term="devel" /><category term="software" />
   <summary type="text">Eine weitere Story in meinem CONAN Tagebuch ist seine 
schwierige Beziehung zu Debuggern.

Denn obgleich conan build . brav im lokalen Verzeichnis alle Quellcodes
durchbauen kann, so bekommen wir dann jede Menge fehlende Abhängigkeiten,
wenn wir die gebauten Programme im Debugger ausführen möchten.
</summary>
   <content type="html">&lt;p&gt;Eine weitere Story in meinem &lt;a href=&quot;https://conan.io/&quot;&gt;CONAN&lt;/a&gt; Tagebuch ist seine 
schwierige Beziehung zu &lt;a href=&quot;https://de.wikipedia.org/wiki/Debugger&quot;&gt;Debuggern&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Denn obgleich &lt;code&gt;conan build .&lt;/code&gt; brav im lokalen Verzeichnis alle Quellcodes
durchbauen kann, so bekommen wir dann jede Menge fehlende Abhängigkeiten,
wenn wir die gebauten Programme im Debugger ausführen möchten.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;CONAN’s wichtigstes Feature ist aus meiner Sicht auch sein größter Bug.
Alles wird in den CONAN-Cache geladen und ein Projekt bekommt z.B. für
&lt;a href=&quot;https://de.wikipedia.org/wiki/CMake&quot;&gt;CMAKE&lt;/a&gt; jede Menge Variablen injiziert, 
wo die Pfade zu den benötigten Headern und weitere Sourcen hinterlegt sind.&lt;/p&gt;

&lt;p&gt;Das klappt in der Regel recht gut und der Compiler kann alles finden,
was unter &lt;code&gt;requirements&lt;/code&gt; auf der CONAN Seite deklariert ist.&lt;/p&gt;

&lt;p&gt;Doch wenn man eine EXE ausführen will, braucht man auch die Binärdateien
und diese sind ebenfalls im CONAN Cache in einem der unzähligen
Hash-Paket-Unterverzeichnisse versteckt.&lt;/p&gt;

&lt;p&gt;Der reguläre Weg wäre nun, eine virtuelle Laufzeitumgebung 
(virtual run-environment) per CONAN einrichten zu lassen.
&lt;code&gt;conan install . -g virtualrunenv&lt;/code&gt; würde das erledigen und dann hat
man ein &lt;code&gt;.sh&lt;/code&gt; und ein &lt;code&gt;.bat&lt;/code&gt; Script in seinem Verzeichnis, das bei
Ausführung alle benötigten Verzeichnisse als &lt;code&gt;PATH&lt;/code&gt; oder &lt;code&gt;LD_LIBRARY_PATH&lt;/code&gt;
einrichtet.&lt;/p&gt;

&lt;p&gt;Innerhalb dieser Umgebung lässt sich dann auch problemlos ein Debugger starten
um das Projekt zu inspizieren.&lt;/p&gt;

&lt;p&gt;…. doch, wenn man viele CONAN Projekte verwaltet, ist das echt mühsam.&lt;/p&gt;

&lt;h3 id=&quot;visual-studio-path-patch&quot;&gt;Visual Studio PATH Patch&lt;/h3&gt;

&lt;p&gt;Ein tolle Lösung, die meine Kollegen in der Firma gefunden haben, sieht 
wie folgt aus:
Man definiert in CMAKE die target-Variable &lt;code&gt;VS_DEBUGGER_ENVIRONMENT&lt;/code&gt; und 
setzt sie auf den Wert &lt;code&gt;Path=${CONAN_BIN_DIRS};%Path%&lt;/code&gt;. Das sieht dann etwa
so aus:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;set_target_properties(${PROJECT} PROPERTIES 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;  VS_DEBUGGER_ENVIRONMENT &amp;quot;Path=${CONAN_BIN_DIRS};%Path%&amp;quot;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;)
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Lässt man nun ein &lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_C%2B%2B&quot;&gt;MSVC&lt;/a&gt; Projekt
erstellen, werden dem quasi alle notwendigen Infos injiziert und man kann 
direkt seine Software (per F5) starten und wegen der gesetzten Pfad Variable 
können auch alle anderen notwendigen von CONAN verwalteten Module geladen 
werden.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Es sind solche Kleinigkeiten, die das Leben entscheidend erleichtern und in
Summe Stunden einsparen.&lt;br /&gt;
Und diese eine CMAKE Zeile macht das Arbeiten zumindest unter Windows mit
CONAN und MSVC um Längen erträglicher.&lt;/p&gt;

&lt;p&gt;Doch für mich zeigt das Beispiel, dass es auf diese Weise vielleicht auch
einen Weg gibt, einer &lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt; / POSIX 
Umgebung ein schöneres Arbeiten mit CONAN beizubringen.&lt;br /&gt;
Mal sehen, ob ich da auch was dazu finden kann …&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>WinGet</title>
   <link href="https://www.opengate.at/blog/2021/07/winget/"/>
   <published>2021-07-18T13:00:00+02:00</published>
   <updated>2021-07-18T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2021/07/winget</id>
   <category term="software" />
   <summary type="text">Worüber die Linux Community seit 
Jahrzehnten bei Windows 
lacht und was auch Windows-Nachbauprojekte wie ReactOS 
hinbekommen haben, ist das Fehlen eines Anwendungs-Installationsprogramms, 
das alle möglichen Apps aus einem Repository installiert.
Oder anders gesagt: Windows hatte nie ein apt install.

Und jetzt, 20 Jahre zu spät, kommt winget …
</summary>
   <content type="html">&lt;p&gt;Worüber die &lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt; Community seit 
Jahrzehnten bei &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows&quot;&gt;Windows&lt;/a&gt; 
lacht und was auch Windows-Nachbauprojekte wie &lt;a href=&quot;https://de.wikipedia.org/wiki/ReactOS&quot;&gt;ReactOS&lt;/a&gt; 
hinbekommen haben, ist das Fehlen eines Anwendungs-Installationsprogramms, 
das alle möglichen Apps aus einem Repository installiert.&lt;br /&gt;
Oder anders gesagt: Windows hatte nie ein &lt;code&gt;apt install&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Und jetzt, 20 Jahre zu spät, kommt &lt;code&gt;winget&lt;/code&gt; …
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;vorgeschichte&quot;&gt;Vorgeschichte&lt;/h3&gt;

&lt;p&gt;Das Thema &lt;code&gt;Installation&lt;/code&gt; oder &lt;code&gt;Setup&lt;/code&gt; ist historisch bedingt unter Windows 
(und früher auch unter &lt;a href=&quot;https://de.wikipedia.org/wiki/MS-DOS&quot;&gt;DOS&lt;/a&gt;), Sache 
des Anwendungsentwicklers gewesen.&lt;br /&gt;
Ganz anders ist es heute in unixoiden Systemen, denn sowohl Linux, &lt;a href=&quot;https://de.wikipedia.org/wiki/BSD&quot;&gt;BSD&lt;/a&gt;, 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Android_(Betriebssystem)&quot;&gt;Android&lt;/a&gt; und MacOS 
nutzen die für sie typischen “Paket-Manager”, die eine Anwendung von einem 
definierten Ort herunterladen und alle Dateien an den korrekten Stellen 
integrieren.&lt;/p&gt;

&lt;p&gt;Unter Windows (und DOS) hingegen hatte jeder Hersteller seinen eigenen
Installer entwickelt, der häufig mehr Probleme verursacht als gelöst hatte.
Da wurden wild DLLs in &lt;code&gt;Windows\System[32]&lt;/code&gt; überschrieben nur damit die
eigene Anwendung eine anders-aussehende “coolere” Titelleiste bekam.&lt;/p&gt;

&lt;p&gt;Am Ende bildeten sich ein Hand voll “Installer” Hersteller, die den Vorgang
der Installation durch eigene proprietäre Scriptsprachen abbildeten.&lt;/p&gt;

&lt;p&gt;Microsoft versuchte das Chaos noch durch Standards wie dem &lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_Installer&quot;&gt;MSI Format&lt;/a&gt; 
(Microsoft Installer) und später mit dem &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Store&quot;&gt;Windows-Store&lt;/a&gt;
zu verhindern, doch bis heute schreiben die Hersteller eigene Setups, um den 
Kunden-PC mit möglichst viel Werbung und andere Blödheiten zu infizieren.&lt;/p&gt;

&lt;p&gt;Nun, man darf dabei nicht vergessen, dass große Firmen ihre genutzte
Fremdsoftware immer selbst anpassen wollen und forderten die “Eigenständigkeit”
dafür von Microsoft ein. Für den Endanwender zu Hause blieb natürlich das 
reine Chaos übrig, denn der hatte kein &lt;a href=&quot;https://de.wikipedia.org/wiki/Active_Directory&quot;&gt;Active Directory&lt;/a&gt;
und keine eigene Software-Administrationsabteilung, die seinen Rechner 
korrekt aufsetzte.&lt;/p&gt;

&lt;h3 id=&quot;lösung&quot;&gt;Lösung&lt;/h3&gt;

&lt;p&gt;Es ist doch eigentlich einfach:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Man lädt seine Binärdateien in ein definiertes Verzeichnis auf einen 
Webserver&lt;/li&gt;
  &lt;li&gt;Dann schreibt man ein Script, das nach dem Herunterladen der Binärdateien
alles an eine korrekte Stelle im Dateisystem schreibt und dann noch ein 
paar Konfigurationsdateien anpasst.&lt;/li&gt;
  &lt;li&gt;Und am Ende erstellt man ein paar fette XML (JSON oder YAML) Dateien auf 
einen zentralen öffentlichen Webserver, wo jede Software mit seinen Dateien und
Scripten verzeichnet ist.&lt;/li&gt;
  &lt;li&gt;Jetzt braucht man nur noch ein kleines Programm, das die Softwareliste
herunterlädt, gefolgt von den Binärdateien und dann das Setup-Script 
ausführt.&lt;br /&gt;
Fertig ist die allumfassende Softwareverwaltung.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;apt&lt;/code&gt;, &lt;code&gt;rpm&lt;/code&gt;, &lt;code&gt;apk&lt;/code&gt; und wie sie alle heißen machen das schon seit vielen 
vielen Jahren und jetzt rüstet Microsoft endlich mit &lt;code&gt;winget&lt;/code&gt; nach, was
im Endeffekt auch nichts anderes ist, als ein Downloader und Installer-Starter&lt;/p&gt;

&lt;h3 id=&quot;anwendung&quot;&gt;Anwendung&lt;/h3&gt;

&lt;p&gt;Microsoft plant &lt;code&gt;winget&lt;/code&gt; in Zukunft direkt mit Windows auszuliefern, 
vermutlich im frisch angekündigten[] Windows 11](https://de.wikipedia.org/wiki/Microsoft_Windows_11).
Heute müssen wir es manuell installieren, damit alles andere “automatisch”
installiert werden kann.&lt;/p&gt;

&lt;p&gt;Unter &lt;a href=&quot;https://github.com/microsoft/winget-cli/releases&quot;&gt;github.com/microsoft/winget-cli/releases&lt;/a&gt;
findet man beim neuesten Release eine &lt;code&gt;msixbundle&lt;/code&gt; Datei, die man herunterlädt
und ausführt.
Dann startet die Installation von &lt;code&gt;winget&lt;/code&gt; und am Ende kann man sofort 
seine Konsole (&lt;code&gt;cmd.exe&lt;/code&gt;) öffnen und &lt;code&gt;winget&lt;/code&gt; eintippen.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;winget search&lt;/code&gt; listet die gesamte Software auf, die man per &lt;code&gt;winget&lt;/code&gt; 
installieren kann. Natürlich kann man auch einen Token anfügen, der 
vorhanden sein muss, wie &lt;code&gt;winget search visualstudio&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;winget list&lt;/code&gt; zeigt, was bereits alles am PC installiert ist, und ob &lt;code&gt;winget&lt;/code&gt;
eine neuere Version online bereit hätte.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;winget install APP-ID&lt;/code&gt; leitet dann den Download und die Installation ein.
Die APP-ID setzt sich in der Regel aus&lt;br /&gt;
&lt;code&gt;Hersteller + &quot;.&quot; + Produkt [ + &quot;.&quot; + Untertitel ]&lt;/code&gt;&lt;br /&gt;
zusammen. Ein &lt;code&gt;winget install microsoft.openjdk.11&lt;/code&gt; installiert dann z.B. 
die neuesten Version von OpenJDK.11 (bei mir aktuell in Version 11.0.11.9)&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;winget upgrade APP-ID&lt;/code&gt; leitet die Installation einer neueren Version eines
bereits installierten Programms ein. Ich konnte z.B. per
&lt;code&gt;winget upgrade CPUID.CPU-Z&lt;/code&gt; meine aktuelle CPU-Z Version v1.92 auf 
v1.96 aktualisieren.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;winget uninstall APP-ID&lt;/code&gt; führt einfach die Deinstallations-Routine eines
Softwarepaketes aus.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;Warum erst jetzt, Microsoft? Verdammt noch mal!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Dieses Feature hätte schon vor 15 Jahren mit Windows Vista an die breiten
Massen verteilt werden können und müssen.&lt;br /&gt;
Denn das größte Problem mit Windows ist, dass jeder sich seine Software per
Suche im Internet zusammenladen muss und nicht selten landet man bei einem
bösen Abzocker, der seine eigene “FireFox-Setup.Exe” zum Download anbietet,
die dann viele weitere Holzpferdchen mitinstalliert.&lt;/p&gt;

&lt;p&gt;Ein “geprüftes” Repository, wo sich alle seriösen Hersteller eintragen können,
und ein einziges Setup-Tool, das alles installieren kann, ist doch DIE
Lösung für viele Probleme.&lt;/p&gt;

&lt;p&gt;Ich verstehe nicht, wie es so lange dauern konnte, bis so eine essentielle
Funktion endlich bereitgestellt wird.&lt;/p&gt;

&lt;p&gt;Wie auch immer … das Tool ist eine meiner großen Hoffnungen.
Und ich bin schon sehr gespannt, was sich mein älteres Ich in 10 Jahren 
denken wird, wenn es diesen Text wiederfindet.&lt;br /&gt;
Wird dann &lt;code&gt;winget&lt;/code&gt; die ganze Windows-Welt erobert haben … oder blieb es 
eine bedauernswerte Eintagsfliege, die nur mir verdammt gut gefallen hat?&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Loki und die TVA</title>
   <link href="https://www.opengate.at/blog/2021/07/loki/"/>
   <published>2021-07-17T13:00:00+02:00</published>
   <updated>2021-07-17T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2021/07/loki</id>
   <category term="entertainment" />
   <summary type="text">Diese Woche wurde die letzte Folge von Marvels
neuester Serie Loki 
ausgestrahlt (bzw. ausgestreamt).

Und … W-T-F, ich hätte nie gedacht, was sich daraus nun für die “Zukunft”
… oder sagen wir mal, “die Zeitlinie” ableiten wird.
</summary>
   <content type="html">&lt;p&gt;Diese Woche wurde die letzte Folge von &lt;a href=&quot;https://de.wikipedia.org/wiki/Marvel_Cinematic_Universe&quot;&gt;Marvels&lt;/a&gt;
neuester Serie &lt;a href=&quot;https://de.wikipedia.org/wiki/Loki_(Fernsehserie)&quot;&gt;Loki&lt;/a&gt; 
ausgestrahlt (bzw. ausgestreamt).&lt;/p&gt;

&lt;p&gt;Und … W-T-F, ich hätte nie gedacht, was sich daraus nun für die “Zukunft”
… oder sagen wir mal, “die Zeitlinie” ableiten wird.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;strong&gt;Vorsicht! Spoiler voraus!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Es war eine 1-Minuten Szene in &lt;a href=&quot;https://de.wikipedia.org/wiki/Avengers:_Endgame&quot;&gt;Avengers Endgame&lt;/a&gt;
in welcher der Hulk Schuld daran war, dass sich der bereits besiegte und 
überführte Loki mit dem Tesserakt wegteleportieren konnte.&lt;br /&gt;
Im Film musste dann eine weitere Zeitreise herhalten um den 2014 verschwundenen
Tesserakt durch einen anderen zu ersetzen und damit war die Sache gegessen.&lt;/p&gt;

&lt;p&gt;Doch schon damals wusste man, dass diese nicht weiter geklärte Szene etwas
Wichtiges bedeuten sollte. Denn Loki hätte in seinem Gefängnis in Asgard
sitzen sollen, bis die Dunkelelfen … usw. und so fort.&lt;/p&gt;

&lt;p&gt;An dieser Stelle wurde das “Multiversum” in “Marvels Cinematic Universe” 
verankert, in der es also mehrere Welten mit unterschiedlichen Ausgängen von 
Ereignissen geben konnte.&lt;/p&gt;

&lt;p&gt;Und nun erklärte uns also endlich eine eigene 6 Folgen Serie, was es mit den
“alternativen Zeitlinien” auf sich hat.&lt;br /&gt;
Denn dieses Konzept ist “schwierig”. Da fiebert man mit seinen Helden mit und
hofft, dass sie siegreich sind, und dann erfährt man, dass es sowieso 
unendlich viele Möglichkeiten gibt, wo alles anders verläuft und auch 
“die Bösen” gewinnen.&lt;br /&gt;
Das versaut einem im Nachhinein eigentlich jeden heroischen Film.&lt;/p&gt;

&lt;iframe width=&quot;640&quot; height=&quot;360&quot; src=&quot;/blog/redirect.html?https%3A%2F%2Fwww.youtube-nocookie.com%2Fembed%2F9ZcyoZlY0aU&quot; frameborder=&quot;1&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;

&lt;h3 id=&quot;genialer-einstieg&quot;&gt;Genialer Einstieg&lt;/h3&gt;

&lt;p&gt;Doch dann sehen wir in der ersten Minute der Serie Loki, wie der seiner 
Bestimmung entronnene Antiheld von einer “Zeitlinien-Polizei” (der 
Time-Variant-Authority == TVA) aufgegriffen wird.
5 Minuten später kommt der Erklär-Bär (namens Ms. Minutes) und beschreibt 
die “Heilige Zeitlinie”, die um jeden Preis erhalten werden muss und alle 
“Varianten”, die sich davon abspalten, werden von eben dieser Organisation 
wieder zurückgesetzt.&lt;/p&gt;

&lt;p&gt;WOW, damit ist der alte Weltaufbau also wieder in Ordnung. Auch trotz 
eines Multiversums mit unterschiedlichen Möglichkeiten, gibt es weiter 
nur eine “gewollte” Form, in der alles so ist und bleibt, wie wir es
gewohnt sind.&lt;/p&gt;

&lt;p&gt;… wäre da nun nicht “der Gott des Schabernaks”, der es immer wieder 
schafft Chaos in die Ordnung zu bringen.&lt;/p&gt;

&lt;h3 id=&quot;loki-vs-loki&quot;&gt;Loki vs. Loki&lt;/h3&gt;

&lt;p&gt;Und ich empfinde es schon fast als Geniestreich, dass die Serie anfangs
davon handelt, dass unser gestellter Avengers-Loki nicht ausgelöscht wird,
sondern als “Berater” fungieren soll, eine andere viel gefährlichere
Loki-Variante zu jagen und dingfest zu machen.&lt;/p&gt;

&lt;p&gt;Dass nun ein Loki mit einem anderen Loki klarkommen muss, bietet alleine
schon genug Stoff um verfilmt werden zu müssen.
Doch dass es auch noch ein Loki-Mädchen ist, macht es extrem interessant.
Und so sehen wir einige Interpretationen, wie die zwei selbst erklärten 
Bösewichte eine Beziehung zu einander aufbauen.&lt;/p&gt;

&lt;p&gt;Und es wäre nicht Marvel, wenn man nicht hinter jedem Stein eine Anspielung
und einen versteckten Hinweis finden würden.&lt;/p&gt;

&lt;h3 id=&quot;übergreifendes-chaos&quot;&gt;Übergreifendes Chaos&lt;/h3&gt;

&lt;p&gt;Am schönsten ist es (für jemanden wie mich, der die originalen Comics nicht
kennt), dass nun frühere Begriffe mehr Sinn ergeben.
“Nexus” wurde als Begriff schon in &lt;a href=&quot;https://de.wikipedia.org/wiki/WandaVision&quot;&gt;WandaVision&lt;/a&gt;
eingeführt und mit der Bedeutung der Nexus-Events erhält die andere Serie nun
nocheinmal mehr Tiefe.&lt;/p&gt;

&lt;p&gt;Und da Wanda “Chaos-Magic” nutzen kann und die TVA gegen eben dieses ankämpft
um eine “Total Madness” im Multiversum auszulösen, weist ja schon auf den
kommenden Film &lt;a href=&quot;https://www.imdb.com/title/tt9419884/&quot;&gt;Doctor Strange in the multiverse of madness&lt;/a&gt;
hin.&lt;/p&gt;

&lt;p&gt;Aber der für mich unerwartete Hammer-Moment war dann das Staffel-Finale,
das seine Ähnlichkeit zu Avengers Infinity War kaum leugnen kann.&lt;/p&gt;

&lt;p&gt;Denn nun wissen wir, welcher noch viel gefährlichere Bösewicht die nächste 
Marvel-Phase dominieren wird. Und wir haben eben (wieder) kein Happy-End, 
sondern allen Grund zu hoffen, dass sich alle Superhelden erneut formieren
um eine noch viel schlimmere Bedrohung als Thanos zu bekämpfen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Nachdem &lt;a href=&quot;https://de.wikipedia.org/wiki/The_Falcon_and_the_Winter_Soldier&quot;&gt;Falcon and the Wintersoldier&lt;/a&gt; 
ein ganz normales Actionspektakel war, hat es Loki (ähnlich wie WandaVision) 
mit seiner Story geschafft, mich zu überraschen. Nichts verlief erwartet ab 
und am Ende kam sowieso alles anders.&lt;br /&gt;
Das ist, was ich an Marvels Erzählstil wirklich schätze. Man fiebert jede Woche 
auf die neue Episode hin und kann es kaum erwarten, die Auflösung zu erhalten.&lt;/p&gt;

&lt;p&gt;Leider hat Loki aber auch die Tendenz, die vorhergehenden Filme abzuwerten.
Es fing in der ersten Folge an, wo die früher allmächtigen Infinity-Steine
nur noch kraftlose Briefbeschwerer wurden.
Und wenn am Ende immer ein noch krasserer Bösewicht zum Vorschein kommt, 
erscheinen die bereits erlebten Abenteuer wertlos und an der Stelle - 
finde ich - sollte Marvel aufpassen, dass sie sich ihr bisheriges Meisterwerk
nicht kaputt machen.&lt;/p&gt;

&lt;p&gt;Letztendlich habe ich auch etwas Angst, dass mit der Einführung von 
“Jetzt ist alles möglich und alles wird noch extremer.” die Geschichte des
Heldentums zur billigen Seifenoper verkommt.&lt;/p&gt;

&lt;p&gt;Doch … auch mit Infinity War und Endgame hat Marvel gezeigt, dass sie das
Ruder noch herumreißen können, und deshalb bin ich voller Hoffnung und 
freue mich auf die “multiple” Zukunft.&lt;/p&gt;

&lt;p&gt;Auf jeden Fall ziehe ich den Hut vor den Machern, die es trotz mehr als 10 
Jahren von unterschiedlichen Handlungssträngen es immer wieder schaffen, doch 
noch einen drauf zu setzen!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>GATE Games</title>
   <link href="https://www.opengate.at/blog/2021/07/gategames/"/>
   <published>2021-07-11T13:00:00+02:00</published>
   <updated>2021-07-11T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2021/07/gategames</id>
   <category term="devel" /><category term="software" /><category term="projects" />
   <summary type="text">Mit gategames existiert nun also die erste GATE Framework basierte Demo-App 
für Windows, X11 #
und Android, 
die per OpenGL ein bisschen Grafik 
auf die Displays zeichnet.

Damit ist ein nicht unwesentliches Teilziel des GATE-Projektes erreicht, wenn
gleich UIs kein Primärfeature darstellen.

Wie auch immer, meiner Motivation tat diese Demo recht gut.
</summary>
   <content type="html">&lt;p&gt;Mit &lt;code&gt;gategames&lt;/code&gt; existiert nun also die erste GATE Framework basierte Demo-App 
für &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows&quot;&gt;Windows&lt;/a&gt;, &lt;a href=&quot;https://de.wikipedia.org/wiki/X_Window_System&quot;&gt;X11&lt;/a&gt; #
und &lt;a href=&quot;https://de.wikipedia.org/wiki/Android_%28Betriebssystem%29&quot;&gt;Android&lt;/a&gt;, 
die per &lt;a href=&quot;https://de.wikipedia.org/wiki/OpenGL&quot;&gt;OpenGL&lt;/a&gt; ein bisschen Grafik 
auf die Displays zeichnet.&lt;/p&gt;

&lt;p&gt;Damit ist ein nicht unwesentliches Teilziel des GATE-Projektes erreicht, wenn
gleich UIs kein Primärfeature darstellen.&lt;/p&gt;

&lt;p&gt;Wie auch immer, meiner Motivation tat diese Demo recht gut.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Neben der Herausforderung den kleinsten gemeinsamen Nenner zwischen OpenGL 1.1
(Windows) und EGL (X11 Linux und Android) zu finden, und das Android-App Modell
mit einer klassischen &lt;code&gt;int main()&lt;/code&gt; basierten Anwendung zu kombinieren, 
erforderte &lt;code&gt;gategames&lt;/code&gt; eine weitere Anpassung, die ich bisher unterschätzt 
bzw. wenig bedacht hatte: Keyboard und/oder Maus-basierte Steuerung.&lt;/p&gt;

&lt;h3 id=&quot;wer-nutzt-heute-eine-maus&quot;&gt;Wer nutzt heute eine Maus?&lt;/h3&gt;

&lt;p&gt;Das Problem liegt an den Programmiermodellen “meiner Zeit”, also vor 20 Jahren,
wo es genau zwei Gruppen von Benutzer-Ereignisse gab:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;on_key_something()&lt;/code&gt;: Wenn jemand etwas über die Tastatur eingibt&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;on_mouse_something()&lt;/code&gt;: Wenn jemand mit der PC-Maus hantiert.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Und weil wir heute alle eine kleine Tastatur und eine Maus an unsere 
Smartphones anschließen, bevor wir sie nutzen, kann das ja auch so bleiben
…….. ODER ?&lt;/p&gt;

&lt;p&gt;Nun, während sich einige Frameworks genau einem Zweck widmen, können sie 
entweder für Desktop-Anwendungen so weitermachen wie bisher und wer für
Smartphones codet, arbeitet nur noch mit &lt;code&gt;on_touch_something()&lt;/code&gt;.
Ähm … leider nein, denn auch das reicht nicht. Moderne Apps werden 
teilweise auch mit Sensoren gesteuert, denn jedes Smartphone kann einigermaßen
genau sagen, wie es gerade gehalten wird und schon haben wir eine weitere
Input-Quelle … also &lt;code&gt;on_sensor_somthing()&lt;/code&gt;&lt;/p&gt;

&lt;h3 id=&quot;keycodes-und-pointer&quot;&gt;Keycodes und Pointer&lt;/h3&gt;

&lt;p&gt;Schon bei Tastaturen ergibt sich bei stark interaktiven grafischen Programmen
(auch gerne “Spiele” genannt) die Frage, will man Texte tippen, oder Elemente
per Tasten fernsteuern.&lt;br /&gt;
Bei Texten hilft uns oft das OS, in dem es einen Tastenanschlag 
(&lt;code&gt;key-down&lt;/code&gt; + &lt;code&gt;key-up&lt;/code&gt;) in ein einzelnes Ereignis umwandelt und uns ein 
generiertes UTF-Zeichen liefert. Und wer eine Taste länger drückt, bringt sein
OS dazu dem Programm vorzugaukeln, man hätte die Taste ganz schnell mehrmals
gedrückt.&lt;/p&gt;

&lt;p&gt;Wenn man aber Spiele spielt, startet das Drücken einer Taste eine Aktion und
das Loslassen beendet diese in der Regel … und genau das ist eine ganz 
andere Logik.&lt;/p&gt;

&lt;p&gt;Mäuse und Touch-Eingaben lassen sich oft als “Pointer-Events” zusammenfassen.
Man hat also mit einem “Zeigegerät” auf dem Bildschirm etwas berührt oder 
den Zeiger bewegt.
Bei der Logik von Spielen ist es aber intuitiver, wenn Mäuse bei Bewegungen
ohne Tastendruck auch eine Aktion auslösen, wie z.B. die Bildkamera im
virtuellen 3D Raum bewegen, während ein Touch-Gerät nur nach einer Berührung 
(&lt;code&gt;on_pointer_down()&lt;/code&gt;) weitere Bewegungen wahrnehmen kann.&lt;/p&gt;

&lt;p&gt;Lösen kann man das, in dem man bei jedem &lt;code&gt;on_pointer_something()&lt;/code&gt; wieder
einen Pointer-Typ übergibt.&lt;br /&gt;
Nachdem man ja an Android-Tabletts sehr wohl eine Maus anschließen kann, 
sollte man auch auf dieser Plattform auf Maus-Eingaben vorbereitet sein.&lt;/p&gt;

&lt;h3 id=&quot;implementierung&quot;&gt;Implementierung&lt;/h3&gt;

&lt;p&gt;Unter Windows ist das Sache sehr old-style artig gelöst: &lt;code&gt;WM_KEYDOWN&lt;/code&gt; und 
&lt;code&gt;WM_KEYUP&lt;/code&gt; sagen uns den VK-Code (Virtual Key Code), der vom GATE-Framework
in generische Codes übersetzt wird. Mit 
&lt;code&gt;GetKeyState(VK_CONTROL/MENU/SHIFT) &amp;amp; 0x8000&lt;/code&gt; lässt sich auch noch 
herausfinden, ob parallel zur Taste eine andere Steuertaste gedrückt wurde,
was in Spielen gerne für alternative Bewegungen genutzt wird.
&lt;code&gt;WM_LBUTTONDOWN/UP&lt;/code&gt;, &lt;code&gt;WM_RBUTTONDOWN/UP&lt;/code&gt;, &lt;code&gt;WM_MBUTTONDOWN/UP&lt;/code&gt; lassen uns 3
Mausbuttons verwalten und &lt;code&gt;WM_MOUSEMOVE&lt;/code&gt; meldet Bewegungen.&lt;/p&gt;

&lt;p&gt;In X11 holt man sich mit &lt;code&gt;XSelectInput()&lt;/code&gt; über die Event-Masken &lt;code&gt;KeyPressMask&lt;/code&gt;, 
&lt;code&gt;KeyReleaseMask&lt;/code&gt;, &lt;code&gt;ButtonPressMask&lt;/code&gt;, &lt;code&gt;ButtonReleaseMask&lt;/code&gt;, &lt;code&gt;PointerMotionMask&lt;/code&gt;
die nötigen Ereignisse via &lt;code&gt;XNextEvent()&lt;/code&gt; ab. Hier braucht man noch ein
&lt;code&gt;XLookupKeysym()&lt;/code&gt; um einen Tastencode in ein einheitliches “Symbol” umwandeln 
zu können. Auch das wird am Ende vom GATE-Framework übersetzt.&lt;/p&gt;

&lt;p&gt;Android nutzt in seinem NDK-Gluecode-Beispiel eine &lt;code&gt;ALooper&lt;/code&gt; 
Nachrichtenschleife, die sich &lt;code&gt;AInputEvent&lt;/code&gt;s abholt und dann nach Typen
sortiert bearbeitet. &lt;code&gt;AINPUT_EVENT_TYPE_KEY&lt;/code&gt; bildet dabei die Tastatur ab
und &lt;code&gt;AINPUT_EVENT_TYPE_MOTION&lt;/code&gt; verarbeitet Touch und Maus Ereignisse.
Man kann hier immer noch zwischen &lt;code&gt;AMOTION_EVENT_ACTION_DOWN/UP&lt;/code&gt; und
&lt;code&gt;AMOTION_EVENT_ACTION_POINTER_DOWN/UP&lt;/code&gt; unterscheiden und so den Finger
von der Maus oder einem Stylus unterscheiden.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Nicht ganz so trivial ist die Umwandlung der nativen Keyboard-Tasten in
generische System-Übergreifende Key-Codes, weil jedes System das ein bisschen
anders macht. Damit meine ich Dinge wie:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Nutzen &lt;code&gt;Shift&lt;/code&gt; + &lt;code&gt;A&lt;/code&gt; und nur &lt;code&gt;A&lt;/code&gt; jetzt einen Tastencode mit oder ohne 
Shift-Flag, oder wird Klein-&lt;code&gt;a&lt;/code&gt; und Groß-&lt;code&gt;A&lt;/code&gt; dafür benutzt.&lt;/li&gt;
  &lt;li&gt;Welche Tastekombinationen lassen sich nutzen und welche sind reserviert.
Weil ein &lt;code&gt;Ctrl&lt;/code&gt; + &lt;code&gt;C&lt;/code&gt; eigentlich ein Kopieren auslösen sollte, doch
eine Linux-Konsole reagiert da meist ganz anders darauf.&lt;/li&gt;
  &lt;li&gt;Und ob man jetzt eine Tastenwiederholung hat oder braucht, wenn 
eine Taste länger gedrückt wird, regeln die APIs ebenfalls abweichend.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Wie auch immer, alle diese Erkenntnisse und Codeänderungen machen es mir
nun möglich, sowohl auf grafischer Ebene kleine Spielereien auf alle
Plattformen zu bringen und gleichzeitig lassen sich auch CLI Programme
mit den neuen “vereinheitlichten” Codes steuern.&lt;/p&gt;

&lt;p&gt;In diesem Sinne: Mission accomplished! Und ab geht’s zum nächsten Thema…&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Dateneingabe im VT100 Style</title>
   <link href="https://www.opengate.at/blog/2021/07/vt100-input/"/>
   <published>2021-07-10T13:00:00+02:00</published>
   <updated>2021-07-10T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2021/07/vt100-input</id>
   <category term="devel" /><category term="projects" /><category term="retro" />
   <summary type="text">Während man unter Windows 
diverse Sondertasten durch VKEYs gut abbilden kann, steht man in 
POSIX 
oder Linux vor der Frage, wie man dort
mit Tastenkombinationen oder z.B. den F-Tasten umgehen soll.

X11 käme mit seinen keysyms
um die Ecke, doch das gilt nur für X11 apps. Aus meiner Sicht sind die alten 
VT100 Escape-Codes die einzig
“generische” Möglichkeit sich diesem Thema plattformübergreifend zu widmen.
</summary>
   <content type="html">&lt;p&gt;Während man unter &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows&quot;&gt;Windows&lt;/a&gt; 
diverse Sondertasten durch VKEYs gut abbilden kann, steht man in 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Portable_Operating_System_Interface&quot;&gt;POSIX&lt;/a&gt; 
oder &lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt; vor der Frage, wie man dort
mit Tastenkombinationen oder z.B. den F-Tasten umgehen soll.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/X_Window_System&quot;&gt;X11&lt;/a&gt; käme mit seinen &lt;code&gt;keysyms&lt;/code&gt;
um die Ecke, doch das gilt nur für X11 apps. Aus meiner Sicht sind die alten 
&lt;a href=&quot;/blog/2020/05/vt100/&quot;&gt;VT100 Escape-Codes&lt;/a&gt; die einzig
“generische” Möglichkeit sich diesem Thema plattformübergreifend zu widmen.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Code sagt mehr als tausend Worte:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color:#B44;font-weight:bold&quot;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color:#B44;font-weight:bold&quot;&gt;&amp;lt;sys/select.h&amp;gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color:#B44;font-weight:bold&quot;&gt;&amp;lt;string.h&amp;gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color:#B44;font-weight:bold&quot;&gt;&amp;lt;unistd.h&amp;gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color:#B44;font-weight:bold&quot;&gt;&amp;lt;termios.h&amp;gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; main()
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;# define&lt;/span&gt; BUFLEN &lt;span style=&quot;color:#00D&quot;&gt;32&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt; buffer[BUFLEN];
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;struct&lt;/span&gt; termios t;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;  t.c_lflag &amp;amp;= ~ICANON;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;  tcsetattr(STDIN_FILENO, TCSANOW, &amp;amp;t);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;for&lt;/span&gt;(;;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;  {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;    ssize_t received = read(STDIN_FILENO, &amp;amp;buffer[&lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;], BUFLEN);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt;(received &amp;gt; &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;    {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;      printf(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#b0b&quot;&gt;\r&lt;/span&gt;&lt;span style=&quot;color:#b0b&quot;&gt;\n&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;-----&lt;/span&gt;&lt;span style=&quot;color:#b0b&quot;&gt;\r&lt;/span&gt;&lt;span style=&quot;color:#b0b&quot;&gt;\n&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;      &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;for&lt;/span&gt;(ssize_t n = &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;; n != received; ++n)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n21&quot; name=&quot;n21&quot;&gt;21&lt;/a&gt;&lt;/span&gt;      {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n22&quot; name=&quot;n22&quot;&gt;22&lt;/a&gt;&lt;/span&gt;        &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;unsigned&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt; chr = (&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;unsigned&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt;)buffer[n];
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n23&quot; name=&quot;n23&quot;&gt;23&lt;/a&gt;&lt;/span&gt;        printf(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;%03d   0x%02x&lt;/span&gt;&lt;span style=&quot;color:#b0b&quot;&gt;\r&lt;/span&gt;&lt;span style=&quot;color:#b0b&quot;&gt;\n&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, (&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;unsigned&lt;/span&gt;)chr, (&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;unsigned&lt;/span&gt;)chr);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n24&quot; name=&quot;n24&quot;&gt;24&lt;/a&gt;&lt;/span&gt;      }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n25&quot; name=&quot;n25&quot;&gt;25&lt;/a&gt;&lt;/span&gt;      printf(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;=====&lt;/span&gt;&lt;span style=&quot;color:#b0b&quot;&gt;\r&lt;/span&gt;&lt;span style=&quot;color:#b0b&quot;&gt;\n&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n26&quot; name=&quot;n26&quot;&gt;26&lt;/a&gt;&lt;/span&gt;    }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n27&quot; name=&quot;n27&quot;&gt;27&lt;/a&gt;&lt;/span&gt;  }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n28&quot; name=&quot;n28&quot;&gt;28&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n29&quot; name=&quot;n29&quot;&gt;29&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Und jetzt sieht man, wie Tastatureingaben in Bytes übersetzt werden.&lt;/p&gt;

&lt;p&gt;Die &lt;code&gt;CTRL&lt;/code&gt; + Buchstabe Kombinationen habe ich ja 
&lt;a href=&quot;/blog/2020/06/ctrl-alt-serial/&quot;&gt;letztes Jahr geprüft&lt;/a&gt;,
doch &lt;code&gt;ALT&lt;/code&gt; Tasten und weitere Konstellationen hatte ich damals ausgespart.&lt;/p&gt;

&lt;p&gt;Wie sich hier zeigt, werden viele dieser Konstellationen mit dem &lt;code&gt;ESC&lt;/code&gt;
Zeichen (&lt;code&gt;0x1b&lt;/code&gt;) eingeleitet, wir sind also im VT100 Land.&lt;br /&gt;
Sondertasten wie die Pfeiltasten oder der Ziffernblock setzen sich zusammen
aus &lt;code&gt;0x1b&lt;/code&gt;, &lt;code&gt;0x5b&lt;/code&gt; (&lt;code&gt;[&lt;/code&gt;) und einem oder mehreren Bytes.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ALT&lt;/code&gt; + Buchstabe manifestiert sich als &lt;code&gt;0x1b&lt;/code&gt; + ASCII-Code des Buchstaben.&lt;/p&gt;

&lt;p&gt;Tja, und daraus lässt sich eine Tabelle basteln, mit der man Eingaben fixen
&lt;code&gt;switch&lt;/code&gt;-baren Codes zuordnen kann. Denn solche “Keycodes” sind wesentlich
angenehmer als eine Zuordnung mit variablen Bytefolgen durchzuführen.&lt;/p&gt;

&lt;p&gt;Und wenn es dann um das Thema plattformunabhängige Remote-Administration 
geht, haben wir auch gleich eine Lösung.&lt;/p&gt;

&lt;script src=&quot;/blog/assets/mermaid/mermaid.min.js&quot;&gt;&lt;/script&gt;
&lt;div class=&quot;mermaid&quot;&gt;
graph LR
    W[Win32&lt;br /&gt;VKEY] --&amp;gt;|Mapping| G1(GATE&lt;br /&gt;Keycode)
    G1 --&amp;gt; C{Communication&lt;br /&gt;Channel}
    C --&amp;gt; G2(GATE&lt;br /&gt;Keycode)
    G2 --&amp;gt;|Mapping| P[POSIX&lt;br /&gt;VT100]

    P --&amp;gt;|Mapping| G2
    G2 --&amp;gt; C
    C --&amp;gt; G1
    G1 --&amp;gt;|Mapping| W
&lt;/div&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Es geht also weiter mit der Analyse und dem Versuch ohne &lt;a href=&quot;https://de.wikipedia.org/wiki/Ncurses&quot;&gt;ncurses&lt;/a&gt; 
mit Eingaben an der Konsole zu arbeiten.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Fenstergrößen mit XLIB und GLES</title>
   <link href="https://www.opengate.at/blog/2021/07/xlib-resize/"/>
   <published>2021-07-04T13:00:00+02:00</published>
   <updated>2021-07-04T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2021/07/xlib-resize</id>
   <category term="devel" />
   <summary type="text">EGL 
und die XLIB bereiteten mir schon vor 
einigen Jahren Schwierigkeiten und ich bin offenbar nicht der einzige. Selbst 
die Raspberry-PI 
Edition von Minecraft kam beim 
Verändern der Fenstergröße durcheinander.

Nun treffe ich erneut auf diese Umgebung im Zuge der OpenGL 
Implementierung im GATE Projekt.
In diesem Sinne fasse ich mal meinen aktuellen Stand zusammen.
</summary>
   <content type="html">&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Open_Graphics_Library_for_Embedded_Systems&quot;&gt;EGL&lt;/a&gt; 
und die &lt;a href=&quot;https://de.wikipedia.org/wiki/Xlib&quot;&gt;XLIB&lt;/a&gt; bereiteten mir schon vor 
einigen Jahren Schwierigkeiten und ich bin offenbar nicht der einzige. Selbst 
die &lt;a href=&quot;https://de.wikipedia.org/wiki/Raspberry_Pi&quot;&gt;Raspberry-PI&lt;/a&gt; 
Edition von &lt;a href=&quot;https://de.wikipedia.org/wiki/Minecraft&quot;&gt;Minecraft&lt;/a&gt; kam beim 
Verändern der Fenstergröße durcheinander.&lt;/p&gt;

&lt;p&gt;Nun treffe ich erneut auf diese Umgebung im Zuge der &lt;a href=&quot;https://de.wikipedia.org/wiki/OpenGL&quot;&gt;OpenGL&lt;/a&gt; 
Implementierung im GATE Projekt.&lt;br /&gt;
In diesem Sinne fasse ich mal meinen aktuellen Stand zusammen.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Viele Spiele machen es sich leicht. Sie funktionieren nur im Vollbildmodus
und nicht selten stürzt eines ab, wenn sich die Auflösung ändert oder man
z.B. einen zweiten Monitor an oder absteckt und die Fenster damit den
Bildschirm wechseln.&lt;/p&gt;

&lt;p&gt;Das läuft also nach dem Schema: Screen einmal initialisieren und der bleibt
für immer so. Heute reagieren die meisten Apps zum Glück korrekt, aber 
Fehler passieren und früher war das noch viel schlimmer.&lt;/p&gt;

&lt;p&gt;Deshalb möchte ich, dass in meinen Anwendungen Fenstergrößen immer vom
Nutzer frei bestimmbar sein sollen.&lt;br /&gt;
Und im Fall der &lt;code&gt;XLIB&lt;/code&gt; bedeutet das bei meinen OpenGL-Experimenten natürlich
ein bisschen mehr Aufwand.&lt;/p&gt;

&lt;h3 id=&quot;configurenotify-event&quot;&gt;ConfigureNotify Event&lt;/h3&gt;

&lt;p&gt;Wenn man in seiner &lt;a href=&quot;https://de.wikipedia.org/wiki/X_Window_System&quot;&gt;X11&lt;/a&gt; 
Event-Mask per &lt;a href=&quot;https://tronche.com/gui/x/xlib/event-handling/XSelectInput.html&quot;&gt;&lt;code&gt;XSelectInput&lt;/code&gt;&lt;/a&gt; 
die Flags &lt;code&gt;StructureNotifyMask&lt;/code&gt; und  &lt;code&gt;SubstructureNotifyMask&lt;/code&gt; gesetzt hat, 
dann liefert &lt;a href=&quot;https://tronche.com/gui/x/xlib/event-handling/manipulating-event-queue/XNextEvent.html&quot;&gt;&lt;code&gt;XNextEvent&lt;/code&gt;&lt;/a&gt; 
auch &lt;code&gt;ConfigureNotify&lt;/code&gt; Ereignisse und dort drinnen steht, wo und wie groß 
der Benutzer sein Fenster haben möchte.&lt;/p&gt;

&lt;p&gt;Das ist also ein guter Ort um Größenveränderungen zu erkennen und 
entsprechende Callbacks auszulösen.&lt;/p&gt;

&lt;p&gt;Ich hatte anfangs den Fehler gemacht, das Ereignis &lt;code&gt;ConfigureRequest&lt;/code&gt; 
abzufangen aber dieses Unterfangen bereitete mir nur Probleme und 
Crashes.&lt;/p&gt;

&lt;p&gt;Doch die Dimensionen des Fensters beziehen sich vor allem auf die äußeren
Größen und müssen nicht zwingend mit dem Anzeigebereich übereinstimmen.&lt;/p&gt;

&lt;p&gt;Und deshalb nutze ich im Event-Callback &lt;a href=&quot;https://tronche.com/gui/x/xlib/window-information/XGetWindowAttributes.html&quot;&gt;&lt;code&gt;XGetWindowAttributes()&lt;/code&gt;&lt;/a&gt;
um die tatsächliche aktuelle Größe des Fenster-Clientbereiches auszulesen.&lt;/p&gt;

&lt;h3 id=&quot;glviewport-macht-den-rest&quot;&gt;glViewport macht den Rest&lt;/h3&gt;

&lt;p&gt;Die vorhin abgeholten Fenstergrößen werden dann in der Render-Routine
in den ersten Zeilen an &lt;a href=&quot;https://www.khronos.org/registry/OpenGL-Refpages/es2.0/xhtml/glViewport.xml&quot;&gt;&lt;code&gt;glViewport()&lt;/code&gt;&lt;/a&gt;
übergeben, also &lt;code&gt;glViewport(0, 0, width, height)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Das Verhältnis von Höhe und Breite braucht zusätzlich noch beim Setzen des 
&lt;code&gt;AspectRatio&lt;/code&gt; Wertes beim Definieren der Perspektive in der Projektionsmatrix.&lt;/p&gt;

&lt;p&gt;Das erledigt oft auch die Hilfsfunktion &lt;code&gt;gluPerspective()&lt;/code&gt;, doch leider fehlt 
die in EGL/GLES Implementierungen.&lt;br /&gt;
Dank des weltweiten Netzes konnte ich eine alternative &lt;code&gt;gluPerspective&lt;/code&gt;
Implementierung finden, dich ich hier nicht vorenthalten möchte:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt; glPerspective(GLfloat fovy, GLfloat aspect, 
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;                   GLfloat znear, GLfloat zfar)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  GLfloat f = (GLfloat)(&lt;span style=&quot;color:#60E&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#60E&quot;&gt;.0f&lt;/span&gt; / tan((fovy * PI / &lt;span style=&quot;color:#00D&quot;&gt;18&lt;/span&gt;&lt;span style=&quot;color:#60E&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#60E&quot;&gt;.0f&lt;/span&gt;) / &lt;span style=&quot;color:#60E&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#60E&quot;&gt;.0f&lt;/span&gt;));
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  GLfloat m[&lt;span style=&quot;color:#00D&quot;&gt;16&lt;/span&gt;] = {
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;    f / aspect, &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;, &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;, &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;, f, &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;, &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;, &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;, (zfar + znear) / (znear - zfar), -&lt;span style=&quot;color:#60E&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#60E&quot;&gt;.0f&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;, &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;, (&lt;span style=&quot;color:#60E&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#60E&quot;&gt;.0f&lt;/span&gt; * zfar * znear) / (znear - zfar), &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  };
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;  glMultMatrixf(m);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Und eigentlich war es das auch schon, denn nun wird die nächste Szene korrekt
an die neue Fenstergröße angepasst gezeichnet.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Am Ende des Tages läuft also auch unter X11 eine EGL Anwendung, die sich 
genau so verhält wie eine OpenGL Anwendung unter Windows.&lt;br /&gt;
Denn unter Windows konnte ich den entsprechenden &lt;code&gt;WM_SIZE&lt;/code&gt; Code quasi 
auswendig niederschreiben … doch &lt;code&gt;XLIB&lt;/code&gt; Event Details habe ich leider
nicht mehr so genau im Hinterkopf.&lt;/p&gt;

&lt;p&gt;Schließlich liegen meine X11 Experimente auch schon 10 Jahre zurück und
in der Praxis schreibt man nur selten Code auf dieser Ebene.&lt;/p&gt;

&lt;p&gt;Und was die GL-Matrizen anbelangt, da muss auch unter 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Android_%28Betriebssystem%29&quot;&gt;Android&lt;/a&gt;
rechnen, dass sie sich ändern können.&lt;br /&gt;
Denn wenn man das Smartphone kippt und keine Rotationssperre gesetzt ist,
dann ändert sich auch dort der Aspect-Ratio des Anzeigebereichs.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Android main()</title>
   <link href="https://www.opengate.at/blog/2021/07/android-main/"/>
   <published>2021-07-03T13:00:00+02:00</published>
   <updated>2021-07-03T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2021/07/android-main</id>
   <category term="devel" /><category term="projects" />
   <summary type="text">Mein erster Android 
App-Prototyp im GATE Framework ist fertig. Und nachdem Android NDK 
Apps ganz anders aufgebaut sind als übliche C int main() Programme,
musste ich einige Umleitungen legen, damit das alles läuft.

Eine gute Gelegenheit also niederzuschreiben, wie Android NDK Apps 
hochfahren und wo man was tun muss.
</summary>
   <content type="html">&lt;p&gt;Mein erster &lt;a href=&quot;https://de.wikipedia.org/wiki/Android_%28Betriebssystem%29&quot;&gt;Android&lt;/a&gt; 
App-Prototyp im GATE Framework ist fertig. Und nachdem &lt;a href=&quot;https://developer.android.com/ndk&quot;&gt;Android NDK&lt;/a&gt; 
Apps ganz anders aufgebaut sind als übliche C &lt;code&gt;int main()&lt;/code&gt; Programme,
musste ich einige Umleitungen legen, damit das alles läuft.&lt;/p&gt;

&lt;p&gt;Eine gute Gelegenheit also niederzuschreiben, wie Android &lt;code&gt;NDK&lt;/code&gt; Apps 
hochfahren und wo man was tun muss.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;In der Praxis generiert das &lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_Studio&quot;&gt;Visual Studio&lt;/a&gt;
2017+ Android Projekt-Template eigentlich schon jede Menge “Glue-Code” für 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Open_Graphics_Library_for_Embedded_Systems&quot;&gt;OpenGL-ES&lt;/a&gt; 
Projekte, wo man nur noch seinen Code in eine Render-Funktion verlegen muss.&lt;/p&gt;

&lt;p&gt;Doch im GATE Projekt möchte ich nicht, dass jede App anders “angefangen” 
werden muss. Ich möchte den Glue-Code also in den GATE-Platform-Support-Layer
schieben und den Applikationscode genau so aussehen lassen, als ob eine
&lt;code&gt;main()&lt;/code&gt; Routine (genau genommen eine &lt;code&gt;gate_main()&lt;/code&gt; Funktion) ausgeführt wird.&lt;/p&gt;

&lt;p&gt;Und dazu muss man etwas genauer wissen, was bei Android im Hintergrund passiert.&lt;/p&gt;

&lt;h3 id=&quot;ndk-apps-sind-shared-libraries&quot;&gt;NDK Apps sind “shared libraries”&lt;/h3&gt;

&lt;p&gt;Eine &lt;code&gt;NDK&lt;/code&gt; basierte Android App produziert ein &lt;a href=&quot;https://en.wikipedia.org/wiki/Library_(computing)#Shared_libraries&quot;&gt;shared object&lt;/a&gt;
(&lt;code&gt;*.so&lt;/code&gt;), das eine Funktion export, und zwar &lt;code&gt;ANativeActivity_onCreate&lt;/code&gt;. 
Beim Start lädt die Laufzeitumgebung die &lt;code&gt;SO&lt;/code&gt; Datei und ruft diese Funktion 
auf um ihr einen &lt;code&gt;ANativeActivity&lt;/code&gt; Pointer zu übergeben.&lt;/p&gt;

&lt;p&gt;Diese &lt;code&gt;ANativeActivity&lt;/code&gt; versorgt uns mit weiteren Zeigern zu 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Java_Native_Interface&quot;&gt;JNI&lt;/a&gt; und weiteren
Ressourcen, aber vor allem können wir dort eigene Callback-Routinen zu 
diversen Android-Ereignissen registrieren, wie z.B.:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;onStart&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;onResume&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;onSaveInstanceState&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;onPause&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;onStop&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;onDestroy&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;onWindowFocusChanged&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;onNativeWindowCreated&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;onNativeWindowResized&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;onNativeWindowRedrawNeeded&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;onNativeWindowDestroyed&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;onInputQueueCreated&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;onInputQueueDestroyed&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;onContentRectChanged&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;onConfigurationChanged&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;onLowMemory&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Der Glue-Code hängt an die meisten Callback-Pointer eigene Funktionen und 
ruft dann die ebenfalls generierte Funktion &lt;code&gt;android_app_create()&lt;/code&gt; auf.
Diese Funktion erzeugt eine interne &lt;code&gt;struct android_app&lt;/code&gt; in der weitere
App-relevante Daten angefügt werden können und startet einen Thread per 
&lt;code&gt;pthread_create()&lt;/code&gt; zur Funktion &lt;code&gt;android_app_entry()&lt;/code&gt;.
An dieser Stelle kehrt dann &lt;code&gt;ANativeActivity_onCreate&lt;/code&gt; zurück und alles 
weitere läuft dann in unserem Thread quasi asynchron zur Android Runtime.&lt;/p&gt;

&lt;p&gt;Innerhalb von &lt;code&gt;android_app_entry()&lt;/code&gt; wird ein “Looper” erzeugt (&lt;code&gt;ALooper_prepare&lt;/code&gt;), 
der als Nachrichtenschleife fungieren und Ereignisse wie Tasten oder 
Touch-Events empfangen soll. Der Looper nutzt Pipes um auf Events reagieren 
zu können.&lt;br /&gt;
Nachdem der Looper erzeugt wurde wird die Funktion &lt;code&gt;android_main()&lt;/code&gt; aufgerufen,
die so lange synchron ausgeführt werden soll, wie die App laufen soll.
Kehrt sie zurück, leitet &lt;code&gt;android_app_destroy()&lt;/code&gt; den Shutdown der App ein
und beendet den Thread.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;android_main()&lt;/code&gt; lässt nun die Schleife laufen, die vom Looper Events 
herauszieht, wenn welche da sind, und danach wird der OpenGL ES Code
aufgerufen um die aktuelle Szene zu zeichnen.&lt;/p&gt;

&lt;h3 id=&quot;reagieren-auf-ereignisse&quot;&gt;Reagieren auf Ereignisse&lt;/h3&gt;

&lt;p&gt;Durch die zuvor gesetzten Callbacks kommen nach der Rückkehr von 
&lt;code&gt;ANativeActivity_onCreate()&lt;/code&gt; immer wieder Callbacks von Android herein.
Solche wie &lt;code&gt;onNativeWindowCreated&lt;/code&gt; bringen eine Pointer mit, der eine Resource
bereitstellt und dieser wird an unsere &lt;code&gt;struct android_app&lt;/code&gt; Instanz dran 
geheftet. Danach wird per &lt;code&gt;android_app_write_cmd&lt;/code&gt; ein Ereignis-Byte in die 
zuvor erzeugte Pipe geschrieben, die unseren Looper aufwachen und das Ereignis
weiterverarbeiten lässt.
Die unterstützten Bytewerte sind in einer Enumeration abgebildet und 
beschreiben eigentlich alle ursprünglichen Callbacks, nämlich&lt;br /&gt;
&lt;code&gt;APP_CMD_INPUT_CHANGED&lt;/code&gt;, &lt;code&gt;APP_CMD_INIT_WINDOW&lt;/code&gt;, &lt;code&gt;APP_CMD_TERM_WINDOW&lt;/code&gt;,
&lt;code&gt;APP_CMD_WINDOW_RESIZED&lt;/code&gt;, &lt;code&gt;APP_CMD_WINDOW_REDRAW_NEEDED&lt;/code&gt;,
&lt;code&gt;APP_CMD_CONTENT_RECT_CHANGED&lt;/code&gt;, &lt;code&gt;APP_CMD_GAINED_FOCUS&lt;/code&gt;,
&lt;code&gt;APP_CMD_LOST_FOCUS&lt;/code&gt;, &lt;code&gt;APP_CMD_CONFIG_CHANGED&lt;/code&gt;, &lt;code&gt;APP_CMD_LOW_MEMORY&lt;/code&gt;, 
&lt;code&gt;APP_CMD_START&lt;/code&gt;, &lt;code&gt;APP_CMD_RESUME&lt;/code&gt;, &lt;code&gt;APP_CMD_SAVE_STATE&lt;/code&gt;,
&lt;code&gt;APP_CMD_PAUSE&lt;/code&gt;, &lt;code&gt;APP_CMD_STOP&lt;/code&gt;, &lt;code&gt;APP_CMD_DESTROY&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Ein geschriebenes Byte landet über den Looper in der Funktion &lt;code&gt;process_cmd&lt;/code&gt;,
die bei dessen Setup registriert wurde, und &lt;code&gt;process_cmd&lt;/code&gt; spaltet dann den
Aufruf in 3 Aufruf auf, und zwar in &lt;code&gt;android_app_pre_exec_cmd&lt;/code&gt;, &lt;code&gt;onAppCmd&lt;/code&gt;
und &lt;code&gt;android_app_post_exec_cmd&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;android_app_pre_exec_cmd&lt;/code&gt; bereitet Ereignisse vor und hängt empfangene
Ressourcen-Handles und -Pointer an interne Strukturen.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;onAppCmd&lt;/code&gt; leitet typische Input-Events zu eigenen Behandlungsroutinen
weiter. Hier wird also auf eine Tastenanschlag oder eine Berührung 
reagiert.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;android_app_post_exec_cmd&lt;/code&gt; kann noch Cleanups durchführen, macht aber
sonst nicht besonders viel.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Beendet wird eine App durch das Setzen eines &lt;code&gt;destroyRequested&lt;/code&gt; Flags in 
unserer &lt;code&gt;struct android_app&lt;/code&gt;. Und das geschieht im generierten Code, wenn
das Event &lt;code&gt;APP_CMD_DESTROY&lt;/code&gt; ankommt.&lt;br /&gt;
Dann wird die Nachrichten Schleife verlassen und alle Ressourcen werden
freigegeben.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Das war es auch schon wieder.&lt;br /&gt;
Es ist eigentlich mit jeder UI-Bibliothek das Gleiche.&lt;br /&gt;
Man muss wissen, wie man:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;sie initialisiert.&lt;/li&gt;
  &lt;li&gt;Zeichenoberflächen (Fenster) erhält.&lt;/li&gt;
  &lt;li&gt;auf den Oberflächen zeichnet.&lt;/li&gt;
  &lt;li&gt;Callbacks für Tasten, Mouse und Toucheingaben registriert.&lt;/li&gt;
  &lt;li&gt;am Ende alles herunterfährt.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Hat man die nötigen Funktionen dafür in einem UI Framework
gefunden, kann man dahinter “ganz normal” seine Logik weiterentwickeln.&lt;/p&gt;

&lt;p&gt;In so fern ist Android da nichts Besonderes.&lt;br /&gt;
Lustig wird es erst, wenn man dann &lt;code&gt;JNI&lt;/code&gt; für Aufgaben braucht, die
das &lt;code&gt;NDK&lt;/code&gt; nicht über C/C++ Schnittstellen bereitstellt.&lt;/p&gt;

&lt;p&gt;Aber das ist eine andere Geschichte.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Liebes Corona-Tagebuch ...</title>
   <link href="https://www.opengate.at/blog/2021/06/corona-vaccine/"/>
   <published>2021-06-29T13:00:00+02:00</published>
   <updated>2021-06-29T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2021/06/corona-vaccine</id>
   <category term="general" />
   <summary type="text">
  Liebes Corona-Tagebuch.
Heute war ich impfen.


Und damit beginnt nun für mich - so hoffe ich - eine Zeit, wo
ich nicht länger immer zur Teststraße pilgern muss, wenn ich einen
neuen Haarschnitt brauche.
</summary>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;Liebes Corona-Tagebuch.&lt;br /&gt;
Heute war ich impfen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Und damit beginnt nun für mich - so hoffe ich - eine Zeit, wo
ich nicht länger immer zur Teststraße pilgern muss, wenn ich einen
neuen Haarschnitt brauche.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Seit über drei Monaten laufen die Impfaktionen und haben bei Hochrisikofällen
angefangen dann die älteren Jahrgänge bis zu den jüngeren die Möglichkeit 
einer Immunisierung geboten.&lt;br /&gt;
Von Anfang an war ich beim Impfportal der Stadt Wien registriert und hatte 
bisher vergebens auf eine Meldung über freie Termine gewartet. Das war ein
bisschen frustrierend, weil die Verwandtschaft auf dem Lande schon vor über 
einem Monat zumindest die erste Impfung erhalten hatte.&lt;/p&gt;

&lt;p&gt;Doch ich bin letztendlich froh, dass in der Großstadt strukturiert vorgegangen
wird, und nach Prioritäten geimpft wird, und zugegeben, Priorität hatte ich
“zum Glück” keine.&lt;/p&gt;

&lt;p&gt;Es gab übrigens zwei Möglichkeiten, vorgereiht zu werden.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Die eine wäre das Zusammenleben mit einer Schwangeren.&lt;br /&gt;
Hmm, heißt also, man hätte sich von der &lt;a href=&quot;https://de.wikipedia.org/wiki/Pandemie&quot;&gt;Pandemie&lt;/a&gt;
“freivögeln” können …&lt;br /&gt;
F*ck”, warum ist mir das nicht früher eingefallen!&lt;/li&gt;
  &lt;li&gt;Mit einem Body-Mass-Index von über 32 (glaube ich) wäre man dann als 
“Fettgefressener” mit Risiko ebenfalls schon früher dran gewesen.
Ja, das wäre schon greifbar nahe gewesen, denn die Pandemie hat mir
mit über +10 kg aus Fertigfutter nicht gerade gut getan.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;impfzentrum-im-wiener-austria-center&quot;&gt;Impfzentrum im Wiener Austria Center&lt;/h3&gt;

&lt;p&gt;Unweit von jener Filmkulisse, wo der frühere König von Wakanda im Film
&lt;a href=&quot;https://de.wikipedia.org/wiki/The_First_Avenger:_Civil_War&quot;&gt;Captain America - Civil War&lt;/a&gt; 
getötet und am Ende sein Sohn eine bedeutende Rede gehalten hatte, hat Wien 
sein größtes Impfzentrum eingerichtet.
(Man könnte auch sagen: Gleich neben dem UN-Gebäudekomplex in Kaisermühlen,
aber das kennt dann wieder keiner).&lt;/p&gt;

&lt;p&gt;Wenn man aus der U-Bahn (U1) aussteigt, ist man in weniger als 5 Minuten am
ersten Checkpoint, den man ob der vielen Schilder nicht verfehlen kann.&lt;/p&gt;

&lt;p&gt;Meine Prozedur war folgende:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Mit der Anmeldung zum Termin erhielt man eine Liste der mitzubringenden
Dinge, die da waren: &lt;a href=&quot;https://de.wikipedia.org/wiki/E-card_(Chipkarte)&quot;&gt;E-Card&lt;/a&gt;, 
Lichtbildausweis, Impfpass, FFP2-Maske und ausgefüllter Impffragebogen.&lt;/li&gt;
  &lt;li&gt;Der Fragebogen stellte die üblichen Fragen nach Versicherungsnummer 
und Vorerkrankungen. Ich konnte ihn mir zu Hause ausdrucken, ausfüllen
und unterschreiben.&lt;/li&gt;
  &lt;li&gt;Vor dem Austria-Center gab es mehrere abgegrenzte Schlangenwege, an 
deren Eingang ein Security-Mitarbeiter das E-Mail oder die SMS mit dem
Impftermin sehen wollte.&lt;/li&gt;
  &lt;li&gt;Danach wurde man zügig zu einem von vielen Baucontainern gelotst, wo
die Personaldaten geprüft wurden und man eine farbige “Nummer” mitbekam.&lt;/li&gt;
  &lt;li&gt;Mit der Nummer ging es dann weiter zu einem Gebäude mit eine Schild mit
der eigenen Nummernfarbe davor und dort schickte einen der dort
stehende nächste Security-Mitarbeiter zu einem der vielen Schreibtische 
im Saal.&lt;/li&gt;
  &lt;li&gt;Hier wurde dann der Impfpass geprüft und der Sticker für die &lt;a href=&quot;https://de.wikipedia.org/wiki/COVID-19&quot;&gt;COVID19&lt;/a&gt;
Impfung eingeklebt. Ich habe dabei auch gleich einen neuen gelben Impfpass 
bekommen, weil mein alter tatsächlich schon fast voll war, da hier von 
meiner Geburt an alles eingetragen wurde.&lt;/li&gt;
  &lt;li&gt;Nun ging es 30 Meter weiter zum nächsten Schreibtisch, wo das 
“ärztliche Vorgespräch” stattfand. Nachdem mein Fragebogen keine 
Außergewöhnlichkeiten aufwies und ich nochmals erfuhr, dass es Nebenwirkungen
wie jene eines grippalen Infektes geben kann, wurde meine Impfung 
freigegeben und ich marschierte ein paar Meter weiter zu einer Impfkabine.&lt;/li&gt;
  &lt;li&gt;Tja und dann hieß es nur noch “Ärmel hochkrempeln”. Tatsächlich habe ich
den Stich überhaupt nicht gespürt, was bei meiner Wehleidigkeit selten ist,
und die Sache war somit in fast unter einer Minute vorbei.&lt;/li&gt;
  &lt;li&gt;Auf der anderen Seite der Kabine waren in großen Abständen Stühle aufgestellt,
wo die Geimpften noch 15 Minuten abwarten sollten. Wenn es zu Impfreaktionen
kommen würde, wären Sanitäter und Ärzte bereit um zu helfen.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Das war also meine erste COVID-19 Impfung. Ein Vorgang von etwa 30 Minuten.
15 Minuten um durch die Schlangenwege zu den gerade freien Registrierungsstellen
zu kommen und 15 Minuten Chill-Phase für danach.&lt;/p&gt;

&lt;p&gt;Was das anbelangt muss ich der Organisation ein großes Lob aussprechen. Ich
hatte erwartet, dass ich mich mal ein halbe Stunde wo anstellen muss, bis ich 
mich erstmals ausweisen muss.&lt;br /&gt;
Doch da an allen Checkpoints mehrere Stellen, Container oder Schreibtische 
bereit standen, wurde immer einer frei, wo mich ein Helfer sofort hinwinkte.
Somit war die Wartezeit wie auch die Bearbeitungszeit pro Checkpoint immer 
zwischen einer und fünf Minuten … also kaum messbar.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Mag sein, dass es am Anfang der Aktion länger gedauert hat bzw. der Andrang 
größer war, doch auch bei meinem Termin, heute um 12:35, waren viele Menschen 
vor Ort … aber eben genau so viel, wie das System bearbeiten konnte. 
Eine gute Terminplanung ist also schon was wert.&lt;/p&gt;

&lt;p&gt;Ich kam außerdem noch fast eine halbe Stunde zu früh und wurde trotzdem gleich
durchgewunken, da ich ja nicht gedacht hatte, so schnell ans Ziel zu gelangen.
Und ich habe auch noch einen neuen Impfpass bekommen und bin damit für die
Zukunft gerüstet.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/vaccination-cert.jpg&quot; alt=&quot;Vaccination-Certificate&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Inzwischen ist es Abend geworden und etwa zwei Stunden nach der Impfung hat 
dann mein linker “Impf-Arm” wie erwartet leicht zu schmerzen begonnen. So als 
wäre man wo dagegen gelaufen und hätte sich einen Bluterguss geholt.&lt;br /&gt;
Ich werde nun also weniger oft mit dem Arm etwas hochheben und erwarte, dass 
die “Impfprellung” in ein paar Tagen wieder abklingen wird.&lt;/p&gt;

&lt;p&gt;Ansonsten fühle ich mich gut und kann auch meiner Arbeit nachgehen.
… also alles reine Routine.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>EGL, OpenGL-ES und Linux</title>
   <link href="https://www.opengate.at/blog/2021/06/egl/"/>
   <published>2021-06-27T13:00:00+02:00</published>
   <updated>2021-06-27T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2021/06/egl</id>
   <category term="devel" />
   <summary type="text">Der kleinste gemeinsame Nenner aller Linux 
Systeme in Sachen OpenGL ist - so
mein aktueller Stand - OpenGL ES 1.0 (OpenGL for Embedded Systems, 
auch GLES oder EGL genannt), welches ein Subset von OpenGL 1.3 ist.
Genau hier schließt sich der Kreis, wie man eine GL-Codebase ohne (große)
Anpassungen auf allen Plattformen zum Laufen bekommen kann.
(Selbstverständlich geht das nur ohne Shader
einzusetzen.)

Sowohl unsere Desktop und Embedded Linux Varianten bis hin zu Android
bieten EGL Support, also ist klar, dass diese Anbindung ins GATE Projekt
muss.
</summary>
   <content type="html">&lt;p&gt;Der kleinste gemeinsame Nenner aller &lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt; 
Systeme in Sachen &lt;a href=&quot;https://de.wikipedia.org/wiki/OpenGL&quot;&gt;OpenGL&lt;/a&gt; ist - so
mein aktueller Stand - OpenGL ES 1.0 (&lt;a href=&quot;https://de.wikipedia.org/wiki/Open_Graphics_Library_for_Embedded_Systems&quot;&gt;OpenGL for Embedded Systems&lt;/a&gt;, 
auch GLES oder EGL genannt), welches ein Subset von OpenGL 1.3 ist.
Genau hier schließt sich der Kreis, wie man eine GL-Codebase ohne (große)
Anpassungen auf allen Plattformen zum Laufen bekommen kann.&lt;br /&gt;
(Selbstverständlich geht das nur ohne &lt;a href=&quot;https://de.wikipedia.org/wiki/Shader&quot;&gt;Shader&lt;/a&gt;
einzusetzen.)&lt;/p&gt;

&lt;p&gt;Sowohl unsere Desktop und Embedded Linux Varianten bis hin zu Android
bieten EGL Support, also ist klar, dass diese Anbindung ins GATE Projekt
muss.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Da OpenGL ES eine Teilmenge von OpenGL 1.3 ist, kann man sagen:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ein GLES-API basiertes Programm läuft auch unter OpenGL ohne
Anpassungen. OpenGL-API basierte Programme laufen jedoch nicht unter
GLES Umgebungen, wenn sie OpenGL-only APIs benutzen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Die Sache ist also einfach: Wir müssen bzw. dürfen nur jene APIs nutzen,
die in GLES und OpenGL gemeinsam vorkommen. Dann laden wir die entsprechenden
GL Libraries zur Laufzeit und holen nur die notwendigen Funktionszeiger 
heraus.&lt;br /&gt;
Naja … leider nicht ganz … aber grundsätzlich doch …&lt;/p&gt;

&lt;h3 id=&quot;kein-64-bit-auf-gles&quot;&gt;Kein 64 Bit auf GLES&lt;/h3&gt;

&lt;p&gt;Es ist ein bisschen kompliziert. Die GL APIs sind oft mehrfach vorhanden
und zwar für die Datentypen: &lt;code&gt;int&lt;/code&gt;, &lt;code&gt;float&lt;/code&gt; und &lt;code&gt;double&lt;/code&gt;. Bei &lt;code&gt;int&lt;/code&gt; handelt
es sich um &lt;a href=&quot;https://de.wikipedia.org/wiki/Festkommazahl&quot;&gt;Festkommazahlen&lt;/a&gt;, 
die in einen Integer abgebildet sind, und dann
noch 32 bit und 64 bit &lt;a href=&quot;https://de.wikipedia.org/wiki/Gleitkommazahl&quot;&gt;Gleitkomma-Varianten&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Bei GLES gibt es mehrere Profile, wobei &lt;code&gt;double&lt;/code&gt; auf meinen Plattformen nie
implementiert war.&lt;br /&gt;
Die Integer-Variante ist im Zahlenbereich recht limitiert und somit sind 
die &lt;code&gt;float&lt;/code&gt; Funktionen das einzige, was man plattformübergreifend nutzen kann.&lt;/p&gt;

&lt;p&gt;Also wenn man eine Farbe setzen möchte, wählt man von den verfügbaren
&lt;code&gt;glColor4d&lt;/code&gt; (double), &lt;code&gt;glColor4f&lt;/code&gt; (float), &lt;code&gt;glColor4i&lt;/code&gt; (int), 
&lt;code&gt;glColor4s&lt;/code&gt; (short) einfach nur &lt;code&gt;glColor4f&lt;/code&gt; und kann sich recht sicher sein,
dass man damit am weitesten kommen wird (außer man hat wirklich eine Plattform
erwischt, die gar keine Gleitkommazahlen kann).&lt;/p&gt;

&lt;p&gt;Ein bisschen “blöd” wird es mit einer Hand voll Funktionen, die unter OpenGL
nur eine &lt;code&gt;double&lt;/code&gt;-only und unter GLES nur eine &lt;code&gt;float&lt;/code&gt;-only Implementierung 
haben. Bei diesen musste ich bei den Funktionsdeklarationen “&lt;code&gt;#ifdef&lt;/code&gt;“-en und
einmal &lt;code&gt;float&lt;/code&gt; und einmal &lt;code&gt;double&lt;/code&gt; als Parameter wählen. In der Anwendung
selbst nutze ich dann nur &lt;code&gt;float&lt;/code&gt; welches unter OpenGL automatisch in einen 
&lt;code&gt;double&lt;/code&gt; gecastet wird.&lt;br /&gt;
Folgende Funktionen sind in meinem Anwendungsbereich betroffen und haben unter
GLES ein &lt;code&gt;f&lt;/code&gt; am Ende angefügt, während OpenGL sie ohne Suffix mit &lt;code&gt;double&lt;/code&gt; 
füttert:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.khronos.org/registry/OpenGL-Refpages/es1.1/xhtml/glClearDepth.xml&quot;&gt;&lt;code&gt;glClearDepth&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.khronos.org/registry/OpenGL-Refpages/es1.1/xhtml/glClipPlane.xml&quot;&gt;&lt;code&gt;glClipPlane&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.khronos.org/registry/OpenGL-Refpages/es1.1/xhtml/glDepthRange.xml&quot;&gt;&lt;code&gt;glDepthRange&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.khronos.org/registry/OpenGL-Refpages/es1.1/xhtml/glFrustum.xml&quot;&gt;&lt;code&gt;glFrustum&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.khronos.org/registry/OpenGL-Refpages/es1.1/xhtml/glGetClipPlane.xml&quot;&gt;&lt;code&gt;glGetClipPlane&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.khronos.org/registry/OpenGL-Refpages/es1.1/xhtml/glOrtho.xml&quot;&gt;&lt;code&gt;glOrtho&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;richtige-lib-laden&quot;&gt;Richtige Lib laden&lt;/h3&gt;

&lt;p&gt;Unter Windows lädt man seit &lt;a href=&quot;https://en.wikipedia.org/wiki/Windows_NT_4.0&quot;&gt;NT 4.0&lt;/a&gt;
einfach &lt;code&gt;opengl32.dll&lt;/code&gt; und alles ist gut.
Linux und &lt;a href=&quot;https://de.wikipedia.org/wiki/Android_%28Betriebssystem%29&quot;&gt;Android&lt;/a&gt;
machen einem das etwas schwerer, indem nicht überall alle Links gesetzt sind, 
oder die Libs grundsätzlich anders heißen.&lt;br /&gt;
Mit:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;libGLESv1_CM.so&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;libGL.so.1.2&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;libGL.so.1&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;libGL.so&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;habe ich aber eine Möglichkeitensammlung, wo meist ein Treffer dabei ist.
Aber ich wette, dass mit weiteren Plattformen weitere Libnamen möglich sein
werden.&lt;/p&gt;

&lt;h3 id=&quot;gles-ablauf&quot;&gt;GLES Ablauf&lt;/h3&gt;

&lt;p&gt;Es kommt natürlich darauf an, ob man auf UI Fenster oder in Bitmaps zeichnet,
aber folgender Ablauf ist notwendig, um per GLES den Bildschirm zu erhellen:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY)&lt;/code&gt;&lt;br /&gt;
Display-Handle holen&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;eglInitialize(egl_display, &amp;amp;egl_version_major, &amp;amp;egl_version_minor)&lt;/code&gt;&lt;br /&gt;
EGL/GLES initialisieren (und Versionsnummer abholen)&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;eglGetConfigs(egl_display, all_configs_array, all_configs_count, &amp;amp;configs_returned)&lt;/code&gt;&lt;br /&gt;
Alle unterstützten Konfigurationsprofile auslesen&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;eglChooseConfig(egl_display, attrib_list, configs_array, configs_array_capacity, &amp;amp;configs_returned)&lt;/code&gt;&lt;br /&gt;
Zu einer Liste von gewünschten Attributen alle dazu passenden 
Konfigurationsprofile auslesen. Ich nutze für Fenstergrafik folgendes:
    &lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;static&lt;/span&gt; EGLint gate_egl_attribs_window[] =
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  EGL_SURFACE_TYPE,    EGL_WINDOW_BIT,
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT,
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  EGL_RED_SIZE,        (EGLint)&lt;span style=&quot;color:#00D&quot;&gt;5&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;  EGL_GREEN_SIZE,      (EGLint)&lt;span style=&quot;color:#00D&quot;&gt;5&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  EGL_BLUE_SIZE,       (EGLint)&lt;span style=&quot;color:#00D&quot;&gt;5&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;  EGL_ALPHA_SIZE,      (EGLint)&lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;  EGL_DEPTH_SIZE,      (EGLint)&lt;span style=&quot;color:#00D&quot;&gt;16&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;//EGL_STENCIL_SIZE,  (EGLint)0,&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;  EGL_NONE
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;};
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
    &lt;/div&gt;
    &lt;p&gt;Das sind zwar nur 16-bit Farbtiefe aber funktionieren zumindest immer.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code&gt;egl_context = eglCreateContext(egl_display, configs_array[0], NULL, NULL)&lt;/code&gt;&lt;br /&gt;
Gewünschtes Profil laden, das erste gelieferte Profil von &lt;code&gt;eglChooseConfig&lt;/code&gt;
hat bei mir immer auf Anhieb funktioniert.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;egl_surface = eglCreateWindowSurface(egl_display, configs_array[0], native_window, NULL)&lt;/code&gt;&lt;br /&gt;
Nun wird die Zeichenoberfläche vorbereitet. Dafür braucht man das 
&lt;code&gt;native_window&lt;/code&gt; der Plattform. Bei &lt;a href=&quot;https://de.wikipedia.org/wiki/X_Window_System&quot;&gt;X11&lt;/a&gt;
wäre das ein Fenster, das mit &lt;code&gt;XCreateWindow()&lt;/code&gt; erzeugt wurde und bei 
Android NDK nutzt man das &lt;code&gt;ANativeWindow&lt;/code&gt; welches man über den Event-Callback 
&lt;code&gt;onNativeWindowCreated&lt;/code&gt; empfangen hat.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;eglMakeCurrent(egl_display, egl_surface, egl_surface, egl_context)&lt;/code&gt;&lt;br /&gt;
Am Ende werden “display”, “surface” und “context” gemeinsam aktiviert und 
nun kann man die üblichen &lt;code&gt;glXYZ()&lt;/code&gt; Funktionen nutzen um darauf zu zeichnen.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Tja und wenn man genug von GLES hat, muss man die Bindung und die Objekte
einfach nur freigeben:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;eglMakeCurrent(egl_display, NULL, NULL, EGL_NO_CONTEXT)&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;eglDestroySurface(egl_display, egl_surface)&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;eglDestroyContext(egl_display, egl_context)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Im Großen und Ganzen war es das auch schon.
Ein offenere Brocken ist natürlich das “Event-Handling”, also wie eine
Mausbewegung oder ein Tastendruck da noch hineinspielt und das ist natürlich
wieder extrem plattformspezifisch.&lt;br /&gt;
In Linux lässt man eine X11 &lt;a href=&quot;https://tronche.com/gui/x/xlib/events/structures.html&quot;&gt;XEvent&lt;/a&gt; 
Schleife um das  &lt;code&gt;native_window&lt;/code&gt; kreisen und im Android NDK darf man die 
entsprechenden &lt;code&gt;AInputEvent&lt;/code&gt;s empfangen um z.B. &lt;code&gt;AKeyEvent&lt;/code&gt; und 
&lt;code&gt;AMotionEvent&lt;/code&gt; herauszupicken.&lt;/p&gt;

&lt;p&gt;Das Schöne dabei ist jedoch, dass man nach der Initialisierung nicht mehr 
an die Plattform denken muss. Windows, Linux und Android können mit den
gleichen Zeichenbefehlen gefüttert werden, die (solange alles &lt;code&gt;float&lt;/code&gt; ist)
brav abgearbeitet und auf dem Anzeigegerät sichtbar werden.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>OpenGL GATEs</title>
   <link href="https://www.opengate.at/blog/2021/06/ogl/"/>
   <published>2021-06-26T13:00:00+02:00</published>
   <updated>2021-06-26T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2021/06/ogl</id>
   <category term="devel" />
   <summary type="text">Ein großer Hemmschuh für das GATE Projekt war bisher die Fixierung auf 
Windows und Linux GTK 
Bereich in Sachen UI.

Viel interessanter sind da mobile Plattformen wie Android
oder UWP,
denn diese haben einen vollkommen anderen Aufbau und können mit klassischen
Desktop-UIs nichts anfangen.

Die Idee: OpenGL öffnet die Tore 
zwischen diesen Welten.
</summary>
   <content type="html">&lt;p&gt;Ein großer Hemmschuh für das GATE Projekt war bisher die Fixierung auf 
Windows und Linux &lt;a href=&quot;https://de.wikipedia.org/wiki/GTK_(Programmbibliothek)&quot;&gt;GTK&lt;/a&gt; 
Bereich in Sachen UI.&lt;/p&gt;

&lt;p&gt;Viel interessanter sind da mobile Plattformen wie &lt;a href=&quot;https://de.wikipedia.org/wiki/Android_%28Betriebssystem%29&quot;&gt;Android&lt;/a&gt;
oder &lt;a href=&quot;https://de.wikipedia.org/wiki/Universal_Windows_Platform&quot;&gt;UWP&lt;/a&gt;,
denn diese haben einen vollkommen anderen Aufbau und können mit klassischen
Desktop-UIs nichts anfangen.&lt;/p&gt;

&lt;p&gt;Die Idee: &lt;a href=&quot;https://de.wikipedia.org/wiki/OpenGL&quot;&gt;OpenGL&lt;/a&gt; öffnet die Tore 
zwischen diesen Welten.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;vorgeschichte&quot;&gt;Vorgeschichte&lt;/h3&gt;

&lt;p&gt;Exemplarische Tests von GATE Code in Android und UWP gibt es ja schon länger.
Aber was bringt es den Inhalt eines Ordners aufzulisten, wenn man es nirgends
anzeigen kann.&lt;/p&gt;

&lt;p&gt;Genau das ist der essentielle Bruch zwischen Desktop und Phone-Apps.
Die UIs sind nicht vereinbar und das gilt auch für deren Frameworks.
So gesehen müsste ich mein Vorhaben, ein Framework für “alles” zu schaffen
genau hier als Fehlschlag beenden.&lt;/p&gt;

&lt;p&gt;Doch da gibt es ja noch OpenGL, die alte Grafik-API, die auf vielen Plattformen
für Spiele benutzt wird und wurde.&lt;br /&gt;
Denn Spiele sind stets individuell aufgebaut und bauen selten auf einem Fenster 
UI Framework auf (schon gar nicht auf dem Desktop-Framework), sondern sie 
zeichnen sich ihre Welt selbst.&lt;/p&gt;

&lt;p&gt;Ich möchte also einen neuen OpenGL-App-Typ einführen, mit dem der gleiche
Logikcode auf Windows, Linux und Android kompilierbar ist und auf jeder
Plattform eine korrekte Umsetzung davon gewährleistet ist.&lt;/p&gt;

&lt;h3 id=&quot;opengl-11-und-die-winapi&quot;&gt;OpenGL 1.1 und die WinAPI&lt;/h3&gt;

&lt;p&gt;Das größte Problem bei OpenGL sind seine Versionen und die dortigen Features, 
die sich leider extrem unterscheiden. Hatte man in OpenGL 1 noch die 
“Fixed-Function-Pipline” mit einem rein auf 3D-Grafik ausgelegten API-Set,
so wurde dieses ab OpenGL 2 durch &lt;a href=&quot;https://de.wikipedia.org/wiki/Shader&quot;&gt;Shader&lt;/a&gt;
ersetzt, wo wir Rechenvorgänge als Strings an den Shader-Compiler übergeben, 
der speziellen Code für die Grafikkarte erzeugt.&lt;/p&gt;

&lt;p&gt;Damit gewinnt man natürlich enorm viel Flexibilität, weil man alles mögliche
rechnen lassen kann, doch damit verschwinden auch die “Gemeinsamkeiten” 
zwischen 3D Renderfunktionen.&lt;br /&gt;
Doch für mich am schlimmsten ist, dass man jetzt von der Grafikkarte und 
deren Treiber abhängig ist. Passt da was nicht, lassen sich Shader-Routinen 
nicht ausführen.&lt;/p&gt;

&lt;p&gt;Im Gegensatz dazu, war OpenGL 1.1 aber auch in Software implementiert und 
man konnte 3D Szenen von der gleichen API auch auf der CPU rechnen lassen.
Das dauerte zwar viel viel länger, war aber somit stabil und immer verfügbar.&lt;/p&gt;

&lt;p&gt;Die Erkenntnis: OpenGL 1.1 Programme laufen also von &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_NT_4.0&quot;&gt;NT4&lt;/a&gt;
/ Win95 angefangen bis hin zum neuesten Windows 10 oder dessen Server 
Varianten, weil sie stets auf die CPU umschalten können, wenn die 
entsprechende Grafikhardware oder deren Treiber fehlen.&lt;br /&gt;
OpenGL 2.0 und neuer tun das nicht und so kann ich nie sicher sein, auf 
welcher Hardware meine Software letztendlich läuft.&lt;/p&gt;

&lt;h3 id=&quot;kleinstes-gemeinsames-vielfaches-vertex-arrays&quot;&gt;Kleinstes gemeinsames Vielfaches: Vertex-Arrays&lt;/h3&gt;

&lt;p&gt;Leider wird OpenGL 1.1 aber nicht von mobile Geräten wie Smartphones unterstützt,
hier kommt Embedded GL (EGL) zum Einsatz, das auf OpenGL 2 aufsetzt.
Hier wurde zwar eine Vielzahl on v1.1 APIs entfernt, doch es gibt eine Routine,
mit der man auch recht viel machen kann, die in OpenGL 1.1 und 2+ enthalten ist:
nämlich &lt;a href=&quot;https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDrawArrays.xhtml&quot;&gt;&lt;code&gt;glDrawArrays()&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Und diese Routine kann auch auf den neueren OpenGL Standards ohne den Einsatz
von Shadern durch Vertexe definierte Objekte auf eine Oberfläche zeichnen.&lt;/p&gt;

&lt;p&gt;Von daher ist meine Herausforderung die folgende:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Finde die Schnittpunkte zwischen den OpenGL Standards und 
schaffe eine gemeinsame Schnittstelle, die je nach Plattform das dortigen
Toolset nutzt um Grafikoperationen durchführen zu können.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Und so beginnt die Aufgabe bei der WinAPI, die den gesamten OpenGL 1.1
Standard in sich abgebildet hat.&lt;/p&gt;

&lt;h3 id=&quot;winapi-opengl-setup&quot;&gt;WinAPI OpenGL Setup&lt;/h3&gt;

&lt;p&gt;Hat man ein Fenster erstellt (&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-createwindowexw&quot;&gt;CreateWindowEx()&lt;/a&gt;)
und den Zeichenkontext davon (&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getdc&quot;&gt;GetDC()&lt;/a&gt;)
dann kann man recht schnell einen OpenGL Kontext dafür erzeugen.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;PIXELFORMATDESCRIPTOR format;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;format.nSize = &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;sizeof&lt;/span&gt;(format);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;format.nVersion = &lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;format.iPixelType = PFD_TYPE_RGBA;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;format.dwFlags = (PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW 
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;               | PFD_DOUBLEBUFFER);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;format.cColorBits = &lt;span style=&quot;color:#00D&quot;&gt;12&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;format.cDepthBits = &lt;span style=&quot;color:#00D&quot;&gt;16&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;format.dwLayerMask = PFD_MAIN_PLANE;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;format.iLayerType = PFD_MAIN_PLANE;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; pixel_format = ChoosePixelFormat(hdc, &amp;amp;format);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;SetPixelFormat(hdc, pixel_format, &amp;amp;format);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;HGLRC context = wglCreateContext(hdc);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;wglMakeCurrent(hdc, context);
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Danach kann man auch schon GL-Routinen nutzen und zeichnen.&lt;br /&gt;
Und mit der Funktion &lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-swapbuffers&quot;&gt;SwapBuffers()&lt;/a&gt;
wird das Gezeichnete auf dem Fenster erscheinen, wenn beim Double-Buffering
der Zeichenpuffer umgeschaltet wird.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Mit der WinAPI Implementierung ist somit eine erste OpenGL Testbasis
im GATE Projekt entstanden. Und nachdem die ersten Objekte auf dem Bildschirm
halbwegs korrekt dargestellt wurden, habe ich nun einen Vergleichswert
für andere Implementierungen.&lt;/p&gt;

&lt;p&gt;Als nächstes steht eine EGL/GLES Variante auf dem Plan, mit die OpenGL
Ansteuerung unter Linux befeuert werden soll.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Not NULL</title>
   <link href="https://www.opengate.at/blog/2021/06/not-null/"/>
   <published>2021-06-20T13:00:00+02:00</published>
   <updated>2021-06-20T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2021/06/not-null</id>
   <category term="devel" />
   <summary type="text">Beim Stöbern in alten Codes, habe ich mich wieder an eine alte “Weisheit”
erinnert, die ich oft verbreitet habe:


  Nutze stets das NULL Makro, um Pointer zu prüfen.


Für reine C++ Entwickler ist das 
natürlich hinfällig (siehe nullptr) … doch wenn man seine Gebete (auch) 
an die Mutter C 
richtet, sieht die Sache ein wenig anders aus.
</summary>
   <content type="html">&lt;p&gt;Beim Stöbern in alten Codes, habe ich mich wieder an eine alte “Weisheit”
erinnert, die ich oft verbreitet habe:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Nutze stets das &lt;code&gt;NULL&lt;/code&gt; Makro, um Pointer zu prüfen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Für reine &lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B&quot;&gt;C++&lt;/a&gt; Entwickler ist das 
natürlich hinfällig (siehe &lt;code&gt;nullptr&lt;/code&gt;) … doch wenn man seine Gebete (auch) 
an die Mutter &lt;a href=&quot;https://de.wikipedia.org/wiki/C_(Programmiersprache)&quot;&gt;C&lt;/a&gt; 
richtet, sieht die Sache ein wenig anders aus.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Wenn man in den C/C++ Headern herumwühlt, findet man meist (aber nicht immer)
folgende Implementierung&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#ifdef&lt;/span&gt; __cplusplus
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#  define&lt;/span&gt; &lt;span style=&quot;color:#069&quot;&gt;NULL&lt;/span&gt; &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#else&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#  define&lt;/span&gt; &lt;span style=&quot;color:#069&quot;&gt;NULL&lt;/span&gt; ((&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt; *)&lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#endif&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;In C++ hat die Zahlenkonstante &lt;code&gt;0&lt;/code&gt; eine ganz besondere Bedeutung. Sie wird
nämlich in genau den integralen oder Pointer-Typ konvertiert, der von
ihr erwartet wird.&lt;br /&gt;
Sowohl &lt;code&gt;int x = 0;&lt;/code&gt; als auch &lt;code&gt;int* x = 0;&lt;/code&gt; sind valider C++ Code, obwohl 
die Nullen zu etwas ganz anderem werden. Im ersten Fall eine Ganzzahl und im
zweiten Fall ein zur Null-Adresse zeigender Pointer vom Typ &lt;code&gt;int&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;C&lt;/code&gt; ist man da eigentlich nicht so tolerant und erwartet, dass eine &lt;code&gt;0&lt;/code&gt;
nur eine Ganzzahl ist. Ein Pointer ließe sich damit zwar auch initialisieren,
aber der Compiler müsste dann mindestens eine Warnung werfen, dass eine 
implizite (möglicherweise falsche) Typenkonvertierung stattgefunden hat.
(Ältere Compiler verzichten darauf allerdings und frühere Standards waren
da auch wesentlich toleranter bzw. ignoranter.)&lt;/p&gt;

&lt;p&gt;Und genau deshalb existiert das &lt;code&gt;NULL&lt;/code&gt; Makro, denn dieses erzeugt eine 
Null-Pointer-Konstante durch einen expliziten Cast der Null-Konstante (&lt;code&gt;0&lt;/code&gt;)
auf einen generischen Pointer.&lt;/p&gt;

&lt;p&gt;Genau hier gibt es wieder einen Unterschied zu C++, denn in C sollten alle
Datenzeiger implizit zu generischen Pointer konvertiert werden können
und umgekehrt.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; dummy = &lt;span style=&quot;color:#00D&quot;&gt;42&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt;* ptr_dummy = &amp;amp;dummy;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;* ptr_generic = ptr_dummy; &lt;span style=&quot;color:#777&quot;&gt;// valid everywhere&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt;* ptr_alias = ptr_generic;  &lt;span style=&quot;color:#777&quot;&gt;// valid in C, invalid in C++&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Daraus folgt, dass der Code &lt;code&gt;type_t* ptr = NULL;&lt;/code&gt; universell gültig ist
und in C dann zu einem &lt;code&gt;type_t* ptr = (type_t*)((void*)0);&lt;/code&gt; wird,
während C++ &lt;code&gt;type_t* ptr = (type_t*)0;&lt;/code&gt; direkt verstehen kann.&lt;/p&gt;

&lt;p&gt;Würde man stattdessen &lt;code&gt;type_t* ptr = 0;&lt;/code&gt; schreiben, gäbe es unter C 
eine Warnung. Schriebe man andererseits &lt;code&gt;type_t* ptr = ((void*)0);&lt;/code&gt;, 
würde C++ die Pointer-Konvertierung nicht 
(oder nur mit Bauchschmerzen == Warnungen) durchgehen lassen.&lt;/p&gt;

&lt;h3 id=&quot;null--0-&quot;&gt;NULL != 0 ?&lt;/h3&gt;

&lt;p&gt;Schon vor langer Zeit hörte ich, dass der Wert &lt;code&gt;NULL&lt;/code&gt; etwas ganz anderes
sein kann und nicht zwingend in Zusammenhang mit der Null-Konstante (&lt;code&gt;0&lt;/code&gt;) 
steht. Es könnte auch sein, dass &lt;code&gt;NULL&lt;/code&gt; so definiert ist:&lt;br /&gt;
&lt;code&gt;#define NULL ((void*)-1)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Da würde mir auch gleich eine alte Plattform einfallen, wo das sinnvoll wäre:
nämlich &lt;a href=&quot;https://de.wikipedia.org/wiki/MS-DOS&quot;&gt;DOS&lt;/a&gt;. Denn der dort aktive 
X86-Real-Mode legt an der Speicheradress &lt;code&gt;0&lt;/code&gt; seine Interrupt-Vektor-Tabelle ab.
Ein Zugriff auf diese Adresse per Pointer ist erlaubt und so könnte man 
unabsichtlich beim Schreiben auf einen &lt;code&gt;0&lt;/code&gt;-basierten Null-Pointer diese 
Tabelle korrumpieren.
Ein &lt;code&gt;NULL&lt;/code&gt; mit &lt;code&gt;-1&lt;/code&gt; könnte das verhindern.&lt;/p&gt;

&lt;p&gt;Da würde es also Sinn machen, das &lt;code&gt;NULL&lt;/code&gt; Makro auf einen Wert zu setzen, 
der einen ungültigen Speicherbereich adressiert.&lt;/p&gt;

&lt;p&gt;Mal schnell ins Archiv geguckt und … 
&lt;strong&gt;Nein&lt;/strong&gt;, &lt;a href=&quot;https://en.wikipedia.org/wiki/Turbo_C%2B%2B&quot;&gt;Turbo C++&lt;/a&gt; 1.0 und 
3.0 für DOS definieren &lt;code&gt;NULL&lt;/code&gt; so:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;#if defined(__TINY__) || defined(__SMALL__) || defined(__MEDIUM__)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;#  define NULL    0
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;#else
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;#  define NULL    0L
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;#endif
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Und das alte Microsoft C 5.1 tat das damals auch so, 
ebenfalls ohne &lt;code&gt;void*&lt;/code&gt; Cast.&lt;/p&gt;

&lt;p&gt;Im &lt;a href=&quot;http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf&quot;&gt;C Standard&lt;/a&gt; 
heißt es aber generell in 6.3.2.3, dass eine nach einem Pointer-Typ 
gecastete Null-Konstante (also die Zahl &lt;code&gt;0&lt;/code&gt;), offiziell ein Null-Pointer 
ist, mit all seinen Rechten und Pflichten. In 7.17 wird das &lt;code&gt;NULL&lt;/code&gt; Makro 
lediglich als implementierungsspezifische Null-Pointer Konstante beschrieben.
Es ist nicht definiert wie es aussehen soll, aber ein &lt;code&gt;(NULL == ((void*)0))&lt;/code&gt; 
sollte am Ende &lt;code&gt;true&lt;/code&gt; zurückgeben.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;int* ptr = (int*)0;&lt;/code&gt; oder &lt;code&gt;int* ptr = (void*)0;&lt;/code&gt; sind also in C korrekt und 
ein Null-Pointer, genau so wie &lt;code&gt;int* ptr = NULL;&lt;/code&gt; auch.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Nun, ich werde weiter versuchen, dass &lt;code&gt;NULL&lt;/code&gt; Makro einzusetzen, vor allem,
um die Kompatibilität zwischen C und C++ Code zu gewährleisten.&lt;/p&gt;

&lt;p&gt;Ich habe aber früher gerne mal behauptet:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;code&gt;NULL&lt;/code&gt; kann in C auch ungleich &lt;code&gt;(void*)0&lt;/code&gt; sein und deshalb sollte 
auch in &lt;code&gt;if&lt;/code&gt; Statements immer gegen &lt;code&gt;NULL&lt;/code&gt; verglichen werden.
Es sollte also immer &lt;code&gt;if(NULL != ptr)&lt;/code&gt; benutzt werden und keine anderen
Formen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Meine Implikation, dass &lt;code&gt;if(ptr)&lt;/code&gt; fehlerhaft sein könnte und &lt;code&gt;if(NULL != ptr)&lt;/code&gt;
immer korrekt wäre, ist jedenfalls &lt;strong&gt;nicht richtig&lt;/strong&gt;.&lt;br /&gt;
Wie auch immer … lesbarer ist der Vergleich mit &lt;code&gt;NULL&lt;/code&gt; aus meiner 
Sicht aber schon, und schadet jedenfalls nicht.&lt;/p&gt;

&lt;p&gt;Tja … den Standard zu lesen und zu verstehen ist immer eine gute Idee.
Und ich habe wieder mal gelernt, dass nur weil man 10 Jahre glaubt, dass etwas
so oder so sei, heißt das noch lange nicht, dass das auch stimmt.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Lithium Eisenphosphat Akkus</title>
   <link href="https://www.opengate.at/blog/2021/06/lifepo4/"/>
   <published>2021-06-19T13:00:00+02:00</published>
   <updated>2021-06-19T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2021/06/lifepo4</id>
   <category term="hardware" />
   <summary type="text">So cool Lithium-Polymer-Akkus
und die üblichen 3.7 V Lithium-Cobalt Zellen 
auch sind, so kennen wir auch man alle die Videos, die aufzeigen, was beim
Kurzschluss solcher Akkus passieren kann.

Eine Alternative dazu bieten 
Lithium-Eisenphosphat Akkus 
an, deren chemischer Aufbau solche extremen Gefahrensituationen ausschließt 
bzw. die Gefahren stark reduziert.
</summary>
   <content type="html">&lt;p&gt;So cool &lt;a href=&quot;https://de.wikipedia.org/wiki/Lithium-Polymer-Akkumulator&quot;&gt;Lithium-Polymer-Akkus&lt;/a&gt;
und die üblichen 3.7 V Lithium-Cobalt Zellen 
auch sind, so kennen wir auch man alle die Videos, die aufzeigen, was beim
Kurzschluss solcher Akkus passieren kann.&lt;/p&gt;

&lt;p&gt;Eine Alternative dazu bieten 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Lithium-Eisenphosphat-Akkumulator&quot;&gt;Lithium-Eisenphosphat Akkus&lt;/a&gt; 
an, deren chemischer Aufbau solche extremen Gefahrensituationen ausschließt 
bzw. die Gefahren stark reduziert.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Ich bin eher zufällig über den Begriff &lt;code&gt;LiFePO4&lt;/code&gt; im Zusammenhang mit 18650
Zellen gestoßen. Auf den ersten Blick waren das für mich schlechte Modelle,
da sie eine geringere Spannung (nämlich 3.2 V) und reduzierte Kapazitäten
im Vergleich zu den Standardakkus hatten, die mit Lithium-Cobalt &lt;code&gt;LiCoO2&lt;/code&gt;. 
Preislich liegen die Eisenzellen auch höher.&lt;/p&gt;

&lt;p&gt;Warum sollte man also mehr Geld für weniger Leistung ausgeben?&lt;/p&gt;

&lt;p&gt;Nun … Sicherheit ist ein gutes Argument!&lt;/p&gt;

&lt;iframe width=&quot;640&quot; height=&quot;360&quot; src=&quot;/blog/redirect.html?https%3A%2F%2Fwww.youtube-nocookie.com%2Fembed%2FCUgbmCSmSNY&quot; frameborder=&quot;1&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;

&lt;p&gt;Youtube ist voller Videos von Personen, die 18650 Zellen beschädigen und 
damit ein nicht kontrollierbares Feuerwerk produzieren. Gut, dass sind 
absichtlich herbeigeführte Probleme, die man im Alltag ausschließen kann.
Und ich fahre auch keine Modell-Rennauto mit Vollgas gegen die Wand, 
was einem der Akku übel nehmen könnte.&lt;/p&gt;

&lt;p&gt;Was mir aber schon passieren kann, sind Kurzschlüsse oder Überladungen.
Angenommen ich löte mir eine Ladeschaltung für einen Akku zusammen, der
am Solarmodul aufgeladen werden soll und gehe dann zur Arbeit.&lt;br /&gt;
Nun … da traue ich mir selbst und den Chips nicht hinreichend, dass 
dann nicht doch was passieren kann und ich am Abend meine Wohnung 
abgebrannt vorfinde.&lt;/p&gt;

&lt;h3 id=&quot;lifepo4-aufladen&quot;&gt;LiFePO4 aufladen&lt;/h3&gt;

&lt;p&gt;Lithium-Eisenphosphat Akkus haben kein “böses” O2 in ihrer Formel und
wirken bei Beschädigungen bei weitem nicht so intensiv als Brandbeschleuniger,
wie es bei anderen Lithium Zellen der Fall ist.&lt;br /&gt;
Das heißt natürlich nicht, dass die Eisenphosphat Akkus ungefährlich sind.
Auch sie erreichen bei hohen Strömen hohe Temperaturen, doch sie neigen nicht
zum Funkensprühen.&lt;/p&gt;

&lt;p&gt;Ich habe mir also ein paar 18650 Akkus dieser ungefährlicheren Abart gekauft.&lt;/p&gt;

&lt;p&gt;Das größte Problem mit ihnen ist die Tatsache, dass sie eine andere 
Ladesteuerung brauchen, als meine bisherigen 18650 Zellen.
Meine Ladechips basieren alle auf dem &lt;code&gt;TP4056&lt;/code&gt; Baustein und sind auf das 
Laden  mit einer Spannung von 4.2 Volt ausgelegt, was perfekt zu den 
üblichen Lithium-Ionen bzw. LiPo Akkus passt.&lt;/p&gt;

&lt;p&gt;Lithium-Eisenphosphat Akkus werden aber mit maximal 3.6 Volt geladen und 
würden mit dem &lt;code&gt;TP4056&lt;/code&gt; kräftig überladen werden.&lt;/p&gt;

&lt;p&gt;Die günstigste Lösung, die ich finden konnte, waren &lt;code&gt;TP5000&lt;/code&gt; Chips. Die sind
nämlich auf LiFePO4 Akkus voreingestellt und laden mit 3.6 Volt. Man könnte
aber auch durch das Verbinden von zwei Pins den Chip für das Laden mit 4.2 
Volt umschalten.&lt;/p&gt;

&lt;p&gt;Also habe ich mir von den Ladechips auch ein paar Stück mitbestellt.
Das Aufladen hat perfekt funktioniert und ich konnte per Messung die richtige
Spannung feststellen.&lt;/p&gt;

&lt;p&gt;Ein Negativpunkt war die Schaltung der LED, die unverlötet mitgeliefert wurde.
Es handelt sich dabei um eine Zwei-Farben LED mit einem Ground-Pin und zwei 
Stromzuflüssen. Doch mein &lt;code&gt;TP5000&lt;/code&gt; Chip ist genau anders herum gestrickt. 
Er stellt an einem Pin Strom bereit und lässt diesen an zwei Pins abfließen,
je nach Status (“Ladevorgang läuft” oder “Akku voll”).&lt;br /&gt;
Lötet man die LED einfach an das Schaltbrett, wird einem nie ein Licht 
aufgehen.&lt;/p&gt;

&lt;p&gt;Ich habe daher zwei kleinere LEDs in der korrekten Schaltrichtung eingesetzt
und nun bekomme ich mit ROT für “laden” und GRÜN für “voll” optisch mit, was
der Chips gerade tut.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/lifepo4-battery.jpg&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Die 3.2 Volt liefernden LiFePO4 Akkus sind aus meiner Sicht gut für 
&lt;a href=&quot;http://www.mikrocontroller.net/articles/AVR_Typen&quot;&gt;ATmega und ATtiny&lt;/a&gt; 
Projekt geeignet. Sie müssten auch für die auf 3.3 Volt ausgelegten
&lt;a href=&quot;https://de.wikipedia.org/wiki/ESP8266&quot;&gt;ESP8266&lt;/a&gt; und &lt;a href=&quot;https://de.wikipedia.org/wiki/ESP32&quot;&gt;ESP32&lt;/a&gt;
MCUs “gerade so” ausreichen, doch das müsste ich mal separat testen.&lt;/p&gt;

&lt;p&gt;Ich vertraue diesen Akkus weit mehr und bin bereit sie “alleine” zu Hause 
arbeiten zu lassen, während ich die regulären LiPo Akkus nur nutze, 
wenn ich anwesend bin.&lt;/p&gt;

&lt;p&gt;Einen schönen Vergleich zwischen den unterschiedlichen Akku-Typen, zeigt das
folgende Video auf:&lt;/p&gt;

&lt;iframe width=&quot;640&quot; height=&quot;360&quot; src=&quot;/blog/redirect.html?https%3A%2F%2Fwww.youtube-nocookie.com%2Fembed%2FQzt9RZ0FQyM&quot; frameborder=&quot;1&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;

&lt;p&gt;Aktuell habe ich nichts bei mir am Laufen, was zwingend auf Akkus angewiesen
ist, doch es ist gut zu wissen, dass ich eine Akku-Technologie zu Hause habe,
die bei Kurzschlüssen oder Überladungen nicht gleich Funken sprüht.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Kein Kino für mich</title>
   <link href="https://www.opengate.at/blog/2021/06/no-cinema/"/>
   <published>2021-06-18T13:00:00+02:00</published>
   <updated>2021-06-18T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2021/06/no-cinema</id>
   <category term="general" />
   <summary type="text">Die Kino-Karte für Wonderwoman 1984 
war schon bezahlt und in meinen Händen, und dann musste ich mich entscheiden 
… und … ich bin meiner Überzeugung treu geblieben und habe die Karte 
zurückgegeben.

Zumindest das schöne Wetter beim Spaziergang nach Hause hat mir die trübe
Stimmung etwas aufhellen können.
</summary>
   <content type="html">&lt;p&gt;Die Kino-Karte für &lt;a href=&quot;https://en.wikipedia.org/wiki/Wonder_Woman_1984&quot;&gt;Wonderwoman 1984&lt;/a&gt; 
war schon bezahlt und in meinen Händen, und dann musste ich mich entscheiden 
… und … ich bin meiner Überzeugung treu geblieben und habe die Karte 
zurückgegeben.&lt;/p&gt;

&lt;p&gt;Zumindest das schöne Wetter beim Spaziergang nach Hause hat mir die trübe
Stimmung etwas aufhellen können.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Naja … eigentlich war es ja meine Schuld.
Denn als bekannt gegeben wurde, dass mit 18. Juni die Kinos wieder aufsperren,
sagte ich mir spontan:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Egal was läuft, die Kinos müssen wieder in die Gänge kommen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Auf der Infoseite stand groß und breit, dass man mit Corona-Test rein darf
und ohne weiteres nachforschen wurde eine Karte reserviert.&lt;/p&gt;

&lt;p&gt;Und dann, als ich an der Kassa bezahlt hatte und mich zum Kinosaal aufmachte,
fiel mir das Klapptischchen neben dem Eingang auf und der nette Mann, der
mit einem Bündel an Zetteln jeden Kinogast kurz aufhielt.&lt;/p&gt;

&lt;p&gt;Hmm … schnell das Smartphone gezückt und das Kleingedruckte auf der 
Kinoseite aufgerufen … und, das stand es: Alle müssen registriert sein.&lt;/p&gt;

&lt;p&gt;Tja, und diese Blödheit kann und will ich nicht mitmachen.
Und eben diesen Zusatz hätte ich auch schon früher lesen bzw erahnen können,
bevor ich extra eine Corona-Test mache um ins Kino gehen zu können.
Denn die Vorgaben des Gesundheitsministeriums verlangen, dass jeder Gast 
in Gastronomie und Freizeiteinrichtungen zwecks 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Kontaktpersonennachverfolgung&quot;&gt;Contact-Tracing&lt;/a&gt; registriert
sein muss.&lt;/p&gt;

&lt;p&gt;Jetzt hätte ich nichts dagegen, dass eine offizielle staatliche Stelle
meine Daten kennt, aber ich kann es mit meinem Datenschutzgewissen nicht
vereinen, dass ich auf einem Papierzettel Namen, Adresse, Telefonnummer
und Mailadresse raufkritzeln soll und das dann durch die Hände von 
10 Praktikanten geht, bis es jemand manuell abtippt.&lt;/p&gt;

&lt;p&gt;Natürlich möchte ich den Kinoangestellten keine bösen Absichten unterstellen,
aber mir geht es um das Prinzip einer solchen Bloßstellung in der 
Öffentlichkeit.&lt;/p&gt;

&lt;p&gt;Und ich weiß, dass der Vergleich absolut unangebracht und herabwürdigend ist,
aber mein erster Gedanke bei diesem Formularklapptisch, war die Szene aus
Schindlers Liste, wo alle Juden namentlich erfasst wurden.
Kurz gesagt: Ich verabscheue so etwas.&lt;/p&gt;

&lt;h3 id=&quot;und-die-gastronomie-scheißt-sowieso-drauf&quot;&gt;Und die Gastronomie scheißt sowieso drauf&lt;/h3&gt;

&lt;p&gt;Wie der Zufall wollte, war ich die Woche zuvor schon zweimal im Restaurant
und habe wirklich ein hervorragendes und köstliches Mahl zu mir genommen.
Der &lt;a href=&quot;https://de.wikipedia.org/wiki/Corona-Test&quot;&gt;Corona-Test&lt;/a&gt; wurde vor Ort 
gemacht und war - wie erwartet - OK. Und als ich extra noch fragte, ob wir 
uns registrieren müssen, kam prompt die Antwort: Nein.&lt;/p&gt;

&lt;p&gt;Nun … rein rechtlich war das (wie ich jetzt nachgelesen habe) falsch.
Die gesetzliche Registrierungspflicht gilt überall.&lt;br /&gt;
Aber mal unabhängig vom Datenschutz … was bringt die Datensammelei, wenn
sie ohnehin nur Bruchstücke von Kontakten am Ende dem Ministerium liefern 
kann, weil viele es einfach nicht umsetzen.&lt;/p&gt;

&lt;h3 id=&quot;wie-man-es-richtig-mache-könnte&quot;&gt;Wie man es richtig mache könnte&lt;/h3&gt;

&lt;p&gt;Die Technik ist schon lange erfunden, und die App des Roten Kreuzes soll es
bereits so machen:
Man gibt nur “einen &lt;a href=&quot;https://de.wikipedia.org/wiki/Hashfunktion&quot;&gt;Hashwert&lt;/a&gt; 
von sich” her. Keine privaten Daten, nur eine eindeutige kryptografisch 
sichere ID.&lt;br /&gt;
Sollte also ein Krankheitsfall bei einem Kinobesucher festgestellt werden,
löst eine offizielle Stelle “meinen Hash” in meine richtigen Kontaktdaten
auf und kontaktiert mich.&lt;/p&gt;

&lt;p&gt;Somit ist es nicht nötig, dass ich diversen Angestellten meine privaten 
Daten auf Zetteln zukommen lasse, die sie jederzeit missbrauchen können,
sondern es gibt nur eine Stelle (mit hoffentlich gut gesicherter IT),
die meine Daten vorrätig hält und diese auch zuverlässig wieder löscht,
wenn etwas Zeit vergangen ist.&lt;/p&gt;

&lt;p&gt;Aber so wie es jetzt abläuft, wo man ungeschulte Angestellte zu 
Dateneintreibern rekrutiert und Methoden aus den vergangenen Jahrtausend
einsetzt, da dreht sich mir einfach der Magen um.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Mein größter Frust ist, dass ich nun meine geliebte 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Scarlett_Johansson&quot;&gt;Scarlett Johansson&lt;/a&gt; 
in “&lt;a href=&quot;https://de.wikipedia.org/wiki/Black_Widow_(Film)&quot;&gt;Black Widow&lt;/a&gt;” nächstes 
Monat auch nicht sehen können werde.&lt;/p&gt;

&lt;p&gt;Meine einzige Hoffnung wäre, dass diese unerträgliche 
Datenverwaltungsregelung im August zurückgenommen wird, wenn sich die 
Impfzahlen weiter erhöhen.&lt;/p&gt;

&lt;p&gt;Gewinner der Aktion sind nun erneut die amerikanischen Streaming-Portale … 
denn was bleibt mir jetzt sonst übrig, als bei denen weitere Inhalte
zu beziehen?&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>EAN-13 Barcodes</title>
   <link href="https://www.opengate.at/blog/2021/06/ean-13/"/>
   <published>2021-06-13T13:00:00+02:00</published>
   <updated>2021-06-13T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2021/06/ean-13</id>
   <category term="devel" />
   <summary type="text">Neulich waren QRCodes und Datamatrix-Codes
bei mir Thema.
Doch wie sieht es mit den älteren und am weitesten verbreiteten 
Barcodes aus?

Hier finde ich im OpenSource 
Bereich nur “böse” LGPL 
Varianten, oder Komponenten mit Abhängigkeiten zu OpenCV und Schlimmeren.

Natürlich kommt dann die Frage auf: Kann man das auch selbst schreiben?
</summary>
   <content type="html">&lt;p&gt;Neulich waren &lt;a href=&quot;/blog/2021/05/qr-dmtx/&quot;&gt;QRCodes und Datamatrix-Codes&lt;/a&gt;
bei mir Thema.&lt;br /&gt;
Doch wie sieht es mit den älteren und am weitesten verbreiteten 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Strichcode&quot;&gt;Barcodes&lt;/a&gt; aus?&lt;/p&gt;

&lt;p&gt;Hier finde ich im &lt;a href=&quot;https://de.wikipedia.org/wiki/Open_Source&quot;&gt;OpenSource&lt;/a&gt; 
Bereich nur “böse” &lt;a href=&quot;https://de.wikipedia.org/wiki/GNU_Lesser_General_Public_License&quot;&gt;LGPL&lt;/a&gt; 
Varianten, oder Komponenten mit Abhängigkeiten zu OpenCV und Schlimmeren.&lt;/p&gt;

&lt;p&gt;Natürlich kommt dann die Frage auf: Kann man das auch selbst schreiben?
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Barcodes gab es offenbar schon viele und bevor ich mich zu weit wo verlaufe,
dachte ich, fange ich mal mit dem an, was auf jedem und zwar wirklich jedem
Artikel im Kaufhaus klebt: Ein &lt;a href=&quot;https://de.wikipedia.org/wiki/European_Article_Number&quot;&gt;EAN-13 Barcode&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;ean-13&quot;&gt;EAN-13&lt;/h3&gt;

&lt;p&gt;Diese Art von Barcodes kann 13 Ziffern kodieren, und steht für 
“European Article Number”, die aber inzwischen weltweit für Artikel benutzt
werden.&lt;br /&gt;
Jede Ziffer wird durch 7 Bits definiert, wobei eine Null einem weißen und eine
Eins einem schwarzen Block entspricht. Je nachdem wie die Bits gesetzt sind,
werden die finalen Striche und Abstände damit breiter oder schmaler.&lt;/p&gt;

&lt;p&gt;Eingeleitet wird ein EAN13 Code auf beiden Seiten mit den Bits &lt;code&gt;101&lt;/code&gt;, woraus 
sich zwei dünne Striche an den Rändern abbilden, die in der Regel auch nach
unten hin länger gezeichnet werden.&lt;br /&gt;
So definiert sich die Breite eines einzelnen Bits und alle folgenden Abstände
und Strichdicken sind ein ganzzahliges Vielfaches davon.&lt;br /&gt;
Es ist auch definiert, dass vor und nach dem Barcode ein weißer Rand 
freigelassen werden muss, um den Barcode von der Umgebung abzuheben.&lt;/p&gt;

&lt;p&gt;In der Mitte befindet sich ein 5-Bit breiter Separator nach dem Schema &lt;code&gt;01010&lt;/code&gt;,
was dort ebenso zu zwei dünnen Strichen führt, die ebenso nach unten länger
gezeichnet werden.&lt;/p&gt;

&lt;p&gt;Links und rechts von der Mitte werden jeweils 6 Ziffern durch die 7 Bit breite
Strichmuster abgebildet. Man ließt also über die Strich bzw. Abstandsbreite 7
Bits aus und sieht in einer Mapping-Tabelle nach, welche Ziffer sich dahinter
verbirgt.
Doch dadurch kommt man erst auf 12 Ziffern in Summe.
Die 13. Ziffer ergibt sich aus dem Muster der im Linken Block stehenden 6 
Ziffern. Denn hier gibt es zwei Code-Tabellen (A und B), die zum Einsatz kommen 
können und je nach Kombination, welche Tabelle benutzt wurde, ergeben sich 
weitere 6 Bits und aus diesen 6 Bits lässt sich die 13. Ziffer ableiten.&lt;/p&gt;

&lt;p&gt;Man scannt also die Bits der linken Hälfte und schaut nach, ob die Bits in 
Tabelle A oder B vorkommen. Wenn man einen Treffer in A hat, nutzt man die 
Ziffer und merkt sich eine Null als Bit.
Andernfalls sieht man in B nach, nutzt die Ziffer von dort, und notiert sich 
eine Eins.
Am Ende hat man 6 Bits gesammelt, die man über eine Zusatztabelle in eine
Ziffer umwandeln kann. Diese Zahl wird übrigens dem EAN13-Code voran gestellt.
Es ist eigentlich die erste Ziffer, danach folgen die 6 Ziffern der linken
und abschließend die 6 Ziffern der rechten Hälfte.&lt;/p&gt;

&lt;p&gt;Die rechte Seite benutzt nur eine einzige Bit-Mapping-Tabelle (C) und kann
damit am einfachsten ausgelesen werden.&lt;/p&gt;

&lt;p&gt;Zu erwähnen wäre noch, dass bei den linken Codes das höchste (== erste) Bit
immer Null ist, während auf der rechten Seite das niedrigste (== letzte) Bit
stets eine Null aufweist.&lt;/p&gt;

&lt;p&gt;Im Sourcecode sehen die Tabellen bei mir etwa so aus:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#777&quot;&gt;/* first number encoding table for left side */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;static&lt;/span&gt; gate_uint8_t &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt; EAN13_CODETABLE_A[] = {
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;        &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;b00001101,        &lt;span style=&quot;color:#777&quot;&gt;/* 0 */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;        &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;b00011001,        &lt;span style=&quot;color:#777&quot;&gt;/* 1 */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;        &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;b00010011,        &lt;span style=&quot;color:#777&quot;&gt;/* 2 */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;        &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;b00111101,        &lt;span style=&quot;color:#777&quot;&gt;/* 3 */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;        &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;b00100011,        &lt;span style=&quot;color:#777&quot;&gt;/* 4 */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;        &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;b00110001,        &lt;span style=&quot;color:#777&quot;&gt;/* 5 */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;        &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;b00101111,        &lt;span style=&quot;color:#777&quot;&gt;/* 6 */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;        &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;b00111011,        &lt;span style=&quot;color:#777&quot;&gt;/* 7 */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;        &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;b00110111,        &lt;span style=&quot;color:#777&quot;&gt;/* 8 */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;        &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;b00001011         &lt;span style=&quot;color:#777&quot;&gt;/* 9 */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;};
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#777&quot;&gt;/* second number encoding table for left side */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;static&lt;/span&gt; gate_uint8_t &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt; EAN13_CODETABLE_B[] = {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;        &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;b00100111,        &lt;span style=&quot;color:#777&quot;&gt;/* 0 */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;        &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;b00110011,        &lt;span style=&quot;color:#777&quot;&gt;/* 1 */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;        &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;b00011011,        &lt;span style=&quot;color:#777&quot;&gt;/* 2 */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;        &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;b00100001,        &lt;span style=&quot;color:#777&quot;&gt;/* 3 */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n21&quot; name=&quot;n21&quot;&gt;21&lt;/a&gt;&lt;/span&gt;        &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;b00011101,        &lt;span style=&quot;color:#777&quot;&gt;/* 4 */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n22&quot; name=&quot;n22&quot;&gt;22&lt;/a&gt;&lt;/span&gt;        &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;b00111001,        &lt;span style=&quot;color:#777&quot;&gt;/* 5 */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n23&quot; name=&quot;n23&quot;&gt;23&lt;/a&gt;&lt;/span&gt;        &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;b00000101,        &lt;span style=&quot;color:#777&quot;&gt;/* 6 */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n24&quot; name=&quot;n24&quot;&gt;24&lt;/a&gt;&lt;/span&gt;        &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;b00010001,        &lt;span style=&quot;color:#777&quot;&gt;/* 7 */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n25&quot; name=&quot;n25&quot;&gt;25&lt;/a&gt;&lt;/span&gt;        &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;b00001001,        &lt;span style=&quot;color:#777&quot;&gt;/* 8 */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n26&quot; name=&quot;n26&quot;&gt;26&lt;/a&gt;&lt;/span&gt;        &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;b00010111         &lt;span style=&quot;color:#777&quot;&gt;/* 9 */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n27&quot; name=&quot;n27&quot;&gt;27&lt;/a&gt;&lt;/span&gt;};
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n28&quot; name=&quot;n28&quot;&gt;28&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n29&quot; name=&quot;n29&quot;&gt;29&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#777&quot;&gt;/* number encoding table for right side */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n30&quot; name=&quot;n30&quot;&gt;30&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;static&lt;/span&gt; gate_uint8_t &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt; EAN13_CODETABLE_C[] = {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n31&quot; name=&quot;n31&quot;&gt;31&lt;/a&gt;&lt;/span&gt;        &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;b01110010,        &lt;span style=&quot;color:#777&quot;&gt;/* 0 */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n32&quot; name=&quot;n32&quot;&gt;32&lt;/a&gt;&lt;/span&gt;        &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;b01100110,        &lt;span style=&quot;color:#777&quot;&gt;/* 1 */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n33&quot; name=&quot;n33&quot;&gt;33&lt;/a&gt;&lt;/span&gt;        &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;b01101100,        &lt;span style=&quot;color:#777&quot;&gt;/* 2 */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n34&quot; name=&quot;n34&quot;&gt;34&lt;/a&gt;&lt;/span&gt;        &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;b01000010,        &lt;span style=&quot;color:#777&quot;&gt;/* 3 */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n35&quot; name=&quot;n35&quot;&gt;35&lt;/a&gt;&lt;/span&gt;        &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;b01011100,        &lt;span style=&quot;color:#777&quot;&gt;/* 4 */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n36&quot; name=&quot;n36&quot;&gt;36&lt;/a&gt;&lt;/span&gt;        &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;b01001110,        &lt;span style=&quot;color:#777&quot;&gt;/* 5 */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n37&quot; name=&quot;n37&quot;&gt;37&lt;/a&gt;&lt;/span&gt;        &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;b01010000,        &lt;span style=&quot;color:#777&quot;&gt;/* 6 */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n38&quot; name=&quot;n38&quot;&gt;38&lt;/a&gt;&lt;/span&gt;        &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;b01000100,        &lt;span style=&quot;color:#777&quot;&gt;/* 7 */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n39&quot; name=&quot;n39&quot;&gt;39&lt;/a&gt;&lt;/span&gt;        &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;b01001000,        &lt;span style=&quot;color:#777&quot;&gt;/* 8 */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n40&quot; name=&quot;n40&quot;&gt;40&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;        &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;b01110100         &lt;span style=&quot;color:#777&quot;&gt;/* 9 */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n41&quot; name=&quot;n41&quot;&gt;41&lt;/a&gt;&lt;/span&gt;};
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n42&quot; name=&quot;n42&quot;&gt;42&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n43&quot; name=&quot;n43&quot;&gt;43&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#777&quot;&gt;/* left-table (A or B) usage pattern for very first digit */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n44&quot; name=&quot;n44&quot;&gt;44&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;static&lt;/span&gt; gate_uint8_t &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt; EAN13_PATTERNTABLE_LEFT[] =
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n45&quot; name=&quot;n45&quot;&gt;45&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n46&quot; name=&quot;n46&quot;&gt;46&lt;/a&gt;&lt;/span&gt;        &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;b00000000,        &lt;span style=&quot;color:#777&quot;&gt;/* 0 */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n47&quot; name=&quot;n47&quot;&gt;47&lt;/a&gt;&lt;/span&gt;        &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;b00001011,        &lt;span style=&quot;color:#777&quot;&gt;/* 1 */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n48&quot; name=&quot;n48&quot;&gt;48&lt;/a&gt;&lt;/span&gt;        &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;b00001101,        &lt;span style=&quot;color:#777&quot;&gt;/* 2 */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n49&quot; name=&quot;n49&quot;&gt;49&lt;/a&gt;&lt;/span&gt;        &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;b00001110,        &lt;span style=&quot;color:#777&quot;&gt;/* 3 */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n50&quot; name=&quot;n50&quot;&gt;50&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;        &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;b00010011,        &lt;span style=&quot;color:#777&quot;&gt;/* 4 */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n51&quot; name=&quot;n51&quot;&gt;51&lt;/a&gt;&lt;/span&gt;        &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;b00011001,        &lt;span style=&quot;color:#777&quot;&gt;/* 5 */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n52&quot; name=&quot;n52&quot;&gt;52&lt;/a&gt;&lt;/span&gt;        &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;b00011100,        &lt;span style=&quot;color:#777&quot;&gt;/* 6 */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n53&quot; name=&quot;n53&quot;&gt;53&lt;/a&gt;&lt;/span&gt;        &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;b00010101,        &lt;span style=&quot;color:#777&quot;&gt;/* 7 */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n54&quot; name=&quot;n54&quot;&gt;54&lt;/a&gt;&lt;/span&gt;        &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;b00010110,        &lt;span style=&quot;color:#777&quot;&gt;/* 8 */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n55&quot; name=&quot;n55&quot;&gt;55&lt;/a&gt;&lt;/span&gt;        &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;b00011010,        &lt;span style=&quot;color:#777&quot;&gt;/* 9 */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n56&quot; name=&quot;n56&quot;&gt;56&lt;/a&gt;&lt;/span&gt;};
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h3 id=&quot;implementierungsansatz&quot;&gt;Implementierungsansatz&lt;/h3&gt;

&lt;p&gt;Nun, ich habe weiß Gott keine große Erfahrung mit Bildverarbeitung und 
manche bestehende OpenSource Libs nutzen &lt;a href=&quot;https://de.wikipedia.org/wiki/OpenCV&quot;&gt;OpenCV&lt;/a&gt;
für die Stricherkennung.&lt;br /&gt;
Doch … ein bisschen nachgedacht, stellt sich raus, dass es keine 
Raketenwissenschaft ist.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Man wandelt ein Bild mit einem Barcode in eine Monochrom-Grafik um.&lt;/li&gt;
  &lt;li&gt;Dann läuft man in einer Zeile die Pixel durch und zählt die Anzahl der 
gleichfarbigen Pixel als “Längen” und füllt damit ein Array von
Weiß-Schwarz Übergängen.&lt;/li&gt;
  &lt;li&gt;Das Array beinhaltet nun potentielle Strich- und Abstand-Längen.&lt;/li&gt;
  &lt;li&gt;Nun sucht man die kürzeste Strichlänge als kleinsten Wert im Array
und nutzt ihn als Referenz.&lt;/li&gt;
  &lt;li&gt;Jetzt werden alle Längen durch die Referenz-Länge dividiert.
Das Resultat ist ein neues Array von der mit der Anzahl an gleichen
aufeinander folgenden Bits.
(Man sollte hierbei ein paar Toleranzen bei der Rundung von 
Fließkommazahlen einbauen).&lt;/li&gt;
  &lt;li&gt;Aus den Längen wird nun ein Array von Bits aufgebaut.
z.B.: &lt;code&gt;{ W:8, S:1, W:1, S:1, W:2, S:3 }&lt;/code&gt; würde dann zu &lt;code&gt;0000000010100111&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Nun sucht man nach dem Muster &lt;code&gt;01010&lt;/code&gt; und geht davon aus, dass es der
Beginn eines EAN13-Barcodes ist.&lt;/li&gt;
  &lt;li&gt;Nun kann man nach dem einleitenden &lt;code&gt;0101&lt;/code&gt; jeweils 6 mal 7 Bits mit den
Code-Mapping-Tabellen der Linken Seite abgleichen. Dann erwartet man
erneut ein &lt;code&gt;01010&lt;/code&gt; und danach werden die 6 Ziffern der rechten Hälfte
dekodiert.&lt;/li&gt;
  &lt;li&gt;Wird ein Bitmuster nicht erkannt, kann man nach einer späteren &lt;code&gt;01010&lt;/code&gt;
Sequenz suchen und dort erneut zu lesen probieren oder man erhöht die 
Referenzbreite eines Streifens und beginnt wieder bei Punkt 5.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Tatsächlich funktioniert mein Ansatz prototypisch und nun kann ich mit 
meiner Webcam Barcodes aus Artikeln auslesen.&lt;/p&gt;

&lt;p&gt;Die Sache mit der Längen-Ausdividierung erforderte ein paar Experimente.
Denn bei geringeren Auflösungen oder Unschärfe, werden auch gleich breite
Striche nicht immer in die exakt gleiche Anzahl an Pixel übersetzt.
Und dickere Striche und Abstände sind kein exaktes Vielfaches einer
Referenzbreite.&lt;br /&gt;
Man braucht also immer einen “Spielraum” und ein paar Versuche mit einer
anwachsenden Referenzbreite, bis der gesamte Barcode fehlerfrei ausgelesen
werden kann.&lt;/p&gt;

&lt;p&gt;In Summe bin ich aber zufrieden. Etwa 300 Zeilen purer &lt;a href=&quot;https://de.wikipedia.org/wiki/C_(Programmiersprache)&quot;&gt;C Code&lt;/a&gt;
im GATE Projekt haben gereicht, um provisorisch EAN13 Barcodes auslesen zu 
können. Und daraus lassen sich &lt;a href=&quot;https://de.wikipedia.org/wiki/Internationale_Standardbuchnummer&quot;&gt;ISBN&lt;/a&gt;
Nummern von Büchern und vieles mehr generieren.&lt;/p&gt;

&lt;p&gt;Ich denke … ich sollte die Codebase irgendwie mal auf ein Android Phone
bringen und dann im Supermarkt mal Scanexperimente starten um zu sehen, 
wie gut oder schlecht das nun wirklich funktioniert.&lt;/p&gt;

&lt;p&gt;However … wieder etwas gelernt … und eine mögliche Karriere als
Kassenprogrammierer ist nun auch etwas näher gerückt.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Store Apps manuell installieren</title>
   <link href="https://www.opengate.at/blog/2021/06/ltsb-store/"/>
   <published>2021-06-05T13:00:00+02:00</published>
   <updated>2021-06-05T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2021/06/ltsb-store</id>
   <category term="software" />
   <summary type="text">Tja … was ist jetzt besser?
Eine offene und freie Plattform, wo jeder sein eigenes Süppchen kocht?
Oder ein zentralistischer Monarch, der Stabilität durch Einheitlichkeit 
verspricht?

Microsoft wollte mit seinen Windows Store Apps
vom ersten zum zweiten Weg wechseln. Doch die Enterprise IOT
LTSC (Long Term Service Channel) Varianten und die Server rudern wieder zurück.

Wie kann man das vereinen?
</summary>
   <content type="html">&lt;p&gt;Tja … was ist jetzt besser?&lt;br /&gt;
Eine offene und freie Plattform, wo jeder sein eigenes Süppchen kocht?
Oder ein zentralistischer Monarch, der Stabilität durch Einheitlichkeit 
verspricht?&lt;/p&gt;

&lt;p&gt;Microsoft wollte mit seinen &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Store&quot;&gt;Windows Store Apps&lt;/a&gt;
vom ersten zum zweiten Weg wechseln. Doch die &lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_IoT#Windows_10_IoT_Enterprise&quot;&gt;Enterprise IOT&lt;/a&gt;
LTSC (Long Term Service Channel) Varianten und die Server rudern wieder zurück.&lt;/p&gt;

&lt;p&gt;Wie kann man das vereinen?
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Den Windows Store findet man in allen Endanwender Produkten von Windows 10, 
auch in Windows 10 IOT Enterprise, wenn es an den Semi-Annual-Channel (SAC)
gebunden ist und wie die Consumer-Versionen permanent aktualisiert wird.&lt;/p&gt;

&lt;p&gt;Doch im Long-Term Service Channel (LTSC) fehlen die Store-App und auch die 
anderen üblichen Mitbringsel wie die Mail App oder der “neue” Taschenrechner.
Nur die Einstellungs bzw. Settings App liegt nativ bei.&lt;/p&gt;

&lt;p&gt;Das Gleiche haben wir auch bei den Server Plattformen, die ebenso auf den 
Store und deren Apps verzichten.&lt;/p&gt;

&lt;p&gt;Wie bekommt also Mails auf einem IOT Enterprise LTSC Terminal angezeigt?&lt;/p&gt;

&lt;h3 id=&quot;manueller-download&quot;&gt;Manueller Download&lt;/h3&gt;

&lt;p&gt;Ohne die Store App, hat man vor allem das Problem, dass man nicht so leicht
an einen Download Link kommt, mit dem man weiterarbeiten kann.&lt;br /&gt;
Glücklicherweise wurde dieses Problem schon von findigen Mitstreitern gelöst,
und so entstand die WebSite: &lt;a href=&quot;https://store.rg-adguard.net/&quot;&gt;store.rg-adguard.net&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Geht man auf die Store-Webseite in seiner lokalen Variante, z.B.:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;https://www.microsoft.com/en-us/store/apps/windows&lt;/li&gt;
  &lt;li&gt;https://www.microsoft.com/de-de/store/apps/windows&lt;/li&gt;
  &lt;li&gt;https://www.microsoft.com/de-at/store/apps/windows&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;und findet über die Suchfunktion die gewünschte App, sieht man im Link zur App
die &lt;code&gt;Product ID&lt;/code&gt; als Buchstaben- und Zahlenkombination am Ende,
z.B.: https://www.microsoft.com/de-at/p/mail-und-kalender/9wzdncrfhvqm&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;a href=&quot;https://www.microsoft.com/store/productId/9WZDNCRFHVQM&quot;&gt;Windows Mail App&lt;/a&gt;&lt;br /&gt;
ProductID: 9WZDNCRFHVQM&lt;br /&gt;
CategoryID: 64a79953-cf0b-44f9-b5c4-ee5df3a15c63&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Kopiert man diesen Link dann ins Eingabefeld von store.rg-adguard.net, dann
erhält man die Links zu allen &lt;code&gt;appx&lt;/code&gt; und &lt;code&gt;appxbundle&lt;/code&gt; Paketen für alle 
von der App unterstützten Plattformen.&lt;/p&gt;

&lt;p&gt;Nun lädt man sich alle &lt;code&gt;appx&lt;/code&gt; und &lt;code&gt;appxbundle&lt;/code&gt; Dateien der eigenen Plattform 
herunter, bzw. manche tragen auch den Titel &lt;code&gt;neutral&lt;/code&gt; wenn sie
plattformunabhängig sind, und installiert diese über die &lt;code&gt;powershell&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://tlu.dl.delivery.mp.microsoft.com/filestreamingservice/files/3ed8ad89-ec2f-44bf-a38b-d75989e80b0a?P1=1622849513&amp;amp;P2=404&amp;amp;P3=2&amp;amp;P4=ANXRw7E6CXxzb7tBL40tq6RUqpIL05dPusHFGBvJPvWVCaSN0N0lFGY8ow3JxtziHtWMayRvHM9BTsmPBmQt4Q%3d%3d&quot;&gt;Microsoft.VCLibs.140.00 X64&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://tlu.dl.delivery.mp.microsoft.com/filestreamingservice/files/db8f70ad-901c-48f9-b306-339605b25d64?P1=1622854921&amp;amp;P2=404&amp;amp;P3=2&amp;amp;P4=LvsObAafgELhhQpIHjWimrvHCN3uHd8lnUu2cnuTUpHqZd90c2WEOqeFttjlIBM92MCJNThwEUVYDZqE0Qxa%2fg%3d%3d&quot;&gt;microsoft.windowscommunicationsapps 16005.13426.20920.0 neutral&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Und so konnte ich mit:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;Add-AppXPackage -Path `
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;  &amp;quot;C:\path\to\Microsoft.VCLibs.140.00_14.0.30035.0_x64__8wekyb3d8bbwe.Appx&amp;quot;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;Add-AppXPackage -Path `
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  &amp;quot;...\microsoft.windowscommunicationsapps_16005.13426.20920.0_.....AppxBundle&amp;quot;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;die Windows Mail App auf mein Windows 10 IOT Enterprise bringen.
Ganz ohne Windows Store.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Eigentlich ist es ja ganz lustig zu lernen, was die Windows Store App im
Hintergrund macht um Apps zu installieren.&lt;/p&gt;

&lt;p&gt;Doch ein bisschen eigenartig ist das schon, dass Store-Apps heute “die”
Plattform sein sollen und gleichzeitig distanziert man sich im IOT Bereich 
davon.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Hamster Kolonien in Wien</title>
   <link href="https://www.opengate.at/blog/2021/06/hamster-area/"/>
   <published>2021-06-03T13:00:00+02:00</published>
   <updated>2021-06-03T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2021/06/hamster-area</id>
   <category term="general" />
   <summary type="text">Normalerweise erlebt man Tiere in Wien nur streng gesittet als Hunde an der
Leine oder als Katzen hinter Fenstergittern in den Wohnungen. Ein paar Leute 
halten sich noch ein Meerschweinchen oder einen Vogel im Käfig
(… oder sind mit einem verheiratet), aber das war es “in der Großstadt” 
somit auch schon, wenn man nach Tieren sucht.

OK … es gibt jede Menge Tauben in den Gassen, aber die zählen hier nicht 
wirklich, und die Exoten im Tiergarten lassen wir auch mal weg.

Aber fast niemand kennt die riesige Hamsterkolonie, die einen besonders 
schönen Fleck mitten in der Stadt buchstäblich untergraben hat.
</summary>
   <content type="html">&lt;p&gt;Normalerweise erlebt man Tiere in Wien nur streng gesittet als Hunde an der
Leine oder als Katzen hinter Fenstergittern in den Wohnungen. Ein paar Leute 
halten sich noch ein Meerschweinchen oder einen Vogel im Käfig
(… oder sind mit einem verheiratet), aber das war es “in der Großstadt” 
somit auch schon, wenn man nach Tieren sucht.&lt;/p&gt;

&lt;p&gt;OK … es gibt jede Menge Tauben in den Gassen, aber die zählen hier nicht 
wirklich, und die Exoten im Tiergarten lassen wir auch mal weg.&lt;/p&gt;

&lt;p&gt;Aber fast niemand kennt die riesige Hamsterkolonie, die einen besonders 
schönen Fleck mitten in der Stadt buchstäblich untergraben hat.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Ein paar hundert Meter vom Meidlinger Bahnhof entfernt liegt mitten 
im 12. Bezirk der lokale &lt;a href=&quot;https://de.wikipedia.org/wiki/Meidlinger_Friedhof&quot;&gt;Friedhof&lt;/a&gt;. 
Während auf den angrenzenden Straßen der übliche Verkehr tobt, schützen Bäume, 
Hecken und Sträucher ein eigentlich recht großes grünes Areal, auf dem viele 
Menschen ihre letzte Ruhestätte gefunden haben.&lt;/p&gt;

&lt;p&gt;Neben teuren Obelisk-artigen Riesengrabstätten der ehemaligen High-Society,
liegen auch zahlreiche, oft schon stark verfallene Gräber, Grabsteine und
Kreuze aus früheren wie auch aus aktuellen Zeiten.&lt;/p&gt;

&lt;p&gt;Es mag makaber klingen, doch ein ruhiger Spaziergang durch eben diesen
Friedhof wirkt auf mich stets entspannend und ist ein 
wohltuenderer Zeitvertreib, als durch diverse Parks zu schlendern.&lt;/p&gt;

&lt;p&gt;Einen ganz besonderen Aspekt hat dieser Friedhof, wie ich es sonst noch 
nie erlebt habe:&lt;br /&gt;
Er beherbergt eine große Anzahl von Feldhamstern, die in den Gräsern 
zwischen den Gräbern nach Nahrung suchen.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/hamster-area.jpg&quot; alt=&quot;Hamster Area&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Man stößt auf diesem Friedhof zwangsläufig alle 5 Meter auf ein kleines
Loch im Boden, wo eine Hamsterfamilie wohnt und alle paar Minuten huscht
einer der kleinen Fellgesellen aus einer der Bodenöffnungen und durchstöbert 
die Umgebung.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/hamster01.jpg&quot; alt=&quot;Hamster Pic 1&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Da zwischen den Gräbern immer wieder größere begraste Grünstreifen verlaufen,
finden die niedlichen Vierbeiner jede Menge Pflanzen und Körner vor, die sie
vernaschen können. Auf Gräberdekorationen, die Hamstern schmecken könnten, 
sollte man auf diesem Friedhof daher eher verzichten.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/hamster02.jpg&quot; alt=&quot;Hamster Pic 2&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Die Hamster haben sich vermutlich schon sehr an die auf dem Friedhof die
Gräber besuchenden Menschen gewöhnt und nehmen kaum Notiz von ihnen.&lt;/p&gt;

&lt;p&gt;Wenn man sich ihnen jedoch nähert wird man zuerst mit großen Augen gemustert.
Aber sobald man sich auf 3 Meter anpirscht, beschließen sie zumeist 
das Weite zu suchen.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/hamster03.jpg&quot; alt=&quot;Hamster Pic 3&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Doch, wenn man ruhig stehen bleibt und die kleinen Nager freundlich anlächelt,
passiert manchmal etwas Besonderes, so wie ich es neulich erleben durfte:&lt;/p&gt;

&lt;p&gt;Langsam und vorsichtig kommen sie näher und beschnuppern behutsam die Schuhe,
blicken dann freundlich nach oben zu dessen Besitzer und laufen dann 
gemütlich weiter um wieder nach etwas Essbarem zu suchen.&lt;/p&gt;

&lt;p&gt;Schade, dass ich bei diesem Ereignis keine Kamera parat hatte, aber das 
Zücken des Smartphones hätte den kleinen Freund vermutlich verschreckt.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Und so geht wieder ein äußerst schöner Tag vorbei, an dem ich am Friedhof 
einen neuen Freund kennenlernen durfte, der dort mit seiner Familie 
vielleicht schon länger dort lebt, als ich selbst in Wien wohne.&lt;/p&gt;

&lt;p&gt;Nun denke ich mir wieder, in was für einer schönen Stadt ich leben darf, in 
der wenige hundert Meter weiter die neuesten Technologien am Werk sind, und 
wo gleichzeitig eine Hamsterkolonie so lebt, wie vor hunderten von Jahren, 
als der gesamte Grund dort Felder waren und Wien nur ein Städtchen mit der 
Ausdehnung des heutigen ersten Bezirks war.&lt;/p&gt;

&lt;p&gt;Ich sollte mal weitere Spaziergänge machen. Vielleicht verbergen sich noch 
andere Naturreservate hinter den Gassen, die man so in der Großstadt gar 
nicht erwarten würde.&lt;/p&gt;

&lt;h3 id=&quot;nachtrag-besuch-im-september&quot;&gt;Nachtrag: Besuch im September&lt;/h3&gt;

&lt;p&gt;Und wieder kam ein Grabbewohner angelaufen, grüßte freundlich und zog sich 
dann wieder zurück.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/hamster-movie-01.jpg&quot; alt=&quot;Hamster-Movie-01&quot; /&gt;
&lt;img src=&quot;/blog/assets/img/hamster-movie-02.jpg&quot; alt=&quot;Hamster-Movie-02&quot; /&gt;
&lt;img src=&quot;/blog/assets/img/hamster-movie-03.jpg&quot; alt=&quot;Hamster-Movie-03&quot; /&gt;
&lt;img src=&quot;/blog/assets/img/hamster-movie-04.jpg&quot; alt=&quot;Hamster-Movie-04&quot; /&gt;
&lt;img src=&quot;/blog/assets/img/hamster-movie-05.jpg&quot; alt=&quot;Hamster-Movie-05&quot; /&gt;
&lt;img src=&quot;/blog/assets/img/hamster-movie-06.jpg&quot; alt=&quot;Hamster-Movie-06&quot; /&gt;
&lt;img src=&quot;/blog/assets/img/hamster-movie-07.jpg&quot; alt=&quot;Hamster-Movie-07&quot; /&gt;
&lt;img src=&quot;/blog/assets/img/hamster-movie-08.jpg&quot; alt=&quot;Hamster-Movie-08&quot; /&gt;
&lt;img src=&quot;/blog/assets/img/hamster-movie-09.jpg&quot; alt=&quot;Hamster-Movie-09&quot; /&gt;
&lt;img src=&quot;/blog/assets/img/hamster-movie-10.jpg&quot; alt=&quot;Hamster-Movie-10&quot; /&gt;
&lt;img src=&quot;/blog/assets/img/hamster-movie-11.jpg&quot; alt=&quot;Hamster-Movie-11&quot; /&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>install.wim für FAT32 USB Stick</title>
   <link href="https://www.opengate.at/blog/2021/05/wim-split/"/>
   <published>2021-05-30T13:00:00+02:00</published>
   <updated>2021-05-30T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2021/05/wim-split</id>
   <category term="software" />
   <summary type="text">Früher waren Windows Vista, 
Windows 7 und Windows 8 Installations-Images in den install.wim Dateien nie 
größter als 4 GB. Und somit konnte man sie problemlos auf einen USB Stick 
packen, der mit FAT32
formatiert war.

Doch mit integrierten Updates und generell ab Windows 10 wurde die 4 GB Marke
durchbrochen. Man kann einen USB Stick natürlich mit NTFS
formatieren, doch dann funktioniert keine EFI-Installation mehr.

Die richtige Lösung ist: 
WIM aufsplitten.
</summary>
   <content type="html">&lt;p&gt;Früher waren &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_Vista&quot;&gt;Windows Vista&lt;/a&gt;, 
Windows 7 und Windows 8 Installations-Images in den &lt;code&gt;install.wim&lt;/code&gt; Dateien nie 
größter als 4 GB. Und somit konnte man sie problemlos auf einen USB Stick 
packen, der mit &lt;a href=&quot;https://de.wikipedia.org/wiki/File_Allocation_Table#FAT32&quot;&gt;FAT32&lt;/a&gt;
formatiert war.&lt;/p&gt;

&lt;p&gt;Doch mit integrierten Updates und generell ab Windows 10 wurde die 4 GB Marke
durchbrochen. Man kann einen USB Stick natürlich mit &lt;a href=&quot;https://de.wikipedia.org/wiki/NTFS&quot;&gt;NTFS&lt;/a&gt;
formatieren, doch dann funktioniert keine EFI-Installation mehr.&lt;/p&gt;

&lt;p&gt;Die richtige Lösung ist: 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_Imaging_Format_Archive&quot;&gt;WIM&lt;/a&gt; aufsplitten.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;vorgeschichte&quot;&gt;Vorgeschichte&lt;/h3&gt;

&lt;p&gt;Das alte &lt;a href=&quot;https://de.wikipedia.org/wiki/BIOS&quot;&gt;BIOS&lt;/a&gt; machte es uns einfach: 
Es lud den ersten Sektor eines Mediums in den RAM und führte den Code einfach 
aus. Jedes Betriebssystem und jedes Dateisystem konnte dort genau den Code 
platzieren, der notwendig war, das vollständige OS zu laden.&lt;/p&gt;

&lt;p&gt;Doch mit der Einführung von &lt;a href=&quot;https://de.wikipedia.org/wiki/Unified_Extensible_Firmware_Interface&quot;&gt;EFI&lt;/a&gt;, 
muss der EFI-OS-Loader das Dateisystem lesen können und daraus die 
OS-Boot-Dateien extrahieren können.
FAT32 ist einfach und offen genug, und daher ist dieses Dateisystem 
“zum Maß aller Dinge” geworden.&lt;/p&gt;

&lt;p&gt;Bei der Installation von Windows, entscheidet die Art des Starts des 
Boots des Setup-Mediums darüber, wie Windows installiert werden kann.
Bootet man über den BIOS-Layer, kann man Windows auch nur im BIOS Modus
mit &lt;a href=&quot;https://de.wikipedia.org/wiki/Master_Boot_Record&quot;&gt;MBR&lt;/a&gt; Partitionstabellen
aufsetzen.&lt;br /&gt;
Startet man jedoch über &lt;code&gt;EFI&lt;/code&gt;, legt Windows Setup 
&lt;a href=&quot;https://de.wikipedia.org/wiki/GUID_Partition_Table&quot;&gt;GUID-Partitionstabellen&lt;/a&gt;
und eine EFI-Boot Partition an. Die fertige Windows Installation kann am
Ende dann alle EFI-Features nutzen.&lt;/p&gt;

&lt;p&gt;Problem: Zu große &lt;code&gt;install.wim&lt;/code&gt; Dateien können nicht auf FAT32 USB Sticks
kopiert werden und nutzt man &lt;code&gt;NTFS&lt;/code&gt;, kann man nicht über EFI Booten.&lt;/p&gt;

&lt;h3 id=&quot;installwim-anpassen&quot;&gt;install.wim anpassen&lt;/h3&gt;

&lt;p&gt;Die zu großen &lt;code&gt;install.wim&lt;/code&gt; Dateien kann man auf unterschiedliche Weisen verkleinern.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Man extrahiert nur die Windows-Installation, die man braucht, denn in der Regel
beinhaltet eine &lt;code&gt;install.wim&lt;/code&gt; mehrere verschiedene Windows Setup Arten.
(Home, Eduction, “N” oder Professional und Enterprise).
Doch leider ist hier nicht garantiert, dass die resultierende &lt;code&gt;install.wim&lt;/code&gt; 
wirklich kleiner als 4 GB wird.&lt;/li&gt;
  &lt;li&gt;Man benutzt &lt;code&gt;dism&lt;/code&gt; um die &lt;code&gt;WIM&lt;/code&gt; Datei in mehrere &lt;code&gt;SWM&lt;/code&gt; Dateien aufzuspalten.
Windows Setup erkannt dann automatisch, dass es nicht eine einzelne &lt;code&gt;install.wim&lt;/code&gt; 
hat, sondern ein Set von &lt;code&gt;install.swm&lt;/code&gt;, &lt;code&gt;install2.swm&lt;/code&gt; bis &lt;code&gt;installN.swm&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Diesen zweiten &lt;code&gt;dism&lt;/code&gt; Weg möchte ich nun dokumentieren, auf dass ich ihn nicht immer
auf anderen Seiten suchen muss:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Windows Installations-ISO herunterladen und Inhalt lokal entpacken
(z.B. mit 7zip) nach &lt;code&gt;C:\ISO&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Konsole (&lt;code&gt;cmd.exe&lt;/code&gt;) als &lt;code&gt;Administrator&lt;/code&gt; starten&lt;/li&gt;
  &lt;li&gt;Aufspaltung in Teildateien erfolgt alle 3800 MB:
    &lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;dism /Split-Image /ImageFile:C:\ISO\sources\install.wim ^
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;     /SWMFile:C:\ISO\sources\install.swm /FileSize:3800
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code&gt;del C:\ISO\sources\install.wim&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nun kann man einen USB Stick mit FAT32 formatieren, z.B. mit &lt;code&gt;diskpart&lt;/code&gt;.&lt;br /&gt;
Wichtig: Hier immer gut aufpassen, dass man per &lt;code&gt;list disk&lt;/code&gt; die richtige 
Nummer des USB-Sticks herausfindet und “selected”, ansonsten löscht man 
sich eventuell seine Festplatte!&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;list disk
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;select disk 9
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;clean
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;create part primary
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;format fs=fat32 quick
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;active
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;assign letter=U
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;exit
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Und am Ende kann man einfach den gesamten präparierten Inhalt von &lt;code&gt;c:\ISO&lt;/code&gt; 
auf den unter &lt;code&gt;U:&lt;/code&gt; verfügbaren USB Stick kopieren.&lt;/p&gt;

&lt;p&gt;Hat man nun im EFI-BIOS Setup eingestellt, dass man über EFI booten möchte
und den USB Stick angesteckt, sollte Windows PE mit dem Setup hochfahren 
und Windows lässt sich mit den &lt;code&gt;SWM&lt;/code&gt; Dateien im EFI-Modus installieren.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ich frage mich immer, wie es passieren konnte, dass Windows, welches früher
auf 9 - 40 Disketten passte (also unter 100 MB) heute komprimiert mit 
4 GB nicht auskommt.&lt;/p&gt;

&lt;p&gt;Wie auch immer … so lange ich weiter eine Möglichkeit habe mit USB Sticks
EFI Installationen zu machen, bin ich zufrieden.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>RockPI-X</title>
   <link href="https://www.opengate.at/blog/2021/05/rock-pi-x/"/>
   <published>2021-05-29T13:00:00+02:00</published>
   <updated>2021-05-29T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2021/05/rock-pi-x</id>
   <category term="hardware" />
   <summary type="text">Endlich ist mal wieder ein Stück Hardware bei mir eingetrudelt. Und zwar 
der RockPI-X, ein Intel Atom
System-on-Chip Modul in der 
Dimension eines RaspberryPI Modell B.

Während auf den Raspberry PI 
Modellen Windows 10 in der ARM Version nicht wirklich gut lauffähig war 
(die IOT Core 
Version mal ausgenommen), habe ich mit dem RockPI erstmals die Möglichkeit 
ein vollständiges X86 64-bit Windows System auf einem Chipkarten großen PC 
zu installieren.
</summary>
   <content type="html">&lt;p&gt;Endlich ist mal wieder ein Stück Hardware bei mir eingetrudelt. Und zwar 
der &lt;a href=&quot;https://rockpi.org/#rockpix&quot;&gt;RockPI-X&lt;/a&gt;, ein &lt;a href=&quot;https://de.wikipedia.org/wiki/Intel_Atom&quot;&gt;Intel Atom&lt;/a&gt;
&lt;a href=&quot;https://de.wikipedia.org/wiki/System-on-a-Chip&quot;&gt;System-on-Chip&lt;/a&gt; Modul in der 
Dimension eines RaspberryPI Modell B.&lt;/p&gt;

&lt;p&gt;Während auf den &lt;a href=&quot;https://de.wikipedia.org/wiki/Raspberry_Pi&quot;&gt;Raspberry PI&lt;/a&gt; 
Modellen Windows 10 in der ARM Version nicht wirklich gut lauffähig war 
(die &lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_IoT#Windows_10_IoT_Core&quot;&gt;IOT Core&lt;/a&gt; 
Version mal ausgenommen), habe ich mit dem RockPI erstmals die Möglichkeit 
ein vollständiges X86 64-bit Windows System auf einem Chipkarten großen PC 
zu installieren.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;der-rock-pi-x&quot;&gt;Der Rock-PI X&lt;/h3&gt;

&lt;p&gt;Um die 100 Euro kostet ein RockPI-X Modul bei unseren Freunden in Fernost, 
je nachdem wie viel RAM und &lt;a href=&quot;https://de.wikipedia.org/wiki/Multimedia_Card&quot;&gt;eMMC&lt;/a&gt; 
Speicher verbaut ist, schwankt der Preis um +/- 20 Euro.&lt;br /&gt;
Ich habe mir die 4 GB RAM und 32 GB eMMC Variante gegönnt.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/rockpi-x-box.jpg&quot; alt=&quot;RockPI-X Box&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Die Box kam mit dem &lt;a href=&quot;https://de.wikipedia.org/wiki/System-on-a-Chip&quot;&gt;SOC Modul&lt;/a&gt; 
und einer &lt;a href=&quot;https://de.wikipedia.org/wiki/Wireless_Local_Area_Network&quot;&gt;WLAN&lt;/a&gt;
Antenne. Nicht dabei war ein &lt;a href=&quot;https://de.wikipedia.org/wiki/USB-C&quot;&gt;USB-C&lt;/a&gt; 
Stromadapter und dieser ist leider kein 0815 Modell.
Wir brauchen nämlich einen &lt;strong&gt;USB-C 9 oder 12 Volt&lt;/strong&gt; Adapter.&lt;br /&gt;
Reguläre Adapter arbeiten nur mit 5 Volt und mit dieser zu geringen Spannung 
soll es zu Instabilitäten im Betrieb kommen können.&lt;br /&gt;
Zum Glück hatte ich bereits einen Adapter, der entsprechend mehr Spannung 
liefert, und konnte das Modul damit betreiben.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/rockpi-x.jpg&quot; alt=&quot;RockPI-X&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/High_Definition_Multimedia_Interface&quot;&gt;HDMI&lt;/a&gt;, 
Audio, USB 2 und 3, wie auch Ethernet, WLAN und Bluetooth soll der
“Mikro-PC” anbieten können. Ein 4-Kern &lt;a href=&quot;http://ark.intel.com/content/www/de/de/ark/products/93361/intel-atom-x5z8350-processor-2m-cache-up-to-1-92-ghz.html&quot;&gt;Intel Atom Z8350&lt;/a&gt;
mit 1.4 GHz treibt das Cherry Trail System an.&lt;/p&gt;

&lt;p&gt;Nicht zu vergessen ist dann noch seine PIN Leiste.&lt;br /&gt;
Eigentlich wollte ich das Teil nur deshalb haben, weil mich interessiert,
ob wir über Windows irgendwie mit den &lt;a href=&quot;https://de.wikipedia.org/wiki/GPIO&quot;&gt;GPIO&lt;/a&gt; 
PINs sprechen können.
Jede reguläre Linux-Installation sollte keine Probleme haben, die 
&lt;a href=&quot;https://de.wikipedia.org/wiki/GPIO&quot;&gt;GPIO&lt;/a&gt; Pins per &lt;code&gt;sysfs&lt;/code&gt; einzubinden und 
auch &lt;a href=&quot;https://de.wikipedia.org/wiki/Android_(Betriebssystem)&quot;&gt;Android&lt;/a&gt; 
wäre eine kompatible Plattform für dieses Gerät.&lt;/p&gt;

&lt;p&gt;Vor allem aber wollte ich mal einen “PC” haben, den ich nicht immer mit 
sperrigen Gehäuse herumstellen muss, wenn ich mal schnell was testen möchte.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/rockpi-x-backside.jpg&quot; alt=&quot;RockPI-X Backside&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;windows-10-installation&quot;&gt;Windows 10 Installation&lt;/h3&gt;

&lt;p&gt;Hier gibt es eigentlich nichts zu sagen, außer: Alles PC Standard.&lt;/p&gt;

&lt;p&gt;Man erstellt einen USB Boot-Stick aus einer Windows-Setup-&lt;a href=&quot;https://de.wikipedia.org/wiki/ISO-Abbild&quot;&gt;ISO&lt;/a&gt;
Datei, startet den Rock-PI-X, drückt &lt;code&gt;DEL&lt;/code&gt; um ins BIOS zu gelangen und 
aktiviert dort den Boot from USB Stick. Der Boot im &lt;code&gt;UEFI&lt;/code&gt; Modus ist dabei 
stets vorzuziehen.&lt;/p&gt;

&lt;p&gt;Dann startet die Windows Installation, die den &lt;code&gt;eMMC&lt;/code&gt; Speicher automatisch 
erkennt und Windows darauf installiert.&lt;/p&gt;

&lt;p&gt;Sobald das Setup durchgelaufen ist, landet man in einer regulären Windows 10
Installation, die die Hardware mit Standardtreibern nutzt.
Es werden dabei jedoch noch einige Einträge im Gerätemanager angezeigt, für 
die kein Treiber existiert.&lt;/p&gt;

&lt;h3 id=&quot;treiber-update&quot;&gt;Treiber Update&lt;/h3&gt;

&lt;p&gt;Fehlende INF Dateien findet man dann auf &lt;a href=&quot;https://wiki.radxa.com/RockpiX/downloads&quot;&gt;wiki.radxa.com/RockpiX/downloads&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Einen Treiber bekam ich allerdings nicht zum Laufen, und das war der WLAN-Chip.
Das kann theoretisch auch am von mir eingesetzten 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_IoT#Windows_10_IoT_Enterprise&quot;&gt;Windows 10 IOT Enterprise&lt;/a&gt;
liegen, welches ich im RockPI-X installiert hatte.&lt;/p&gt;

&lt;p&gt;Man findet aber bei den Treiber Downloads auch eine fertige 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_Imaging_Format_Archive&quot;&gt;WIM Datei&lt;/a&gt; und 
ich vermute mal, dass dort drinnen alle Treiber integriert sind.&lt;/p&gt;

&lt;p&gt;Ich habe mein WLAN-Problem vorläufig ignoriert und einen 0815-USB-WLAN-Dongle
per USB genutzt und der wurde unmittelbar erkannt und war einsatzbereit.&lt;/p&gt;

&lt;h3 id=&quot;thema-gpio&quot;&gt;Thema GPIO&lt;/h3&gt;

&lt;p&gt;Die Dokumentation zur GPIO Pinleiste ist zwar &lt;a href=&quot;https://wiki.radxa.com/RockpiX/hardware/gpio&quot;&gt;online abrufbar&lt;/a&gt;,
richtet sich primär an &lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt;. Dort 
kann man GPIOs in der Regel per &lt;code&gt;/sys/class/gpio&lt;/code&gt; exportieren (also nutzbar
machen) und dann über das Dateisystem steuern. Es werden 5 GPIO-Geräte beschrieben, 
die die eigentlichen GPIO-Pins über eine interne Nummer ansteuerbar machen.&lt;/p&gt;

&lt;p&gt;Meine erste Anlaufstelle war das Tool &lt;a href=&quot;https://docs.microsoft.com/en-us/sysinternals/downloads/winobj&quot;&gt;WinObj&lt;/a&gt;,
welches brav alle Treiber und Geräte im Windows Objektbaum anzeigen kann.
Und tatsächlich findet man dort &lt;code&gt;GPIO_1&lt;/code&gt; bis &lt;code&gt;6&lt;/code&gt; aufgelistet.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/winobj-gpio.gif&quot; alt=&quot;WinObj GPIO&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Es gibt aber keine Links aus dem globalen Namensraum heraus, womit schon 
mal die Nutzung aus dem User-Mode nicht vorgesehen ist.&lt;/p&gt;

&lt;p&gt;Beim &lt;a href=&quot;https://docs.microsoft.com/en-us/windows-hardware/drivers/gpio/gpio-driver-support-overview&quot;&gt;Nachlesen auf der MSDN&lt;/a&gt;
fand ich dann die Erklärung, dass man unter Windows GPIOs grundsätzlich nur 
durch eigene Treiber für andere Geräte zugänglich macht.&lt;br /&gt;
Das macht eigentlich auch Sinn, denn im produktiven Betrieb lädt man einen
Treiber für z.B. einen Button am Gerät oder einen Sensor und definiert für 
diesen ein Interface.&lt;br /&gt;
Dass im Hintergrund dann Bits von und an GPIOs herumgeschickt werden ist 
ein Implementierungsdetail.&lt;/p&gt;

&lt;p&gt;Man kann also nicht so einfach GPIO Pins ein und ausschalten, wie das unter
Linux möglich wäre. Da müsste man sich einen eigenen GPIO-Playground-Treiber
schreiben, dem man dann per &lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilew&quot;&gt;CreateFile()&lt;/a&gt; 
und &lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/ioapiset/nf-ioapiset-deviceiocontrol&quot;&gt;DeviceIoControl()&lt;/a&gt;
Kommandos schickt, welche dieser dann an die nativen GPIOs weitergibt.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Nun, da muss ich wohl noch ein bisschen warten, bis ich für einen GPIO Treiber
Zeit habe. Aber ein gutes Gerät für diese Tests habe ich ja zumindest schon.&lt;/p&gt;

&lt;p&gt;Der RockPI-X verhält sich etwa so wie Tablets mit diesem Prozessor. Er lässt 
sich auch gut mit dem Raspberry-PI 4 vergleichen.
Man kann einigermaßen damit im Web browsen und typische Office-Aufgaben damit
erledigen. Er ist sicher keine Rennsau, aber auch keine lahme Ente.&lt;/p&gt;

&lt;p&gt;Rechenaufgaben kombiniert mit viel eMMC drücken aber negativ auf die 
Performance. Das merkt man beim Update-installieren, denn das kann Stunden 
dauern. Ein einzelner Kern rechnet alleine und die Dateien finden nur langsam
ihr Ziel. Das ist gegenüber einem “richtigen” Desktop-Rechner eher ein Witz.&lt;/p&gt;

&lt;p&gt;However, ich haben einen vollständigen X86 PC auf Chipkarten-Größe, also halb
so groß wie mein Smartphone.&lt;br /&gt;
Hätte mir das mal einer vor 20 Jahren gesagt,
dass so etwas mal möglich werden wird …&lt;br /&gt;
Echt krass, was es heute alles gibt!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Dialoge per Aufruf</title>
   <link href="https://www.opengate.at/blog/2021/05/sync-dialogs/"/>
   <published>2021-05-23T13:00:00+02:00</published>
   <updated>2021-05-23T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2021/05/sync-dialogs</id>
   <category term="devel" />
   <summary type="text">Vor einem Jahr waren Dialoge bereits 
für mich ein Thema.
Jetzt stellt sich die Frage, wie man die Ergebnisse von Dialogen auch als
Funktionsaufruf - also “synchron” per “blocking-call” - erhalten kann.

Oder anders gefragt: Wie wird eine UI Message-Loop
innerhalb einer anderen UI-Message-Loop für begrenzte Zeit angekurbelt?
</summary>
   <content type="html">&lt;p&gt;Vor einem Jahr waren &lt;a href=&quot;/blog/2020/04/dialogs/&quot;&gt;Dialoge&lt;/a&gt; bereits 
für mich ein Thema.&lt;br /&gt;
Jetzt stellt sich die Frage, wie man die Ergebnisse von Dialogen auch als
Funktionsaufruf - also “synchron” per “blocking-call” - erhalten kann.&lt;/p&gt;

&lt;p&gt;Oder anders gefragt: Wie wird eine &lt;a href=&quot;https://de.wikipedia.org/wiki/Ereignisschleife&quot;&gt;UI Message-Loop&lt;/a&gt;
innerhalb einer anderen UI-Message-Loop für begrenzte Zeit angekurbelt?
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;winapi&quot;&gt;WinAPI&lt;/h3&gt;

&lt;p&gt;Die Windows API ist stets eine Blaupause für mich, wenn es um Fragen zu 
Message-Loops usw. geht. Denn empfängt die Funktion &lt;code&gt;GetMessage()&lt;/code&gt; 
eine Nachricht, und &lt;code&gt;DispatchMessage()&lt;/code&gt; leitet das Ereignis an die 
entsprechende Callback-Routine der Fensterklasse weiter.&lt;/p&gt;

&lt;p&gt;Man implementiert die Message-Loop immer selbst, in dem
&lt;code&gt;GetMessage()&lt;/code&gt; und &lt;code&gt;DispatchMessage()&lt;/code&gt; in einer Endlosschleife laufen,
die nur durch &lt;code&gt;WM_QUIT&lt;/code&gt; oder programmspezifische Logiken verlassen
werden soll.&lt;/p&gt;

&lt;p&gt;Ein Dialog, kann seine eigene Schleife einbauen und die so lange 
laufen lassen, wie der Dialog offen ist und dann zur Elternschleife
zurückkehren.&lt;/p&gt;

&lt;script src=&quot;/blog/assets/mermaid/mermaid.min.js&quot;&gt;&lt;/script&gt;
&lt;div class=&quot;mermaid&quot;&gt;
graph TD
    LOOP[[Main Message Loop]] --&amp;gt; GET
    GET(GetMessage) --&amp;gt; DISP
    DISP(DispatchMessage) --&amp;gt; LOOP
    DISP -- Event --&amp;gt; DLG
    DLG[[Dialog Message Loop]] --&amp;gt; DLGGET
    DLGGET(GetMessage) --&amp;gt; DLGDISP
    DLGDISP(DispatchMessage) --&amp;gt; DLGIF[IF continue_dialog]
    DLGIF -- yes --&amp;gt; DLG
    DLGIF -- no --&amp;gt; DISP
&lt;/div&gt;

&lt;p&gt;Alles läuft in einem Thread und jeder Dialog führt seine eigene Schleife aus,
so lange er sie braucht, bis er die Kontrolle wieder eine Ebene zurückgibt.
So kann man auch mehrere Dialoge übereinander legen.&lt;/p&gt;

&lt;h3 id=&quot;gtk&quot;&gt;GTK&lt;/h3&gt;

&lt;p&gt;Vor &lt;a href=&quot;https://de.wikipedia.org/wiki/GTK_(Programmbibliothek)&quot;&gt;GTK&lt;/a&gt; hatte ich 
bei dem Thema Angst, dass mir ein solche Zugriff nicht möglich hätte sein 
können.&lt;br /&gt;
Doch zu meinem Glück konnte ich die Funktion 
&lt;a href=&quot;https://developer.gnome.org/gtk3/stable/gtk3-General.html#gtk-main-iteration&quot;&gt;&lt;code&gt;gtk_main_iteration&lt;/code&gt;&lt;/a&gt;
finden und schon war alles gut.&lt;/p&gt;

&lt;p&gt;Ein Aufruf dieser Funktion ist das Äquivalent eines &lt;code&gt;WINAPI&lt;/code&gt; 
GetMessage - DispatchMessage Paares und somit braucht eine Dialog-Funktion 
nur diese Routine in einer Schleife immer wieder aufrufen, bis der Dialog 
geschlossen werden kann.&lt;/p&gt;

&lt;p&gt;Das Aufruf-Diagramm ist hier viel einfacher, weil auf main-Ebene die 
Schleife nicht selbst implementiert wird, sondern &lt;code&gt;gtk_main()&lt;/code&gt; seine eigene
Magie walten lässt.&lt;/p&gt;

&lt;script src=&quot;/blog/assets/mermaid/mermaid.min.js&quot;&gt;&lt;/script&gt;
&lt;div class=&quot;mermaid&quot;&gt;
graph TD
    MAIN[[GTK main run]] --&amp;gt; GTK(gtk_main)
    GTK -- Event --&amp;gt; DLG
    DLG[[Dialog Message Loop]] --&amp;gt; DLGITER
    DLGITER(gtk_main_iteration) --&amp;gt; DLGIF[IF continue_dialog]
    DLGIF -- yes --&amp;gt; DLG
    DLGIF -- no --&amp;gt; GTK
&lt;/div&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Kombiniert man dieses Wissen mit dem Feature, dass ein Top-Level Fenster
immer vor einem anderen Fenster gereiht ist und dieses andere Fenster für
Events “deaktiviert” ist, hat man jetzt einen Dialog, der per Funktionsaufruf
so lange seine eigene Schleife betreibt, bis er fertig ist.&lt;/p&gt;

&lt;p&gt;Man ruft den Dialog also synchron auf und hat damit einen einfachen und 
übersichtlichen Programmaufbau geschaffen.&lt;/p&gt;

&lt;p&gt;Ich habe basierend auf dieser Technik sofort eine Input-Box Klasse zum
eingeben von Texten erstellt und das Ergebnis hat wie erwartet funktioniert.&lt;/p&gt;

&lt;p&gt;Nun steht dem Einsatz von weiteren selbst-definierten Dialogen nichts
mehr im Weg.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>QR Codes und Datamatrix</title>
   <link href="https://www.opengate.at/blog/2021/05/qr-dmtx/"/>
   <published>2021-05-22T13:00:00+02:00</published>
   <updated>2021-05-22T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2021/05/qr-dmtx</id>
   <category term="devel" />
   <summary type="text">Bald kommen QR-Codes, die uns einen 
Impfstatus oder eine Testung bestätigen sollen.

Das ist doch der perfekte Zeitpunkt um diese beiden Bild-Kodierungen ins
GATE Projekt aufzunehmen und mit ihnen zu experimentieren.
</summary>
   <content type="html">&lt;p&gt;Bald kommen &lt;a href=&quot;https://de.wikipedia.org/wiki/QR-Code&quot;&gt;QR-Codes&lt;/a&gt;, die uns einen 
Impfstatus oder eine Testung bestätigen sollen.&lt;/p&gt;

&lt;p&gt;Das ist doch der perfekte Zeitpunkt um diese beiden Bild-Kodierungen ins
GATE Projekt aufzunehmen und mit ihnen zu experimentieren.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Neben den alt bekannten Artikel-Barcodes (&lt;a href=&quot;https://de.wikipedia.org/wiki/Strichcode&quot;&gt;Strichcodes&lt;/a&gt;), 
sind mir folgende optischen Datencodes in der Öffentlichkeit bekannt:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;QR-Codes sind diese Punkte-Quadrate, die an 3 Ecken ein umrandetes Quadrat
beinhalten.&lt;br /&gt;
Sie sind auf Plakaten und überall dort vertreten, wo man sie mit dem
Smartphone abscannen kann und beinhalten häufig URLs für weitere
Infos zu einem Produkt.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/DataMatrix-Code&quot;&gt;Data-Matrix-Codes&lt;/a&gt; sind wie 
QR-Codes quadratisch und zeichnen sich durch durchgehende Linien an zwei 
Achsen an den Rändern aus.&lt;br /&gt;
Sie sind als Bar-Code Ersatz gedacht und man findet sie (etwas versteckt)
auf Geräten, wo sie häufig Seriennummern oder Adressen kodieren.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Beide Techniken können allerlei mögliche Formen von Bytes kodieren, auch 
Binärdaten.
Und mit folgenden hilfreichen Bibliotheken kann man aus Pixel-Rastergrafiken 
(z.B. Bitmaps) Codes erkennen lassen:&lt;/p&gt;

&lt;h3 id=&quot;libdmtx&quot;&gt;libdmtx&lt;/h3&gt;

&lt;p&gt;Mit Data-Matrix-Codes (auch als 2D-Barcodes bekannt), habe ich schon vor ein
paar Jahren “experimentiert”. Die Bibliothek &lt;a href=&quot;https://github.com/dmtx&quot;&gt;&lt;code&gt;libdmtx&lt;/code&gt;&lt;/a&gt;
soll mir daher auch diesmal einen guten Dienst leisten, wenn es um das 
Auslesen von Datamatrix Codes in Bildern geht.&lt;/p&gt;

&lt;p&gt;Die Bibliothek ist für den Anwender recht einfach gestrickt und kann mit 
jedem möglichen Rasterbild-Format (RGB, RGBA, usw.) gefüttert werden.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;DmtxImage* dmtx_image = dmtx_image = dmtxImageCreate(pixelptr, width, height, DmtxPack32bppRGBX);&lt;/code&gt;&lt;br /&gt;
Erzeugt ein Bildobjekt basierend auf den Eingabedaten, 
wobei es ein paar Optionen für Formate gibt.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;DmtxDecode* decoder = dmtxDecodeCreate(dmtx_image, 1);&lt;/code&gt;&lt;br /&gt;
Dann wird die Dekodierung für das Bild eingeleitet.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;DmtxRegion* region = dmtxRegionFindNext(decoder, NULL);&lt;/code&gt;&lt;br /&gt;
Nun sucht man eine gefundene Datamatrix-Region.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;DmtxMessage* message = dmtxDecodeMatrixRegion(decoder, region, DmtxUndefined);&lt;/code&gt;&lt;br /&gt;
Und dann liest man die Nachricht aus der Region heraus.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;message-&amp;gt;output, message-&amp;gt;outputSize&lt;/code&gt;&lt;br /&gt;
Auf die dekodierten Daten zeigt dann der &lt;code&gt;output&lt;/code&gt; Pointer und die Größe.
steht in &lt;code&gt;outputSize&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;dmtxMessageDestroy(&amp;amp;message);&lt;/code&gt;&lt;br /&gt;
Freigeben des Message Objektes.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;dmtxRegionDestroy(&amp;amp;region);&lt;/code&gt;&lt;br /&gt;
Freigeben des Region Objektes.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;dmtxDecodeDestroy(&amp;amp;decoder);&lt;/code&gt;&lt;br /&gt;
Freigeben des Dekoders.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;dmtxImageDestroy(&amp;amp;dmtx_image);&lt;/code&gt;&lt;br /&gt;
Freigeben der Bilddaten.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Viel einfacher geht es ja kaum und &lt;code&gt;libdmtx&lt;/code&gt; kann auch verdrehte Bilder
so lange herumtransformieren, bis eine Matrix entdeckt wurde. Man kann auch
ein Timeout angeben um zu lange Suchoperationen dann abbrechen zu lassen.&lt;/p&gt;

&lt;h3 id=&quot;libquirc&quot;&gt;libquirc&lt;/h3&gt;

&lt;p&gt;Mit der &lt;a href=&quot;https://github.com/dlbeer/quirc/tree/master/lib&quot;&gt;&lt;code&gt;quirc&lt;/code&gt;&lt;/a&gt; Lib
haben wir eine C Bibliothek mit BSD Lizenz, die QR Codes dekodieren kann
und keine zusätzlichen Abhängigkeiten hat.&lt;/p&gt;

&lt;p&gt;Bilddaten muss man für &lt;code&gt;quirc&lt;/code&gt; als Graustufen-Bytes übergeben.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;struct quirc* qr = quirc_new();&lt;/code&gt;&lt;br /&gt;
Eine neue Dekoder-Sitzung wird gestartet.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;quirc_resize(qr, width, height);&lt;/code&gt;&lt;br /&gt;
Die Dimensionen des zu ladenden Bildes werden übergeben.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;gray_image = quirc_begin(qr, &amp;amp;width, &amp;amp;height);&lt;/code&gt;&lt;br /&gt;
Wir erhalten einen Pointer auf die internen Bild-Pixel.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;for(pixel : pixels) gray_image[offset] = gray(pixel);&lt;/code&gt;&lt;br /&gt;
Nun müssen alle Bild-Pixel befüllt werden.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;quirc_end(qr);&lt;/code&gt;&lt;br /&gt;
Das Aufnehmen der Bilddaten ist fertig und die Dekodierung startet.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;int num_codes = quirc_count(qr);&lt;/code&gt;&lt;br /&gt;
Die Anzahl der gefundenen QR-Codes wird abgefragt.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;for(int index = 0; index &amp;lt; num_codes; index++)&lt;/code&gt;&lt;br /&gt;
Wir gehen nun durch alle gefundenen QR-Bereiche durch:
    &lt;ul&gt;
      &lt;li&gt;&lt;code&gt;struct quirc_code code&lt;/code&gt;;&lt;/li&gt;
      &lt;li&gt;&lt;code&gt;quirc_extract(qr, index, &amp;amp;code);&lt;/code&gt;&lt;br /&gt;
Es wird versucht einen QR-Code zu extrahieren.&lt;/li&gt;
      &lt;li&gt;&lt;code&gt;struct quirc_data data;&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;&lt;code&gt;quirc_decode(&amp;amp;code, &amp;amp;data);&lt;/code&gt;&lt;br /&gt;
Die extrahierten Daten werden in Bytes dekodiert.&lt;/li&gt;
      &lt;li&gt;&lt;code&gt;data.payload, data.payload_len&lt;/code&gt;&lt;br /&gt;
Und durch einen Pointer zu den Daten und die Anzahl der Bytes
  kann der QR-Code Inhalt weiterverarbeitet werden&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code&gt;quirc_destroy(qr);&lt;/code&gt;&lt;br /&gt;
Am Ende wird die quirc-Sitzung beendet und alle Ressourcen 
werden freigegeben.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Auch hier ist das Ergebnis mit nur wenigen Zeilen Code zu erhalten.
Und es sind nur ein paar &lt;code&gt;if&lt;/code&gt; Statements erforderlich um nicht-erkennbare
Codes zu überspringen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Also ich bin echt beeindruckt.&lt;/p&gt;

&lt;p&gt;Die Komplexität der Bildverarbeitung ist in einer Hand voll von Funktionen
abgebildet, die nahezu selbstbeschreibend sind.&lt;/p&gt;

&lt;p&gt;Mein Respekt geht an die Macher und ich habe die beiden Bibliotheken mit 
Freude ins GATE Projekt aufgenommen.&lt;/p&gt;

&lt;p&gt;Nun kann ich in Verbindung mit meinen Video-Source-Routinen Bilder auf 
Webcams und anderen Kameras auf QR- und Datamatrix-Codes durchsuchen lassen.
Und das klappt wirklich gut.&lt;/p&gt;

&lt;p&gt;Das schwierigste ist meist, die Schärfeeinstellung der Webcams so 
hinzubekommen, dass ein gut lesbares Bild dabei herauskommt.&lt;/p&gt;

&lt;p&gt;Daumen hoch für diese geniale Codebase.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Einheitliches Mapping</title>
   <link href="https://www.opengate.at/blog/2021/05/mappings/"/>
   <published>2021-05-16T13:00:00+02:00</published>
   <updated>2021-05-16T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2021/05/mappings</id>
   <category term="devel" /><category term="projects" />
   <summary type="text">Mit der Einführung von Hashmaps 
war es nun so weit:


  Die Map APIs im GATE Projekt müssen umgestellt werden.


Und dieses Unterfangen war mühsamer als erwartet. Denn inzwischen bauen
einige Applikationen darauf auf, die ebenso angepasst werden mussten.
</summary>
   <content type="html">&lt;p&gt;Mit der Einführung von &lt;a href=&quot;https://de.wikipedia.org/wiki/Hashtabelle&quot;&gt;Hashmaps&lt;/a&gt; 
war es nun so weit:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Die Map APIs im GATE Projekt müssen umgestellt werden.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Und dieses Unterfangen war mühsamer als erwartet. Denn inzwischen bauen
einige Applikationen darauf auf, die ebenso angepasst werden mussten.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Während C++ mit &lt;a href=&quot;https://www.cplusplus.com/reference/map/map/&quot;&gt;&lt;code&gt;std::map&lt;/code&gt;&lt;/a&gt;
und seit C++11 mit &lt;a href=&quot;https://www.cplusplus.com/reference/unordered_map/unordered_map/&quot;&gt;&lt;code&gt;std::unordered_map&lt;/code&gt;&lt;/a&gt;
jedes beliebige Key-Value Mapping problemlos bewältigen kann, hat man in 
C genau gar nichts im Standard, was einem hilft.&lt;/p&gt;

&lt;p&gt;Natürlich könnte man hier unzählige Fremdbibliotheken einbinden, die alle
zu einander inkompatibel sind und einen fetten Rattenschwanz an Abhängigkeiten
nachziehen, oder man implementiert dieses Strukturen selbst und achtet auf
möglichst viel Unabhängigkeit.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;gate_map_t&lt;/code&gt; ist seit Anfang des GATE Projektes mit dabei und stellt eine 
generische &lt;a href=&quot;https://de.wikipedia.org/wiki/Rot-Schwarz-Baum&quot;&gt;Rot-Schwarz-Baum&lt;/a&gt; 
Implementierung bereit, die jedes beliebige 
Objekt (inklusive Konstruktor- und Destruktor-Funktion) aufnehmen kann.&lt;br /&gt;
Im C++ Layer nutzt das &lt;code&gt;gate::Map&amp;lt;KEY, VALUE&amp;gt;&lt;/code&gt; Template die C Schnittstelle 
und macht sie ähnlich wie &lt;code&gt;std::map&lt;/code&gt; nutzbar.&lt;br /&gt;
Schlüssel und Werte sind dabei direkt in die Baumknoten Objekte eingebaut
und die C Iteratoren geben den Zugriff darauf über generische Pointer 
(&lt;code&gt;void*&lt;/code&gt;)  zurück, während C++ diese auf die korrekten Typ-Referenzen
umwandelt.&lt;/p&gt;

&lt;p&gt;Und dann kam die &lt;em&gt;Sequence-Map&lt;/em&gt; hinzu, die im Endeffekt nur ein 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Feld_(Datentyp)&quot;&gt;Array&lt;/a&gt; von
Schlüssel-Wert Paaren ist und deren Auszeichnungsmerkmal das Erhalten 
der Reihenfolge des Hinzufügens ist.&lt;br /&gt;
Hier speichert ein &lt;code&gt;gate_seqmap_t&lt;/code&gt; Objekt die Byte Offsets von Schlüssel
und Wert in einem Eintrag und im Array wird stets ein ganzer Eintragsblock
allokiert, wo die beiden Felder direkt hintereinander liegen.&lt;br /&gt;
Iteratoren nutzen dann die Offsets um aus einem Pointer dann zwei zu 
machen.&lt;/p&gt;

&lt;p&gt;In den letzten Tagen kam nach der Implementierung einer 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Hashfunktion&quot;&gt;Hashfunktion&lt;/a&gt; für die meisten
GATE Typen eine Hashmap hinzu. Sie führt ein Array von verkürzten Hash-Codes
in dem wiederum ein Array von Schlüssel-Wert Paaren liegen kann.&lt;/p&gt;

&lt;p&gt;Und genau hier fiel mir mein Fehler auf: Alle Maps speichern Key/Value 
Paare, aber speichern sie immer anders.&lt;br /&gt;
Die Lösung war naheliegend:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Wir brauchen eine gemeinsame Datenstruktur, die alle Maps intern
nutzen, damit Iteratoren und Enumeratoren immer die gleiche Schnittstelle
zurückliefern können.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;gate_mapping_t-und-gatemappingkey-value&quot;&gt;&lt;code&gt;gate_mapping_t&lt;/code&gt; und &lt;code&gt;gate::Mapping&amp;lt;KEY, VALUE&amp;gt;&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;Es ist eigentlich nur eine Art Header, der aus zwei Zeigern besteht, nämlich
einem &lt;code&gt;void const* key;&lt;/code&gt; und einem &lt;code&gt;void* value;&lt;/code&gt; und dieser ist der kleinste
gemeinsame Nenner aller Formen von Map-Objekten. Die tatsächlichen Daten
liegen in der Regel unmittelbar hinter den beiden Zeigern, wenn gleich
dieser Header auch zulassen würde, dass die Daten außerhalb der Maps
liegen können.&lt;/p&gt;

&lt;script src=&quot;/blog/assets/mermaid/mermaid.min.js&quot;&gt;&lt;/script&gt;
&lt;div class=&quot;mermaid&quot;&gt;
classDiagram
  key_instance -- mapping_t
  value_instance -- mapping_t
  mapping_t &amp;lt;-- map_t : RB-Tree
  mapping_t &amp;lt;-- seqmap_t : Entry-Array
  mapping_t &amp;lt;-- hashmap_t : Hash-Buckets

  mapping_t : void const* key  
  mapping_t : void* value

  map_t : -tree_node* root
  map_t : -compare_func key_comparer
  map_t : +add(key, value)  
  map_t : +get(key)
  map_t : +remove(key)

  seqmap_t : -mapping_t** contents
  seqmap_t : -compare_func key_comparer
  seqmap_t : +add(key, value)  
  seqmap_t : +get(key)
  seqmap_t : +remove(key)

  hashmap_t : -bucket_t** buckets
  hashmap_t : -compare_func key_comparer
  hashmap_t : -hash_func key_hash_generator
  hashmap_t : +add(key, value)  
  hashmap_t : +get(key)
  hashmap_t : +remove(key)

&lt;/div&gt;

&lt;p&gt;Hilfreich ist das vor allem für Enumeratoren, diese stellen eine 
einheitliche Form des Auflistens von Containern zur Verfügung und
bisher hat jede Map etwas anderes zurückgegeben.&lt;br /&gt;
Ab sofort liefen alle Maps einen C Enumerator von &lt;code&gt;gate_mapping_t&lt;/code&gt;
zurück und der C++ Wrapper castet das wiederum auf 
&lt;code&gt;gate::Enumerator&amp;lt;gate::Mapping&amp;lt;KEY, VALUE&amp;gt; &amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Nun kann man also endlich einheitlich mit allen Key/Value Containern
arbeiten.&lt;/p&gt;

&lt;h3 id=&quot;zucker-für-den-debugger&quot;&gt;Zucker für den Debugger&lt;/h3&gt;

&lt;p&gt;In C++ im Debugging-Modus (&lt;code&gt;NDEBUG&lt;/code&gt; oder &lt;code&gt;GATE_DEBUG_MODE&lt;/code&gt;) hat nun das 
&lt;code&gt;Mapping&lt;/code&gt; Template einen kleinen Zusatz spendiert bekommen hat, der in 
etwa so aussieht:&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;template&lt;/span&gt;&amp;lt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;KEY&lt;/span&gt;, &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;VALUE&lt;/span&gt;&amp;gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;Mapping&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;private&lt;/span&gt;:
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#if&lt;/span&gt; defined(GATE_DEBUG_MODE)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;union&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  {
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;    gate_mapping_t        impl;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;struct&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;    {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;      KEY &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt;* key_shadow;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;      VALUE &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt;* value_shadow;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;    };
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;  };
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#else&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;  gate_mapping_t        impl;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#endif&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Durch den Einsatz von &lt;code&gt;union&lt;/code&gt; wird im Template parallel zu den generischen
&lt;code&gt;void*&lt;/code&gt; Zeigern auch noch eine typisierte Variante sichtbar.
Und im Debugger kann man auf diese Weise den Inhalt der Datentypen 
inspizieren.&lt;/p&gt;

&lt;p&gt;Das Schöne dabei ist, dass sich das Speicherlayout des Objektes dabei
nicht ändert und man keine Inkompatibilitäten zwischen Debug und Release
Variante schafft.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Nun, solche “Überarbeitungen” sind mühsam, wenn man zahlreiche andere
Codestellen anpassen muss, wo die vorherige Schnittstelle im Einsatz war.
Doch es lohnt sich, wenn man nun viel generischer zwischen 
unterschiedlichen Containertypen hin und her wechseln kann.&lt;/p&gt;

&lt;p&gt;Und dass das nun auch in purem C Code möglich ist, freut mich natürlich
ganz besonders. Schließlich sind es genau diese Features aus C++, die 
man in C immer so schmerzlich vermisst.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Workfolders auf anderen Port legen</title>
   <link href="https://www.opengate.at/blog/2021/05/workfolders-port/"/>
   <published>2021-05-15T13:00:00+02:00</published>
   <updated>2021-05-15T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2021/05/workfolders-port</id>
   <category term="software" />
   <summary type="text">Da habe ich vor kurzem das Windows Server 
Update Service installiert und dabei gar nicht gemerkt, dass meine Server
Work Folders seither nicht mehr funktionieren.

Der Grund war einfach: Ein Port 
Konflikt.
Aber dann kam noch ein dummes Anmeldeproblem hinzu und schon ward ein
Drama geboren …
</summary>
   <content type="html">&lt;p&gt;Da habe ich vor kurzem das &lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_Server_2016&quot;&gt;Windows Server&lt;/a&gt; 
Update Service installiert und dabei gar nicht gemerkt, dass meine Server
Work Folders seither nicht mehr funktionieren.&lt;/p&gt;

&lt;p&gt;Der Grund war einfach: Ein &lt;a href=&quot;https://de.wikipedia.org/wiki/Liste_der_standardisierten_Ports&quot;&gt;Port&lt;/a&gt; 
Konflikt.&lt;br /&gt;
Aber dann kam noch ein dummes Anmeldeproblem hinzu und schon ward ein
Drama geboren …
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Die Windows Server &lt;a href=&quot;http://docs.microsoft.com/en-us/windows-server/storage/work-folders/work-folders-overview&quot;&gt;Workfolders&lt;/a&gt;
(zu deutsch Arbeitsordner) arbeiten mit dem
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Internet_Information_Services&quot;&gt;IIS&lt;/a&gt;
und belegen die üblichen &lt;a href=&quot;https://de.wikipedia.org/wiki/Hypertext_Transfer_Protocol_Secure&quot;&gt;HTTP und HTTPS&lt;/a&gt; 
Ports. Tatsächlich läuft der Dienst nicht direkt innerhalb eines IIS, sondern
nutzt nur dessen Kern.&lt;/p&gt;

&lt;p&gt;Wenn man nun parallel andere HTTP Dienste installiert (oder wie ich einfach
die IIS Konfiguration ändert), schafft man schnell eine Situation,
in der die konfigurierten HTTP Ports von anderen Seiten benutzt werden
und die Workfolders fallen aus.&lt;/p&gt;

&lt;p&gt;Nun stellt sich für mich die Frage, wie ich die Workfolders auf einen
anderen Port legen kann. Denn mit “Nicht-Standard-Ports” geht man
künftigen Konflikten aus dem Weg.&lt;/p&gt;

&lt;p&gt;Wären Workfolders direkt im IIS zu Hause, könnte man den Port leicht in dessen
UI abändern, doch leider liegt die Konfiguration nicht dort.&lt;br /&gt;
Was nun?&lt;/p&gt;

&lt;h3 id=&quot;workfolders-mit-neuem-port-einrichten&quot;&gt;Workfolders mit neuem Port einrichten&lt;/h3&gt;

&lt;p&gt;Zum Glück hilft uns das Internet schnell weiter:
&lt;a href=&quot;https://blog.cloud-client.info/?p=913&quot;&gt;blog.cloud-client.info&lt;/a&gt;
Ein meinem Beispiel möchte ich den alten konfigurierten HTTPS Port &lt;code&gt;443&lt;/code&gt; 
durch &lt;code&gt;3443&lt;/code&gt; ersetzen.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Unter &lt;code&gt;c:\windows\system32\SyncShareSvc.config&lt;/code&gt; liegen die benötigten
Einstellungen und nachdem man den Besitz der Datei übernommen hat, kann
man sie auch bearbeiten.&lt;/li&gt;
  &lt;li&gt;Der enthaltene Eintrag &lt;code&gt;:443:&lt;/code&gt; ist durch den neuen Port &lt;code&gt;:3443:&lt;/code&gt; 
zu ersetzen. Die Doppelpunkte sind beide notwendig.&lt;/li&gt;
  &lt;li&gt;Dann führt man auf der Konsole &lt;br /&gt;
&lt;code&gt;netsh http add urlacl url=https://*:3443/ user=”NT Authority\LOCAL SERVICE”&lt;/code&gt;
aus.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Tatsächlich reichte diese Einstellung bei mir schon aus und nach dem Neustart
der Sync-Dienste (&lt;code&gt;SyncShareSvc&lt;/code&gt; und &lt;code&gt;SyncShareTTSvc&lt;/code&gt;) konnte ich meine 
Arbeits-PCs mit der angepassten neuen URL mit dem neuen Port auch gleich 
wieder verbinden.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Tja … Ports.&lt;br /&gt;
Seit 20 Jahren immer wieder das gleiche: Zwei Dienste bilden sich ein, 
sie müssten ihre Inhalte über die HTTP-Ports (80 und 443) bereitstellen 
und wehe man will zwei dieser Dienste auf einer Maschine laufen lassen.&lt;/p&gt;

&lt;p&gt;Das üble dabei: Gerade der IIS sollte als “Host” all diese Verbindungsdetails
übernehmen und Anfragen an seine Plug-Ins weiterverteilen. Denn da würde
genau ein Prozess die Ports belegen und es könnten mehrere Dienste parallel
betrieben werden, so lange sie in unterschiedlichen virtuellen 
Unterverzeichnissen liegen.&lt;/p&gt;

&lt;p&gt;Doch Fehlanzeige! Jedes Feature will seinen Port nur für sich alleine.&lt;/p&gt;

&lt;p&gt;Und so werde ich wohl auch noch in 20 Jahren immer noch damit beschäftigt 
sein, Dienste auf unterschiedliche Ports zu verteilen.&lt;br /&gt;
… eigentlich ist so etwas eine furchtbare Zeitverschwendung!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>GCC Binaries sind viel zu groß</title>
   <link href="https://www.opengate.at/blog/2021/05/gcc-exe-size/"/>
   <published>2021-05-09T13:00:00+02:00</published>
   <updated>2021-05-09T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2021/05/gcc-exe-size</id>
   <category term="devel" />
   <summary type="text">Schon 2007 am Anfang meiner C++ 
Liebschaft wunderte ich mich stets darüber, dass Programme, die aus den 
gleichen Sourcen kompiliert wurden, unter Linux
mit GCC Umgebung um 
einiges größer waren als unter Windows
mit MSVC.

Und ja, das manifestiert sich vor allem im Einsatz von statisch 
kompilierten Bibliotheken.
Also was kann man dagegen tun?
</summary>
   <content type="html">&lt;p&gt;Schon 2007 am Anfang meiner &lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B&quot;&gt;C++&lt;/a&gt; 
Liebschaft wunderte ich mich stets darüber, dass Programme, die aus den 
gleichen Sourcen kompiliert wurden, unter &lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt;
mit &lt;a href=&quot;https://de.wikipedia.org/wiki/GNU_Compiler_Collection&quot;&gt;GCC&lt;/a&gt; Umgebung um 
einiges größer waren als unter &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows&quot;&gt;Windows&lt;/a&gt;
mit &lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_C%2B%2B&quot;&gt;MSVC&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Und ja, das manifestiert sich vor allem im Einsatz von statisch 
kompilierten Bibliotheken.&lt;br /&gt;
&lt;em&gt;Also was kann man dagegen tun?&lt;/em&gt;
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; LTO funktioniert erst ab GCC 7.&lt;br /&gt;
&lt;a href=&quot;/blog/2021/11/lto/&quot;&gt;Auf älteren Umgebungen gibt es Probleme&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;windows-exe-und-linux-binaries-im-vergleich&quot;&gt;Windows EXE und Linux Binaries im Vergleich&lt;/h3&gt;

&lt;p&gt;Mit heutigem Stichtag sehen das größte und kleinste GATE Demo Projekt so aus:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Programm&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Plattform&lt;/th&gt;
      &lt;th style=&quot;text-align: right&quot;&gt;Größe&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;gatecli.exe&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Windows x64&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;1 890 KB&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;gatecli&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Linux x64&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;2 765 KB&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;vtxtedit.exe&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Windows x64&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;287 KB&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;vtxtedit&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Linux x64&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;1 005 KB&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Die statisch kompilierten Bibliotheken sind auf beiden Seiten gleich
(zB. &lt;code&gt;zlib&lt;/code&gt;, &lt;code&gt;libjpeg&lt;/code&gt; oder &lt;code&gt;libreSSL&lt;/code&gt;) und trotzdem ergeben sich 
Größenunterschiede vom Faktor 2 bis 3 zwischen den resultierenden Binärdateien.&lt;/p&gt;

&lt;p&gt;Natürlich könnte man argumentieren, dass die statisch einkompilierte C
&lt;a href=&quot;https://de.wikipedia.org/wiki/Laufzeitbibliothek&quot;&gt;Runtime&lt;/a&gt; in Windows nur 
ein kleiner Wrapper zur dynamischen System-C-Runtime ist,
während im &lt;code&gt;GCC&lt;/code&gt; größere Funktionssammlungen in die Binärdatei einfließen.&lt;br /&gt;
Aber mal im ernst … wenn &lt;code&gt;memcopy()&lt;/code&gt; &lt;code&gt;printf()&lt;/code&gt;, &lt;code&gt;fopen()&lt;/code&gt; und ihre 
Geschwister eine 1 Megabytes große Implementierung haben, müsste Linux schon 
verdammt ineffizient sein, wenn andere Implementierungen am Mikrocontroller 
in wenigen Kilobytes unterkommen.&lt;/p&gt;

&lt;p&gt;Einen Unterschied gibt es bei den UI-Tools wie &lt;code&gt;vtxtedit&lt;/code&gt;, das unter Windows
direkt die &lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_Application_Programming_Interface&quot;&gt;WinAPI&lt;/a&gt;
(&lt;code&gt;kernel&lt;/code&gt;, &lt;code&gt;user32&lt;/code&gt; und &lt;code&gt;gdi32&lt;/code&gt;) nutzt, während das Linux-Kompilat auf 
&lt;a href=&quot;https://de.wikipedia.org/wiki/GTK_(Programmbibliothek)&quot;&gt;GTK+ 3&lt;/a&gt; zugreift.
&lt;code&gt;GTK&lt;/code&gt; ist zwar dynamisch gelinkt, was aber nicht heißt, dass hier 
zusätzliche Dispatcher und Inline-Funktionen zur Geltung kommen.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;gatecli&lt;/code&gt; hingegen nutzt ausschließlich nur Konsolen-APIs zur Kommunikation
und alle externen Algorithmen und Features liegen in den gleichen Quellen vor.&lt;/p&gt;

&lt;p&gt;Der Grund für die Größenunterschiede sollte also in der “üblichen”
Codegenerierung liegen …&lt;/p&gt;

&lt;h3 id=&quot;gcc-binärausgaben-verkleinern&quot;&gt;GCC Binärausgaben verkleinern&lt;/h3&gt;

&lt;p&gt;Ich habe daher mal im Netz etwas herumgesucht, was man tun kann, 
um GCC Binaries zu verkleinern. Folgende Ansätze habe ich gefunden:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;-Os&lt;/code&gt; Compiler Option anstatt von &lt;code&gt;-O3&lt;/code&gt; um für geringe Größe zu optimieren.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;-flto&lt;/code&gt; Compiler und Linker Option um 
&lt;a href=&quot;https://gcc.gnu.org/wiki/LinkTimeOptimization&quot;&gt;Link-Time-Optimization&lt;/a&gt; 
zu aktivieren.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;-fdata-sections -ffunction-sections&lt;/code&gt; beim Kompilieren und 
&lt;code&gt;-Wl,--gc-sections&lt;/code&gt; beim Linken einsetzen um unbenutzten Code und Daten 
zu entfernen.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;-s&lt;/code&gt; Compiler und Linker Option zur Entfernung von Debugging-Symbolen 
aktivieren.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nun kommt hinzu, dass ich aus Kompatibilitätsgründen nur 
&lt;a href=&quot;https://de.wikipedia.org/wiki/CMake&quot;&gt;CMake&lt;/a&gt; 3.0 nutze, welches die 
Link-Time-Optimization noch nicht selbst unterstützt, womit ich alle 
Compiler und Linker-Flags selbst setzen muss.&lt;/p&gt;

&lt;p&gt;Ein Spezialfall ist auch &lt;code&gt;-Os&lt;/code&gt;, denn &lt;code&gt;CMake&lt;/code&gt; fügt automatisch ein &lt;code&gt;-O3&lt;/code&gt; 
hinten an, was mein &lt;code&gt;-Os&lt;/code&gt; offenbar aufhebt. Daher muss dieses zuerst in 
&lt;code&gt;CMake&lt;/code&gt; entfernt werden mit:&lt;br /&gt;
&lt;code&gt;string(REPLACE &quot;-O3&quot; &quot;&quot; CMAKE_C_FLAGS_RELEASE &quot;${CMAKE_C_FLAGS_RELEASE}&quot;)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Nachdem diese Optimierungen nur im Falle eines &lt;code&gt;GCC&lt;/code&gt; Compiler wirksam 
werden sollen, sieht mein &lt;code&gt;CMakeLists.txt&lt;/code&gt; Update ungefähr so aus:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;if(CMAKE_COMPILER_IS_GNUCC)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;  string(REPLACE &amp;quot;-O3&amp;quot; &amp;quot;&amp;quot; CMAKE_C_FLAGS_RELEASE &amp;quot;${CMAKE_C_FLAGS_RELEASE}&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  set(CMAKE_C_FLAGS_RELEASE 
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;      ${CMAKE_C_FLAGS_RELEASE} 
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;      -flto -Os -s -fdata-sections -ffunction-sections)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;  set(CMAKE_EXE_LINKER_FLAGS_RELEASE 
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;      ${CMAKE_EXE_LINKER_FLAGS_RELEASE} 
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;      -flto -s -Wl,--gc-sections)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;endif(CMAKE_COMPILER_IS_GNUCC)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;if(CMAKE_COMPILER_IS_GNUCXX)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;  string(REPLACE &amp;quot;-O3&amp;quot; &amp;quot;&amp;quot; CMAKE_CXX_FLAGS_RELEASE &amp;quot;${CMAKE_CXX_FLAGS_RELEASE}&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;  set(CMAKE_CXX_FLAGS_RELEASE 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;      ${CMAKE_CXX_FLAGS_RELEASE} 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;      -flto -Os -s -fdata-sections -ffunction-sections)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;  set(CMAKE_EXE_LINKER_FLAGS_RELEASE 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;      ${CMAKE_EXE_LINKER_FLAGS_RELEASE} 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;      -flto -s -Wl,--gc-sections)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;endif(CMAKE_COMPILER_IS_GNUCXX)
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h3 id=&quot;resultate&quot;&gt;Resultate&lt;/h3&gt;

&lt;p&gt;Nach einem vollständigen Rebuild nach einem &lt;code&gt;make clean&lt;/code&gt; sieht die 
Tabelle jetzt anders aus:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Programm&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Plattform&lt;/th&gt;
      &lt;th style=&quot;text-align: right&quot;&gt;Neue Größe&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;gatecli.exe&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Windows x64&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;1 890 KB&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;gatecli&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Linux x64&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;1 621 KB&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;vtxtedit.exe&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Windows x64&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;287 KB&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;vtxtedit&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Linux x64&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;598 KB&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Wow! &lt;code&gt;gatecli&lt;/code&gt; ist unter Linux jetzt sogar kleiner als unter Windows.
Fast könnte man glauben, dass der &lt;code&gt;GCC&lt;/code&gt; jetzt bessere Resultate liefert als
der &lt;code&gt;MSVC&lt;/code&gt; (was im Detail auch stimmen kann), aber hier wirkt sich eher aus,
dass einige Linux-Implementierungen auf meiner Seite nur &lt;code&gt;NOT_IMPLEMENTED&lt;/code&gt;
zurückliefern, während unter Windows schon ein paar hundert Zeilen 
abgetippt wurden.&lt;/p&gt;

&lt;p&gt;Aber mit diesem Ergebnis kann ich mich schon ganz gut anfreunden.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Link-Time-Optimierungen sind unter &lt;code&gt;MSVC&lt;/code&gt; schon lange eine Default 
Einstellung, die der &lt;code&gt;GCC&lt;/code&gt; jedoch explizit vorgeschrieben braucht.
Das Entfernen von Debug-Infos könnte man bei den Windows-Binaries natürlich
auch aktivieren, aber meiner Erfahrung nach bringt das nur wenige Kilobytes.&lt;/p&gt;

&lt;p&gt;Eher könnte man diverse Runtime-Sicherheitsfeatures deaktivieren,
was ebenso in kleinerem generiertem Code-Output mündet.&lt;/p&gt;

&lt;p&gt;Natürlich ist mir auch klar, dass mit dynamisch gelinkten C-Runtimes die 
Binärpakete um ein paar hundert Kilobytes kleiner werden können, doch dafür
verlieren sie die Fähigkeit auf allen Systemen ohne Installation der Runtime
zu laufen … und dieses Opfer möchte ich nicht erbringen.&lt;/p&gt;

&lt;p&gt;Wie auch immer. Mit ein paar Zeilen &lt;code&gt;CMake&lt;/code&gt; wurde fast 1 MB unnötiger Ballast
entfernt und die anderen hier nicht gelisteten Projekte profitieren 
ebenfalls von der Magerkur.&lt;/p&gt;

&lt;p&gt;Tja, wieder was gelernt … alles in allem also ein erfolgreicher Tag.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Lambda Experimente</title>
   <link href="https://www.opengate.at/blog/2021/05/lambda/"/>
   <published>2021-05-08T13:00:00+02:00</published>
   <updated>2021-05-08T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2021/05/lambda</id>
   <category term="devel" />
   <summary type="text">Da Lambda Ausdrücke 
leider erst mit C++11 in den 
Standard eingeflossen sind, fällt ihre direkte Nutzung im GATE Projekt 
grundsätzlich weg.
Dann dann würden die Builds auf älteren Compilern unmittelbar fehlschlagen.

Aber … da stellt sich mir die Frage, ob man nicht mit Makros etwas
basteln kann, was abwärts und aufwärts kompatibel ist?
</summary>
   <content type="html">&lt;p&gt;Da &lt;a href=&quot;http://en.cppreference.com/w/cpp/language/lambda&quot;&gt;Lambda&lt;/a&gt; Ausdrücke 
leider erst mit &lt;a href=&quot;https://en.wikipedia.org/wiki/C%2B%2B11&quot;&gt;C++11&lt;/a&gt; in den 
Standard eingeflossen sind, fällt ihre direkte Nutzung im GATE Projekt 
grundsätzlich weg.&lt;br /&gt;
Dann dann würden die Builds auf älteren Compilern unmittelbar fehlschlagen.&lt;/p&gt;

&lt;p&gt;Aber … da stellt sich mir die Frage, ob man nicht mit Makros etwas
basteln kann, was abwärts und aufwärts kompatibel ist?
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Gleich eins vorweg: Das folgende Experiment produziert hässlichen
Code. Denn Makros sind immer hässlich.&lt;br /&gt;
Wie auch immer … manchmal reduzieren sie jedoch Code-Wiederholungen,
die ansonsten noch viel unübersichtlicher wären.&lt;/p&gt;

&lt;h3 id=&quot;von-funktoren-zu-lambdas&quot;&gt;Von Funktoren zu Lambdas&lt;/h3&gt;

&lt;p&gt;Das Äquivalent zu Lambda Ausdrücken waren früher freie Funktionen oder
&lt;a href=&quot;http://de.wikibooks.org/wiki/C%2B%2B-Programmierung/_Die_STL/_Funktionsobjekte&quot;&gt;Funktoren&lt;/a&gt;. 
Funktoren sind dabei den normalen Funktionen überlegen, weil sie als Objekte 
Membervariablen haben können um Zustände zu speichern.&lt;/p&gt;

&lt;p&gt;In C++03 musste man für viele &lt;code&gt;STL&lt;/code&gt; Algorithmen also immer erst ein 
Funktor Objekt erzeugen und dieses einem Algorithmus übergeben, der
über den &lt;code&gt;operator()&lt;/code&gt; den eigentlichen Code aufrufen konnte.&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;MyFunctor&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;public&lt;/span&gt;:
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;operator&lt;/span&gt;()(type_t arg)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  {
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#777&quot;&gt;// do something&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  }
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;};
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; main()
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;  type_t arg;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;  MyFunctor functor;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;  functor(arg);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Lambda Ausdrücke reduzieren das wie folgt:&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; main()
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  type_t arg;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;auto&lt;/span&gt; lambda = [](type_t arg) -&amp;gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  {
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#777&quot;&gt;// do something&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  };
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;  lambda(arg);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Man sieht also deutlich, wie sich die Schreibarbeit reduziert.&lt;/p&gt;

&lt;h3 id=&quot;makros-helfen-beim-codeverkürzen&quot;&gt;Makros helfen beim Codeverkürzen&lt;/h3&gt;

&lt;p&gt;Die Idee:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Wenn man ein Makro so gestaltet, dass es eine Funktorklasse versteckt,
hätte man ein “Interface”, das sowohl einen Funktor wie auch einen 
Lambda Ausdruck generieren kann.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ohne Captures ist dieses Unterfangen leicht. Denn C++ gestattet es 
innerhalb einer Methode eine lokale Klasse zu definieren. 
Das könnte dann so aussehen:&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#if&lt;/span&gt; defined(CPP11)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#define&lt;/span&gt; LAMBDA(instance_name, return_type, arguments, code) \
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;auto&lt;/span&gt; instance_name = [] arguments -&amp;gt; return_type code
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#else&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#define&lt;/span&gt; LAMBDA(instance_name, return_type, arguments, code) \
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;instance_name&lt;/span&gt; &lt;span style=&quot;color:#579&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;# _class&lt;/span&gt; \
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  { \
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;public&lt;/span&gt;: \
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;    return_type &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;operator&lt;/span&gt;() arguments code
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;  } instance_name
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#endif&lt;/span&gt;        
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;und wird dann so benutzt:&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; main()
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  LAMBDA(lambda_add, &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt;, (&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; x, &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; y), { 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; x + y; 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  });
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; sum = lambda_add(&lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;, &lt;span style=&quot;color:#00D&quot;&gt;2&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Schwieriger wird es mit Captures. Denn während in C++11 Lambdas
die Typen für die “eingefangenen” Variablen selbst ermittelt,
brauchen wir sie für den Funktor-Konstruktor leider schon.&lt;br /&gt;
Und ein weiterer Nachteil ist, dass man Referenzen und Kopien
separat behandeln müsste.
Ich behaupte jedoch, dass Lambdas normalerweise alles per Referenz
fangen können sollten … und folglich implementiere ich auch nur
diesen Fall aus.&lt;/p&gt;

&lt;p&gt;Und leider braucht man auch für jede Anzahl von Captures ein 
eigenes Makro:&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#define&lt;/span&gt; LAMBDA_GET_TYPE(type, variable) type
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#define&lt;/span&gt; LAMBDA_GET_VAR(type, variable) variable
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#if&lt;/span&gt; defined(CPP11)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#define&lt;/span&gt; LAMBDA_2(instance_name, cap1, cap2, return_type, arguments, code) \
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;auto&lt;/span&gt; instance_name = [&amp;amp; LAMBDA_GET_VAR cap1, \
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;                        &amp;amp; LAMBDA_GET_VAR cap2] \
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;    arguments -&amp;gt; return_type \
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;    code
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;                        
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#else&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;                        
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#define&lt;/span&gt; LAMBDA_2(instance_name, cap1, cap2, return_type, arguments, code) \
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;instance_name&lt;/span&gt; &lt;span style=&quot;color:#579&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;# _class&lt;/span&gt; \
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;{ \
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;public&lt;/span&gt;: \
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;  LAMBDA_GET_TYPE cap1 &amp;amp; LAMBDA_GET_VAR cap1 ; \
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;  LAMBDA_GET_TYPE cap2 &amp;amp; LAMBDA_GET_VAR cap2 ; \
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  instance_name &lt;span style=&quot;color:#579&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;# _class&lt;/span&gt; ( LAMBDA_GET_TYPE cap1 &amp;amp; arg1, \
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n21&quot; name=&quot;n21&quot;&gt;21&lt;/a&gt;&lt;/span&gt;                            LAMBDA_GET_TYPE cap2 &amp;amp; arg2) \
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n22&quot; name=&quot;n22&quot;&gt;22&lt;/a&gt;&lt;/span&gt;  : LAMBDA_GET_VAR cap1 (arg1), \
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n23&quot; name=&quot;n23&quot;&gt;23&lt;/a&gt;&lt;/span&gt;    LAMBDA_GET_VAR cap2 (arg2) \
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n24&quot; name=&quot;n24&quot;&gt;24&lt;/a&gt;&lt;/span&gt;    {} \
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n25&quot; name=&quot;n25&quot;&gt;25&lt;/a&gt;&lt;/span&gt;  return_type &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;operator&lt;/span&gt;() arguments code \
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n26&quot; name=&quot;n26&quot;&gt;26&lt;/a&gt;&lt;/span&gt;}; \
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n27&quot; name=&quot;n27&quot;&gt;27&lt;/a&gt;&lt;/span&gt;instance_name &lt;span style=&quot;color:#579&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;# _class&lt;/span&gt; instance_name( \
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n28&quot; name=&quot;n28&quot;&gt;28&lt;/a&gt;&lt;/span&gt;  LAMBDA_GET_VAR cap1, \
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n29&quot; name=&quot;n29&quot;&gt;29&lt;/a&gt;&lt;/span&gt;  LAMBDA_GET_VAR cap2)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n30&quot; name=&quot;n30&quot;&gt;30&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;        
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n31&quot; name=&quot;n31&quot;&gt;31&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#endif&lt;/span&gt;        
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Angewendet würde das dann so:&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; main()
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; a = &lt;span style=&quot;color:#00D&quot;&gt;1000&lt;/span&gt;; &lt;span style=&quot;color:#777&quot;&gt;// to be captured&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; b = &lt;span style=&quot;color:#00D&quot;&gt;100&lt;/span&gt;;  &lt;span style=&quot;color:#777&quot;&gt;// to be captured&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  LAMBDA_2(lambda_add_ex, (&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt;, a), (&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt;, b), 
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt;, (&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; x, &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; y),
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;    {
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; a + b + x + y;        
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;    });
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; sum = lambda_add_ex(&lt;span style=&quot;color:#00D&quot;&gt;10&lt;/span&gt;, &lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Nun, wie gesagt: Schön sind solche Makros nicht. Und trotzdem sparen sie im
Verhältnis zum voll ausprogrammierten Funktor jede Menge Code und machen
die Anweisungen dichter und meines Erachtens auch leichter lesbar.&lt;/p&gt;

&lt;p&gt;Im GATE Projekt ist dieser Entwurf im &lt;code&gt;gate/lambdas.hpp&lt;/code&gt; Header
mit weiteren Capture-Varianten implementiert.
Nachdem diese Technik nur in high-level App-Codes vorkommen soll, weiß ich 
noch nicht, ob ich es häufiger einsetzen werde, oder ob es bei einem einfachen
Experiment bleibt.&lt;/p&gt;

&lt;p&gt;Tatsächlich sind überhaupt nur die Capture-Varianten für mich relevant, denn
wenn man ohne Captures auskommt, würde ich immer eine kleine statische
Funkion schreiben und diese statt einem Lambda oder Funktor einsetzen.&lt;/p&gt;

&lt;p&gt;Aber … wenn ich ein modernes C++ Projekt betreiben würde, das nur mit 
neueren Standards ab C++17 arbeiten müsste, dann wären Lambdas für mich eine
willkommene Lösung. Sie sind zwar auch nicht immer ein Augenschmaus, aber 
sie haben ihren eigenen Charm um Code besser lesbar zu gestalten.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Mermaid Graphen in Jekyll</title>
   <link href="https://www.opengate.at/blog/2021/05/mermaid/"/>
   <published>2021-05-02T13:00:00+02:00</published>
   <updated>2021-05-02T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2021/05/mermaid</id>
   <category term="devel" /><category term="software" />
   <summary type="text">Als Erweiterung für Markdown 
Readme Dateien in GitLab kenne ich 
das Mermaid Plugin schon länger. 
Aber aktuell nutze ich es wieder häufiger in Dokumentationen für 
Ablaufdiagramme.

Hmm … und eigentlich wäre das doch ganz toll für die Homepage
und im Blog … aber wie richtet man diese Erweiterung in 
Jekyll ein?
</summary>
   <content type="html">&lt;p&gt;Als Erweiterung für &lt;a href=&quot;https://de.wikipedia.org/wiki/Markdown&quot;&gt;Markdown&lt;/a&gt; 
Readme Dateien in &lt;a href=&quot;https://de.wikipedia.org/wiki/GitLab&quot;&gt;GitLab&lt;/a&gt; kenne ich 
das &lt;a href=&quot;https://mermaid-js.github.io/mermaid/&quot;&gt;Mermaid&lt;/a&gt; Plugin schon länger. &lt;br /&gt;
Aber aktuell nutze ich es wieder häufiger in Dokumentationen für 
Ablaufdiagramme.&lt;/p&gt;

&lt;p&gt;Hmm … und eigentlich wäre das doch ganz toll für die Homepage
und im Blog … aber wie richtet man diese Erweiterung in 
&lt;a href=&quot;https://jekyllrb.com/docs/installation/&quot;&gt;Jekyll&lt;/a&gt; ein?
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;was-ist-mermaid&quot;&gt;Was ist Mermaid?&lt;/h3&gt;

&lt;p&gt;Mit &lt;code&gt;Mermaid&lt;/code&gt; definiert man in &lt;a href=&quot;https://de.wikipedia.org/wiki/American_Standard_Code_for_Information_Interchange&quot;&gt;ASCII&lt;/a&gt;
Form Abhängigkeiten zwischen Elementen und das Plugin zeichnet dann eine 
graphische Darstellung daraus. Es ist also eine Erweiterung die so ähnlich 
wie das Code-Highlighting-Plugin Texte liest und die Darstellung dann 
farblich “anpasst”.&lt;/p&gt;

&lt;p&gt;Am Ende bewirkt dann ein Text-Code wie&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;graph LR
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;  A[Home] -- go to --&amp;gt;    B(Here)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  A       -- fly to --&amp;gt;   C(There)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  B       -- drive to --&amp;gt; D[[Destination]]
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  C       -- run to --&amp;gt;   D 
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;die Zeichnung eines Diagramms wie folgt:&lt;/p&gt;

&lt;script src=&quot;/blog/assets/mermaid/mermaid.min.js&quot;&gt;&lt;/script&gt;
&lt;div class=&quot;mermaid&quot;&gt;
graph LR
  A[Home] -- go to --&amp;gt;    B(Here)
  A       -- fly to --&amp;gt;   C(There)
  B       -- drive to --&amp;gt; D[[Destination]]
  C       -- run to --&amp;gt;   D
&lt;/div&gt;

&lt;p&gt;Man nutzt IDs (im Beispiel &lt;code&gt;A&lt;/code&gt;, &lt;code&gt;B&lt;/code&gt;, &lt;code&gt;C&lt;/code&gt;, und &lt;code&gt;D&lt;/code&gt;) und Zeichenpfeile um
sie zu verknüpfen und kann dann mit Klammern eckige und abgerundete Kasten 
rund um Beschreibungen dazu definieren.&lt;br /&gt;
Beim Zeichnen des Graphen versucht &lt;code&gt;Mermaid&lt;/code&gt; sein bestes um eine 
ansprechende Grafik zu erzeugen. Manchmal muss man aber auch die 
Reihenfolge der Verknüpfungszeilen umstellen, damit von links nach rechts
bzw. von oben nach unten alles gut ausbalanciert ist.&lt;/p&gt;

&lt;p&gt;Eine gute Übersicht über alle Möglichkeiten findet man natürlich auf der
&lt;a href=&quot;https://mermaid-js.github.io/mermaid/#/flowchart?id=flowcharts-basic-syntax&quot;&gt;Webseite&lt;/a&gt;&lt;/p&gt;

&lt;h3 id=&quot;einrichtung-in-jekyll&quot;&gt;Einrichtung in Jekyll&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Kurzfassung:&lt;/strong&gt; &lt;code&gt;Mermaid&lt;/code&gt; gibt es als reine &lt;a href=&quot;https://de.wikipedia.org/wiki/JavaScript&quot;&gt;JavaScript&lt;/a&gt;
Implementierung, die man einfach dem eigenen Jekyll Projekt hinzufügt. 
Installiert man dann noch das &lt;a href=&quot;https://de.wikipedia.org/wiki/RubyGems&quot;&gt;Ruby GEM&lt;/a&gt;
&lt;code&gt;jekyll-mermaid&lt;/code&gt; und richtet es in der &lt;code&gt;_config.yml&lt;/code&gt; ein, kann man schon 
loslegen.&lt;br /&gt;
Die Jekyll Erweiterung braucht den Pfad zu den Javascript Sourcen, weil 
einfach ein &lt;code&gt;&amp;lt;script src=&quot;path/to/mermaid.js&quot;&amp;gt;&lt;/code&gt; Tag eingefügt wird und der 
Text-Code dem Javascript vorgeworfen wird. Dieses zeichnet dann das 
Ergebnis in ein dynamisch eingefügtes SVG Element.&lt;/p&gt;

&lt;p&gt;Für die Installation braucht man also folgende Schritte:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Download der &lt;code&gt;mermaid&lt;/code&gt; Sourcen von &lt;a href=&quot;https://github.com/mermaid-js/mermaid/&quot;&gt;github.com/mermaid-js&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Kopieren der Dateien aus dem Unterordner &lt;code&gt;dist_dev&lt;/code&gt; ins eigene Jekyll 
Projekt, z.B.: nach &lt;code&gt;/assets/mermaid&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Installation des Jekyll &lt;code&gt;mermaid&lt;/code&gt; Plugins per &lt;code&gt;gem install jekyll-mermaid&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;In der Datei &lt;code&gt;Gemfile&lt;/code&gt; im Jekyll Projekt: Eintrag der Zeile 
&lt;code&gt;gem &quot;jekyll-mermaid&quot;&lt;/code&gt; innerhalb des Blocks &lt;code&gt;group :jekyll_plugins do&lt;/code&gt;&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;group :jekyll_plugins do
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;  gem &amp;quot;first-plugin&amp;quot;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  gem &amp;quot;some-plugin&amp;quot;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  gem &amp;quot;other-plugin&amp;quot;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;     
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;    gem &amp;quot;jekyll-mermaid&amp;quot;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;end
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;In der Datei &lt;code&gt;_config.yml&lt;/code&gt; im Jekyll Projekt: Hinzufügung der YAML 
Einträge:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;plugins:
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;  - jekyll-mermaid
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;mermaid:
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  src: &amp;quot;/path/to/mermaid/mermaid.js&amp;quot;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Tja, und nun kann es auch schon losgehen. In Jekyll muss der &lt;code&gt;mermaid&lt;/code&gt; Block
wie folgt kodiert werden:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;... some other markdown text
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;{% mermaid %}
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;graph TD
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  A[Home] -- go to --&amp;gt;    B(Here)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;  A       -- fly to --&amp;gt;   C(There)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  B       -- drive to --&amp;gt; D
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;  C       -- run to --&amp;gt;   D    
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;{% endmermaid %}
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;some other markdown text ...
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Echt coole Sache, dieses Plugin. Nun kann ich auch Abläufe im GATE Projekt
grafisch anschaulich beschreiben, ohne dass ich immer &lt;a href=&quot;https://de.wikipedia.org/wiki/JPEG&quot;&gt;JPEGs&lt;/a&gt;
und &lt;a href=&quot;https://de.wikipedia.org/wiki/Portable_Network_Graphics&quot;&gt;PNGs&lt;/a&gt; 
dafür einbinden muss.&lt;/p&gt;

&lt;p&gt;Eine weitere geniale Erfindung ist der Online-Editor unter:&lt;br /&gt;
&lt;a href=&quot;https://mermaid-js.github.io/mermaid-live-editor&quot;&gt;mermaid-js.github.io/mermaid-live-editor&lt;/a&gt;&lt;br /&gt;
Mit diesem kann man sofort sehen, wie der eingetippte Code interpretiert und
gezeichnet wird.
Damit kann man den idealen Graphen entwerfen und dann das Resultat direkt in
die finale Markdown Datei kopieren.&lt;/p&gt;

&lt;p&gt;Fast Schade, dass ich das erst jetzt entdeckt habe. Schließlich hätte ich dieses
Feature vom Anfang an auf &lt;code&gt;opengate.at&lt;/code&gt; nutzen können.
Aber ein paar Graphen kann ich ja rückwirkend in ältere Seiten einfügen.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>CONAN exports vs. exports_sources</title>
   <link href="https://www.opengate.at/blog/2021/05/conan-exports/"/>
   <published>2021-05-01T13:00:00+02:00</published>
   <updated>2021-05-01T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2021/05/conan-exports</id>
   <category term="devel" /><category term="software" />
   <summary type="text">Seit eineinhalb Jahren darf bzw. muss ich mit CONAN
zurecht kommen und langsam “hat man sich eingewöhnt”.

Jetzt kommt die Phase wo man feststellt, dass man von Anfang an vieles
verkehrt aufgebaut hat, weil damals eben vieles falsch verstanden wurde.

Und ein solcher lästiger Punkt ist 
exports und 
exports_sources.
</summary>
   <content type="html">&lt;p&gt;Seit eineinhalb Jahren darf bzw. muss ich mit &lt;a href=&quot;https://docs.conan.io/&quot;&gt;CONAN&lt;/a&gt;
zurecht kommen und langsam “hat man sich eingewöhnt”.&lt;/p&gt;

&lt;p&gt;Jetzt kommt die Phase wo man feststellt, dass man von Anfang an vieles
verkehrt aufgebaut hat, weil damals eben vieles falsch verstanden wurde.&lt;/p&gt;

&lt;p&gt;Und ein solcher lästiger Punkt ist 
&lt;a href=&quot;https://docs.conan.io/en/latest/reference/conanfile/attributes.html#exports&quot;&gt;&lt;code&gt;exports&lt;/code&gt;&lt;/a&gt; und 
&lt;a href=&quot;https://docs.conan.io/en/latest/reference/conanfile/attributes.html#exports-sources&quot;&gt;&lt;code&gt;exports_sources&lt;/code&gt;&lt;/a&gt;.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Nachdem ich nun meine Erkenntnisse schon ein paar mal verbal 
weiterverteilt habe, macht es Sinn alles niederzuschreiben und dann 
darauf zu verweisen.&lt;/p&gt;

&lt;h3 id=&quot;opensource-funktioniert-anders&quot;&gt;OpenSource funktioniert anders&lt;/h3&gt;

&lt;p&gt;In der &lt;a href=&quot;https://de.wikipedia.org/wiki/Open_Source&quot;&gt;OpenSource&lt;/a&gt; Welt wird 
&lt;code&gt;CONAN&lt;/code&gt; anders eingesetzt, als wir es in Firmen-internen Buildumgebungen tun.&lt;br /&gt;
Da gibt es:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;ein Projekt, das den Build “irgendwie” durchführt und Ergebnisse 
produziert und publiziert.&lt;/li&gt;
  &lt;li&gt;und ein &lt;code&gt;CONAN&lt;/code&gt; Projekt, das nur aus einem &lt;code&gt;conanfile.py&lt;/code&gt; besteht.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;conanfile.py&lt;/code&gt; implementiert dort eine &lt;code&gt;source()&lt;/code&gt; Methode, die die
Ergebnisse des OpenSource Projektes aus dem Internet herunterlädt 
(manchmal als Quellcodes, manchmal als fertige Binärdateien).
Danach läuft falls erforderlich ein Build-Vorgang und danach wird
ein &lt;code&gt;CONAN&lt;/code&gt; Paket geschnürt.&lt;/p&gt;

&lt;p&gt;Bei dieser Form von Trennung, hat das &lt;code&gt;CONAN&lt;/code&gt; Projekt keine Abhängigkeiten
zu anderen Dateien, weil es alles, was es braucht, während der Ausführung
aus dem Netz herunterlädt.
Manche Projekte nutzen dann zusätzlich &lt;code&gt;exports: &quot;\*&quot;&lt;/code&gt;, weil einige 
Lizenzdateien beiliegen, die sie immer dabei haben wollen.&lt;/p&gt;

&lt;h3 id=&quot;problem-exports-&quot;&gt;Problem: exports: “*”&lt;/h3&gt;

&lt;p&gt;In unserem Build-System hingegen werden die Quellcodes der Projekte aus 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Git&quot;&gt;GIT&lt;/a&gt; geladen und dann wird das dort 
inkludierte &lt;code&gt;conanfile.py&lt;/code&gt; mit &lt;code&gt;conan create .&lt;/code&gt; aufgerufen um die Sourcen zu 
bauen und ein &lt;code&gt;CONAN&lt;/code&gt; Paket zu schaffen.&lt;/p&gt;

&lt;p&gt;Immer wieder stößt man dabei auf die Zeile &lt;code&gt;exports: &quot;*&quot;&lt;/code&gt; bzw. 
&lt;code&gt;exports: ( &quot;*&quot;, &quot;!private&quot;)&lt;/code&gt;.
&lt;code&gt;CONAN&lt;/code&gt; exportiert dann den gesamten Checkout-Ordner (ohne die Einträge,
die durch &lt;code&gt;!&lt;/code&gt; ausgeschlossen wurden).&lt;br /&gt;
Danach springt die &lt;code&gt;build()&lt;/code&gt; Methode an und kann “irgendwie” alles 
finden, bauen und fertigstellen.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Doch dieser Weg ist falsch!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;exports&lt;/code&gt; soll nur all jenes exportieren oder “wegsichern”, was &lt;code&gt;CONAN&lt;/code&gt;
braucht um &lt;code&gt;conanfile.py&lt;/code&gt; auszuführen. &lt;a href=&quot;https://docs.conan.io/en/latest/reference/conanfile/attributes.html?highlight=exports#exports&quot;&gt;Siehe Doku&lt;/a&gt;.&lt;br /&gt;
Hat man also ein zweites &lt;a href=&quot;https://de.wikipedia.org/wiki/Python_(Programmiersprache)&quot;&gt;Python&lt;/a&gt; 
Script mit Hilfsroutinen neben &lt;code&gt;conanfile.py&lt;/code&gt; liegen und nutzt es aus dem 
&lt;code&gt;CONAN&lt;/code&gt; Script heraus, dann muss es “exportiert” werden, um später für die 
Ausführung zur Verfügung zu stehen.&lt;/p&gt;

&lt;p&gt;Wenn nun eine andere Komponente eine Abhängigkeit zu unserer erstellten
deklariert, lädt CONAN alles “exportierte” zusammen mit &lt;code&gt;conanfile.py&lt;/code&gt; 
herunter und führt Teile davon aus, um die Abhängigkeiten korrekt
aufzulösen.&lt;br /&gt;
Da macht es keinen Sinn, dass Sourcecodes (oder noch schlimmer: Binärdateien)
dabei sind, was bei &lt;code&gt;exports: &quot;\*&quot;&lt;/code&gt; der Fall wäre.&lt;/p&gt;

&lt;p&gt;Dieser falsche Weg wird eingeschlagen, weil alles, was durch &lt;code&gt;exports&lt;/code&gt; 
markiert wird, automatisch auch im Build-Schritt den Build-Tools zur 
Verfügung steht.&lt;/p&gt;

&lt;p&gt;Aber eben genau dafür existiert &lt;code&gt;exports_sources&lt;/code&gt;, damit diese Inhalte
in einem eigenen Ordner im &lt;code&gt;CONAN&lt;/code&gt; Cache gespeichert werden. Bei 
einer Abhängigkeits-Auflösung werden diese Daten dann nämlich nicht mit 
heruntergeladen. Sehr wohl wird der Inhalt aber beim Build-Vorgang in den
Build-Ordner kopiert, damit alles gebaut werden kann.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Für meine Arbeitswelt existieren also zwei Formen der Nutzung von &lt;code&gt;CONAN&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;conanfile.py&lt;/code&gt; hat eine &lt;code&gt;source()&lt;/code&gt; Methode, die die eigentlichen Daten
von einem anderen Ort herunterlädt (oder irgendwie generiert)&lt;/li&gt;
  &lt;li&gt;oder &lt;code&gt;conanfile.py&lt;/code&gt; liegt bei den Sourcen und speichert sich 
die Quellcodes per &lt;code&gt;exports_sources&lt;/code&gt; im Cache weg, um sie dann nur 
beim Neubauen (Build-Schritt) einzusetzen.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Wir konnten jedenfalls durch die Umstellung von &lt;code&gt;exports: &quot;*&quot;&lt;/code&gt; zu 
&lt;code&gt;exports_sources: ( &quot;include/*&quot;, &quot;lib/*&quot;, &quot;source/*&quot;)&lt;/code&gt; Downloads von 
mehreren 100 MB durch wenige Kilobytes ersetzen.&lt;/p&gt;

&lt;p&gt;Und nachdem Dank &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Azure&quot;&gt;Azure&lt;/a&gt; und
andere &lt;a href=&quot;https://de.wikipedia.org/wiki/Cloud_Computing&quot;&gt;Cloud-Dienste&lt;/a&gt; die 
Daten quer über den Planeten verschickt werden, bringt das am Ende einiges.&lt;br /&gt;
Trotzdem tauchen immer wieder kleinere Projekte auf, bei denen diese 
Umstellung noch nicht durchgeführt wurde.&lt;/p&gt;

&lt;p&gt;Die &lt;code&gt;CONAN&lt;/code&gt; Dokumentation ist aus meiner Sicht nicht deutlich genug um 
diese Ausprägungen zu beschreiben … und somit macht man es am Anfang
leider oft falsch, bis man aus Schaden klug wird.&lt;/p&gt;

&lt;p&gt;… wie so oft in unserer digitalen Welt.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Teilfehlschlag: Alte SDK in Docker</title>
   <link href="https://www.opengate.at/blog/2021/04/winsdk-docker/"/>
   <published>2021-04-25T13:00:00+02:00</published>
   <updated>2021-04-25T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2021/04/winsdk-docker</id>
   <category term="devel" /><category term="software" />
   <summary type="text">Obwohl ich Docker nicht 
wirklich gut leiden kann, bin ich immer offen dafür, künstlich geschaffene 
Probleme damit zu lösen … so lange sie “spannend” sind.

Vor einiger Zeit hatte ich doch das Quick-and-Dirty Setup für 
MSVC 2005 Builds ohne Installation
geschildert. Daraus ergibt sich doch die Frage:


  Kann man eine “ordentliche” MSVC 2005 Buildumgebung für Docker schaffen?


</summary>
   <content type="html">&lt;p&gt;Obwohl ich &lt;a href=&quot;https://de.wikipedia.org/wiki/Docker_(Software)&quot;&gt;Docker&lt;/a&gt; nicht 
wirklich gut leiden kann, bin ich immer offen dafür, künstlich geschaffene 
Probleme damit zu lösen … so lange sie “spannend” sind.&lt;/p&gt;

&lt;p&gt;Vor einiger Zeit hatte ich doch das Quick-and-Dirty Setup für 
&lt;a href=&quot;/blog/2020/10/vs-no-install/&quot;&gt;MSVC 2005 Builds ohne Installation&lt;/a&gt;
geschildert. Daraus ergibt sich doch die Frage:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Kann man eine “ordentliche” &lt;code&gt;MSVC&lt;/code&gt; 2005 Buildumgebung für Docker schaffen?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Antwort: Halb Ja, halb Nein, es kommt darauf an.&lt;/p&gt;

&lt;p&gt;Ich, der ich von &lt;a href=&quot;https://de.wikipedia.org/wiki/CMake&quot;&gt;CMake&lt;/a&gt; abhängig bin, 
schaue leider durch die Finger, aber wer ohne &lt;code&gt;CMake&lt;/code&gt; direkt mit 
&lt;a href=&quot;https://docs.microsoft.com/en-us/cpp/build/reference/nmake-reference&quot;&gt;NMAKE&lt;/a&gt;
arbeitet, hat eventuell Glück.&lt;/p&gt;

&lt;p&gt;Alte Platform-SDKs (zB. von Server 2003 oder Vista) haben den MSVC++ 2005
integriert und lassen sich tatsächlich in Docker installieren und wenn 
man das Environment-Script ausführt, springt tatsächlich der Compiler an.&lt;/p&gt;

&lt;p&gt;Leider kann &lt;code&gt;CMake&lt;/code&gt; damit nicht umgehen und sendet in seinen Test-Routinen
Flags, die Runtime falsch einbinden. Damit kann &lt;code&gt;CMake&lt;/code&gt; nicht feststellen,
welcher Compiler benutzt wird und bricht alles Weitere ab.&lt;/p&gt;

&lt;p&gt;Aber vielleicht hilft mein Experiment ja anderen weiter, die direkt
mit &lt;code&gt;NMAKE&lt;/code&gt; arbeiten. &lt;code&gt;MSBUILD&lt;/code&gt; wird leider auch nicht unterstützt und somit
kann man auch keine Studio Solutions (&lt;code&gt;*.sln&lt;/code&gt;) kompilieren lassen.&lt;/p&gt;

&lt;h3 id=&quot;dockerfile-für-msvc-2005&quot;&gt;Dockerfile für MSVC 2005&lt;/h3&gt;

&lt;p&gt;Wir starten mit einem Arbeitsordner, z.B.: &lt;code&gt;c:\build2005&lt;/code&gt;
Man kopiert sich am besten den Inhalt des &lt;code&gt;Setup&lt;/code&gt; Folders einer SDK wie
z.B. vom &lt;a href=&quot;https://www.microsoft.com/en-us/download/details.aspx?id=15656&quot;&gt;Server 2003 SP1&lt;/a&gt;
in ein Unterverzeichnis namens &lt;code&gt;sdk&lt;/code&gt;.&lt;br /&gt;
Dort sind dann alle MSI Pakete für die Installation drinnen.&lt;/p&gt;

&lt;p&gt;Nun legt man eine Textdatei namens &lt;code&gt;c:\build2005\Dockerfile&lt;/code&gt; an und fügt
folgenden Inhalt ein:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;FROM mcr.microsoft.com/windows/servercore:ltsc2019
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;COPY [&amp;quot;sdk&amp;quot;, &amp;quot;C:/Windows/TEMP/sdk&amp;quot;]
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;RUN msiexec.exe /i C:\Windows\TEMP\sdk\PSDK-amd64.msi /quiet /qn
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;#COPY [&amp;quot;Git-2.31.1-64-bit.exe&amp;quot;, &amp;quot;C:/Windows/TEMP/&amp;quot;]
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;#RUN C:\Windows\TEMP\Git-2.31.1-64-bit.exe /VERYSILENT /SUPPRESSMSGBOXES `
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;#      /NOCANCEL /NORESTART
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;#
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;#COPY [&amp;quot;cmake-3.6.3-win64-x64.msi&amp;quot;, &amp;quot;C:/Windows/TEMP/&amp;quot;]
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;#RUN msiexec.exe /i C:\Windows\TEMP\cmake-3.6.3-win64-x64.msi /quiet /qn
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;#RUN SETX PATH &amp;quot;%PATH%;C:\Program Files\cmake\bin&amp;quot;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;ENTRYPOINT  [&amp;quot;C:\\Windows\\System32\\cmd.exe&amp;quot;,&amp;quot;/K&amp;quot;,  `
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;&amp;quot;C:\\Program Files\\Microsoft Platform SDK for Windows Server 2003 R2\\SETENV.CMD&amp;quot;, `
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;&amp;quot;/XP64&amp;quot;,&amp;quot;/RETAIL&amp;quot;]
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Es installiert die PSDK für AMD64.
Optional hatte ich noch eine GIT und die CMAKE Installation dabei.&lt;/p&gt;

&lt;p&gt;Im &lt;code&gt;ENTRYPOINT&lt;/code&gt; wird das Build-Environment auf WinXP für Releases (Retail) aktiviert.&lt;/p&gt;

&lt;p&gt;Wenn wir &lt;code&gt;docker build -t build2005:1.0 .&lt;/code&gt; im Verzeichnis &lt;code&gt;c:\build2005&lt;/code&gt; 
ausführen, sollte Docker ein neues Images mit dem SDK einrichten.&lt;/p&gt;

&lt;p&gt;Wenn wir dieses dann mit &lt;code&gt;docker run -it build2005:1.0&lt;/code&gt; ausführen, können wir
auf der Konsole bereits &lt;code&gt;NMAKE&lt;/code&gt; und &lt;code&gt;CL&lt;/code&gt; nutzen.&lt;/p&gt;

&lt;p&gt;Wenn man aber &lt;code&gt;CMAKE&lt;/code&gt; anwirft, erscheinen Fehlermeldungen wie:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;LINK : warning LNK4012: invalid value &apos;x64&apos;, must be &apos;AM33, AMD64, 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;       ARM, CEE, EBC, IA64, M32R, MIPS, MIPS16, MIPSFPU, MIPSFPU16, 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;       MIPSR41XX, SH4, SH5, THUMB, or X86&apos;; option ignored
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;testCCompiler.c.obj : error LNK2001: unresolved external symbol _RTC_Shutdown
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;testCCompiler.c.obj : error LNK2001: unresolved external symbol _RTC_InitBase
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Weitere Tests haben ergeben, dass das Kompilieren einer einfachen “Hello World”
Test-EXE mit der Option &lt;code&gt;/MD&lt;/code&gt; (dynamische CRT) ein funktionierendes Programm 
produzierte, während &lt;code&gt;/MT&lt;/code&gt; (statische CRT) zu vielen Fehlern führte. 
Problem waren fehlende Security-Cookies und Runtime-Checks:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;main.obj : error LNK2001: unresolved external symbol _RTC_Shutdown
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;main.obj : error LNK2001: unresolved external symbol _RTC_InitBase
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;LIBCMT.lib(mbctype.obj) : error LNK2001: unresolved external symbol 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;                                         __security_check_cookie
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;LIBCMT.lib(setlocal.obj) : error LNK2001: unresolved external symbol 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;                                          __security_check_cookie
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;LIBCMT.lib(write.obj) : error LNK2001: unresolved external symbol 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;                                       __security_check_cookie
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Also entweder fehlt mir da noch eine essentielle Einstellung, oder die SDK 
Installation kann nicht ohne Weiteres alle Projektformen durchbauen.
Gerade statische Bibliotheken sind im GATE Projekt wichtig und auch
CMake brauchte sie für seine Tests.&lt;/p&gt;

&lt;p&gt;Man muss auch hinzufügen, dass das SDK in Docker nur als 64-bit Setup läuft
und dieses auch nur 64-bit Projekte bauen kann.&lt;br /&gt;
Es kann schon sein, dass der 64-bit Support damals noch unvollständig war,
weil 32-bit den Standard darstellte.&lt;br /&gt;
Auch die VC 2005 Express Variante war nur auf 32-bit fixiert.&lt;/p&gt;

&lt;p&gt;Naja … auch Misserfolge gehören zum Leben.&lt;br /&gt;
Und vielleicht finde ich die Lösung ja ein anderes Mal.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Falcon and the Wintersoldier</title>
   <link href="https://www.opengate.at/blog/2021/04/falcon/"/>
   <published>2021-04-24T13:00:00+02:00</published>
   <updated>2021-04-24T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2021/04/falcon</id>
   <category term="entertainment" />
   <summary type="text">In Zeiten, in denen Kinos geschlossen haben und immer wieder kleinere 
StraßenaufmÄrsche durch die Gassen ziehen und gegen “ein Virus” 
demonstrieren, ziehe ich mich in meine Wohnung zurück und versuche über 
Internet-Streams und Online-Videos dem grauen Alltag zu entfliehen.

Nun ist Marvels Serie Falcon and the Winter Soldier
bei seiner letzten Folge auf Disney+ 
angelangt … also Zeit mal darüber nachzudenken.
</summary>
   <content type="html">&lt;p&gt;In Zeiten, in denen Kinos geschlossen haben und immer wieder kleinere 
Straßenaufm&lt;em&gt;Ä&lt;/em&gt;rsche durch die Gassen ziehen und gegen “ein Virus” 
demonstrieren, ziehe ich mich in meine Wohnung zurück und versuche über 
Internet-Streams und Online-Videos dem grauen Alltag zu entfliehen.&lt;/p&gt;

&lt;p&gt;Nun ist Marvels Serie &lt;a href=&quot;https://de.wikipedia.org/wiki/The_Falcon_and_the_Winter_Soldier&quot;&gt;Falcon and the Winter Soldier&lt;/a&gt;
bei seiner letzten Folge auf &lt;a href=&quot;https://de.wikipedia.org/wiki/Disney%2B&quot;&gt;Disney+&lt;/a&gt; 
angelangt … also Zeit mal darüber nachzudenken.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Im Vergleich zu &lt;a href=&quot;https://de.wikipedia.org/wiki/WandaVision&quot;&gt;WandaVision&lt;/a&gt;, wo 
ich die Protagonistin immer schon “geliebt” habe, wurden mit 
&lt;a href=&quot;http://marvel-filme.fandom.com/de/wiki/Sam_Wilson&quot;&gt;Falcon&lt;/a&gt;
 und dem &lt;a href=&quot;http://marvel-filme.fandom.com/de/wiki/Bucky_Barnes&quot;&gt;Wintersoldier&lt;/a&gt; 
 zwei andere “nicht-so-ganz-Hauptcharaktere” in den Vordergrund gebracht. 
 Die beiden waren für die Handlung früherer Filme wie 
 &lt;a href=&quot;https://de.wikipedia.org/wiki/The_Return_of_the_First_Avenger&quot;&gt;Captain America 2&lt;/a&gt; und 
 &lt;a href=&quot;https://de.wikipedia.org/wiki/The_First_Avenger:_Civil_War&quot;&gt;Civil War&lt;/a&gt; 
 relevant, aber so wirklich “spannend” fand ich diese Figuren eigentlich nicht.&lt;/p&gt;

&lt;p&gt;“Zweckdienlich” ist vermutlich das Wort, das ich am besten mit ihnen 
assoziieren kann.&lt;br /&gt;
Und von daher gingen meine Erwartungen eher in Richtung “nette Nebenbeiserie”,
wo man aber nicht all zu sehr mitfiebert.&lt;/p&gt;

&lt;p&gt;Und auf den ersten Blick war das auch so. Man sah den “Alltag” von 
Auftragshelden, die nicht wie Superhelden in den Filmen gegen übermächtige
Gegner kämpften, sondern eher wie ein Spezialkommando der Polizei agierte 
um Terroristennetze ausfindig und dingfest zu machen.&lt;/p&gt;

&lt;p&gt;Dann noch ein bisschen Drama dazu, wer jetzt der neue “Chef” werden wird und
hier könnte man das ganze schon in eine Kiste packen und als “angesehen”
abhaken.&lt;/p&gt;

&lt;h3 id=&quot;politik-und-gesellschaftskritik&quot;&gt;Politik und Gesellschaftskritik&lt;/h3&gt;

&lt;p&gt;(Achtung Spoiler!)&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Avengers:_Infinity_War&quot;&gt;Avengers Infinity War&lt;/a&gt; 
und &lt;a href=&quot;https://de.wikipedia.org/wiki/Avengers:_Endgame&quot;&gt;End Game&lt;/a&gt; hatte eine 
bis dato nicht diskutierte Weltlage geschaffen. Zuerst lässt &lt;a href=&quot;https://marvel-filme.fandom.com/de/wiki/Thanos&quot;&gt;Thanos&lt;/a&gt;
die halbe Erdbevölkerung zu Staub zerfallen, dann vergehen 5 Jahre und am Ende 
können die einst vernichteten Seelen wiederhergestellt werden.&lt;/p&gt;

&lt;p&gt;Doch was geschah in der Zwischenzeit? Hier erklärt die Serie wage, wie Staaten 
anfangs zusammenbrachen und sich dann eine “neue” Weltordnung formierte.
Leerstehende Häuser konnten an andere “vergeben” werden und irgendwie schuf der
Verlust ein neues Gefühl des Zusammenhalts.&lt;/p&gt;

&lt;p&gt;Und 5 Jahre später tauchen die zuvor ausgelöschten 4 Milliarden Menschen 
einfach wieder auf.&lt;br /&gt;
Ähm … wenn man darüber nachdenkt … eigentlich fast das schlimmere Chaos.&lt;br /&gt;
Denn so wurde die Welt wieder “zurückgesetzt”, Staaten und Ansprüche waren 
wieder da, jene, die sich in den 5 Jahren etwas aufgebaut hatten, wurden 
plötzlich zu den Sonderlingen, die nicht mehr dazu passten.&lt;/p&gt;

&lt;p&gt;Hier muss ich der Serie ein Lob aussprechen, denn selten wurde so genau
dargestellt, wie eine Gruppe von “Flüchtlingen” der neuen alten Weltordnung 
sich einfach dafür einsetzte, dass alles wieder so werden sollte, wie es
aus ihrer Sicht in den letzten 5 Jahren “gut” war.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Was hätte ich wohl an deren Stelle getan?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ich bin echt froh, dass nicht in alter Captain America Art, einfach alles 
schwarz und weiß gezeichnet wurde, und dass Falcon und der Wintersoldier 
nicht die strahlenden Helden waren, sondern als Menschen mit Problemen und 
abweichenden Ansichten dargestellt wurden.&lt;/p&gt;

&lt;h3 id=&quot;neue-hoffnung-am-ende&quot;&gt;Neue Hoffnung am Ende&lt;/h3&gt;

&lt;p&gt;Tatsächlich waren es die letzten Minuten der letzten Folge, die mir die Serie
vermutlich noch lange im Gedächtnis halten wird.&lt;br /&gt;
Denn seit der Ansprache aus &lt;a href=&quot;https://de.wikipedia.org/wiki/Black_Panther_(Film)&quot;&gt;Black Panther&lt;/a&gt;, 
gab es keine so direkte Moralrede mehr, die den Geist unserer Zeit ähnlich 
exakt und kritisch trifft.&lt;/p&gt;

&lt;p&gt;Nach der Verhinderung eines fatalen Terroranschlags redet Falcon als neuer 
Captain America “den Abgeordneten der Weltordnung” tief ins Gewissen:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Die Politiker sollen sich nicht mit Gleichgesinnten in einen Raum setzen 
und über andere bestimmen, sondern sich mit eben diesen an den Tisch 
begeben und auf Augenhöhe Lösungen ausarbeiten.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Tja, leicht gesagt … das kann man vielerorts einfordern. Sei es die 
Flüchtlingskrise, die uns seit 2015 beschäftigt, oder seien es die 
Corona-Verordnungen.&lt;br /&gt;
Viel zu selten kommt es vor, dass mal jemand sagt:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Sorry, tut mir leid, wir haben das falsch gemacht. 
jetzt machen wir es besser.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Anstatt dessen wird weiter ohne Rechtfertigung von oben nach unten hin 
“entschieden”.&lt;/p&gt;

&lt;p&gt;Und vielleicht braucht unsere Welt genau so etwas, nämlich eine fiktiven
Filmhelden, der eine Szene abspielt, in der das Hässliche von Seiten 
aufgezeigt wird, damit beide daraus lernen könne.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Genau deshalb bin ich dafür, dass jeder die Serie ansieht und die letzten 
Szenen auch nachvollziehen kann. Wie so oft, kommen wir nämlich immer nur 
gemeinsam durch die Krise.&lt;/p&gt;

&lt;p&gt;Für eine “Superheldenserie” war dieser Titel vielleicht zu bodenständig.
Aber manchmal tut nüchterner Realismus dem Körper auch ganz gut …
auch wenn er nicht so süß und zugedröhnt wie andere Serien-Bon-Bons 
schmeckt.&lt;/p&gt;

&lt;p&gt;… als nächstes steht dann die “Loki” Serie auf dem Marvel-Plan.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Python 3.6 PIP Upgrade Fehler</title>
   <link href="https://www.opengate.at/blog/2021/04/python-pip-error/"/>
   <published>2021-04-18T13:00:00+02:00</published>
   <updated>2021-04-18T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2021/04/python-pip-error</id>
   <category term="software" />
   <summary type="text">Schlimm genug, dass ich meine wertvolle Lebenszeit mit 
Python
verschwenden muss.
Regelmäßig darf ich dann auch noch Fehler mit diesem Ding ausbaden.


  Unable to find resource t64.exe in package pip._vendor.distlib


Also dokumentieren wir das mal, damit ich in Zukunft gleich weiß, 
wo ich nachschlagen muss.
</summary>
   <content type="html">&lt;p&gt;Schlimm genug, dass ich meine wertvolle Lebenszeit mit 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Python_(Programmiersprache)&quot;&gt;Python&lt;/a&gt;
verschwenden muss.&lt;br /&gt;
Regelmäßig darf ich dann auch noch Fehler mit diesem Ding ausbaden.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Unable to find resource t64.exe in package pip._vendor.distlib&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Also dokumentieren wir das mal, damit ich in Zukunft gleich weiß, 
wo ich nachschlagen muss.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Mein &lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_Studio#Version_2017&quot;&gt;Visual Studio 2017&lt;/a&gt; 
kommt in seiner Standard-Installation mit Python 3.6 aufs System und 
wenn ich was damit testen muss, nutzt ich es.&lt;/p&gt;

&lt;p&gt;Und immer wieder muss man hierfür neue Module mit &lt;code&gt;pip&lt;/code&gt; installieren,
welches dann sofort meldet, dass es selbst veraltet sei.&lt;/p&gt;

&lt;p&gt;Nun gut, &lt;code&gt;python -m pip install --upgrade pip&lt;/code&gt; sollte das für 
gewöhnlich erledigen. Doch mein altes 3.6 meldet nun eine 
Fehler (siehe oben) und bricht die Installation ab.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lösung:&lt;/strong&gt; &lt;code&gt;setuptools&lt;/code&gt; und &lt;code&gt;pip&lt;/code&gt; neu installieren.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;code&gt;python -m pip unistall pip setuptools&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;python -m pip install --upgrade setuptools&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Kaum ist der Schritt durchgelaufen, verhält sich &lt;code&gt;pip&lt;/code&gt;
(sowohl as Modul wie auch als separates Programm) wieder korrekt, 
es kann sich wieder selbst aktualisieren und neue Module installieren.&lt;/p&gt;

&lt;p&gt;Die Info findet man natürlich leicht mit einer Suche im Web, wie
z.B. &lt;a href=&quot;https://www.programmersought.com/article/31264827557/&quot;&gt;hier&lt;/a&gt;&lt;br /&gt;
Also sorgen wir mal dafür, dass sich das fortpflanzt.&lt;/p&gt;

&lt;p&gt;Was mir dann natürlich noch auffällt, ist das Problem,
in welchem Kontext man Python Updates durchgeführt hat.
Als &lt;code&gt;Administrator&lt;/code&gt; ausgeführt, liegen installierte Programme in
&lt;code&gt;C:\Program Files (x86)\Microsoft Visual Studio\Shared\Python36_64\Scripts&lt;/code&gt;
und dieser Verzeichnis muss natürlich in die &lt;code&gt;PATH&lt;/code&gt; Variable aufgenommen 
werden, damit alles von der Konsole aus funktioniert.&lt;/p&gt;

&lt;p&gt;Als unprivilegierter Benutzer aufgerufen, installiert &lt;code&gt;pip&lt;/code&gt; seine Dateien
in &lt;code&gt;c:\users\[username]\appdata\roaming\python\python36\scripts&lt;/code&gt;, was ebenso 
nicht im &lt;code&gt;PATH&lt;/code&gt; fehlen sollte.&lt;/p&gt;

&lt;p&gt;Gut … Problem gelöst&lt;br /&gt;
… und ich kann gelangweilt mit Python weitermachen.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Android und MSVC 2017</title>
   <link href="https://www.opengate.at/blog/2021/04/android-msvc/"/>
   <published>2021-04-17T13:00:00+02:00</published>
   <updated>2021-04-17T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2021/04/android-msvc</id>
   <category term="devel" />
   <summary type="text">Schon sein einiger Zeit beinhaltet das GATE Projekt eine separate 
Visual Studio 2017
Solution mit einem C++ Build für das 
Android NDK 
(Native Development Kit).

Man lernt doch so einiges, wenn man Quellcodes durch unterschiedliche 
Compiler oder Platformen schickt.

Hier mal ein Bericht von der Front:
</summary>
   <content type="html">&lt;p&gt;Schon sein einiger Zeit beinhaltet das GATE Projekt eine separate 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_Studio#Version_2017&quot;&gt;Visual Studio 2017&lt;/a&gt;
Solution mit einem C++ Build für das 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Android-Softwareentwicklung#Android_NDK&quot;&gt;Android NDK&lt;/a&gt; 
(&lt;strong&gt;N&lt;/strong&gt;ative &lt;strong&gt;D&lt;/strong&gt;evelopment &lt;strong&gt;K&lt;/strong&gt;it).&lt;/p&gt;

&lt;p&gt;Man lernt doch so einiges, wenn man Quellcodes durch unterschiedliche 
Compiler oder Platformen schickt.&lt;/p&gt;

&lt;p&gt;Hier mal ein Bericht von der Front:
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;vorgeschichte&quot;&gt;Vorgeschichte&lt;/h3&gt;

&lt;p&gt;Mein Kontakt mit dem Android NDK liegt schon über 5 Jahre zurück und war 
nicht besonders positiv. Da Android auf mich wie eine andere 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt; Distribution wirkte, vermutete 
ich, dass keine sonderlich große Portierung meiner &lt;a href=&quot;https://de.wikipedia.org/wiki/Portable_Operating_System_Interface&quot;&gt;POSIX&lt;/a&gt; 
Sourcen notwendig war.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Leider Falsch!&lt;/strong&gt; Denn Android unterstützt einige Standard POSIX Features wie
z.B. &lt;a href=&quot;https://de.wikipedia.org/wiki/Shared_Memory&quot;&gt;Shared Memory&lt;/a&gt; nicht 
und somit laufen solche API-Aufrufe ins Leere.
Auch die &lt;a href=&quot;https://de.wikipedia.org/wiki/Standard_Template_Library&quot;&gt;C++ STL&lt;/a&gt; 
und korrektes Exception Handling waren nicht Teil des ursprünglichen Konzeptes
und somit wird die Portierung von nativen Code enorm erschwert.&lt;br /&gt;
Anstatt dessen wurden neue Non-Standard C-APIs publiziert, die auf dieser
Plattform zu nutzen sind.&lt;/p&gt;

&lt;p&gt;Die Kompatibilität verbesserte sich zwar von NDK Release zu Release und es 
kamen nach und nach Wrapper-Bibliotheken ins Netz, die APIs wie &lt;a href=&quot;https://www.man7.org/linux/man-pages/man3/shmget.3p.html&quot;&gt;shmget&lt;/a&gt; 
auf Android Äquivalente hin und her übersetzten … doch ein solches 
Abhängigkeitschaos wollte ich eigentlich nicht in meiner Code-Base haben.&lt;/p&gt;

&lt;h3 id=&quot;installation-mit-studio-2017&quot;&gt;Installation mit Studio 2017&lt;/h3&gt;

&lt;p&gt;Mit Microsofts Entscheidung, Android in Visual Studio zu integrieren, stieg
meine Hoffnung, dass es nun einfacher werden könnte, mit dieser Plattform 
zu experimentieren.&lt;br /&gt;
Denn früher musste man eine Google Installation mit deren eigenen Tools 
durchführen und Projekte auf das dort vorherrschende Format konvertieren 
bzw. neu anlegen.&lt;/p&gt;

&lt;p&gt;Nun übernimmt das alles der Studio Installer und nachdem eine Vorlage und 
ein Ziel System gewählt wird, richtet die Solution alles bis zum Emulator 
hin ein.&lt;/p&gt;

&lt;h3 id=&quot;kein-x86-64-bit&quot;&gt;Kein X86 64 bit&lt;/h3&gt;

&lt;p&gt;Nun, für Android wird ohnehin meist nur für die &lt;a href=&quot;https://de.wikipedia.org/wiki/Arm-Architektur&quot;&gt;ARM Architektur&lt;/a&gt;
entwickelt, trotzdem lassen sich &lt;a href=&quot;https://de.wikipedia.org/wiki/X86-Prozessor&quot;&gt;X86&lt;/a&gt; 
32 und 64 bit Ziele anlegen. Leider werden aber für 64-bit keine Header 
mitinstalliert.&lt;br /&gt;
Im Setup wurde 64-bit aktiviert doch Builds finden dann keine Header, weil 
das benötigte Verzeichnis nicht vorhanden ist.&lt;/p&gt;

&lt;h3 id=&quot;c-locale-und-math-nicht-implementiert&quot;&gt;C-locale und math nicht implementiert&lt;/h3&gt;

&lt;p&gt;Dass System-Funktionen wie &lt;code&gt;shmget()&lt;/code&gt; wie fehlen … naja OK, aber dass
der C-Header &lt;code&gt;&amp;lt;locale.h&amp;gt;&lt;/code&gt; leer implementiert ist, gefällt mir nicht.
Die im GATE Framework integrierte Script-Sprache &lt;a href=&quot;https://de.wikipedia.org/wiki/Lua&quot;&gt;LUA&lt;/a&gt;
macht hier einen Aufruf zu &lt;code&gt;localeconf()&lt;/code&gt; in einem Makro, der nicht aufgelöst 
werden kann.&lt;/p&gt;

&lt;p&gt;Nun gut, hier geht es um ein alternatives Dezimalkommazeichen.&lt;br /&gt;
Das kann man zum Glück per vordefiniertem Maktro in den Projekteinstellungen
überschreiben, z.B. mit: &lt;code&gt;&quot;lua_getlocaledecpoint()=&apos;.&apos;&quot;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Und dann fehlt auch noch die &lt;a href=&quot;https://de.wikipedia.org/wiki/Varianten_der_Programmiersprache_C#C99&quot;&gt;C99&lt;/a&gt;
Funktion &lt;code&gt;log2&lt;/code&gt;, obwohl der Compiler diesen Standard voll abdecken sollte.
Nun gut, auch hier kann man auf das ältere &lt;code&gt;log&lt;/code&gt; aufweichen und 
&lt;code&gt;result = log(value) / log(2.0)&lt;/code&gt; nutzen.
In LUA wird das z.B. durch das Makro &lt;code&gt;LUA_USE_C89&lt;/code&gt; aktiviert.&lt;/p&gt;

&lt;h3 id=&quot;emulator-mit-unterschiedlichen-halbwertszeiten&quot;&gt;Emulator mit unterschiedlichen Halbwertszeiten&lt;/h3&gt;

&lt;p&gt;Das mit Visual Studio mitgelieferte &lt;a href=&quot;https://de.wikipedia.org/wiki/Hyper-V&quot;&gt;Hyper-V&lt;/a&gt;
VM Image mit Android in unterschiedlichen API-Levels ist eigentlich genial. 
Man kompiliert ein X86 Android Paket und das Resultat wird von der IDE in 
die VM Sitzung geladen um dort live getestet zu werden.&lt;/p&gt;

&lt;p&gt;Leider ist dieses Setup aus meiner Sicht instabil, denn mir passiert es stets,
dass nach einiger Zeit (1 - 5 Monte) Android Projekte zwar kompilieren aber 
nicht mehr zum Emulator hochgeladen werden können.&lt;br /&gt;
Ich vermute, dass Studio-Updates wie auch die halbjährlichen Windows Updates
jedes mal etwas kaputt machen und dann hilft nur noch eine Neuinstallation
oder vollständige Reparaturinstallation von Visual Studio.&lt;/p&gt;

&lt;p&gt;Und so etwas nervt über die Jahre hinweg tierisch und wurde bis heute nicht 
vollständig gefixt.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;In Summe waren die Probleme gar nicht so groß und im GATE Framework konnte
ich die meisten nicht-existierenden System-APIs einfach per &lt;code&gt;#ifdef&lt;/code&gt;
auf den Result-Code &lt;code&gt;NOTIMPLEMENTED&lt;/code&gt; umleiten.&lt;/p&gt;

&lt;p&gt;Die Emulatorsache ist lästig, aber wenn er wieder läuft, dann hält es auch
für einige Zeit.&lt;/p&gt;

&lt;p&gt;In Summe muss ich dem Visual Studio Team ein großes Lob aussprechen.
Mit der Möglichkeit Windows und Android Apps in einer Umgebung zu entwickeln,
wurde die IDE enorm aufgewertet.&lt;/p&gt;

&lt;p&gt;Mein nächstes Ziel wird es sein, ganze Android Apps mit dem GATE 
Framework zu erstellen. Bin gespannt, was sich da noch alles zeigen wird.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>3D-Druck: Monitor-Regal</title>
   <link href="https://www.opengate.at/blog/2021/04/monitor-shelf/"/>
   <published>2021-04-11T13:00:00+02:00</published>
   <updated>2021-04-11T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2021/04/monitor-shelf</id>
   <category term="hardware" /><category term="projects" />
   <summary type="text">Eigentlich hatte ich eines online bestellt, doch es fiel einem Lieferengpass
zum Opfer. Und zwar gibt so kleine Plastikteile, die man oben an seinen 
Monitor klemmen kann und damit etwas Stauraum darüber gewinnt.

Doch wozu hat man schließlich einen 3D-Drucker. 
Ein ausreichender Ersatz ist dank verfügbarer Modelle in ein paar Stunden 
selbst gedruckt.
</summary>
   <content type="html">&lt;p&gt;Eigentlich hatte ich eines online bestellt, doch es fiel einem Lieferengpass
zum Opfer. Und zwar gibt so kleine Plastikteile, die man oben an seinen 
Monitor klemmen kann und damit etwas Stauraum darüber gewinnt.&lt;/p&gt;

&lt;p&gt;Doch wozu hat man schließlich einen &lt;a href=&quot;https://de.wikipedia.org/wiki/3D-Druck&quot;&gt;3D-Drucker&lt;/a&gt;. 
Ein ausreichender Ersatz ist dank verfügbarer Modelle in ein paar Stunden 
selbst gedruckt.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Es sind oft die kleinen Dinge, die einem das tägliche Leben erleichtern.
Und nachdem mein PC Schreibtisch voll mit kleinen Schachteln ist, wo 
allerlei “Zeug” griffbereit vor mir liegt, wirkt dieser Arbeitsplatz 
stets überladen und ist mit eben diesem “Zeug” überfüllt.&lt;/p&gt;

&lt;p&gt;Ich dachte schon daran, wieder mal ein Kästchen links oder rechts 
dranzustellen, doch auf Beinhöhe ist es in meinem Zimmer auch recht 
eng geworden, weil PCs und andere Geräte wie auch Kabel den Platz 
rauben.&lt;/p&gt;

&lt;p&gt;Und dann sah ich diese kleinen “Monitor-Regale”, quasi ein Brett mit 
Widerhaken und zwei Beinchen, die die Oberfläche an der Monitor-Rückwand
stabilisieren.&lt;br /&gt;
Genau so eines wollte ich haben. Man kann sie recht günstig im Onlinehandel
finden, aber wie so oft, lässt die Logistik Tage und Wochen verstreichen
und wenn dann am Ende auch noch ein “Gerade nicht lieferbar” rauskommt,
ist es eben auch blöd gelaufen.&lt;/p&gt;

&lt;h3 id=&quot;thingiverse-löst-das-problem&quot;&gt;Thingiverse löst das Problem&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Thingiverse&quot;&gt;Thingiverse.com&lt;/a&gt; hat (fast) alles!&lt;br /&gt;
Unter dem Suchtitel “Monitor Shelf” haben kreative Personen eigene 
Varianten dieser Ablagen als 
&lt;a href=&quot;https://www.thingiverse.com/thing:1114319&quot;&gt;3D Modelle&lt;/a&gt; bereitgestellt.&lt;br /&gt;
Diese sind zugegeben etwas kleiner, kommen in Dimensionen von 
15-20 x 10 cm, doch genau das können die meisten Drucker heute drucken.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/monitor-shelf.jpg&quot; alt=&quot;Monitor Shelf&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Und es hindert einen ja niemand zwei solcher “Shelves” an einen Monitor 
zu heften.&lt;/p&gt;

&lt;p&gt;Der Druck der Abstellflächen dauerte bei mir etwa 5 Stunden und eine weitere
war für die Beine und Schrauben nötig.&lt;/p&gt;

&lt;p&gt;Kaum war der Druck abgeschlossen, hatte ich das Teil schon zusammengeschraubt
und an meinen Monitor geklettet.&lt;br /&gt;
Nun trägt es meine USB-Adapter-Schachtel, die so auch weiter griffbereit vor 
meiner Nase baumelt, aber so habe ich wieder 20 cm² Platz auf dem Tisch 
gewonnen.&lt;/p&gt;

&lt;p&gt;Und die nächsten Druckaufträge laufen schon …&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Mir gefallen solche kleinen “Hilfsmöbel”. Und während man früher nur bei 
diversen Möbelhäusern Ähnliches erhalten konnte, haben wir heute die 
Möglichkeit, sie selbst herzustellen.&lt;/p&gt;

&lt;p&gt;Das hat mir wieder mal gezeigt, dass ich falsch denke.
Anstatt lange in Einkaufsportalen herumzuhängen, sollte ich häufiger prüfen,
was ich selbst “produzieren” kann.&lt;br /&gt;
Denn ob ich jetzt mehrere Stunden in einem Baumarkt oder Möbelhaus herumsuche,
wo ich ja auch hin- und zurückfahren muss, oder ob ich den Druckauftrag gebe,
ist zeitlich auch schon egal.&lt;/p&gt;

&lt;p&gt;PS: Einzig das Filament für den Drucker muss ich weiter nachbestellen … 
denn das kann ich (noch) nicht selbst herstellen.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Blog Update</title>
   <link href="https://www.opengate.at/blog/2021/04/blog-update/"/>
   <published>2021-04-10T13:00:00+02:00</published>
   <updated>2021-04-10T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2021/04/blog-update</id>
   <category term="general" /><category term="projects" />
   <summary type="text">Boah! Schon wieder ein halbes Jahr um!

Nun gut, die Beitragüberprüfung läuft und ist fast abgeschlossen.
</summary>
   <content type="html">&lt;p&gt;Boah! Schon wieder ein halbes Jahr um!&lt;/p&gt;

&lt;p&gt;Nun gut, die Beitragüberprüfung läuft und ist fast abgeschlossen.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Mein altes Problem bleibt offenbar weiter bestehen: Ich habe bzw. nehme mir
nicht genug Zeit. Und so vertagte sich das für den Jahreswechsel geplante 
Blog Update bis zu diesem Wochenende.&lt;/p&gt;

&lt;p&gt;Die Themen gehen mir nicht aus, besonders seitdem die monatliche
&lt;a href=&quot;https://de.wikipedia.org/wiki/COVID-19-Pandemie&quot;&gt;Corona-Doku&lt;/a&gt; ebenso 
einfließt, aber “anfangen” und “fertigstellen” … das sind leider zwei 
unterschiedliche Dinge.&lt;/p&gt;

&lt;p&gt;Lange blieben wieder ein paar Server-Berichte halbfertig, weil es an 
Verifikation und Vervollständigung fehlte, doch nun ist es geschafft.
2020 ist halbwegs abgeschlossen und 2021 bis zum heutigen Tag mehr oder
weniger fertig.&lt;/p&gt;

&lt;p&gt;Technisch hat sich nach außen hin nichts getan, doch intern habe ich 
mal ein anderes “Retro-Design” mit den Blog-Text getestet.&lt;br /&gt;
Wir sind zwar im Jahr 2021, doch nachdem ich mich von meinen alten
&lt;a href=&quot;https://en.wikipedia.org/wiki/Windows_NT&quot;&gt;NT&lt;/a&gt; VMs nicht trennen kann, 
ärgert es mich, dass ich die Blog-Seiten von dort nicht laden kann.&lt;br /&gt;
Also habe ich ein &lt;a href=&quot;https://en.wikipedia.org/wiki/Internet_Explorer_6&quot;&gt;IE6&lt;/a&gt; 
kompatibles - light-weight Design erstellt und damit ein bisschen 
herumgespielt.&lt;/p&gt;

&lt;p&gt;Mal sehen ob es bis zum nächsten Update so weit fertig ist, dass man es
ins Internet hochladen kann.&lt;/p&gt;

&lt;p&gt;Ich hoffe dann mal, dass es bis zum nächsten Update nicht wieder ein
halbes Jahr dauert … aber in der aktuellen Lage wage ich keine 
Versprechungen mehr.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>DOS mit Startmenü</title>
   <link href="https://www.opengate.at/blog/2021/04/dos-menu/"/>
   <published>2021-04-04T13:00:00+02:00</published>
   <updated>2021-04-04T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2021/04/dos-menu</id>
   <category term="retro" />
   <summary type="text">Heute habe ich eine alte selbst gebrannte CD
etwa aus dem Jahr 2000 gefunden und mich darüber gefreut, was ich damals 
alles eingebaut hatte:

Sie konnte DOS starten und dort ein 
Boot-Menü für unterschiedlichste Tools und Start-Varianten bereitstellen, 
um danach unterschiedliche Tools oder Betriebssysteme zu installieren.

Es ist ziemlich in Vergessenheit geraten … aber in 
CONFIG.SYS konnte 
man Auswahlmenüs für unterschiedliche Startformen hinterlegen.
</summary>
   <content type="html">&lt;p&gt;Heute habe ich eine alte &lt;a href=&quot;https://de.wikipedia.org/wiki/Brenner_(Hardware)&quot;&gt;selbst gebrannte CD&lt;/a&gt;
etwa aus dem Jahr 2000 gefunden und mich darüber gefreut, was ich damals 
alles eingebaut hatte:&lt;/p&gt;

&lt;p&gt;Sie konnte &lt;a href=&quot;https://de.wikipedia.org/wiki/MS-DOS&quot;&gt;DOS&lt;/a&gt; starten und dort ein 
Boot-Menü für unterschiedlichste Tools und Start-Varianten bereitstellen, 
um danach unterschiedliche Tools oder Betriebssysteme zu installieren.&lt;/p&gt;

&lt;p&gt;Es ist ziemlich in Vergessenheit geraten … aber in 
&lt;a href=&quot;https://de.wikipedia.org/wiki/CONFIG.SYS&quot;&gt;&lt;code&gt;CONFIG.SYS&lt;/code&gt;&lt;/a&gt; konnte 
man Auswahlmenüs für unterschiedliche Startformen hinterlegen.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;configsys-als-ini-datei&quot;&gt;CONFIG.SYS als INI Datei&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;CONFIG.SYS&lt;/code&gt; war in DOS Zeiten eine reine Text-Datei, in der definiert wurde,
welche Treiber (meist binäre &lt;code&gt;.SYS&lt;/code&gt; Dateien) beim Start geladen werden sollten.
Bekannt sind Zeilen wie &lt;code&gt;DEVICE=HIMEM.SYS&lt;/code&gt; oder &lt;code&gt;DEVICE=RAMDRIVE.SYS&lt;/code&gt;.&lt;br /&gt;
Man merkt hier schon den &lt;code&gt;KEY=VALUE&lt;/code&gt; Charakter.&lt;/p&gt;

&lt;p&gt;Doch spätestens seit DOS 6 (keine Ahnung ob das schon früher ging), darf
&lt;code&gt;CONFIG.SYS&lt;/code&gt; auch die aus &lt;a href=&quot;https://de.wikipedia.org/wiki/Initialisierungsdatei&quot;&gt;INI Dateien&lt;/a&gt;
bekannten “Sektionen” beinhalten.&lt;br /&gt;
Sobald eine solche “Sektion” mit Namen &lt;code&gt;MENU&lt;/code&gt; vorhanden war, 
(wie z.B.: &lt;code&gt;[MENU]&lt;/code&gt;), die auch mehrere &lt;code&gt;MENUITEM&lt;/code&gt; Einträge hatte,
zeigte DOS beim BOOT ein Menü an, wo man einen dieser Einträge
auswählen konnte. &lt;br /&gt;
Der &lt;code&gt;MENUITEM&lt;/code&gt; Eintrag bestand aus dem zu startenden Sektions-Namen 
gefolgt von Komma und dem Menüeintragstext, also 
&lt;code&gt;MENUITEM=SectionName, Menu-Text&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Beim Start wurden dann nur die Kommandos der gewählten Sektion ausgeführt.
Damit man aber mehr Flexibilität hatte, gestattete die Zeile 
&lt;code&gt;INCLUDE=OtherSection&lt;/code&gt;, dass eine Sektion alle Kommandos einer anderen
beinhalten können sollte.&lt;/p&gt;

&lt;p&gt;Und so kam es, dass ich mir damals folgende &lt;code&gt;CONFIG.SYS&lt;/code&gt; gebaut hatte:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;[MENU]
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;MENUITEM=Config1,(Normal)    Start mit allgemeinem ATAPI-CDROM Treiber
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;MENUITEM=Config2,(Minimal)   Minimalstart ohne CD-Unterstützung
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;MENUITEM=Config3,(Spezial 1) Normalstart mit RAM-Disk (2 MB)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;MENUITEM=Config4,(Spezial 2) Normalstart mit RAM-Disk (8 MB)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;MENUITEM=Config5,(Spezial 3) Normalstart mit Interlink-Client
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;[Minimal]
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;DEVICE=HIMEM.SYS /TESTMEM:OFF
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;DEVICE=EMM386.EXE NOEMS
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;BUFFERS=40
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;FILES=35
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;DOS=HIGH,UMB
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;LASTDRIVE=Z
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;COUNTRY = 49,,COUNTRY.SYS
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;[Config1]
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;INCLUDE=Minimal
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;DEVICEHIGH=ATAPICD.SYS /D:CD003
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n21&quot; name=&quot;n21&quot;&gt;21&lt;/a&gt;&lt;/span&gt;[Config2]
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n22&quot; name=&quot;n22&quot;&gt;22&lt;/a&gt;&lt;/span&gt;INCLUDE=Minimal
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n23&quot; name=&quot;n23&quot;&gt;23&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n24&quot; name=&quot;n24&quot;&gt;24&lt;/a&gt;&lt;/span&gt;[Config3]
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n25&quot; name=&quot;n25&quot;&gt;25&lt;/a&gt;&lt;/span&gt;INCLUDE=Minimal
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n26&quot; name=&quot;n26&quot;&gt;26&lt;/a&gt;&lt;/span&gt;DEVICEHIGH=ATAPICD.SYS /D:CD003
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n27&quot; name=&quot;n27&quot;&gt;27&lt;/a&gt;&lt;/span&gt;DEVICEHIGH=RAMDRIVE.SYS 2048 /e
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n28&quot; name=&quot;n28&quot;&gt;28&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n29&quot; name=&quot;n29&quot;&gt;29&lt;/a&gt;&lt;/span&gt;[Config4]
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n30&quot; name=&quot;n30&quot;&gt;30&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;INCLUDE=Minimal
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n31&quot; name=&quot;n31&quot;&gt;31&lt;/a&gt;&lt;/span&gt;DEVICEHIGH=ATAPICD.SYS /D:CD003
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n32&quot; name=&quot;n32&quot;&gt;32&lt;/a&gt;&lt;/span&gt;DEVICEHIGH=RAMDRIVE.SYS 8192 /e
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n33&quot; name=&quot;n33&quot;&gt;33&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n34&quot; name=&quot;n34&quot;&gt;34&lt;/a&gt;&lt;/span&gt;[Config5]
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n35&quot; name=&quot;n35&quot;&gt;35&lt;/a&gt;&lt;/span&gt;INCLUDE=Minimal
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n36&quot; name=&quot;n36&quot;&gt;36&lt;/a&gt;&lt;/span&gt;DEVICEHIGH=ATAPICD.SYS /D:CD003
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n37&quot; name=&quot;n37&quot;&gt;37&lt;/a&gt;&lt;/span&gt;DEVICEHIGH=INTERLNK.EXE
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h3 id=&quot;fortsetzung-in-autoexecbat&quot;&gt;Fortsetzung in AUTOEXEC.BAT&lt;/h3&gt;

&lt;p&gt;Nach der Abarbeitung von &lt;code&gt;CONFIG.SYS&lt;/code&gt;, wurde in DOS stets 
&lt;a href=&quot;https://de.wikipedia.org/wiki/AUTOEXEC.BAT&quot;&gt;&lt;code&gt;AUTOEXEC.BAT&lt;/code&gt;&lt;/a&gt; ausgeführt.&lt;br /&gt;
Damit man hier ebenso auf den “ausgewählten” Menüeintrag reagieren konnte,
wurde die &lt;a href=&quot;https://de.wikipedia.org/wiki/Umgebungsvariable&quot;&gt;Umgebungsvariable&lt;/a&gt;
&lt;code&gt;CONFIG&lt;/code&gt; auf den per Menü ausgewählten Sektionsnamen gesetzt.&lt;/p&gt;

&lt;p&gt;Meine damalige Version sah so aus:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;@ECHO OFF
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;PROMPT $v$_$p$g
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;GOTO %CONFIG%
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;:Config3
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;:Config4
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;:Config5
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;:Config1
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;MSCDEX /V /D:CD003 /M:10
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;GOTO Config2
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;:Config2
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;Path A:\
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;KEYB GR
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;MOUSE.COM
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;DOSKEY
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Und der bewirkte, dass in allen “normalen” Konfigurationen der CD-Mount
durchgeführt wurde, jedoch im “Minimal-Fall” wurde dieser übersprungen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Auf dieser DOS-CD (eigentlich ein Disketten-Image, das beim Start von CD 
geladen wurde) hatte ich noch weitere BATCH Dateien um alles mögliche
zu installieren.&lt;/p&gt;

&lt;p&gt;Doch mit dem interaktiven Startmenü konnte ich spielend leicht auch 
Remote-Zugriffe per &lt;a href=&quot;https://de.wikipedia.org/wiki/Laplink&quot;&gt;&lt;code&gt;INTERLINK&lt;/code&gt;&lt;/a&gt; 
durchführen, oder &lt;a href=&quot;https://de.wikipedia.org/wiki/RAM-Disk&quot;&gt;RAM-Drives&lt;/a&gt; 
für andere Funktionen einrichten.&lt;/p&gt;

&lt;p&gt;Bevor ich das &lt;code&gt;MENU&lt;/code&gt; Feature entdeckt hatte, kam ich immer mit einer
Schachtel an &lt;a href=&quot;https://de.wikipedia.org/wiki/Diskette&quot;&gt;Disketten&lt;/a&gt; angelaufen, 
wo für jeden Notfall eine besondere Start-Variante fixiert war … nun hatte
ich eine einzige, die alles konnte.&lt;/p&gt;

&lt;p&gt;Ach, Wahnsinn … über 20 Jahre ist das jetzt her. Doch jetzt erinnere
ich mich daran, als ob es erst gestern gewesen wäre, als DOS Startmenüs
meinen Experimentier-Alltag versüßten.&lt;/p&gt;

&lt;p&gt;… und man merkt, dass ich stets immer 5-10 Jahre hinter der Zeit war,
wo ich im Jahr 2000 immer noch mit DOS beschäftigt war.
Aber … wir hatten damals ja nichts anderes im Provinzdorf.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Benutzerkonten und Gruppen</title>
   <link href="https://www.opengate.at/blog/2021/04/accounts/"/>
   <published>2021-04-03T13:00:00+02:00</published>
   <updated>2021-04-03T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2021/04/accounts</id>
   <category term="devel" />
   <summary type="text">Seit meiner Arbeit in der User-Administration
hat mich das Thema der Verwaltung von Benutzerkonten in die Programmierung 
hinein begleitet.

Und tatsächlich wird dieser Bereich sofort relevant, wenn man sich 
“ordentlich” um Prozesse kümmern muss. Denn auch die starten ja immer im 
Kontext eines bestimmten Accounts. Und der muss korrekt aufgesetzt sein.
</summary>
   <content type="html">&lt;p&gt;Seit meiner Arbeit in der &lt;a href=&quot;https://de.wikipedia.org/wiki/Benutzerverwaltung&quot;&gt;User-Administration&lt;/a&gt;
hat mich das Thema der Verwaltung von Benutzerkonten in die Programmierung 
hinein begleitet.&lt;/p&gt;

&lt;p&gt;Und tatsächlich wird dieser Bereich sofort relevant, wenn man sich 
“ordentlich” um Prozesse kümmern muss. Denn auch die starten ja immer im 
Kontext eines bestimmten Accounts. Und der muss korrekt aufgesetzt sein.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;windows&quot;&gt;Windows&lt;/h3&gt;

&lt;p&gt;Das Auflisten und Verwalten von lokalen Useraccounts übernimmt die 
&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/netmgmt/network-management-functions&quot;&gt;NETAPI&lt;/a&gt;,
auch als “Network Management Functions” bekannt.&lt;br /&gt;
Sie stellte Funktionen und Strukturdefinitionen bereit um Benutzer und Gruppen
aufzulisten, sowie auch für das Auslesen der Mitgliedschaften (Memberships) der
Benutzer in den Gruppen.&lt;/p&gt;

&lt;p&gt;Da &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_NT&quot;&gt;Windows NT&lt;/a&gt; immer 
schon die Mitgliedschaft in Domänen vorgesehen hat, wird  zwischen 
“lokalen” Gruppen (also denen auf dem benutzten Computer) und “globalen” 
Gruppen innerhalb der Domäne unterschieden und es existieren daher
auch zwei Funktionsgruppen für deren Auflistung.&lt;/p&gt;

&lt;p&gt;Ein interner Begriff für “lokale Gruppen” ist der Typ “Alias”, denn für lokale
Benutzer sind lokale Gruppen quasi Pseudonyme für Berechtigungen. 
Eine lokale Gruppe, die einen z.B. für einen Dateizugriff berechtigt ist für 
den Benutzer eben nur eine Art “anderer Name” um den Zugriff zu erhalten.&lt;/p&gt;

&lt;p&gt;Globale Gruppen bekommen dann den internen Typ “Group” um vom “Alias” 
unterschieden zu werden … aber um die soll es heute nicht gehen.&lt;/p&gt;

&lt;p&gt;Berechtigungen in &lt;a href=&quot;https://de.wikipedia.org/wiki/Access_Control_List&quot;&gt;ACLs&lt;/a&gt; 
werden immer über eine &lt;a href=&quot;https://de.wikipedia.org/wiki/Security_Identifier&quot;&gt;SID&lt;/a&gt; 
gesteuert, während die APIs meist einen Account-Namen für Benutzer und 
Gruppen erwarten, um eine Identität auszuwählen.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-lookupaccountnamew&quot;&gt;&lt;code&gt;LookupAccountName&lt;/code&gt;&lt;/a&gt; 
und &lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-lookupaccountsidw&quot;&gt;&lt;code&gt;LookupAccountSid&lt;/code&gt;&lt;/a&gt; 
sind notwendig, um eine &lt;code&gt;SID&lt;/code&gt; in einen Accountnamen und umgekehrt aufzulösen.&lt;/p&gt;

&lt;p&gt;Bei der &lt;code&gt;NETAPI&lt;/code&gt; hat man dann vor allem das Problem, dass man nur über 
den Namen eines Accounts Infos auslesen kann, aber nie direkt zur &lt;code&gt;SID&lt;/code&gt;
kommt. Man müsste also immer hin- und her auflösen.&lt;br /&gt;
Außer man benutzt einen Trick:&lt;/p&gt;

&lt;p&gt;Lokale Benutzer Accounts tragen stets die &lt;code&gt;SID&lt;/code&gt; das lokalen Computers in 
sich und diese bekommt man über &lt;a href=&quot;http://docs.microsoft.com/en-us/windows/win32/api/lmaccess/nf-lmaccess-netusermodalsget&quot;&gt;&lt;code&gt;NetUserModalsGet&lt;/code&gt;&lt;/a&gt;
mit Parameter &lt;code&gt;2&lt;/code&gt; für die &lt;code&gt;USER_MODALS_INFO_2&lt;/code&gt; Datenstruktur, denn dort liegt 
in &lt;code&gt;usrmod2_domain_id&lt;/code&gt; die &lt;code&gt;SID&lt;/code&gt; des Computers.&lt;/p&gt;

&lt;p&gt;Wenn man dann per &lt;a href=&quot;http://docs.microsoft.com/en-us/windows/win32/api/lmaccess/nf-lmaccess-netquerydisplayinformation&quot;&gt;NetQueryDisplayInformation&lt;/a&gt; 
alle lokalen Accounts über die &lt;code&gt;NET_DISPLAY_USER&lt;/code&gt; Datenstruktur auflistet, 
erhält man im Member &lt;code&gt;usri1_user_id&lt;/code&gt; die &lt;code&gt;RID&lt;/code&gt; (Relative-ID) des Accounts.&lt;br /&gt;
Und diesen Integer hängt man an die Computer-SID und hat die komplette 
Account SID.&lt;/p&gt;

&lt;p&gt;Das ist gegenüber &lt;code&gt;LookupAccountName()&lt;/code&gt; deshalb meist viel schneller, weil 
der Lookup-Vorgang gerne mal erst das Netzwerk befragt und das kann lange
dauern, während des Selbstzusammensetzen in Millisekunden erledigt ist.&lt;/p&gt;

&lt;p&gt;Tja und die anderen APIs wie 
&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/lmaccess/nf-lmaccess-netusergetinfo&quot;&gt;NetUserGetInfo()&lt;/a&gt;, 
&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/lmaccess/nf-lmaccess-netlocalgroupenum&quot;&gt;NetLocalGroupEnum()&lt;/a&gt;, 
&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/lmaccess/nf-lmaccess-netlocalgroupgetinfo&quot;&gt;NetLocalGroupGetInfo()&lt;/a&gt;, 
&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/lmaccess/nf-lmaccess-netlocalgroupaddmember&quot;&gt;NetLocalGroupAddMember()&lt;/a&gt;, 
&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/lmaccess/nf-lmaccess-netusergetlocalgroups&quot;&gt;NetUserGetLocalGroups()&lt;/a&gt; usw.
sind ja quasi selbsterklärend und gut in der MSDN beschrieben.&lt;/p&gt;

&lt;p&gt;Eines sollte man beachten: Will man brav mit NT 4 kompatibel sein, dann 
sollten man den Computernamen (also den ersten Parameter in allen Funktionen)
mit zwei Backslashes starten lassen, z.b. &lt;code&gt;\\MY_HOSTNAME&lt;/code&gt;).
Die Übergabe von &lt;code&gt;NULL&lt;/code&gt; funktioniert nämlich auf solchen Systemen nicht immer.&lt;/p&gt;

&lt;h3 id=&quot;linux&quot;&gt;Linux&lt;/h3&gt;

&lt;p&gt;Gegenüber Windows ist &lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt; recht 
leicht gestrickt, denn es hält sich hier gemäß &lt;a href=&quot;https://de.wikipedia.org/wiki/Portable_Operating_System_Interface&quot;&gt;POSIX&lt;/a&gt; 
an die Funktionen der Header &lt;a href=&quot;https://pubs.opengroup.org/onlinepubs/7908799/xsh/pwd.h.html&quot;&gt;&lt;code&gt;pwd.h&lt;/code&gt;&lt;/a&gt; 
und &lt;a href=&quot;https://pubs.opengroup.org/onlinepubs/7908799/xsh/grp.h.html&quot;&gt;&lt;code&gt;grp.h&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Hier kommt störend hinzu, dass diese Funktionen allesamt nicht thread-sicher 
sind und man stets einen &lt;a href=&quot;https://de.wikipedia.org/wiki/Mutex&quot;&gt;Mutex&lt;/a&gt; über 
alle Aufrufe stülpen sollte.&lt;/p&gt;

&lt;p&gt;Benutzer werden mit &lt;a href=&quot;https://pubs.opengroup.org/onlinepubs/7908799/xsh/endpwent.html&quot;&gt;&lt;code&gt;getpwent()&lt;/code&gt;&lt;/a&gt; 
aufgelistet und mit &lt;a href=&quot;https://pubs.opengroup.org/onlinepubs/7908799/xsh/getpwuid.html&quot;&gt;&lt;code&gt;getpwuid()&lt;/code&gt;&lt;/a&gt;
aus der User-ID und mit &lt;a href=&quot;https://pubs.opengroup.org/onlinepubs/7908799/xsh/getpwnam.html&quot;&gt;&lt;code&gt;getpwnam()&lt;/code&gt;&lt;/a&gt; 
aus dem Namen aufgelöst.&lt;br /&gt;
Bei Gruppen existieren analog die Funktionen 
&lt;a href=&quot;https://pubs.opengroup.org/onlinepubs/7908799/xsh/getgrent.html&quot;&gt;&lt;code&gt;getgrent&lt;/code&gt;&lt;/a&gt;, 
&lt;a href=&quot;https://pubs.opengroup.org/onlinepubs/7908799/xsh/getgrgid.html&quot;&gt;&lt;code&gt;getgrgid&lt;/code&gt;&lt;/a&gt; und 
&lt;a href=&quot;https://pubs.opengroup.org/onlinepubs/7908799/xsh/getgrnam.html&quot;&gt;&lt;code&gt;getgrnam&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Da bei POSIX (im Gegensatz zu Windows) ein Account immer mit einer 
Primärgruppe verknüpft ist, ist das Auflisten aller Gruppenmitgliedschaften
etwas komplizierter, dann man erhält beim Auflisten der User-Accounts die
Primärgruppen und beim Auflisten der Gruppeninhalte die Liste der 
Sekundär-Gruppenmitgliedschaften.&lt;/p&gt;

&lt;p&gt;Will man also wissen, in welchen Gruppen ein Benutzer ist, muss man alle
Gruppen durchgehen und nach dem User suchen. Umgekehrt braucht man für 
alle Mitglieder eine Gruppe die Liste aller User mit ihren Primärgruppen.&lt;/p&gt;

&lt;p&gt;Besonders relevant sind die Gruppenmitgliedschaften, wenn man Prozesse
per &lt;a href=&quot;https://pubs.opengroup.org/onlinepubs/009695399/functions/setuid.html&quot;&gt;&lt;code&gt;setuid()&lt;/code&gt;&lt;/a&gt; 
nach einem &lt;a href=&quot;https://pubs.opengroup.org/onlinepubs/009695399/functions/fork.html&quot;&gt;&lt;code&gt;fork()&lt;/code&gt;&lt;/a&gt; 
als anderer Benuter starten will. 
Hierfür muss man nämlich nach &lt;code&gt;setgid()&lt;/code&gt; mit der korrekten Primärgruppe
auch noch &lt;a href=&quot;http://www.opengroup.org/rfc/rfc86.0.html&quot;&gt;&lt;code&gt;initgroups()&lt;/code&gt;&lt;/a&gt; aufrufen.
Man braucht also Benutzeraccount und Gruppeninfo parallel, wenn man Prozesse
bearbeiten will.&lt;/p&gt;

&lt;p&gt;Ich hatte &lt;code&gt;initgroups()&lt;/code&gt; mal bei einer Implementierung vergessen und schon 
konnte ein Prozess nicht mehr auf diverse Geräte zugreifen, die eigentlich 
zugänglich hätten sein sollen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Das GATE Projekt versucht &lt;code&gt;gate/system/accounts.h&lt;/code&gt; einen
“kleinsten gemeinsamen Nenner” zwischen Windows und POSIX Benutzer- und
Gruppenaccounts zu finden und nach außen einheitlich abzubilden.&lt;/p&gt;

&lt;p&gt;Das schränkt natürlich den Handlungsspielraum ein (z.B. kein globalen
Windows-Gruppen), aber gerade im Embedded-Bereich bietet diese Abstraktion
eine ausreichende und einfache Möglichkeit, auf die äußerst 
systemspezifische Accountverwaltung zuzugreifen.&lt;/p&gt;

&lt;p&gt;Ich persönlich finde, dass viele Softwareprodukte zu wenig Gebrauch von der
Benutzerverwaltung des Systems machen und dann immer undurchsichtige 
Scripts und Installer verwenden, um Berechtigungen nachzuliefern.&lt;br /&gt;
Und genau diese Scripts versagen dann zunehmend mit neueren OS-Versionen
und man landet in einem dezenten Chaos von Anpassungen.
Noch schlimmer ist es, wenn jede Anwendung eine eigene Datenbank mit 
eigener User/Gruppenverwaltung aufbaut und im Hintergrund dann alles als
&lt;code&gt;root&lt;/code&gt; oder &lt;code&gt;LocalSystem&lt;/code&gt; läuft.&lt;/p&gt;

&lt;p&gt;Daher lautet mein Motto: &lt;strong&gt;Nutzt die System-APIs direkt!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Diese sind seit mindestens 20 Jahren stabil integriert und dokumentiert 
und jede OS-Variante baut darauf auf.&lt;br /&gt;
Egal ob Windows 10 über &lt;code&gt;hotmail.com&lt;/code&gt; oder &lt;code&gt;outlook.com&lt;/code&gt; eingerichtet wird,
oder ob Ubuntu zum X-ten Mal das &lt;code&gt;/etc&lt;/code&gt; Verzeichnis neu durchbenennt …
im Hintergrund laufen immer klassische lokale Accounts und die 
System-APIs liefern für sie die richtigen Ergebnisse.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Windows Server: RestoreHealth</title>
   <link href="https://www.opengate.at/blog/2021/03/restorehealth/"/>
   <published>2021-03-28T13:00:00+02:00</published>
   <updated>2021-03-28T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2021/03/restorehealth</id>
   <category term="software" />
   <summary type="text">Eigentlich wollte ich nur eine Windows Server Komponente hinzufügen, doch 
dann kam die Fehlermeldung, dass das Windows Komponentenrepository
korrupt sei.

Hmm … soviel zur hohen Stabilität von 
Server 2016.
Hier muss man also manuell eingreifen.
</summary>
   <content type="html">&lt;p&gt;Eigentlich wollte ich nur eine Windows Server Komponente hinzufügen, doch 
dann kam die Fehlermeldung, dass das Windows Komponentenrepository
korrupt sei.&lt;/p&gt;

&lt;p&gt;Hmm … soviel zur hohen Stabilität von 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_Server_2016&quot;&gt;Server 2016&lt;/a&gt;.
Hier muss man also manuell eingreifen.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Nun, für Problemchen in einer Windows Installation, haben wir zum Glück seit
geraumer Zeit eine &lt;a href=&quot;https://docs.microsoft.com/en-us/windows-hardware/manufacture/desktop/what-is-dism&quot;&gt;DISM&lt;/a&gt;
Zusatzfunktion und diese lautet auf:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;dism /Online /Cleanup-Image /RestoreHealth&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Dabei wird versucht, die laufende Windows Installation zu reparieren.
Das gleich kann man natürlich auch aus &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_PE&quot;&gt;Windows PE&lt;/a&gt;
heraus für nicht laufende (offline) Images oder gemountete WIM-Images tun.&lt;/p&gt;

&lt;p&gt;Tja… und dann kam:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Error:&lt;br /&gt;
The source files could not be found. Use the “Source” option to specify 
the location of the files that are required to restore the feature.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Offenbar brauchte &lt;code&gt;dism&lt;/code&gt; für meinen Problemfall die originalen Windows Sourcen.
Und dafür braucht man z.B.: das originale Windows ISO Image, worin die
&lt;code&gt;install.wim&lt;/code&gt; mit den Setup-Images liegt.&lt;/p&gt;

&lt;p&gt;Nachdem aber in der &lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_Imaging_Format_Archive&quot;&gt;WIM&lt;/a&gt; 
Datei wieder mehrere Images für unterschiedliche Produkte liegen 
(Server Core, Advanced Server usw.), muss man vorher noch den korrekten 
Image-Index herausfinden, der zur aktuellen Installation passt.&lt;br /&gt;
Die Auflistung der Image-Indizes samt weiterer Infos erreicht man mit:&lt;br /&gt;
&lt;code&gt;dism /Get-WimInfo /WimFile:E:\Sources\Install.wim&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Jetzt kann man endlich das Kommando:&lt;br /&gt;
&lt;code&gt;dism /Online /Cleanup-Image /RestoreHealth /Source:wim:E:\Sources\Install.wim:1 /limitaccess&lt;/code&gt;&lt;br /&gt;
ausführen und geduldig auf dessen Abschluss warten.&lt;/p&gt;

&lt;p&gt;Und tatsächlich … nach einem abschließenden Neustart, konnte ich endlich 
wieder weitere Komponenten installieren. Windows ist also repariert.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;RestoreHealth&lt;/code&gt; hat mir schon früher aus der Patsche geholfen. Am besten
erinnere ich mich da an die &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_7&quot;&gt;Windows 7&lt;/a&gt;
Installations-WIM-Dateien, die sich ohne ein vorangehendes &lt;code&gt;RestoreHealth&lt;/code&gt; 
nicht mit Updates patchen ließen.&lt;/p&gt;

&lt;p&gt;Nun habe ich mit &lt;code&gt;/sources&lt;/code&gt; wieder ein weiteres Feature kennengelernt.&lt;/p&gt;

&lt;p&gt;Nunja … solche Arbeitsgänge sind lästig … aber immer noch besser als 
eine komplette Neuinstallation.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Corona Teststraßen Marsch</title>
   <link href="https://www.opengate.at/blog/2021/03/corona-test-walk/"/>
   <published>2021-03-27T12:00:00+01:00</published>
   <updated>2021-03-27T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2021/03/corona-test-walk</id>
   <category term="general" />
   <summary type="text">Lange habe ich gewartet … doch nun geht es einfach nicht mehr:


  Ich MUSS zum Friseur!


Denn sich eine Haarwelle über die Stirn zu kämmen so wie 
Teenage-Justin-Bieber 
seinerzeit sieht in meinem Alter leider nicht mehr “so cool” aus, 
wie man es sich erhoffen würde.

Also auf zur Teststraße um eine Freigabe für “körpernahe Dienste” zu 
erhaschen.
</summary>
   <content type="html">&lt;p&gt;Lange habe ich gewartet … doch nun geht es einfach nicht mehr:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ich MUSS zum Friseur!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Denn sich eine Haarwelle über die Stirn zu kämmen so wie 
Teenage-&lt;a href=&quot;https://de.wikipedia.org/wiki/Justin_Bieber&quot;&gt;Justin-Bieber&lt;/a&gt; 
seinerzeit sieht in meinem Alter leider nicht mehr “so cool” aus, 
wie man es sich erhoffen würde.&lt;/p&gt;

&lt;p&gt;Also auf zur Teststraße um eine Freigabe für “körpernahe Dienste” zu 
erhaschen.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Nachdem die österreichische BundesNegierung bemüht ist, in jedes Fettnäpfchen
zu treten um die Corona-Impfung zu verzögern, gilt weiter Status-Quo:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Jeder Bürger, der einen körpernahen Dienst (wie etwa Haareschneiden) in
Anspruch nehmen will, braucht einen offiziell abgesegneten Coronatest,
der nicht älter als 48 Stunden sein darf.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href=&quot;/blog/2021/03/covid19-hometest/&quot;&gt;Meine Heimtests&lt;/a&gt; von vor ein paar
Wochen bringen beim Friseur nichts, denn die könnte ich ja manipuliert haben.&lt;/p&gt;

&lt;h3 id=&quot;alptraum-online-abmeldung&quot;&gt;Alptraum Online-Abmeldung&lt;/h3&gt;

&lt;p&gt;Am Anfang war ich noch motiviert, öffnete &lt;a href=&quot;https://coronavirus.wien.gv.at/testangebote/&quot;&gt;wien.gv.at&lt;/a&gt;
und fand auch gleich den Link zur Anmeldung in einer von Wiens “Teststraßen”.&lt;br /&gt;
Meine Wahl fiel auf die &lt;a href=&quot;https://de.wikipedia.org/wiki/Therme_Wien&quot;&gt;Therme Wien in Oberlaa&lt;/a&gt;, 
denn schließlich ist das nur ein paar Stationen mit der U1 von mir entfernt.&lt;/p&gt;

&lt;p&gt;Die Seite verlangte nur Vor- und Nachname wie eine E-Mail-Adresse, was mir
etwas wenig vorkam.
Man konnte quasi jeden Zeitpunkt zwischen 7:00 und 20:00 Uhr wählen (in 
15-Minuten Blöcken), und ich dachte, dass ich mit 12:00 Uhr den geringsten
Stress hätte.
Nach der Überprüfung der eingegeben Daten poppt auch schon eine “Fertig”
Seite auf und ein E-Mail mit der gleichen Information trudelt ein.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Nehmen Sie den bei der Registrierung erhaltenen 
&lt;a href=&quot;https://de.wikipedia.org/wiki/QR-Code&quot;&gt;QR-Code&lt;/a&gt; unbedingt zum Test mit!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Nur hatte ich einen solchen Code nicht. Was war da schief gelaufen?&lt;br /&gt;
Also las ich mir die FAQ-Seite durch und die meinte:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Zuerst “reservieren” Sie einen Termin für den Test in der Straße ihrer Wahl&lt;/li&gt;
  &lt;li&gt;Dann “registrieren” Sie sich einmal kostenlosen.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Zur “Reservierung” gab es einen Link und das hatte ich ja schon erledigt.
Die “Registrierung” war aber mit keiner Seite verknüpft … also wo muss
man da hin?&lt;/p&gt;

&lt;p&gt;Ich machte also eine weitere “Reservierung” und las die Punkte nun genauer 
durch … doch erneut fand ich nur den Hinweis, dass ich einen QR-Code 
mitnehmen soll. Wie der zu bekommen war, war wieder nicht beschrieben.&lt;/p&gt;

&lt;p&gt;Dann startete ich eine dritte “Reservierung” und da fiel mir am Ende etwas
auf:
Normalerweise haben diese Schritt-für-Schritt Seiten links einen “Zurück”
Button und rechts einen mit “Weiter”. 
Bei der Reservierungsseite, verwandelte sich am Ende der “Weiter” Button in
ein “Bearbeiten” und der führte zu einer Seite um seine Daten wieder editieren
zu können.&lt;/p&gt;

&lt;p&gt;Was mir aber nicht aufgefallen war: Dort wo normalerweise “Zurück” steht, 
tauchte nun ein simples “Weiter” auf …. und das ist der Link zu einer 
gänzlich anderen Seite, wo man sich “registrieren” kann, um Adresse und
Sozialversicherungsnummer einzutragen.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Also mal ehrlich!
viel bescheuerter kann man es eigentlich nicht mehr machen!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Entweder bin ich einfach nur dumm … oder es andere Bürger mussten hier 
auch lange herumirren, bis sie zum Ziel gelangten.&lt;br /&gt;
Hoffentlich wird das noch verbessert!&lt;/p&gt;

&lt;h3 id=&quot;ein-test-wie-im-wohnzimmer&quot;&gt;Ein Test wie im Wohnzimmer&lt;/h3&gt;

&lt;p&gt;Um 11:53 stehe ich also vor dem Kurzzentrum, dort war auch schon alle 5 Meter
ein Plakat um einen zur Parkgarage zu geleiten, denn dort unten wurde getestet.&lt;/p&gt;

&lt;p&gt;Es waren zwar schon einige Personen zum Testen vor Ort, aber da es mehrere
Stationen gab kam ich unmittelbar dran, zeigte meinen ausgedruckten QR Code 
her und schon durfte ich mich setzen und ein von Schutzkleidung und Helm 
ummantelter Mann kam mit einem Wattestäbchen auf mich zu.&lt;/p&gt;

&lt;p&gt;Es wurde der &lt;em&gt;exakt gleiche Test&lt;/em&gt; gemacht, den ich mir auch aus der Apotheke
für zu Hause geholt hatte. Auch die Teststreifen und Röhrchen waren identisch
verpackt.&lt;/p&gt;

&lt;p&gt;Der Unterschied ist nur, dass jemand anderer einem in die Nase bohrt.
Kaum waren die Tröpfchen auf dem Streifen, durfte ich es mir auf einem 
isoliert stehenden Sessel bequem machen und 15 Minuten warten.&lt;br /&gt;
Dabei fiel mir auf, dass die ganze Garage von Heizkanonen befeuert wurde
und mir in der Winterjacke wesentlich wärmer wurde, als zu Hause.&lt;/p&gt;

&lt;p&gt;Nach den 15 Minuten darf man seinen Streifen (der auf der Unterseite mit 
einem Barcode-Sticker versehen war) selbst zu einem Abgabeplatz am anderen
Ende der Garage befördern, wo ein Mitarbeiter nochmals den Ausweis sehen 
will und dann das Testergebnis (bei mir natürlich: Negativ) auf Papier 
ausdruckt.&lt;/p&gt;

&lt;p&gt;Nach dem Test ging’s mit der U-Bahn zum Friseur, wo ich auch gleich dran kam
und der Zettel vorgezeigt werden musste.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Also … das ist ja mal was, worüber ich in 5-10 Jahren hoffentlich lachen
kann. Seit 20 Jahren gehe ich immer mal so am Friseur vorbei und lasse mir 
die Haare schneiden, wenn sie mir über die Augen wachsen.&lt;/p&gt;

&lt;p&gt;Doch in diesen Tagen, muss ich zuerst zu einem von 10 Testplätzen oder zu
speziellen Apotheken marschieren, bevor ich mich der Schnibblerei aussetzen
darf.&lt;/p&gt;

&lt;p&gt;Das Schlimme dabei ist … eben wegen unzähliger illegaler Parties und
“Demonstrationen gegen das Virus” breitet sich &lt;a href=&quot;https://de.wikipedia.org/wiki/COVID-19&quot;&gt;COVID-19&lt;/a&gt;
aktuell wieder viel zu sehr aus. Das Herausfiltern von Infizierten ist daher 
ein  notwendiges Übel … however … es klingt einfach zu komisch:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ich brauche eine Freigabe fürs Haare schneiden…&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Tja, so ist das Leben nun mal.&lt;br /&gt;
Oder wie mein Großvater dann scherzhaft sagte:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ernst ist das Leben,&lt;br /&gt;
heiter die Kunst,&lt;br /&gt;
nass ist der Rinnstein,&lt;br /&gt;
wenn man drauf brun…nenwasser gießt.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Man muss eben versuchen, alles mit einer Portion Humor zu nehmen.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Azure VM Swapspace</title>
   <link href="https://www.opengate.at/blog/2021/03/azure-vm/"/>
   <published>2021-03-21T12:00:00+01:00</published>
   <updated>2021-03-21T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2021/03/azure-vm</id>
   <category term="hardware" /><category term="software" />
   <summary type="text">Für ein Jahr MSDN
Abo bekommt man “aus Gottes Gnaden” dann ganze 45 Dollar 
Azure Guthaben.
WOW, echt großzügig für 1000 Euro Schmiergeld!

Und die 45 Dollar reichen gerade um die billigste 1-Kern 
VM
für etwa ein Jahr laufen zu lassen.

Doch leider crashen dort Compiler und andere Tools…
</summary>
   <content type="html">&lt;p&gt;Für ein Jahr &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Developer_Network&quot;&gt;MSDN&lt;/a&gt;
Abo bekommt man “aus Gottes Gnaden” dann ganze 45 Dollar 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Azure&quot;&gt;Azure&lt;/a&gt; Guthaben.
WOW, echt großzügig für 1000 Euro Schmiergeld!&lt;/p&gt;

&lt;p&gt;Und die 45 Dollar reichen gerade um die billigste 1-Kern 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Virtuelle_Maschine&quot;&gt;VM&lt;/a&gt;
für etwa ein Jahr laufen zu lassen.&lt;/p&gt;

&lt;p&gt;Doch leider crashen dort Compiler und andere Tools…
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;ul&gt;
  &lt;li&gt;1 CPU Kern,&lt;/li&gt;
  &lt;li&gt;512 MB RAM&lt;/li&gt;
  &lt;li&gt;30 GB Festplatte&lt;/li&gt;
  &lt;li&gt;Ubuntu &lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt; 18.04&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ein Azure VM mit diesen Eigenschaften ist aktuell das billigste Angebot.
Aber bevor ich ein ganzes Jahr lang einen &lt;a href=&quot;https://de.wikipedia.org/wiki/Raspberry_Pi&quot;&gt;Raspberry PI&lt;/a&gt;
zu Hause am Laufen halten muss, ist dieses Angebot genug, um hin und 
wieder mal einen Build dort laufen zu lassen.&lt;/p&gt;

&lt;p&gt;Gesagt, getan … &lt;a href=&quot;https://portal.azure.com&quot;&gt;portal.azure.com&lt;/a&gt;, einloggen,
Ressourcen anlegen, starten, IP ablesen, Putty starten, 
&lt;code&gt;apt install build-essentials&lt;/code&gt; usw. und am Ende &lt;code&gt;make&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Killed&lt;/code&gt; nach ein paar Minuten.&lt;/p&gt;

&lt;p&gt;Na toll! Wozu hat man eine VM in der &lt;a href=&quot;https://de.wikipedia.org/wiki/Cloud_Computing&quot;&gt;Cloud&lt;/a&gt;, 
wenn der Regen dort auf den Compiler niederprasselt?&lt;/p&gt;

&lt;p&gt;Nun, nachdem kleinere Kompilate durchgehen und ich im GATE Projekt stets
am &lt;a href=&quot;https://de.wikipedia.org/wiki/SQLite&quot;&gt;SQLITE&lt;/a&gt; Projekt hängen bleibe, 
drängt sich der Verdacht auf:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Dem Compiler geht der RAM aus.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Aber dann sollte eigentlich die &lt;a href=&quot;https://de.wikipedia.org/wiki/Auslagerungsdatei&quot;&gt;SWAP Partition&lt;/a&gt;
aushelfen. Ist zwar langsamer, aber immerhin kommt man so über die Runden.&lt;br /&gt;
Doch offenbar sind keine SWAP-Partitionen in Linux Azure VMs vorkonfiguriert.&lt;/p&gt;

&lt;p&gt;Aber nach einer kurzen Suche im Web war die Lösung schnell gefunden:&lt;/p&gt;

&lt;p&gt;Microsoft hat seinen eigenen Azure-Dienst in den Cloud Distributionen
namens &lt;a href=&quot;http://docs.microsoft.com/en-us/azure/virtual-machines/extensions/agent-linux&quot;&gt;“Microsoft Azure Linux Agent” (waagent)&lt;/a&gt;
und dieser wird über &lt;code&gt;/etc/waagent.conf&lt;/code&gt; konfiguriert.&lt;/p&gt;

&lt;p&gt;Wenn man dort folgende Zeilen einträgt (bzw. aktiviert):&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;ResourceDisk.Format=y
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;ResourceDisk.EnableSwap=y
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;ResourceDisk.SwapSizeMB=4096
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;bindet die VM einen Swap-Bereich auf einem temporären Storage ein. Dieser
wird mit dem Beenden der VM ebenfalls freigegeben (bzw. gelöscht), also wird
bei jedem Reboot dieser Bereich neu angelegt und formatiert.&lt;/p&gt;

&lt;p&gt;Im Beispiel werden 4 GB (4096) für Auslagerungsdateien eingesetzt.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Mit diesem kleinen Konfigurationsupdate läuft nun der GATE Build in Azure
durch und bestätigt damit wieder einmal, dass ohne RAM bzw. virtuellen
Speicher nichts mehr läuft.&lt;/p&gt;

&lt;p&gt;Vorbei sind die Zeiten, wo man mit 64 MB RAM nicht wusste, wie man sie voll
kriegen soll.&lt;/p&gt;

&lt;p&gt;Naja … zumindest habe ich etwas über Azure gelernt … nämlich dass es 
für Buildvorgänge unverschämt teuer ist.
Für Builds bleibe ich bei &lt;a href=&quot;https://de.wikipedia.org/wiki/Bitbucket&quot;&gt;BitBucket&lt;/a&gt;.
Aber wenn ich mal schnell eine Linux Konsole brauche, habe ich die 
Azure-VM nun griffbereit (samt SWAP).&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Schneller als das Licht</title>
   <link href="https://www.opengate.at/blog/2021/03/ftl/"/>
   <published>2021-03-20T12:00:00+01:00</published>
   <updated>2021-03-20T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2021/03/ftl</id>
   <category term="general" />
   <summary type="text">Und wieder mal eine Predigt zur beobachteten Lage:

Der von mir hoch geschätzte Professor Harald Lesch
nennt in seinen kritischen Vorträgen zu Wissenschaft und Gesellschaft stets 
das Problem der Lichtgeschwindigkeit in unserem Alltag.

Die Tatsache, dass wir als langsam herumschlendernden Geister uns einbilden,
die Welt mit Hilfe der Technik immer schneller drehen zu müssen, stößt nicht
nur physikalisch an Grenzen …
</summary>
   <content type="html">&lt;p&gt;Und wieder mal eine Predigt zur beobachteten Lage:&lt;/p&gt;

&lt;p&gt;Der von mir hoch geschätzte Professor &lt;a href=&quot;https://de.wikipedia.org/wiki/Harald_Lesch&quot;&gt;Harald Lesch&lt;/a&gt;
nennt in seinen kritischen Vorträgen zu Wissenschaft und Gesellschaft stets 
das Problem der Lichtgeschwindigkeit in unserem Alltag.&lt;/p&gt;

&lt;p&gt;Die Tatsache, dass wir als langsam herumschlendernden Geister uns einbilden,
die Welt mit Hilfe der Technik immer schneller drehen zu müssen, stößt nicht
nur physikalisch an Grenzen …
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Oft genug habe ich mich darüber ausgelassen, dass die Qualität in der Software 
Entwicklung zum Vergessen ist. Anstatt von durchdachten Konzepten, stehen 
billige UI-Blinkereien auf den Wunschlisten der Auftraggeber. Kosten soll das
alles natürlich möglichst wenig und fertig sein soll es am besten gestern.&lt;/p&gt;

&lt;p&gt;Kein Wunder also, dass es inzwischen keine App und kein Portal mehr gibt, 
das nicht jährlich einmal zusammenbricht. Doch das Marketing hat inzwischen
alle davon überzeugt, “dass das eben so ist” und “100% geht einfach nicht”.&lt;/p&gt;

&lt;h3 id=&quot;das-problem-mit-der-schönheit&quot;&gt;Das Problem mit der Schönheit&lt;/h3&gt;

&lt;p&gt;Ein andere geschätzte Größe in der Wissenschaft, 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Sabine_Hossenfelder&quot;&gt;Sabine Hossenfelder&lt;/a&gt; hat 
das Problem in der Physik und Mathematik bildlich für Menschen wie mich 
dargestellt:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Wir suchen nicht nach der Wahrheit, sondern nach dem, was uns gefällt.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;iframe width=&quot;640&quot; height=&quot;360&quot; src=&quot;/blog/redirect.html?https%3A%2F%2Fwww.youtube-nocookie.com%2Fembed%2F99hVAu1k6G8&quot; frameborder=&quot;1&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;

&lt;p&gt;Es mag nicht direkt vergleichbar sein, aber ähnlich oberflächlich verhält 
es sich bei uns in der Software-Entwicklung. Wir behaupten zwar immer 
vorwärts kommen zu wollen, laufen dabei aber einem Trugbild hinterher
und bemerken dabei gar nicht, dass wir immer wieder an teils offensichtlichen
Problemen scheitern.&lt;/p&gt;

&lt;p&gt;Der Aufbau vieler &lt;a href=&quot;https://de.wikipedia.org/wiki/Compiler&quot;&gt;Compiler&lt;/a&gt; und 
Programmiersprachen wurde in der Theorie vor über 60 Jahren durchgedacht. 
Heute kommt jedoch alle 5 Jahre eine neue sich selbst als Universallösung 
bezeichnende Sprache, die mit den gleichen Kinderkrankheiten startet, wie 
ihre Vorgänger. Kaum sind diese gelöst, wird sie durch die nächste Generation
abgelöst, die wieder die gleichen Fehler macht.&lt;/p&gt;

&lt;p&gt;Viele davon vereint das Motto:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Mein Ansatz ist ‘schöner’ als der von anderen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Und sogar einfachste Ideen wie “Dialoge” wiederholten ihre Adoleszenz
von &lt;a href=&quot;https://en.wikipedia.org/wiki/Text-based_user_interface&quot;&gt;TUI&lt;/a&gt; zu 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Grafische_Benutzeroberfl%C3%A4che&quot;&gt;GUI&lt;/a&gt; und 
nun zum Web aufs Neue.&lt;/p&gt;

&lt;h3 id=&quot;entschleunigung-mit-nachdenken&quot;&gt;Entschleunigung mit Nachdenken&lt;/h3&gt;

&lt;p&gt;Warum muss also alles so schnell gehen, dass sich jeder nur noch durch 
Abkopplung (wie z.B. Forks) in seinem Fortschritt ermutigt sieht?&lt;/p&gt;

&lt;p&gt;Wäre es nicht sinnvoller mal ein Jahr nachdenklich über die Gesamtsituation
zu grübeln und um dann die bestehenden Lösungen zu erweitern?&lt;/p&gt;

&lt;p&gt;Die Frage muss ich mir auch kritisch selbst stellen, schließlich komme ich 
ja auch nicht mit den vielen Entwicklungssträngen klar und kann mich nur 
noch durch Eigenlösungen entschlagen.&lt;/p&gt;

&lt;p&gt;Lieber hätte ich aber, dass die Standardisierungs-Gremien und Konzerne
offener und langfristiger planen würden. Gute Lösungen brauchen nun mal
Zeit. Und der &lt;a href=&quot;https://en.wikipedia.org/wiki/C%2B%2B11&quot;&gt;C++11&lt;/a&gt; Standard hat 
mit seiner langen Planungszeit folgendes aufgezeigt:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;em&gt;Positiv:&lt;/em&gt; Man kann ein stabiles Set an Funktionen auswählen und 
bereitstellen, mit dem man länger glücklich ist ohne sich die Zukunft 
verbaut zu haben.&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;Negativ:&lt;/em&gt; Abwarten wollte aber keiner und so wurden tonnenweise Projekte 
mit &lt;a href=&quot;https://www.boost.org/doc/libs/1_54_0/doc/html/thread/thread_management.html#thread.thread_management.thread.interrupt&quot;&gt;boost::thread::interrupt()&lt;/a&gt;
und ähnlichen Grässlichkeiten verseucht, womit wir wieder jahrelang mit 
Bugfixes beschäftigt sind, anstatt echte Innovation umzusetzen.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;überforderung&quot;&gt;Überforderung&lt;/h3&gt;

&lt;p&gt;Und tut der Stress von andauernden Änderungen der Menschheit gut?
Nein, im Gegenteil. Das andauernde Gezerre, man müsse morgen wieder alles 
anders machen, hat inzwischen ausreichend viele Menschen verschreckt, so
dass nun die politisch tugendlosesten Kräfte ihre Renaissance erleben.&lt;/p&gt;

&lt;p&gt;Wieso laufen stetig mehr Menschen den Schreiern nach Revolution und Gewalt
hinterher? Weil diese immer mit der erfundenen hohen Moral von gestern und 
den guten alten Zeiten argumentieren. Sie zeichnen ein Bild einer stillen,
einer ruhigen Welt, einer beruhigenden Welt, die jede Änderung als 
Bedrohung ansieht.&lt;/p&gt;

&lt;p&gt;Und das wünschen sich viele … endlich mal wieder mit “normalen”
Geschwindigkeiten zu leben.&lt;/p&gt;

&lt;p&gt;Das Kratzen an der Lichtgeschwindigkeit mag technisch beachtlich sein,
aber wir einfachen Menschen stoßen schon bei Schall und Rauch an unsere
Grenzen.&lt;/p&gt;

&lt;p&gt;… und … da sollten wir mal darüber nachdenken … sollte ich auch mal
darüber nachdenken … ob nicht viel Unheil dadurch verhindert wird,
wenn man (wie Harald Lesch auch einmal meinte) einfach mal NICHTS tut.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Docker Links in &apos;windowsfilters&apos;</title>
   <link href="https://www.opengate.at/blog/2021/03/docker-links/"/>
   <published>2021-03-14T12:00:00+01:00</published>
   <updated>2021-03-14T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2021/03/docker-links</id>
   <category term="software" />
   <summary type="text">Dank Docker war bei mir 
vor ein paar Wochen eine Reparaturinstalltion notwendig geworden.
Offiziell war ich natürlich selbst daran Schuld, weil man den von Docker
angelegten windowsfilters Ordner auf gar keinen Fall selbst löschen darf!

Grund genug sich das Thema mal etwas genauer anzusehen …
</summary>
   <content type="html">&lt;p&gt;Dank &lt;a href=&quot;https://de.wikipedia.org/wiki/Docker_(Software)&quot;&gt;Docker&lt;/a&gt; war bei mir 
vor ein paar Wochen eine Reparaturinstalltion notwendig geworden.&lt;br /&gt;
Offiziell war ich natürlich selbst daran Schuld, weil man den von Docker
angelegten &lt;code&gt;windowsfilters&lt;/code&gt; Ordner auf gar keinen Fall selbst löschen darf!&lt;/p&gt;

&lt;p&gt;Grund genug sich das Thema mal etwas genauer anzusehen …
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/virtualization/windowscontainers/deploy-containers/deploy-containers-on-server&quot;&gt;Docker für Windows Server&lt;/a&gt;
speichert seine Images standardmäßig im Verzeichnis &lt;code&gt;c:\ProgramData\docker\windowsfilters&lt;/code&gt;.&lt;br /&gt;
Und damit das richtig undurchschaubar wird, werden tausende Links im 
Dateisystem angelegt, damit alle Docker-Container auf “das gleiche”
Basissystem verweisen (verlinken) können.&lt;/p&gt;

&lt;p&gt;Wenn man Docker deinstalliert, bleibt dieser Ordner gerne übrig und
sein Inhalt lässt sich großteils nicht löschen, weil bei den Dateien
sowohl der &lt;code&gt;Administrators&lt;/code&gt; Gruppe wie auch dem &lt;code&gt;LocalSystem&lt;/code&gt; sämtliche
Schreib und Löschrechte fehlen.&lt;/p&gt;

&lt;p&gt;Die offizielle Lösung, die mir ein sehr lieber Kollege empfohlen hat,
lautet &lt;a href=&quot;https://github.com/moby/docker-ci-zap&quot;&gt;docker-ci-zap&lt;/a&gt;.&lt;br /&gt;
Der dokumentierte Aufruf &lt;code&gt;.\docker-ci-zap.exe -folder &quot;C:\ProgramData\docker&quot;&lt;/code&gt;
löscht das ganze Verzeichnis inklusive dem &lt;code&gt;windowsfilters&lt;/code&gt; Ordner
über einige spezielle API Funktionen im Systemkern.&lt;/p&gt;

&lt;p&gt;Doch wenn man per Konfiguration die Speicherung wo anders hin verlagert hat
(z.B.: per Konfiguration in &lt;code&gt;c:\ProgramData\docker\config\daemon.json&lt;/code&gt;) aber 
schon vorher Images geladen hat, dann stürzt (bei mir zumindest) das Tool 
&lt;code&gt;docker-ci-zap&lt;/code&gt; einfach ab und macht gar nichts.&lt;/p&gt;

&lt;h3 id=&quot;auf-keinen-fall-den-ordner-direkt-löschen&quot;&gt;Auf keinen Fall den Ordner direkt löschen!&lt;/h3&gt;

&lt;p&gt;Tja, als Admin löst man das Problem von nicht-löschbaren Ordnern gerne mit 
so etwas wie:&lt;br /&gt;
&lt;code&gt;icacls C:\ProgramData\docker\windowsfilters /grant Administrators:F /Q /C /T&lt;/code&gt;&lt;br /&gt;
Dann erhält die Admin-Gruppe auf alles Schreibrechte und das Löschen kann 
beginnen (manchmal muss man auch noch den Besitz übernehmen).&lt;br /&gt;
&lt;em&gt;Und damit löscht man sich auch gleich die halbe Windows Umgebung weg.&lt;/em&gt; 
Zumindest fehlen aber diverse Benutzerprofile und Registry-Hive-Dateien.&lt;/p&gt;

&lt;p&gt;Denn innerhalb der Images gibt es diverse Dateisystem-Links. Man nennt sie
auch “&lt;a href=&quot;https://de.wikipedia.org/wiki/Symbolische_Verkn%C3%BCpfung&quot;&gt;symbolische Verknüpfungen&lt;/a&gt;”, 
die in &lt;code&gt;NTFS&lt;/code&gt; durch so genannte &lt;a href=&quot;https://en.wikipedia.org/wiki/NTFS_reparse_point&quot;&gt;Reparse-Points&lt;/a&gt;
umgesetzt werden.&lt;/p&gt;

&lt;p&gt;Während innerhalb einer Docker-Session ein Link auf &lt;code&gt;C:\Windows&lt;/code&gt; 
auf einen Ordner innerhalb der &lt;code&gt;windowsfilters&lt;/code&gt; verweist, glaubt aber die
Windows-API von außerhalb, dass die Link-Verfolgung auf dem realen 
&lt;code&gt;C:\Windows&lt;/code&gt; weiterläuft.&lt;/p&gt;

&lt;p&gt;Und so löscht man sich mit einem&lt;br /&gt;
&lt;code&gt;rmdir /s /q c:\ProgramData\docker\windowsfilters&lt;/code&gt; 
wichtige Dateien des Host-Systems weg. Zwar lassen sich geladene &lt;a href=&quot;https://de.wikipedia.org/wiki/Dynamic_Link_Library&quot;&gt;DLLs&lt;/a&gt;
und Programme nicht löschen, aber diverse &lt;code&gt;INF&lt;/code&gt; und &lt;code&gt;MANIFEST&lt;/code&gt; Dateien in 
&lt;code&gt;System32&lt;/code&gt; wandern still und heimlich ins Nirvana. Vor allem sind &lt;code&gt;C:\Users&lt;/code&gt;, 
&lt;code&gt;C:\ProgramData&lt;/code&gt; und &lt;code&gt;C:\Program Files&lt;/code&gt; betroffen.&lt;/p&gt;

&lt;p&gt;Ich weiß nicht, welche Dateien es am Ende genau trifft, aber es reichte aus, 
dass mein System nicht mehr booten konnte. Das war mit der 
Systemwiederherstellung zwar reparierbar, aber Spaß machte mir diese Aktion 
absolut nicht.&lt;br /&gt;
Vor allem weil es meinen Rechner in der Firma betraf.&lt;/p&gt;

&lt;h3 id=&quot;lösungsansatz&quot;&gt;Lösungsansatz&lt;/h3&gt;

&lt;p&gt;Tatsächlich konnte ich dann nicht widerstehen und begann die APIs zu 
studieren und ließ die Ergebnisse sofort ins GATE Projekt einfließen.
&lt;a href=&quot;https://en.wikipedia.org/wiki/NTFS_links&quot;&gt;Junctions&lt;/a&gt;, “SymLinks” und das von 
Docker und &lt;a href=&quot;https://de.wikipedia.org/wiki/Hyper-V&quot;&gt;Hyper-V&lt;/a&gt; benutzte 
&lt;a href=&quot;http://docs.microsoft.com/en-us/virtualization/community/team-blog/2017/20170127-introducing-the-host-compute-service-hcs&quot;&gt;“HCM” (Host Compute Service)&lt;/a&gt;
bauen alle auf Reparse-Points auf und ein jeder dieser Verzeichnis-Einträge 
hat das Attribute &lt;code&gt;FILE_ATTRIBUTE_REPARSE_POINT&lt;/code&gt; gesetzt.&lt;br /&gt;
Und das bekommt man per &lt;a href=&quot;http://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfileattributesw&quot;&gt;GetAttributes()&lt;/a&gt;
oder &lt;a href=&quot;http://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-findfirstfilew&quot;&gt;FindFirstFile()&lt;/a&gt;
mitgeteilt.&lt;/p&gt;

&lt;p&gt;Das Schöne dabei ist, dass klassische Windows APIs wie 
&lt;a href=&quot;http://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-deletefilew&quot;&gt;DeleteFile()&lt;/a&gt;
und &lt;a href=&quot;http://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-removedirectoryw&quot;&gt;RemoveDirectory()&lt;/a&gt;
im Normalfall nur den Reparse-Point löschen und nicht das Ziel, 
wo dieser hinzeigt.&lt;/p&gt;

&lt;p&gt;Bei einer Standard-Löschung gehen die Tools durch alle Unterverzeichnisse
und löschen zuerst deren Inhalt und am Ende erst das Verzeichnis selbst.
Deshalb wird auch das reale &lt;code&gt;C:\&lt;/code&gt; Laufwerk durchlöchert, wenn man nur
&lt;code&gt;windowsfilters&lt;/code&gt; wegputzen will.&lt;/p&gt;

&lt;p&gt;Die Lösung ist also bei jedem &lt;code&gt;windowsfilters&lt;/code&gt; Unterverzeichnis zu prüfen, 
ob dieses ein Reparse-Point ist. Wenn ja, dann sollte &lt;code&gt;RemoveDirectory()&lt;/code&gt; 
funktionieren, obwohl der Inhalt gar nicht leer ist. 
Und bei allen Nicht-Reparse-Points geht man wie üblich vor.&lt;/p&gt;

&lt;p&gt;Auf diese Weise wird nur “innerhalb” des Docker-Images gelöscht.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Aber Achtung! Diese Angabe ist ohne Gewähr. Auch durch dieses Verfahren
kann das laufenden System beschädigt oder zumindest beeinträchtigt werden.
&lt;strong&gt;Anwendung auf eigene Gefahr!&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Bei einem Test der Link-Lösch-Prozedur wurde mein privater Docker-Server 
scheinbar nicht beschädigt und ich konnte 11 GB auf &lt;code&gt;C:\&lt;/code&gt; freigeben, weil 
die Images ohnehin auf &lt;code&gt;D:\&lt;/code&gt; nochmals heruntergeladen wurden.
Ein &lt;code&gt;Packages&lt;/code&gt; Verzeichnis ließ sich trotzdem nicht Löschen, aber das 
ignoriere ich vorläufig mal.&lt;/p&gt;

&lt;p&gt;Ich habe also wieder etwas gelernt und dem GATE Framework Reparse-Points
beigebracht.&lt;br /&gt;
Interessant dabei ist, dass Windows zwischen Datei und Verzeichnis-Links
per API unterscheidet, während POSIX SymLinks immer wie Dateien mit 
&lt;a href=&quot;http://pubs.opengroup.org/onlinepubs/009604599/functions/unlink.html&quot;&gt;unlink()&lt;/a&gt;
löscht und &lt;a href=&quot;https://pubs.opengroup.org/onlinepubs/009604599/functions/rmdir.html&quot;&gt;rmdir()&lt;/a&gt;
ausschließlich bei realen leeren Verzeichnissen funktioniert.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Angefressen bin ich trotzdem!&lt;/em&gt;&lt;br /&gt;
Von Docker hätte ich erwartet, dass es seine eigenen “Reinigungskräfte” 
mitbringt. Wie die Netzsuche zeigte, haben sich auch schon andere Leute wegen
Docker einen PC oder einen Server zerschossen. Und eine gute Software sollte
solche “Missverständnisse” im Dateisystem erst gar nicht möglich machen.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Ein Schlafmittel namens dotNet</title>
   <link href="https://www.opengate.at/blog/2021/03/dotnet/"/>
   <published>2021-03-13T12:00:00+01:00</published>
   <updated>2021-03-13T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2021/03/dotnet</id>
   <category term="software" />
   <summary type="text">Meine “Beziehung” zum dotNet Framework
ist eine sehr sehr schwierige.
Die Kernaufbau ist mir so verhasst, dass ich stets versuche an dotNet Sprachen
nicht anzustreifen.

Gleichzeitig halte ich den Klassenaufbau des Frameworks selbst für ausgezeichnet
durchdacht und vorbildhaft. Nicht grundlos habe ich viele Klassen- und 
Methodenkonventionen in die C++ 
Schicht des GATE Frameworks aufgenommen.
</summary>
   <content type="html">&lt;p&gt;Meine “Beziehung” zum &lt;a href=&quot;https://de.wikipedia.org/wiki/.NET_Framework&quot;&gt;dotNet Framework&lt;/a&gt;
ist eine sehr sehr schwierige.
Die Kernaufbau ist mir so verhasst, dass ich stets versuche an dotNet Sprachen
nicht anzustreifen.&lt;/p&gt;

&lt;p&gt;Gleichzeitig halte ich den Klassenaufbau des Frameworks selbst für ausgezeichnet
durchdacht und vorbildhaft. Nicht grundlos habe ich viele Klassen- und 
Methodenkonventionen in die &lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B&quot;&gt;C++&lt;/a&gt; 
Schicht des GATE Frameworks aufgenommen.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Neulich saß ich wieder vor einem meiner virtuellen 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_Server_2016&quot;&gt;Windows Server&lt;/a&gt;, die auf 
meinen stromsparenden &lt;a href=&quot;https://de.wikipedia.org/wiki/Intel_Atom&quot;&gt;Atom&lt;/a&gt; 
Rechnern liefen.&lt;br /&gt;
Dann kam das monatliche dotNet Update und nach einer Stunde mühsamen 
Updates (zusammen mit anderen nativen Windows Updates), lief dann über 
2 Stunden die dotNet Runtime Optimierung und fraß die Systemressourcen
derart auf, dass das System unbenutzbar wurde.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/taskmgr-dotnet-update.png&quot; alt=&quot;TaskMgr dotNet Update&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Neben der CPU Auslastung waren vor allem die Festplattenzugriffe ein stark
bremsenden Faktor.&lt;/p&gt;

&lt;h3 id=&quot;die-performance-illusion&quot;&gt;Die Performance-Illusion&lt;/h3&gt;

&lt;p&gt;Die Idee eines &lt;a href=&quot;https://de.wikipedia.org/wiki/Just-in-time-Kompilierung&quot;&gt;Just-In-Time Compilers&lt;/a&gt;, 
(JIT) der erst zur Laufzeit Pseudocode in CPU-Code übersetzt, hat schon 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Java-Technologie&quot;&gt;Java&lt;/a&gt; nie performant umsetzen 
können. Ich habe daher nie verstanden, wie man die Fehlentscheidung treffen 
konnte, die bestehende &lt;a href=&quot;https://de.wikipedia.org/wiki/Component_Object_Model&quot;&gt;COM&lt;/a&gt;
Struktur in Windows durch langsame JIT-dotNet Komponenten zu ersetzen.&lt;/p&gt;

&lt;p&gt;Das hat man uns seit 2000 immer wieder als “beste Lösung” verkauft und erst
seit ein paar Jahren rudert man mit dotNet Native und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_Runtime&quot;&gt;WinRT&lt;/a&gt; kräftig zurück.&lt;/p&gt;

&lt;p&gt;Es stimmt zwar, dass manche Operationen mit modernen CPU-Instruktionen
wesentlich schneller laufen. Ein C oder C++ Programm aus dem Jahr 2003 
hätte &lt;a href=&quot;http://www.cplusplus.com/reference/cstring/memcpy/&quot;&gt;&lt;code&gt;memcpy&lt;/code&gt;&lt;/a&gt; in 
einen Byte-zu-Byte Transfer übersetzt. Bereits 5 Jahre später war es aber
üblich, dass &lt;code&gt;memcpy&lt;/code&gt; auf das Alignment der Daten prüft und dann 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Streaming_SIMD_Extensions&quot;&gt;SSE&lt;/a&gt; oder neuere 
Vektor-Instruktionen einsetzt. Das geht tatsächlich dann 2 bis 4 mal schneller.&lt;/p&gt;

&lt;p&gt;Man könnte also argumentieren, dass ein dotNet Programm von 2003 im Jahr 2008
ohne Zutun ob der neuen Instruktionen schneller ausgeführt wird, während das 
C/C++ Kompilat keinen Performancegewinn ermöglicht.&lt;br /&gt;
Ja, das ist auch so. Man kann das teils schon bei der &lt;a href=&quot;https://de.wikipedia.org/wiki/Zlib&quot;&gt;ZLIB&lt;/a&gt;
gut nachweisen.
(Habe das mal bei &lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_C%2B%2B&quot;&gt;MSVC&lt;/a&gt; 2012 
vs MSVC 2005 nachgemessen.)&lt;/p&gt;

&lt;p&gt;Aber mal ehrlich! Zeitkritische Software wird stets weiterentwickelt und 
spätestens alle paar Jahre neu ausgerollt. Im Normalfall benutzt also niemand
X-Jahre veraltete Software und hofft darauf, dass die Runtime-Umgebung diese 
“schneller” macht.&lt;br /&gt;
Und zum Zeitpunkt der Veröffentlichung sind die nativen Routinen dank ihrer
hohen Optimierung stets schneller (oder im schlechtesten Fall gleich schnell)
wie “verwaltete” Programme.&lt;/p&gt;

&lt;h3 id=&quot;versionschaos&quot;&gt;Versionschaos&lt;/h3&gt;

&lt;p&gt;“Ein Framework” gab es seit v2.0 in dotNet leider nicht mehr. Mit jeder neuen 
Version kamen Features hinzu und weil die Entwicklungsumgebungen von Microsoft
immer auf die neueste Inkarnation verweisen (und die Entwickler offenbar 
nichts hinterfragen), braucht fast jede Software ihr eigenes dotNet Paket.&lt;/p&gt;

&lt;p&gt;Ganz besonders schlimm ist die Integration ins Betriebssystem. Ein dotNet
3.5 ist ein optionaler Teil von &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_7&quot;&gt;Windows 7&lt;/a&gt;
und kann nur per Windows Setup installiert werden. Ältere und neuere Versionen 
müssen jedoch per &lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_Installer&quot;&gt;MSI&lt;/a&gt; Setup
installiert werden, aber das macht die Administration und das Deployment
schwierig.&lt;br /&gt;
Und &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_8&quot;&gt;Windows 8&lt;/a&gt; bis 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_10&quot;&gt;Windows 10&lt;/a&gt; stellen 
wieder weitere 4.X Profile zur Verfügung, die auf älteren Systemen separat 
und eben “anders” nachinstalliert werden müssen.&lt;br /&gt;
Dafür, dass dotNet letztlich nur ein “Wrapper” rund um das Betriebssystem ist,
und kein eigenes Subsystem, sind diese Inkompatibilitäten und 
Installationshürden nicht gerade nachvollziehbar.&lt;/p&gt;

&lt;p&gt;Und eben weil sich niemand mehr auskennt, welches Feature in welcher Version
mit welchem anderen funktioniert, entsteht der “Druck” zur neuesten Version 
und einem ständigen Update mit immer wieder neuen Bugs.&lt;br /&gt;
DotNet Patches haben inzwischen die Größe der “üblichen” OS Patches erreicht 
bzw. diese überschritten.&lt;br /&gt;
Und dass nach jedem Update sich das ganze System selbst neu durchkompiliert,
produziert unnötig Rechenlast, die die Last der eigentlichen Apps übersteigt.
Letztendlich erzeugen Millionen von Maschinen wegen dotNet jeden Tag den 
gleichen Code.&lt;br /&gt;
… den Strom könnte man sich durchaus sparen!&lt;/p&gt;

&lt;h3 id=&quot;falschangaben-beim-marketing&quot;&gt;Falschangaben beim Marketing&lt;/h3&gt;

&lt;p&gt;Anfangs hieß es:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;C# und VB.NET sind rein statische Sprachen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Und dann kam die &lt;code&gt;Dynamic Language Runtime&lt;/code&gt; und das Statement, dass man nun 
die dynamische Typisierung, die es “intern immer schon gab”, auch in 
allen Sprachen verfügbar gemacht hätte.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;C# und VB.NET sind nach JIT Kompilierung “fast” gleich schnell wie C 
oder C++ Programme.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Das heißt dann quasi übersetzt: “Man kann es gar nicht schneller machen.”&lt;br /&gt;
… zumindest bis mit der nachfolgenden Initiative behauptet wurde:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;dotNet Native ist um bis zu 60% schneller als die Implementierung des
klassischen Frameworks.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ein neuer &lt;a href=&quot;https://de.wikipedia.org/wiki/Ahead-of-time-Compiler&quot;&gt;Ahead-of-Time-Compiler&lt;/a&gt;
erlaubt nun das Kompilieren ähnlich wie C oder C++ und deshalb ist dotNet
jetzt fast oder genau so schnell.&lt;/p&gt;

&lt;p&gt;Hmm … na, ich warte dann mal auf den nächsten Future-Prediction 
dotNet-Compiler, der wieder 50% schneller sein wird und damit 
WIEDER EINMAL gleichwertig mit C und C++ sein wird.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Beim dotNet Marketing wird so viel Bullshit geplappert, dass es weh tut.&lt;br /&gt;
Die Beispiele, die die hohe Performance zeigen sollen, sind immer genau 
auf die neueste Optimierung abgestimmt, stellen aber selten die 
allgemeine Praxis nach. Das passiert leider auch bei quasi allen 
Garbage-Collector-Vorführungen.&lt;/p&gt;

&lt;p&gt;Wer Programme (egal mit welcher Technologie) testen will, sollte fertige
Applikationen auf Systemen mit geringen CPU und RAM Kapazitäten laufen 
lassen.&lt;br /&gt;
Denn dort zeigt sich unmittelbar, dass kein Garbage-Collector “intelligent”
genug arbeitet und kein “verwaltetes” Framework performant arbeitet.
Und das wird noch deutlicher, wenn große Datenbanksysteme zeitkritisch 
arbeiten sollen.&lt;/p&gt;

&lt;p&gt;Aber eines muss ich leider eingestehen:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Schuld sind wir! Wir C und C++ Programmierer.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Denn obwohl native Sprachen die Chance bieten würden, wirklich effizient zu
arbeiten, sind eine Vielzahl der Entwickler, die mit diesen Sprachen arbeiten,
nicht fähig ordentliche Programme damit zu entwerfen.&lt;br /&gt;
Die Anzahl von &lt;a href=&quot;https://de.wikipedia.org/wiki/Speicherleck&quot;&gt;Memory-Leaks&lt;/a&gt;, 
Logikfehlern und falsch verstandenem Multithreading ist unerhört groß. 
In allen Firmen, in denen ich bisher gearbeitet habe, zeigte sich das 
Problem, dass niemand ausreichend auf Codequalität achtet, am wenigsten 
leider das Management.&lt;/p&gt;

&lt;p&gt;Und eben deshalb sucht “die Industrie” krampfhaft nach jemandem, der 
zumindest behauptet “Out-of-the-box” alles perfekt machen zu können.&lt;/p&gt;

&lt;p&gt;dotNet, Java und jede Menge &lt;a href=&quot;https://de.wikipedia.org/wiki/Python_(Programmiersprache)&quot;&gt;Python&lt;/a&gt;
Scripts versuchen diese Lücken mit ebenso schlechten Implementierungen 
zu füllen und sind der Grund, warum wir in der IT seit langem keinen 
wirklichen Fortschritt mehr produzieren, sondern nur Wiederholungen 
der immer wieder gleichen Bugs und Workarounds.&lt;/p&gt;

&lt;p&gt;… und dabei fing alles gut an, mit einem durchdachten Klassengerüst und 
einer formal konsistenten Infrastruktur.&lt;br /&gt;
Schade, dass unter dieser schönen Hülle und fauliger Kern steckt.&lt;/p&gt;

&lt;p&gt;Wie auch immer … ich versuche nach bestem Wissen und Gewissen 
aus diesen Fehlern zu lernen.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Linux unter Windows Server</title>
   <link href="https://www.opengate.at/blog/2021/03/wsl-server/"/>
   <published>2021-03-07T12:00:00+01:00</published>
   <updated>2021-03-07T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2021/03/wsl-server</id>
   <category term="software" />
   <summary type="text">Unter Windows 10 öffnet 
man die Windows-Store App, 
sucht nach Linux und wählt aus, was man haben möchte.

Doch unter Windows Server
gibt es keine Store-App.

Wie installiert man also dort das 
Windows Subsystem for Linux 
(WSL) und eine Distribution ?
</summary>
   <content type="html">&lt;p&gt;Unter &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_10&quot;&gt;Windows 10&lt;/a&gt; öffnet 
man die &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Store&quot;&gt;Windows-Store&lt;/a&gt; App, 
sucht nach Linux und wählt aus, was man haben möchte.&lt;/p&gt;

&lt;p&gt;Doch unter &lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_Server_2019&quot;&gt;Windows Server&lt;/a&gt;
gibt es keine Store-App.&lt;/p&gt;

&lt;p&gt;Wie installiert man also dort das 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Windows-Subsystem_f%C3%BCr_Linux&quot;&gt;Windows Subsystem for Linux&lt;/a&gt; 
(WSL) und eine &lt;a href=&quot;https://de.wikipedia.org/wiki/Linux-Distribution&quot;&gt;Distribution&lt;/a&gt; ?
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Nachdem das Subsystem für Linux erst um 2017 in Windows Einzug hielt, steht es 
im originalen &lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_Server_2016&quot;&gt;Windows Server 2016&lt;/a&gt;
nicht zur Verfügung.
Microsoft hat parallel zu Windows 10 auch aktualisierte Server Varianten 
basierend auf Server 2016 erstellt (z.B. Windows Server, version 1709) wo
das WSL integriert war, aber ganz offiziell steht das neue Feature erst
in Server 2019 zur Verfügung.&lt;/p&gt;

&lt;h3 id=&quot;wsl-installieren&quot;&gt;WSL installieren&lt;/h3&gt;

&lt;p&gt;Allgemein startet man einfach die &lt;a href=&quot;https://de.wikipedia.org/wiki/PowerShell&quot;&gt;PowerShell&lt;/a&gt;
als Administrator und führt&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;Enable-WindowsOptionalFeature -Online `
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;  -FeatureName Microsoft-Windows-Subsystem-Linux
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;aus, aber man findet dieses Feature auch im &lt;code&gt;Server Manager&lt;/code&gt; im 
&lt;code&gt;Add Roles and Features Wizard&lt;/code&gt; unter dem Namens &lt;code&gt;Windows Subsystem for Linux&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/wsl-svr2019.png&quot; alt=&quot;WSL Server 2019&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Nach einem Neustart ist der WSL Kern einsatzbereit, nun brauchen wir
noch eine Linux Distribution.&lt;/p&gt;

&lt;h3 id=&quot;linux-distribution-installieren&quot;&gt;Linux Distribution installieren&lt;/h3&gt;

&lt;p&gt;An dieser Stelle fehlt uns die Store-App am Server, die das
&lt;a href=&quot;https://en.wikipedia.org/wiki/Universal_Windows_Platform_apps&quot;&gt;APPX Paket&lt;/a&gt;
herunterlädt und am System installiert.&lt;br /&gt;
Am Server müssen wir diese Schritte manuell nachbauen:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Wir brauchen den Download Link einer Linux Distribution:
    &lt;ul&gt;
      &lt;li&gt;Ubuntu 20.04 X64: &lt;a href=&quot;https://aka.ms/wslubuntu2004&quot;&gt;https://aka.ms/wslubuntu2004&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;Ubuntu 20.04 ARM: &lt;a href=&quot;https://aka.ms/wslubuntu2004arm&quot;&gt;https://aka.ms/wslubuntu2004arm&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;Ubuntu 18.04 X64: &lt;a href=&quot;https://aka.ms/wsl-ubuntu-1804&quot;&gt;https://aka.ms/wsl-ubuntu-1804&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;Ubuntu 18.04 ARM: &lt;a href=&quot;https://aka.ms/wsl-ubuntu-1804-arm&quot;&gt;https://aka.ms/wsl-ubuntu-1804-arm&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;Ubuntu 16.04 X64: &lt;a href=&quot;https://aka.ms/wsl-ubuntu-1604&quot;&gt;https://aka.ms/wsl-ubuntu-1604&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;Debian: &lt;a href=&quot;https://aka.ms/wsl-debian-gnulinux&quot;&gt;https://aka.ms/wsl-debian-gnulinux&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;KaliLinux: &lt;a href=&quot;https://aka.ms/wsl-kali-linux-new&quot;&gt;https://aka.ms/wsl-kali-linux-new&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;OpenSUSE Leap 42: &lt;a href=&quot;https://aka.ms/wsl-opensuse-42&quot;&gt;https://aka.ms/wsl-opensuse-42&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;SuSE Enterprise 12: &lt;a href=&quot;https://aka.ms/wsl-sles-12&quot;&gt;https://aka.ms/wsl-sles-12&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;Fedora: &lt;a href=&quot;https://github.com/WhitewaterFoundry/WSLFedoraRemix/releases/&quot;&gt;https://github.com/WhitewaterFoundry/WSLFedoraRemix/releases/&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Wir laden die Datei lokal herunter:
    &lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;Invoke-WebRequest -Uri https://aka.ms/wslubuntu2004 -OutFile `
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;   Ubuntu-20.04.appx -UseBasicParsing
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;Die heruntergeladene APPX Datei ist (Überraschung!) eine 
&lt;a href=&quot;https://de.wikipedia.org/wiki/ZIP-Dateiformat&quot;&gt;ZIP&lt;/a&gt; Datei.&lt;br /&gt;
Wir müssen sie umbenennen und extrahieren:
    &lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;Rename-Item .\Ubuntu-20.04.appx .\Ubuntu-20.04.zip
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;Expand-Archive .\Ubuntu-20.04.zip .\Ubuntu-20.04
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;Jetzt starten wir das Setup Programm im extrahierten Verzeichnis:
    &lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;cd .\Ubuntu-20.04\
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;.\ubuntu2004.exe
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Während unter Windows 10 alle Store-Apps unter &lt;code&gt;C:\Users\%USERNAME%\AppData\Local\Packages&lt;/code&gt;
installiert werden, sind wir am Server frei in der Wahl des Zielverzeichnisses.&lt;br /&gt;
Will man (so wie bei den Store-Apps üblich) die Linux-Sitzung für nur einen 
Benutzer konfigurieren, dann macht es Sinn, die Installation in einem 
Unterverzeichnis von &lt;code&gt;C:\Users\%USERNAME%\AppData\Local&lt;/code&gt; durchzuführen.&lt;/p&gt;

&lt;h3 id=&quot;wsl-distribution-nutzen&quot;&gt;WSL Distribution nutzen&lt;/h3&gt;

&lt;p&gt;Jede Distribution liefert ein anderes Executable aus. Es liegt in der Regel
immer direkt im Installationsverzeichnis. Bei Ubuntu 20.04 heißt sie 
&lt;code&gt;ubuntu2004.exe&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Beim ersten Start von &lt;code&gt;ubuntu2004.exe&lt;/code&gt; wird die Umgebung eingerichtet und 
ein User-Account angelegt, für den wir Namen und Passwort eingeben müssen.
Aber so bald das durchgelaufen ist, startet die WSL Shell (meist &lt;code&gt;/bin/bash&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Jeder weitere Start des Programs öffnet ein weiteres Linux Shell-Fenster.&lt;br /&gt;
Man braucht sich also nur mehr einen Link darauf einrichten und diesen ins
Startmenü aufnehmen … dann sieht es genau so aus, als hätte man den
App-Store benützt.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;WSL am Windows Server stellen sicher kein besonders performantes System dar,
aber für die Softwareentwicklung eignet sich ein solches System durchaus,
wenn man Windows und Linux parallel entwickelt und ohne Virtualisierung 
Binärpakete bauen möchte.&lt;br /&gt;
Dann braucht man nämlich nur genau einen Windows Server, der die Build-Jobs
übernimmt. Natürlich sind dafür aber einige Konfigurationsschritte 
erforderlich, vor allem der automatische Start die Linux-Umgebung beim
Systemstart.&lt;/p&gt;

&lt;p&gt;Wie auch immer, mir gefällt diese Option. Vor allem das Benutzer-unabhängige 
zentrale Installieren der WSL Distribution war mir früher nicht bekannt und 
somit musste ich immer mühsam im User-Packager Unterverzeichnis nach dem 
dortigen &lt;code&gt;rootfs&lt;/code&gt; Folder suchen.&lt;br /&gt;
Die manuelle Installation macht mir die Datenverwaltung wesentlich einfacher.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>WandaVision</title>
   <link href="https://www.opengate.at/blog/2021/03/wandavision/"/>
   <published>2021-03-06T12:00:00+01:00</published>
   <updated>2021-03-06T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2021/03/wandavision</id>
   <category term="entertainment" />
   <summary type="text">O-M-G! Ich liebe Marvel’s WandaVision!
Und Elizabeth Olsen als Wanda.
Und Paul Bettany als Vision.
Und Julian Hilliard als Billy.
und Jett Klyne als Tommy.
</summary>
   <content type="html">&lt;p&gt;O-M-G! &lt;strong&gt;Ich liebe Marvel’s &lt;a href=&quot;https://de.wikipedia.org/wiki/WandaVision&quot;&gt;WandaVision&lt;/a&gt;!&lt;/strong&gt;&lt;br /&gt;
Und &lt;a href=&quot;https://en.wikipedia.org/wiki/Elizabeth_Olsen&quot;&gt;Elizabeth Olsen&lt;/a&gt; als Wanda.&lt;br /&gt;
Und &lt;a href=&quot;https://en.wikipedia.org/wiki/Paul_Bettany&quot;&gt;Paul Bettany&lt;/a&gt; als Vision.&lt;br /&gt;
Und &lt;a href=&quot;https://de.wikipedia.org/wiki/Julian_Hilliard&quot;&gt;Julian Hilliard&lt;/a&gt; als Billy.&lt;br /&gt;
und &lt;a href=&quot;https://www.imdb.com/name/nm4810527/bio&quot;&gt;Jett Klyne&lt;/a&gt; als Tommy.&lt;br /&gt;
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Marvels Mini-Serie rund um Wanda Maximoff und “ihre Welt” ist nun zu Ende 
gegangen und ich stelle fest, dass mich diese Serie weit mehr begeistern
konnte, als ich ursprünglich gedachte hatte.&lt;/p&gt;

&lt;p&gt;Als die erste Episode als “Schwarz-weiß” Serie im Sinne von 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Bezaubernde_Jeannie&quot;&gt;Bezaubernde Jeannie&lt;/a&gt; 
angekündigt wurde, wusste niemand, was Marvel sich dabei gedacht hatte.&lt;/p&gt;

&lt;p&gt;Zwei Stars aus den Avengers Filmen spielen nun in einer nachgestellten
Fernsehserie aus den 60er Jahren? W-T-F?&lt;/p&gt;

&lt;p&gt;Doch schnell wurde klar, dass es sich dabei um kein weiteres 
“Zeitreise-Spiel” und auch kein “alternatives Universum” handelte, sondern
dass nach den Ereignissen von &lt;a href=&quot;https://de.wikipedia.org/wiki/Avengers:_Endgame&quot;&gt;Avengers Endgame&lt;/a&gt;, 
sich die magische Heldin “Wanda”, die ihren geliebten “Vision” verloren 
hatte, mit sich selbst befassen muss.&lt;/p&gt;

&lt;p&gt;Schon am Ende der ersten Episode war zu erkennen, dass sie sich eine 
eigene Welt geschaffen hatte, in der alles fast so perfekt war, wie
es uns die Familien-Fernsehserien aus jenen Tagen zeigen sollten.&lt;/p&gt;

&lt;h3 id=&quot;das-leben-in-einer-sitcom&quot;&gt;Das Leben in einer SitCom&lt;/h3&gt;

&lt;p&gt;Eines muss ich zugeben: Der Ansatz der Serie stimmte mich nachdenklich.
Auch ich habe als Scheidungskind meine Jugend mit neugierigen Augen vor
dem Fernseher verbracht und dort penibel die Darstellung der vermeintlich
perfekten amerikanischen Familie verfolgt, die zwar in jeder Episode 
“ein Problem” zu lösen hatten, in Wahrheit aber so sorgenfrei wie kaum 
jemand unterwegs waren … und am Ende hatte sich immer alle lieb.&lt;br /&gt;
… was für eine Fiktion!&lt;/p&gt;

&lt;p&gt;Ich glaube, “Bezaubernde_Jeannie” war so ziemlich das einzige, was ich noch
aus der frühen Fernsehzeit selbst mitbekommen hatte. Der &lt;a href=&quot;https://de.wikipedia.org/wiki/%C3%96sterreichischer_Rundfunk&quot;&gt;ORF&lt;/a&gt;
(stets 20 Jahre hinter allen anderen) strahlte noch bis Ende der 90er 
altertümliche Serien aus. So auch &lt;a href=&quot;https://de.wikipedia.org/wiki/Raumschiff_Enterprise&quot;&gt;StarTrek TOS&lt;/a&gt;, 
während die deutschen Privatsender längst die damals aktuellen Serien 
vorführten.&lt;/p&gt;

&lt;p&gt;Aber die Ähnlichkeit zu anderen mir bekannten Serien wie 
&lt;a href=&quot;https://de.wikipedia.org/wiki/H%C3%B6r_mal,_wer_da_h%C3%A4mmert&quot;&gt;Hör mal, wer da hämmert&lt;/a&gt; 
oder &lt;a href=&quot;https://de.wikipedia.org/wiki/Malcolm_mittendrin&quot;&gt;Malcolm mittendrin&lt;/a&gt;
waren auch mit den WandaVision Referenzen abgleichbar.&lt;/p&gt;

&lt;p&gt;Interessant, dass ich 20 Jahre später durch eine Marvel Produktion nebenbei
drauf komme, wie sehr mich diese Serien damals geprägt … bzw. von der 
Realität abgelenkt haben.&lt;/p&gt;

&lt;h3 id=&quot;die-beste-sitcom-aller-zeiten&quot;&gt;Die beste SitCom aller Zeiten&lt;/h3&gt;

&lt;iframe width=&quot;640&quot; height=&quot;360&quot; src=&quot;/blog/redirect.html?https%3A%2F%2Fwww.youtube-nocookie.com%2Fembed%2FIPojTmFgglw&quot; frameborder=&quot;1&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;

&lt;p&gt;WandaVision spielt so detailverliebt alte SitComs nach, dass man fast
Gänsehaut bekommt, wenn man die Referenzen nachvollziehen kann.&lt;br /&gt;
Und trotzdem sind das nur Stationen in einem “fast typischen” Superhelden
Film.&lt;br /&gt;
Denn eigentlich ist die Serie mit 9 Episoden zu je 45 Minuten ein 
2 teiliger Wanda-Film. Und im zweiten Teil erhalten wir auch ein angemessenes
Maß an Spezialeffekten und Superhelden-Kunststücke.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Achtung Spoiler!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Am großartigsten fand ich ja die beiden Jungs von Wanda und Vison, die als
10 jährige Kleinstadtkinder ihren Alltag mit Spielen verbrachten, aber dann
“ihre Kräfte” entdecken durften und am Ende “wie die großen” mitkämpften.&lt;/p&gt;

&lt;p&gt;Ein besonderer Hingucker sind die Intros, die in jeder Episode das Intro 
einer entsprechenden SitCom nachstellen sollten.&lt;br /&gt;
Doch eingeleitet wurde das stets durch Marvel’s Movie-Intro, welches in der 
Form zuletzt bei &lt;a href=&quot;https://de.wikipedia.org/wiki/Ant-Man_and_the_Wasp&quot;&gt;Ant-Man and the Wasp&lt;/a&gt;
zu sehen und zu hören war, nur dass nun zwischen den Marvel-Buchstaben die 
Szenen aus Avengers Endgame aufblitzten.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;Einfach nur genial!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Das Spiel rund um &lt;a href=&quot;https://de.wikipedia.org/wiki/Sitcom&quot;&gt;SitComs&lt;/a&gt; in den 
ersten Episoden und die “Heldenentwicklung” hin zum Staffelfinale hat mir 
weit mehr Abwechslung geboten, als ich es je erwartet hätte.&lt;/p&gt;

&lt;p&gt;Vielleicht ist der größte Vorteil auch der größte Nachteil der Serie, denn:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Man muss sie gesehen haben.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ich vermute, dass künftige Marvel Produktionen wie alle 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Marvel_Cinematic_Universe&quot;&gt;MCU&lt;/a&gt; Titel stark
auf den Ausgang der Serie verweisen werden.&lt;br /&gt;
Man wird daher eventuell den kommenden &lt;a href=&quot;https://de.wikipedia.org/wiki/Doctor_Strange_(2016)&quot;&gt;Dr Strange&lt;/a&gt;
Film nicht gänzlich verstehen können, wenn man WandaVision übersprungen hat.&lt;/p&gt;

&lt;p&gt;… aber … wie könnte man als Fan der Reihe denn so etwas auslassen?&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>COVID-19 Test für zu Hause</title>
   <link href="https://www.opengate.at/blog/2021/03/covid19-hometest/"/>
   <published>2021-03-01T12:00:00+01:00</published>
   <updated>2021-03-01T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2021/03/covid19-hometest</id>
   <category term="general" />
   <summary type="text">Samstag Abend und Sonntag Vormittag hatte ich wieder mal einen unangenehmen
Höhepunkt in Sachen Kopfschmerzen.
Natürlich dachte ich da:


  Ah, jetzt hat mich Corona also doch erwischt.


Doch zum Glück wurde ja am Freitag angekündigt, dass am folgenden Montag
in allen Apotheken COVID-19 
Selbst-Test-Kits kostenlos aufliegen werden.
</summary>
   <content type="html">&lt;p&gt;Samstag Abend und Sonntag Vormittag hatte ich wieder mal einen unangenehmen
Höhepunkt in Sachen Kopfschmerzen.&lt;br /&gt;
Natürlich dachte ich da:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ah, jetzt hat mich Corona also doch erwischt.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Doch zum Glück wurde ja am Freitag angekündigt, dass am folgenden Montag
in allen Apotheken &lt;a href=&quot;https://de.wikipedia.org/wiki/COVID-19&quot;&gt;COVID-19&lt;/a&gt; 
Selbst-Test-Kits kostenlos aufliegen werden.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Ich stehe also heute Vormittag vor der Apotheke und lese am an die Scheibe
geklebten A4-Blatt:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;COVID-19 Tests heute erst ab 14:00 Uhr verfügbar.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Also wieder ab nach Hause …&lt;/p&gt;

&lt;p&gt;Zweiter Versuch, 14:00 Uhr. Den Test wollen offenbar auch viele andere
Menschen machen, also ordnete ich mich in eine Schlange ein. 
Es waren so etwa 10 Menschen vor dem Eingang weil in der Apotheke nicht mehr als 4 Personen
gleichzeitig erlaubt waren.&lt;/p&gt;

&lt;p&gt;Doch die Abwicklung ging recht zügig und mit meiner 
&lt;a href=&quot;https://de.wikipedia.org/wiki/E-card_(Chipkarte)&quot;&gt;E-Card&lt;/a&gt;
erhielt ich dann 10 Minuten später in einem A4-Kuvert 5 Corona Heimtests.&lt;/p&gt;

&lt;p&gt;Zuhause angekommen beäugte ich den Inhalt:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;“Verlängerte” Wattestäbchen für den Abstrich&lt;/li&gt;
  &lt;li&gt;Ein Röhrchen mit speziellem Verschluss&lt;/li&gt;
  &lt;li&gt;Behälter mit ein wenig Flüssigkeit&lt;/li&gt;
  &lt;li&gt;und ein versiegeltes Päckchen mit dem Teststreifen&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/covid19-hometest-02.jpg&quot; alt=&quot;COVID-19-Hometest&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Für den Test musste ich mir mit dem Stäbchen einmal quer durch die Nase 
fahren, bis man im Gaumen hinten ansteht. Das ist verdammt unangenehm und 
man hat immer wieder einen Hies- oder Hustenreiz.&lt;/p&gt;

&lt;p&gt;Nun soll man mit Drehbewegungen das Stäbchen wieder langsam aus der Nase
herausziehen, damit sich daran Flüssigkeit bzw. Schleim aus dem Rachen und
Nasenraum festsetzt.&lt;/p&gt;

&lt;p&gt;Die Flüssigkeit aus dem Behälter wird dann in das Röhrchen gekippt und das
Wattestäbchen darin eingetaucht. Etwa eine Minute soll man es darin lassen,
damit sich der Abstrich mit der Flüssigkeit verbindet.&lt;br /&gt;
Dann kann man das Stäbchen wegwerfen und das Röhrchen mit der speziellen
Kappe verschließen.&lt;/p&gt;

&lt;p&gt;Nun wird das Testgerät ausgepackt und dann sollen 3 Tropfen des 
Flüssigkeitsgemisches auf einen Testpunkt aufgebracht werden. Die Kappe 
des Röhrchens wirkt wie ein &lt;a href=&quot;https://de.wikipedia.org/wiki/Pipette&quot;&gt;Pipette&lt;/a&gt;
und lässt die Flüssigkeit langsam durchtropfen, wenn man es umdreht.&lt;/p&gt;

&lt;p&gt;Jetzt darf man 15 Minuten warten.&lt;br /&gt;
Die Flüssigkeit wird aufgesogen und verfärbt den Teststreifenbereich.&lt;/p&gt;

&lt;p&gt;Es gibt eine Kontrolllinie (C), die sich immer einfärben sollte und falls man
bereits infiziert ist, sollte ein zweiter Streifen (T) sichtbar werden.&lt;/p&gt;

&lt;p&gt;… so funktioniert also der neue Corona-Test.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Tja, ich bin offenbar “leider nur” normal krank, aber nicht mit COVID-19 
infiziert, zumindest blieb mein Teststreifen an der Stelle weiß.&lt;/p&gt;

&lt;p&gt;“Bringen” tut der Test aber nicht viel, außer dass man selbst ungefähr weiß,
ob man ansteckend ist.&lt;/p&gt;

&lt;p&gt;Die Nutzung von “körpernahen” Diensten wie ein Besuch beim Friseur ist damit
nicht zulässig, denn dafür braucht man einen “beglaubigten” Test einer 
Teststation oder beim Arzt.&lt;/p&gt;

&lt;p&gt;Aber für solche Fälle wie bei mir, wo man sich krank fühlt, gibt dieser 
kostenlose Test einen wertvollen Hinweis, ohne dass man gleich in den 
Nachbarbezirk für einen “Tiefentest” fahren muss. Auch für den Besuch von 
Verwandten ist dieser Indikator eine kleine Hilfe.&lt;/p&gt;

&lt;p&gt;Mal sehen, wie viele Corona-Test-Methoden ich hier mitdokumentieren 
werde. Niemand hätte noch vor einem Jahr gedacht, wie langatmig diese
Pandemie werden wird.&lt;/p&gt;

&lt;p&gt;Wenn das so weitergeht, muss ich die Subkategorie “COVID-19 Stories” im 
Blog anlegen.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>C++ CLI</title>
   <link href="https://www.opengate.at/blog/2021/02/cpp-cli/"/>
   <published>2021-02-27T12:00:00+01:00</published>
   <updated>2021-02-27T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2021/02/cpp-cli</id>
   <category term="devel" />
   <summary type="text">Vor 10 Jahren gehörte neben Win32
und POSIX
noch eine dritte quasi-Plattform zum ersten Entwurf des damalig GATE Projektes.
Und das war dotNet, genau 
genommen C++/CLI, also jene 
Erweiterung von C++, mit der man 
seit Studio 2005 
verwalteten dotNet Code mit C++ kreuzen konnte.

Tja … gebraucht hat das keiner und am wenigsten ich selbst.
… aber zumindest war es eine nette Erfahrung.
</summary>
   <content type="html">&lt;p&gt;Vor 10 Jahren gehörte neben &lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_Application_Programming_Interface&quot;&gt;Win32&lt;/a&gt;
und &lt;a href=&quot;https://de.wikipedia.org/wiki/Portable_Operating_System_Interface&quot;&gt;POSIX&lt;/a&gt;
noch eine dritte quasi-Plattform zum ersten Entwurf des damalig GATE Projektes.&lt;br /&gt;
Und das war &lt;a href=&quot;https://de.wikipedia.org/wiki/.NET_Framework&quot;&gt;dotNet&lt;/a&gt;, genau 
genommen &lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B/CLI&quot;&gt;C++/CLI&lt;/a&gt;, also jene 
Erweiterung von &lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B&quot;&gt;C++&lt;/a&gt;, mit der man 
seit &lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_Studio#Version_2005&quot;&gt;Studio 2005&lt;/a&gt; 
verwalteten dotNet Code mit C++ kreuzen konnte.&lt;/p&gt;

&lt;p&gt;Tja … gebraucht hat das keiner und am wenigsten ich selbst.
… aber zumindest war es eine nette Erfahrung.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Folgende Info zu Visual Studio 2017 erregte neulich meine Aufmerksamkeit:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;If your code needs to be safe or verifiable, 
then we recommend that you port it to C#.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Das steht bei der Info zum alten &lt;code&gt;pure&lt;/code&gt; und &lt;code&gt;safe&lt;/code&gt; Mode für C++/CLI.
&lt;a href=&quot;https://docs.microsoft.com/en-us/cpp/dotnet/pure-and-verifiable-code-cpp-cli?view=msvc-160&quot;&gt;in der MS Doku&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Es ist kein besonderes Kunststück mit C++ CLI eine dotNet Anwendung zu bauen.
Im sogenannten &lt;code&gt;mixed&lt;/code&gt; Mode kann man freie Pointer und native APIs gemeinsam
mit dotNet Assemblies nutzen … zumindest theoretisch.&lt;br /&gt;
Denn wenn die dotNet Security Features zur Geltung kommen, wird eine solche
“Mixed Assembly” schnell als Risiko eingestuft und nicht ausgeführt.&lt;/p&gt;

&lt;p&gt;Für Bibliotheken ist das ein sprichwörtlicher Killer.&lt;/p&gt;

&lt;p&gt;Doch genau dafür gab es den &lt;code&gt;pure&lt;/code&gt; Mode. Damit konnte man jeglichen C++ Code
dotNet-like kompilieren, jedoch nicht gegen native Bibliotheken linken.
Heißt also:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Algorithmen, Datenformate und In-Memory-Operationen: &lt;strong&gt;gut&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;WINAPI&lt;/code&gt;, DLLs, oder nicht-pure statische Libs: &lt;strong&gt;schlecht&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Genau das faszinierte mich damals, denn so könnte man die Codes von 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Zlib&quot;&gt;ZLIB&lt;/a&gt; und Co als “pure” dotNet 
Assembly kompilieren und von &lt;a href=&quot;https://de.wikipedia.org/wiki/C-Sharp&quot;&gt;C#&lt;/a&gt; 
oder &lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_Basic_.NET&quot;&gt;VB.NET&lt;/a&gt; aus nutzen.&lt;/p&gt;

&lt;p&gt;Aber auch der umgekehrte Weg war interessant: Ein C++ Framework, das
optional als “echte” dotNet Assembly kompiliert werden kann.&lt;/p&gt;

&lt;p&gt;Ein Problem dabei war das Aufbewahren von dotNet-Referenz Objekten in
nicht-verwalteten C++ Objekten.&lt;/p&gt;

&lt;h3 id=&quot;pointer-äquivalent-für-dotnet-objekt&quot;&gt;Pointer-Äquivalent für dotNet Objekt&lt;/h3&gt;

&lt;p&gt;Man kann zwar native Pointer in dotNet &lt;code&gt;ref&lt;/code&gt;-Klassen aufnehmen, aber nicht 
umgekehrt.&lt;br /&gt;
Aber: Man kann eine &lt;code&gt;ref&lt;/code&gt;-Instanz in ein 
&lt;a href=&quot;https://docs.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.gchandle?view=net-5.0&quot;&gt;&lt;code&gt;GCHandle&lt;/code&gt;&lt;/a&gt;
kapseln und dieses als &lt;code&gt;IntPtr&lt;/code&gt; speichern und umgekehrt aus dem &lt;code&gt;IntPtr&lt;/code&gt; 
wieder ein &lt;code&gt;GCHandle&lt;/code&gt; machen. Und reine Integer kann man in ein natives 
Objekt bekanntlich problemlos aufnehmen.&lt;/p&gt;

&lt;p&gt;Dafür hatte ich damals ein kleines Template geschrieben, das aus einem
irgendwo gespeicherten &lt;code&gt;intptr&lt;/code&gt; eine nutzbare dotNet Referenz machen konnte:&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;template&lt;/span&gt;&amp;lt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;T&lt;/span&gt;&amp;gt; Class CliHandle
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;protected&lt;/span&gt;:
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  intptr_t&amp;amp; refaddr;  &lt;span style=&quot;color:#777&quot;&gt;// external intptr to store object&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;public&lt;/span&gt;:
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;// bind to external `intptr` Instance&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;  CliHandle(intptr_t&amp;amp; h = &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;) : refaddr(h) {}
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;  CliHandle(&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;*&amp;amp; ptr) 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;    : refaddr(&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;reinterpret_cast&lt;/span&gt;&amp;lt;intptr_t&amp;amp;&amp;gt;(ptr)) 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;  { }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;  ~CliHandle() {}
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;// release object for intptr&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt; release()
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;  {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt;(&lt;span style=&quot;color:#950&quot;&gt;this&lt;/span&gt;-&amp;gt;refaddr)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;    {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;      System::Runtime::InteropServices::GCHandle gch(
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;        System::Runtime::InteropServices::GCHandle::FromIntPtr(
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n21&quot; name=&quot;n21&quot;&gt;21&lt;/a&gt;&lt;/span&gt;          System::IntPtr(&lt;span style=&quot;color:#950&quot;&gt;this&lt;/span&gt;-&amp;gt;refaddr)));
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n22&quot; name=&quot;n22&quot;&gt;22&lt;/a&gt;&lt;/span&gt;      gch.Free();
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n23&quot; name=&quot;n23&quot;&gt;23&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#950&quot;&gt;this&lt;/span&gt;-&amp;gt;refaddr = &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n24&quot; name=&quot;n24&quot;&gt;24&lt;/a&gt;&lt;/span&gt;    }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n25&quot; name=&quot;n25&quot;&gt;25&lt;/a&gt;&lt;/span&gt;  }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n26&quot; name=&quot;n26&quot;&gt;26&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n27&quot; name=&quot;n27&quot;&gt;27&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;// embed object in intptr&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n28&quot; name=&quot;n28&quot;&gt;28&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt; set(T t)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n29&quot; name=&quot;n29&quot;&gt;29&lt;/a&gt;&lt;/span&gt;  {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n30&quot; name=&quot;n30&quot;&gt;30&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;    &lt;span style=&quot;color:#950&quot;&gt;this&lt;/span&gt;-&amp;gt;release();
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n31&quot; name=&quot;n31&quot;&gt;31&lt;/a&gt;&lt;/span&gt;    System::Runtime::InteropServices::GCHandle gch(
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n32&quot; name=&quot;n32&quot;&gt;32&lt;/a&gt;&lt;/span&gt;      System::Runtime::InteropServices::GCHandle::Alloc(t));
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n33&quot; name=&quot;n33&quot;&gt;33&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#950&quot;&gt;this&lt;/span&gt;-&amp;gt;refaddr = (intptr_t)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n34&quot; name=&quot;n34&quot;&gt;34&lt;/a&gt;&lt;/span&gt;      System::Runtime::InteropServices::GCHandle::ToIntPtr(gch);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n35&quot; name=&quot;n35&quot;&gt;35&lt;/a&gt;&lt;/span&gt;  }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n36&quot; name=&quot;n36&quot;&gt;36&lt;/a&gt;&lt;/span&gt;  
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n37&quot; name=&quot;n37&quot;&gt;37&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;// access object by intptr&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n38&quot; name=&quot;n38&quot;&gt;38&lt;/a&gt;&lt;/span&gt;  T% get()
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n39&quot; name=&quot;n39&quot;&gt;39&lt;/a&gt;&lt;/span&gt;  {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n40&quot; name=&quot;n40&quot;&gt;40&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;    System::Runtime::InteropServices::GCHandle gch(
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n41&quot; name=&quot;n41&quot;&gt;41&lt;/a&gt;&lt;/span&gt;      System::Runtime::InteropServices::GCHandle::FromIntPtr(
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n42&quot; name=&quot;n42&quot;&gt;42&lt;/a&gt;&lt;/span&gt;        System::IntPtr(&lt;span style=&quot;color:#950&quot;&gt;this&lt;/span&gt;-&amp;gt;refaddr)));
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n43&quot; name=&quot;n43&quot;&gt;43&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; safe_cast&amp;lt;T%&amp;gt;(gch.Target);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n44&quot; name=&quot;n44&quot;&gt;44&lt;/a&gt;&lt;/span&gt;  }  
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n45&quot; name=&quot;n45&quot;&gt;45&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n46&quot; name=&quot;n46&quot;&gt;46&lt;/a&gt;&lt;/span&gt;  T% &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;operator&lt;/span&gt;*()
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n47&quot; name=&quot;n47&quot;&gt;47&lt;/a&gt;&lt;/span&gt;  {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n48&quot; name=&quot;n48&quot;&gt;48&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color:#950&quot;&gt;this&lt;/span&gt;-&amp;gt;get();
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n49&quot; name=&quot;n49&quot;&gt;49&lt;/a&gt;&lt;/span&gt;  }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n50&quot; name=&quot;n50&quot;&gt;50&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n51&quot; name=&quot;n51&quot;&gt;51&lt;/a&gt;&lt;/span&gt;  T% &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;operator&lt;/span&gt;-&amp;gt;()
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n52&quot; name=&quot;n52&quot;&gt;52&lt;/a&gt;&lt;/span&gt;  {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n53&quot; name=&quot;n53&quot;&gt;53&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color:#950&quot;&gt;this&lt;/span&gt;-&amp;gt;get();
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n54&quot; name=&quot;n54&quot;&gt;54&lt;/a&gt;&lt;/span&gt;  }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n55&quot; name=&quot;n55&quot;&gt;55&lt;/a&gt;&lt;/span&gt;};
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;So bettet man also dotNet Objekte in native Strukturen als &lt;code&gt;intptr_t&lt;/code&gt; ein.
Und in nativen Callbacks kann man über diesen Trick aus dem &lt;code&gt;intptr&lt;/code&gt; wieder
eine dotNet Instanz machen und darauf dann Methoden ausführen.&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;intptr_t my_dotnet_handle;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;CliHandle&amp;lt;DotNetClass&amp;gt; adapter(my_dotnet_handle);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;adapter.set(ref &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;new&lt;/span&gt; DotNetClass());
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;adapter-&amp;gt;dotnetFoo();
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;adapter-&amp;gt;dotnetBar();
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;adapter.release();
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Theoretisch lassen sich so dotNet Codes auch durch reine C Schichten
durchschleifen … aber so weit habe ich es damals nicht getrieben.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Naja, wie gesagt, gebraucht habe ich das nie und so flog die Idee aus dem
GATE Konzept und ist heute auch nicht mehr vorhanden.&lt;/p&gt;

&lt;p&gt;Trotzdem finde ich es Schade, das Microsoft diesen Pfad nun zugeschüttet hat,
schließlich war er ja schon “ausgetrampelt” und gehbereit. Aber vermutlich
war das so eine Nischenlösung, dass sie wirklich fast niemand gebraucht hat.&lt;/p&gt;

&lt;p&gt;Wie auch immer … ich hatte zumindest kurzfristig etwas Spaß damit, 
diesen Weg zu entdecken.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Ohr-ale Befriedigung</title>
   <link href="https://www.opengate.at/blog/2021/02/headsets/"/>
   <published>2021-02-21T12:00:00+01:00</published>
   <updated>2021-02-21T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2021/02/headsets</id>
   <category term="hardware" />
   <summary type="text">In Zeiten von Pandemie und 
Homeworking, ist ein gutes Headset
lebenswichtig.
Ich habe bisher nicht so besonders darauf geachtet, doch nun lehrt mich der
stetig Wechsel, wie unterschiedlich gut und schlecht der Klang an meine
Ohren dringt.
</summary>
   <content type="html">&lt;p&gt;In Zeiten von &lt;a href=&quot;https://de.wikipedia.org/wiki/COVID-19-Pandemie&quot;&gt;Pandemie&lt;/a&gt; und 
Homeworking, ist ein gutes &lt;a href=&quot;https://de.wikipedia.org/wiki/Headset&quot;&gt;Headset&lt;/a&gt;
lebenswichtig.&lt;br /&gt;
Ich habe bisher nicht so besonders darauf geachtet, doch nun lehrt mich der
stetig Wechsel, wie unterschiedlich gut und schlecht der Klang an meine
Ohren dringt.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Seit ein paar Jahren habe ich ein kabelloses (wireless) Headset der guten 
alten Marke &lt;a href=&quot;https://de.wikipedia.org/wiki/Sound_Blaster&quot;&gt;Soundblaster&lt;/a&gt; 
… und dieses Teil habe ich erst jetzt so richtig schätzen gelernt.&lt;br /&gt;
Denn leider ist es etwas altersschwach und mir ist wegen der langen Nutzung
auf einer Seite der Bügel gebrochen.&lt;/p&gt;

&lt;p&gt;Diese Problem konnte mit Superkleber geheilt werden, doch weil ich mit dem
Ausfall des Geräts gerechnet hatte, habe ich mir schon ein paar Alternativen
zugelegt.&lt;/p&gt;

&lt;p&gt;Hier eine Liste meiner “Lessons learned”:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Der &lt;a href=&quot;https://de.wikipedia.org/wiki/Dongle&quot;&gt;USB-Dongle&lt;/a&gt;, der mit 
Funkkopfhörern arbeitet, sollte nicht am PC angeschlossen werden, sondern 
per Verlängerungskabel vom PC-Gehäuse weggeführt werden. Denn direkt am PC 
dürfte das Gehäuse das Signal schwächen, und bereits im Nebenzimmer treten 
Störungen auf. Doch mit der Entfernung des Sticks zum Gehäuse steigt die 
Reichweite und so funktionieren die Kopfhörer in meiner gesamten Wohnung 
und nicht nur im Wohn/Arbeitszimmer.&lt;/li&gt;
  &lt;li&gt;Meine neuen Kopfhörer sind gleichzeitig ein grässliche Lichtorgel, die man
nicht abschalten kann. Dieses “Negativ-Feature” soll wohl cool wirken, ist 
aber eine bescheuerte Schlafstörung, wenn der Kopfhörer beim Laden 
rote, gelbe und blaue LED-Spiele durchführt, die man nicht abstellen kann.
Ein dunkles Zimmer kenne ich seither nicht mehr …&lt;/li&gt;
  &lt;li&gt;Mute-Taste neben der Lautstärkenregelung direkt am Ohr ist auch ein No-Go.
Man fasst ans Headset um die Lautstärke zu regeln und berührt dabei den 
Mute-Button und am Ende des Meetings wundern sich die Leute, warum ich so
still war. Und ich dachte, ich hätte eh jeden Satz lautstark kommentiert.&lt;/li&gt;
  &lt;li&gt;Bitte keine Laptop-Mikrofone! Die sind für alle anderen Online-Meeting
Teilnehmer eine Zumutung. Ja, inzwischen funktioniert die Ausfilterung
von Eigentonausgabe im Mikro recht gut, aber trotzdem ist die 
Geräuschkulisse störend, die sich im Laufe des Gespräches ergibt. Auch 
wird oft die eigene Stimme weggefiltert, wenn parallel wer anderer spricht,
während bei einem Headset das parallel sprechen und hören meist gut 
funktioniert.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Bluetooth&quot;&gt;Bluetooth&lt;/a&gt; In-Ears mit Mikrofon 
sind zwar leicht zu tragen aber kommen qualitativ selten an echte Headsets
heran. Aus Fernost habe ich um wenige Dollar so ein Teil zum Testen bestellt.
Für den geringen Preis, war das Gerät OK, doch ich merkte auch, dass 
Kollegen mich um Wortwiederholung baten. Soll heißen: Nur hören: JA, 
zum Sprechen: NEIN.&lt;/li&gt;
  &lt;li&gt;Billige Bluetooth Geräte haben dann auch noch einen Verzögerungseffekt.
Der Sound kommt erst ein paar hundert Millisekunden später an.
Filme ansehen ist mit den Teilen also keine Option … außer man beschuldigt
sowieso die Synchronsprecher einen schlechten Job gemacht zu haben …&lt;/li&gt;
  &lt;li&gt;Dämpfung der Umgebung ist auch nicht immer das beste.
Meine alten Kopfhörer saßen quasi perfekt. Nicht zu leicht aber auch nicht
zu fest. Ich konnte also noch schwach meine Umgebung hören.&lt;br /&gt;
Das neue Teil presst sich fest um die Ohren, womit man von der Umgebung
nur wenig mitbekommt … aber gerade beim Arbeiten, wo man gar nichts mehr
hört, bekomme ich meist ein komisches Gefühl, weil sich die Welt und der
eigene Körper nicht mehr so anhört, wie gewohnt.&lt;/li&gt;
  &lt;li&gt;Klein = Kurze Laufzeit.&lt;br /&gt;
Es ist eine Frage der Größe, denn in großen Headsets lassen sich auch 
leistungsfähigere Akkus verbauen, als in In-Ears.
Mit einer vollen Ladung kommen meine Funkheadsets meist einen Arbeitstag
(also bis zu 12 Stunden) aus. 
Die In-Ears machen schon nach ein bis zwei Stunden schlapp.
Das hängt natürlich auch von der Lautstärke ab. Bei Meetings halten sie 
länger durch, als im Kino-Modus.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Also kurz gesagt … ich will wieder ein neues Modell meiner alten Kopfhörer. 
Die waren offenbar ein zufälliger Glücksgriff und alle meine Alternativen 
kommen da nicht heran.&lt;/p&gt;

&lt;p&gt;Kann schon sein, dass es auch Gewohnheit ist, aber ich erinnere mich, dass ich
sie von Anfang an als “perfekt” wahrnahm. Und jetzt fällt mir eben um so
intensiver auf, dass wirklich jedes Audiogerät anders klingt.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>SQL, SQLite und ODBC</title>
   <link href="https://www.opengate.at/blog/2021/02/sql/"/>
   <published>2021-02-20T12:00:00+01:00</published>
   <updated>2021-02-20T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2021/02/sql</id>
   <category term="devel" /><category term="software" />
   <summary type="text">Für gewöhnlich versuche ich Datenbanken
zu meiden. Die meisten brauchen aufwändige Installationen und fressen 
Ressourcen, obwohl man oft nur ein paar Datenfelder sortiert speichern möchte.

Eine Ausnahme mache ich jedoch gerne. Und zwar für 
SQLite.
Tja und wenn man schon SQL
basierte Datenbanken anbinden möchte, dann ist der gute alte 
ODBC 
Standard auch nicht fern …
</summary>
   <content type="html">&lt;p&gt;Für gewöhnlich versuche ich &lt;a href=&quot;https://de.wikipedia.org/wiki/Datenbank&quot;&gt;Datenbanken&lt;/a&gt;
zu meiden. Die meisten brauchen aufwändige Installationen und fressen 
Ressourcen, obwohl man oft nur ein paar Datenfelder sortiert speichern möchte.&lt;/p&gt;

&lt;p&gt;Eine Ausnahme mache ich jedoch gerne. Und zwar für 
&lt;a href=&quot;https://de.wikipedia.org/wiki/SQLite&quot;&gt;SQLite&lt;/a&gt;.
Tja und wenn man schon &lt;a href=&quot;https://de.wikipedia.org/wiki/SQL&quot;&gt;SQL&lt;/a&gt;
basierte Datenbanken anbinden möchte, dann ist der gute alte 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Open_Database_Connectivity&quot;&gt;ODBC&lt;/a&gt; 
Standard auch nicht fern …
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;sqlite&quot;&gt;SQLite&lt;/h3&gt;

&lt;p&gt;SQLite ist eine In-Process-Datenbank. Man braucht also keinen separaten Server,
sondern bettet eine Bibliothek ein, die eine Datenbank Datei öffnen und
bearbeiten kann.&lt;br /&gt;
Genau das macht SQLite zur perfekten Embedded-Datenbank, denn sie ist rein in 
&lt;a href=&quot;https://de.wikipedia.org/wiki/C_(Programmiersprache)&quot;&gt;C&lt;/a&gt; geschrieben und kann 
statisch zum Programm gelinkt werden. Dann hat man seinen eigenen DB Server 
direkt in der EXE drinnen.&lt;/p&gt;

&lt;p&gt;Der Ablauf einer Anfrage sieht in SQLite etwa so aus:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;sqlite3_open(&quot;dbfile.sqlit&quot;, &amp;amp;db_handle)&lt;/code&gt;&lt;br /&gt;
Öffnet eine Datenbank&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;sqlite3_prepare(db_handle, &quot;SELECT * FROM some_table&quot;, sizeof(sql_command), &amp;amp;statement_handle, NULL)&lt;/code&gt;&lt;br /&gt;
Allokiert Ressourcen für eine SQL Abfrage oder ein Kommando&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;while(sqlite3_step(statement_handle) != SQLITE_DONE)&lt;/code&gt;&lt;br /&gt;
Nun läuft man alle Ergebnis Datensätze durch (falls vorhanden)
    &lt;ul&gt;
      &lt;li&gt;&lt;code&gt;sqlite3_column_count(statement_handle)&lt;/code&gt;&lt;br /&gt;
Gibt die Anzahl der Felder im aktuellen Datensatz zurück.
Die Felder werden über einen Index &lt;code&gt;(0 &amp;lt;= index &amp;lt; column_count)&lt;/code&gt; adressiert.&lt;/li&gt;
      &lt;li&gt;&lt;code&gt;sqlite3_column_name(statement_handle, index)&lt;/code&gt;&lt;br /&gt;
Gibt den Namen des Feldes im aktuellen Datensatz zurück.&lt;/li&gt;
      &lt;li&gt;&lt;code&gt;sqlite3_column_type(statement_handle, index)&lt;/code&gt;&lt;br /&gt;
Gibt den primären Datentypen eines Feldes per SQLite-Konstante zurück.
(also quasi &lt;code&gt;int64&lt;/code&gt;, &lt;code&gt;double&lt;/code&gt;, &lt;code&gt;char*&lt;/code&gt; oder &lt;code&gt;void*&lt;/code&gt;)&lt;/li&gt;
      &lt;li&gt;&lt;code&gt;sqlite3_column_int64(statement_handle, index)&lt;/code&gt;&lt;br /&gt;
Gibt den Feldinhalt als 64 bit Integer zurück.&lt;/li&gt;
      &lt;li&gt;&lt;code&gt;sqlite3_column_double(statement_handle, index)&lt;/code&gt;&lt;br /&gt;
Gibt den Feldinhalt als 64 bit Fließkommazahl zurück.&lt;/li&gt;
      &lt;li&gt;&lt;code&gt;sqlite3_column_bytes(statement_handle, index)&lt;/code&gt;&lt;br /&gt;
Gibt für &lt;a href=&quot;https://de.wikipedia.org/wiki/Binary_Large_Object&quot;&gt;BLOB&lt;/a&gt;
und TEXT die Anzahl der Bytes des Feldes zurück.&lt;/li&gt;
      &lt;li&gt;&lt;code&gt;sqlite3_column_blob(statement_handle, index)&lt;/code&gt;&lt;br /&gt;
Gibt einen Pointer auf das erst Byte eines Bytefeldes zurück.&lt;/li&gt;
      &lt;li&gt;&lt;code&gt;sqlite3_column_text(statement_handle, index)&lt;/code&gt;&lt;br /&gt;
Gibt einen Pointer auf das erste Zeichen in einem Text-String zurück.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code&gt;sqlite3_finalize(statement_handle)&lt;/code&gt;&lt;br /&gt;
Gibt alle offenen Ressourcen der Abfrage frei.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;sqlite3_close(db_handle)&lt;/code&gt;&lt;br /&gt;
Schließt die Datenbank.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Viel einfacher geht es wohl kaum aus Schnittstellensicht. Und alles andere wie
das Setzen von Option erfolgt per Kommando. Es gibt da ein paar spezielle
&lt;code&gt;PRAGMA&lt;/code&gt; Anweisungen, wie z.B.: &lt;code&gt;PRAGMA foreign_keys = ON&lt;/code&gt; mit der man das 
Verwalten von Fremdschlüsseln bewusst einschalten kann.&lt;br /&gt;
Das erledigt man auch über &lt;code&gt;sqlite3_prepare&lt;/code&gt;, &lt;code&gt;sqlite3_step&lt;/code&gt; und 
&lt;code&gt;sqlite3_finalize&lt;/code&gt;, denn SQLite deaktiviert beim Start manche Features um 
die Ausführung zu beschleunigen.&lt;br /&gt;
Wie auch immer … Fremdschlüssel sind etwas, was ich trotzdem von jeder
Datenbank erwarte.&lt;/p&gt;

&lt;p&gt;Ganz besonders cool: Diese API existiert für die meisten Programmiersprachen,
sie kann also “universal” genutzt werden, nicht nur in C oder C++.&lt;/p&gt;

&lt;h3 id=&quot;odbc&quot;&gt;ODBC&lt;/h3&gt;

&lt;p&gt;Die &lt;strong&gt;O&lt;/strong&gt;pen &lt;strong&gt;D&lt;/strong&gt;ata&lt;strong&gt;B&lt;/strong&gt;ase &lt;strong&gt;C&lt;/strong&gt;onnectivity ist mir seit dem alten 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_3.1&quot;&gt;Windows 3.1&lt;/a&gt; ein 
Begriff und war der Versuch alle Datenbanken hinter einer API zu verstecken. 
Mit &lt;code&gt;unixODBC&lt;/code&gt; gibt es auch eine kompatible Implementierung für 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt; und andere 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Portable_Operating_System_Interface&quot;&gt;POSIX&lt;/a&gt; 
Systeme.&lt;/p&gt;

&lt;p&gt;Wichtig ist die Konfiguration von Datenquellen und deren Namen im System,
denn über einen entsprechenden Connection-String verbindet man sich dann per
ODBC als Wrapper zu einer beliebigen Datenbank von SQLite über 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_SQL_Server&quot;&gt;MS-SQL&lt;/a&gt; bis hin
zu &lt;a href=&quot;https://de.wikipedia.org/wiki/MySQL&quot;&gt;MySQL&lt;/a&gt; usw.&lt;/p&gt;

&lt;p&gt;Der API Aufbau sieht hier ähnlich aus, wenn auch etwas komplexer:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;SQLAllocEnv(&amp;amp;henv)&lt;/code&gt;&lt;br /&gt;
Allokiert eine ODBC Umgebung.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;SQLAllocConnect(henv, &amp;amp;hdbc)&lt;/code&gt;&lt;br /&gt;
Allokiert eine ODBC Datenbankverbindung.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;SQLConnect(hdbc, &quot;my_odbc_name&quot;, sizeof(&quot;my_odbc_name&quot;), &quot;user&quot;, sizeof(&quot;user&quot;), &quot;passwd&quot;, sizeof(&quot;passwd&quot;))&lt;/code&gt;&lt;br /&gt;
Verbindet sich zu einer konfigurierten Datenbank.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;SQLAllocStmt(hdbc, &amp;amp;hstmt)&lt;/code&gt;&lt;br /&gt;
Allokiert Ressourcen für ein SQL Statement.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;SQLPrepare(hstmt, &quot;SELECT * FROM some_table&quot;, sizeof(sql_command))&lt;/code&gt;&lt;br /&gt;
Bereitet die Ausführung eines SQL Statements vor.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;SQLExecute(hstmt)&lt;/code&gt;&lt;br /&gt;
Startet die Ausführung eines SQL Statements auf der Datenbank.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;while(SQL_SUCCESS == SQLFetch(hstmt))&lt;/code&gt;&lt;br /&gt;
Liest eine Datenzeile aus dem Abfrageergebnis.
    &lt;ul&gt;
      &lt;li&gt;&lt;code&gt;SQLNumResultCols(hstmt, &amp;amp;col_count)&lt;/code&gt;&lt;br /&gt;
Gibt die Anzahl der Datenfelder im aktuellen Datensatz zurück.&lt;/li&gt;
      &lt;li&gt;&lt;code&gt;SQLDescribeCol(hstmt, (index + 1), colname_buffer, colname_buffer_len, &amp;amp;colname_buffer_used, &amp;amp;coltype, &amp;amp;colvalue_len, &amp;amp;colvalue_digits, &amp;amp;colvalue_nullable)&lt;/code&gt;&lt;br /&gt;
Liefert Informationen über ein Datenfeld, wie Name, Datentype oder Größe.
Der Index beginnt allerdings bei “1”, also &lt;code&gt;0 &amp;lt; index &amp;lt;= SQLNumResultCols&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;&lt;code&gt;SQLGetData(hstmt, (index + 1), sql_type, buffer, sizeof(buffer), &amp;amp;buffer_used)&lt;/code&gt;&lt;br /&gt;
List die Daten eines Feldes in einen generischen Puffer.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code&gt;SQLFreeStmt(stmt, SQL_CLOSE)&lt;/code&gt;&lt;br /&gt;
Schließt Ressourcen einer Abfrage.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;SQLFreeStmt(stmt, SQL_DROP)&lt;/code&gt;&lt;br /&gt;
Gibt Ressourcen einer Abfrage final frei.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;SQLDisconnect(hdbc)&lt;/code&gt;&lt;br /&gt;
Schließt eine Datenbank Verbindung.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;SQLFreeConnect(hdbc)&lt;/code&gt;&lt;br /&gt;
Gibt allokierte Ressourcen einer Verbindung final frei.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;SQLFreeEnv(henv)&lt;/code&gt;&lt;br /&gt;
Gibt alle Ressourcen der ODBC Umgebung final frei.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Etwas kompliziert sind die Datentypen, weil es recht viele gibt und 
manche nicht extakt gleich mit &lt;code&gt;SQLGetData&lt;/code&gt; angefordert werden können,
wie sie mit &lt;code&gt;SQLDescribeCol&lt;/code&gt; beschrieben sind.&lt;/p&gt;

&lt;p&gt;Hinweis: In Windows gibt es natürlich immer eine &lt;a href=&quot;https://de.wikipedia.org/wiki/Unicode&quot;&gt;Unicode&lt;/a&gt;
API parallel zur ANSI API, womit man jeden String als &lt;code&gt;TCHAR&lt;/code&gt; übergeben 
sollte und die Anzahl der Zeichen eben nicht &lt;code&gt;sizeof&lt;/code&gt; wie im obigen Beispiel
ist.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ab sofort sind SQLite und ODBC im GATE Framework vertreten und werden durch
eine &lt;code&gt;DBConnection&lt;/code&gt; und eine &lt;code&gt;DBReader&lt;/code&gt; Klasse abstrahiert.&lt;br /&gt;
Die Connection verwaltet den Start von Abfragen und der Reader übersetzt immer
den aktuellen Datensatz in GATE-kompatible Datentypen.&lt;/p&gt;

&lt;p&gt;Für Suchanfragen eignet sich SQL natürlich viel besser als irgend welche 
nativen Datensätze, die binär in Dateien stehen. Und eben deshalb darf
diese Schnittstelle im Framework nicht fehlen.&lt;/p&gt;

&lt;p&gt;Hmm … dabei bemerke ich natürlich eines: Jetzt fehlt mir eine Art von 
editierbarer Grid-View im UI Framework.&lt;/p&gt;

&lt;p&gt;Tja, so schafft man sich selbst Arbeit.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Variadic Templates</title>
   <link href="https://www.opengate.at/blog/2021/02/variadic-templates/"/>
   <published>2021-02-14T12:00:00+01:00</published>
   <updated>2021-02-14T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2021/02/variadic-templates</id>
   <category term="devel" />
   <summary type="text">Zu Variadic Templates habe
ich historisch bedingt ein schlechtes Verhältnis. Da sie erst mit 
C++11 viel zu spät in den Standard 
kamen, wucherten Schnellschüsse in boost
und Co schon Jahre zuvor, die aus Code “Kot” machten.

Wie auch immer, heute, mit dem C++20
Standard kommt man an diesem Feature eigentlich nicht mehr vorbei, 
wenn man die STL 
verstehen möchte.
</summary>
   <content type="html">&lt;p&gt;Zu &lt;a href=&quot;https://en.wikipedia.org/wiki/Variadic_template&quot;&gt;Variadic Templates&lt;/a&gt; habe
ich historisch bedingt ein schlechtes Verhältnis. Da sie erst mit 
&lt;a href=&quot;https://en.wikipedia.org/wiki/C%2B%2B11&quot;&gt;C++11&lt;/a&gt; viel zu spät in den Standard 
kamen, wucherten Schnellschüsse in &lt;a href=&quot;https://de.wikipedia.org/wiki/Boost_(C%2B%2B-Bibliothek)&quot;&gt;&lt;code&gt;boost&lt;/code&gt;&lt;/a&gt;
und Co schon Jahre zuvor, die aus Code “Kot” machten.&lt;/p&gt;

&lt;p&gt;Wie auch immer, heute, mit dem &lt;a href=&quot;https://en.wikipedia.org/wiki/C%2B%2B20&quot;&gt;C++20&lt;/a&gt;
Standard kommt man an diesem Feature eigentlich nicht mehr vorbei, 
wenn man die &lt;a href=&quot;https://de.wikipedia.org/wiki/Standard_Template_Library&quot;&gt;STL&lt;/a&gt; 
verstehen möchte.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;überladungen-sind-zu-wenig&quot;&gt;Überladungen sind zu wenig&lt;/h3&gt;

&lt;p&gt;Variadic Templates sollen in C++ das ermöglichen, was &lt;code&gt;variadic functions&lt;/code&gt; in
&lt;a href=&quot;https://de.wikipedia.org/wiki/C_(Programmiersprache)&quot;&gt;C&lt;/a&gt; schon 30 Jahre 
früher konnten: Man kann eine freie Anzahl an Argumenten an eine Funktion 
übergeben und diese iteriert sie durch.&lt;br /&gt;
Bestes Beispiel ist &lt;code&gt;prinf(format, ...)&lt;/code&gt; wo man so viele Variablen übergeben
kann, wie im &lt;code&gt;format&lt;/code&gt; String angegeben sind.&lt;/p&gt;

&lt;p&gt;Aber C++ unterstützte von Anfang an Funktions-Überladung und so konnte man
für jede Anzahl an Argumenten eine Funktion schreiben, die sich genau um die
Anzahl kümmerte und alle durften den gleichen Namen haben.&lt;/p&gt;

&lt;p&gt;Genau so wurden viele Features von 1998 bis 2011 implementiert … doch die 
Sache hatte einen Haken: 
&lt;strong&gt;Es fehlten R-Value-References.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Und wenn man eine Variable “frei” übergeben möchte, soll die Funktion diese
auch “ohne Auflagen” entgegennehmen.&lt;/p&gt;

&lt;p&gt;Jedoch musst man sich entweder für “by-value” oder “by-reference” entscheiden:&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;template&lt;/span&gt;&amp;lt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;T&lt;/span&gt;&amp;gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt; use_argument(T byValue);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;template&lt;/span&gt;&amp;lt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;T&lt;/span&gt;&amp;gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt; use_argument(T&amp;amp; byReference);
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Der erste Fall kopiert die Variable, erzwingt also die Kopierbarkeit des 
Objektes und entkoppelt es vom Original.&lt;br /&gt;
Der zweite Fall bekommt mit Konstanten Probleme, man bräuchte noch eine 
dritte Variante mit &lt;code&gt;T const&amp;amp;&lt;/code&gt; die dann aber in manchen Fällen &lt;code&gt;T&amp;amp;&lt;/code&gt; schlucken
kann.&lt;/p&gt;

&lt;p&gt;Und wenn man 2, 3 oder mehr Argumente hat, müsste man alle Kombinationen von
Referenzen und Werten ausimplementieren, also bei 2 Argumenten sind das 4,
bei 3 schon 8 … allgemein also &lt;code&gt;2 hoch n&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;template&lt;/span&gt;&amp;lt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;T&lt;/span&gt;&amp;gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt; use_argument(T&amp;amp;&amp;amp; anything);
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;hingegen löst alles.&lt;/p&gt;

&lt;h3 id=&quot;anwendung&quot;&gt;Anwendung&lt;/h3&gt;

&lt;p&gt;Mein erstes Demo-Beispiel von vor langer Zeit sah etwa so aus:&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;template&lt;/span&gt;&amp;lt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;T&lt;/span&gt;&amp;gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt; print1(T &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt;&amp;amp; t)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  std::cout &amp;lt;&amp;lt; t;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;}
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt; print1(nullptr_t &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt;&amp;amp; n)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;}
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;template&lt;/span&gt;&amp;lt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;A&lt;/span&gt; = nullptr_t, &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;B&lt;/span&gt; = nullptr_t, 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;C&lt;/span&gt; = nullptr_t, &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;D&lt;/span&gt; = nullptr_t, &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;E&lt;/span&gt; = nullptr_t&amp;gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt; print(A&amp;amp;&amp;amp; a = A(), B&amp;amp;&amp;amp; b = B(), C&amp;amp;&amp;amp; c = C(), D&amp;amp;&amp;amp; d = D(), E&amp;amp;&amp;amp; e = E())
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;  print1(a);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;  print1(b);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;  print1(c);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;  print1(d);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;  print1(e);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;}
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n21&quot; name=&quot;n21&quot;&gt;21&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n22&quot; name=&quot;n22&quot;&gt;22&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;template&lt;/span&gt;&amp;lt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;typename&lt;/span&gt;... T&amp;gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt; print_variadic(T... var)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n23&quot; name=&quot;n23&quot;&gt;23&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n24&quot; name=&quot;n24&quot;&gt;24&lt;/a&gt;&lt;/span&gt;  print(var...);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n25&quot; name=&quot;n25&quot;&gt;25&lt;/a&gt;&lt;/span&gt;}
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n26&quot; name=&quot;n26&quot;&gt;26&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n27&quot; name=&quot;n27&quot;&gt;27&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; main()
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n28&quot; name=&quot;n28&quot;&gt;28&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n29&quot; name=&quot;n29&quot;&gt;29&lt;/a&gt;&lt;/span&gt;  print_variadic(&lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;, &lt;span style=&quot;color:#00D&quot;&gt;2&lt;/span&gt;, &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Hello World&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n30&quot; name=&quot;n30&quot;&gt;30&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n31&quot; name=&quot;n31&quot;&gt;31&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;OK … es war “recht dumm” und wandelt den freien Aufruf wieder in eine feste
Anzahl von Argumenten um, bei denen die nicht benutzten durch &lt;code&gt;nullptr_t&lt;/code&gt; 
ersetzt werden, die dann keine Aktion bewirken … aber so kann man schön
zeigen, dass damit in erster Linie Funktionsaufrufe generiert werden, die nur 
das weitergeben, was am Anfang durch Beistriche getrennt aufgezählt wird.&lt;/p&gt;

&lt;p&gt;Das kann man auch gut mit einem überladenen &lt;code&gt;operator,()&lt;/code&gt; handhaben.&lt;/p&gt;

&lt;h3 id=&quot;rekursionen-bevorzugt&quot;&gt;Rekursionen bevorzugt&lt;/h3&gt;

&lt;p&gt;Um das Feature im “modernen C++ Style” zu nutzen sind aber Rekursionen
und rekursive Vererbungen samt Spezialisierungen angesagt:&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;template&lt;/span&gt;&amp;lt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;.&lt;/span&gt;.. T&amp;gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;VarTempl&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;template&lt;/span&gt;&amp;lt;&amp;gt; 
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;VarTempl&lt;/span&gt;&amp;lt;&amp;gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;{  &lt;span style=&quot;color:#777&quot;&gt;// no args&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;};
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;template&lt;/span&gt;&amp;lt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;T&lt;/span&gt;, &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;.&lt;/span&gt;.. Others&amp;gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;VarTempl&lt;/span&gt;&amp;lt;T, Others...&amp;gt; : &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;public&lt;/span&gt; VarTempl&amp;lt;Others...&amp;gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;{  &lt;span style=&quot;color:#777&quot;&gt;// N-args extends (N-1)-args&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;};
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Das klassische Beispiel dafür ist &lt;code&gt;std::tuple&lt;/code&gt;, doch man stellt leider auch 
fest, dass das Ganze nicht mehr ganz so unkompliziert ist, wie in 
C mit &lt;code&gt;va_start&lt;/code&gt;, &lt;code&gt;va_arg&lt;/code&gt; und &lt;code&gt;va_end&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Im GATE Projekt wird diese Technik vorläufig nicht eingesetzt um mit älteren
Compilern kompatibel zu bleiben … aber … so wie auch R-Value-References 
optional aktiviert werden können, denke ich über einen “schöneren” 
Ersatz für die bestehenden &lt;code&gt;Delegate0&lt;/code&gt;, &lt;code&gt;Delegate1&lt;/code&gt; bis &lt;code&gt;DelegateN&lt;/code&gt; Klassen 
nach.&lt;/p&gt;

&lt;p&gt;Und dafür wären Variadic Templates natürlich perfekt.&lt;br /&gt;
Mal sehen, wann ich dazu komme.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Win32 auf Linux kompilieren</title>
   <link href="https://www.opengate.at/blog/2021/02/win-linux/"/>
   <published>2021-02-13T12:00:00+01:00</published>
   <updated>2021-02-13T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2021/02/win-linux</id>
   <category term="devel" />
   <summary type="text">Dank dem Windows Subsystem für Linux
(WSL) können wir also unter Windows 10 native Linux
Binaries kompilieren.
Aber wie sieht es anders herum aus?

Dank dem guten alten MinGW können wir 
auch unter Linux native Windows Binärprogramme erstellen lassen.

Heißt also konkret: Der nächste GATE Build für Windows wird am 
Raspberry PI laufen …
</summary>
   <content type="html">&lt;p&gt;Dank dem &lt;a href=&quot;https://de.wikipedia.org/wiki/Windows-Subsystem_f%C3%BCr_Linux&quot;&gt;Windows Subsystem für Linux&lt;/a&gt;
(WSL) können wir also unter Windows 10 native &lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt;
Binaries kompilieren.&lt;br /&gt;
Aber wie sieht es anders herum aus?&lt;/p&gt;

&lt;p&gt;Dank dem guten alten &lt;a href=&quot;https://de.wikipedia.org/wiki/MinGW&quot;&gt;MinGW&lt;/a&gt; können wir 
auch unter Linux native Windows Binärprogramme erstellen lassen.&lt;/p&gt;

&lt;p&gt;Heißt also konkret: Der nächste GATE Build für Windows wird am 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Raspberry_Pi&quot;&gt;Raspberry PI&lt;/a&gt; laufen …
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;mingw-installieren&quot;&gt;MinGW installieren&lt;/h3&gt;

&lt;p&gt;Für Debian und Ubuntu könnte es einfacher nicht sein:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;sudo apt install gcc-mingw-w64 -y
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;sudo apt install g++-mingw-w64 -y
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Die Installation liefert alles, was notwendig ist, also Compiler und 
alle nötigen &lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_Application_Programming_Interface&quot;&gt;WinAPI&lt;/a&gt; 
Header für die meisten Anwendungsfälle.&lt;/p&gt;

&lt;p&gt;Und mit &lt;code&gt;x86_64-w64-mingw32-g++ --version&lt;/code&gt; sieht man ob die Installation
erfolgreich war.
Jetzt könnte man schon manuell kompilieren … aber wie sieht es mit 
&lt;a href=&quot;https://de.wikipedia.org/wiki/CMake&quot;&gt;CMake&lt;/a&gt; aus?&lt;/p&gt;

&lt;h3 id=&quot;cmake-toolchain-anpassen&quot;&gt;CMake Toolchain anpassen&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;CMake&lt;/code&gt; nutzt für gewöhnlich den Standard &lt;a href=&quot;https://de.wikipedia.org/wiki/GNU_Compiler_Collection&quot;&gt;GCC&lt;/a&gt;
eines Systems, wenn man keine weiteren Parameter setzt.&lt;br /&gt;
Um dieses Tool mit &lt;code&gt;MinGW&lt;/code&gt; anzufreunden, nutzen viele OpenSource Projekte
eine Toolchain-Datei, die nötige Parameter setzt.&lt;/p&gt;

&lt;p&gt;Die könnte &lt;code&gt;mingw-w64-x86_64.cmake&lt;/code&gt; heißen und sieht dann etwa so aus:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;set(CMAKE_SYSTEM_NAME Windows)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;set(TOOLCHAIN_PREFIX x86_64-w64-mingw32)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}-gcc)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}-g++)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;set(CMAKE_Fortran_COMPILER ${TOOLCHAIN_PREFIX}-gfortran)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;set(CMAKE_RC_COMPILER ${TOOLCHAIN_PREFIX}-windres)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;set(CMAKE_FIND_ROOT_PATH /usr/${TOOLCHAIN_PREFIX})
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Nun startet man &lt;code&gt;CMake&lt;/code&gt; mit dem Parameter &lt;code&gt;CMAKE_TOOLCHAIN_FILE&lt;/code&gt;
mit dem Pfad zur Datei und schon bereitet &lt;code&gt;CMake&lt;/code&gt; alles vor.
Per &lt;code&gt;ccmake&lt;/code&gt; kann man letzte Flags im Cache bequem einstellen,
oder man übergibt diese als Parameter direkt an das &lt;code&gt;cmake&lt;/code&gt; Kommando.
Am Ende kann dann ein reguläres &lt;code&gt;make&lt;/code&gt; den Build anstoßen.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;cd build-dir
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;cmake -DCMAKE_TOOLCHAIN_FILE=path/to/mingw-w64-x86_64.cmake path/to/sources
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;ccmake path/to/sources
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;make
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Und wenn man kein 64-bit Build, sondern nur 32-bit möchte,&lt;br /&gt;
ersetzt man &lt;code&gt;set(TOOLCHAIN_PREFIX x86_64-w64-mingw32)&lt;/code&gt;&lt;br /&gt;
durch &lt;code&gt;set(TOOLCHAIN_PREFIX i686-w64-mingw32)&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;winapi-header-verweise-anpassen&quot;&gt;WinAPI Header Verweise anpassen&lt;/h3&gt;

&lt;p&gt;Sourcen aus dem MSDN oder diversen Codebeispielen nutzen gerne Headerverweise
mit Großbuchstaben. Das funktioniert dann unter Linux nicht, denn MinGW 
stellt alle WinAPI-Header nur mit Kleinbuchstaben zur Verfügung.&lt;/p&gt;

&lt;p&gt;Hat man also Einträge wie z.B.:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;#include &amp;quot;Winsock2.h&amp;quot;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;#include &amp;quot;Windows.h&amp;quot;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;müssen diese auf &lt;code&gt;&quot;winsock2.h&quot;&lt;/code&gt;, &lt;code&gt;&quot;windows.h&quot;&lt;/code&gt; und so weiter angepasst werden.&lt;/p&gt;

&lt;p&gt;Das war auch im GATE Projekt schon längst notwendig.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ähm … hätte mir mal vor 15 Jahren jemand gesagt, dass es so leicht sei,
Windows Programme unter Linux und umgekehrt zu kompilieren, hätte ich 
überheblich gelacht und gemeint:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Na dann viel Spaß beim manuellen Schreiben der Konfiguration!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Aber mit &lt;code&gt;CMake&lt;/code&gt; und &lt;code&gt;MinGW&lt;/code&gt; ist das echt komfortabel geworden.&lt;br /&gt;
Und das bedeutet, dass man sich nicht mehr ewig lange mit dem 
Setup von Windows und der &lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_C%2B%2B&quot;&gt;MSVC&lt;/a&gt;
Toolchain abmühen muss, denn nun läuft der Windows Build einfach auf 
einer Linux VM mit, und diese sind in vielen Cloud-Lösungen wesentlich 
günstiger zu bekommen als entsprechende Windows-Umgebungen.&lt;/p&gt;

&lt;p&gt;Und das GATE Framework lässt sich nun tatsächlich vollständig 
auf dem Raspberry PI für Windows bauen.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;… also eine “echt geniale Sache”!&lt;/em&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>WSUS: Windows Server Update Service</title>
   <link href="https://www.opengate.at/blog/2021/02/wsus/"/>
   <published>2021-02-07T12:00:00+01:00</published>
   <updated>2021-02-07T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2021/02/wsus</id>
   <category term="software" />
   <summary type="text">Hmm… vor einem Jahr konnte ich noch 
Server 2003
Installationen mit dem Standard Windows Update aktualisieren. Heute schlägt
das fehlt. Offenbar sind jetzt dafür notwendige Zertifikate abgelaufen.

Es gibt aber einen Ausweg: Das 
Windows Server Update Service, 
kurz WSUS. Und mit diesem lädt ein aktueller Server 2016 oder 2019 alles 
herunter und stellt es seinen gealterten Geschwistern zur Verfügung.
</summary>
   <content type="html">&lt;p&gt;Hmm… vor einem Jahr konnte ich noch 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_Server_2003&quot;&gt;Server 2003&lt;/a&gt;
Installationen mit dem Standard Windows Update aktualisieren. Heute schlägt
das fehlt. Offenbar sind jetzt dafür notwendige Zertifikate abgelaufen.&lt;/p&gt;

&lt;p&gt;Es gibt aber einen Ausweg: Das 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_Server_Update_Services&quot;&gt;Windows Server Update Service&lt;/a&gt;, 
kurz WSUS. Und mit diesem lädt ein aktueller Server 2016 oder 2019 alles 
herunter und stellt es seinen gealterten Geschwistern zur Verfügung.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;vorgeschichte-volume-license&quot;&gt;Vorgeschichte: Volume License&lt;/h3&gt;

&lt;p&gt;Mir ist letztes Jahr ein Fehler unterlaufen. Ich hatte für meine alten
Testsysteme normale Windows Installation durchgeführt und diese auf den
Letztstand gepatcht.&lt;br /&gt;
Das Problem dabei ist, dass diese bei Microsoft “aktiviert” werden müssen
und das hatte ich genervt “verschoben” um mich später wieder daran zu
erinnern, dass man die ja heute auch nicht mehr so leicht aktivieren kann.&lt;/p&gt;

&lt;p&gt;Jetzt beinhaltet aber mein &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Developer_Network#MSDN_Subscriptions&quot;&gt;MSDN Paket&lt;/a&gt;
auch eine Volume-License mit der die lästige Aktivierung wegfällt … 
aber dafür braucht man wieder ein Windows Setup, das diese speziellen 
Seriennummern akzeptiert.&lt;/p&gt;

&lt;p&gt;Nun gut, somit wollte ich wieder mal meine Checklist abarbeiten:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Originales Installations-ISO herunterladen&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Virtuelle_Maschine&quot;&gt;VM&lt;/a&gt; Installation 
durchführen&lt;/li&gt;
  &lt;li&gt;Auf &lt;a href=&quot;https://en.wikipedia.org/wiki/Internet_Explorer_8&quot;&gt;IE8&lt;/a&gt; updaten 
und Windows Update anwerfen&lt;/li&gt;
  &lt;li&gt;Benötigte Windows Updates separat herunterladen&lt;/li&gt;
  &lt;li&gt;Per &lt;a href=&quot;https://de.wikipedia.org/wiki/NLite&quot;&gt;nLite&lt;/a&gt; das Windows Setup patchen&lt;/li&gt;
  &lt;li&gt;Neues ISO erstellen und damit glücklich werden.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Doch Windows Update verweigert nun den Dienst.&lt;/p&gt;

&lt;h3 id=&quot;wsus-2019&quot;&gt;WSUS 2019&lt;/h3&gt;

&lt;p&gt;Vor so etwa 13 Jahren hatte ich mich auch mal &lt;code&gt;WSUS&lt;/code&gt; unter Server 2003 
gespielt. Funktioniert hat das damals nicht wirklich (vermutlich mein 
Fehler) und ich ließ es bleiben.&lt;br /&gt;
Heute klickte ich mal ein bisschen herum und aktivierte WSUS auf meinem 
externen Testserver.&lt;/p&gt;

&lt;p&gt;Es dauerte zwar ewig bis die erste Synchronisation fertig war, doch dann 
sah ich eine Liste der unterstützen Microsoft Produkte und war fast erstaunt, 
dass Server 2003, &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_XP&quot;&gt;Windows XP&lt;/a&gt; 
und sogar &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_2000&quot;&gt;Windows 2000&lt;/a&gt; 
noch darunter waren.&lt;br /&gt;
Nun gut … jetzt musste ich es ausprobieren.&lt;/p&gt;

&lt;p&gt;Hinweis: Die dafür notwendige 
&lt;a href=&quot;https://en.wikipedia.org/wiki/Windows_Internal_Database&quot;&gt;Windows Internal Database&lt;/a&gt; 
ist auf meinen Stromspar-Atom-Servern ein Alptraum. Das Mistding versucht 
offenbar single-threaded die gesamte Microsoft Update Datenbank zu duplizieren 
und legt eine Performance hin, dass sich sogar meine 16 MHz Arduinos beim 
Zusehen langweilen.&lt;br /&gt;
Für den produktiven Einsatz braucht man also rechenkräftige Hardware!&lt;/p&gt;

&lt;h3 id=&quot;wsus-client-manuell-einrichten&quot;&gt;WSUS Client manuell einrichten&lt;/h3&gt;

&lt;p&gt;In einem (von MS gewünschten) &lt;a href=&quot;https://de.wikipedia.org/wiki/Active_Directory&quot;&gt;Active-Directory&lt;/a&gt;
Server-Wald würde man per Gruppenrichtlinie alle Systeme dazu bringen, dass 
sie nicht mehr das öffentliche Windows Update nutzen, sondern den internen 
Update Server befragen.&lt;/p&gt;

&lt;p&gt;Ohne AD kann man die Richtlinie aber auch manuell anpassen:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;gpedit.msc&lt;/code&gt; starten (oder &lt;code&gt;mmc&lt;/code&gt; starten und dort die Gruppenrichtlinien
hinzufügen)&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;Computer Configuration&lt;/code&gt; - &lt;code&gt;Administrative Templates&lt;/code&gt; - 
&lt;code&gt;Windows Components&lt;/code&gt; - &lt;code&gt;Windows Update&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Unter &lt;code&gt;Specify intranet Microsoft update service location&lt;/code&gt; wird dann die 
URL des Servers eingetragen. WSUS 2019 nutzt den Port &lt;code&gt;8530&lt;/code&gt; für HTTP
als Standard (und &lt;code&gt;8531&lt;/code&gt; für HTTPS).
Somit trägt man bei beiden Feldern dann &lt;code&gt;http://192.168.XX.YY:8530&lt;/code&gt;
(bzw. die korrekte Server IP) ein.&lt;/li&gt;
  &lt;li&gt;Abschließend kann man dann noch das “Automatic Update Service” neu starten
oder gleich die Maschine neu booten lassen.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/wsus-gpo-setup2k3.png&quot; alt=&quot;WSUS GPO Setup 2K3&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;updates-freischalten-und-verteilen&quot;&gt;Updates freischalten und verteilen&lt;/h3&gt;

&lt;p&gt;Damit sich die Zielmaschine sofort bei der WSUS Adresse mal meldet, hilft ein&lt;br /&gt;
&lt;code&gt;wuauclt /reportnow&lt;/code&gt; oder &lt;code&gt;wuauclt /detectnow&lt;/code&gt;. Der Update Server erkennt den 
neuen Client und man kann dann alle Updates für die Zielplattform freigeben,
weil in der Ansicht der “benötigten Updates” (“Updates needed by computers”)
bereits alle markiert sind, die das neue System haben möchte.&lt;/p&gt;

&lt;p&gt;Natürlich kann man auch alle Updates ungefiltert anzeigen lassen, mit 
&lt;code&gt;Ctrl + A&lt;/code&gt; alle markieren und im Kontextmenü mit &lt;code&gt;Approve...&lt;/code&gt; freigeben.&lt;/p&gt;

&lt;p&gt;Die mit &lt;code&gt;wuauclt /detectnow&lt;/code&gt; begonnene Update-Installation kann ein paar 
Iterationen brauchen, weil am Anfang mal ein neuer Update Client 
heruntergeladen wird, ehe Systemupdates usw. folgen.&lt;/p&gt;

&lt;p&gt;Das Tool &lt;code&gt;wuauclt&lt;/code&gt; hält übrigens noch ein paar andere Optionen bereit, die
man zum Konfigurieren nutzen kann:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;wuauclt /detectnow&lt;/code&gt; Startet eine Updatesuche&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;wuauclt /reportnow&lt;/code&gt; Meldet den aktuellen Updatestatus an den 
konfigurierten WSUS Dienst&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;wuauclt /updatenow&lt;/code&gt; Startet die Installation aller gefundenen fehlenden 
Updates&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;wuauclt /showsettingsdialog&lt;/code&gt; Zeigt die Einstellungen für automatische 
Updates an (also das, was man auch in den Systemsteuerungen findet)&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;wuauclt /showwindowsupdate&lt;/code&gt; Öffnet den IE mit der Windows Update Webseite&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;wuauclt /resetauthorization&lt;/code&gt; Setzten den Update-Suche zurück, damit man 
eine neue vollständige Suche initiieren kann.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;wuauclt /showoptions&lt;/code&gt; Zeigt den Update-Optionen Dialog an&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;wuauclt /showfeaturedupdates&lt;/code&gt; Zeigt die Updateliste an&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;wuauclt /showfeaturedoptindialog&lt;/code&gt; Zeigt die optionale Updateliste an&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;wuauclt /demoui&lt;/code&gt; Blendet das SysTray-Icon für Windows Updates ein, damit 
man darüber zu den anderen Update-Fenstern gelangen kann&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Hinweis: Je nach Windows Version und aktuellem Update-Status kann es sein, 
dass einige Kommandos keine Wirkung haben.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ich bin mit der WSUS-Update Methode eigentlich zufrieden, wenn man von der 
miesen Performance auf schwachbrüstiger Hardware absieht. Der Vorteil ist,
dass alle Updates zwischengespeichert werden und man ein weiteres System
dann in Windeseile aktualisieren kann, weil kein Internet-Download mehr 
notwendig ist.&lt;/p&gt;

&lt;p&gt;Wie auch immer … für mich privat zahlt sich der Server nur für Sonderfälle
wie meine Altsysteme aus, denn seitdem Microsoft für Windows 10 jedes halbe
Jahr ein gepatchtes ISO bereitstellt, muss man bei Neuinstallationen ja nicht
mehr 5 Jahre Updates nachholen.&lt;/p&gt;

&lt;p&gt;Aber wäre ich Sys-Admin in einem Unternehmen wo viele PCs aktualisiert werden
müssten, so würde der WSUS wohl zu meinem täglichen Werkzeug gehören.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>cdecl dynamisch zusammenbauen</title>
   <link href="https://www.opengate.at/blog/2021/02/cdecl/"/>
   <published>2021-02-06T12:00:00+01:00</published>
   <updated>2021-02-06T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2021/02/cdecl</id>
   <category term="devel" />
   <summary type="text">Nehmen wir mal an:


  Wir lesen zur Laufzeit die Text-Deklaration einer beliebigen C Funktion
ein. Können wir einen “generischen” Funktionsaufruf mit allen Argumenten
zur Laufzeit zusammenstellen?


Ja natürlich! Mit Assembler!
Aber das wäre zu plattformspezifisch.
Geht es auch mit reinem C Code?
</summary>
   <content type="html">&lt;p&gt;Nehmen wir mal an:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Wir lesen zur Laufzeit die Text-Deklaration einer beliebigen C Funktion
ein. Können wir einen “generischen” Funktionsaufruf mit allen Argumenten
zur Laufzeit zusammenstellen?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ja natürlich! Mit &lt;a href=&quot;https://de.wikipedia.org/wiki/Assembler_(Informatik)&quot;&gt;Assembler&lt;/a&gt;!&lt;br /&gt;
Aber das wäre zu plattformspezifisch.&lt;br /&gt;
Geht es auch mit &lt;a href=&quot;https://de.wikipedia.org/wiki/C_(Programmiersprache)&quot;&gt;reinem C&lt;/a&gt; Code?
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Egal ob leicht oder nicht, man hat nicht immer einen Assembler
parat und &lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_C%2B%2B&quot;&gt;MSVC&lt;/a&gt; erlaubt für 
64bit auch kein Inline-ASM mehr.&lt;br /&gt;
Und trotzdem wäre es doch “cool”, wenn man eine Funktion mit zur 
Übersetzungszeit unbekannter Deklaration trotzdem korrekt aufrufen könnte.&lt;/p&gt;

&lt;p&gt;Meine Erkenntnisse bisher:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Es funktioniert halbwegs, wenn man Abstriche macht und ABI-Details für 
jede Plattform separat implementiert.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;windows-32-bit&quot;&gt;Windows 32 Bit&lt;/h3&gt;

&lt;p&gt;Für &lt;a href=&quot;https://de.wikipedia.org/wiki/X86-Prozessor#Protected_und_Enhanced_Mode&quot;&gt;X86 32 bit&lt;/a&gt; 
gilt, dass unter der &lt;a href=&quot;https://de.wikipedia.org/wiki/Aufrufkonvention&quot;&gt;C-decl Aufrufkonvention&lt;/a&gt;
alle Parameter 32-bit ausgerichtet auf den Stack geschrieben werden und 
außerdem C-Strukturen auch als Ganzes auf den Stack gelegt werden, dann 
kann man jede Funktion in den Prototyp…&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;union&lt;/span&gt; x86_stack_args
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;        &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;*        dummy;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;        &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt;        data[&lt;span style=&quot;color:#00D&quot;&gt;1024&lt;/span&gt;];
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;}
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;typedef&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;* (*generic_x86_func_t)(&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;union&lt;/span&gt; x86_stack_args args);
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;…casten, in dem die Parameter als Datenblock übergeben werden, wo man die
Werte der richtigen Parameter einfach an die richtige Stelle schreibt.&lt;br /&gt;
Ist die Größe aller Ziel-Stack-Elemente kleiner als der Block, müsste der
Aufruf korrekt funktionieren, weil der C-Compiler alles erforderliche
für uns macht.&lt;/p&gt;

&lt;p&gt;Beim Return-Value müsste man noch zwischen &lt;code&gt;&amp;lt;= 32 bit&lt;/code&gt; und &lt;code&gt;&amp;gt; 32 bit&lt;/code&gt; 
unterscheiden, aber grundsätzlich wäre es das bereits.&lt;/p&gt;

&lt;h3 id=&quot;windows-64-bit&quot;&gt;Windows 64 Bit&lt;/h3&gt;

&lt;p&gt;Für &lt;a href=&quot;https://de.wikipedia.org/wiki/X86-Prozessor#64_Bit&quot;&gt;X64&lt;/a&gt; nutzt Microsoft
teils Register und danach den Stack, der ebenso speziell ausgerichtet sein 
muss.&lt;br /&gt;
Mein Trick wäre es dann, die generische Funktion mit extrem vielen &lt;code&gt;void*&lt;/code&gt; 
Parametern auszustatten und deren Inhalt entsprechend dem Zielfunktionslayout 
zu befüllen.&lt;br /&gt;
Das ist zwar viel lästiger als für 32 bit, aber geht auch.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;typedef&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;* (*generic_x64_func_t)(
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;*, &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;*, &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;*, &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;*, &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;*, &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;*, &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;*, &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;*,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;*, &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;*, &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;*, &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;*, &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;*, &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;*, &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;*, &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;*,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;*, &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;*, &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;*, &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;*, &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;*, &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;*, &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;*, &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;*,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;*, &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;*, &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;*, &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;*, &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;*, &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;*, &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;*, &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;*,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;);
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Egal, ob man einen Pointer, einen &lt;code&gt;char&lt;/code&gt;, &lt;code&gt;long&lt;/code&gt; oder &lt;code&gt;short&lt;/code&gt; übergibt, 
auf dem Stack ist alles an 64 Bits (also = &lt;code&gt;void*&lt;/code&gt;) ausgerichtet.&lt;/p&gt;

&lt;p&gt;Natürlich belegt man hier viel mehr Stack als notwendig ist, aber nachdem der
Aufrufer den Stack zurücksetzt, kann uns das egal sein.&lt;/p&gt;

&lt;p&gt;Problematisch sind bei X64 &lt;code&gt;double&lt;/code&gt; und &lt;code&gt;float&lt;/code&gt; Typen, die in 
Multimedia-Registern übergeben werden und von den “normalen” Registern 
entkoppelt sind. Der &lt;code&gt;void*&lt;/code&gt; Trick funktioniert also nur bei allen Zeiger-
und Integer-Typen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Die meisten Funktionen bleiben unter 10 Parametern und nutzen nur 
CPU-Wort-breite Typen, alles andere wird meist auf Pointer abgebildet.&lt;/p&gt;

&lt;p&gt;Nur die teuflischen C-&lt;code&gt;struct&lt;/code&gt;s, die als Wert übergeben werden sprengen hier
womöglich den Rahmen. Wenn man also auf diese Spezialfälle verzichtet (die 
ja auch nur sehr selten als öffentliche C-API wo vorkommen), dann kann man 
mit etwas Glück und Wohlwollen des Compilers ohne Assembler solche Hacks 
anwenden.&lt;/p&gt;

&lt;p&gt;Ob das nun unter &lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt;
und unter nicht X86-Plattformen wie z.B. 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Arm-Architektur&quot;&gt;ARM&lt;/a&gt; auch noch geht … 
Tja, das sollte ich bei Gelegenheit mal untersuchen.&lt;/p&gt;

&lt;p&gt;Das ist aber auf jeden Fall ein spannendes Thema.
Im GATE Framework ist dieses Beispiel für weitere Experimente nun in
&lt;code&gt;gate/functions.h&lt;/code&gt; verewigt.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Wie man unabsichtlich JPEGs vernudelt</title>
   <link href="https://www.opengate.at/blog/2021/01/skip-jpeg/"/>
   <published>2021-01-31T12:00:00+01:00</published>
   <updated>2021-01-31T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2021/01/skip-jpeg</id>
   <category term="devel" /><category term="projects" />
   <summary type="text">
  Ups! Ein 13 Jahre alter Bug, den ich seither immer mitschleppe.


Tja, aber nachdem mich bisher niemand angerufen und “nach Support” gefragt 
hat, wird der wohl bei meinen früheren “Kunden” nie aufgetreten sein
… oder?

Es geht um die liebe libJPEG und 
ihren Callback zum Überspringen von Datenblöcken.
</summary>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;Ups! Ein 13 Jahre alter Bug, den ich seither immer mitschleppe.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Tja, aber nachdem mich bisher niemand angerufen und “nach Support” gefragt 
hat, wird der wohl bei meinen früheren “Kunden” nie aufgetreten sein
… oder?&lt;/p&gt;

&lt;p&gt;Es geht um die liebe &lt;a href=&quot;https://de.wikipedia.org/wiki/Libjpeg&quot;&gt;libJPEG&lt;/a&gt; und 
ihren Callback zum Überspringen von Datenblöcken.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Ich glaube Anfang 2008 habe ich erstmals mit der &lt;code&gt;libJpeg&lt;/code&gt; gearbeitet und mir
damals eine Experimentierumgebung zu Hause eingerichtet, von der ich das
Ergebnis immer in Projekte wegkopiert habe.&lt;/p&gt;

&lt;p&gt;Dabei nutze ich nicht die Standard-Funktionen, die nur auf Dateibasis 
arbeiten, sondern registriere Callbacks für das Lesen und Schreiben von
Daten, in denen ich auch eigene Streams umleiten kann.&lt;/p&gt;

&lt;p&gt;Und da ist mir offenbar eine Funktion unter den Tisch gefallen.&lt;br /&gt;
Sie heißt &lt;code&gt;skip_input_data&lt;/code&gt; und wird vom JPEG-Decoder aufgerufen um 
uninteressante Datenblöcke zu überspringen.&lt;br /&gt;
Besteht ein JPEG nur aus Bilddaten, kommt diese Funktion kaum zum Zug,
doch heutige Digitalkameras schreiben hunderte Kilobytes an Zusatzinfos
in den Datenstrom. Geokoordinaten, Thumbnails und anderes Gewäsch wird 
mit unterschiedlichsten Zusatzheadern eingebaut.&lt;/p&gt;

&lt;p&gt;libJPEG fängt mit diesen Daten nichts an und überspringt sie einfach 
um zu den richtigen Bilddaten zu kommen. Und genau dann wird 
&lt;code&gt;skip_input_data&lt;/code&gt; aufgerufen.&lt;/p&gt;

&lt;p&gt;Und ich dachte bisher, dass diese Funktion nur eine optionale Optimierung 
sei und habe sie leer implementiert.&lt;br /&gt;
&lt;em&gt;Tja, das war aber so was von falsch!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Die Standard-Implementierung sieht nämlich so aus:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;static&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt; skip_input_data(j_decompress_ptr cinfo, &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;long&lt;/span&gt; num_bytes)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;struct&lt;/span&gt; jpeg_source_mgr * src = cinfo-&amp;gt;src;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  size_t nbytes;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt; (num_bytes &amp;gt; &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;) 
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;  {
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;    nbytes = (size_t) num_bytes;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;while&lt;/span&gt; (nbytes &amp;gt; src-&amp;gt;bytes_in_buffer) 
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;        {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;      nbytes -= src-&amp;gt;bytes_in_buffer;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;      (&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;) (*src-&amp;gt;fill_input_buffer) (cinfo);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;    }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;    src-&amp;gt;next_input_byte += nbytes;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;    src-&amp;gt;bytes_in_buffer -= nbytes;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;  }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Es werden so lange Daten nachgeladen, bis die zu überspringende Menge im 
zuletzt geladenen Block angekommen ist. Dort wird dann nur noch der Pointer
weiter gerückt die Anzahl der verfügbaren Bytes reduziert.&lt;/p&gt;

&lt;p&gt;Ohne diesen Codebatzen ruckelt der Decoder offenbar selbst weiter. Manchmal
klappt das, oft aber nicht.&lt;br /&gt;
Hätte ich nicht ein grafisches Demoprojekt im GATE Framework gestartet, das
Bilder laden und anzeigen kann, wäre mir das auch weiter nicht aufgefallen.&lt;br /&gt;
Denn das Tool konnte kein einziges Bild meiner Smartphone-Kamera lesen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Nun … echt peinlich so etwas! Denn diesen Bug habe ich in mehrere kommerzielle 
Produkte in den letzten 12 Jahren hineinkopiert.&lt;br /&gt;
Doch zum Glück war das Lesen von JPEGs in keinem einzigen betriebsrelevant.
Es wurden immer nur JPEGs erzeugt und diese eventuell später neu geladen um 
noch was darüber zu zeichnen.&lt;/p&gt;

&lt;p&gt;Da kamen also nie Metadaten vor, die den Sprungmarken-Bug auslösen konnten.&lt;/p&gt;

&lt;p&gt;Hmm … ich frage mich, wie viele andere unentdeckte Bugs ich sonst noch wo
verbaut habe… und … wie viele andere Programmierkollegen ähnliche
Verschreibser in Ihren Lebensläufen haben.&lt;/p&gt;

&lt;p&gt;Eines steht für mich aber fest: Mit dem GATE Projekt komme ich endlich dazu
solche Langzeit-Bugs aus meinen Codebases und meinem Hirn zu vertreiben.
Eine solche Reinigungskur kann ich daher nur weiterempfehlen.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>PIPO Windows-ARM-Tablet</title>
   <link href="https://www.opengate.at/blog/2021/01/pipo-tablet/"/>
   <published>2021-01-30T12:00:00+01:00</published>
   <updated>2021-01-30T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2021/01/pipo-tablet</id>
   <category term="hardware" />
   <summary type="text">Windows-on-ARM 
… war für mich bisher ein Mysterium. Zwar konnte ich für diese Plattform
schon lange Kompilate erstellen, aber ich hatte keine Hardware um sie darauf 
auszuführen.

Und so ein Microsoft-Surface irgendwas um 1000 Euro ist mir für einen simplen
Test viel zu teuer.

Doch unter der Marke PIPO W12 gibt 
es eines der letzten ARM Tablets unter 500 Euro und ein solches nenne ich 
nun “mein Eigen”.
</summary>
   <content type="html">&lt;p&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/arm/&quot;&gt;Windows-on-ARM&lt;/a&gt; 
… war für mich bisher ein Mysterium. Zwar konnte ich für diese Plattform
schon lange Kompilate erstellen, aber ich hatte keine Hardware um sie darauf 
auszuführen.&lt;/p&gt;

&lt;p&gt;Und so ein Microsoft-Surface irgendwas um 1000 Euro ist mir für einen simplen
Test viel zu teuer.&lt;/p&gt;

&lt;p&gt;Doch unter der Marke &lt;a href=&quot;http://www.pipo.com/product.php?id=296&quot;&gt;PIPO W12&lt;/a&gt; gibt 
es eines der letzten ARM Tablets unter 500 Euro und ein solches nenne ich 
nun “mein Eigen”.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;wie-was-und-woher&quot;&gt;Wie, was und woher?&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/pipo-arm-tablet.jpg&quot; alt=&quot;PIPO ARM Tablet&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.aliexpress.com/&quot;&gt;Aliexpress.com&lt;/a&gt; listete das Gerät um ca. 
370 Euro + 20 Euro Versand. Unsere Zollbehörde hat dann noch 95 Euro 
draufgeknallt, aber das war es dann auch.&lt;/p&gt;

&lt;p&gt;Das Tablet wurde 2019 auf den Markt gebracht und nachdem Lenovo und andere
Hersteller ihre Win-ARM-Tablets leider wieder vom Markt genommen haben, war
dieses Modell neben Microsofts teurer Surface-Schiene das einzige, was ich
aktuell finden konnte.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/pipo-arm-tablet-1.jpg&quot; alt=&quot;PIPO ARM Tablet Size&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Mit 8 GB RAM rechnet der &lt;a href=&quot;https://de.wikipedia.org/wiki/Snapdragon_(Prozessor)&quot;&gt;Snapdrogon&lt;/a&gt;
850 in dem A4 großen Tablet brav vor sich hin, taktet seine 8 Kerne nur auf 
etwas über 1 GHz im Leerlauf.
Wenn er aber ausgelastet wird, geht er schon mal gerne auf knapp 3 GHz hoch.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/pipo-arm-tablet-stats.png&quot; alt=&quot;PIPO ARM Tablet Stats&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Da merke ich auch den krassen Unterschied in Sachen Reaktion im Gegensatz zu
meinem &lt;a href=&quot;https://de.wikipedia.org/wiki/Intel_Atom&quot;&gt;x86-Atom-x5&lt;/a&gt; Tablet, das 
immer nur langsam in die Gänge kommt. Und die 2880x1920 Pixel sind ein 
angenehmes Erlebnis auf dem 12 Zoll breiten Touchdisplay.&lt;/p&gt;

&lt;p&gt;Mit der 230 GB SSD (250 GB mit der üblichen falschen Rechnung) konnte ich mein
C-Laufwerk auf 130 GB verkleinern, damit die Daten eine separate Partition 
bekommen.&lt;/p&gt;

&lt;p&gt;Auf der Seite findet man den bei Tablets üblichen kleinen Einschub für 
eine &lt;a href=&quot;https://de.wikipedia.org/wiki/SIM-Karte&quot;&gt;SIM-Karte&lt;/a&gt; und eine 
&lt;a href=&quot;https://de.wikipedia.org/wiki/MicroSD&quot;&gt;Mikro-SD-Karte&lt;/a&gt;. Man braucht hier 
eine Nadel oder sehr feine Pinzette um das kleine Plastikgerüst aus dem 
Gerät herauszuziehen.&lt;br /&gt;
Das ist immer wieder eine Frickelei und für das Auflegen und 
wiedereinschieben der Karten braucht man eine ruhige Hand.&lt;br /&gt;
Aber bei solch dünnen Modellen geht das eben nicht anders.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/pipo-arm-tablet-3.jpg&quot; alt=&quot;PIPO ARM Tablet Slot&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Die magnetisch “ansaugbare” Tastatur ist US-basiert … gut, das wird bei mir 
wieder ein paar Tastenverwechslungen führen, wenn ich Sonderzeichen und 
Klammern brauche.&lt;br /&gt;
Lästig ist nur, dass die erste Taste Links unten &lt;code&gt;FN&lt;/code&gt; und nicht &lt;code&gt;Ctrl&lt;/code&gt; ist.
Dieses mich störende Design haben leider auch viele Laptops.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/pipo-arm-tablet-2.jpg&quot; alt=&quot;PIPO ARM Tablet Keyboard&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;windows-on-arm&quot;&gt;Windows on ARM&lt;/h3&gt;

&lt;p&gt;Endlich! Und es geilt mich schon ein bisschen auf, mal so eine exotische 
Hardware in den Händen halten zu dürfen. Windows sieht fast so wie immer aus,
außer, dass wir neben &lt;code&gt;Program Files (x86)&lt;/code&gt; auch noch &lt;code&gt;Program Files (arm)&lt;/code&gt;
auf &lt;code&gt;c:&lt;/code&gt; haben. Denn die ARM64 Plattform (&lt;code&gt;C:\Program Files&lt;/code&gt;) ist einerseits 
zu &lt;code&gt;ARM32&lt;/code&gt; kompatibel so wie &lt;code&gt;X64&lt;/code&gt; mit &lt;code&gt;X86&lt;/code&gt; umgehen konnte, und parallel
können auch X86 Windows Programme per Emulation ausgeführt werden.
Das sieht man auch am neuen &lt;code&gt;SysArm32&lt;/code&gt;, welches das bekannte &lt;code&gt;SysWOW64&lt;/code&gt; 
in &lt;code&gt;c:\Windows\&lt;/code&gt; ergänzt.&lt;/p&gt;

&lt;p&gt;Genau dieses Feature war es wohl, was die ersten Windows on ARM Geräte 
scheitern ließ, weil sie es nicht unterstützten. Denn als Microsoft mit 
Windows 8 ihren ersten ARM Gehversuche machte, war X86 eben nativ nicht 
ausführbar und man gestattete nur native ARM32 Metro-Apps, oder 
plattformunabhängige &lt;a href=&quot;https://de.wikipedia.org/wiki/.NET&quot;&gt;dotNet&lt;/a&gt; Software.&lt;/p&gt;

&lt;p&gt;Doch nun kann ich sogar das aktuelle &lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_Studio&quot;&gt;Visual Studio 2019&lt;/a&gt;
vollständig auf meinem ARM Tablet installieren und ausführen, obwohl dieses 
nur für die X86 Plattform bereitgestellt wird.&lt;/p&gt;

&lt;p&gt;Und das ist &lt;strong&gt;ECHT GEIL !!&lt;/strong&gt;&lt;/p&gt;

&lt;h3 id=&quot;arm64-debugging&quot;&gt;ARM64 Debugging&lt;/h3&gt;

&lt;p&gt;Studio, &lt;a href=&quot;https://de.wikipedia.org/wiki/CMake&quot;&gt;CMake&lt;/a&gt;, &lt;a href=&quot;https://de.wikipedia.org/wiki/Git&quot;&gt;Git&lt;/a&gt;
und der GATE Source Code kamen also genau so auf das ARM Tablet wie auf einen 
normalen PC und dann startete ich mit CMake die ARM64 Projektgenerierung. 
Alles lief genau so wie unter X86.&lt;br /&gt;
Dann kompilierte ich das gesamte GATE Projekt einmal durch … ebenso alles
ohne Probleme unter ARM64.&lt;/p&gt;

&lt;p&gt;Doch das Starten der Debug-EXEn schlug fehl … weil es keinen Debugger gab.&lt;/p&gt;

&lt;p&gt;Microsoft hatte nie eingeplant, dass jemand direkt auf einem ARM Gerät 
entwickelt und empfiehlt stets nur Remote-Debugging.&lt;/p&gt;

&lt;p&gt;Nun gut, auch das geht. Man installiert die Visual Studio Debugging Tools 
für ARM64 und konfiguriert Visual Studio für Remote-Debugging auf &lt;code&gt;localhost&lt;/code&gt;.
Dann muss man noch die Pfade der kompilierten Programme eintragen und …&lt;/p&gt;

&lt;p&gt;WOW, alle GATE-UI Tools fahren hoch, laufen nativ auf ARM64 und können Stück
für Stück durchschritten werden.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Also, ich bin echt beeindruckt. Meine bisherigen Sparefroh-200-Euro-Tablets
sind allesamt nicht Visual-Studio-tauglich. Doch das verhältnismäßig günstige 
PIPO Tablet schafft es problemlos mit VS umzugehen trotz der zusätzlichen 
Emulationsschicht.&lt;/p&gt;

&lt;p&gt;Es gibt zwar gelegentlich mal ein paar Haken beim Öffnen eines Projektes oder
beim Starten von Build-Jobs, aber das habe ich auf meinem 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Intel-Core-i-Serie&quot;&gt;Core-i3&lt;/a&gt; ebenso.&lt;/p&gt;

&lt;p&gt;Fast bin ich ein bisschen traurig, weil alles so perfekt beim ersten Anlauf
funktioniert hat. Ich brauche gar nichts großartig anpassen.&lt;br /&gt;
Hier zeigt sich also, dass die gesamt Windows API vollständig auf ARM 
vorhanden und (so weit ich es prüfen kann) verhaltensgleich ist.&lt;/p&gt;

&lt;p&gt;Mit diesem neuen Erkenntnisstand möchte ich einen Aufruf starten:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ihr Hersteller da draußen! Baut endlich ganze ARM basierte PCs!
Denn endlich laufen Windows und alle sein Goodies darauf und 
je mehr native ARM Apps es gibt, um so leistungseffizienter wird die 
neue Hardware werden.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Denn wenn ARM Chips eines gut können, dann ist das Strom sparen und 
zusammen mit der aufgeräumteren CPU-Architektur gibt es vielleicht noch ganz
andere Potentiale zu entdecken, die unsere Zukunft positiv mitgestalten
können.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Mit OpenSCAD zum 3D Modell</title>
   <link href="https://www.opengate.at/blog/2021/01/open-scad/"/>
   <published>2021-01-24T12:00:00+01:00</published>
   <updated>2021-01-24T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2021/01/open-scad</id>
   <category term="software" />
   <summary type="text">Meine gestern zusammengebaute DIY-Smartwatch 
braucht ein Gehäuse. Aber:


  Verdammt! Auf Thingiverse.com gibt es kein 
3D Modell dafür!


Kein Problem … dann machen wir es eben selbst.
</summary>
   <content type="html">&lt;p&gt;Meine &lt;a href=&quot;/blog/2021/01/esp8266-watch/&quot;&gt;gestern zusammengebaute DIY-Smartwatch&lt;/a&gt; 
braucht ein Gehäuse. Aber:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Verdammt! Auf &lt;a href=&quot;http://www.thingiverse.com/&quot;&gt;Thingiverse.com&lt;/a&gt; gibt es kein 
3D Modell dafür!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Kein Problem … dann machen wir es eben selbst.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Das ist offen gesagt das erste Mal, dass ich wirklich ein Gehäuse brauche
und im Netz (noch) keines gefunden habe.&lt;br /&gt;
Doch zum Glück war bei diversen “Empfehlungen” die Software 
&lt;a href=&quot;https://www.openscad.org/&quot;&gt;OpenSCAD&lt;/a&gt; dabei, die gegenüber ihren Konkurrenten 
wie FreeCAD und weiß der Geier wie die anderen heißen nur 20 MB groß war, 
während die anderen bei 200 MB anfingen.&lt;/p&gt;

&lt;p&gt;Als Minimalist dachte ich zuerst “Hey Cool” um danach gleich zu zweifeln,
weil: Wenn es so klein ist, kann es vermutlich nichts.&lt;/p&gt;

&lt;p&gt;Aber für meine Zwecke stellte sich dieses Stück Software als ideal dar.
Es baut nämlich auf einer Script-Sprache auf, mit der man sein Modell
aus geometrischen Figuren zusammensetzen kann.&lt;/p&gt;

&lt;p&gt;Und das ist eine Form, in der ich leicht denken kann. 
Es ist wie damals in der Schule, als man mit Lineal und Zirkel bewaffnet
Quader und Pyramiden vermessen und die fehlenden Punkte ausrechnen musste.&lt;/p&gt;

&lt;h3 id=&quot;wie-man-eine-offene-schachtel-baut&quot;&gt;Wie man eine offene Schachtel baut&lt;/h3&gt;

&lt;p&gt;Bildlich gesprochen: Man erzeugt einen massiven Quader und subtrahiert 
einen etwas kleineren Quader aus ihm heraus, sodass genau die Ränder und 
der Boden der Schachtel übrig bleiben.&lt;/p&gt;

&lt;p&gt;Das ist es … mehr kann ich bis dato auch nicht in &lt;code&gt;OpenSCAD&lt;/code&gt; und 
trotzdem reicht das voll und ganz aus.&lt;/p&gt;

&lt;p&gt;Nachdem laut Online-Hilfe &lt;code&gt;cube([length, width, height])&lt;/code&gt; einen Quader 
erzeugt, braucht man noch eine “Funktion” für das “rausschneiden” und die
heißt &lt;code&gt;difference()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Meine Smartwatch ist etwa 46x38x16 Millimeter groß. Soll die Schachtel eine
Dicke von 1mm haben, lautet das OpenSCAD Script:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;difference() {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;  translate([0,0,0]) cube([48, 40, 17]); //shell
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  translate([1,1,1]) cube([46, 38, 16]); //inner space
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Wir bauen einen äußeren Quader angefangen bei Koordinate (0,0,0) und
dann einen zweiten Quader startend bei (1,1,1) der in allen Dimensionen
um 2mm kleiner ist außer bei der Höhe, denn dort soll ja oben offen bleiben.&lt;/p&gt;

&lt;p&gt;Es kann nicht schaden bei offenen Stellen den zweiten Quader etwas größer 
zu dimensionieren, damit er wirklich “ins Freie” durchsticht. Endet das 
subtrahierte Objekt nämlich genau auf der Grenzfläche, kann am Ende dennoch
eine hauchdünne Schicht herauskommen, die gedruckt wird.&lt;/p&gt;

&lt;h3 id=&quot;modell-wie-steinmetz-herausarbeiten&quot;&gt;Modell wie Steinmetz herausarbeiten&lt;/h3&gt;

&lt;p&gt;Und genau das gleiche macht man für alle anderen Öffnungen. In meinem Fall
sind das das Display, der On/Off Schalter, diverse Buttons und LEDs.
Man misst mit dem Lineal, wie weit die Öffnung von der Ursprungsecke entfernt
ist und fügt weitere &lt;code&gt;translate&lt;/code&gt; und &lt;code&gt;cube&lt;/code&gt; Zeilen an.
&lt;code&gt;difference()&lt;/code&gt; behandelt das erste Objekt wie einen rohren Felsblock 
und alle weiteren Objekte werden aus diesem Block herausgeschlagen.&lt;/p&gt;

&lt;p&gt;Mit weiteren Objekt-Bezeichnern wie &lt;code&gt;cylinder&lt;/code&gt;lassen sich auch runde Elemente
herausstanzen.
Und so kam am Ende mein Entwurf für ein primitives Smartwatch Gehäuse heraus:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;difference() {
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;  translate([0,0,0]) cube([48, 41, 17]); //shell
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  translate([1,1,1]) cube([46, 39, 17]); //inner space
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  translate([8.5,2.5,-1]) cube([24.5, 36, 10]);//display 
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;  translate([32,12.5,-1]) cube([3.5, 16, 10]);//display 
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  translate([2,17,-1]) cube([6, 7, 3]);  //top LED
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;  translate([8.5,-1,2.5]) cube([16, 10, 5]); //wheel
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  translate([30,-1,2.5]) cube([7, 5, 3]);  //on/off
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;  translate([20,-1,12]) cube([9, 5, 6]); //usb
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;  translate([11.5,37,3]) cube([7, 5, 4]);  //button
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;  translate([11.5,37,11]) cube([7, 5, 4]); //button
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;  translate([21,37,3]) cube([6, 5, 6]);  //side LED
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;  translate([29.5,37,3]) cube([7, 5, 4]);  //button
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;  translate([-1, 7, 12]) cube([6, 27, 10]); //top band
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;  translate([45, 7, 12]) cube([6, 27, 10]); //bottom band
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n21&quot; name=&quot;n21&quot;&gt;21&lt;/a&gt;&lt;/span&gt;  translate([4, 4, -1]) cylinder(5, 1.7, 1.7); //screw
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n22&quot; name=&quot;n22&quot;&gt;22&lt;/a&gt;&lt;/span&gt;  translate([44, 4, -1]) cylinder(5, 1.7, 1.7); //screw
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n23&quot; name=&quot;n23&quot;&gt;23&lt;/a&gt;&lt;/span&gt;  translate([4, 37, -1]) cylinder(5, 1.7, 1.7); //screw
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n24&quot; name=&quot;n24&quot;&gt;24&lt;/a&gt;&lt;/span&gt;  translate([44, 37, -1]) cylinder(5, 1.7, 1.7); //screw
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n25&quot; name=&quot;n25&quot;&gt;25&lt;/a&gt;&lt;/span&gt;};
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Das Teil ist einfach nur primitiv, man könnte jetzt viele Zahlen durch
Variablen und Rechnungen ersetzen, doch für mich war das direkte verfüttern
der Koordinaten ausreichend, um nach 15 Minuten den ersten Entwurf fertig
zu haben.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/8266-watch5.jpg&quot; alt=&quot;DIY 8266 Smartwatch&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;nacharbeit-und-testdruck&quot;&gt;Nacharbeit und Testdruck&lt;/h3&gt;

&lt;p&gt;Es brauchte letztendlich dann doch mehrere Anläufe, 
bis ein vernünftiges Ergebnis fertig war.&lt;br /&gt;
Einerseits hatte ich auf einige Öffnungen vergessen, andererseits habe
ich gelernt, dass ein 1 Millimeter mehr Freiraum extrem helfen kann, 
weil es ansonsten meist zu eng ist, um das Gerät unbeschadet ins Gehäuse 
hineinzubekommen.&lt;/p&gt;

&lt;p&gt;Und während dieser Größentests dabei ist mir leider auch das Display 
etwas gesplittert.&lt;/p&gt;

&lt;p&gt;Doch wenn man die Druckzeiten (etwa 40 Minuten pro Versuch) wegrechnet, 
kann man sagen, dass ich maximal eine Stunde für das Modell gebraucht 
habe, inklusive aller Einbauvorgänge und Scriptkorrekturen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;Mann! Das hätte man mir früher zeigen sollen!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ich dachte immer, dass Modelle zu erstellen höhere Magie sei und man Tage 
damit verbringt, Linien an die richtige Stelle zu setzen. Und überhaupt 
glaubte ich, dass man alles mit der Maus Millimeter für Millimeter 
zusammenklicken muss.&lt;/p&gt;

&lt;p&gt;Aber die Idee mit den Koordinaten-Scripts ist echt super.
Mag sein, dass man komplexere Sachen damit nicht so gut lösen kann, aber für
meinen Bedarf an &lt;a href=&quot;https://de.wikipedia.org/wiki/Mikrocontroller&quot;&gt;MCU&lt;/a&gt; 
Gehäusen ist OpenSCAD perfekt.&lt;br /&gt;
Denn da brauche ich meist nur Quader mit Schalter-Löchern.&lt;/p&gt;

&lt;p&gt;Das heißt dann, dass ich in Zukunft nicht mehr “ähnliche” Gehäuse drucken
muss um sie danach zurecht zu schleifen, sondern ich kann an den nötigen
Stellen gleich das Modell patchen.&lt;/p&gt;

&lt;p&gt;Also 10 Sterne und Daumen hoch für dieses kostenlose und einfache Tool.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>ESP8266 als fürs Handgelenk</title>
   <link href="https://www.opengate.at/blog/2021/01/esp8266-watch/"/>
   <published>2021-01-23T12:00:00+01:00</published>
   <updated>2021-01-23T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2021/01/esp8266-watch</id>
   <category term="hardware" />
   <summary type="text">Eigentlich sind die ESP8266 Chips durch 
ESP32 und andere abgelöst. Das 
bedeutet aber auch, dass der “billigste” IOT
WLAN Mikrocontroller nun noch günstiger zu haben ist und in weiteren 
Halbfertigprodukten verbaut wird.

So auch in einem Nachbau diverser DIY-Smartwatches, wo man bereits für 15-20
Euro ein Modell aus Fernost abgreifen kann.
</summary>
   <content type="html">&lt;p&gt;Eigentlich sind die &lt;a href=&quot;https://de.wikipedia.org/wiki/ESP8266&quot;&gt;ESP8266&lt;/a&gt; Chips durch 
&lt;a href=&quot;https://de.wikipedia.org/wiki/ESP32&quot;&gt;ESP32&lt;/a&gt; und andere abgelöst. Das 
bedeutet aber auch, dass der “billigste” &lt;a href=&quot;https://de.wikipedia.org/wiki/Internet_der_Dinge&quot;&gt;IOT&lt;/a&gt;
WLAN Mikrocontroller nun noch günstiger zu haben ist und in weiteren 
Halbfertigprodukten verbaut wird.&lt;/p&gt;

&lt;p&gt;So auch in einem Nachbau diverser DIY-Smartwatches, wo man bereits für 15-20
Euro ein Modell aus Fernost abgreifen kann.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Unterschiedliche Shops auf &lt;a href=&quot;https://www.aliexpress.com/&quot;&gt;aliexpress.com&lt;/a&gt; haben
eine ESP8266 “Smart Watch”, “Wearable” oder “portable Development Board” im 
Angebot.&lt;br /&gt;
Tatsächlich wird mit dem Feature &lt;a href=&quot;https://de.wikipedia.org/wiki/Wi-Fi-Deauthentication-Angriff&quot;&gt;Deauther&lt;/a&gt;
geworben … was ich aber doch für recht dreist halte. Denn die 
vorinstallierte Software lässt einen WLANs abscannen und die 
“De-Autorisierungs-Sequenz” senden, womit klassische WLAN Router dann die 
Verbindung zu den Clients kappen. Damit ist der WLAN-Betrieb dann für einige 
Zeit gestört.&lt;/p&gt;

&lt;p&gt;Wie auch immer, aus dieser bösen Hacker-Hardware kann man ja auch andere
Dinge machen, und von daher musste ich so ein Teil auf die Bestellliste setzen.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/esp8266-watch1.jpg&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Das Gerät besteht aus zwei Leiterplatten, die mit Stiftschrauben verbunden
sind. Oben ist ein 128x64 Pixel &lt;a href=&quot;https://de.wikipedia.org/wiki/Organische_Leuchtdiode&quot;&gt;OLED&lt;/a&gt;
Display draufgeklebt und mittig darüber eine RGB-LED. Im Hohlraum zwischen den 
beiden Platinen ist ein 500mA &lt;a href=&quot;https://de.wikipedia.org/wiki/Lithium-Polymer-Akkumulator&quot;&gt;LiPo Akku&lt;/a&gt;
eingeklemmt und ein Flachbandkabel verbindet das obige Display mit der 
unteren Platine.
An der Seite befinden sich links 3 Druckknöpfe (der untere als Reset)
und eine weiße LED.
Rechts haben wir einen Micro-USB-Port zum Laden, einen On/Off Schalter
und eine Art “halbes Rad”, was aber in Wahrheit auch nur 3 Druckknüpfe sind.
Man zieht das Rad nach oben oder unten um die äußeren Taster zu drücken oder
drückt das Rad hinein um den dritten Druckpunkt auszulösen.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/esp8266-watch2.jpg&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Zerlegt man die Smartwatch (indem man einfach die 4 Schrauben entweder oben 
oder unten entfernt, werden Innereien sichtbar.&lt;br /&gt;
An der Unterseite der Deckplatine erkennt man dann, dass 6 Pins nach oben 
geführt werden, nämlich von links nach rechts an der Oberseite:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;(IO0 - GND - 3.3V)&lt;/code&gt; und &lt;code&gt;(IO2 - TX - RX)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Man kann also oben noch Stecker anlöten und vermutlich auch die 
Programmierung auf diese Weise “von außen” durchführen.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/esp8266-watch3.jpg&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;vorsicht-display-ist-sehr-zerbrechlich&quot;&gt;Vorsicht! Display ist sehr zerbrechlich!&lt;/h3&gt;

&lt;p&gt;Hmm, gut dass ich mir dachte: Das Teil ist so billig, ich bestelle gleich
zwei Stück. Und das ist bei einem Tollpatsch wie mir auch dringend notwendig.
Denn ich wollte mir eine kleine Coverbox per 3D Drucker anfertigen und als 
mein Prototyp fertig war, passte der “fast genau”. … Nur leider hatte ich 
beim Display neben der Anzeigefläche auch die darunter angebrachte 
Zuleitung vergessen und den Ausschnitt zu klein gestaltet.&lt;/p&gt;

&lt;p&gt;Beim Hineindrücken der Platine splitterte sofort das untere Eck des Displays 
ab, wo offenbar die Zu/Ableitung der ersten Pixelzeilen verlegt war.&lt;/p&gt;

&lt;p&gt;Tja, nun sind die ersten 12 Zeilen “interlaced” … es funktioniert nur
jede zweite … oder anders gesagt, die ersten 1.5 Textzeilen sind nur 
halbstark ausgeführt.&lt;/p&gt;

&lt;p&gt;Das Display ist wie alle OLED Bauteile extrem druckempfindlich.&lt;br /&gt;
Die Uhr im Alltag zu tragen halte ich für unmöglich, man würde sie
wahrscheinlich recht bald unabsichtlich zerstören.&lt;br /&gt;
Natürlich könnte man sich jetzt etwas mit Schutzglas oder Folien überlegen, 
aber dafür habe ich leider nicht ausreichend Zeit.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Von der Fragilität mal abgesehen, finde ich solche Spielereien aber echt 
lustig. Vor allem inspirieren sie, wie man mit zwei simplen Platinen ein 
schlichtes Alltagsgerät bauen könnte.&lt;br /&gt;
Ich überlege vor allem, ob man mit einem &lt;a href=&quot;/blog/2019/01/nokia-5110/&quot;&gt;Nokia 5100 Display&lt;/a&gt;, 
das weit stabiler (und auch stromsparender) sein sollte, nicht eine viel 
bessere Smartwatch bauen könnte, die ganz nebenbei mit vorkonfigurierten 
WLANs die Uhrzeit abholt und gesammelte Daten hochlädt.&lt;/p&gt;

&lt;p&gt;Von daher trotzdem ein Daumen hoch von mir … auch wenn ich mit dem 
ersten Modell wegen des gesplitterten Displays Abstriche hatte.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>FFP2 - So wird man verarscht</title>
   <link href="https://www.opengate.at/blog/2021/01/corona-ffp2/"/>
   <published>2021-01-22T12:00:00+01:00</published>
   <updated>2021-01-22T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2021/01/corona-ffp2</id>
   <category term="general" />
   <summary type="text">Also … ich weiß ja nicht, was ich nun davon halten soll …

Die österreichische Bundes-Negierung verordnet, dass wir ohne 
FFP2 Atemschutzmasken 
nicht mehr raus oder Bus fahren dürfen, aber erhalten kann man die neueste 
Corona
Bekämpfungsmaßnahme nicht.
</summary>
   <content type="html">&lt;p&gt;Also … ich weiß ja nicht, was ich nun davon halten soll …&lt;/p&gt;

&lt;p&gt;Die österreichische Bundes-Negierung verordnet, dass wir ohne 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Atemschutzmaske&quot;&gt;FFP2 Atemschutzmasken&lt;/a&gt; 
nicht mehr raus oder Bus fahren dürfen, aber erhalten kann man die neueste 
&lt;a href=&quot;https://de.wikipedia.org/wiki/COVID-19-Pandemie&quot;&gt;Corona&lt;/a&gt;
Bekämpfungsmaßnahme nicht.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Man sagte uns über alle Medien, dass die Masken im Handel zum 
Selbstkostenpreis um 59 Cent käuflich zu erwerben sind, während die 
Hochrisikogruppe (Menschen im Alter über 60 Jahre) ein Set zugesendet bekommt.&lt;/p&gt;

&lt;p&gt;Seit gestern laufe ich nach der Arbeit alle Geschäfte ab um bereits am Eingang
mit dem Schild:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Alle FFP2 Masken ausverkauft!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;abgeschmettert zu werden.&lt;br /&gt;
Da hilft es auch nicht, früher Schluss zu machen, denn entweder wurden wieder 
im Handel nur 3 Stück für 1000 Menschen bestellt, oder eine Hamsterhorde räumt 
am Morgen alle Filialen leer.&lt;/p&gt;

&lt;p&gt;Nachdem ich vom öffentlichen Transport abhängig bin um zum Arbeitsplatz zu 
kommen und mich ohne Maske ab Montag (2021-01-25) strafbar mache, fällt mir 
also nur noch eine Stelle ein: die &lt;a href=&quot;https://de.wikipedia.org/wiki/Apotheke&quot;&gt;Apotheke&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Und ja, die haben Masken, weil sie nur maximal 2 Stück pro Person verkaufen 
und eine einzelne Maske satte 3,40 Euro kostet.&lt;br /&gt;
&lt;strong&gt;Wow! Das ist über 5 mal teurer als angekündigt!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/corona-ffp2-masks.jpg&quot; alt=&quot;Corona-FFP2-Mask&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Die Empfehlung lautet eine Maske pro Wochentag zu kaufen (also 7 Stück) und 
dann durchzuwechseln. Wird eine Maske schmutzig oder undicht muss sie sofort
durch eine neue ersetzt werden.&lt;/p&gt;

&lt;p&gt;Tja, ich könnte/kann mir diesen Luxus leisten und tue das heute auch 
demonstrativ. Aber diese Rechnung werde ich mir noch lange aufheben.
Nicht, dass ich einem Produkt, dass offenbar sogar in Wien hergestellt wird,
seinen Wert absprechen möchte, aber es ist eine Frechheit kurzfristig eine 
Verordnung auf den Weg zu bringen und die Nichtbeachtung unter Strafe zu 
stellen, obwohl die Versorgung nicht sichergestellt ist.&lt;/p&gt;

&lt;p&gt;Ich möchte nicht wissen, was aktuell Menschen ohne Job dann tun…
Scheißen die einfach drauf, oder lassen die immer wieder mal eine Mahlzeit 
aus um sich eine teure Apotheken-Maske leisten zu können?&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ehrlich, so etwas pisst mich echt an!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Es heißt, man soll sich nur an die guten Dinge erinnern, aber Nein! 
Ich möchte mich auch in 10 Jahren noch an diesen heutigen Tag erinnern, und 
kann diese Planlosigkeit einfach nur scharf kritisieren.&lt;/p&gt;

&lt;p&gt;Und dieser Eintrag hier soll das nachhaltig dokumentieren.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;PS:&lt;br /&gt;
Eines muss ich allerdings positiv erwähnen: Meine Firma war intelligent und
hat mitgedacht. Maskenpakete für alle Mitarbeiter wurden bestellt und sind 
auch schon geliefert. Ich hätte das Privileg mir von der Arbeit eine 
mitzunehmen, aber dieses Glück haben vermutlich nicht alle Angestellten.&lt;/p&gt;

&lt;p&gt;Und wie gesagt … wer nun ohne Job dasteht (und derer werden leider immer 
mehr), der wird mit diesen Wucherpreisen gerade heftig verarscht.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Nachtrag:&lt;br /&gt;
Die beste Verarsche kommt aber noch: 
Am Montag, wo die Verordnung in Kraft getreten war, haben plötzlich viele
Geschäfte wieder Masken verkaufen können … und diesmal tatsächlich zum
59 Cent Preis.&lt;br /&gt;
Tja … jetzt muss ich mir wohl einreden, dass meine 3,40 Euro Maske 
mindestens 5 mal besser ist, als die Teile aus dem Supermarkt.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Die Optik von Common Controls</title>
   <link href="https://www.opengate.at/blog/2021/01/common-controls/"/>
   <published>2021-01-17T12:00:00+01:00</published>
   <updated>2021-01-17T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2021/01/common-controls</id>
   <category term="devel" />
   <summary type="text">Raymond Chen
hat einige schöne Artikel zum Thema Common Controls
verfasst.

Doch wie nutzt man die 
Windows Common Controls
nun am Besten?
</summary>
   <content type="html">&lt;p&gt;&lt;a href=&quot;https://devblogs.microsoft.com/oldnewthing/author/oldnewthing&quot;&gt;Raymond Chen&lt;/a&gt;
hat einige schöne &lt;a href=&quot;https://devblogs.microsoft.com/oldnewthing/20080129-00/?p=23663&quot;&gt;Artikel zum Thema Common Controls&lt;/a&gt;
verfasst.&lt;/p&gt;

&lt;p&gt;Doch wie nutzt man die 
&lt;a href=&quot;http://docs.microsoft.com/en-us/windows/win32/controls/common-controls-intro&quot;&gt;Windows Common Controls&lt;/a&gt;
nun am Besten?
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;manifest&quot;&gt;Manifest&lt;/h3&gt;

&lt;p&gt;Am Anfang hat man uns beigebracht, man müsse einfach eine 
&lt;code&gt;MYPROGRAM.EXE.manifest&lt;/code&gt; Datei mit folgendem Inhalt erstellen&lt;/p&gt;

&lt;div class=&quot;language-xml highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot; standalone=&amp;quot;yes&amp;quot;?&amp;gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#070;font-weight:bold&quot;&gt;&amp;lt;assembly&lt;/span&gt; &lt;span style=&quot;color:#b48&quot;&gt;xmlns&lt;/span&gt;=&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;urn:schemas-microsoft-com:asm.v1&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span style=&quot;color:#b48&quot;&gt;manifestVersion&lt;/span&gt;=&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;1.0&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#070;font-weight:bold&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#070;font-weight:bold&quot;&gt;&amp;lt;assemblyIdentity&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#b48&quot;&gt;version&lt;/span&gt;=&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;1.0.0.0&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#b48&quot;&gt;processorArchitecture&lt;/span&gt;=&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#b48&quot;&gt;name&lt;/span&gt;=&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;CompanyName.ProductName.YourApplication&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#b48&quot;&gt;type&lt;/span&gt;=&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;win32&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#070;font-weight:bold&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#070;font-weight:bold&quot;&gt;&amp;lt;description&amp;gt;&lt;/span&gt;Your application description here.&lt;span style=&quot;color:#070;font-weight:bold&quot;&gt;&amp;lt;/description&amp;gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  &lt;span style=&quot;color:#070;font-weight:bold&quot;&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#070;font-weight:bold&quot;&gt;&amp;lt;dependentAssembly&amp;gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#070;font-weight:bold&quot;&gt;&amp;lt;assemblyIdentity&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;        &lt;span style=&quot;color:#b48&quot;&gt;type&lt;/span&gt;=&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;win32&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;        &lt;span style=&quot;color:#b48&quot;&gt;name&lt;/span&gt;=&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Microsoft.Windows.Common-Controls&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;        &lt;span style=&quot;color:#b48&quot;&gt;version&lt;/span&gt;=&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;6.0.0.0&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;        &lt;span style=&quot;color:#b48&quot;&gt;processorArchitecture&lt;/span&gt;=&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;        &lt;span style=&quot;color:#b48&quot;&gt;publicKeyToken&lt;/span&gt;=&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;6595b64144ccf1df&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;        &lt;span style=&quot;color:#b48&quot;&gt;language&lt;/span&gt;=&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#070;font-weight:bold&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;    &lt;span style=&quot;color:#070;font-weight:bold&quot;&gt;&amp;lt;/dependentAssembly&amp;gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n21&quot; name=&quot;n21&quot;&gt;21&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#070;font-weight:bold&quot;&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n22&quot; name=&quot;n22&quot;&gt;22&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#070;font-weight:bold&quot;&gt;&amp;lt;/assembly&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;und neben die EXE legen. Windows macht den Rest.
Das war zu Zeiten von &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_XP&quot;&gt;Windows XP&lt;/a&gt;
auch die einzige Möglichkeit, weil Programme noch mit dem klassischen 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_Basic_Classic&quot;&gt;VB6&lt;/a&gt; oder &lt;a href=&quot;https://en.wikipedia.org/wiki/Microsoft_Visual_C%2B%2B&quot;&gt;VC6&lt;/a&gt;
geschrieben wurden und es keine Tools gab um “Manifest” Dateien für Programme 
zu erstellen.&lt;/p&gt;

&lt;p&gt;Erst &lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_Studio#Version_.NET&quot;&gt;Visual Studio 2002&lt;/a&gt;
brachte Werkzeuge für das Erstellen von Programmen mit, in denen das Manifest
in der EXE selbst untergebracht war.&lt;br /&gt;
Nun erstellt man &lt;code&gt;.manifest&lt;/code&gt; Dateien und lässt sie vom Ressourcen Compiler
in die EXE mitaufnehmen. Und wenn wir uns so an die Common-Controls 6.0 binden,
erhalten wir neben “smootheren” Listviews und Treeviews auch neue Features
wie z.B. die Tile-Ansicht (Mehrzeilige Listeneinträge in einem Block).&lt;/p&gt;

&lt;h3 id=&quot;statische-bibliotheken&quot;&gt;Statische Bibliotheken&lt;/h3&gt;

&lt;p&gt;Was mich bei der &lt;code&gt;.manifest&lt;/code&gt; Datei ein bisschen “ankotzt”, ist die Tatsache,
dass ich UI-Special-Features in einer Bibliothek habe und das EXE-Projekt
dann wegen der UI-Lib “angepasst” werden muss, damit es das &lt;code&gt;manifest&lt;/code&gt; 
in sich aufnimmt. Ist die UI eine dynamische Bibliothek, könnte man das 
Manifest dort anbringen, aber bei statischen Bibliotheken geht das nicht.&lt;/p&gt;

&lt;p&gt;Außer …&lt;/p&gt;

&lt;p&gt;Man kann jedoch ein klassisches Microsoft-C Features nutzen, nämlich
&lt;code&gt;#pragma comment(linker, &quot;...&quot;)&lt;/code&gt; und dort dem Linker ein paar Zusatzanweisungen
geben. Statische Bibliotheken geben diese Info auf diese Weise an das 
EXE-Projekt weiter und wir können so einen Manifestinhalt per Linker-Option
anfügen.&lt;/p&gt;

&lt;p&gt;Das sieht dann etwa so aus:
&lt;code&gt;#pragma comment(linker, &quot;\&quot;/manifestdependency:type=&apos;Win32&apos; name=&apos;Microsoft.Windows.Common-Controls&apos; version=&apos;6.0.0.0&apos; processorArchitecture=&apos;*&apos; publicKeyToken=&apos;6595b64144ccf1df&apos; language=&apos;*&apos;\&quot;&quot;)&lt;/code&gt;&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Baum_(Steuerelement)&quot;&gt;Treeview und Listview&lt;/a&gt; 
sind neben Tabs und Toolbars nach wie vor die häufigsten UI Elemente aus den 
“Common Controls”, ohne die ich keine UI bauen könnte. 
(Buttons und Textfelder sind eben nicht genug.)&lt;br /&gt;
Dass die Elemente aus Kompatibilitätsgründen nur dann das “aktuelle” Windows 
Design erhalten, wenn sie per Manifest dafür freigeschaltet sind, ist 
ärgerlich. Das liegt vor allem an jenen Entwicklern, die sich unsauber an 
nicht dokumentierte Features geheftet haben und Microsoft dann deren 
Versagen auszugleichen versuchte.&lt;/p&gt;

&lt;p&gt;Wie auch immer … mit der &lt;code&gt;pragma&lt;/code&gt; Lösung kann ich leben. Natürlich steht
dieses Feature nicht unter anderen Compilern zur Verfügung, aber ich erstelle
offizielle Windows Programme nur mit &lt;code&gt;MSVC&lt;/code&gt;. Den MinGW nutze ich nur zur 
Verifizierung, dass alles portabel implementiert ist und da kann man mal auf
Manifeste verzichten.&lt;/p&gt;

&lt;p&gt;Von daher: &lt;strong&gt;Ein Hoch auf &lt;code&gt;pragma&lt;/code&gt;&lt;/strong&gt;&lt;br /&gt;
&lt;em&gt;!Aber nur hier in diesem Sondernfall, ansonsten ist &lt;code&gt;pragma&lt;/code&gt; meist böse!&lt;/em&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>1GB Tablet Updates</title>
   <link href="https://www.opengate.at/blog/2021/01/1gb-tablet/"/>
   <published>2021-01-16T12:00:00+01:00</published>
   <updated>2021-01-16T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2021/01/1gb-tablet</id>
   <category term="hardware" /><category term="software" />
   <summary type="text">Also … Windows NT 4.0 
kam mit 12 MB RAM aus (bei weniger startete das Setup nicht), 
Windows Vista 
verweigerte unter 512 MB den Dienst und 
Windows 10 braucht 
offiziell 1 GB für 32 bit.

Und trotzdem startet nicht mal das Setup auf meinem TrekStor WinTron 7.
… aber das Setup aus dem Jahr 2016, das hatte keine Probleme …

Hmm …
</summary>
   <content type="html">&lt;p&gt;Also … &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_NT_4.0&quot;&gt;Windows NT 4.0&lt;/a&gt; 
kam mit 12 MB RAM aus (bei weniger startete das Setup nicht), 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_Vista&quot;&gt;Windows Vista&lt;/a&gt; 
verweigerte unter 512 MB den Dienst und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_10&quot;&gt;Windows 10&lt;/a&gt; braucht 
offiziell 1 GB für 32 bit.&lt;/p&gt;

&lt;p&gt;Und trotzdem startet nicht mal das Setup auf meinem &lt;code&gt;TrekStor WinTron 7&lt;/code&gt;.
… aber das Setup aus dem Jahr 2016, das hatte keine Probleme …&lt;/p&gt;

&lt;p&gt;Hmm …
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Das Billigteil “Wintron 7” ist ein &lt;a href=&quot;https://de.wikipedia.org/wiki/Intel_Atom&quot;&gt;Intel Atom&lt;/a&gt;
Tablet, das so gegen 2015 um etwa 80 Euro zu bekommen war. 
Doch seit 2016 verweigerte das Teil konsequent Updates wegen zu wenig 
Speicher und landete im Kasten.
Bevor ich mich offiziell schäme, ein solches Billigteil überhaupt gekauft 
zu haben, hier mal gleich die Schnell-Lösung, wie man das Teil
auf den neuesten Stand bekommt.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Windows 10 1607 Setup zur Installation auf einen USB Stick bringen&lt;/li&gt;
  &lt;li&gt;Windows 10 2020/H2 oder neuer auf zweiten USB Stick kopieren&lt;/li&gt;
  &lt;li&gt;Treiber von TrekStor herunterladen und auf einen der USB Sticks kopieren&lt;/li&gt;
  &lt;li&gt;Tablet vom 1607 USB Stick booten lassen und per Reparaturmodus die Konsole öffnen&lt;/li&gt;
  &lt;li&gt;Festplatte löschen (&lt;code&gt;format c: /q&lt;/code&gt;)&lt;/li&gt;
  &lt;li&gt;Per &lt;a href=&quot;https://docs.microsoft.com/en-us/windows-hardware/manufacture/desktop/what-is-dism&quot;&gt;&lt;code&gt;dism&lt;/code&gt;&lt;/a&gt; 
vom 2020/H2 (oder neuer) die &lt;code&gt;install.wim&lt;/code&gt; auf &lt;code&gt;c:&lt;/code&gt; installieren&lt;/li&gt;
  &lt;li&gt;Treiber per &lt;code&gt;dism&lt;/code&gt; in das neue Image auf &lt;code&gt;c:&lt;/code&gt; integrieren&lt;/li&gt;
  &lt;li&gt;Tablet neu starten und Setup durchlaufen lassen&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Tja, so einfach ist das und schon läuft das neueste Windows auf einem Tablet,
das offiziell zu klein dafür ist.&lt;br /&gt;
(Wobei … “laufen” kann man nicht gerade sagen … aber es war auch schon 
vor dem Update sehr langsam).&lt;/p&gt;

&lt;h3 id=&quot;windows-10-auf-unter-1-gb-installieren&quot;&gt;Windows 10 auf unter 1 GB installieren&lt;/h3&gt;

&lt;p&gt;Das Problem mit der Installation ist offenbar die Grafikkarte, die nochmal 
128 MB vom RAM abzweigt und die größere RAM-Disk der neueren 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_PE&quot;&gt;Windows-PE&lt;/a&gt; Images.
Da wird dann offenbar ein Limit überschritten und der Boot bricht mit der 
Meldung&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;Status: 0xc0000017  
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;Info: There isn&apos;t enough memory available to create a ramdisk device.
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;ab. Aber zu Zeiten von Windows 10 1607 war die RAM-Disk offenbar um ein paar
MB kleiner dimensioniert und somit startet das alte Setup ohne Probleme.
Ich nutzte also diese Version um per &lt;code&gt;diskpart&lt;/code&gt; zuerst alle Partitionen
zu löschen und eine Komplette Neuinstallation durchzuführen.&lt;/p&gt;

&lt;p&gt;Natürlich waren dann mehrere Versuche notwendig und da das Tablet nur über
einen einzigen USB-Port verfügt, war das ganze überhaupt nur per USB-Hub mit
externer Stromversorgung durchführbar.&lt;/p&gt;

&lt;p&gt;Doch bekanntlich macht das Windows Setup auch nicht viel mehr als per 
DISM-APIs eines der ge-&lt;code&gt;sysprep&lt;/code&gt;-ten Images in &lt;code&gt;\sources\install.wim&lt;/code&gt; auf 
die Festplatte zu übertragen und genau das kann man auch manuell übernehmen.
Und somit habe ich nach der 1607er Installation nochmal den Reparaturmodus
gestartet und nur Laufwerk &lt;code&gt;C:&lt;/code&gt; gelöscht (&lt;code&gt;format c: /q&lt;/code&gt;)  und dann per
&lt;code&gt;dism /apply-image&lt;/code&gt; die neueste Windows Version darübergelegt.&lt;/p&gt;

&lt;p&gt;Streng genommen ist mein Setup nicht vollständig, denn ich habe den 
EFI-Bootloader der alten Version 1607 belassen und nur das System auf &lt;code&gt;C:&lt;/code&gt;
ausgetauscht … aber es läuft trotzdem, schließlich hat sich jetzt auch nicht
so viel in den letzten Jahren geändert.&lt;/p&gt;

&lt;p&gt;Doch wegen der fehlenden USB-Treiber wird auch der Host-Controller nicht ohne
Weiteres erkannt. Daher war es notwendig auch die Treiber in das Image 
per &lt;code&gt;dism /image:... /add-driver&lt;/code&gt; zu integrieren.&lt;/p&gt;

&lt;p&gt;Erst mit diesem Schritt kann man die nötigen &lt;code&gt;Weiter&lt;/code&gt; Klicks machen um das 
Setup abzuschließen.&lt;br /&gt;
Ein Problem ist auch, dass der Touch-Screen nicht kalibriert ist und keine 
einzige Berührung funktioniert. Das kann man leider auch erst korrigieren,
wenn man per Maus oder Tastatur zur richtigen Einstellungsseite hinnavigiert
hat.&lt;/p&gt;

&lt;p&gt;Und so lange nicht alle Treiber korrekt installiert sind, gibt es auch Fehler
beim Shutdown. Da muss man erst 10 Sekunden auf den On/Off Button drücken um
das Gerät hart auszuschalten, um dann per 3-4 Sekunden-Tastendruck das Gerät
wieder hochfahren zu lassen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Es mag ein etwas nutzloses Experiment gewesen sein … aber ich freue mich
immer, wenn “etwas unmögliches” mit ein paar Experimenten dann plötzlich 
doch möglich wird.&lt;/p&gt;

&lt;p&gt;Aber … ich weiß nicht, ob ich bei dieser Installation bleiben werde.
Denn das Gerät ist nun so voll, dass man nichts mehr installieren kann.&lt;/p&gt;

&lt;p&gt;Vielleicht ist das mal ein Grund mit 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_IoT#Windows_10_IoT_Enterprise&quot;&gt;Windows 10 IOT&lt;/a&gt;
ein abgespecktes Images zu generieren, das den Limits des Tablets besser
angepasst ist.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Verzeichnis Ordnung</title>
   <link href="https://www.opengate.at/blog/2021/01/dir-order/"/>
   <published>2021-01-10T12:00:00+01:00</published>
   <updated>2021-01-10T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2021/01/dir-order</id>
   <category term="software" /><category term="retro" />
   <summary type="text">
  Was kommt in welches Datei-Verzeichnis?


Dieses Frage beantworten viele Programme mit festgelegten (hard-gecodeten)
Verzeichnispfaden. Und wenn dann in einer Quelldatei ein c:\programme\ 
oder /usr/local/bin drinnen steht … tja dann fängt die Hölle Feuer.
</summary>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;Was kommt in welches &lt;a href=&quot;https://de.wikipedia.org/wiki/Dateisystem#Hierarchische_Dateisysteme&quot;&gt;Datei-Verzeichnis&lt;/a&gt;?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Dieses Frage beantworten viele Programme mit festgelegten (hard-gecodeten)
Verzeichnispfaden. Und wenn dann in einer Quelldatei ein &lt;code&gt;c:\programme\&lt;/code&gt; 
oder &lt;code&gt;/usr/local/bin&lt;/code&gt; drinnen steht … tja dann fängt die Hölle Feuer.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Ein ehemaliger Kollege meinte einmal:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Diese bibliothekarisch sortierten Verzeichnisstrukturen sind nicht mehr 
zeitgemäß und sollten durch etwas intuitiveres ersetzt werden.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Nur leider ist genau das bis heute nicht massentauglich geschehen.&lt;/p&gt;

&lt;p&gt;Ein beachtlicher Anteil an Software wird wegen falschen Dateipfaden regelmäßig
von Ausfällen geplagt und muss dann durch neuere Versionen mit ebenso 
hässlichen Workarounds ersetzt werden.&lt;/p&gt;

&lt;p&gt;Das Problem sind fehlende Standards oder die fehlende Durchsetzung eben 
solcher. Auch wenn dieser Zustand in den letzten 15 Jahren sichtlich besser 
wurde, verschwunden ist er leider noch nicht.&lt;/p&gt;

&lt;h3 id=&quot;windows&quot;&gt;Windows&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows&quot;&gt;Windows&lt;/a&gt; hatte ursprünglich 
aus der &lt;a href=&quot;https://de.wikipedia.org/wiki/MS-DOS&quot;&gt;DOS&lt;/a&gt;-Zeit die Idee der 
absoluten Freiheit übernommen. Man durfte alles überall hinspeichern, nur einige wenige 
Verzeichnisse wie &lt;code&gt;C:\DOS&lt;/code&gt; und &lt;code&gt;C:\Windows&lt;/code&gt; sollten verschont bleiben. Doch
auch das passierte nicht und so ward die &lt;a href=&quot;https://de.wikipedia.org/wiki/DLL-Konflikt&quot;&gt;DLL-Hölle&lt;/a&gt; 
geboren, wo jeder App-Installer die DLLs seiner Software im &lt;code&gt;System&lt;/code&gt; 
Unterverzeichnis von Windows ablegte und damit die Versionen anderer Softwareprodukte überschrieb.
Das Resultat waren die lustigsten Formen von Abstürzen and anderem 
Fehlverhalten.&lt;/p&gt;

&lt;p&gt;Mit &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_95&quot;&gt;Windows 95&lt;/a&gt; wurde 
dann &lt;code&gt;c:\Program Files&lt;/code&gt; eingeführt, welches dann auch noch in alle Sprachen 
übersetzt wurde. Und so hieß der Ordner im deutschsprachigen Raum 
&lt;code&gt;c:\Programme&lt;/code&gt; und wir lernten dann recht flott, dass auch viele kommerziellen
Profi-Tools mit der Installation nach &lt;code&gt;c:\Program Files&lt;/code&gt; offenbar etwas 
falsch machten.&lt;/p&gt;

&lt;p&gt;Ebenso schlimm waren private Daten, die in Win9X unter &lt;code&gt;c:\Eigene Dateien&lt;/code&gt;
oder &lt;code&gt;C:\Windows\Profiles\name&lt;/code&gt; landen konnten, je nach Systemeinstellung.
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_NT&quot;&gt;Windows NT&lt;/a&gt; 
verabschiedete sich dann auch noch von &lt;code&gt;C:\Windows&lt;/code&gt; und setzte anfangs 
&lt;code&gt;c:\WinNT&lt;/code&gt; bzw. &lt;code&gt;c:\wtsrv&lt;/code&gt; ein, womit Benutzerdaten eben dort im
Unterverzeichnis &lt;code&gt;Profiles\username&lt;/code&gt; zu finden sein sollten.&lt;/p&gt;

&lt;p&gt;Mit Windows 2000 und XP wurde &lt;code&gt;C:\Windows&lt;/code&gt; wieder gültig und 
ein &lt;code&gt;c:\Documents and Settings&lt;/code&gt; eingeführt, was im Deutschen wieder 
&lt;code&gt;C:\Dokumente und Einstellungen&lt;/code&gt; hieß.&lt;br /&gt;
Erst Windows Vista und 7 legten &lt;code&gt;C:\Users&lt;/code&gt; in allen Sprachen als Primärziel
fest, erstellten aber übersetzte Dateisystem-Links wie &lt;code&gt;c:\Benutzer&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;All das sollten die Programmierer nicht im entferntesten kümmern, denn diese
Pfade sollten nie in Programmen enthalten sein, sondern sollten per Aufruf wie 
etwa über &lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/shlobj_core/nf-shlobj_core-shgetspecialfolderpathw&quot;&gt;SHGetSpecialFolderPathW&lt;/a&gt;
abgefragt werden.&lt;/p&gt;

&lt;p&gt;Doch weil genau das nicht immer geschah erlebte Windows hier ein Chaos. 
Angefangen bei z.B.: Microsoft’s &lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_Basic_Classic&quot;&gt;Visual Basic 4&lt;/a&gt;, 
das nur in &lt;code&gt;c:\VB&lt;/code&gt; installiert werden sollte, verunreinigten auch viele 
andere Tools das Dateisystem mit solchen Eigenmächtigkeiten.&lt;/p&gt;

&lt;h3 id=&quot;linux-bsd&quot;&gt;Linux, BSD&lt;/h3&gt;

&lt;p&gt;Theoretisch hatten es &lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt; und generell 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Unix&quot;&gt;Unix Systeme&lt;/a&gt; richtig gemacht. Mit der
&lt;a href=&quot;https://de.wikipedia.org/wiki/Stammverzeichnis&quot;&gt;Root-Dateisystem&lt;/a&gt; Konvention
für Unterverzeichnisse existiert quasi ein Standard, der alle 
unterschiedlichen Implementierungen vereint.&lt;br /&gt;
Man findet also unter &lt;code&gt;/etc&lt;/code&gt; immer alle globalen Konfigurationsdateien, 
&lt;code&gt;/dev&lt;/code&gt; enthält nur Gerätetreiber und deren Datenströme und &lt;code&gt;/home&lt;/code&gt; ist die 
Basis für die Unterverzeichnisse pro registriertem Benutzer.
&lt;code&gt;/var&lt;/code&gt; für logs und lokale Hilfsdateien und &lt;code&gt;/tmp&lt;/code&gt; für Temporäres dürfen
ebenso wenig fehlen wie &lt;code&gt;/bin&lt;/code&gt; und &lt;code&gt;/sbin&lt;/code&gt; für Systemtools und &lt;code&gt;/usr&lt;/code&gt; als Host für 
alle weiteren Programme.&lt;br /&gt;
Ab &lt;code&gt;/media&lt;/code&gt; und &lt;code&gt;/mnt&lt;/code&gt; wird es schon knifflig, welche Mountpoints man 
darunter findet.&lt;/p&gt;

&lt;p&gt;Doch leider haben unterhalb dieser Ebene die Distributionen ihre 
Meinungsfreiheit zu sehr ausgenutzt.&lt;br /&gt;
Und so findet man die gleichen Softwareprodukte mal unter &lt;code&gt;/usr/bin&lt;/code&gt; und 
mal unter &lt;code&gt;/usr/local/bin&lt;/code&gt;, womit ein paar Scripts ihre Portierbarkeit
verlieren und Probleme bereiten, wenn sie Dateien falsch duplizieren oder
nicht finden.&lt;/p&gt;

&lt;p&gt;Nachdem &lt;a href=&quot;https://de.wikipedia.org/wiki/Portable_Operating_System_Interface&quot;&gt;POSIX&lt;/a&gt; 
und Linux keine APIs für die Pfade vorsehen, wählte man Umgebungsvariablen 
wie &lt;code&gt;$HOME&lt;/code&gt; um “leichter” zum richtigen Verzeichnis gelangen zu können. 
Doch wenn Programme &lt;a href=&quot;http://pubs.opengroup.org/onlinepubs/007904875/functions/exec.html&quot;&gt;&lt;code&gt;exec&lt;/code&gt;&lt;/a&gt; 
falsch nutzen und kein Environment oder eine manipuliertes Environment 
weitervererben, verhalten sich Bibliotheken ob der unkorrekten Variablen 
falsch.&lt;br /&gt;
Und schon landen Dateien im Arbeitsverzeichnis oder können wegen fehlender
Rechte gar nicht geschrieben werden.&lt;/p&gt;

&lt;p&gt;Auf &lt;code&gt;/etc&lt;/code&gt; ist wiederum unter &lt;a href=&quot;https://de.wikipedia.org/wiki/FreeBSD&quot;&gt;FreeBSD&lt;/a&gt; 
kein Verlass, denn nicht-elementare Systemkonfigurationen 
(z.B. Zusatzdienste wie &lt;code&gt;sudo&lt;/code&gt;) speichern ihre Einstellungen dann manchmal
in &lt;code&gt;/usr/local/etc&lt;/code&gt; … und man wundert sich, warum die Einstellungen in 
&lt;code&gt;/etc&lt;/code&gt; einfach nicht greifen wollen.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;/tmp&lt;/code&gt; ist heute meist nur noch ein Link auf &lt;code&gt;/var/tmp&lt;/code&gt; oder ein anderes 
benutzerspezifisches Verzeichnis. Doch leider beginnen Distributionen nun damit
dieses alte Standardverzeichnis erst gar nicht mehr anzulegen.
Und da die Variable &lt;code&gt;$TMP&lt;/code&gt; auch nicht immer vorhanden ist, überlässt man es
Drittbibliotheken, den richtigen Pfad zu finden.&lt;/p&gt;

&lt;p&gt;Dass das nicht immer so gut klappt, merkt man erst nach vielen Stunden 
Debug-Logs entschlüsseln, wenn man ein Open Source Projekt heruntergeladen
und kompiliert hat und dieses einfach nicht starten möchte.&lt;/p&gt;

&lt;p&gt;Es sind also nicht nur die distributionsspezifischen Scripts sondern auch
Binärprogramme, die ohne spezielle Anpassungen ihr Lauffähigkeit einbüßen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Programme hätten eigentlich das Potential - einmal geschrieben - ewig zu 
leben. Dass es ausgerechnet bescheuerte Dateisystem Pfade sind, die sich von
OS zu OS-Version so ändern und dann Funktionsstörungen auftreten, 
ist sehr ärgerlich.&lt;/p&gt;

&lt;p&gt;Doch eben dafür sollten die OS-Hersteller stabile Schnittstellen etablieren,
die die Wirrungen der Zeit überdauern und den Programmen sagen, wohin sie
ihre Daten schreiben dürfen.
Natürlich bringt es auch nichts, diese Schnittstellen ständig inkompatibel
abzuändern, was wieder zum Nutzen von hart kodierten Pfaden in den Programmen
führt.&lt;/p&gt;

&lt;p&gt;Im GATE Projekt versuche ich diese Wirrungen durch Funktionen aufzulösen,
doch genau hier merkt man leider sehr intensiv, wie unterschiedlich sogar die
Versionen der gleichen Plattform sind. Auch in den Quellen anderer Programme 
findet sich eine Vielzahl solcher Sonderfall-Lösungen.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Was uns leider fehlt ist EIN von allen akzeptierter Standard !!&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>WinRT/UWP ICoreWindow</title>
   <link href="https://www.opengate.at/blog/2021/01/corewindow/"/>
   <published>2021-01-09T12:00:00+01:00</published>
   <updated>2021-01-09T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2021/01/corewindow</id>
   <category term="devel" />
   <summary type="text">
  Wie kommt man von main zu 
ICoreWindow
und dem restlichen UWP Schnickschnack der 
Windows RunTime?


Nun, wenn ich schon die C 
Interface Projection zerlege, dann kann ich das hiermit auch gleich mal 
mitdokumentieren.
</summary>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;Wie kommt man von &lt;code&gt;main&lt;/code&gt; zu 
&lt;a href=&quot;https://docs.microsoft.com/en-us/uwp/api/windows.ui.core.icorewindow?view=winrt-19041&quot;&gt;&lt;code&gt;ICoreWindow&lt;/code&gt;&lt;/a&gt;
und dem restlichen UWP Schnickschnack der 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_Runtime&quot;&gt;Windows RunTime&lt;/a&gt;?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Nun, wenn ich schon die &lt;a href=&quot;https://de.wikipedia.org/wiki/C_(Programmiersprache)&quot;&gt;C&lt;/a&gt; 
Interface Projection zerlege, dann kann ich das hiermit auch gleich mal 
mitdokumentieren.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;WinRT Programme werden ja “anders” behandelt als reguläre 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_Application_Programming_Interface#Win32&quot;&gt;Win32&lt;/a&gt; 
Prozesse. Ähnlich wie bei Services erwartet das System, dass der Prozess 
binnen einer bestimmten Zeit sich meldet und seine Schnittstellen zum 
Empfangen von “Anweisungen” bereitstellt.&lt;br /&gt;
Gut analysieren kann man das über die C++ &lt;a href=&quot;https://de.wikipedia.org/wiki/DirectX&quot;&gt;DirectX&lt;/a&gt; 
UWP Projektvorlage.&lt;/p&gt;

&lt;p&gt;In WinRT übernimmt das die Klasse &lt;a href=&quot;http://docs.microsoft.com/en-us/uwp/api/windows.applicationmodel.core.coreapplication?view=winrt-19041&quot;&gt;&lt;code&gt;CoreApplication&lt;/code&gt;&lt;/a&gt;, 
deren statische Methode &lt;a href=&quot;http://docs.microsoft.com/en-us/uwp/api/windows.applicationmodel.core.coreapplication.run?view=winrt-19041&quot;&gt;&lt;code&gt;Run&lt;/code&gt;&lt;/a&gt; 
eine Instanz von &lt;a href=&quot;https://docs.microsoft.com/en-us/uwp/api/windows.applicationmodel.core.iframeworkviewsource?view=winrt-19041&quot;&gt;&lt;code&gt;IFrameworkViewSource&lt;/code&gt;&lt;/a&gt;
entgegen nimmt, was wiederum nur eine Factory für eine 
&lt;a href=&quot;https://docs.microsoft.com/en-us/uwp/api/windows.applicationmodel.core.iframeworkview?view=winrt-19041&quot;&gt;&lt;code&gt;IFrameworkView&lt;/code&gt;&lt;/a&gt; 
Instanz ist, die mit der Methode 
&lt;a href=&quot;https://docs.microsoft.com/en-us/uwp/api/windows.applicationmodel.core.iframeworkviewsource.createview?view=winrt-19041&quot;&gt;&lt;code&gt;CreateView()&lt;/code&gt;&lt;/a&gt;
genau eine solche erzeugt.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;CoreApplication::Run()&lt;/code&gt; ruft nach der Erzeugung von &lt;code&gt;IFrameworkView&lt;/code&gt;
folgende Methoden auf:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/uwp/api/windows.applicationmodel.core.iframeworkview.initialize?view=winrt-19041&quot;&gt;&lt;code&gt;Initialize()&lt;/code&gt;&lt;/a&gt;&lt;br /&gt;
Hier erhält man ein &lt;code&gt;ICoreApplicationView&lt;/code&gt; wo man seine eigene 
Ereignisbehandlung für Events wie &lt;code&gt;Activated&lt;/code&gt;, &lt;code&gt;Suspending&lt;/code&gt; oder &lt;code&gt;Resuming&lt;/code&gt;
setzen kann&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/uwp/api/windows.applicationmodel.core.iframeworkview.setwindow?view=winrt-19041&quot;&gt;&lt;code&gt;SetWindow()&lt;/code&gt;&lt;/a&gt;&lt;br /&gt;
Über den &lt;code&gt;ICoreWindow&lt;/code&gt; Parameter erhalten wir DAS Fenster, in dem die App
laufen wird. Auch hier kann man diverse Event-Handler für Fensteränderungen
setzen&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/uwp/api/windows.applicationmodel.core.iframeworkview.load?view=winrt-19041&quot;&gt;&lt;code&gt;Load()&lt;/code&gt;&lt;/a&gt;&lt;br /&gt;
Dann sollten Einstellungen und Ressourcen geladen werden, was hier 
angestoßen werden sollte.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/uwp/api/windows.applicationmodel.core.iframeworkview.run?view=winrt-19041&quot;&gt;&lt;code&gt;Run()&lt;/code&gt;&lt;/a&gt;&lt;br /&gt;
Und wenn alles vorbereitet ist, darf gearbeitet werden … oder man wartet
einfach auf ein &lt;code&gt;Shutdown&lt;/code&gt; bzw. &lt;code&gt;CloseWindow&lt;/code&gt; Event.
Dazu lässt man in einer Schleife die Methode &lt;a href=&quot;https://docs.microsoft.com/en-us/uwp/api/windows.ui.core.coredispatcher.processevents?view=winrt-19041#Windows_UI_Core_CoreDispatcher_ProcessEvents_Windows_UI_Core_CoreProcessEventsOption_&quot;&gt;&lt;code&gt;ProcessEvents()&lt;/code&gt;&lt;/a&gt;
von &lt;code&gt;ICoreDispatcher&lt;/code&gt; ausführen, welchen man von &lt;code&gt;ICoreWindow&lt;/code&gt; über das 
&lt;code&gt;Dispatcher&lt;/code&gt; Property erhalten hat.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/uwp/api/windows.applicationmodel.core.iframeworkview.uninitialize?view=winrt-19041&quot;&gt;&lt;code&gt;Uninitialize()&lt;/code&gt;&lt;/a&gt;&lt;br /&gt;
Kehrt &lt;code&gt;Run&lt;/code&gt; zurück, wird die App üblicherweise beendet und eben hier tritt
die &lt;code&gt;Uninitialize()&lt;/code&gt; Methode in Aktion.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;was-muss-man-also-tun&quot;&gt;Was muss man also tun?&lt;/h3&gt;

&lt;p&gt;Man implementiert eine &lt;code&gt;IFrameworkView&lt;/code&gt; Ableitung, welches die 
&lt;code&gt;ICoreApplicationView&lt;/code&gt; und &lt;code&gt;ICoreWindow&lt;/code&gt; von &lt;code&gt;Initialize&lt;/code&gt; und &lt;code&gt;SetWindow&lt;/code&gt; 
aufbewahrt und “vorbereitet”.
Dann implementiert man eine &lt;code&gt;IFrameworkViewSource&lt;/code&gt;, die die zuvor 
beschriebene &lt;code&gt;IFrameworkView&lt;/code&gt; Ableitung instanziiert.
In &lt;code&gt;main&lt;/code&gt; erzeugt man seine &lt;code&gt;IFrameworkViewSource&lt;/code&gt; Instanz und 
übergibt sie an &lt;code&gt;CoreApplication::Run&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Klingt kompliziert … naja, ist eben &lt;a href=&quot;https://de.wikipedia.org/wiki/Component_Object_Model&quot;&gt;COM&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;und-wie-macht-man-weiter&quot;&gt;Und wie macht man weiter?&lt;/h3&gt;

&lt;p&gt;Für DirectX/Direct3D gibt es ja ein schönes Beispiel.
&lt;a href=&quot;https://de.wikipedia.org/wiki/Extensible_Application_Markup_Language&quot;&gt;XAML&lt;/a&gt; 
ist mir aktuell echt zu anstrengend, um das nativ alles nachzubauen.
Da ist man eben doch mit den fertigen Templates und den C++ Erweiterungen
gut beraten, die die Generierung der nötigen Codes und Metadaten übernehmen.&lt;/p&gt;

&lt;p&gt;Aber zum Herumspielen sei noch eines erwähnt:&lt;br /&gt;
Tief versteckt gibt es noch das Interface 
&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/corewindow/nn-corewindow-icorewindowinterop&quot;&gt;&lt;code&gt;ICoreWindowInterop&lt;/code&gt;&lt;/a&gt;
mit der Methode &lt;code&gt;get_WindowHandle&lt;/code&gt;, die ein &lt;code&gt;HWND&lt;/code&gt; zurückliefert.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Oh mein Gott! Ein &lt;code&gt;HWND&lt;/code&gt; in jedem &lt;code&gt;CoreWindow&lt;/code&gt;?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Tja, sieht fast so aus. Bei Nicht-Desktop Apps deaktiviert Microsoft die 
Implementierung in den Headern … aber wer das Interface selbst zusammenbaut
und per &lt;code&gt;QueryInterface&lt;/code&gt; auf die IID &lt;code&gt;45D64A29-A63E-4CB6-B498-5781D298CB4F&lt;/code&gt; 
wechselt, der wird auch dort mit einer &lt;code&gt;HWND&lt;/code&gt; belohnt.&lt;/p&gt;

&lt;p&gt;Da sag ich nur: &lt;strong&gt;NICE!&lt;/strong&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Star Trek: Discovery</title>
   <link href="https://www.opengate.at/blog/2021/01/discovery/"/>
   <published>2021-01-08T12:00:00+01:00</published>
   <updated>2021-01-08T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2021/01/discovery</id>
   <category term="entertainment" />
   <summary type="text">Heute endete die 3. Staffel von 
Star Trek Discovery
und brachte damit endlich ein wenig “Licht” in die Dunkelheit rund um die 
Sternenflotte im 32. Jahrhundert.

Viele Fans meinen:


  Das ist nicht Star Trek!


Genau so wie es das mit jeder und zwar wirklich jeder neuen Serie im
Star Trek Universum in den vergangenen Jahrzehnten der Fall war.
</summary>
   <content type="html">&lt;p&gt;Heute endete die 3. Staffel von 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Star_Trek:_Discovery&quot;&gt;Star Trek Discovery&lt;/a&gt;
und brachte damit endlich ein wenig “Licht” in die Dunkelheit rund um die 
Sternenflotte im 32. Jahrhundert.&lt;/p&gt;

&lt;p&gt;Viele Fans meinen:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Das ist nicht Star Trek!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Genau so wie es das mit jeder und zwar wirklich jeder neuen Serie im
Star Trek Universum in den vergangenen Jahrzehnten der Fall war.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;wie-alles-anfing&quot;&gt;Wie alles anfing…&lt;/h3&gt;

&lt;p&gt;Ich wurde mit Star Trek tatsächlich schon in frühesten Kindestagen 
konfrontiert. 
Während das deutsche Privatfernsehen in den 90ern längst TNG, also 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Raumschiff_Enterprise_%E2%80%93_Das_n%C3%A4chste_Jahrhundert&quot;&gt;The Next Generation&lt;/a&gt;,
&lt;a href=&quot;https://de.wikipedia.org/wiki/Star_Trek:_Deep_Space_Nine&quot;&gt;DS9&lt;/a&gt; und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Star_Trek:_Raumschiff_Voyager&quot;&gt;Voyager&lt;/a&gt; 
ausstrahlte, verblieb der österreichische Rundfunk lange bei den 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Raumschiff_Enterprise&quot;&gt;originalen Serien&lt;/a&gt; (TOS) 
aus den 60er Jahren.&lt;br /&gt;
Das lief immer wieder am Nachmittag … aber wirklich verstanden hatte ich
damals nichts.&lt;/p&gt;

&lt;p&gt;Sozialisiert wurde ich erst Ende der 90er, als dann verspätet auch bei uns 
eine Satellitenschüssel knapp unterm Dach montiert wurde und so die
Wiederholungen aus Deutschland auch bei uns im Wohnzimmer landeten.&lt;/p&gt;

&lt;p&gt;Erst Jahre später “lernte” ich dann im Internet, dass mein Jugendvorbild 
&lt;a href=&quot;https://memory-alpha.fandom.com/de/wiki/Wesley_Robert_Crusher&quot;&gt;Whesley Crusher&lt;/a&gt;
aus TNG offiziell zu den verhassten Charakteren gehören sollte.
Darüber nachdenkend, fand auch ich viele Episoden dann plötzlich “blöd”, die
ich zuvor noch geliebt hatte.&lt;br /&gt;
Aber heute bin ich mir bewusst, dass genau diese Art von 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Science-Fiction&quot;&gt;SciFi&lt;/a&gt; mich damals
im positiven Sinne geprägt hat und somit lasse ich mir den Spaß an den
Serien nicht weiter nachträglich verderben.&lt;/p&gt;

&lt;h3 id=&quot;neu-gleich-schlecht&quot;&gt;Neu gleich schlecht&lt;/h3&gt;

&lt;p&gt;Inzwischen hat die Zeit uns eines gelehrt: Alles Neue wird grundsätzlich mal 
als schlecht empfunden … ganz besonders bei &lt;code&gt;Star Trek&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Die Fans von TOS konnten zuerst den Film nicht leiden, der zweite Film war
nur geduldet weil “Khan” aus der Serie wieder dabei war und als Ende der
1980er dann TNG auftauchte liefen alle Amok:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Man kann doch kein Raumschiff Enterprise herumfliegen lassen, 
ohne dass ein James T. Kirk es kommandiert !!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;1995 kam dann DS9 auf die Fernseher und alle schrie:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Jetzt wird die beste Serie, nämlich TNG, durch eine bescheuerte
Raumstation abgelöst.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Und als 1 Jahr später auch noch “Voyager” parallel durch den Delta-Quadranten
nach Hause flog, lästerte jeder über “den weiblichen Captain” und die starre
emotionslose Crew.&lt;/p&gt;

&lt;p&gt;Und nach 2000 kam dann das “Enterprise” Prequel, wo sich wieder alle sicher
waren:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Das ist NICHT Star Trek! Es kann mit TNG, DS9 und Voyager nicht mithalten!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Kurz um: Die Leute finden offenbar nur genau das gut, mit dem sie gestartet
haben und alles was danach kommt, hassen sie.&lt;/p&gt;

&lt;h3 id=&quot;seit-2017-discovery&quot;&gt;Seit 2017: Discovery&lt;/h3&gt;

&lt;p&gt;Als 2017 Star Trek Discovery auf den Markt kam, ignorierte ich es 
unfreiwillig. Da ich kein klassisches Fernsehen mehr empfing und damals noch
kein Netflix-Abo hatte, las ich nur gelegentlich Kommentare darüber, wie
pervers die Klingonen jetzt aussehen und Raumschiffe nun mit Pilzsporen
betrieben werden … W-T-F …&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/star-trek-discovery.jpg&quot; alt=&quot;Star Trek Discovery&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Aber 2019 war es dann so weit und ich holte die erste und zweite Staffel nach
und freute mich offen gesagt, dieses neue Star Trek kennen lernen zu dürfen.
Die Serie war voller Referenzen zu früheren Serien, verfolgte aber dennoch
einen ganz anderen Weg in Sachen Storytelling und Charakterentwicklung.
Und ja, ein paar Charaktere entwickeln sich sogar … ein großer Fortschritt
zu früher.&lt;/p&gt;

&lt;h3 id=&quot;die-zukunft&quot;&gt;Die Zukunft&lt;/h3&gt;

&lt;p&gt;Die dritte Staffel machte dann etwas bis dato Unvorstellbares. Sie verlegte 
die Handlung durch einen Zeitsprung 1000 Jahre in die Zukunft, damit es 
nicht dauernd Querschläger aus anderen Serien geben konnte. Denn das 
Problem bei allen Star Trek Serien ist, dass sie in den Kanon der anderen
Serien passen müssen und so durfte in der originalen Zeitlinie von 
Discovery, die noch vor Captain Kirk angesiedelt war, nichts passieren,
was die chronologisch späteren spielenden Serien durcheinander bringen
könnte.&lt;/p&gt;

&lt;p&gt;Doch 1000 Jahre später fand sich die Crew nicht im elysischen Utopia 
wieder, sondern in einer durch eine Katastrophe ausgebrannten Galaxie.&lt;/p&gt;

&lt;p&gt;Tja … natürlich ist damit auch wieder keiner der alten Fans zufrieden,
weil plötzlich alles “schlechter” geworden ist.&lt;br /&gt;
Aber genau das, finde ich, macht die Serie “realistisch”.&lt;/p&gt;

&lt;p&gt;Was hätte wohl ein römischer Bürger aus 100 v. Chr. erlebt, wäre er 
1000 Jahre in die Zukunft ins finstere Mittelalter gereist? Ihm wären
die drastischen Verschlechterungen in Gesellschaft und Wissenschaft 
sicher deutlich aufgefallen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ja, ich mag Discovery, genau so wie ich TOS, TNG, DS9, VOY und ENT
sehr schätze.&lt;br /&gt;
Jede Star Trek Serie hat auf ihre ganz eigene Weise Probleme der
Gegenwart in eine futuristische Geschichte eingebettet und am Ende
gelöst.&lt;br /&gt;
Heutige Produktionen sind sicher düsterer als frühere um damit 
bewusst mehr Konflikte und Dramatik zu schaffen. Doch daran kann ich
nichts Schlechtes erkennen.&lt;/p&gt;

&lt;p&gt;Und außerdem steht bereits das nächste Spin-Off “Strange new Worlds”
in den Startlöchern, in welchem angeblich wieder mehr “TOS” Feeling
aufkommen soll.&lt;br /&gt;
Ich freue mich jedenfalls darauf genau so, wie auf die kommende 4. 
Staffel von Star Trek Discovery.&lt;/p&gt;

&lt;p&gt;Mein Tipp an alle anderen Star Trek Fans lautet daher:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Seid mal ein bisschen offen für Veränderungen und lasst euch nicht 
von den Netztrollen die Freude an SciFi verderben!&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>0815 GetProcAddress Hacks</title>
   <link href="https://www.opengate.at/blog/2021/01/getprocaddress/"/>
   <published>2021-01-06T12:00:00+01:00</published>
   <updated>2021-01-06T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2021/01/getprocaddress</id>
   <category term="devel" />
   <summary type="text">Wenn ich mich nicht irre, habe ich etwas Ähnliches schon bei der Einführung
von Windows Phone 8 
gelesen:


  Eigentlich gesperrte API Funktionen sind per GetProcAddress() erreichbar.


Es geht dabei um APIs die Microsoft in den SDKs für bestimmte Plattformen
deaktiviert bzw ausgeschlossen hat. Früher war das beim Windows Phone so, 
heute sind das allgemein “Store Apps” oder andere UWP Konstellationen.
</summary>
   <content type="html">&lt;p&gt;Wenn ich mich nicht irre, habe ich etwas Ähnliches schon bei der Einführung
von &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_Phone_8&quot;&gt;Windows Phone 8&lt;/a&gt; 
gelesen:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Eigentlich gesperrte API Funktionen sind per &lt;code&gt;GetProcAddress()&lt;/code&gt; erreichbar.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Es geht dabei um APIs die Microsoft in den SDKs für bestimmte Plattformen
deaktiviert bzw ausgeschlossen hat. Früher war das beim Windows Phone so, 
heute sind das allgemein “Store Apps” oder andere UWP Konstellationen.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;In Desktop Apps kann man per 
&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryw&quot;&gt;&lt;code&gt;LoadLibrary ()&lt;/code&gt;&lt;/a&gt; 
und &lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getprocaddress&quot;&gt;&lt;code&gt;GetProcAddress()&lt;/code&gt;&lt;/a&gt; 
quasi alles laden und danach ausführen. In Verbindung mit 
&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createremotethread&quot;&gt;&lt;code&gt;CreateRemoteThread()&lt;/code&gt;&lt;/a&gt; 
konnte also jeder &lt;a href=&quot;https://en.wikipedia.org/wiki/Computer_virus&quot;&gt;Virus&lt;/a&gt; sich 
selbst in bereits laufende Prozesse hineinladen und dort Daten ausspähen oder 
Blödsinn anstellen.&lt;/p&gt;

&lt;p&gt;Kein Wunder also, dass Microsoft dieses aus Kompatibilitätsgründen erhaltene
Einbruchwerkzeug wo immer es möglich war deaktivieren wollte. Und die neuen 
Plattformen ab Windows 8 waren dabei ein guter Kandidat.&lt;/p&gt;

&lt;p&gt;Windows Store Apps verfügen daher zwar noch über &lt;code&gt;GetProcAddress()&lt;/code&gt;, doch die 
anderen APIs zur Lieferung des &lt;code&gt;HMODULE&lt;/code&gt; Pointers, der für &lt;code&gt;GetProcAddress()&lt;/code&gt; 
notwendig ist, sind diesen Prozessen nicht zugänglich.&lt;br /&gt;
Man findet sie nicht in den Headern und sie fehlen auch in den Lib-Bibliotheken.
Damit kann ein Prozess eigentlich nichts mehr dynamisch nachladen.
(Für Plugins und Ähnliches gibt es das abgespeckte 
&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-loadpackagedlibrary&quot;&gt;&lt;code&gt;LoadPackagedLibrary&lt;/code&gt;&lt;/a&gt;
um DLLs innerhalb einer signierten App laden zu dürfen).&lt;/p&gt;

&lt;p&gt;Der Punkt ist also: Hat man ein &lt;code&gt;HMODULE&lt;/code&gt; der implizit geladenen DLLs, könnte 
man auch andere Funktionen der Bibliotheken nutzen, die uns das SDK 
vorenthalten möchte.&lt;/p&gt;

&lt;p&gt;Und dafür gibt es tatsächlich einen bekannten Hack, der so lange funktionieren
wird, bis Microsoft die gesamte Windows API aufräumt. Und nachdem das bis 
Windows 10 nicht passiert wird, wird die Lösung vermutlich noch lange 
funktionieren:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualquery&quot;&gt;&lt;code&gt;VirtualQuery()&lt;/code&gt;&lt;/a&gt; 
auf einen Funktionszeiger liefert in &lt;code&gt;AllocationBase&lt;/code&gt; die Adresse zurück, 
auf die auch &lt;code&gt;HMODULE&lt;/code&gt; normalerweise zeigt.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Das heißt also, nachdem &lt;code&gt;LoadLibrary()&lt;/code&gt; zumeist im gleichen Modul sitzt wie auch
&lt;code&gt;GetProcAddress()&lt;/code&gt; (nämlich &lt;code&gt;kernel32.dll&lt;/code&gt;), hilft uns folgender Hack:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;typedef&lt;/span&gt; HMODULE (WINAPI *loader_ptr)(LPCWSTR lpLibFileName);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;MEMORY_BASIC_INFORMATION info;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;VirtualQuery(&amp;amp;GetProcAddress, &amp;amp;info, &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;sizeof&lt;/span&gt;(info));
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;HMODULE hkernel = (HMODULE)mbi.AllocationBase;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;loader_ptr my_loader = GetProcAddress(hkernel, &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;LoadLibraryW&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;HMODULE injected = my_loader(L&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;unsupported.dll&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;FARPROC backdoor = GetProcAddress(injected, &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;backdoor&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;);
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Natürlich kann Windows dann immer noch das Laden innerhalb der Funktionen 
blockieren bzw. nur nach bestimmten Regeln zulassen. Man kann also nie sicher
sein, wann und wo der Hack wirklich funktioniert.&lt;/p&gt;

&lt;p&gt;Es gibt aber eine ähnliche Anwendung, die mir recht nützlich erscheint:&lt;br /&gt;
Man kann so auch “Nachbarfunktionen” dynamisch Laden, die gar nicht gesperrt
sind und diese Technik versetzt dann ältere Compiler oder ältere SDKs in die 
Lage Funktionen einzubinden, die sie offiziell gar nicht unterstützen.&lt;/p&gt;

&lt;p&gt;Ein Beispiel: Mit dem Wissen, dass einige WinRT Funktionen in &lt;code&gt;combase.dll&lt;/code&gt; 
implementiert sind und dort nun auch alte &lt;a href=&quot;https://de.wikipedia.org/wiki/Object_Linking_and_Embedding&quot;&gt;OLE&lt;/a&gt;
Routinen liegen, kann man daher “klassisch” linken und dann z.B. per 
&lt;code&gt;HMODULE&lt;/code&gt; von &lt;code&gt;CoCreateInstance()&lt;/code&gt; zu &lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/roapi/nf-roapi-rogetactivationfactory&quot;&gt;&lt;code&gt;RoGetActivationFactory&lt;/code&gt;&lt;/a&gt;
wechseln.&lt;br /&gt;
Dann hätte man nämlich Code, der Windows 7 kompatibel ist und trotzdem unter 
Windows 8 / Windows 10 innerhalb eines App-Pakets auf die Windows RunTime 
zugreifen könnte.
Der Linker entscheidet dann, was verfügbar ist und der Code kann ohne 
Änderungen beide Szenarien abbilden. Das wäre also in statischen Bibliotheken
ein gangbarer Weg, die keine unnötigen bzw. exklusive Abhängigkeiten eingehen
wollen.&lt;/p&gt;

&lt;p&gt;Ob das dann sinnvoll ist, ist natürlich eine ganz andere Frage ;)&lt;br /&gt;
Aber hey … wir wollen hier schließlich keine “bösen” Pfade beschreiten.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>WinRT und UWP mit purem C</title>
   <link href="https://www.opengate.at/blog/2021/01/winrt/"/>
   <published>2021-01-03T12:00:00+01:00</published>
   <updated>2021-01-03T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2021/01/winrt</id>
   <category term="devel" />
   <summary type="text">Metro Apps, WinRT 
(Windows Runtime), Immersive siehe 
IsImmersiveProcess
und jetzt also UWP
(Universal Windows Platform).
So viele Namen für eine Technologie, mit der Microsoft in die Zukunft gehen
wollte.

Sinnvoll oder nicht, darüber kann man streiten. Aber wie kommt man nun da ran?
</summary>
   <content type="html">&lt;p&gt;&lt;code&gt;Metro Apps&lt;/code&gt;, &lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_Runtime&quot;&gt;&lt;code&gt;WinRT&lt;/code&gt;&lt;/a&gt; 
(Windows Runtime), &lt;code&gt;Immersive&lt;/code&gt; siehe 
&lt;a href=&quot;http://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-isimmersiveprocess&quot;&gt;&lt;code&gt;IsImmersiveProcess&lt;/code&gt;&lt;/a&gt;
und jetzt also &lt;a href=&quot;https://de.wikipedia.org/wiki/Universal_Windows_Platform&quot;&gt;&lt;code&gt;UWP&lt;/code&gt;&lt;/a&gt;
(Universal Windows Platform).&lt;br /&gt;
So viele Namen für eine Technologie, mit der Microsoft in die Zukunft gehen
wollte.&lt;/p&gt;

&lt;p&gt;Sinnvoll oder nicht, darüber kann man streiten. Aber wie kommt man nun da ran?
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Mit fertigen Wizards für Apps möchte ich mich nicht aufhalten, schließlich 
sind nur für &lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_C%2B%2B&quot;&gt;MSVC&lt;/a&gt; wirksam. 
Und &lt;a href=&quot;https://de.wikipedia.org/wiki/.NET_Framework&quot;&gt;dotNet&lt;/a&gt; Zusammenklickereien
sind mir offen gesagt zu trivial, dass ich meine Zeit damit verschwende 
… das sollen die Anfänger machen.&lt;/p&gt;

&lt;p&gt;Bei &lt;a href=&quot;https://de.wikipedia.org/wiki/Component_Object_Model&quot;&gt;COM&lt;/a&gt; konnte man 
stets auf das “gute alte” &lt;a href=&quot;https://de.wikipedia.org/wiki/C_(Programmiersprache)&quot;&gt;C&lt;/a&gt; 
Interface zurücksteigen und damit jedem, und zwar wirklich jedem Compiler 
dessen Features eröffnen.
&lt;a href=&quot;http://docs.microsoft.com/en-us/windows/win32/api/combaseapi/nf-combaseapi-coinitializeex&quot;&gt;&lt;code&gt;CoInitializeEx()&lt;/code&gt;&lt;/a&gt; 
machte eine Thread COM-fähig, dann brauchte man noch den Interface-Header 
mit der Klasse und der richtigen Klassen-GUID und die Funktion 
&lt;a href=&quot;http://docs.microsoft.com/en-us/windows/win32/api/combaseapi/nf-combaseapi-cocreateinstance&quot;&gt;&lt;code&gt;CoCreateInstance()&lt;/code&gt;&lt;/a&gt; 
erzeugte auch schon eine &lt;a href=&quot;http://docs.microsoft.com/en-us/windows/win32/api/unknwn/nn-unknwn-iunknown&quot;&gt;&lt;code&gt;IUnknown&lt;/code&gt;&lt;/a&gt;
Instanz mit Referenzzähler &lt;code&gt;1&lt;/code&gt;.
Jetzt wechselte man noch (falls nötig) mit &lt;a href=&quot;http://docs.microsoft.com/en-us/cpp/atl/queryinterface?view=msvc-160&quot;&gt;&lt;code&gt;QueryInterface&lt;/code&gt;&lt;/a&gt; 
und der richtigen Interface-ID (&lt;code&gt;IID&lt;/code&gt;) zu der Schnittstelle, die man haben 
wollte, und schon konnte man COM-Methoden aufrufen.&lt;/p&gt;

&lt;p&gt;WinRT bzw. die “neue” UWP API baut bekanntlich auf COM auf und erweitert
&lt;code&gt;IUnknown&lt;/code&gt; zu &lt;a href=&quot;http://docs.microsoft.com/en-us/windows/win32/api/inspectable/nn-inspectable-iinspectable&quot;&gt;&lt;code&gt;IInspectable&lt;/code&gt;&lt;/a&gt;, 
damit ein Objekt zur Laufzeit fragen kann, welche Interfaces es unterstützt, 
weil &lt;code&gt;QueryInterface&lt;/code&gt; nur Ja oder Nein zu einer Interface Anfrage sagen kann.&lt;/p&gt;

&lt;p&gt;Aber &lt;em&gt;WIE&lt;/em&gt; lädt man nun WinRT/UWP Klassen in C bzw. purem C++?&lt;/p&gt;

&lt;h3 id=&quot;winrt-ohne-ccx&quot;&gt;WinRT ohne C++/CX?&lt;/h3&gt;

&lt;p&gt;Microsofts Compiler Erweiterungen sind ja alle recht nett (so wie auch 
C++/CLI), aber was soll man mit diesen Non-Standards, wenn z.B. den 
&lt;a href=&quot;https://de.wikipedia.org/wiki/MinGW&quot;&gt;MinGW&lt;/a&gt; nutzen möchte?&lt;/p&gt;

&lt;p&gt;Alles beginnt mit &lt;a href=&quot;http://docs.microsoft.com/en-us/windows/win32/api/roapi/nf-roapi-roinitialize&quot;&gt;&lt;code&gt;RoInitialize()&lt;/code&gt;&lt;/a&gt; 
um einen Thread auf WinRT vorzubereiten. Zuerst braucht man nun den &lt;code&gt;HSTRING&lt;/code&gt;,
also einen konstanten (Immutable) Unicodestring, der Klassenpfade beschreiben
kann. Die Funktionen &lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/winstring/nf-winstring-windowscreatestring&quot;&gt;&lt;code&gt;WindowsCreateString&lt;/code&gt;&lt;/a&gt;
und &lt;a href=&quot;http://docs.microsoft.com/en-us/windows/win32/api/winstring/nf-winstring-windowsdeletestring&quot;&gt;&lt;code&gt;WindowsDeleteString&lt;/code&gt;&lt;/a&gt;
lassen einen solchen entstehen.&lt;/p&gt;

&lt;p&gt;Die wichtigste Funktion zum laden und verwalten von WinRT/UWP Modulen ist
&lt;a href=&quot;http://docs.microsoft.com/en-us/windows/win32/api/roapi/nf-roapi-rogetactivationfactory&quot;&gt;&lt;code&gt;RoGetActivationFactory()&lt;/code&gt;&lt;/a&gt;. 
Ihr übergibt man den &lt;code&gt;HSTRING &lt;/code&gt;Klassenpfad um eine WinRT Klasse nutzen zu 
können.&lt;/p&gt;

&lt;p&gt;Hier gibt es einen wichtigen Unterschied zu COM, denn es gibt zwei Arten von
Methoden:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;WinRT Klassen können quasi “statische” Methoden haben, die es COM nicht gab.&lt;br /&gt;
Das Ergebnis von &lt;code&gt;RoGetActivationFactory()&lt;/code&gt; ist ein &lt;code&gt;IInspectable&lt;/code&gt;, von dem
man nun per &lt;code&gt;QueryInterface&lt;/code&gt; auf das Static-Interface der Klasse wechselt.
Dort hat man dann Zugriff auf die statischen Methoden.&lt;/li&gt;
  &lt;li&gt;Für WinRT Instanz-Objekte nutzt man &lt;code&gt;QueryInterface&lt;/code&gt; um vom zurückgegebenen
&lt;code&gt;IInspectable&lt;/code&gt; von &lt;code&gt;RoGetActivationFactory()&lt;/code&gt; auf das Interface 
&lt;a href=&quot;http://docs.microsoft.com/en-us/windows/win32/api/activation/nn-activation-iactivationfactory&quot;&gt;&lt;code&gt;IActivationFactory&lt;/code&gt;&lt;/a&gt; 
zu wechseln. Dieses unterstützt nämlich die Methode 
&lt;a href=&quot;http://docs.microsoft.com/en-us/windows/win32/api/activation/nf-activation-iactivationfactory-activateinstance&quot;&gt;&lt;code&gt;ActivateInstance()&lt;/code&gt;&lt;/a&gt; 
mit der eine neue Instanz des gewünschten WinRT Objektes erzeugt wird.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;(Natürlich kann man &lt;code&gt;QueryInterface()&lt;/code&gt; auch überspringen, wenn man 
&lt;code&gt;RoGetActivationFactory()&lt;/code&gt; gleich mit der korrekten &lt;code&gt;IID&lt;/code&gt; befüttert).&lt;/p&gt;

&lt;p&gt;Nun braucht man ganz analog zu COM immer die richtigen Interface-Header und 
Interface-IIDs um an die benötigten Methoden zu kommen.&lt;/p&gt;

&lt;h3 id=&quot;klassensuche&quot;&gt;Klassensuche&lt;/h3&gt;

&lt;p&gt;Schlimmer ist es, sich in dem Chaos von Headern zurecht zu finden. Und auch 
die Namen von Klassen sind in elendslangen Konstanten deklariert.&lt;/p&gt;

&lt;p&gt;Angenommen, man braucht Zufallszahlen. Die erhält man aus einer statischen
Methode des &lt;code&gt;CryptographicBuffer&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Dazu braucht man:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;#include &amp;lt;windows.security.cryptography.h&amp;gt;&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Der Klassenpfad ist in der Konstante 
&lt;code&gt;RuntimeClass_Windows_Security_Cryptography_CryptographicBuffer&lt;/code&gt; und lautet
einfach auf: &lt;code&gt;&quot;Windows.Security.Cryptography.CryptographicBuffer&quot;&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Die Interface-ID findet man in 
&lt;code&gt;IID___x_ABI_CWindows_CSecurity_CCryptography_CICryptographicBufferStatics&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Das C-Interface struct-typedef heißt:
&lt;code&gt;__x_ABI_CWindows_CSecurity_CCryptography_CICryptographicBufferStatics&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Und der VTBL-Pointer des Types &lt;code&gt;__x_ABI_CWindows_CSecurity_CCryptography_CICryptographicBufferStaticsVtbl&lt;/code&gt;
lässt uns dann endlich zur Method &lt;code&gt;GenerateRandomNumber()&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;… also “schön” sehen dieses langen Namen nicht aus … es handelt sich eben
um generierten C Code, der objektorientierte Features wie Namensräume 
abbilden soll.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;OK … da sieht man also recht deutlich, warum das Programmieren mit der 
C++ Erweiterung empfohlen wird.
Dort hat man dann zwar auch lange Namensräume für Klassen, wie
&lt;code&gt;ABI::Windows::Security::Cryptography::ICryptographicBufferStatics&lt;/code&gt; doch die
lassen sich leichter per IntelliSense nutzen als die hässlichen generierten
C Strukturen. Und wenn man noch &lt;code&gt;using namespace&lt;/code&gt; an erlaubten Stellen 
einsetzt, ist es fast so leicht wie in C#.&lt;/p&gt;

&lt;p&gt;However … für Extrembergsteiger sind steile Klippen kein Grund abzuspringen,
und so soll man sich auch nicht davon abhalten lassen, mit Nicht-&lt;code&gt;MSVC&lt;/code&gt; Compilern
in die WinRT Welt vorzudringen.&lt;/p&gt;

&lt;p&gt;Es geht nämlich! &lt;a href=&quot;https://de.wikipedia.org/wiki/Quod_erat_demonstrandum&quot;&gt;Quod erat demonstrandum!&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;PS: Übelste Hardcore-Challenge: Die nötigen RT-Interfaces selbst schreiben und
dort “bessere” Namen nutzen. Das hilft manchmal auch sehr.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Der Weg zu Notepad++</title>
   <link href="https://www.opengate.at/blog/2021/01/notepadpp/"/>
   <published>2021-01-02T12:00:00+01:00</published>
   <updated>2021-01-02T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2021/01/notepadpp</id>
   <category term="software" /><category term="retro" />
   <summary type="text">Es gibt heute keine Windows Installation bei mir, in welcher der Texteditor 
Notepad++ fehlt.

Doch wenn ich zurückdenke, war das nicht immer so, denn vor 10-15 Jahren
hatte ich noch eine strenge Trennung zwischen Quellcodes, 
Konfigurationsdateien und HTML.
</summary>
   <content type="html">&lt;p&gt;Es gibt heute keine Windows Installation bei mir, in welcher der Texteditor 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Notepad%2B%2B&quot;&gt;Notepad++&lt;/a&gt; fehlt.&lt;/p&gt;

&lt;p&gt;Doch wenn ich zurückdenke, war das nicht immer so, denn vor 10-15 Jahren
hatte ich noch eine strenge Trennung zwischen Quellcodes, 
Konfigurationsdateien und &lt;a href=&quot;https://de.wikipedia.org/wiki/Hypertext_Markup_Language&quot;&gt;HTML&lt;/a&gt;.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;code&gt;notepad.exe&lt;/code&gt; ist das wohl älteste Windows-Werkzeug, das es schon vor dem
mir bekannten &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_3.1&quot;&gt;Windows 3.1&lt;/a&gt; 
gab und welches bis heute in Windows 10 “DAS” Programm zum Lesen und 
Bearbeiten von Textdateien ist.&lt;/p&gt;

&lt;p&gt;Ein Fenster, ein Menü zum Laden und Speichern und eine fette mehrzeilige 
Textbox, mehr braucht man nicht um einen Texteditor zu erstellen und viel
mehr war und ist NotePad auch nicht.&lt;/p&gt;

&lt;p&gt;Doch wenn man Quellcodes bearbeiten möchte, sind Features wie andersfarbige
Schlüsselwörter oder erweiterte Suchfunktionen sehr empfehlenswert.
Und so gibt es heute zahlreiche Produkte, die das Wort “NotePad” im Namen
tragen und viel mehr können.&lt;/p&gt;

&lt;h3 id=&quot;ide-versus-web&quot;&gt;IDE versus Web&lt;/h3&gt;

&lt;p&gt;Als im Jahr 2000 mein Programmierwille größer wurde, waren die Welten klar 
abgetrennt. &lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_Basic_Classic&quot;&gt;Visual Basic&lt;/a&gt; 
kam mit seiner eigenen IDE zum Bearbeiten der Quelltexte, 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_C%2B%2B&quot;&gt;Visual C++&lt;/a&gt; ebenso.&lt;br /&gt;
Für das Web gab es zwar Microsoft’s &lt;a href=&quot;https://en.wikipedia.org/wiki/Microsoft_FrontPage&quot;&gt;FrontPage&lt;/a&gt;,
aber mal ehrlich, das haben ausschließlich talentfreie Möchtegern Freelancer
für ihre Visitenkarten-Homepages benutzt.&lt;/p&gt;

&lt;p&gt;Und so habe ich mit meinen ersten HTML Experimenten tatsächlich in Microsoft’s
Notepad begonnen. Doch dank “dem Internet” aber auch dank damaliger 
Zeitschriften mit Heft-CDs kam ich bald zu einem Editor namens 
&lt;a href=&quot;https://de.wikipedia.org/wiki/HTML-Editor_Phase_5&quot;&gt;&lt;code&gt;phase5&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Der damals junge Programmierer &lt;a href=&quot;https://krit.de/apfel-ulli-m.shtml&quot;&gt;Ulli Meybohm&lt;/a&gt;
hatte &lt;code&gt;phase5&lt;/code&gt; als Freeware für alle bereitgestellt und wurde für mich eine
Art Vorbild.&lt;br /&gt;
Der Editor existiert heute noch, wurde aber schon 2000 von Hans-Dieter Berretz
weiterentwickelt, der auch &lt;a href=&quot;https://www.phase5.info/index.php&quot;&gt;andere Projekte&lt;/a&gt;
betreut.&lt;br /&gt;
Ich hoffe Ulli und Hans-Dieter geht es gut und ich möchte ihnen heute 
nachträglich für ihre Werke danken. Sie haben mir damals eine tolle neue Welt
eröffnet bzw. den Zugang stark vereinfacht.&lt;br /&gt;
Meister Meybohm startete auch einen Multi-Sprachen Editor namens “Proton”, der
aber meines Wissens über die Betaphase nie hinausgekommen ist und heute nicht
mehr in Umlauf ist.&lt;/p&gt;

&lt;p&gt;Trotzdem wechselte ich (vermutlich so gegen 2002/2003) zu 
&lt;a href=&quot;https://thomas.weinert.info/&quot;&gt;Weaverslave&lt;/a&gt;. 
Dieser Editor hatte eine integrierte &lt;a href=&quot;https://de.wikipedia.org/wiki/PHP&quot;&gt;PHP&lt;/a&gt; 
Befehlsreferenz, was bei der Entwicklung von PHP Webseiten sehr nützlich war.&lt;/p&gt;

&lt;p&gt;Parallel dazu gewann so ab 2002 der 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Mono_(Software)&quot;&gt;dotNet-Nachbau “Mono”&lt;/a&gt;
einen Platz im  Rampenlicht und das Projekt 
&lt;a href=&quot;https://de.wikipedia.org/wiki/SharpDevelop&quot;&gt;SharpDevelop&lt;/a&gt; wurde öffentlich 
zugänglich.&lt;br /&gt;
Da Microsoft sein &lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_Studio#Version_.NET&quot;&gt;Visual Studio 2002&lt;/a&gt;
nur teuer verkaufte, war das kostenfreie SharpDevelop die erste OpenSource 
IDE, die ich einsetzte.&lt;br /&gt;
Mit SharpDevelop konnte man auch Textdateien wunderbar editieren und
HTML wie auch &lt;a href=&quot;https://de.wikipedia.org/wiki/Extensible_Markup_Language&quot;&gt;XML&lt;/a&gt;
mit Syntax-Highlighting überarbeiten.&lt;/p&gt;

&lt;p&gt;Doch hier kam es auch zum Bruch zwischen mir und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/.NET_Framework&quot;&gt;dotNet&lt;/a&gt;, denn die Trägheit
und Ressourcenhungrigkeit des Systems überforderten meine primitiven 
Computer damals regelmäßig und so kam der Editor eher selten bis nie zum
Einsatz.&lt;/p&gt;

&lt;p&gt;Nicht vergessen darf man dabei auf &lt;a href=&quot;http://bloodshed.net/&quot;&gt;Bloodsheed’s Dev-C++&lt;/a&gt;.
Doch in jenen Tagen war es leider noch zu früh für mich und C++.
Und so blieb es bei einer “Ah-nett-löschen” Installation.&lt;/p&gt;

&lt;h3 id=&quot;2008-bis-heute&quot;&gt;2008 bis heute&lt;/h3&gt;

&lt;p&gt;Mit meinem offiziellen und auch kommerziellen Einstieg in die C++ Welt gegen 
2007 und 2008, war ich auf lange Zeit nur mit zwei IDEs beschäftigt.
Microsofts Visual Studio für die Windows Seite und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Code::Blocks&quot;&gt;Code::Blocks&lt;/a&gt; für Linux bzw.
plattformübergreifende Angelegenheiten.&lt;/p&gt;

&lt;p&gt;Am liebsten wäre es mir ja gewesen, wenn CodeBlocks alles abgedeckt hätte, 
doch vor allem unter Linux bereitete mir diese IDE immer wieder mal 
sporadisch Crashes, wo Daten verloren gingen.
Auch Microsoft’s Studio 2005 und 2008 IDE legte dank fehlerhafter 
Intellisense Implementierungen immer wieder mal Crashes hin.&lt;/p&gt;

&lt;p&gt;Und weil ich das auf das häufige Springen zwischen mehreren Codefenstern
zurückführte, beschloss ich, nur ein primäres Codefenster in der IDE offen 
zu halten und öffnete “zum Nachsehen” externe Codes in separaten Editoren.&lt;/p&gt;

&lt;p&gt;Das war die Stelle, wo sich Notepad++ bei mir als Universalwerkzeug 
einnistete und bis heute dort geblieben ist.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Egal, ob mal XML-Dateien oder JSON Strukturen ansehen möchte, Notepad++ 
hält ein Plugin bereit.&lt;br /&gt;
Auch Mark-Down, der für diesen Blog benutzt wird, zeigt es gut erkennbar
und formatiert an.&lt;br /&gt;
Die Standardsprachen von C++ bis VB und alle gängigen Scriptsprachen 
glänzen mit sauberem Codehighlighting darin und wenn mal eine Studio
Solution bockt, wird auch sie manuell in Notepad++ nachbearbeitet.&lt;/p&gt;

&lt;p&gt;Am meisten liebe ich Notepad++ aber für seine Stabilität. Ich glaube,
ich habe es noch nie zum Absturz gebracht … bestenfalls eines der
HEX-Editor Plugins zeigt mal Blödsinn an … aber das liegt dann ja am
Plugin und nicht am Editor selbst.&lt;/p&gt;

&lt;p&gt;Kurz gesagt: Ich liebe und brauche dieses Tool und ob gleich 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_Studio_Code&quot;&gt;Visual Studio Code&lt;/a&gt; 
heute viele ebenso nützliche Features bereitstellt, in Sachen Performance 
bleibe ich wohl noch einige Zeit bei NP++.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Alles Gute für 2021</title>
   <link href="https://www.opengate.at/blog/2021/01/happy-new-year/"/>
   <published>2021-01-01T12:00:00+01:00</published>
   <updated>2021-01-01T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2021/01/happy-new-year</id>
   <category term="general" />
   <summary type="text">Das Corona Jahr 2020 
ist vorbei und mit dem Jahreswechsel steigt der Optimismus, 
dass 2021 alles besser wird.

Dem schließe ich mich mal an.
</summary>
   <content type="html">&lt;p&gt;Das &lt;a href=&quot;https://de.wikipedia.org/wiki/COVID-19-Pandemie&quot;&gt;Corona&lt;/a&gt; Jahr 2020 
ist vorbei und mit dem Jahreswechsel steigt der Optimismus, 
dass 2021 alles besser wird.&lt;/p&gt;

&lt;p&gt;Dem schließe ich mich mal an.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Die guten Vorsätze sind schon mal da:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Gesünder essen (wieder mal)&lt;/li&gt;
  &lt;li&gt;Mehr Bewegung trotz Lock-down&lt;/li&gt;
  &lt;li&gt;Zeit effizienter nutzen (z.B. Weniger 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Minecraft&quot;&gt;MineCraft&lt;/a&gt;, mehr Code schreiben)&lt;/li&gt;
  &lt;li&gt;Sozialprojekte mehr fördern&lt;/li&gt;
  &lt;li&gt;Arbeitszeiten in der Firma besser planen&lt;/li&gt;
  &lt;li&gt;Mal etwas ganz Neues und Unbekanntes lernen&lt;/li&gt;
  &lt;li&gt;Keine Verwaltungs- und Zahlungstermine mehr vergessen 
(und dann Strafe zahlen …)&lt;/li&gt;
  &lt;li&gt;Weniger einkaufen und bereits Gekauftes besser und gezielter nutzen.&lt;/li&gt;
  &lt;li&gt;Wieder mehr an Hardware basteln&lt;/li&gt;
  &lt;li&gt;Und natürlich das GATE Projekt ausbauen&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Mal sehen, wie viel sich davon umsetzen lässt.
Auf jeden Fall hoffe ich für meine Umgebung, dass wir wirtschaftlich wieder
auf die Beine kommen und die Corona-Krise zu einem Ende kommt.&lt;/p&gt;

&lt;p&gt;Es wird Zeit für mehr Optimismus und Fortschritt!&lt;/p&gt;

&lt;p&gt;Und in diesem Sinne wünsche ich allen ein herzliches:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;em&gt;Prosit Neujahr!&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>Das Jahr 2020</title>
   <link href="https://www.opengate.at/blog/2020/12/year-2020/"/>
   <published>2020-12-31T12:00:00+01:00</published>
   <updated>2020-12-31T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2020/12/year-2020</id>
   <category term="general" />
   <summary type="text">An dieser Stelle müsste nun eigentlich stehen:


  Das schlimmste Jahr aller Zeiten.


Aber so war es für mich nicht.

Es war auch kein Jahr “wie immer”, sondern genau so
besonders wie die anderen auch auf deren Weise.
</summary>
   <content type="html">&lt;p&gt;An dieser Stelle müsste nun eigentlich stehen:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Das schlimmste Jahr aller Zeiten.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Aber so war es für mich nicht.&lt;/p&gt;

&lt;p&gt;Es war auch kein Jahr “wie immer”, sondern genau so
besonders wie die anderen auch auf deren Weise.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Es hat bis in den Herbst gedauert, bis ich vom ersten 
&lt;a href=&quot;https://de.wikipedia.org/wiki/COVID-19-Pandemie&quot;&gt;Corona&lt;/a&gt; Fall im 
Bekanntenkreis gehört hatte. Dieser ging zwar nicht tödlich aus, hat aber bis
heute ein Nachspiel mit Organschädigungen, die nicht mal eben so abheilen.&lt;/p&gt;

&lt;p&gt;Und so muss auch ich am Ende des Jahres 2020 eingestehen, dass ich die 
Folgen der Pandemie vielleicht nicht ernst genug genommen habe.&lt;/p&gt;

&lt;p&gt;Ich bin weiter davon überzeugt, dass viele Maßnahmen an einigen Stellen 
überzogen waren und großen Schaden angerichtet haben, während an anderen
Orten Tatenlosigkeit vorherrschte.&lt;br /&gt;
Dennoch haben uns die letzten Monate gelehrt, wie schnell das Ganze außer 
Kontrolle geraten kann.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Ich habe das vergangene Jahr eigentlich sehr gut überstanden und muss es 
auch als recht positiv in meine Biographie aufnehmen.&lt;br /&gt;
Es freut mich, dass die IT-Technik mal beweisen konnte, dass sie auch 
Probleme lösen kann, anstatt neue zu schaffen und dass sie die Menschen
entlasten kann.&lt;/p&gt;

&lt;p&gt;Vielleicht werden wir auch die USA in Zukunft wieder als konstruktive Kraft
am runden Tisch begrüßen dürfen, nun wo der Alptraum 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Donald_Trump&quot;&gt;Donald Trump&lt;/a&gt; 
hoffentlich bald zu Ende geht.&lt;/p&gt;

&lt;p&gt;Und bei solchen Gelegenheiten muss ich immer wieder an das rührende Ende
des &lt;a href=&quot;https://de.wikipedia.org/wiki/Marvel_Cinematic_Universe&quot;&gt;Marvel&lt;/a&gt; 
Blockbusters &lt;a href=&quot;https://de.wikipedia.org/wiki/Black_Panther_(Film)&quot;&gt;Black Panther&lt;/a&gt; 
denken, wo hier bei mir in Wien folgende starke Worte gesprochen werden&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Wir werden als gutes Beispiel voran gehen, als Beispiel dafür, 
wie wir uns als Brüder und Schwestern auf dieser Erde gegenseitig 
behandeln sollten.&lt;br /&gt;
Heute mehr als je zuvor bedrohen Missverständnisse und Vorurteile 
unsere kostbare Existenz, dabei kennen wir alle die Wahrheit:&lt;br /&gt;
Es verbindet uns viel mehr, als uns trennt.&lt;/p&gt;

  &lt;p&gt;In Zeiten der Krise bauen die Weisen Brücken, 
während die Narren Mauern errichten.&lt;br /&gt;
Wir müssen einen Weg finden gegenseitig auf uns Acht zu geben.&lt;br /&gt;
So als wären wir ein einziges Volk.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;iframe width=&quot;640&quot; height=&quot;360&quot; src=&quot;/blog/redirect.html?https%3A%2F%2Fwww.youtube-nocookie.com%2Fembed%2FgB83bZVXv_k&quot; frameborder=&quot;1&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;

&lt;p&gt;Und damit hat König &lt;a href=&quot;https://marvel-filme.fandom.com/de/wiki/T%27Challa&quot;&gt;T’Challas&lt;/a&gt; 
vollkommen recht!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Auf ein frohes Neues!&lt;/em&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>JibJab Reviews</title>
   <link href="https://www.opengate.at/blog/2020/12/jibjab/"/>
   <published>2020-12-27T12:00:00+01:00</published>
   <updated>2020-12-27T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2020/12/jibjab</id>
   <category term="entertainment" />
   <summary type="text">Sie hatten mich mit “Big Box Mart” sofort überzeugt und 
mit “What we call the News” war ich verliebt. Dann veröffentlichten sie
ihre jährliche Zusammenfassung des Jahres mit “coolem” Soundtrack.

Und plötzlich im Jahr 2014 war einfach Schluss.

Doch 2020 kamen sie dank COVID19
zurück und nun gibt es endlich wieder ein:

JibJab.com Year in Review!
</summary>
   <content type="html">&lt;p&gt;Sie hatten mich mit “Big Box Mart” sofort überzeugt und 
mit “What we call the News” war ich verliebt. Dann veröffentlichten sie
ihre jährliche Zusammenfassung des Jahres mit “coolem” Soundtrack.&lt;/p&gt;

&lt;p&gt;Und plötzlich im Jahr 2014 war einfach Schluss.&lt;/p&gt;

&lt;p&gt;Doch 2020 kamen sie dank &lt;a href=&quot;https://de.wikipedia.org/wiki/COVID-19&quot;&gt;COVID19&lt;/a&gt;
zurück und nun gibt es endlich wieder ein:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://jibjab.com&quot;&gt;JibJab.com&lt;/a&gt; &lt;strong&gt;Year in Review&lt;/strong&gt;!
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;was-macht-jibjabcom&quot;&gt;Was macht JibJab.com?&lt;/h3&gt;

&lt;p&gt;JibJab.com produziert “Sendables”, eine Art von Online-Postkarte als Video
mit lustiger Musik und selbst hochladbaren Fotos für diverse Szenen.
Dort kann man sich (oder andere) “in Szene” setzen und dann darüber lachen,
was durch witzige musikalische Beträge unterstrichen wird.&lt;/p&gt;

&lt;p&gt;Bekannt gemacht wurde mir JibJab tatsächlich durch ihre “politischen” 
Präsentationen erstmals im Jahr 2004, wo sie zur 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Pr%C3%A4sidentschaftswahl_in_den_Vereinigten_Staaten_2004&quot;&gt;US Präsidentschaftswahl&lt;/a&gt;
ein Video mit &lt;a href=&quot;https://de.wikipedia.org/wiki/George_W._Bush&quot;&gt;George W. Bush&lt;/a&gt; und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/John_Kerry&quot;&gt;John Kerry&lt;/a&gt; veröffentlichten.&lt;/p&gt;

&lt;p&gt;Nun hatte ich etwas, wonach ich “suchen” konnte und stieß auf das zuvor
veröffentlichte Video “Big Box Mart”, das ich bis heute zu den besten
Sozialkritiken zähle. Es mag auf den US-amerikanischen Markt zugeschnitten
sein, aber mal ehrlich, bei uns läuft es nicht viel anders:&lt;/p&gt;

&lt;h4 id=&quot;big-box-mart---wer-kauft-gerne-billig-ein&quot;&gt;Big Box Mart - Wer kauft gerne billig ein?&lt;/h4&gt;
&lt;iframe width=&quot;640&quot; height=&quot;360&quot; src=&quot;/blog/redirect.html?https%3A%2F%2Fwww.youtube-nocookie.com%2Fembed%2FpKv6RcXa2UI&quot; frameborder=&quot;1&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;

&lt;p&gt;Danach folgte dann mit “What we call the news” ein leider nur
all zu realistisches Zerrbild unserer Tagesnachrichten. Selbst in Europa 
verging damals kein Tag, wo nicht täglich jede Handbewegung im 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Irakkrieg&quot;&gt;Irakkrieg&lt;/a&gt; dramatisch berichtet 
und pseudo-kritisch kommentiert wurde:&lt;/p&gt;

&lt;h4 id=&quot;what-we-call-the-news---es-folgen-die-tagesnachrichten&quot;&gt;What we call the News - Es folgen die Tagesnachrichten&lt;/h4&gt;
&lt;iframe width=&quot;640&quot; height=&quot;360&quot; src=&quot;/blog/redirect.html?https%3A%2F%2Fwww.youtube-nocookie.com%2Fembed%2F3Q2EPKKVrqI&quot; frameborder=&quot;1&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;

&lt;h3 id=&quot;der-jahresrückblick-von-2005-bis-2014&quot;&gt;Der Jahresrückblick von 2005 bis 2014&lt;/h3&gt;

&lt;p&gt;Jedes Jahr im Dezember wurde unter dem Titel “JibJab Originals” ein 
Scherzvideo veröffentlicht, das die Ereignisse des vergangen Jahres 
zusammenfassen sollte.&lt;br /&gt;
Das ganze war natürlich sehr US-amerikanisch fokussiert, doch das eine oder
andere internationale Ereignis hatte ebenso seinen Auftritt.&lt;/p&gt;

&lt;p&gt;Und so sind die JibJab Videos seit 15 Jahren in den letzten Tagen vor Neujahr
immer bei mir auf der YouTube Watchlist.&lt;br /&gt;
Da kann man schön an die vergangen Jahre denken … und manchmal auch darüber
hinaus.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Wie zum Beispiel im Jahr 2005, als George W Bush seinen Jahresablauf
mit Countrymusic-Style vorsang:&lt;/p&gt;
&lt;iframe width=&quot;640&quot; height=&quot;360&quot; src=&quot;/blog/redirect.html?https%3A%2F%2Fwww.youtube-nocookie.com%2Fembed%2F3ThHrqlGdSk&quot; frameborder=&quot;1&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;!-- 2005 https://www.youtube.com/watch?v=3ThHrqlGdSk --&gt;

&lt;hr /&gt;

&lt;p&gt;Oder wie 2006 einige Kinder in einem Schultheaterstück die Erlebnisse 
bekannter Prominenter Revue passieren ließen:&lt;/p&gt;
&lt;iframe width=&quot;640&quot; height=&quot;360&quot; src=&quot;/blog/redirect.html?https%3A%2F%2Fwww.youtube-nocookie.com%2Fembed%2FMLQ928VhyxM&quot; frameborder=&quot;1&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;!-- 2006 https://www.youtube.com/watch?v=MLQ928VhyxM --&gt;

&lt;hr /&gt;

&lt;p&gt;2007 mussten sich Engel überlegen, wie sie “dem Meister” erklären sollen,
warum auf der Erde so viel Mist passiert, und schilderten ihm nur die guten
Dinge:&lt;/p&gt;
&lt;iframe width=&quot;640&quot; height=&quot;360&quot; src=&quot;/blog/redirect.html?https%3A%2F%2Fwww.youtube-nocookie.com%2Fembed%2Fztj2qfui114&quot; frameborder=&quot;1&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;!-- 2007 https://www.youtube.com/watch?v=ztj2qfui114 --&gt;

&lt;hr /&gt;

&lt;p&gt;Das Neujahrsbaby für 2009 bekam dann eine Lektion über die Wirtschaftskrise
vom Neujahrsbaby von 2008:&lt;/p&gt;
&lt;iframe width=&quot;640&quot; height=&quot;360&quot; src=&quot;/blog/redirect.html?https%3A%2F%2Fwww.youtube-nocookie.com%2Fembed%2FRmEP93NVTaw&quot; frameborder=&quot;1&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;!-- 2008 https://www.youtube.com/watch?v=RmEP93NVTaw --&gt;

&lt;hr /&gt;

&lt;p&gt;Im nächsten Jahr fuhr dann die Eisenbahn durch die Zeit und prallte auf die
seltsamen Ereignisse des Jahres 2009:&lt;/p&gt;
&lt;iframe width=&quot;640&quot; height=&quot;360&quot; src=&quot;/blog/redirect.html?https%3A%2F%2Fwww.youtube-nocookie.com%2Fembed%2FeKYe1KiwywE&quot; frameborder=&quot;1&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;!-- 2009 https://www.youtube.com/watch?v=eKYe1KiwywE --&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Barack_Obama&quot;&gt;Barak Obama&lt;/a&gt; und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Joe_Biden&quot;&gt;Joe Biden&lt;/a&gt; durften dann 2010 als
Stoffpuppen ihren unguten Job besingen:&lt;/p&gt;
&lt;iframe width=&quot;640&quot; height=&quot;360&quot; src=&quot;/blog/redirect.html?https%3A%2F%2Fwww.youtube-nocookie.com%2Fembed%2FCCuoLd0K4lY&quot; frameborder=&quot;1&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;!-- 2010 https://www.youtube.com/watch?v=CCuoLd0K4lY --&gt;

&lt;hr /&gt;

&lt;p&gt;Buh-Bye hieß es dann für alle Skandale, die im Jahr 2011 öffentlich wurden:&lt;/p&gt;
&lt;iframe width=&quot;640&quot; height=&quot;360&quot; src=&quot;/blog/redirect.html?https%3A%2F%2Fwww.youtube-nocookie.com%2Fembed%2F2zls4Ao3GyM&quot; frameborder=&quot;1&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;!-- 2011 https://www.youtube.com/watch?v=2zls4Ao3GyM --&gt;

&lt;hr /&gt;

&lt;p&gt;Laut &lt;a href=&quot;https://de.wikipedia.org/wiki/Maya-Kalender&quot;&gt;Maya Kalender&lt;/a&gt; sollte dann 
2012 die Welt untergehen … oder zumindest wurde es der Trend in der 
Google Suche:&lt;/p&gt;
&lt;iframe width=&quot;640&quot; height=&quot;360&quot; src=&quot;/blog/redirect.html?https%3A%2F%2Fwww.youtube-nocookie.com%2Fembed%2FG0zf7EWZET0&quot; frameborder=&quot;1&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;!-- 2012 https://www.youtube.com/watch?v=G0zf7EWZET0 --&gt;

&lt;hr /&gt;

&lt;p&gt;2013 war es endlich mal wieder Zeit für ein Bühnenstück, wo die Celebrities
ihre aktuellen Handlungen darstellen konnten:&lt;/p&gt;
&lt;iframe width=&quot;640&quot; height=&quot;360&quot; src=&quot;/blog/redirect.html?https%3A%2F%2Fwww.youtube-nocookie.com%2Fembed%2F7vNy05_3QV4&quot; frameborder=&quot;1&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;!-- 2013 https://www.youtube.com/watch?v=7vNy05_3QV4 --&gt;

&lt;hr /&gt;

&lt;p&gt;Und mit der Kunstausstellung “2014 Retrospective” endete leider die
zehnjährige Serie an JibJab Reviews:&lt;/p&gt;
&lt;iframe width=&quot;640&quot; height=&quot;360&quot; src=&quot;/blog/redirect.html?https%3A%2F%2Fwww.youtube-nocookie.com%2Fembed%2FYkqaq3KNPsc&quot; frameborder=&quot;1&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;!-- 2014 https://www.youtube.com/watch?v=Ykqaq3KNPsc --&gt;

&lt;h3 id=&quot;2020-youve-got-to-go&quot;&gt;2020, You’ve Got to Go&lt;/h3&gt;

&lt;p&gt;Wie sah das letzte Jahr mit COVID-19 und dem Lockdown aus? JibJab zeigt es 
uns. Vom fehlenden Klopapier bis zur Wahl von Joe Biden sind die wenigen 
Highlights und viele Homestories zusammengefasst:&lt;/p&gt;
&lt;iframe width=&quot;640&quot; height=&quot;360&quot; src=&quot;/blog/redirect.html?https%3A%2F%2Fwww.youtube-nocookie.com%2Fembed%2FnNaGzi_LpDw&quot; frameborder=&quot;1&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;!-- 2020 https://www.youtube.com/watch?v=nNaGzi_LpDw --&gt;

&lt;p&gt;Und mit dem Slogan “2021, We’re ready for you!” endet das neueste Video der
kreativen Videofabrik.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Was soll ich noch sagen … ich liebe diese Art von Humor einfach. Und die
Soundtracks eignen sich auch gut um die Stimmung zu heben.
Von daher kann ich die Videos, die alle auf YouTube vertreten sind, jedem 
empfehlen.&lt;/p&gt;

&lt;h3 id=&quot;nachtrag&quot;&gt;Nachtrag&lt;/h3&gt;

&lt;p&gt;Es gibt auch noch ein paar weitere Videos aus dem Umfeld von Politik und
Kultur. Hier eine Liste, die man natürlich stets erweitern kann:&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Ahnuld for Governor - Als Schwarzenegger “mehr” werden wollte:&lt;/p&gt;
&lt;iframe width=&quot;640&quot; height=&quot;360&quot; src=&quot;/blog/redirect.html?https%3A%2F%2Fwww.youtube-nocookie.com%2Fembed%2FTaIWM2ruyK4&quot; frameborder=&quot;1&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;!-- https://www.youtube.com/watch?v=TaIWM2ruyK4 --&gt;

&lt;hr /&gt;

&lt;p&gt;Matzah! Rap - Hip Hop für Juden:&lt;/p&gt;
&lt;iframe width=&quot;640&quot; height=&quot;360&quot; src=&quot;/blog/redirect.html?https%3A%2F%2Fwww.youtube-nocookie.com%2Fembed%2FOlg1efSlvLg&quot; frameborder=&quot;1&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;!-- https://www.youtube.com/watch?v=Olg1efSlvLg --&gt;

&lt;hr /&gt;

&lt;p&gt;This Land! - Vor der US Wahl 2004:&lt;/p&gt;
&lt;iframe width=&quot;640&quot; height=&quot;360&quot; src=&quot;/blog/redirect.html?https%3A%2F%2Fwww.youtube-nocookie.com%2Fembed%2Fz8Q-sRdV7SY&quot; frameborder=&quot;1&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;!-- https://www.youtube.com/watch?v=z8Q-sRdV7SY --&gt;

&lt;hr /&gt;

&lt;p&gt;Good to be in DC! - Auch vor der US Wahl 2004:&lt;/p&gt;
&lt;iframe width=&quot;640&quot; height=&quot;360&quot; src=&quot;/blog/redirect.html?https%3A%2F%2Fwww.youtube-nocookie.com%2Fembed%2Fm0OXJneDQ1s&quot; frameborder=&quot;1&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;!-- https://www.youtube.com/watch?v=m0OXJneDQ1s --&gt;

&lt;hr /&gt;

&lt;p&gt;Second Term - Nach der US Wahl 2004:&lt;/p&gt;
&lt;iframe width=&quot;640&quot; height=&quot;360&quot; src=&quot;/blog/redirect.html?https%3A%2F%2Fwww.youtube-nocookie.com%2Fembed%2FhE8V22unwRo&quot; frameborder=&quot;1&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;!-- https://www.youtube.com/watch?v=hE8V22unwRo --&gt;

&lt;hr /&gt;

&lt;p&gt;Time for some Campaignin’ - Vor der US Wahl 2008:&lt;/p&gt;
&lt;iframe width=&quot;640&quot; height=&quot;360&quot; src=&quot;/blog/redirect.html?https%3A%2F%2Fwww.youtube-nocookie.com%2Fembed%2Fadc3MSS5Ydc&quot; frameborder=&quot;1&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;!-- https://www.youtube.com/watch?v=adc3MSS5Ydc --&gt;

&lt;hr /&gt;

&lt;p&gt;Barak Obama als Pseudo-Superheld:&lt;/p&gt;
&lt;iframe width=&quot;640&quot; height=&quot;360&quot; src=&quot;/blog/redirect.html?https%3A%2F%2Fwww.youtube-nocookie.com%2Fembed%2FkVFdAJRVm94&quot; frameborder=&quot;1&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;!-- https://www.youtube.com/watch?v=kVFdAJRVm94 --&gt;

&lt;hr /&gt;

&lt;p&gt;… ähm, spinne ich, oder kommt &lt;a href=&quot;https://en.wikipedia.org/wiki/Monica_Lewinsky&quot;&gt;Monica Lewinsky&lt;/a&gt;
in fast allen Videos vor? Also auch in denen ohne Clinton?&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Doch 5G in Wien</title>
   <link href="https://www.opengate.at/blog/2020/12/5g-80/"/>
   <published>2020-12-26T12:00:00+01:00</published>
   <updated>2020-12-26T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2020/12/5g-80</id>
   <category term="hardware" /><category term="software" />
   <summary type="text">Als ich vor einem Monat meinen 5G Router 
zugeschickt bekam, war ich pessimistisch, weil ich keinen 
5G Empfang feststellen konnte.

Doch jetzt weiß ich: Der alte Vertrag lief noch bis zum 22. Dezember
und erst mit diesem Datum wurde 5G für mich freigeschaltet.

Und es ist sau-geil!
</summary>
   <content type="html">&lt;p&gt;Als ich &lt;a href=&quot;/blog/2020/11/5g/&quot;&gt;vor einem Monat meinen 5G Router&lt;/a&gt; 
zugeschickt bekam, war ich pessimistisch, weil ich keinen 
&lt;a href=&quot;https://de.wikipedia.org/wiki/5G&quot;&gt;5G&lt;/a&gt; Empfang feststellen konnte.&lt;/p&gt;

&lt;p&gt;Doch jetzt weiß ich: Der alte Vertrag lief noch bis zum 22. Dezember
und erst mit diesem Datum wurde 5G für mich freigeschaltet.&lt;/p&gt;

&lt;p&gt;Und es ist sau-geil!
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Hmm, da versucht man sich in buddhistischer Bescheidenheit und bekräftigt
stets, dass die Datenrate nicht wichtig sei … doch der Switch von 30 MBit
auf 80 ging selbst an mir nicht ohne Emotion vorbei.&lt;/p&gt;

&lt;p&gt;Denn obwohl ich schon letztes Monat die neue Hardware und SIM-Karte zugesendet
bekommen hatte, wurde erst kürzlich das 5G Netz für mich freigeschaltet.&lt;br /&gt;
Und während &lt;a href=&quot;https://de.wikipedia.org/wiki/Long_Term_Evolution&quot;&gt;LTE&lt;/a&gt; bei mir 
am Fensterbrett eher mangelhaft empfangen wurde (immer 1 bis 2 Strichlein von 
5 in der Anzeige), erhöht der 5G Empfang die Qualitätsanzeige auf ‘ne satte 3.&lt;/p&gt;

&lt;p&gt;Im Alltag bemerke ich Internet-Performance-Probleme kaum, denn schließlich 
sind meine Primärseiten textbasiert und technische Dokus sind zum Glück
nicht ganz so schlimm mit widerwärtigen Werbeinhalten verseucht.&lt;br /&gt;
Doch wenn &lt;a href=&quot;https://de.wikipedia.org/wiki/YouTube&quot;&gt;YouTube&lt;/a&gt; oder 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Netflix&quot;&gt;Netflix&lt;/a&gt; läuft, sollte keine neues 
Windows-Image parallel heruntergeladen werden, weil dann einer der beiden 
Dienste darunter zu leiden hatte.&lt;/p&gt;

&lt;p&gt;Denn meine 30 MBit im LTE Netz wurden ja auch tagesabhängig reduziert und
nachdem Inhalte leider immer größer aufgebläht werden, ergeben sich dann 
Downloads von mehreren Stunden oder die Unmöglichkeit Videos flüssig
zu streamen.&lt;/p&gt;

&lt;p&gt;Doch nun zeigen mir Internet-Speed-Tests zu fast jeder Tageszeit 85 bis 90
MBit/s an, obwohl ich offiziell nur 80 erhalten sollte.
Das mag vielleicht daran liegen, dass heute noch wenige 5G Geräte das Netz
belasten.&lt;/p&gt;

&lt;p&gt;Auf jeden Fall passierte es nun schon, dass ich dachte:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ach Mist, ich muss den Stream für einen Download unterbrechen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Und dann stellte ich fest, das beides parallel problemlos abgearbeitet wurde.&lt;br /&gt;
Soll heißen: Die 80 MBit/s im 5G Netz haben sich für mich extrem deutlich
bemerkbar gemacht.&lt;/p&gt;

&lt;p&gt;Das Router-Webinterface stellt auch eine Analyse zur Signalstärke bereit, die
vor meinem Upgrade eine sehr schlechte Position anmerkte und die Empfehlung
zum Umzug in einen anderen Raum ausgab. Doch nun meint die Software, es wäre
alles perfekt und ist voll funktionsbereit.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/5g-router-3.png&quot; alt=&quot;5G Router Web UI&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Doch ein Problem bahnt sich jetzt wieder an:&lt;/p&gt;

&lt;p&gt;Nun, Ende 2020 ist es also wieder passiert, dass das “mein” Internet eine 
Netzwerkgrößenordnung zu überspringen droht.&lt;br /&gt;
Und so wird mein altes &lt;a href=&quot;https://de.wikipedia.org/wiki/Twisted-Pair-Kabel#Kategorie_5&quot;&gt;CAT-5&lt;/a&gt; 
Kabel zwischen internem Router und Breitband-Router mit seinen 100 MBit/s 
bald zum Flaschenhals werden.&lt;br /&gt;
Ich habe dieses 8-Meter-Kabel seit bald 15 Jahren im Einsatz und damals war es
für das Internet eigentlich überdimensioniert.
(Da fällt mir wieder ein, dass ich so ein Thema mit den 10 MBit-Netzwerkkarten 
vor vielen Jahren schon mal hatte …)&lt;/p&gt;

&lt;p&gt;Wäre ich nicht so geizig, könnte mich mein Internetanbieter schon heute mit 
bis zu 150 MBit/s oder mehr versorgen, und damit sollte der Wechsel auf CAT-6
und einen neuen internen Router notwendig werden.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Nun, man soll die Kirche im Dorf lassen und keine Revolution ausrufen, wenn 
einem mal der Mund offen bleibt.&lt;br /&gt;
Trotzdem freue ich mich nun sehr über meinen Geschwindigkeitsgewinn, 
der im Jahr nur etwa 72 Euro Zusatzkosten verursacht.&lt;/p&gt;

&lt;p&gt;Während sich einige meiner Arbeitskollegen mit 300 MBit/s wegen Trägheit
beschweren, halte ich jede Netzanbindung über 10 MBit für ein kleines Wunder.
Zu lange war “Internet” mit 5 KBit/s limitiert, von daher ist die
behauptete Notwendigkeit von solchen Geschwindigkeiten aus meiner Sicht 
einfach nur “astronomisch”.&lt;/p&gt;

&lt;p&gt;Wie auch immer … auch ich freue mich wenn am Freitag die nächste 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Star_Trek:_Discovery&quot;&gt;Star Trek Discovery&lt;/a&gt; 
Folge in 30 Sekunden heruntergeladen ist und die Netflix App nicht wie 
früher 5 bis 10 Minuten daran nuckelt.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Als die Erde still stand</title>
   <link href="https://www.opengate.at/blog/2020/12/xmas/"/>
   <published>2020-12-24T12:00:00+01:00</published>
   <updated>2020-12-24T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2020/12/xmas</id>
   <category term="general" />
   <summary type="text">Die Lösung vieler Probleme der Menschen wäre so einfach:


  Entschleunigung


Doch nein, man muss noch einkaufen, anrufen, buchen, bestellen,
bezahlen, rückabwickeln, …
</summary>
   <content type="html">&lt;p&gt;Die Lösung vieler Probleme der Menschen wäre so einfach:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Entschleunigung&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Doch nein, man muss noch einkaufen, anrufen, buchen, bestellen,
bezahlen, rückabwickeln, …
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Das &lt;a href=&quot;https://de.wikipedia.org/wiki/COVID-19-Pandemie&quot;&gt;COVID-19 Corona Virus&lt;/a&gt; 
hat uns eines bewiesen, was bisher immer angezweifelt wurde:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Es geht auch anders.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Hat man uns nicht immer gesagt, man könne den Flugverkehr nicht anhalten,
weil das einfach nicht geht? Autobahnen sind immer befahren, die Straße 
schläft nie. Und jeder von uns MUSS X mal Urlaub im Ausland machen, weil 
sonst hätte man ja “nichts zu erzählen”.&lt;/p&gt;

&lt;p&gt;Plötzlich gibt es eine Krankheitsmeldung und dann passiert, was viel zu lange
nicht mehr geschehen ist: Der Planet kann sich endlich von seiner Infektion
durch die Menschheit erholen.&lt;br /&gt;
Die Tier- und Pflanzenwelt kann aufatmen, weil der Feinstaub zurückgeht,
weil wir nicht für 100 Schritte ins Auto steigen. 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Seismograph&quot;&gt;Seismographen&lt;/a&gt; entdecken 
erstmals, dass die Welt weniger zittert, weil wir es mal ruhig haben 
angehen lassen.&lt;/p&gt;

&lt;p&gt;Und ich hatte ein sehr entspanntes Arbeitsjahr, in dem ich vielleicht sogar
mehr gearbeitet habe, als in den Jahren zuvor, und dennoch war ich glücklich. 
Vielleicht weil ich nicht ständig auf Urzeiten achten musste. 
Weil ich während Meetings zur Toilette konnte und per Headset mithören konnte
(Mikrofon natürlich stumm geschaltet!) und nicht mit Druck auf der Blase 
20 Minuten ausharren musste.
Oder weil ich mal ungezwungen aufstehen konnte, auf und ab gehen konnte und
dafür am Abend ein paar Minuten länger “im Dienst” geblieben bin, ohne dass
gleich ein Bürokratiekrieg aufzog.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Heute heißt es im katholischen Österreich wieder:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Stille_Nacht,_heilige_Nacht&quot;&gt;Stille Nacht, heilige Nacht&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Das sollten wir uns wieder mal mehr verinnerlichen. Nämlich, dass Stille 
alleine etwas Heilsames haben kann.&lt;/p&gt;

&lt;p&gt;Musste erst ein Virus kommen, das uns etwas klar macht, was die Philosophen
vor Jahrtausenden diskutiert hatten? Anstatt allem mit Hektik und Panik zu
begegnen kann man auch mal durchatmen, mit den Augen zwinkern und sich 
bewusst machen, dass die Welt nicht zusammenbricht, wenn man einfach mal
ruhig ist.&lt;/p&gt;

&lt;p&gt;Jeden Tag wird so viel “gedacht”, dass zum Nachdenken keine Zeit bleibt.
Warum eigentlich? Darüber sollte man mal nachdenken ….&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Und dann gibt es noch jene, die bereits heute spüren, was unser überhastetes
Leben ausgelöst hat. Jene, die heute nicht ruhig sein können, weil ihnen
der verlorene Arbeitsplatz das Einkommen gekostet hat und dafür jede Menge
Sorgen ausbezahlt hat.&lt;/p&gt;

&lt;p&gt;Wir haben Aktienkurse (reine Zahlenspiele auf Computern) zuerst 
hochgetrieben, und nun am Boden aufschlagen lassen.&lt;br /&gt;
Wir waren unachtsam, mussten an alle Orte der Erde hetzen, damit wir uns jetzt
im Lockdown vor dem Übel, das wir selbst mitgebracht haben, gehörig fürchten
können.&lt;br /&gt;
Wir sind unzufrieden und ärgern uns täglich über alles was die anderen falsch
gemacht haben, dass wir gar nicht mehr Zeit finden, uns selbst zu verbessern.
Gleichzeitig sind wir so tief im Selbstmitleid eingesunken, dass wir jene vor 
unserer Haustüre gar nicht mehr wahrnehmen, wenn sie um Hilfe rufen.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Meine Firma hat dieses Jahr begonnen, Menschen vor die Tür zu setzen, 
so wie viele andere Unternehmen auch. Schließlich musste man etwas 
gegen “die schlechten Zahlen” unternehmen. Bloß nicht zu viele auf einmal, 
damit weder Staat noch Presse etwas ahnen und damit “der Markt” nicht 
beunruhigt wird.&lt;/p&gt;

&lt;p&gt;Jenen ehemaligen Kollegen und deren Familien gilt daher dieses Jahr mein 
Weihnachtsgedenken. Aber es gilt auch meinen Vorgesetzten, auf denen ebenso 
der Druck des Systems liegt, dem sie akribisch dienen.&lt;/p&gt;

&lt;p&gt;Deshalb passt an diesem Weihnachtsabend das Stück 
&lt;a href=&quot;https://de.wikipedia.org/wiki/A_Christmas_Carol&quot;&gt;“Eine Weihnachtsgeschichte” (A Christmas Carol)&lt;/a&gt;
von &lt;a href=&quot;https://de.wikipedia.org/wiki/Charles_Dickens&quot;&gt;Charles Dickens&lt;/a&gt; vielleicht 
viel besser zu uns, als einheimische traditionelle Lieder.&lt;br /&gt;
Ein solcher Blick in den Spiegel kann tiefgründiger sein, als eine 
Plastik-Bethlehemkrippe zu begutäugen. Und wenn wir uns unserer 
Vergangenheit, Gegenwart und Zukunft mal bewusst werden, schlagen wir den 
richtigen Weg vielleicht ganz von selbst ein.&lt;/p&gt;

&lt;p&gt;Weil wir dieses Jahr so deutlich wie selten zu vor gelernt haben:&lt;br /&gt;
&lt;em&gt;Dass wir uns ändern können&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Frohe Weihnachten!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;iframe width=&quot;640&quot; height=&quot;360&quot; src=&quot;/blog/redirect.html?https%3A%2F%2Fwww.youtube-nocookie.com%2Fembed%2FUIaJcjJReCU&quot; frameborder=&quot;1&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
</content>
 </entry>
 
 <entry>
   <title>Dicke Luft mit GP2Y1014AU0F messen</title>
   <link href="https://www.opengate.at/blog/2020/12/dust/"/>
   <published>2020-12-20T12:00:00+01:00</published>
   <updated>2020-12-20T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2020/12/dust</id>
   <category term="hardware" />
   <summary type="text">Kurz bevor Großmutter so richtig wütend wurde, kündigte sie mit


  Gleich staubt’s!


die aufbrodelnde Emotion an.
In Sachen Feinstaub-Belastung merkt man es leider nicht immer so deutlich, 
ab wann die Luft schlecht wird.

Doch genau dafür gibt es ja entsprechende Sensoren.
</summary>
   <content type="html">&lt;p&gt;Kurz bevor Großmutter so richtig wütend wurde, kündigte sie mit&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Gleich staubt’s!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;die aufbrodelnde Emotion an.&lt;br /&gt;
In Sachen Feinstaub-Belastung merkt man es leider nicht immer so deutlich, 
ab wann die Luft schlecht wird.&lt;/p&gt;

&lt;p&gt;Doch genau dafür gibt es ja entsprechende Sensoren.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Modelle der &lt;a href=&quot;https://www.mouser.at/datasheet/2/365/GP2Y1014AU0F_SPEC-1288381.pdf&quot;&gt;GP2Y10 Serie von Sharp&lt;/a&gt;
sind für Bastler und IoT Freunde für wenige Euros käuflich erwerbbar.
Der Sensor beinhaltet eine Infrarot-Diode und einen Empfänger, die so 
positioniert sind, dass sie an einander vorbei schauen.
Doch wo sich ihr Blickwinkel kreuzt, kann die Luft durchfließen und wenn sie
mit Staub angereichert ist, wird das Licht in andere Richtungen reflektiert
und damit auch quasi “um die Ecke” zum Empfänger.&lt;/p&gt;

&lt;p&gt;Je dreckiger die Luft ist, um so mehr Lichtwellen kommen dann am Empfänger an.&lt;/p&gt;

&lt;p&gt;Das wird dann noch in eine Spannung umgewandelt, und schon hat man etwas, was
man am Mikrocontroller super messen und verarbeiten kann.
Also auf zum Arduino-Steckbrett.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/sensor-gp2y1014au0f.jpg&quot; alt=&quot;GP2Y1014AU0F dust sensor&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;verkabelung&quot;&gt;Verkabelung&lt;/h3&gt;

&lt;p&gt;Mein &lt;code&gt;GP2Y1014AU0F&lt;/code&gt; kommt mit 6 Leitungen, die der Stromversorgung, 
Aktivierung und Datenausgabe dienen.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Pin&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Bedeutung&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Anmerkung&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;1 (Blau)&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;IR-LED VCC (3.3 V)&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Mit 150 Ohm Vorwiderstand auf 5 V&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;2 (Grün)&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;IR-LED GND&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Auf Arduino GND&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;3 (Weiß)&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;On/Off - Pin&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Auf digitalen Pin (z.B. D13)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;4 (Gelb)&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Sensor GND&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Auf Arduino GND&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;5 (Schwarz)&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Sensor Output&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;And analogen Pin (z.B. A0)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;6 (Rot)&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Sensor VCC (5 V)&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Auf auf 5 V&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Die &lt;a href=&quot;https://de.wikipedia.org/wiki/Leuchtdiode&quot;&gt;LED&lt;/a&gt; soll nur mit etwa 
3.3 Volt betrieben werden, weshalb ein 150 Ohm Vorwiderstand vor der 5 Volt
Spannungsversorgung und dem Gerät geschaltet werden muss. Man kann natürlich
auch den 3.3 Volt Ausgang der Arduino Boards nutzen, aber nachdem der 150 Ohm 
Widerstand beim Gerät mitgeliefert wird, nutze ich diesen direkt.&lt;/p&gt;

&lt;p&gt;Außerdem soll laut Datenblatt ein 220mF Kondensator nach dem Widerstand zur 
Stabilisierung zwischen LED-Spannung und Ground gesetzt werden.&lt;/p&gt;

&lt;h3 id=&quot;funktionsweise&quot;&gt;Funktionsweise&lt;/h3&gt;

&lt;p&gt;Wird Staub erkannt, erhöht sich die Spannung am Output-Pin. Dabei muss man
wissen, dass auch bei Staubfreiheit eine geringe Spannung ausgegeben wird.
Laut Datenblatt liegt die bei durchschnittlich 0.6 Volt und sollte nie das
Maximum von 1.1 Volt überschreiten.&lt;br /&gt;
Das heißt also, beim Arduino &lt;code&gt;analogRead()&lt;/code&gt;, das die Spannungswerte als
Ganzzahl zwischen 0 und 1023 zurückgibt, würde erst ein Wert von 
größer 122 auf gemessenen Staub hinweisen und ab 225 haben wir garantiert
Staub in der Luft.&lt;/p&gt;

&lt;p&gt;Das Messen selbst ist außerdem kein kontinuierlicher Vorgang. Gemäß Datenblatt
wird die Messung über den On/Off Pin aktiviert, wenn dieser &lt;code&gt;LOW&lt;/code&gt; geschaltet 
ist, und dann sollten 0.28 Millisekunden (als 280 Mikrosekunden) vergehen um 
Staubreflexionen zu detektieren. Danach sollte man etwa 10 Millisekunden im
ausgeschalteten Zustand (On/Off-Pin-&amp;gt; &lt;code&gt;HIGH&lt;/code&gt;) vergehen, ehe man erneut eine 
Messung durchführen kann.&lt;/p&gt;

&lt;p&gt;Das heißt also:&lt;/p&gt;
&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;digitalWrite(ONOFF_PIN, LOW);          &lt;span style=&quot;color:#777&quot;&gt;// switch ON&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;delayMicroseconds(&lt;span style=&quot;color:#00D&quot;&gt;280&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; rawSensorValue = analogRead(SENSOR_PIN);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;digitalWrite(ONOFF_PIN, HIGH);        &lt;span style=&quot;color:#777&quot;&gt;// switch OFF&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;delay(&lt;span style=&quot;color:#00D&quot;&gt;10&lt;/span&gt;);
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Ebenso im Datenblatt verzeichnet ist eine Referenzkurve, die den Spannungswerten
eine physikalische Größe, nämlich Mikrogramm pro Quadratmeter (ug/m2) zuordnet.
0.6 V bis 3.5 Volt decken ziemlich linear den Verlauf von 0 bis 500 Mikrogramm
ab.
Das bedeutet also, aus der gemessenen Spannung V, ergibt sich die Staubmenge
nach der Formel: &lt;code&gt;500 * (V - 0.6) / 2.9&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Wenn man gleich mit den Werten des A/D Wandlers von 0 bis 1023 (für 0 - 5 Volt)
rechnen möchte, wäre das dann:
&lt;code&gt;500 * (AD - 122) / 716&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Werte kleiner 0.6 Volt sollten immer als Null ausgefiltert werden, während
alles über 3.5 Volt einfach nur “größer als 500 ug” bedeutet.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Meine Wohnung ist gar nicht mal so schlimm. Der Sensor kann nämlich 
fast keinen Staub erkennen.&lt;br /&gt;
Außer ich lasse den Staubsauger fahren, der alles aufwirbelt, und schon
meldet der Sensor Werte.&lt;/p&gt;

&lt;p&gt;Interessant wird der Sensor im Sommer, wenn ich häufig das Fenster zur Straße
offen habe, denn da sammelt sich auch schnell bei mir mehr sichtbarer Staub
im Zimmer an.&lt;/p&gt;

&lt;p&gt;Dieser preiswerte Sensor ist also gut geeignet um ungefähr die Luftqualität
einzuschätzen. Wird über einige Zeit Staub festgestellt, empfiehlt sich
ein Luftreiniger oder Filter, denn zu viele Partikel sind für die Lunge
absolut nicht gesund.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Alt versus älter werden</title>
   <link href="https://www.opengate.at/blog/2020/12/old/"/>
   <published>2020-12-19T12:00:00+01:00</published>
   <updated>2020-12-19T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2020/12/old</id>
   <category term="general" />
   <summary type="text">Seit 15 Jahren arbeite ich jetzt (mal mehr mal weniger) in der 
Softwareentwicklung. Und fast doppelt sie viel muss ich wohl noch, wenn ich 
mich an den üblichen staatlichen Vorgaben orientiere.

Und wenn es weiter so bergab geht, wird das echt schlimm mit mir enden.
Der Übergang von Pubertät zur Midlife-Crisis kann beginnen.
</summary>
   <content type="html">&lt;p&gt;Seit 15 Jahren arbeite ich jetzt (mal mehr mal weniger) in der 
Softwareentwicklung. Und fast doppelt sie viel muss ich wohl noch, wenn ich 
mich an den üblichen staatlichen Vorgaben orientiere.&lt;/p&gt;

&lt;p&gt;Und wenn es weiter so bergab geht, wird das echt schlimm mit mir enden.
Der Übergang von Pubertät zur Midlife-Crisis kann beginnen.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Mein Interesse für Technik (damals hauptsächlich Computerspiele) hat ja schon 
im Alter von 10 Jahren begonnen. Wenn ich heute den Vergleich zwischen dem
10., dem 20. und dem 30. Geburtstag aufstelle, dann beginne ich mich vor
dem 40. zu fürchten und möchte die anderen nicht mehr erleben.&lt;/p&gt;

&lt;p&gt;Was war das damals für eine geile Zeit, wo man die Nächte durchmachen konnte
und jeden Tag Wissen einsaugen und sich das dann auch noch merken konnte.
Spätestens mit dem 30er wurde mir klar, dass mir diese Fähigkeiten immer 
mehr entschwinden.&lt;/p&gt;

&lt;p&gt;Natürlich hatte das auch viel mit Motivation zu tun, die im beruflichen 
Alltag leider generell fehlt. Man lernt eben viel leichter &lt;a href=&quot;https://de.wikipedia.org/wiki/Zilog_Z80&quot;&gt;Z80&lt;/a&gt;
&lt;a href=&quot;https://de.wikipedia.org/wiki/Assembler_(Informatik)&quot;&gt;Assembler&lt;/a&gt; wenn man 
sich davon einen &lt;a href=&quot;https://de.wikipedia.org/wiki/Pok%C3%A9mon&quot;&gt;Pokemon&lt;/a&gt; ROM 
Hack erwartet, und sich danach einfach nur “cool” fühlt, als wie wenn man 
in der Firma schon an der Spezifikation sieht, dass das so wahrscheinlich 
schlecht werden wird und man sich trotzdem mit den Fehlern anderer 
(und auch den eigenen) abquälen muss.&lt;/p&gt;

&lt;p&gt;Aber auch das Hirn wird älter. Zweifellos kann man mit “Erfahrung” oft vieles
erschlagen, woran man in der Jugend Wochen und Monate verbraten hat. Und 
dennoch trauere ich der Zeit hinterher, wo ich einen Text gelesen habe, und
zumindest so weit verstehen konnte, damit ich unmittelbar etwas “produzieren”
konnte.&lt;br /&gt;
Diese Fähigkeit, denke ich, geht im Alter mehr und mehr verloren und 
nachdem mehr Arbeit vor als hinter mir liegt, bekomme ich schon meine 
Bedenken, wir das in 5, 10 oder 20 Jahren aussehen wird, wenn der Verfall so
weitergeht.&lt;/p&gt;

&lt;p&gt;Ich weiß nicht, ob andere Menschen das auch so wahrnehmen, oder ob es mir 
intensiver auffällt, wenn ich durch Aufzeichnungen und Zeitstempel im 
Dateisystem durchblättere.&lt;br /&gt;
Die schlimmste Vorstellung ist dann jene, dass ich mit 60 Jahren auch vor 
einem Monitor sitze und absolut unproduktiv vor mich hintippe.&lt;/p&gt;

&lt;p&gt;Interessant ist auch, wie man Thematiken anders wahrnimmt.
Mein Lieblingsbeispiel aus der &lt;a href=&quot;https://de.wikipedia.org/wiki/Anime&quot;&gt;Anime&lt;/a&gt; 
Welt stammt aus &lt;a href=&quot;https://de.wikipedia.org/wiki/Naruto_(Manga)&quot;&gt;Naruto&lt;/a&gt;,
wo der Gegenspieler &lt;a href=&quot;https://naruto.fandom.com/de/wiki/Orochimaru&quot;&gt;Orochimaru&lt;/a&gt; 
danach trachtete die Körper von Jugendlichen zu übernehmen um seine eigenes 
Leben zu verlängern. Da war klar, dass es diesen Charakter zu bekämpfen 
galt.&lt;br /&gt;
Heute hingegen kann ich diesen “Wunsch nach der ewigen Jugend” nachvollziehen.
Denn das Wissen, dass einmal alles erarbeitete durch den Tod verloren gehen 
wird, reift erst mit der Lebenserfahrung heran.
Und wäre es nicht toll, wenn man die gesamte Lebenserfahrung auf ein junges
frisches Gehirn übertragen könnte und dann ohne Schmerzen und Einschränkungen 
unbeschwert weiterleben könnte?&lt;/p&gt;

&lt;p&gt;Aber vielleicht ist genau das der große Vorteil, nämlich durch das Altern
Vergänglichkeit besser erfassen zu können. Man liest weniger die Zeilen,
sondern zwischen den Zeilen und entdeckt dabei Dinge, die man sich in der
Jugend kaum vorstellen konnte.&lt;/p&gt;

&lt;p&gt;Man holt damit aus Daten einen höheren Wissensdurchsatz heraus … und
somit ist es nicht mehr so schlimm, dass man ob des Alters weniger liest,
aber dafür aus dem Wenigen mehr herausbekommt.&lt;/p&gt;

&lt;p&gt;Auch kenne ich heute kein nervöses Herzklopfen mehr, wenn ein “Test” ansteht,
und sitze entspannt vor dem Chef, weil ich das meiste, was kommen wird schon
kenne. 
Das schlimmste was passieren kann, ist dass man eine neue Tätigkeit suchen
muss, wenn ein Job zu Ende geht. Das ist zwar lästig, aber spätestens ab 
dem 3. Mal auch kein Drama mehr, während in Jugendtagen alleine ein neues 
Gesicht im Klassenzimmer schon eine Art Unbehagen auslösen konnte.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ich bin also ein bisschen gespalten, was das älter werden anbelangt. Gerne
hätte ich wieder “die Kraft der Jugend” zurück, vor allem die Wirbelsäule von
damals, die nach 16 Stunden sitzen nicht weh tat.&lt;br /&gt;
Aber die erworbene Erfahrung von heute würde ich nie und nimmer aufgeben 
wollen. Da bin ich über jede Minute und jeden Fehler, den ich gemacht habe
dankbar, dass ich es hinter mir habe und darauf aufbauen kann.&lt;/p&gt;

&lt;p&gt;So lange es also keine technische Möglichkeit gibt, den Verstand zu 100% 
verlustfrei auf einen frischen Körper zu übertragen, muss ich anerkennen,
dass das älter werden gar nicht so schlimm ist, wie es manchmal wirkt.&lt;/p&gt;

&lt;p&gt;Man muss sich nur bewusst daran erinnern, wie gut es einem geht, 
auch wenn man mal griesgrämig aufwacht.&lt;/p&gt;

&lt;p&gt;Alt werden ist zwar nervig, aber älter werden wird um so besser, 
je mehr man getan und erlebt hat.&lt;br /&gt;
… und jetzt bin ich gespannt, was ich in 10 Jahren davon halte, wenn ich 
diesen Text hoffentlich zufällig wiederfinden werde …&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Visual Studio 2005 Express</title>
   <link href="https://www.opengate.at/blog/2020/12/vs2005/"/>
   <published>2020-12-13T12:00:00+01:00</published>
   <updated>2020-12-13T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2020/12/vs2005</id>
   <category term="software" />
   <summary type="text">Visual Studio 2005 
ist für mich die Brücke zwischen Vergangenheit und Zukunft der 
Windows Software Entwicklung.
Der dortige C++ Compiler (MSVC-8) kann 
noch Binärdateien für Windows NT 4 
und Windows 98 erzeugen,
die aber ebenso auf Windows 10 
voll funktionsfähig sind.

Außerdem ist der Compiler halbwegs C++ 2003
konform und kann damit fast alles bauen, was ich im Alltag brauche.
</summary>
   <content type="html">&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_Studio#Version_2005&quot;&gt;Visual Studio 2005&lt;/a&gt; 
ist für mich die Brücke zwischen Vergangenheit und Zukunft der 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows&quot;&gt;Windows&lt;/a&gt; Software Entwicklung.
Der dortige &lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B&quot;&gt;C++&lt;/a&gt; Compiler (MSVC-8) kann 
noch Binärdateien für &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_NT_4.0&quot;&gt;Windows NT 4&lt;/a&gt; 
und &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_98&quot;&gt;Windows 98&lt;/a&gt; erzeugen,
die aber ebenso auf &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_10&quot;&gt;Windows 10&lt;/a&gt; 
voll funktionsfähig sind.&lt;/p&gt;

&lt;p&gt;Außerdem ist der Compiler halbwegs &lt;a href=&quot;https://en.wikipedia.org/wiki/C%2B%2B03&quot;&gt;C++ 2003&lt;/a&gt;
konform und kann damit fast alles bauen, was ich im Alltag brauche.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;jede-express-sprache-mit-eigener-ide&quot;&gt;Jede Express-Sprache mit eigener IDE&lt;/h3&gt;

&lt;p&gt;Während die Professional Ausgabe von Visual Studio 2005 eine einzige IDE für 
alle Sprachen von C++ über &lt;a href=&quot;https://de.wikipedia.org/wiki/C-Sharp&quot;&gt;C#&lt;/a&gt; bis 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_Basic_.NET&quot;&gt;VB.NET&lt;/a&gt; bereitstellt, 
gingen die Express Editionen damals einen ganz anderen Weg:&lt;br /&gt;
Jede Sprache hatte ihr eigenes Installationspaket mit einer separaten IDE.
Man konnte bzw. musste mehrere Express Produkte installieren, wenn man 
alle Sprachen nutzen wollte:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;em&gt;Visual C++ 2005 Express Edition&lt;/em&gt;&lt;br /&gt;
für natives C++ oder C++/CLI&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;Visual C# 2005 Express Edition&lt;/em&gt;&lt;br /&gt;
nur für C# Desktop App Entwicklung&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;Visual Basic 2005 Express Edition&lt;/em&gt;&lt;br /&gt;
nur für VB.NET Desktop App Entwicklung&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;Visual Web Developer 2005 Express Edition&lt;/em&gt;&lt;br /&gt;
für C# und VB.NET nur für ASP.NET Entwicklung&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;Visual J# 2005 Express Edition&lt;/em&gt;&lt;br /&gt;
Java-Syntax für dotNET Desktop App Entwicklung&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Microsoft hat die Downloads leider offline genommen, doch dank diverser 
privater Downloadseiten im Netz und &lt;a href=&quot;https://archive.org&quot;&gt;archive.org&lt;/a&gt;
findet man noch einige ISO-Dateien im Netz, die entweder eine einzelne
Sprache oder alle gesammelt beinhalten:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://archive.org/download/visual-studio-express-2005&quot;&gt;http://archive.org/download/visual-studio-express-2005&lt;/a&gt;&lt;/p&gt;

&lt;h3 id=&quot;problem-registrierung&quot;&gt;Problem: Registrierung&lt;/h3&gt;

&lt;p&gt;Ärgerlich ist, dass nach der Installation einer Expression Edition diese nur
30 Tage funktioniert und man sich danach bei Microsoft kostenlos registrieren
müsste um einen Lizenzschlüssel für die weitere Nutzung zu bekommen.&lt;/p&gt;

&lt;p&gt;Heute funktioniert diese URL natürlich nicht mehr (wurde so vor 7 Jahren 
glaube ich eingestellt) und somit kann man offiziell mit diesen kostenlose
Produkten nicht mehr arbeiten.&lt;/p&gt;

&lt;p&gt;… außer …&lt;/p&gt;

&lt;p&gt;man öffnet den Registry Editor und klickt sich durch bis zu:
&lt;code&gt;HKEY_CURRENT_USER\Software\Microsoft&lt;/code&gt;.
Dort findet man Unterordner mit den Namen&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;VCExpress&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;VCSExpress&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;VBExpress&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;VWDExpress&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;VJSExpress&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;und darunter findet man im Ordner &lt;code&gt;\8.0\Registration&lt;/code&gt; den Eintrag &lt;code&gt;Params&lt;/code&gt;
mit einem Hexadezimal-String.&lt;br /&gt;
Wenn man diesen magischen String durch eine simple “1” ersetzt, kann man die
IDE auch ohne offiziellen Registrierungsschlüssel starten.&lt;/p&gt;

&lt;p&gt;Naja … wenigstens ein einfacher “Hack” um damit arbeiten zu können.&lt;/p&gt;

&lt;h3 id=&quot;c-ohne-winapi&quot;&gt;C++ ohne WinAPI?&lt;/h3&gt;

&lt;p&gt;Visual C++ 2005 Express kommt nur mit der C-Runtime und der STL. Die Windows
API Header wie auch Link-Libraries fehlen. Und ebenso abgängig sind 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Active_Template_Library&quot;&gt;ATL&lt;/a&gt; und die 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Foundation_Classes&quot;&gt;MFC&lt;/a&gt;. 
Da wollte Microsoft wohl wieder Geld mit der Pro-Edition verdienen.&lt;/p&gt;

&lt;p&gt;Aber auch hier gibt es einen kostenlosen Weg:
Man installiert das kostenlose Platform-SDK aus der damaligen Zeit.
Das Platform SDK 2005 für Windows Server 2003 SP1 ist aktuell noch für MSDN
Subscribers als Download verfügbar … wer weiß wie lange noch.
Das letzte SDK &lt;em&gt;“Platform SDK 2006 for Server 2003 R2”&lt;/em&gt; kann ich im Netz
leider nicht mehr finden. Zum Glück ist es seit damals bei mir gesichert.&lt;/p&gt;

&lt;p&gt;Nach der Installation müssen die Pfade der Header und Link-Libraries noch
gesetzt werden. Das geschieht im Menü unter &lt;code&gt;Tools&lt;/code&gt; - &lt;code&gt;Options&lt;/code&gt;
und im Dialog unter  &lt;code&gt;Projects and Solutions&lt;/code&gt; - &lt;code&gt;VC++ Directories&lt;/code&gt;.
Dort kann man (leider nur) für die Win32 Plattform die Verzeichnisse 
hinzufügen:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;Include files&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;code&gt;C:\Program Files\Microsoft Platform SDK...\Include&lt;/code&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code&gt;Library files&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;code&gt;C:\Program Files\Microsoft Platform SDK...\Lib&lt;/code&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Das sollte reichen, damit man native Windows Apps durchkompiliert bekommt.
ATL und MFC sind theoretisch beim SDK auch dabei, nur habe ich die noch nie 
in der Express Edition ausprobiert. Mit etwas Glück reicht es vielleicht aus
die entsprechenden Unterverzeichnisse &lt;code&gt;\Include\atl&lt;/code&gt; und &lt;code&gt;\Include\mfc&lt;/code&gt;, sowie
die &lt;code&gt;\Lib&lt;/code&gt; Unterverzeichnisse hinzufügen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Mit VS2005 hat mein C++ Leben so richtig begonnen. Das Einrichten der Express
Version war für mich damals anfangs ein Alptraum. Weil ich von VB und C# 
gewohnt war, dass alles Out-of-the-box läuft, während das “dumme” C++ immer 
Extraaufwände erzeugte.&lt;/p&gt;

&lt;p&gt;Doch nachdem ich diese Schritte auswendig gelernt hatte, konnte ich mich 
entspannt in die Sprache verlieben.&lt;/p&gt;

&lt;p&gt;Heute zieht mich alle 6 Monate mal das GATE Projekt in die gute alte Zeit
zurück, wenn überprüft werden muss, ob eh noch alles mit den alten Compilern
kompatibel ist.&lt;br /&gt;
… und das wird hoffentlich auch in Zukunft so weiter gehen.&lt;/p&gt;

&lt;p&gt;Über 13 Jahre liegt mein Erstkontakt schon zurück.&lt;br /&gt;
Wahnsinn wie die Zeit vergeht!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Spaß mit Gitlab, Tags und Releases</title>
   <link href="https://www.opengate.at/blog/2020/12/gitlab-fun/"/>
   <published>2020-12-12T12:00:00+01:00</published>
   <updated>2020-12-12T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2020/12/gitlab-fun</id>
   <category term="devel" /><category term="software" />
   <summary type="text">Eine Entwicklungsrichtlinie in meiner Firma verlangt, dass man nach dem 
offiziellen Release einer Komponente unter deren Version keinen weiteren 
Check-in mehr machen darf.

Und ich durfte das umsetzen … und zwar mit
Gitlab CI-YAMLs, 
GIT
Tags und  Shellscripts unter 
[Linux].
Was für ein Spaß … W-T-F …
</summary>
   <content type="html">&lt;p&gt;Eine Entwicklungsrichtlinie in meiner Firma verlangt, dass man nach dem 
offiziellen Release einer Komponente unter deren Version keinen weiteren 
Check-in mehr machen darf.&lt;/p&gt;

&lt;p&gt;Und ich durfte das umsetzen … und zwar mit
&lt;a href=&quot;https://de.wikipedia.org/wiki/GitLab&quot;&gt;Gitlab&lt;/a&gt; CI-YAMLs, 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Git&quot;&gt;GIT&lt;/a&gt;
Tags und  &lt;a href=&quot;https://de.wikipedia.org/wiki/Shellskript&quot;&gt;Shellscripts&lt;/a&gt; unter 
[Linux].&lt;br /&gt;
Was für ein Spaß … W-T-F …
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Da uns GIT keine stabile Versionierung nach dem &lt;code&gt;MAJOR.MINOR.PATCH&lt;/code&gt; Schema
bereitstellt, mussten wir tricksen.
In den &lt;code&gt;.gitlab-ci.yml&lt;/code&gt; Dateien wo die Build-Jobs definiert sind, wird 
eine “globale” Versions-Variable geführt, die bei Änderungen inkrementell
hochgezählt werden muss.&lt;/p&gt;

&lt;p&gt;Während der aktiven Entwicklung ist das eigentlich egal, doch wenn ein
Feature fertig gestellt und getestet ist, soll eine eigene Release-Stage
dafür sorgen, dass das Ergebnis in ein Release-Repository hochgeladen 
wird, woraus dann die produktiven Installationen generiert werden.&lt;/p&gt;

&lt;p&gt;Mit dem “Release” soll die Software-Version eingefroren werden und 
es darf mit eben dieser “Version” keinen weiteren Check-In mehr geben.&lt;/p&gt;

&lt;p&gt;Das Konzept sieht vor, dass beim Release in GIT ein Tag angelegt wird,
das der Version gleicht.
Parallel darf kein Build-Job Code mit einer Version bauen, für die es
schon ein solches Release-Tag gibt.&lt;/p&gt;

&lt;p&gt;Aber wie setzt man das “billig” um?
Denn dort wo ich dieses Schema einsetzen sollte, sind komplexe
Scriptabhängigkeiten eher störend.&lt;/p&gt;

&lt;p&gt;Meine Lösung sieht daher wie folgt aus:&lt;/p&gt;

&lt;p&gt;Im Gitlab-CI Job wird per &lt;code&gt;before-script&lt;/code&gt; vor der Ausführung der 
Build-Stage das gute alte Tool &lt;code&gt;curl&lt;/code&gt; aufgerufen, um den GitLab
Server zu fragen, ob ein Tag mit der aktuellen Version schon existiert.
Fall ja (curl Exitcode == 0) ist das ein Fehler und wir brechen ab.
Andernfalls darf der Build durchlaufen.&lt;/p&gt;

&lt;p&gt;Beim Durchlauf der Release-Stage kommt ebenso wieder &lt;code&gt;curl&lt;/code&gt; zum Einsatz, 
welches die aktuelle Version per &lt;a href=&quot;https://de.wikipedia.org/wiki/Representational_State_Transfer&quot;&gt;REST&lt;/a&gt;
POST den aktuellen Commit mit einem GIT-Tag verknüpft.&lt;/p&gt;

&lt;p&gt;Das sieht dann etwa so aus:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;variables:
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;- GITLAB_API_TOKEN: &amp;quot;my-secret-access-token&amp;quot;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;- VERSION: &amp;quot;1.2.3&amp;quot;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;- TAGS_URL_BASE: &amp;quot;$CI_API_V4_URL/projects/$CI_PROJECT_ID/repository/tags&amp;quot;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;before_script: 
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;- &amp;quot;export CHECK_TAG_EXISTS_COMMAND=\&amp;quot;curl -f --header 
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;   PRIVATE-TOKEN:$GITLAB_API_TOKEN -L $TAGS_URL_BASE/$VERSION\&amp;quot;&amp;quot;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;- &amp;quot;if [[ `$CHECK_TAG_EXISTS_COMMAND` ]]; then exit 1; fi&amp;quot;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;after_script:
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;- &amp;quot;curl -f --header \&amp;quot;PRIVATE-TOKEN: $GITLAB_API_TOKEN\&amp;quot; --request POST
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;   \&amp;quot;$TAGS_URL_BASE?tag_name=$VERSION&amp;amp;ref=$CI_COMMIT_SHA&amp;amp;message=$VERSION\&amp;quot;&amp;quot;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ach wie tief bin ich gesunken …&lt;br /&gt;
Wenn mich als Entwickler etwas überhaupt nicht interessiert, dann sind das 
solche organisatorischen Quick-and-Dirty Ekelskriptereien … aber was soll
man machen.&lt;/p&gt;

&lt;p&gt;Es ist ein schlechter Trost, dass ich sagen kann:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Egal wo ich bisher gearbeitet habe, die anderen haben noch schlechtere
Workarounds fabriziert.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Aber genau das ist das Problem von “Scripting”. Jeder macht irgendetwas
irgendwie. Möglichst schnell und scheinbar einfach … und dann hat man
Gigabytes an Ansammlungen von solchen Codes, die keiner mehr richtig
nachvollziehen kann.&lt;/p&gt;

&lt;p&gt;However, zumindest weiß ich wieder ein bisschen mehr über Gitlab-YAMLs 
Bescheid.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>YAML</title>
   <link href="https://www.opengate.at/blog/2020/12/yaml/"/>
   <published>2020-12-06T12:00:00+01:00</published>
   <updated>2020-12-06T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2020/12/yaml</id>
   <category term="devel" />
   <summary type="text">XML, 
JSON, 
CSV und 
INI sind seit 20 Jahren
die Dateiformate, die ich am häufigsten in Projekten zur Datenspeicherung eingesetzt habe.

Seit etwa 10 Jahren kenne ich ein weiteres, nämlich 
YAML …
aber erst heuer habe ich für dieses Format einen Parser geschrieben …
</summary>
   <content type="html">&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Extensible_Markup_Language&quot;&gt;XML&lt;/a&gt;, 
&lt;a href=&quot;https://de.wikipedia.org/wiki/JavaScript_Object_Notation&quot;&gt;JSON&lt;/a&gt;, 
&lt;a href=&quot;https://de.wikipedia.org/wiki/CSV_(Dateiformat)&quot;&gt;CSV&lt;/a&gt; und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Initialisierungsdatei&quot;&gt;INI&lt;/a&gt; sind seit 20 Jahren
die Dateiformate, die ich am häufigsten in Projekten zur Datenspeicherung eingesetzt habe.&lt;/p&gt;

&lt;p&gt;Seit etwa 10 Jahren kenne ich ein weiteres, nämlich 
&lt;a href=&quot;https://de.wikipedia.org/wiki/YAML&quot;&gt;YAML&lt;/a&gt; …
aber erst heuer habe ich für dieses Format einen Parser geschrieben …
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Das rekursive Akronym &lt;code&gt;YAML&lt;/code&gt; steht für “YAML Ain’t Markup Language”, obwohl
mir die originale “Yet Another Markup Language” besser gefallen hat.&lt;/p&gt;

&lt;p&gt;Ähnlich wie in &lt;code&gt;JSON&lt;/code&gt; kann man damit hierarchische Datenstrukturen als&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Ja/Nein Werte (Boolean)&lt;/li&gt;
  &lt;li&gt;Zahlen (Float/Integer)&lt;/li&gt;
  &lt;li&gt;Text (Strings)&lt;/li&gt;
  &lt;li&gt;Listen (Arrays)&lt;/li&gt;
  &lt;li&gt;Key/Value Objekte (Dictionaries)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;darstellen. Allerdings zeichnet sich YAML als besonders “human-readable” aus,
da es nicht voraussetzt, dass die Dateneinträge durch Sonderzeichen wie 
Hochkomma und Klammern abgegrenzt werden, sondern es nutzt Text-Zeilen
und Einrückungen (ähnlich wie &lt;a href=&quot;https://de.wikipedia.org/wiki/Python_(Programmiersprache)&quot;&gt;Python&lt;/a&gt;) 
als primäres Zuordnungsraster.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;version: 1.2.3
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;description: &amp;quot;Sample YAML document&amp;quot;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;entry_array:
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  - name:    &amp;quot;Entry object 1&amp;quot;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;    id:      1234
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;        content: &amp;quot;Hello&amp;quot;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  - name:    &amp;quot;Entry object 2&amp;quot;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;    id:      5678
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;    content: &amp;quot;World&amp;quot;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;meta_data:
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;  author:    Me
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;  created:   2020-12-06
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;  published: Yes
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Das gleiche Datenstruktur würde in &lt;code&gt;JSON&lt;/code&gt; so aussehen:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;  &amp;quot;version&amp;quot;: &amp;quot;1.2.3&amp;quot;,
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  &amp;quot;description&amp;quot;: &amp;quot;Sample YAML document&amp;quot;,
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  &amp;quot;entry_array&amp;quot;: [
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;    { 
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;          &amp;quot;name&amp;quot;: &amp;quot;Entry object 1&amp;quot;,
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;      &amp;quot;id&amp;quot;: 1234,
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;          &amp;quot;content&amp;quot;: &amp;quot;Hello&amp;quot;,
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;        },
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;        {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;      &amp;quot;name&amp;quot;: &amp;quot;Entry object 2&amp;quot;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;      &amp;quot;id&amp;quot;: 5678,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;      &amp;quot;content&amp;quot;: &amp;quot;World&amp;quot;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;        }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;  ],
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;  &amp;quot;meta_data&amp;quot;: 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;  {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;    &amp;quot;author&amp;quot;: &amp;quot;Me&amp;quot;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;    &amp;quot;created&amp;quot;: &amp;quot;2020-12-06&amp;quot;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;    &amp;quot;published&amp;quot;: true
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n21&quot; name=&quot;n21&quot;&gt;21&lt;/a&gt;&lt;/span&gt;  }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n22&quot; name=&quot;n22&quot;&gt;22&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h3 id=&quot;parser-für-strings&quot;&gt;Parser für Strings&lt;/h3&gt;

&lt;p&gt;Die meisten fertigen Parser haben aus meiner Perspektive zwei Nachteile:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Sie sind entweder an ein Framework gebunden, das viele Abhängigkeiten und
Konventionen mitbringt.&lt;/li&gt;
  &lt;li&gt;Oder sie nutzen &lt;a href=&quot;https://de.wikipedia.org/wiki/C_(Programmiersprache)&quot;&gt;C&lt;/a&gt; 
char Strings oder &lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B&quot;&gt;C++&lt;/a&gt; &lt;code&gt;std::string&lt;/code&gt; 
und sind damit recht ineffizient.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Bei der Einführung von &lt;a href=&quot;http://en.cppreference.com/w/cpp/language/reference&quot;&gt;R-Value-References&lt;/a&gt;
in C++11 wurde gemeldet, dass XML Komponenten um 400% schneller wurden, weil 
dort jedes Attribut als eigener String angelegt wurde.&lt;/p&gt;

&lt;p&gt;Nun seit &lt;code&gt;std::string_view&lt;/code&gt; in C++17 sollte das nochmals dramatisch schneller
geworden sein, wenn dieses neue Feature korrekt benutzt wird.&lt;/p&gt;

&lt;p&gt;Im GATE Framework sind &lt;code&gt;string_view&lt;/code&gt; und &lt;code&gt;string&lt;/code&gt; bereits zusammengefasst
und daher verspricht eine eigene Implementierung basierend auf &lt;code&gt;gate_string_t&lt;/code&gt;
eine wesentlich höhere Effizienz als wenn man Fremdbibliotheken nutzt und 
danach Ende hin- und her konvertieren muss.&lt;/p&gt;

&lt;h3 id=&quot;yaml-zerteilen&quot;&gt;YAML zerteilen&lt;/h3&gt;

&lt;p&gt;Während ich mit &lt;code&gt;JSON&lt;/code&gt; und &lt;code&gt;XML&lt;/code&gt; keine so großen Schwierigkeiten hatte, stellte 
sich &lt;code&gt;YAML&lt;/code&gt; als ungut harte Nuss heraus. Das Fehlen von Feldbegrenzern wie 
Hochkomma versetzt einen an vielen Stellen in den “Probier-mal” Modus.
Ein &lt;code&gt;&quot;a b&quot;: &quot;c d&quot;&lt;/code&gt; wäre eindeutig und würde dem Member “a b” den Wert “c d” 
zuordnen. Doch in YAML lautet die Zeile &lt;code&gt;a b : c d&lt;/code&gt; und die Leerzeichen vor 
und nach dem Doppelpunkt sind zu entfernen, während sie zwischen den 
Buchstaben erhalten bleiben müssen.&lt;/p&gt;

&lt;p&gt;Auch sind Texte von Zahlen und Booleans schwerer zu unterscheiden.
Die Zeile &lt;code&gt;- 42&lt;/code&gt; ist ein Arrayeintrag eines Integer während 
&lt;code&gt;- 42 is the answer&lt;/code&gt; ein Stringeintrag sein sollte.&lt;/p&gt;

&lt;p&gt;Aber am Schlimmsten sind Arrays in Objekten und Objekte in Arrays.
Theoretisch unterscheiden sich Unterelemente von ihren Eltern durch eine 
tiefere Einrückung. Doch das führende &lt;code&gt;-&lt;/code&gt; eines Array-Eintrag darf auf der gleichen
Ebene wie das Elternelement sein, wenn dieses ein Objekt ist&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;entries:
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;- a: b
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  c: d
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;- e: f
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  g: h
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Im Beispiel hat der Member &lt;code&gt;entries&lt;/code&gt; als Wert ein Array mit zwei Einträgen,
die aus Objekten bestehen, einmal mit den Membern &lt;code&gt;a&lt;/code&gt; und &lt;code&gt;c&lt;/code&gt; und einmal mit 
&lt;code&gt;e&lt;/code&gt; und &lt;code&gt;g&lt;/code&gt;.&lt;br /&gt;
Dass das Minus auf der gleichen Einrück-Ebene wie das Elternobjekt liegt,
muss man also speziell behandeln. Umgekehrt muss man auch verstehen, dass
der Member &lt;code&gt;c&lt;/code&gt; zum gleichen Objekt wie &lt;code&gt;a&lt;/code&gt; gehört (genau so wie &lt;code&gt;g&lt;/code&gt; und &lt;code&gt;e&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Und dann gibt es noch eine Art Inline-Format, wo innerhalb von &lt;code&gt;YAML&lt;/code&gt; quasi 
wieder &lt;code&gt;JSON&lt;/code&gt; gesprochen wird (aber auch nur mit optionalen Anführungszeichen).&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;entries: [ { a: b, c: d }, { e: f, g: h } ]
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Muha! Was für ein Kack!&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Noch muss ich einige Tests mit meinem &lt;code&gt;YAML&lt;/code&gt; Parser machen. Einige Features wie
Referenzen zwischen Objekten werde ich gar nicht unterstützen, weil der 
kleinste gemeinsame Nenner zwischen &lt;code&gt;JSON&lt;/code&gt; und &lt;code&gt;YAML&lt;/code&gt; für mich als Richtwert gilt.
Am Ende sollen beide Datenformate gleichwertig gelesen und in einen Objektbaum
geladen werden können und umgekehrt auch wieder zurückgeschrieben werden 
können.&lt;/p&gt;

&lt;p&gt;Da gehen zwangsläufig ein paar Features verloren.&lt;/p&gt;

&lt;p&gt;Doch ich habe schwer unterschätzt, wie komplex das Parsing eines scheinbar 
“einfacheren” Dateiformats sein kann. Hier gilt tatsächlich wieder der 
Grundsatz:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Je leichter etwas für Menschen lesbar ist, um so schwieriger tun sich die 
Maschinen damit … und umgekehrt ebenso.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Wie auch immer … jetzt kann ich endlich auch bei &lt;code&gt;YAML&lt;/code&gt; klugscheißen, 
wenn das Thema angesprochen wird.&lt;br /&gt;
Den Parser selbst schreiben ist also immer eine gute Idee.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>lib-c Interpretationen</title>
   <link href="https://www.opengate.at/blog/2020/12/libc/"/>
   <published>2020-12-05T12:00:00+01:00</published>
   <updated>2020-12-05T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2020/12/libc</id>
   <category term="devel" />
   <summary type="text">Man könnte genau so gut fragen:


  Wie sieht Gott aus?


und würde ähnlich viele unterschiedlichen Antworten erhalten, wie es
Implementierungsunterschiede der C 
Systembibliotheken gibt.

Und damit meine ich nicht Windows
versus Linux. Nein, es reicht schon
Linux-Distros zu vergleichen oder 
POSIX 
ins Spiel zu bringen.
</summary>
   <content type="html">&lt;p&gt;Man könnte genau so gut fragen:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Wie sieht Gott aus?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;und würde ähnlich viele unterschiedlichen Antworten erhalten, wie es
Implementierungsunterschiede der &lt;a href=&quot;https://de.wikipedia.org/wiki/C_(Programmiersprache)&quot;&gt;C&lt;/a&gt; 
Systembibliotheken gibt.&lt;/p&gt;

&lt;p&gt;Und damit meine ich nicht &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows&quot;&gt;Windows&lt;/a&gt;
versus &lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt;. Nein, es reicht schon
Linux-Distros zu vergleichen oder 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Portable_Operating_System_Interface&quot;&gt;POSIX&lt;/a&gt; 
ins Spiel zu bringen.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Nachdem &lt;a href=&quot;http://www.google.com/search?client=firefox-b-d&amp;amp;q=DOS&quot;&gt;DOS&lt;/a&gt; und 
Windows 3.x damit gescheitert waren, MS-Header und die WinAPI als dominante 
C-Programm-Basis zu verbreiten, wurde in &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_NT&quot;&gt;NT&lt;/a&gt;
und Win9x die C-Runtime als Kompatibilitätsschicht eingeführt, damit auch 
Microsoft Programme &lt;code&gt;malloc()&lt;/code&gt; nutzen und nicht wie vorher üblich zB.: 
&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-localalloc&quot;&gt;&lt;code&gt;LocalAlloc()&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Der Hass der Unixianer war groß, weil obwohl vieles “irgendwie” lief, gab es
immer Unterschiede bei den Locales, oder wenn &lt;code&gt;__int64&lt;/code&gt; vorkam und 
&lt;code&gt;printf()&lt;/code&gt; ein paar Flags mehr oder weniger verstand.&lt;/p&gt;

&lt;p&gt;Die großen bekannten Linux-Distributionen wie &lt;a href=&quot;https://de.wikipedia.org/wiki/Debian&quot;&gt;Debian&lt;/a&gt;
und &lt;a href=&quot;https://en.wikipedia.org/wiki/SUSE_Linux&quot;&gt;SuSE&lt;/a&gt; nutzen meines Wissens
immer schon brav die &lt;a href=&quot;https://de.wikipedia.org/wiki/GNU-C-Bibliothek&quot;&gt;GNU GLIB-C&lt;/a&gt; 
und so war für mich deren Implementierung quasi “der Standard”.&lt;/p&gt;

&lt;p&gt;Doch seit meiner Beschäftigung mit &lt;a href=&quot;https://de.wikipedia.org/wiki/Berkeley_Software_Distribution&quot;&gt;BSD&lt;/a&gt;, 
stelle ich immer wieder fest, dass die Behauptung, die C-Lib Implementierungen 
seien alle zu POSIX kompatibel und fügen nur ein paar Erweiterungen hinzu, 
stelle ich fest, dass dann doch noch immer ein bisschen 
Interpretationsspielraum zwischen Theorie und Praxis liegt.&lt;/p&gt;

&lt;p&gt;Kleinere Distros wie &lt;a href=&quot;https://de.wikipedia.org/wiki/Alpine_Linux&quot;&gt;Alpine Linux&lt;/a&gt; 
nutzen z.B. die &lt;code&gt;musl-libc&lt;/code&gt;, die sich ob ihrer Einfachheit als sehr “schnell”
behauptet. Dass es dort dann keinen (oder nicht immer) einen Header namens 
&lt;code&gt;&amp;lt;sys/sysctl.h&amp;gt;&lt;/code&gt; gibt, weil diese Funktion schon wo anders eingebunden wird,
ist zwar lästig, aber per&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color:#B44;font-weight:bold&quot;&gt;&amp;lt;features.h&amp;gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#if&lt;/span&gt; defined(__GLIBC__)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#  include&lt;/span&gt; &lt;span style=&quot;color:#B44;font-weight:bold&quot;&gt;&amp;lt;sys/sysctl.h&amp;gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#endif&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;schnell umgangen.&lt;/p&gt;

&lt;p&gt;Doch dann lese ich die Seite über die 
&lt;a href=&quot;https://wiki.musl-libc.org/functional-differences-from-glibc.html&quot;&gt;funktionellen Unterschiede&lt;/a&gt;
zwischen &lt;code&gt;GLIB-C&lt;/code&gt; und &lt;code&gt;MUSL-LIBC&lt;/code&gt; und finde doch tatsächlich die Aussage, dass 
&lt;a href=&quot;https://pubs.opengroup.org/onlinepubs/009695399/functions/dlclose.html&quot;&gt;&lt;code&gt;dlclose()&lt;/code&gt;&lt;/a&gt;
per &lt;code&gt;NO-OP&lt;/code&gt; implementiert ist, also genau gar nichts macht.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Echt jetzt? Man kann Bibliotheken generell nicht “entladen”?&lt;br /&gt;
Meine Plugins sind keine Plugins mehr? Waaaas?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ja, damit hätte ich nicht gerechnet. So sehr ich “schlanke” Funktionen schätze,
aber eine OS-Kernfunktionalität einfach still und heimlich entfernen … das
geht eigentlich gar nicht.&lt;/p&gt;

&lt;p&gt;Der Kernel könnte natürlich alles notwendige, doch wenn die C-Lib nicht will,
ist eben Hopfen und Malz verloren …&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Nun, ich weiß nicht, ob das jetzt “gut” oder “schlecht” ist, dass wirklich 
jeder offen kritisierte Designfehler in kommerzieller Software von manchen
OSS Implementierungen zum “coolen Feature” erhoben wird.&lt;/p&gt;

&lt;p&gt;Das dynamische Laden und Entladen von Implementierungen in Shared-Libraries
sollte jedenfalls ein “Feature” im GATE Microservice Host werden.
Jetzt weiß ich zumindest, dass wegen Alpine Linux das Thema Prozess-Isolation
eine höhere Priorität bekommen wird … bzw. die Architektur beeinflussen wird.&lt;/p&gt;

&lt;p&gt;Denn offenbar sind im verallgemeinerten Sinn ausschließlich nur Kindprozesse 
unter Linux dazu fähig eine Plugin- und “Plugout” Infrastruktur aufzubauen.&lt;/p&gt;

&lt;p&gt;Innerlich bin ich jetzt enttäuscht darüber, dass Implementierungen einen
so krassen Unterschied aufweisen können und sich vom dokumentierten Standard
derart unterscheiden.&lt;/p&gt;

&lt;p&gt;Naja … aber so ist das eben im Leben eines Entwicklers:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Man lernt mit Schmerzen zu leben.&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>5G in Wien?</title>
   <link href="https://www.opengate.at/blog/2020/11/5g/"/>
   <published>2020-11-29T12:00:00+01:00</published>
   <updated>2020-11-29T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2020/11/5g</id>
   <category term="hardware" />
   <summary type="text">Ach es hätte so schön werden können …
Jetzt habe ich offiziell einen 5G Vertrag 
und auch die Hardware, nur empfangen kann ich nichts.

Doch vielleicht klappt es nächstes Jahr…
</summary>
   <content type="html">&lt;p&gt;Ach es hätte so schön werden können …
Jetzt habe ich offiziell einen &lt;a href=&quot;https://de.wikipedia.org/wiki/5G&quot;&gt;5G&lt;/a&gt; Vertrag 
und auch die Hardware, nur empfangen kann ich nichts.&lt;/p&gt;

&lt;p&gt;Doch vielleicht klappt es nächstes Jahr…
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Mein Internetanbieter &lt;a href=&quot;https://www.drei.at/&quot;&gt;drei.at&lt;/a&gt; behauptet auch im 5G 
Netz zu funken und stellt seinen Kunden diese Technologie zur Verfügung … 
natürlich nur, wenn man sich weitere 2 Jahre fix bindet.&lt;/p&gt;

&lt;p&gt;Aber OK, warum nicht, so schlecht ist das ja nicht und ob ich jetzt 26 oder
33 Euro im Monat bezahle ist auch schon egal.&lt;/p&gt;

&lt;p&gt;Gesagt, getan, Onlinebestellung des neuen 5G Routers spät nachts abgeschlossen 
und … WOW, 32 Stunden später klingelt der Postbote.&lt;/p&gt;

&lt;p&gt;Der neue Router kommt auch mit neuer &lt;a href=&quot;https://de.wikipedia.org/wiki/SIM-Karte&quot;&gt;SIM Karte&lt;/a&gt;
und ich dachte mir:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Cool, da braucht man nur anstecken und geht schon.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/5g-router-1.jpg&quot; alt=&quot;5G Router&quot; /&gt;&lt;/p&gt;

&lt;p&gt;So war es aber leider nicht, denn man musste zuerst über den alten Router
die Anbieterseite öffnen und dort die neue SIM Karte freischalten und 
aktivieren lassen.&lt;/p&gt;

&lt;p&gt;Dann war ich etwas verblüfft wie schnell das ablief, denn schon wenige
Minuten nach dem Absenden des Webformulars zur Neuaktivierung, flog mein
alter Router (mit der alten SIM Karte) aus dem Netz und kam auch nicht 
mehr rein.&lt;br /&gt;
Doch als ich nun den neuen Router wieder mit Strom versorgte, loggte sich
dieser binnen einer Minute ein und stellte mir den Internetzugang bereit.&lt;/p&gt;

&lt;p&gt;Nun war meine Neugier geweckt und ich öffnete die Konfigurationswebseite
des Routers im Browser.&lt;br /&gt;
Hier kam die Ernüchterung: Nur 4G Anbindung in gewohnt geringer Signalstärke.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Naja … vielleicht liegt meine Wohnung eben doch zu ungünstig und kann am
noch im Ausbau befindlichen 5G Netz eben nicht teilhaben.&lt;br /&gt;
Aber vielleicht kommen die neuen Funkwellen ja nächstes Jahr bis zu mir.&lt;/p&gt;

&lt;p&gt;Auf jeden Fall habe ich nun die nötige Hardware parat um sofort durchstarten
zu können, wenn es so weit ist.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/5g-router-2.jpg&quot; alt=&quot;5G Router&quot; /&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Lieber keine Optimierungen</title>
   <link href="https://www.opengate.at/blog/2020/11/no-optimization/"/>
   <published>2020-11-28T12:00:00+01:00</published>
   <updated>2020-11-28T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2020/11/no-optimization</id>
   <category term="devel" />
   <summary type="text">
  Yay! GATE kompiliert auf dem PinePhone 
unter postmarketOS!


… aber erst nach Anpassungen in der 
LIBPNG.


  Ach, pfeif’ drauf, wer braucht schon 
NEON


</summary>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;Yay! GATE kompiliert auf dem &lt;a href=&quot;https://www.pine64.org/pinephone/&quot;&gt;PinePhone&lt;/a&gt; 
unter &lt;a href=&quot;https://postmarketos.org/&quot;&gt;postmarketOS&lt;/a&gt;!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;… aber erst nach Anpassungen in der 
&lt;a href=&quot;http://www.libpng.org/pub/png/libpng.html&quot;&gt;LIBPNG&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ach, pfeif’ drauf, wer braucht schon 
&lt;a href=&quot;https://de.wikipedia.org/wiki/NEON_(Befehlssatzerweiterung)&quot;&gt;NEON&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;code&gt;NEON&lt;/code&gt; ist einer dieser ge-hype-ten mega-ultra-giga-geilen 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Flynnsche_Klassifikation#SIMD_(Single_Instruction,_Multiple_Data)&quot;&gt;SIMD&lt;/a&gt;
(single-instruction-multiple-data) Befehlssatzerweiterungen für 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Arm-Architektur&quot;&gt;ARM&lt;/a&gt; Prozessoren.&lt;/p&gt;

&lt;p&gt;Solchen Codes ist es zu verdanken, dass &lt;code&gt;ARM&lt;/code&gt; Systeme besser und vor allem
schneller mit Multimediaaufgaben umgehen können.&lt;/p&gt;

&lt;p&gt;Zweifellos sind Audiokonvertierungen oder Videostreams ohne diesen
Befehlssatz entweder unmöglich oder CPU-Grillkohlen.&lt;/p&gt;

&lt;p&gt;Da das GATE Projekt selbst keine bzw. nur wenig Multimedia-Implementierung
beinhaltet, sind solche Erweiterungen eigentlich kein Thema.
Sie werden daher nicht eingeschaltet … aber, wie sich herausgestellt hat,
auch nicht abgeschaltet.&lt;/p&gt;

&lt;p&gt;Der &lt;a href=&quot;https://de.wikipedia.org/wiki/GNU_Compiler_Collection&quot;&gt;GCC&lt;/a&gt; versucht 
in der Regel alles an Features zu aktivieren ja nachdem,
auf welcher CPU er betrieben wird. Kompiliert man auf einem 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Intel-Core-i-Serie&quot;&gt;i7&lt;/a&gt;, dann hat man 
i7-Features im Code, so lange man sie nicht explizit abschaltet.&lt;/p&gt;

&lt;p&gt;Das gleiche gilt für &lt;code&gt;ARM NEON&lt;/code&gt;, und da mein PinePhone diesen Befehlssatz 
unterstützt, kann dieser beim Kompilieren herangezogen werden.&lt;/p&gt;

&lt;p&gt;Blöderweise nutzt die &lt;code&gt;LIBPNG&lt;/code&gt; ein paar Makros um dieses Feature zu erkennen
und versucht dann eine andere ARM-Assembler Implementierung aufzurufen.&lt;/p&gt;

&lt;p&gt;Jetzt war es aber mein erklärtes Ziel, keinen (bzw. so gut wie keinen) 
Assemblercode im Projekt zu haben, damit keine Spezialfeatures wirksam
werden, die nicht auf allen CPUs laufen.&lt;br /&gt;
Und genau deshalb sind diese Sourcen der externen Bibliotheken auch nicht
mit eingecheckt worden.&lt;/p&gt;

&lt;p&gt;Nun, der &lt;a href=&quot;https://de.wikipedia.org/wiki/CMake&quot;&gt;CMAKE&lt;/a&gt; Workaround ist einfach:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;add_definitions(-DPNG_ARM_NEON_OPT=0)
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;ins &lt;code&gt;CMakeLists.txt&lt;/code&gt; und schon erkennt &lt;code&gt;LIBPNG&lt;/code&gt; den &lt;code&gt;NEON&lt;/code&gt; Support nicht mehr.
Und da das GATE Projekt die Bibliothek nur für “einfache” Bildkonvertierungen
nutzt um Grafiken einzubinden, ist die Performance hier kein Thema.&lt;/p&gt;

&lt;p&gt;Schlimmer ist aber die Erkenntnis, dass neben den Plattform-Unterschieden von
Linux jetzt auch noch die CPU des Buildsystems den Bau von 
unabhängigen Binärdateien behindert.&lt;/p&gt;

&lt;p&gt;Natürlich wäre es jetzt möglich per CMake allerlei Abschaltungen von Features
einzubauen … aber … irgendwann muss man auch hinterfragen, ob das denn
Sinn macht.&lt;/p&gt;

&lt;p&gt;Eines steht jedoch hiermit wieder mal fest:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Während man für Windows Binaries bauen kann, die von NT 4 bis Windows 10
und vom Pentium 586 bis zum aktuellen AMD Ryzen lauffähig sind, 
wird das beim GCC ein unguter Hürdenlauf.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;PS: Naja … um ehrlich zu sein, auch Microsoft setzt neue Befehlssätze bei
neuen Compilern voraus. Doch dort kann ich zumindest mit 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_Studio#Version_2005&quot;&gt;VS 2005&lt;/a&gt; ein Brücke 
bauen, die über 20 Jahre Codegeschichte miteinander verbindet.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>try außerhalb von Funktionen</title>
   <link href="https://www.opengate.at/blog/2020/11/try-constructor/"/>
   <published>2020-11-22T12:00:00+01:00</published>
   <updated>2020-11-22T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2020/11/try-constructor</id>
   <category term="devel" />
   <summary type="text">Auch nach 13 Jahren lerne ich was Neues in C++
… oder sollte ich mich schämen, dass ich es noch nicht wusste?


  try - catch funktioniert auch außerhalb von Funktionen.


und ganz konkret: Bei Konstruktor-Code kann try-catch die 
Memberinitialisierung prüfen…
</summary>
   <content type="html">&lt;p&gt;Auch nach 13 Jahren lerne ich was Neues in &lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B&quot;&gt;C++&lt;/a&gt;
… oder sollte ich mich schämen, dass ich es noch nicht wusste?&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;code&gt;try - catch&lt;/code&gt; funktioniert auch außerhalb von Funktionen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;und ganz konkret: Bei Konstruktor-Code kann try-catch die 
Memberinitialisierung prüfen…
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Das kennt vermutlich jeder:&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color:#B44;font-weight:bold&quot;&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color:#B44;font-weight:bold&quot;&gt;&amp;lt;string&amp;gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt; throw_something()
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;throw&lt;/span&gt; &lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;}
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; foo()
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;try&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;  {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;    throw_something();
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;    std::cout &amp;lt;&amp;lt; &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;No error - no problem&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;  }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;catch&lt;/span&gt;(&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; error_code)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;  {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;    std::cerr &amp;lt;&amp;lt; &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Exception: &lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &amp;lt;&amp;lt; error_code;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; error_code;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n21&quot; name=&quot;n21&quot;&gt;21&lt;/a&gt;&lt;/span&gt;  }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n22&quot; name=&quot;n22&quot;&gt;22&lt;/a&gt;&lt;/span&gt;}
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n23&quot; name=&quot;n23&quot;&gt;23&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n24&quot; name=&quot;n24&quot;&gt;24&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; main()
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n25&quot; name=&quot;n25&quot;&gt;25&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n26&quot; name=&quot;n26&quot;&gt;26&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; foo();
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n27&quot; name=&quot;n27&quot;&gt;27&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Aber, dass &lt;code&gt;try-catch&lt;/code&gt; auch außerhalb von Funktionen, bzw. ohne 
Funktionsklammern funktioniert, ist mir bisher tatsächlich noch nicht 
untergekommen:&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; foo()
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;try&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  throw_something();
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  std::cout &amp;lt;&amp;lt; &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;No error - no problem&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;}
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;catch&lt;/span&gt;(&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; error_code)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  std::cerr &amp;lt;&amp;lt; &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Exception!&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; error_code;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Na gut, das bringt einem jetzt nicht wirklich was, weil es genau das gleiche
macht, wie der erste Code.&lt;/p&gt;

&lt;p&gt;Aber … wenn man in einem Konstruktor die Initialisierung einer 
Membervariable per &lt;code&gt;try-catch&lt;/code&gt; behandeln möchte, dann muss &lt;code&gt;try&lt;/code&gt; außerhalb 
des Funktionsrumpfes arbeiten.&lt;/p&gt;

&lt;p&gt;Und das sieht dann so aus:&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;struct&lt;/span&gt; clazz
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  std::&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;string&lt;/span&gt; member;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  clazz()
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;try&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  : member(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Hello World&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;  {
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;    std::cout &amp;lt;&amp;lt; &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;yay, member initialized&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;catch&lt;/span&gt;(...)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;  {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;    std::cerr &amp;lt;&amp;lt; &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;oh no, member initialization failed&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;  }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;};
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Lustig, dass ich das bis heute nie gebraucht hatte und auch nicht wusste.
Dafür liebe ich diesen Compiler … er kann mich nach so vielen Jahren 
immer noch (mit neuem Wissen) überraschen.&lt;/p&gt;

&lt;p&gt;Tja, ein Code sagt mehr als tausend Worte, also: End-Of-Blog.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>LGT8F328P MiniEVB</title>
   <link href="https://www.opengate.at/blog/2020/11/lgt8f328p/"/>
   <published>2020-11-21T12:00:00+01:00</published>
   <updated>2020-11-21T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2020/11/lgt8f328p</id>
   <category term="hardware" />
   <summary type="text">Eigentlich habe ich ausreichend ATMEGA328p
Chips zu Hause … doch wenn ein Klon um 70 Cent (Dollar-Cent) angeboten 
wird, kann ich auch nicht wiederstehen und ein paar dieser Teile mitbestellen.

Es handelt sich dabei um einen LGT8F328P Mikrocontroller.

Dieser Chip soll zum Arduino Pro Mini 
kompatibel sein … aber so ganz stimmt das nicht.
</summary>
   <content type="html">&lt;p&gt;Eigentlich habe ich ausreichend &lt;a href=&quot;https://www.microchip.com/wwwproducts/en/ATmega328P&quot;&gt;ATMEGA328p&lt;/a&gt;
Chips zu Hause … doch wenn ein Klon um 70 Cent (Dollar-Cent) angeboten 
wird, kann ich auch nicht wiederstehen und ein paar dieser Teile mitbestellen.&lt;/p&gt;

&lt;p&gt;Es handelt sich dabei um einen &lt;code&gt;LGT8F328P&lt;/code&gt; Mikrocontroller.&lt;/p&gt;

&lt;p&gt;Dieser Chip soll zum &lt;a href=&quot;http://www.arduino.cc/en/pmwiki.php?n=Main/ArduinoBoardProMini&quot;&gt;Arduino Pro Mini&lt;/a&gt; 
kompatibel sein … aber so ganz stimmt das nicht.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Ich habe seit Jahren ein paar Pro-Mini Nachbauten herumliegen, aber deren
fehlender USB Anschluss lässt mich immer zu den Schwesterchips greifen, 
wenn ich mal was ausprobieren will, weil man die so praktisch anstöpseln kann.&lt;/p&gt;

&lt;p&gt;Doch … das war bevor ich versehentlich eine Schachtel &lt;code&gt;CP2102&lt;/code&gt; und &lt;code&gt;CH340E&lt;/code&gt;
&lt;a href=&quot;https://en.wikipedia.org/wiki/USB_adapter&quot;&gt;USB to Serial-TTL&lt;/a&gt; Adapter geordert 
hatte (ja die Dinger sind auch verdammt billig, 10 Stück für ein paar Euro
in Fernost - versus 1 Stück für 5-10 Euro im hiesigen Fachhandel).
Vermutlich werde ich bis zu meinem Tod gar nicht mehr alle verbauen können …&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/mcu-lgt8f328p.jpg&quot; alt=&quot;LGT8F328P MiniEVB&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Das bedeutet also, ich kann mit so einem USB-Adapter auch die Pro-Mini Klone
zügig per &lt;a href=&quot;https://www.arduino.cc/en/software&quot;&gt;Arduino IDE&lt;/a&gt; 
(ohne einen zusätzlichen UNO) programmieren.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/mcu-lgt8f328p-serial.jpg&quot; alt=&quot;LGT8F328P CH340E&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Und das funktionierte tatsächlich problemlos, kaum war der Sketch-Upload 
fertig blinkte die übliche LED … aber leider nicht in dem Intervall,
das vorgeschrieben war, es war vieeeeeeeeel langsamer.&lt;/p&gt;

&lt;p&gt;Das riecht streng nach der falschen Chipkonfiguration oder dem falschen CPU
Takt.&lt;br /&gt;
Doch wozu hat man Suchmaschinen?&lt;br /&gt;
Und zum Glück existiert ein Github Projekt unter 
&lt;a href=&quot;https://github.com/LGTMCU/Larduino_HSP/&quot;&gt;https://github.com/LGTMCU/Larduino_HSP/&lt;/a&gt;
mit den Quellcodes und angepassten Bootloadern für den Chip. Dieses 
Board-Package wandert ins Unterverzeichnis &lt;code&gt;%HOMEPATH%\Documents\Arduino\hardware&lt;/code&gt;
und nach dem Neustart der IDE kann man LGT8F328P Chips im Menü auswählen.&lt;/p&gt;

&lt;p&gt;Meiner ist der &lt;em&gt;LGT8F328P-LQFP32 MiniEVB (16 MHz)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Wenn man sich die Datei &lt;code&gt;boards.txt&lt;/code&gt; der neuen Hardware ansieht, fällt einem
der unterschiedliche Bootloader auf, der mitgeliefert wird, wie auch,
dass ein paar Konfigurations-Bits anders gesetzt sind:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;# %HOMEPATH%\Documents\Arduino\hardware\LGT\avr\boards.txt
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;lardu_328p.name= LGT8F328P-LQFP32 MiniEVB (16 MHz)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;lardu_328p.upload.tool=avrdude
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;lardu_328p.upload.protocol=arduino
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;lardu_328p.upload.maximum_size=29696
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;lardu_328p.upload.speed=57600
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;lardu_328p.bootloader.tool=avrdude
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;lardu_328p.bootloader.high_fuses=0xff
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;lardu_328p.bootloader.low_fuses=0xff
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;lardu_328p.bootloader.extended_fuses=0x07
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;lardu_328p.bootloader.path=lgt8fx8p
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;lardu_328p.bootloader.file=lgt8fx8p/optiboot_lgt8f328p.hex
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;lardu_328p.bootloader.unlock_bits=0x3f
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;lardu_328p.bootloader.lock_bits=0x3f
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;lardu_328p.build.mcu=atmega328p
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;lardu_328p.build.f_cpu=16000000L
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;lardu_328p.build.core=lgt8f
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;lardu_328p.build.variant=lgt8fx8p
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;lardu_328p.build.board=AVR_LARDU_328E
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Im Vergleich zu den Einstellungen der Pro Mini Arduino Boards:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;##############################################################
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;pro.name=Arduino Pro or Pro Mini
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;pro.upload.tool=avrdude
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;pro.upload.protocol=arduino
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;pro.bootloader.tool=avrdude
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;pro.bootloader.unlock_bits=0x3F
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;pro.bootloader.lock_bits=0x0F
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;pro.build.board=AVR_PRO
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;pro.build.core=arduino
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;pro.build.variant=eightanaloginputs
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;## Arduino Pro or Pro Mini (5V, 16 MHz) w/ ATmega328P
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;## --------------------------------------------------
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;pro.menu.cpu.16MHzatmega328=ATmega328P (5V, 16 MHz)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;pro.menu.cpu.16MHzatmega328.upload.maximum_size=30720
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;pro.menu.cpu.16MHzatmega328.upload.maximum_data_size=2048
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;pro.menu.cpu.16MHzatmega328.upload.speed=57600
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;pro.menu.cpu.16MHzatmega328.bootloader.low_fuses=0xFF
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;pro.menu.cpu.16MHzatmega328.bootloader.high_fuses=0xDA
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;pro.menu.cpu.16MHzatmega328.bootloader.extended_fuses=0xFD
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;pro.menu.cpu.16MHzatmega328.bootloader.file=atmega/ATmegaBOOT_168_atmega328.hex
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n21&quot; name=&quot;n21&quot;&gt;21&lt;/a&gt;&lt;/span&gt;pro.menu.cpu.16MHzatmega328.build.mcu=atmega328p
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n22&quot; name=&quot;n22&quot;&gt;22&lt;/a&gt;&lt;/span&gt;pro.menu.cpu.16MHzatmega328.build.f_cpu=16000000L
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Was die PINs anbelangt, ist der Klon nicht wirklich “geklont”, sondern was 
ganz anderes und kleiner. Während der echte Pro Mini alle Pins führt, die
ein Arduino UNO auch bereitstellt (28), bietet der LGT8F328P auf seinen
20 Pins nur ein reduziertes Set.&lt;/p&gt;

&lt;p&gt;Es sieht so aus, als wären die digitalen Pins 5 und 6 mit 0 (RX) und 1 (TX)
vereint, wie auch 3 mit 4, 8 mit 9 und 10 mit 11, wobei TX/RX zusätzlich an 
der Seite hinausgeführt sind. Die analogen Pins 2 und 3 fehlen generell.&lt;br /&gt;
Nun das erschwert auf jeden Fall schon mal 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Serial_Peripheral_Interface&quot;&gt;SPI&lt;/a&gt;, das 
üblicherweise auf den Arudino Pins 10, 11, 12 und 13 betrieben wird.&lt;/p&gt;

&lt;p&gt;Vermutlich muss man hier vom üblichen Arduino-Standard abweichen, um 
ordentlichen kommunizieren zu können. 
Immerhin ist &lt;a href=&quot;https://de.wikipedia.org/wiki/I%C2%B2C&quot;&gt;I2C&lt;/a&gt;
ist nicht betroffen (A4 und A5).&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/mcu-lgt8f328p-compare.jpg&quot; alt=&quot;LGT8F328P-mini-micro&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Man findet im Netz auch kritische Töne gegenüber dem Stiefbruder
aus Fernost. Er besitzt keinen eigenen 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Electrically_Erasable_Programmable_Read-Only_Memory&quot;&gt;EEPROM&lt;/a&gt;,
sondern kann über andere Konfigurationsbits genötigt werden den 
Programmspeicher dafür zu nutzen und die Doku ist nicht so
frei und offen (heißt: nur chinesisch), damit man alles verstehen
kann.&lt;/p&gt;

&lt;p&gt;Das lässt natürlich Spielraum für Spekulationen was sich eventuell
anders verhält als beim echten 328P von ATMEL.
Auch soll der A/D Wandler 12 bits genau sein und nicht nur 10 wie 
üblich.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ich gehe mal davon aus, dass viele kleine Mikrocontrollerprojekt, die
nur ein paar Pins ein und ausschalten oder Sensoren auslesen, recht kompatibel
zum Arduino ATMEL Standard sind.&lt;/p&gt;

&lt;p&gt;Vor geraumer Zeit hatte ich den &lt;a href=&quot;/blog/2019/08/stm8s103f3p6/&quot;&gt;STM8&lt;/a&gt;
Chip gelobt, der ähnlich potent ist wie ein 328P aber auch unter einem Dollar
kostet. Sein großer Nachteil war, dass er nur einen C-Compiler aber kein 
Arduino C++ mitbrachte, womit viele Arduino Bibliotheken schlicht nicht liefen 
oder mit C-Funktionen nachgebaut werden mussten.&lt;/p&gt;

&lt;p&gt;Mit dem &lt;code&gt;LGT8F328P&lt;/code&gt; hätten wir jetzt quasi das erweiterte Programm:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Ein Stück kostet unter einem Dollar (70-80 Cent)&lt;/li&gt;
  &lt;li&gt;Arduino C++ tauglich&lt;/li&gt;
  &lt;li&gt;Wir haben die meisten Pins, die ein Arduino Pro Mini auch hat
(nur bei SPI sollte man aufpassen)&lt;/li&gt;
&lt;/ul&gt;
</content>
 </entry>
 
 <entry>
   <title>Lock-Down, Yay!</title>
   <link href="https://www.opengate.at/blog/2020/11/lock-down-2/"/>
   <published>2020-11-15T12:00:00+01:00</published>
   <updated>2020-11-15T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2020/11/lock-down-2</id>
   <category term="general" />
   <summary type="text">Nach einem langen hin und her, kam dann heute, womit zu rechnen war.
Die Regierung hat heute angekündigt, dass der “sanfte Lock-Down” der 
letzten beiden Wochen wenig bis nichts gebracht hat und wir ab 
Dienstag wieder einen harten 
Lock-Down 
erleben werden.


  Herr Gott, wie mich das langweilt!


</summary>
   <content type="html">&lt;p&gt;Nach einem langen hin und her, kam dann heute, womit zu rechnen war.
Die Regierung hat heute angekündigt, dass der “sanfte Lock-Down” der 
letzten beiden Wochen wenig bis nichts gebracht hat und wir ab 
Dienstag wieder einen harten 
&lt;a href=&quot;https://de.wikipedia.org/wiki/COVID-19-Pandemie_in_%C3%96sterreich&quot;&gt;Lock-Down&lt;/a&gt; 
erleben werden.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Herr Gott, wie mich das langweilt!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Die wichtige Aussage, wir sollen möglichst keine großen Menschenansammlungen
besuchen oder generieren, hat natürlich voll gezogen.&lt;br /&gt;
Alle liefen panisch in den Baumarkt und reihten sich dort in lange Schlangen
vor den Kassen ein … zumindest wird das berichtet.&lt;/p&gt;

&lt;p&gt;Ich war gestern am Samstag nur 10 Minuten im Supermarkt um die Ecke um 
Brötchen und Schokolade einzukaufen. Da waren nicht mehr Menschen als üblich
die letzten 10 Jahre, und an der Kassa war genau eine Person vor mir.&lt;/p&gt;

&lt;p&gt;Schlimmer sieht es dagegen schon seit zwei Wochen in meiner Firma aus.
Die Kantine wurde stark reduziert ist nur zu 30% besetzt, und damit hat sie 
nun teilweise auch die letzten Mitarbeiter verprellt, die dort noch ihr
Mittagessen abholen wollten.&lt;br /&gt;
Gewinner der Aktion ist “das Wurschtsemmerl mit Gurkerl” aus dem Supermarkt, 
denn die gehen (obwohl kalt gelagert) “weg wie warme Semmeln”.&lt;/p&gt;

&lt;p&gt;In meiner Abteilung wurden bereits die ersten Kündigungen ausgesprochen, weil
es an Geld für weitere Projekte fehlt (ich war verwunderlicherweise nicht 
dabei), obwohl vor zwei Monaten solchen Maßnahmen noch dementiert wurden.&lt;/p&gt;

&lt;h3 id=&quot;stadt-vs-land&quot;&gt;Stadt vs. Land&lt;/h3&gt;

&lt;p&gt;Aus meiner bescheidenen Sicht, hält sich die &lt;a href=&quot;https://de.wikipedia.org/wiki/Wien&quot;&gt;Stadt Wien&lt;/a&gt;
immer noch sehr gut in Sachen Infektionen. Eigentlich würde ich bei einer 
Millionenstadt eine rasende Ausbreitung erwarten. Doch auch wenn mich manche 
Mitmenschen mit ihrer offensichtlichen Nichteinhaltung der Abstandsregeln 
nerven, so geht der Großteil sehr sozial miteinander um.&lt;/p&gt;

&lt;p&gt;Anstatt dessen wütet das Virus nun in kleinen Dörfern, die bisher als Inseln
der Seeligen galten.&lt;br /&gt;
Wenn man aber nachfragt, verliert man die Verwunderung, denn anstatt die
geografische Isolation zum Vorteil zu nutzen, fuhren alle fleißig in den
Urlaub oder weigerten sich hartnäckig den wöchentlichen Einkaufsbummel im
billigen Nachbarland mal auszulassen.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Kurz gesagt: Besser infizieren hätte man sich kaum können.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Und so liegen auch in Randdörfern der Provinzen einige Menschen krank im 
Bett bzw. füllen die knapper werdenden Spitalsplätze auf.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Im Frühjahr hat Österreich extrem reagiert und viele Wirtschaftszweige lahm
gelegt. Jetzt soll sich dieser Schritt wiederholen und man sperrt Geschäfte
und die Gastronomie zu, obwohl die aktuellen Infektionszahlen großteils auf
private Zusammenkünfte zurückzuführen sind, wo man die “Mitbringsel” aus 
Urlaub und Großeinkauf an Freunde und Familie weiterverteilt hat.&lt;/p&gt;

&lt;p&gt;Ich dürfte weiter gesund sein, aber ich habe schließlich auch wenige Orte
aufgesucht, an denen ich mich hätte infizieren können.
Tatsächlich ist die Busfahrt zum Arbeitsort vermutlich meine beste Chance 
angesteckt zu werden.&lt;br /&gt;
Doch ich vermute mal, dass nun auch meine Firma den Mitarbeitern noch mehr
als bisher Home-Office vorschlägt und ich somit weiter in meiner Wohnung
sitzen bleiben darf.&lt;/p&gt;

&lt;p&gt;Mehr und mehr glaube ich daran, dass mein Luft-Ionistor die bösen Viren
bei mir zu Hause abtötet … vielleicht ist das das größte Problem an der 
gesamten Pandemie: “Wir &lt;strong&gt;glauben&lt;/strong&gt;, dass …”, wissen aber immer noch 
viel zu wenig.&lt;/p&gt;

&lt;p&gt;Wäre mal schön hierzu ehrliche Worte von der Regierung zu hören, die stets
beteuert eine Lösung zu wissen. Zumindest glauben sie alle fest daran,
etwas zu wissen.&lt;/p&gt;

&lt;p&gt;Ich für meinen Teil, vertraue jemanden eher, der mir sagt, er wisse etwas 
nicht genau, handle aber nach bestem Gewissen, als jemandem der stetig
verspricht, die richtige Lösung im Vorhinein zu kennen.&lt;/p&gt;

&lt;p&gt;Fortsetzung folgt spätestens im Lock-Down #3 nächstes Jahr, falls ich da 
noch leben sollte …&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Das Array-Reflection Problem</title>
   <link href="https://www.opengate.at/blog/2020/11/array-of-struct/"/>
   <published>2020-11-14T12:00:00+01:00</published>
   <updated>2020-11-14T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2020/11/array-of-struct</id>
   <category term="devel" />
   <summary type="text">Da komme ich endlich zum Thema Laden und Schreiben von Konfigurationsdateien
und die erste provisorische Implementierung steht, schon kommen mir Zweifel.


  Im Anfang war die Kraft!
Doch, auch indem ich dieses niederschreibe,
Schon warnt mich was, daß ich dabei nicht bleibe.
Mir hilft der Geist! Auf einmal seh ich Rat
Und schreibe getrost: Im Anfang war die Tat!


</summary>
   <content type="html">&lt;p&gt;Da komme ich endlich zum Thema Laden und Schreiben von Konfigurationsdateien
und die erste provisorische Implementierung steht, schon kommen mir Zweifel.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Im Anfang war die Kraft!&lt;br /&gt;
Doch, auch indem ich dieses niederschreibe,&lt;br /&gt;
Schon warnt mich was, daß ich dabei nicht bleibe.&lt;br /&gt;
Mir hilft der Geist! Auf einmal seh ich Rat&lt;br /&gt;
Und schreibe getrost: Im Anfang war die Tat!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Wie schön und einfach wäre die Welt, käme sie ohne 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Feld_(Datentyp)&quot;&gt;Arrays&lt;/a&gt; aus. Jede
&lt;a href=&quot;https://de.wikipedia.org/wiki/Extensible_Markup_Language&quot;&gt;XML&lt;/a&gt;, 
&lt;a href=&quot;https://de.wikipedia.org/wiki/JavaScript_Object_Notation&quot;&gt;JSON&lt;/a&gt; oder 
&lt;a href=&quot;https://de.wikipedia.org/wiki/YAML&quot;&gt;YAML&lt;/a&gt; Datei könnte man mit Leichtigkeit 
in eine &lt;a href=&quot;https://de.wikibooks.org/wiki/C-Programmierung:_Komplexe_Datentypen&quot;&gt;C-Struktur (struct)&lt;/a&gt;
überführen, wenn diese mit ein paar Reflection-Infos versehen ist.&lt;/p&gt;

&lt;p&gt;Array sind jedoch tückische Konstrukte. Sie stehen als eigenständige
Objekte da, beinhalten aber eine beliebige Menge von anderen Daten.&lt;/p&gt;

&lt;p&gt;… und hier stellt sich die Frage: Wie viel darf oder soll ein Array 
von seinem Inhalt wissen?&lt;/p&gt;

&lt;h3 id=&quot;arrays-mit-konstruktionsbauplänen&quot;&gt;Arrays mit Konstruktionsbauplänen&lt;/h3&gt;

&lt;p&gt;Arrays sind gemäß ihrer Schnittstelle so gebaut, dass sie von außen
fertige Daten überreicht bekommen. Diese “speichern” sie und sie auf Anfrage
wieder zurück.&lt;/p&gt;

&lt;p&gt;Aber so ein Array-Container-Objekt kann nicht selbständig Daten erzeugen, 
die es dann aufnehmen kann.&lt;/p&gt;

&lt;p&gt;Über dieses Problem bin ich nun beim Thema &lt;code&gt;Array-of-Struct&lt;/code&gt; gestoßen.&lt;/p&gt;

&lt;p&gt;Im GATE Projekt, haben alle primitiven Datentypen eine &lt;code&gt;Type-ID&lt;/code&gt; und jedes 
Array eines primitiven Types hat ebenfalls eine solche ID.
Und dann gibt es dann noch spezielle &lt;code&gt;structs&lt;/code&gt; mit Deskriptoren, wodurch eine
zusammengesetzte Datenstruktur ganz am Anfang eine standardisierte
Inhaltsangabe mitbekommt und der Datentyp generisch auslesbar und
beschreibbar wird.&lt;br /&gt;
Ein solches &lt;code&gt;gate_struct_t&lt;/code&gt; ist quasi die Basisklasse für jede beliebige 
&lt;code&gt;struct&lt;/code&gt; Implementierung mit unterschiedlichen Membern, jedoch alle starten
mit einem Reflection-Descriptor der diese Member beschreibt.&lt;/p&gt;

&lt;p&gt;Jede &lt;code&gt;Array-of-gate_struct_t&lt;/code&gt; Instanz erhält somit die gleiche Typen-ID, 
obwohl der Inhalt und Typ seiner &lt;code&gt;struct&lt;/code&gt;s ein anderer sein kann.&lt;/p&gt;

&lt;p&gt;Wie soll jetzt aber ein Parser aus dem generischen &lt;code&gt;Array-of-gate_struct_t&lt;/code&gt;
genau einen ganz spezielle &lt;code&gt;struct&lt;/code&gt; Instanz zusammenbauen, die dann in ein 
Array eingefügt werden soll?&lt;/p&gt;

&lt;h3 id=&quot;erweiterung-des-kopierkonstruktors&quot;&gt;Erweiterung des Kopierkonstruktors&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;gate_arraylist_t&lt;/code&gt; Objekte können Daten von außen in sich selbst 
hineinkopieren (ganze analog zu &lt;code&gt;std::vector&lt;/code&gt; in C++ und das tun sie über 
einen Copy-Constructor Pointer, der formal zum Typen der Array-Einträge 
gehört. Aber der kann nur etwas kopieren was schon da ist und nichts 
“Neues” erschaffen.&lt;/p&gt;

&lt;p&gt;Ohne jetzt alles im gesamten Framework ändern zu müssen, blieb mir 
folgender Weg offen:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Die Copy-Constructor-Funktion soll im Falle eines Null-Pointers eine
neue leere Instanz eines Objektes erschaffen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Erzeugt man nun also eine Instanz von &lt;code&gt;gate_arraylist_t&lt;/code&gt; und initialisiert 
diese mit dem Konstruktorpointer seines Inhalts, erlangt das entstehende
Array die Fähigkeit nicht nur bestehende Daten in sich hineinzukopieren,
sondern auch neue Daten per “Defaultkonstruktor” zu erzeugen.&lt;/p&gt;

&lt;p&gt;Die neue Funktion &lt;code&gt;gate_arraylist_create_item()&lt;/code&gt; liefert ein neues freies 
Element mit dem richtigen Typ, und wenn dies wiederum ein &lt;code&gt;struct&lt;/code&gt; mit 
Deskriptor ist, kann wieder der generische Code anlaufen, um das Element 
(z.B.: per Deserialisierung) zu befüllen.&lt;br /&gt;
Das funktioniert natürlich nur, weil ein &lt;code&gt;struct&lt;/code&gt;-Descriptor neben der 
Type-ID auch die Summe der Größen aller Member-Datentypen beschreibt.&lt;/p&gt;

&lt;p&gt;Am Ende wird das neue Element in das Array aufgenommen und alle sind 
glücklich.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Hier zeigt sich wieder mal, welche Vorteile Sprachen mit eingebauter Reflection
haben. Und während man sich in C++ noch mit Templates etwas behelfen kann, 
steht man in C ganz alleine da.&lt;/p&gt;

&lt;p&gt;Der Missbrauch von C-Objekt-Kopierkonstruktoren gefällt mir zwar nicht sehr,
doch es stellt eine Möglichkeit dar, zwei Fliegen mit eine Klappe zu schlagen.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Wo C++ von C geschlagen wird</title>
   <link href="https://www.opengate.at/blog/2020/11/c-power/"/>
   <published>2020-11-08T12:00:00+01:00</published>
   <updated>2020-11-08T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2020/11/c-power</id>
   <category term="devel" />
   <summary type="text">Bjarne Stroustrup hatte 
bei der Schaffung der Sprache C++
einen Grundsatz mitaufgestellt:


  Es soll unterhalb von C++ keinen Bedarf für eine andere Low-Level Sprache 
geben.


Mit anderen Worten:


  C ist keine notwendige Untermenge von C++


Doch da gibt es so ein paar Dinge, die das gute alte C “besser” kann.
</summary>
   <content type="html">&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Bjarne_Stroustrup&quot;&gt;Bjarne Stroustrup&lt;/a&gt; hatte 
bei der Schaffung der &lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B&quot;&gt;Sprache C++&lt;/a&gt;
einen Grundsatz mitaufgestellt:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Es soll unterhalb von C++ keinen Bedarf für eine andere Low-Level Sprache 
geben.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Mit anderen Worten:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;C ist keine notwendige Untermenge von C++&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Doch da gibt es so ein paar Dinge, die das gute alte C “besser” kann.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Das GATE Projekt lehrt mich in vielen Bereichen, wie unfassbar einfacher es in
C++ ist, Code zu schreiben als in &lt;a href=&quot;https://de.wikipedia.org/wiki/C_(Programmiersprache)&quot;&gt;reinem C&lt;/a&gt;. 
Ich verbringe viele Stunden mit dem Tippen von Zeilen, die in C++ dank 
Operatoren, Konstruktoren und Destruktoren nur kleine Einzeiler wären.&lt;/p&gt;

&lt;p&gt;Besonders Objekte und &lt;a href=&quot;https://de.wikipedia.org/wiki/Polymorphie_(Programmierung)&quot;&gt;Polymorphie&lt;/a&gt; 
hat C++ nativ drauf, wo in C die Deklaration von virtuellen Methodentabellen 
und deren Implementierung pro Objekt von Hand ausgearbeitet werden müssen.&lt;/p&gt;

&lt;p&gt;Früher bestand daher der Bedarf nach C vor allem bei Performance-kritischen
Programmteilen. C++ generierte zusätzlichen Metacode, der an die Einfachheit
von C nicht herankam. Doch auch diese Domäne eroberten neue hoch-optimierte
Compiler, womit Bjarne Stroustrups Zielsetzung erfüllt schien.&lt;/p&gt;

&lt;p&gt;Eine Ausnahme gibt es (aus meiner Sicht) aber:&lt;/p&gt;

&lt;h3 id=&quot;statische-daten-und-objekte&quot;&gt;Statische Daten und Objekte&lt;/h3&gt;

&lt;p&gt;Ein &lt;code&gt;static char const*&lt;/code&gt; hat gegenüber einem &lt;code&gt;static std::string const&lt;/code&gt; vor 
allem den Vorteil, dass die Daten im Datensegment liegen, während beim C++ 
Objekt ein Konstruktor aufgerufen wird und die Daten auf den Heap (oder in 
einen anderen Bereich) kopiert werden.&lt;br /&gt;
Dieses Problem soll &lt;code&gt;constexpr&lt;/code&gt; im neuesten Standard beheben, doch wenn es 
um Objekte, Vererbung und Instanzen geht, kommt man bei C++ einfach nicht
darum herum, dass Code ausgeführt werden muss um Daten zu initialisieren.&lt;br /&gt;
Und sobald ein störrisches &lt;code&gt;if&lt;/code&gt; in einer Methode ist, verliert &lt;code&gt;constexpr&lt;/code&gt;
seine Wirkung.&lt;/p&gt;

&lt;p&gt;In C lässt sich aber ein Fall so hinbiegen, dass ein Objekt samt 
&lt;a href=&quot;https://en.wikipedia.org/wiki/Virtual_method_table&quot;&gt;V-Table&lt;/a&gt; und Daten 
statisch deklariert wird und ohne “Konstruktion” wie ein reguläres
Objekt nach außen erscheint.&lt;/p&gt;

&lt;p&gt;Natürlich wäre ein solcher C Code automatisch auch mit C++ kompilierbar, 
doch man wird von einem waschechten C++ Entwickler nie solche Zeilen erwarten.&lt;/p&gt;

&lt;h3 id=&quot;beispiel-factory-schnittstellen&quot;&gt;Beispiel Factory-Schnittstellen&lt;/h3&gt;

&lt;p&gt;Die &lt;a href=&quot;https://de.wikipedia.org/wiki/Microservices&quot;&gt;MicroService&lt;/a&gt; Implementierung 
des GATE Projektes erfordert &lt;a href=&quot;https://de.wikipedia.org/wiki/Fabrikmethode&quot;&gt;Factory-Objekte&lt;/a&gt;, 
die die eigentlichen Dienste bei Bedarf dynamisch erzeugen. Ein Codemodul oder
Plugin exportiert einfach eine Factory, die den Anforderungen des Servicehosts
entsprechen.&lt;/p&gt;

&lt;p&gt;Eine solche Factory ist (ganz analog zu &lt;a href=&quot;https://de.wikipedia.org/wiki/Component_Object_Model&quot;&gt;COM&lt;/a&gt;
oder einem virtuellen C++ Objekt) ein Pointer zu einem Objekt. Dieses enthält 
eine Schnittstelle für Referenzzählung und somit wäre die übliche 
Implementierung auf den Heap zugeschnitten.&lt;/p&gt;

&lt;p&gt;Doch in C können wir ein solches Objekt auch ganz einfach als globales Objekt
in statische Variablen packen. Diese &lt;code&gt;struct&lt;/code&gt; wird dann global initialisiert
was zur Folge hat, dass ein Abbild des Objektes einfach im Datensegment landet.&lt;/p&gt;

&lt;p&gt;Es ist &lt;strong&gt;kein&lt;/strong&gt; Konstruktor und &lt;strong&gt;kein&lt;/strong&gt; Heap notwendig und wir können Pointer
auf diese eine globale Factory mehrfach “verkaufen”. Die Referenzzählung 
hinter der Schnittstelle findet einfach nicht statt, so wie auch keine 
Löschung durchgeführt wird … denn es sind nur statische Daten.&lt;/p&gt;

&lt;p&gt;Ein Code sagt mehr als tausend Worte:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;typedef&lt;/span&gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;struct&lt;/span&gt; my_vtbl
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; (*my_method)(&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;* thisptr, &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; my_param);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;} my_vtbl_t;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;typedef&lt;/span&gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;struct&lt;/span&gt; my_implementation
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;  my_vtbl_t &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt;* vtbl;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;        
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; some_globale_data;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;} my_implementation_t;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;static&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; my_method_implementation(&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;* thisptr, &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; my_param)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;  my_implementation_t* self = (my_implementation_t)thisptr;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;/* do something */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;}
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;static&lt;/span&gt; my_vtbl_t &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt; my_vtbl = 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n21&quot; name=&quot;n21&quot;&gt;21&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n22&quot; name=&quot;n22&quot;&gt;22&lt;/a&gt;&lt;/span&gt;  &amp;amp;my_method_implementation
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n23&quot; name=&quot;n23&quot;&gt;23&lt;/a&gt;&lt;/span&gt;};
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n24&quot; name=&quot;n24&quot;&gt;24&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n25&quot; name=&quot;n25&quot;&gt;25&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;static&lt;/span&gt; my_implementation_t global_instance = 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n26&quot; name=&quot;n26&quot;&gt;26&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n27&quot; name=&quot;n27&quot;&gt;27&lt;/a&gt;&lt;/span&gt;  &amp;amp;my_vtbl,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n28&quot; name=&quot;n28&quot;&gt;28&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#00D&quot;&gt;123456&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n29&quot; name=&quot;n29&quot;&gt;29&lt;/a&gt;&lt;/span&gt;};
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n30&quot; name=&quot;n30&quot;&gt;30&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n31&quot; name=&quot;n31&quot;&gt;31&lt;/a&gt;&lt;/span&gt;my_implementation_t* create_object()
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n32&quot; name=&quot;n32&quot;&gt;32&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n33&quot; name=&quot;n33&quot;&gt;33&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; &amp;amp;global_instance;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n34&quot; name=&quot;n34&quot;&gt;34&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Natürlich ist viel Schreibarbeit erforderlich, doch das Resultat ist ein
garantiert statisches Konstrukt, das kein Byte verschwendet.&lt;br /&gt;
Dadurch ist es Mikrocontroller-tauglich und kann die Idee von 
Objektorientierung und Schnittstellen auch in Bereiche hineintragen, in 
denen C++ Compiler zu verschwenderisch vorgehen.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Wahlen in den USA 2020</title>
   <link href="https://www.opengate.at/blog/2020/11/us-election/"/>
   <published>2020-11-07T12:00:00+01:00</published>
   <updated>2020-11-07T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2020/11/us-election</id>
   <category term="general" />
   <summary type="text">Was kümmert es einen Europäer, wenn in den Vereinigten Staaten
um das Amt des Präsidenten gekämpft wird?

Nun, der Regisseur Uwe Boll meinte 
dazu in einer Gesprächsrunde rund um seinen Amerika-kritischen Film 
Rampage 2:


  … weil ich will ja die (Amerikaner) attackieren, 
ich will, dass die ihr Verhalten ändern,
weil nur die können am Schluss auch im wahrsten Sinne des Wortes
die Welt retten …
… die haben die Power die Welt zu zerstören, 
die haben die Power jedes andere Land platt zu machen…


</summary>
   <content type="html">&lt;p&gt;Was kümmert es einen Europäer, wenn in den &lt;a href=&quot;https://de.wikipedia.org/wiki/Vereinigte_Staaten&quot;&gt;Vereinigten Staaten&lt;/a&gt;
um das Amt des Präsidenten gekämpft wird?&lt;/p&gt;

&lt;p&gt;Nun, der Regisseur &lt;a href=&quot;https://de.wikipedia.org/wiki/Uwe_Boll&quot;&gt;Uwe Boll&lt;/a&gt; meinte 
dazu in einer Gesprächsrunde rund um seinen Amerika-kritischen Film 
&lt;a href=&quot;https://en.wikipedia.org/wiki/Rampage:_Capital_Punishment&quot;&gt;Rampage 2&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;… weil ich will ja die (Amerikaner) attackieren, 
ich will, dass die ihr Verhalten ändern,
weil nur die können am Schluss auch im wahrsten Sinne des Wortes
die Welt retten …
… die haben die Power die Welt zu zerstören, 
die haben die Power jedes andere Land platt zu machen…&lt;/p&gt;
&lt;/blockquote&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Und Uwe Boll vertrat diese Meinung bereits 2014 und wetterte damals hart gegen
&lt;a href=&quot;https://de.wikipedia.org/wiki/Barack_Obama&quot;&gt;Barack Obama&lt;/a&gt; und dessen 
Unfähigkeit wichtige Änderungen im Land umzusetzen. Die mögliche Wahl eines 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Donald_Trump&quot;&gt;Donald Trump&lt;/a&gt; bezeichnete er 
damals als “beängstigend”.&lt;/p&gt;

&lt;iframe width=&quot;640&quot; height=&quot;360&quot; src=&quot;/blog/redirect.html?https%3A%2F%2Fwww.youtube-nocookie.com%2Fembed%2FuUki3aYS-Ew%3Fstart%3D671&quot; frameborder=&quot;1&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;

&lt;h3 id=&quot;demokratie-nur-dann-wenn-sie-mir-dient&quot;&gt;Demokratie nur dann, wenn sie MIR dient&lt;/h3&gt;

&lt;p&gt;Wie es heute aussieht, hat der &lt;a href=&quot;https://de.wikipedia.org/wiki/Demokratische_Partei_(Vereinigte_Staaten)&quot;&gt;demokratische&lt;/a&gt;
Kandidat &lt;a href=&quot;https://de.wikipedia.org/wiki/Joe_Biden&quot;&gt;Joe Biden&lt;/a&gt;
die &lt;a href=&quot;https://de.wikipedia.org/wiki/Pr%C3%A4sidentschaftswahl_in_den_Vereinigten_Staaten_2020&quot;&gt;US-Präsidentwahl 2020&lt;/a&gt; 
gewonnen und die nötige Anzahl an Bundesstaaten zu seinen Gunsten gedreht,
damit es zu keiner zweiten Amtszeit des 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Republikanische_Partei&quot;&gt;republikanischen&lt;/a&gt; 
Präsidenten Donald Trump kommt.&lt;/p&gt;

&lt;p&gt;Unabhängig von meiner eigenen politischen Meinung verstört mich jedoch der
Umgang des Verlierers mit dem Ergebnis. Denn Donald Trump und die Republikaner
verbreiten nun auf all ihren Kanälen, dass die Wahl sabotiert worden sei, 
denn es kann laut ihrer Meinung unmöglich ein Ergebnis entstehen, bei
dem ihre Politik legal “abgewählt” werden würde.&lt;/p&gt;

&lt;p&gt;Zwar gibt es bis dato keinen einzigen Beweis für diese Aussage, doch …
und das zeigt uns leider die Geschichte … reichen bereits Gerüchte in 
bestimmten Gesellschaftsschichten aus, um die Gewaltbereitschaft zu stärken.&lt;/p&gt;

&lt;p&gt;Der Waffenverkauf ist gestiegen und rechte bis ultrarechte Splittergruppen
proben bereits den Aufstand, sollte die Wahl nicht so ausgehen, wie sie es 
gerne hätten.&lt;/p&gt;

&lt;p&gt;Problematisch ist dabei, dass in diesem Jahr erstmals ein ausgedehntes 
Briefwahlsystem in den USA angewendet wurde. Und so wurden am Wahltag 
zuerst die persönlich abgegebenen Stimmen gezählt (womit eine Tendenz
zum amtierenden Präsidenten angezeigt wurde) und anschließend kamen mehr
und mehr Briefwahlstimmen hinzu, die den Demokraten die Mehrheit sicherte.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Da glüht der Aluhut!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Wären es nur “ein paar Spinner”, die es nun mal eben gibt, die hinter allem
einen unsichtbaren Feind vermuten, könnte man solche Gesinnungen ignorieren.
Doch wenn eine Partei, die knapp die Hälfte einer Bevölkerung vertritt, in
der selbsternannten “ältesten Demokratie” plötzlich die Legalität von
Wahlstimmen angreift, wird es gefährlich.&lt;/p&gt;

&lt;p&gt;Ich habe mich nicht grundlos freiwillig in Wien als Wahlbeisitzer bei der
Stadt gemeldet, denn ich wollte das System verstehen und auch Einblick
“in die Demokratie” erhalten. Das mag vielleicht nicht 1:1 auf die USA
übersetzbar sein, doch demokratische Wahlen laufen so transparent wie nur 
möglich für alle teilnehmenden Parteien ab. Jede kann ihre Beobachter 
entsenden und Stimmen auch ein 4. und 5. mal auszählen, wenn es wo 
Zweifel gibt.&lt;/p&gt;

&lt;p&gt;Und wie man hört, haben auch republikanische Auszähler in den USA 
entgegen der Meinung ihrer Parteivorsitzenden die Legalität der Wahl 
bestätigt. Es gibt daher nur eine Wahrheit und die lautet:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Die Demokratie und das Wahlsystem funktionieren!&lt;br /&gt;
Es gibt keine groß angelegte Manipulation und die Ergebnisse drücken
schlicht den wahren Willen der Bürger aus!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Es ist gefährlich die Grundfesten unserer Gesellschaft mit Zwietracht und
übler Nachrede anzugreifen und Menschen aus puren Machtinteressen gegen 
jeden und alles aufzuhetzen.&lt;br /&gt;
… oder wie es schon in der Bibel hieß:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Wer Wind sät, wird Sturm ernten.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ich bin daher maßlos enttäuscht, dass wir im 21. Jahrhundert in Praktiken
des Mittelalters verfallen und jene mit Dreck bewerfen, die sich “für uns” 
einsetzen. Und das schlimmste für mich ist, dass es wiederum die Technik 
ist, die den Zerstörern nun einen breite Plattform bietet,
ihr übles Werk zu verbreiten.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Ich weiß nicht, wie die Sache am Ende ausgehen wird und hoffe besorgt weiter
auf das Beste.&lt;/p&gt;

&lt;p&gt;Zum Glück erkenne ich in den Massen auch ein paar Anker des Anstandes, 
die sich bemühen, der Gesellschaft durch Rationalität Halt zu bieten.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.dkriesel.com/person&quot;&gt;David Kriesel&lt;/a&gt;, 
“der &lt;a href=&quot;http://www.dkriesel.com/blog/2014/1229_video_meines_vortrags_auf_dem_31c3&quot;&gt;Xerox-Hacker&lt;/a&gt;” 
und Datenanalytiker hat bereits vor einem Jahr seinen Vortrag über Statistik
und Dateninterpretation mit fast prophetischen Worten enden lassen, 
als er die “Empörung im Netz” als großes Problem charakterisierte:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Wenn wir es gemeinsam schaffen, dass wenigstens manche, 
die heute nichts besseres zu tun haben, als sich zu empören, 
im nächsten Jahrzehnt zur engagierten Analyse übergehen 
und dabei auch anerkennen, wenn was rauskommt, 
an das sie vorher nicht gedacht hätten,
dann haben wir gesellschaftlich unglaublich viel gewonnen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;iframe width=&quot;640&quot; height=&quot;360&quot; src=&quot;/blog/redirect.html?https%3A%2F%2Fwww.youtube-nocookie.com%2Fembed%2F0rb9CfOvojk%3Fstart%3D2898&quot; frameborder=&quot;1&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;

&lt;p&gt;Und für diese Einschätzung, bin ich ihm und auch allen anderen positiven
Mitkämpfern wirklich sehr sehr dankbar!&lt;/p&gt;

&lt;p&gt;PS: Man soll mehr auf “das Gute” achten:
Laut den Simpsons gibt es in Amerika keine Wahlmanipulation.
Vielleicht in Ohio, aber nicht in Amerika!&lt;/p&gt;

&lt;iframe width=&quot;640&quot; height=&quot;360&quot; src=&quot;/blog/redirect.html?https%3A%2F%2Fwww.youtube-nocookie.com%2Fembed%2FmcQ-TAoWWgw&quot; frameborder=&quot;1&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
</content>
 </entry>
 
 <entry>
   <title>PinePhone und PostmarketOS</title>
   <link href="https://www.opengate.at/blog/2020/11/pinephone/"/>
   <published>2020-11-01T12:00:00+01:00</published>
   <updated>2020-11-01T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2020/11/pinephone</id>
   <category term="hardware" /><category term="software" />
   <summary type="text">Andere mögen sich funktionierende Smartphones
kaufen und damit glücklich werden.
Ich hingegen kaufe mir Baustellen um darin mein Glück zu finden … bzw. 
es darin suchen zu können.

Das PinePhone ist ein 
OpenSource
Smartphone, das aktuell mit der Alpine Linux 
Abwandlung postmarketOS jetzt 
auch endlich in Europa bestellbar ist.
</summary>
   <content type="html">&lt;p&gt;Andere mögen sich funktionierende &lt;a href=&quot;https://de.wikipedia.org/wiki/Smartphone&quot;&gt;Smartphones&lt;/a&gt;
kaufen und damit glücklich werden.&lt;br /&gt;
Ich hingegen kaufe mir Baustellen um darin mein Glück zu finden … bzw. 
es darin suchen zu können.&lt;/p&gt;

&lt;p&gt;Das &lt;a href=&quot;https://de.wikipedia.org/wiki/PinePhone&quot;&gt;PinePhone&lt;/a&gt; ist ein 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Open_Source&quot;&gt;OpenSource&lt;/a&gt;
Smartphone, das aktuell mit der &lt;a href=&quot;https://de.wikipedia.org/wiki/Alpine_Linux&quot;&gt;Alpine Linux&lt;/a&gt; 
Abwandlung &lt;a href=&quot;https://en.wikipedia.org/wiki/PostmarketOS&quot;&gt;postmarketOS&lt;/a&gt; jetzt 
auch endlich in Europa bestellbar ist.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Wenn mich etwas ganz besonders anpisst, dann sind das Hardware- und 
Softwarehersteller, die ihr Produkt mit einem künstlichen Haltbarkeitsdatum
ausliefern.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_Phone&quot;&gt;Windows Phone&lt;/a&gt;, 
&lt;a href=&quot;https://de.wikipedia.org/wiki/IPhone&quot;&gt;iPhones&lt;/a&gt; und am allerschlimmsten 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Android_(Betriebssystem)&quot;&gt;Android&lt;/a&gt;, hatten nie 
vor, lange zu halten. Spätestens nach 2 Jahren war immer das Ende des 
Supports erreicht und man wurde zum Neukauf gedrängt.&lt;/p&gt;

&lt;p&gt;Dabei war es stets die Software, die das Problem auslöste: Man braucht ein
neues OS Image, im Updates zu erhalten. Ohne Update gibt es keine neuen
&lt;a href=&quot;https://de.wikipedia.org/wiki/Transport_Layer_Security&quot;&gt;SSL/TLS&lt;/a&gt; Zertifikate
und ohne diese kann man nicht mal mehr E-Mails abrufen.&lt;/p&gt;

&lt;p&gt;Ganz anders sieht es in der PC Welt aus, wo ich fast jedes Linux und auch 
fast jedes Windows über viele Jahre hinweg auf die neueste Version upgraden
und im Notfall einfach die neueste Version frisch installieren kann.&lt;/p&gt;

&lt;p&gt;Warum gibt es das nicht auch für Tablets und Smartphones?&lt;br /&gt;
&lt;em&gt;Antwort:&lt;/em&gt; Die Hersteller nutzen proprietäre Treiber und sind die einzigen, 
die ein neues startbares System erstellen können … und genau das bieten 
sie nur begrenzt an.&lt;/p&gt;

&lt;h3 id=&quot;opensource-als-lösung&quot;&gt;OpenSource als Lösung?&lt;/h3&gt;

&lt;p&gt;Ja, wäre Android nicht total in die falsche Richtung abgebogen, dann hätten 
wird schon unser Utopia vor uns. Aber nein, auch dieses Linux-basierte System
ist zur dunklen Seite gewechselt.&lt;/p&gt;

&lt;p&gt;Nun liegt meine Hoffnung auf Plattformen wie dem &lt;a href=&quot;https://de.wikipedia.org/wiki/Raspberry_Pi&quot;&gt;Raspberry PI&lt;/a&gt;
und seinen Nachbauten und …
… auf einem Projekt namens “Pine64”&lt;/p&gt;

&lt;p&gt;Systeme wie:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Pine64, ein &lt;a href=&quot;https://de.wikipedia.org/wiki/Arm-Architektur&quot;&gt;ARM&lt;/a&gt;
System-on-Chip Computer&lt;/li&gt;
  &lt;li&gt;PineBook, ein ARM-basierter Laptop&lt;/li&gt;
  &lt;li&gt;PineTab, ein ARM-basierter Tablet-PC&lt;/li&gt;
  &lt;li&gt;und das PinePhone, ein ARM-basiertes Smartphone&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;zeigen vor, wie man mit einem “echten” Linux moderne Geräte und Smartphones 
ausstatten kann.&lt;/p&gt;

&lt;p&gt;Ich habe mir (inklusive Steuern und Versand) um 200 € ein solches Gerät nun 
gegönnt, nachdem es endlich im Store auch nach Europa lieferbar war.
Ein paar Monate zuvor war dies (warum auch immer) nicht möglich und nur 
in den USA erhältlich.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/pinephone.jpg&quot; alt=&quot;Pinephone postmarketOS&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Ein paar Daten:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Allwinner A64 4 Kerner mit Mali 400 MP2 GPU&lt;/li&gt;
  &lt;li&gt;5.95 Zoll Touch-LCD 1440 x 720 (18:9)&lt;/li&gt;
  &lt;li&gt;2 GB RAM&lt;/li&gt;
  &lt;li&gt;16 GB eMMC für OS und Programme&lt;/li&gt;
  &lt;li&gt;Kamera 5 Megapixel mit LED Flash&lt;/li&gt;
  &lt;li&gt;Selfie-Kamera 2 Megapixel&lt;/li&gt;
  &lt;li&gt;3000 mAh Akku&lt;/li&gt;
  &lt;li&gt;WLAN b/g/n und Bluetooth 4.0&lt;/li&gt;
  &lt;li&gt;MicroSD Karte für weiteren Speicher&lt;/li&gt;
  &lt;li&gt;3 Tasten für ON/OFF, Hinauf und Hinunter&lt;/li&gt;
  &lt;li&gt;Übliche Sensoren + Standard Audioanschluss für Headset&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;erster-anlauf-mit-hürden&quot;&gt;Erster Anlauf mit Hürden&lt;/h3&gt;

&lt;p&gt;Obwohl ich das Teil inzwischen fast liebe, gebe ich zu, dass es alles andere
als markttauglich ist. Zwar läuft das Setup beim ersten Start brav durch, aber
danach sitzt man vor einer Oberfläche mit&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;einer Telefon-App&lt;/li&gt;
  &lt;li&gt;einer Chat/SMS App&lt;/li&gt;
  &lt;li&gt;einer Kontakte-App&lt;/li&gt;
  &lt;li&gt;einem Browser (Firefox)&lt;/li&gt;
  &lt;li&gt;einer Uhr&lt;/li&gt;
  &lt;li&gt;einem Texteditor&lt;/li&gt;
  &lt;li&gt;einem App-Store&lt;/li&gt;
  &lt;li&gt;einer App für Einstellungen&lt;/li&gt;
  &lt;li&gt;und das wichtigste: eine Linux-Terminal-Emulation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Die “Einstellungen” sind eigentlich die beste und funktionabelste Anwendung
auf dem Gerät. Man kann schnell ins WLAN und die SIM-Datendienste 
aktivieren, wie auch einige andere Einstellungen (z.B. Helligkeit) vornehmen.&lt;/p&gt;

&lt;p&gt;Der App-Store kann nur eines, nämlich App-Updates installieren und da findet
man gleich am Anfang einiges. Doch neue Apps gibt es keine. Zwar findet man in
jeder Kategorie einen Eintrag, doch diese tauchen nach der Installation nicht im
Startmenü auf und lassen sich auch aus der Store-App nicht direkt starten.&lt;/p&gt;

&lt;p&gt;Telefonieren geht … aber es fühlt sich recht “retro” an. Der Ton wird unklar
und leicht verstört übertragen bzw. abgespielt. Nicht zu vergleichen mit 
aktuellen Smartphones mit glasklarer Klangqualität.&lt;/p&gt;

&lt;p&gt;Kontakte lassen sich lokal zwar ganz gut anlegen, aber die Verknüpfung mit 
Online-Accounts wie &lt;a href=&quot;https://de.wikipedia.org/wiki/Hotmail&quot;&gt;Hotmail/Outlook&lt;/a&gt; 
oder &lt;a href=&quot;https://de.wikipedia.org/wiki/Gmail&quot;&gt;Gmail&lt;/a&gt; schlagen fehl.&lt;/p&gt;

&lt;p&gt;Der &lt;a href=&quot;https://de.wikipedia.org/wiki/Mozilla_Firefox&quot;&gt;Firefox&lt;/a&gt; ist “OK”,&lt;br /&gt;
aber ist dennoch nicht ganz perfekt auf die Smartphone Bedienung ausgelegt.&lt;/p&gt;

&lt;p&gt;Das Highlight ist aber das Linux &lt;a href=&quot;https://de.wikipedia.org/wiki/Terminal_(Computer)&quot;&gt;Terminal&lt;/a&gt;, 
denn damit kann man alles andere reparieren:&lt;/p&gt;

&lt;h3 id=&quot;apk-eröffnet-möglichkeiten&quot;&gt;APK eröffnet Möglichkeiten&lt;/h3&gt;

&lt;p&gt;Das Alpine Linux Tool &lt;code&gt;APK&lt;/code&gt; (was nichts mit Android APKs zu tun hat) lässt 
einem alles installieren, was im Alpine Linux Repo gespeichert ist. Und 
genau hier liegt das volle Potential.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;sudo apk add pacmanfm&lt;/code&gt;
Installiert einen Dateimanager, womit man das Smartphone OS erforschen kann.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;sudo apk add megapixels&lt;/code&gt;
Installiert eine Kamera-Software um mit dem Smartphone Fotos knipsen zu können.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;sudo apk add eog&lt;/code&gt;&lt;br /&gt;
Installiert einen Image-Viewer mit dem man die zuvor geschossenen Bilder wieder 
ansehen kann&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;sudo apk add xfce4-taskmanager&lt;/code&gt;
Installiert den bekannten Taskmanager um die Prozessressourcen zu betrachten.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Aber auch eine ganze Buildumgebung mit &lt;code&gt;GCC&lt;/code&gt; und &lt;code&gt;CMake&lt;/code&gt; lässt sich nachrüsten.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Nun, eigentlich habe ich mir einen tragbaren Linux-Bastelrechner gekauft.
Denn viele Linux UI Tools sind für Touch-Bedienung und Smartphone Screens
nicht ausgelegt und folglich braucht dieses Gerät noch einiges an
Nacharbeit, bis es alltagstauglich wird.&lt;/p&gt;

&lt;p&gt;Doch genau diese Motivation erreicht man nur, wenn man sich solche Geräte
zulegt und die Community unterstützt. Und genau das habe ich vor.
Einen GATE-Build habe ich schon mal angestoßen, und zwar über 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Secure_Shell&quot;&gt;SSH&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Alleine die Tatsache, dass ich mit Standard-Tools mein Smartphone 
über das Netzwerk administrieren kann, ist ein riesiger Vorteil.&lt;/p&gt;

&lt;p&gt;Nun muss man nur noch einen Weg finden, wie Endbenutzer dieses Gerät
problemlos im Alltag nutzen können&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Visual Studio ohne Installation</title>
   <link href="https://www.opengate.at/blog/2020/10/vs-no-install/"/>
   <published>2020-10-31T12:00:00+01:00</published>
   <updated>2020-10-31T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2020/10/vs-no-install</id>
   <category term="devel" /><category term="software" />
   <summary type="text">Wie kann ich einen alten Compiler
auf einer neuen Windows Plattform ohne Installation zum Laufen bekommen ?

Oder anders gefragt: Wie kann man Visual Studio
Alt bis Uralt (z.B. 2005) in einem Docker-Container zum Arbeiten bewegen?
</summary>
   <content type="html">&lt;p&gt;Wie kann ich einen alten &lt;a href=&quot;https://de.wikipedia.org/wiki/Compiler&quot;&gt;Compiler&lt;/a&gt;
auf einer neuen Windows Plattform ohne Installation zum Laufen bekommen ?&lt;/p&gt;

&lt;p&gt;Oder anders gefragt: Wie kann man &lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_Studio&quot;&gt;Visual Studio&lt;/a&gt;
Alt bis Uralt (z.B. 2005) in einem Docker-Container zum Arbeiten bewegen?
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;msvc-2017-ist-zu-einfach-&quot;&gt;MSVC 2017 ist (zu) einfach …&lt;/h3&gt;

&lt;p&gt;Das Build-Tools Installationsprogramm &lt;code&gt;vs_BuildTools.exe&lt;/code&gt; ist seit Studio 2017
Docker-fähig und deshalb gibt es eine offizielle Installationsprozedur.
Ich füge dann noch &lt;a href=&quot;https://de.wikipedia.org/wiki/Git&quot;&gt;GIT&lt;/a&gt; und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/CMake&quot;&gt;CMake&lt;/a&gt; hinzu, damit man direkt aus der 
Umgebung Code herunterladen und bauen kann.&lt;br /&gt;
Die Programme werden einfach in das Image kopiert und danach werden per 
&lt;a href=&quot;http://docs.microsoft.com/en-us/windows-server/administration/windows-commands/setx&quot;&gt;&lt;code&gt;SETX&lt;/code&gt;&lt;/a&gt;
die Umgebungsvariablen wie &lt;code&gt;PATH&lt;/code&gt; angepasst.&lt;/p&gt;

&lt;p&gt;Mein &lt;code&gt;Dockerfile&lt;/code&gt; sieht dann etwa so aus:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;FROM mcr.microsoft.com/windows/servercore:ltsc2016
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;SHELL [&amp;quot;cmd&amp;quot;, &amp;quot;/S&amp;quot;, &amp;quot;/C&amp;quot;]
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;COPY [&amp;quot;cmake&amp;quot;, &amp;quot;C:/Program Files/cmake&amp;quot;]
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;COPY [&amp;quot;Git&amp;quot;, &amp;quot;C:/Program Files/Git&amp;quot;]
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;RUN SETX PATH &amp;quot;%PATH%;C:\Program Files\Git\cmd;C:\Program Files\cmake\bin&amp;quot;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;RUN MKDIR C:\TEMP
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;ADD vs_BuildTools_2017.exe /TEMP/vs_buildtools.exe
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;RUN C:\TEMP\vs_buildtools.exe --quiet --wait --norestart --nocache \
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;    --installPath C:\BuildTools \
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;    --add Microsoft.VisualStudio.Workload.VCTools \
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;    --add Microsoft.VisualStudio.Component.WinXP \
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;        --add Microsoft.VisualStudio.ComponentGroup.NativeDesktop.WinXP \
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;    --add Microsoft.VisualStudio.Component.Windows81SDK \
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;    --add Microsoft.VisualStudio.Component.Windows10SDK.10580 \
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;    --add Microsoft.VisualStudio.Component.Windows10SDK.14393 \
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt; || IF &amp;quot;%ERRORLEVEL%&amp;quot;==&amp;quot;3010&amp;quot; EXIT 0
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;ENTRYPOINT [&amp;quot;C:\\BuildTools\\Common7\\Tools\\VsDevCmd.bat&amp;quot;, &amp;quot;&amp;amp;&amp;amp;&amp;quot;, `
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;            &amp;quot;powershell.exe&amp;quot;, &amp;quot;-NoLogo&amp;quot;, &amp;quot;-ExecutionPolicy&amp;quot;, &amp;quot;Bypass&amp;quot;]
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Aber mein geschätztes Studio 2005 für die alten &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_NT_4.0&quot;&gt;NT4&lt;/a&gt;
und &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_2000&quot;&gt;Win2K&lt;/a&gt; Builds 
lässt sich so nicht aufsetzen.&lt;/p&gt;

&lt;h3 id=&quot;msvc-2005-per-xcopy-ausrollen&quot;&gt;MSVC 2005 per XCOPY ausrollen&lt;/h3&gt;

&lt;p&gt;Damit man per &lt;code&gt;CMake&lt;/code&gt; einen &lt;code&gt;MSVC 2005&lt;/code&gt; Build durchführen zu können, braucht man
eigentlich nur folgende Zutaten:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;CMake 3.11.4 (oder älter für &lt;code&gt;MSVC 2005&lt;/code&gt;)&lt;br /&gt;
einfach nach &lt;code&gt;C:\Program Files\CMake&lt;/code&gt; kopieren und in den &lt;code&gt;PATH&lt;/code&gt; aufnehmen.&lt;/li&gt;
  &lt;li&gt;dotNet Framework 2.0&lt;br /&gt;
Wird heute per &lt;code&gt;dism&lt;/code&gt; bereitgestellt, und zwar mit:&lt;br /&gt;
&lt;code&gt;dism /online /Enable-Feature /FeatureName:NetFx3ServerFeatures&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;dism /online /Enable-Feature /FeatureName:NetFx3&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Visual Studio 2005 Redistributable (X86 + X64 + Debug)&lt;/li&gt;
  &lt;li&gt;Studio 2005 Kopie aus &lt;code&gt;Program Files (x86)&lt;/code&gt;&lt;br /&gt;
Man installiert am besten eine vollständige MSVC 2005 in eine
virtuelle Maschine und kopiert dann den Ordner 
&lt;code&gt;C:\Program Files (x86)\Microsoft Visual Studio 8&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Umgebungsvariable &lt;code&gt;VS80COMNTOOLS&lt;/code&gt;&lt;br /&gt;
Diese muss auf &lt;code&gt;C:\Program Files (x86)\Microsoft Visual Studio 8\Common7\Tools\&lt;/code&gt;
zeigen, und ganz wichtig ist der Backslash am Ende.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;vcvarsall.bat&lt;/code&gt; muss ausgeführt werden.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Wenn man mit Docker arbeitet muss man sich etwas für das &lt;code&gt;dism&lt;/code&gt; Kommando
überlegen, denn das Image beinhaltet das dotNet-Installationspaket nicht.
Bei meinem Server 2016 musste ich aus der Installations-CD die Datei 
&lt;code&gt;server2016\sources\sxs\microsoft-windows-netfx3-ondemand-package.cab&lt;/code&gt;
ins Image kopieren (z.B. nach &lt;code&gt;c:\windows\temp&lt;/code&gt;) und dort per 
&lt;code&gt;dism /online /Enable-Feature /FeatureName:NetFx3 /All /Source:c:\windows\temp /NoRestart&lt;/code&gt;
integrieren lassen.&lt;/p&gt;

&lt;p&gt;Die Visual Studio 2005 Runtime existiert als zwei Downloads: &lt;code&gt;vcredist_x86.exe&lt;/code&gt;
und &lt;code&gt;vcredist_x64.exe&lt;/code&gt;. Beide lassen sich per Konsolenkommando 
&lt;code&gt;start /wait path\to\vcredist_xYZ.exe /Q&lt;/code&gt; installieren.&lt;/p&gt;

&lt;p&gt;Wäre da nicht CMake, das zum Bauen seiner Test-Pakete Debug-Binaries erzeugt.
Denn die brauchen die Debug-Runtime und die wird offiziell nicht distribuiert
und ist nur Teil einer Visual Studio Installation.&lt;br /&gt;
Es gibt aber einen Ausweg bzw Umweg:&lt;/p&gt;

&lt;p&gt;Man kann einen eigenes [MSI Paket] in einen normal installierten 
Visual Studio 2005 erstellen, das die so genannten “Merge-Module” der 
Debug-Runtime beinhaltet. Ich habe mir also ein Hello-World Konsolenprogramm 
erstellt und einen Installer daran gehängt, der die &lt;code&gt;VC80_Debug*&lt;/code&gt; MSM Dateien
in &lt;code&gt;C:\Program Files (x86)\Common Files\Merge Modules&lt;/code&gt; als Merge-Module 
hinzugefügt bekommen hat.&lt;/p&gt;

&lt;p&gt;Und das entstandene MSI-Paket kann dann wieder einfach per
&lt;code&gt;start /wait msiexec /i path/to/debug-rt-inst.msi&lt;/code&gt; installiert werden und 
schon liegen die benötigten Debug-Dateien in &lt;code&gt;C:\Windows\WinSXS&lt;/code&gt;, wo man 
sie sonst nur schwer in korrekter Form hinbekommt.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Nun, die Prozedur ist jetzt mal ein experimenteller Ansatz und ich kann so 
auf jeden Fall per &lt;code&gt;CMake&lt;/code&gt; erstellte 
&lt;a href=&quot;http://docs.microsoft.com/en-us/cpp/build/reference/nmake-reference?view=msvc-160&quot;&gt;NMAKE&lt;/a&gt;
MSVC 2005 Projekte sogar im Docker auf &lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_Server_2016&quot;&gt;Server 2016&lt;/a&gt;
bauen lassen.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;MSBUILD&lt;/code&gt; erweist sich im Docker Container immer noch bockig und verlangt
eine Neuinstallation von Visual Studio. Vermutlich fehlen Dateien oder
Registry-Hacks, aber ich bin vorerst auch mit &lt;code&gt;NMAKE&lt;/code&gt; Builds zufrieden.&lt;/p&gt;

&lt;p&gt;In der Praxis werde ich weiter meine vollständige Studio-Installation in 
einer &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_XP&quot;&gt;WinXP&lt;/a&gt; bzw. 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_Server_2003&quot;&gt;Server2003&lt;/a&gt; VM 
nutzen, aber die Möglichkeit, dass die Installation durch ein “Fast-XCOPY”
Deployment ersetzt werden kann, gefällt mir.&lt;/p&gt;

&lt;p&gt;Mal sehen, ob sich das noch ausbauen lässt …&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Wie man Daten (nicht) rettet</title>
   <link href="https://www.opengate.at/blog/2020/10/restore-apis/"/>
   <published>2020-10-25T12:00:00+01:00</published>
   <updated>2020-10-25T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2020/10/restore-apis</id>
   <category term="software" />
   <summary type="text">
  Bei aller verschmähter Lieb! Beim höllischen Element!
Ich wollt, ich wüsst was ärgers, dass ichs fluchen könnt!


Das denkt man sich, wenn man vor einem Jahr eine “Restore” Software 
gekauft hat, die man nun plötzlich braucht und dieses elende Mist-Teil 
ohne eine weitere Jahreslizenz den Dienst verweigert!
</summary>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;Bei aller verschmähter Lieb! Beim höllischen Element!&lt;br /&gt;
Ich wollt, ich wüsst was ärgers, dass ichs fluchen könnt!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Das denkt man sich, wenn man vor einem Jahr eine “Restore” Software 
gekauft hat, die man nun plötzlich braucht und dieses elende Mist-Teil 
ohne eine weitere Jahreslizenz den Dienst verweigert!
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Was waren das für herrlich korrekte Zeiten, als man eine Software gekauft und 
bezahlt hatte und dann viele Jahre seine Freude daran hatte …&lt;/p&gt;

&lt;p&gt;Heute denkt sich jeder stinkende Furz, er wäre “Teil der Cloud” und könnte
damit nur durch Gold aufgewogen werden.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Boah! Bin ich angepisst!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Vor etwas mehr als einem Jahr hatte ich mir ein 
&lt;a href=&quot;/blog/2019/08/data-loss-2/&quot;&gt;Restore-Tool gekauft&lt;/a&gt; um eine 
verlorene Partitionstabelle wiederherzustellen, was ja auch gut funktioniert
hat.&lt;br /&gt;
Ich war auch erfreut zu sehen, dass zusätzliche Boot Module mit 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_PE&quot;&gt;Windows PE&lt;/a&gt; beigelegt 
waren um auch ohne ein funktionierendes Windows eine 
Wiederherstellung einzuleiten.&lt;/p&gt;

&lt;p&gt;Neulich fragt mich ein Kollege, ob ich ihn bei der Datenrettung eines Laptops
unterstützen kann.&lt;br /&gt;
Und ich meinte gönnerhaft:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ist ja gar kein Problem, ich habe ja ohnehin ein Tool gekauft, dass ich
Gott sei Danke nicht mehr brauche.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Gesagt, getan. Wir trafen uns und ich brachte die Software am USB Stick 
mit. Der Boot klappte, man konnte in der UI die Laufwerke auswählen, doch 
beim Starten des Wiederherstellungs-Scans, kam die Meldung, dass man eine
weitere Lizenz kaufen müsse. Die bestehende sei nicht mehr gültig und müsse
erneuert werden.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;W-T-F !!!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Am interessantesten war natürlich die Prozedur, wo in der PE-Session eine 
elend lange Base64-Sequenz am Bildschirm stand, die man in ein Formular
im Browser auf einem anderen funktionierenden PC oder Laptop eintippen
sollte.&lt;/p&gt;

&lt;h3 id=&quot;nie-wieder-solche-tools-kaufen&quot;&gt;Nie wieder solche Tools kaufen!!!&lt;/h3&gt;

&lt;p&gt;Ich könnte jetzt noch viele Flüche, die ich in der Zeit erdachte, aufsagen, 
aber am Ende war eine Wiederherstellung der Daten nicht möglich und wir 
einigten uns auf eine Neuinstallation, damit man zumindest wieder 
weiterarbeiten konnte.&lt;/p&gt;

&lt;p&gt;Doch mit diesem bescheuerten Lizenz-Zusatz, steht meine Meinung fest:
“MiniTool Partition Wizard” und viele andere Softwareprodukte dieser
Sparte sind wegen ihrer Einschränkungspolitik meiner Meinung nach 
einfach nur Mist.&lt;br /&gt;
Wenn mich der Start einer Software pro Wiederherstellung und Maschine 
jedes mal 100 Euro und mehr kostet, oder ohne aktive Internetverbindung
grundsätzlich Funktionalität verweigert wird, dann sind diese Tools
für mich wertlos.&lt;/p&gt;

&lt;p&gt;Vor 15 Jahren und mehr kosteten solche Tools nämlich auch so viel, waren 
damals aber uneingeschränkt nutzbar.&lt;/p&gt;

&lt;p&gt;Schließlich sollen sie den Verlustwert von Dokumenten aufwiegen. Aber wenn 
sie wesentlich mehr als eine Neuinstallation kosten und dann am Ende nicht 
mal Daten zur Wiederherstellung finden, ist der Kauf reine Geldverschwendung.
Und leider kommt diese Erkenntnis immer erst im Nachhinein.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Meine alltäglichen Dokumente liegen in der Cloud bzw. am gebackupten Server 
zu Hause.&lt;br /&gt;
Und das kann ich nur weiterempfehlen.&lt;/p&gt;

&lt;p&gt;Von unnötig teuren Tools zur Wiederherstellung von Daten kann ich
hingegen nur abraten.
Man stelle sich mal vor, das Reserverad im Auto würde jährlich eine neueste
Online-Lizenz brauchen, oder es lässt sich nicht mehr montieren! 
Das wäre absolut undenkbar … doch in der Softwarewelt spielt man solche
Spiele mit verzweifelten Anwendern.&lt;/p&gt;

&lt;p&gt;Und inzwischen habe ich eines gelernt:&lt;br /&gt;
&lt;em&gt;Windows stellt seine &lt;code&gt;NTFS&lt;/code&gt; Wiederherstellung gratis zur Verfügung.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In der Bibliothek &lt;code&gt;fmapi.dll&lt;/code&gt; liegen Funktionen wie:
&lt;code&gt;CreateFileRestoreContext&lt;/code&gt;, &lt;code&gt;CloseFileRestoreContext&lt;/code&gt;, &lt;code&gt;RestoreFile&lt;/code&gt;, 
&lt;code&gt;ScanRestorableFiles&lt;/code&gt; und &lt;code&gt;SupplyDecryptionInfo&lt;/code&gt;.&lt;br /&gt;
Das heißt also, eine “einfache” Wiederherstellung gelöschter Daten ist quasi
gratis möglich. Zugegeben, da ist keine Sektor-für-Sektor Scan dabei, doch 
ein eben solcher dürfte (wie meine neueste Erfahrung zeigt) ohnehin nicht auf
SSDs funktionieren.&lt;/p&gt;

&lt;p&gt;Da kriegt man fast Lust ein “besseres” Tool kostenlos auf den Markt zu bringen,
das den Geldhaien das Wasser abgräbt.&lt;br /&gt;
Solche Tools, die die obige API nutzen, gibt es bereits … nur leider haben 
sie nicht die nötig Präsenz im Netz.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Video Capture APIs</title>
   <link href="https://www.opengate.at/blog/2020/10/video-apis/"/>
   <published>2020-10-24T13:00:00+02:00</published>
   <updated>2020-10-24T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2020/10/video-apis</id>
   <category term="devel" /><category term="projects" />
   <summary type="text">Video for Windows VfW, 
Direct-Show dshow und 
Video for Linux v4l - 
das sind die drei Schnittstellen, mit denen ich über die Jahre hinweg immer 
wieder mal Webcam Bilder mitgeschnitten habe.

Nun wird es also mal Zeit diese drei zu dokumentieren und das Modul 
gate/io/videosources.h hat diese Aufgabe nun übernommen.
</summary>
   <content type="html">&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Video_for_Windows&quot;&gt;Video for Windows &lt;code&gt;VfW&lt;/code&gt;&lt;/a&gt;, 
&lt;a href=&quot;https://en.wikipedia.org/wiki/DirectShow&quot;&gt;Direct-Show &lt;code&gt;dshow&lt;/code&gt;&lt;/a&gt; und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Video4Linux&quot;&gt;Video for Linux &lt;code&gt;v4l&lt;/code&gt;&lt;/a&gt; - 
das sind die drei Schnittstellen, mit denen ich über die Jahre hinweg immer 
wieder mal Webcam Bilder mitgeschnitten habe.&lt;/p&gt;

&lt;p&gt;Nun wird es also mal Zeit diese drei zu dokumentieren und das Modul 
&lt;code&gt;gate/io/videosources.h&lt;/code&gt; hat diese Aufgabe nun übernommen.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;video-for-windows&quot;&gt;Video for Windows&lt;/h3&gt;

&lt;p&gt;Diese älteste Schnittstelle von &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows&quot;&gt;Windows&lt;/a&gt;
stammt noch aus den &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_3.1&quot;&gt;Windows 3.x&lt;/a&gt;
Tagen und ist offiziell schon seit Jahrzehnten tot. Und dennoch wurde der 
Sourcecode bis zur aktuellen Windows 10 Release nicht entfernt, womit das alte
Teil in vielen Fällen immer noch brav arbeitet.&lt;br /&gt;
Man erzeugt ein spezielles Fenster und den Rest erledigt man über Nachrichten
um eine Stream-Aufnahme zu starten oder zu stoppen.
Die Bilder trudeln dann in zuvor registrierten Callback-Funktionen herein.
Alle Funktionen müssen in einem einzigen Thread ausgeführt werden, in dem eine
Fensternachrichtenschleife läuft:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;http://docs.microsoft.com/en-us/windows/win32/api/vfw/nf-vfw-capgetdriverdescriptionw&quot;&gt;capGetDriverDescription&lt;/a&gt; 
nutzt man um per hochzählenden Index die verfügbaren Treiber auflisten zu 
können.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://docs.microsoft.com/en-us/windows/win32/api/vfw/nf-vfw-capcreatecapturewindoww&quot;&gt;capCreateCaptureWindow&lt;/a&gt; 
erzeugt ein Fenster, das Nachrichten vom Video-Treiber empfängt bzw. mit ihm
kommuniziert.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://docs.microsoft.com/en-us/windows/win32/multimedia/wm-cap-driver-connect&quot;&gt;WM_CAP_DRIVER_CONNECT&lt;/a&gt;
verbindet das Fenster mit einem Video Treiber.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://docs.microsoft.com/en-us/windows/win32/multimedia/wm-cap-set-callback-frame&quot;&gt;WM_CAP_SET_CALLBACK_*&lt;/a&gt;
setzt Callback Funktionen für Fehler, Frames und Audio Samples, wo man 
Daten vom Treiber zugesendet bekommt.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://docs.microsoft.com/en-us/windows/win32/multimedia/wm-cap-get-sequence-setup&quot;&gt;WM_CAP_GET_SEQUENCE_SETUP&lt;/a&gt;
und &lt;a href=&quot;http://docs.microsoft.com/en-us/windows/win32/multimedia/wm-cap-set-sequence-setup&quot;&gt;WM_CAP_SET_SEQUENCE_SETUP&lt;/a&gt;
lesen Einstellungen aus und legen sie für eine Videositzung fest.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://docs.microsoft.com/en-us/windows/win32/multimedia/wm-cap-sequence-nofile&quot;&gt;WM_CAP_SEQUENCE_NOFILE&lt;/a&gt;
startet eine Videoaufnahme, die nur Callbacks für jedes Frame aufruft.&lt;/li&gt;
  &lt;li&gt;Die &lt;a href=&quot;http://docs.microsoft.com/en-us/windows/win32/multimedia/drawdib&quot;&gt;DrawDib*&lt;/a&gt; 
Funktionen sollten genutzt werden um die nativ kodierten Framedaten auf 
typischen Windows Bitmaps zu zeichnen. Vor dort aus kann man die 
Rastergrafiken ganz einfach weiterverarbeiten.
Nutzt man diese Funktionen nicht, muss man sich mit den Pixeldatenformaten
beschäftigen, die direkt vom Video-Treiber stammen (z.B. 
&lt;a href=&quot;https://de.wikipedia.org/wiki/YUV-Farbmodell&quot;&gt;YUV2&lt;/a&gt; usw.)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://docs.microsoft.com/en-us/windows/win32/multimedia/wm-cap-driver-disconnect&quot;&gt;WM_CAP_DRIVER_DISCONNECT&lt;/a&gt;
schließt die Verbindung des Fensters zum Video-Treiber.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Die meisten Window-Messages haben auch Funktions-Makros in den Headern, die
alle mit &lt;code&gt;cap&lt;/code&gt; starten.&lt;/p&gt;

&lt;h3 id=&quot;direct-show&quot;&gt;Direct-Show&lt;/h3&gt;

&lt;p&gt;Der Nachfolger von &lt;code&gt;VfW&lt;/code&gt; ist vollständig von der UI unabhängig und setzt auf 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Component_Object_Model&quot;&gt;COM&lt;/a&gt; auf. Man hat die 
Idee einer “Verarbeitungskette” aufkommen lassen, in der &lt;em&gt;Sample-Quellen&lt;/em&gt; 
ihre Daten an eine Reihe von &lt;em&gt;Filtern&lt;/em&gt; weitergeben. Die Filter können die 
Daten manipulieren und wieder weiterreichen, oder aber auch irgend wo 
ausgeben.&lt;br /&gt;
Eine Webcam ist also eine solche Quelle und diese wird entweder mit einem
Fenster-Renderer verknüpft, der die Bilder auf den Schirm malt, oder die
Daten werden abgefangen und z.B. per Netzwerk weggeschickt.&lt;/p&gt;

&lt;p&gt;Die APIs hierfür sehen so aus:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Man &lt;a href=&quot;http://docs.microsoft.com/en-us/windows/win32/directshow/using-the-system-device-enumerator&quot;&gt;listet Geräte&lt;/a&gt;
über die Klasse &lt;code&gt;CLSID_SystemDeviceEnum&lt;/code&gt; auf und sucht dort nach 
&lt;code&gt;CLSID_VideoInputDeviceCategory&lt;/code&gt; Einträgen&lt;/li&gt;
  &lt;li&gt;Mit der &lt;a href=&quot;http://docs.microsoft.com/en-us/windows/win32/api/objidl/nn-objidl-imoniker&quot;&gt;IMoniker&lt;/a&gt; 
Schnittstelle kann man sich zum &lt;a href=&quot;http://docs.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/platform-apis/aa768196(v=vs.85)&quot;&gt;IPropertyBag&lt;/a&gt;
verbinden um dort den Gerätepfad und den Namen eines Videogeräts auszulesen.&lt;/li&gt;
  &lt;li&gt;Hat man das gewünschte Gerät gefunden, kann man sich per &lt;code&gt;BindToObject&lt;/code&gt; zur 
Schnittstelle &lt;a href=&quot;http://docs.microsoft.com/en-us/windows/win32/api/strmif/nn-strmif-ibasefilter&quot;&gt;IBaseFilter&lt;/a&gt; 
verbinden, die dann als Quelle für Videodaten fungieren wird.&lt;/li&gt;
  &lt;li&gt;Man erzeugt eine Instanz der Klasse &lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/strmif/nn-strmif-ifiltergraph&quot;&gt;FilterGraph&lt;/a&gt;, 
welches das &lt;a href=&quot;http://docs.microsoft.com/en-us/windows/win32/api/strmif/nn-strmif-igraphbuilder&quot;&gt;IGraphBuilder&lt;/a&gt;
Interface bereitstellt.&lt;/li&gt;
  &lt;li&gt;An &lt;code&gt;IGraphbuilder&lt;/code&gt; kann man nun per &lt;code&gt;AddFilter&lt;/code&gt; den &lt;code&gt;IBaseFilter&lt;/code&gt; der 
Quelle anfügen.&lt;/li&gt;
  &lt;li&gt;Nun erzeugt man eine Instanz von &lt;code&gt;CLSID_SampleGrabber&lt;/code&gt;, der Videoframes 
empfangen und für uns exportieren soll.&lt;br /&gt;
Alternativ kann man hier auch einen eigenen Filter implementieren, der
ebenso empfangene Daten zu uns weiterleitet.&lt;/li&gt;
  &lt;li&gt;Der &lt;code&gt;SampleGrabber&lt;/code&gt; (oder eine Alternative) wird ebenso dem IGraphBuilder
angefügt.&lt;/li&gt;
  &lt;li&gt;Jeder &lt;code&gt;IBaseFilter&lt;/code&gt; beinhaltet eine Sammlung von 
&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/strmif/nn-strmif-ipin&quot;&gt;IPin&lt;/a&gt; 
Instanzen, die als Input oder Output definiert sind und mit diversen 
Eigenschaften versehen sind.&lt;/li&gt;
  &lt;li&gt;Der Output &lt;code&gt;IPin&lt;/code&gt; des Quell-IBaseFilters lässt alle Formate auflisten, die
die Quelle unterstützt.&lt;/li&gt;
  &lt;li&gt;Am &lt;code&gt;SampleGrabber&lt;/code&gt; kann man das gewünschte Zielformat angeben und eine 
Callback Funktion angeben, die bei jedem empfangenen (und konvertierten)
Frame aufgerufen wird.&lt;/li&gt;
  &lt;li&gt;Nun wird am Output &lt;code&gt;IPin&lt;/code&gt; der Quelle das gewünschte Format gesetzt und 
dieser dann mit dem Input &lt;code&gt;IPin&lt;/code&gt; des SampleGrabbers über 
&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/strmif/nf-strmif-igraphbuilder-connect&quot;&gt;IGraphBuilder-&amp;gt;Connect&lt;/a&gt;
verbunden.&lt;/li&gt;
  &lt;li&gt;Über das &lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/control/nn-control-imediacontrol&quot;&gt;IMediaControl&lt;/a&gt; 
Interface der &lt;code&gt;FilterGraph&lt;/code&gt; Instanz kann man nun per &lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/control/nf-control-imediacontrol-run&quot;&gt;&lt;code&gt;Run&lt;/code&gt;&lt;/a&gt;
die Aufnahme der Videodaten starten.&lt;/li&gt;
  &lt;li&gt;Die empfangenen Daten in der Callbackfunktion sollten nur in einen anderen
Puffer kopiert werden. Da diese Routine im Kontext des Treibers laufen kann,
sind nur wenige APIs erlaubt von hier aus aufzurufen. Nach dem Kopieren
kann man per &lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-setevent&quot;&gt;SetEvent()&lt;/a&gt;
einen anderen Thread benachrichtigen, der die Daten weiterverarbeitet.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/control/nf-control-imediacontrol-stop&quot;&gt;IMediaControl::Stop()&lt;/a&gt;
beendet den Aufnahmestream.&lt;/li&gt;
  &lt;li&gt;Am Ende werden alle Filter aus dem &lt;code&gt;IGraphBuilder&lt;/code&gt; per &lt;code&gt;RemoveFilter()&lt;/code&gt; entfernt
und die Objekte danach freigegeben.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;video-4-linux&quot;&gt;Video 4 Linux&lt;/h3&gt;

&lt;p&gt;Obwohl es an &lt;code&gt;VfW&lt;/code&gt; erinnert hat diese &lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt;
Video-Schnittstelle überhaupt nichts mit der antiken Windows-Implementierung 
gemeinsam. Es handelt sich dabei lediglich um ein Set von C Strukturen und 
&lt;a href=&quot;http://man7.org/linux/man-pages/man2/ioctl.2.html&quot;&gt;IOCTL&lt;/a&gt; Codes, die man an 
ein Videogerät schicken kann, welches dann über standardisierte Datenpuffer 
Bilddaten zurückgibt.&lt;br /&gt;
Wenn man “einfach” nur ein paar Bilder speichern möchte, ist diese 
Schnittstelle die effizienteste von den dreien meiner Meinung nach.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Man öffnet ein Videogerät wie eine Datei (meist: &lt;code&gt;/dev/video*&lt;/code&gt;) und nutzt
&lt;a href=&quot;http://www.kernel.org/doc/html/v4.15/media/uapi/v4l/vidioc-querycap.html&quot;&gt;VIDIOC_QUERYCAP&lt;/a&gt;
um den richtigen Gerätenamen herauszufinden.&lt;/li&gt;
  &lt;li&gt;Über die IOCTLs &lt;a href=&quot;http://www.kernel.org/doc/html/v4.14/media/uapi/v4l/vidioc-g-fmt.html&quot;&gt;VIDIOC_G_FMT&lt;/a&gt;
und &lt;a href=&quot;http://www.kernel.org/doc/html/v4.15/media/uapi/v4l/vidioc-enum-fmt.html&quot;&gt;VIDIOC_ENUM_FMT&lt;/a&gt;
lassen sich Details über unterstützte Formate und Auflösungen herausfinden.&lt;/li&gt;
  &lt;li&gt;Per capabilities von &lt;code&gt;VIDIOC_QUERYCAP&lt;/code&gt; lässt sich feststellen, welche 
Aufnahmemöglichkeiten der Treiber bietet.&lt;/li&gt;
  &lt;li&gt;Wird &lt;a href=&quot;http://www.kernel.org/doc/html/v4.9/media/uapi/v4l/mmap.html&quot;&gt;V4L2_CAP_STREAMING&lt;/a&gt; 
unterstützt, sollten ein paar &lt;code&gt;V4L2_MEMORY_MMAP&lt;/code&gt; Puffer mit &lt;a href=&quot;http://man7.org/linux/man-pages/man2/mmap.2.html&quot;&gt;mmap&lt;/a&gt;
angelegt werden und per &lt;a href=&quot;http://www.kernel.org/doc/html/v4.14/media/uapi/v4l/vidioc-reqbufs.html&quot;&gt;VIDIOC_REQBUFS&lt;/a&gt;, 
&lt;a href=&quot;http://www.kernel.org/doc/html/v4.9/media/uapi/v4l/vidioc-querybuf.html&quot;&gt;VIDIOC_QUERYBUF&lt;/a&gt;
und &lt;a href=&quot;http://www.kernel.org/doc/html/v4.14/media/uapi/v4l/vidioc-qbuf.html&quot;&gt;VIDIOC_QBUF&lt;/a&gt;
in der Queue des Gerätes registriert werden.&lt;/li&gt;
  &lt;li&gt;Schlägt die mmap-Streaming-Registrierung fehl, kann man normale 
&lt;a href=&quot;https://man7.org/linux/man-pages/man3/free.3.html&quot;&gt;malloc()&lt;/a&gt; Puffer als 
&lt;a href=&quot;https://www.kernel.org/doc/html/v4.9/media/uapi/v4l/userp.html&quot;&gt;V4L2_MEMORY_USERPTR&lt;/a&gt; 
per &lt;code&gt;VIDIOC_QBUF&lt;/code&gt; registrieren.&lt;/li&gt;
  &lt;li&gt;Per &lt;a href=&quot;https://www.kernel.org/doc/html/v4.9/media/uapi/v4l/vidioc-streamon.html&quot;&gt;VIDIOC_STREAMON&lt;/a&gt; 
wird der MMAP oder USERPTR Stream aktiviert.&lt;/li&gt;
  &lt;li&gt;Ist Streaming generell nicht verfügbar, kann man noch auf 
&lt;a href=&quot;http://www.kernel.org/doc/html/latest/userspace-api/media/v4l/rw.html&quot;&gt;V4L2_CAP_READWRITE&lt;/a&gt;
prüfen. Hierbei wird dann nicht gepuffert sondern per “read” ein Frame
direkt in einen lokalen Puffer kopiert.&lt;br /&gt;
Diese Variante sollte immer funktionieren, ist aber am ineffizientesten.&lt;/li&gt;
  &lt;li&gt;In einer Schleife kann man nun per &lt;a href=&quot;http://man7.org/linux/man-pages/man2/select.2.html&quot;&gt;select()&lt;/a&gt; 
auf das geöffnete Videogerät warten, bis es Daten bereit hält.&lt;/li&gt;
  &lt;li&gt;Im Fall von Streaming nutzt man &lt;a href=&quot;http://01.org/linuxgraphics/gfx-docs/drm/media/uapi/v4l/vidioc-qbuf.html&quot;&gt;VIDIOC_DQBUF&lt;/a&gt;
um einen vollen Puffer aus dem Gerät herauszulösen. Dann bearbeitet man die 
Daten und fügt den Puffer per &lt;code&gt;VIDIOC_QBUF&lt;/code&gt; wieder dem Gerät hinzu, damit 
dieser neu befüllt werden kann.&lt;/li&gt;
  &lt;li&gt;Ohne Streaming wird einfach &lt;a href=&quot;http://man7.org/linux/man-pages/man2/read.2.html&quot;&gt;read()&lt;/a&gt;
aufgerufen um das aktuelle Frame zu empfangen.&lt;/li&gt;
  &lt;li&gt;Um die native kodierten Videodaten besser bearbeiten zu können, empfiehlt
sich der Einsatz der Bibliothek &lt;code&gt;v4l_convert&lt;/code&gt;. Sie kann eine Vielzahl an
Bildformaten nach RGB oder andere Standards übersetzen.&lt;/li&gt;
  &lt;li&gt;Beenden kann man das Streaming per &lt;code&gt;VIDIOC_STREAMOFF&lt;/code&gt;. 
Danach kann der Gerätedatei-Deskriptor mit &lt;a href=&quot;http://man7.org/linux/man-pages/man2/close.2.html&quot;&gt;close()&lt;/a&gt;
freigegeben werden.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Das größte Manko der Windows Schnittstellen ist, dass in den Callbacks nur
einige wenige WinAPIs benutzt werden dürfen. Und das sind Mutexe und 
Speicherallokierungen. Man darf also nur die Daten wo anders hinkopieren,
weil der Callback mehr oder weniger direkt aus dem Treiber heraus aufgerufen
wird.&lt;/p&gt;

&lt;p&gt;Das macht die Programmierung unter Windows mühsam und fehleranfällig.
Mit der &lt;a href=&quot;https://en.wikipedia.org/wiki/Media_Foundation&quot;&gt;Media Foundation&lt;/a&gt; 
seit Windows Vista gibt es eine neuere Schnittstelle und die 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_Runtime&quot;&gt;Windows Runtime&lt;/a&gt;
ist offenbar nochmals ein bisschen mehr “geil” laut MSDN, aber bisher 
bin ich bei meinen alten Bekannten geblieben.&lt;/p&gt;

&lt;p&gt;Linux geht hier seinen üblichen Weg und baut anfangs nur auf klassische
&lt;code&gt;open()&lt;/code&gt; - &lt;code&gt;ioctl()&lt;/code&gt; - &lt;code&gt;read()&lt;/code&gt; - &lt;code&gt;write()&lt;/code&gt; - &lt;code&gt;close()&lt;/code&gt; Abfolgen auf. Doch 
wenn man alle Farbkodierungen unterstützen möchte, empfiehlt sich der Einsatz 
von Hilfsroutinen.&lt;/p&gt;

&lt;p&gt;Wenn man von diversen aufwendigeren Workarounds aber mal absieht, so kann man
hier recht einfach den “kleinsten gemeinsamen Nenner” zwischen den APIs finden
und einen einheitlichen Wrapper darüberlegen.&lt;br /&gt;
… und genau das versucht ja das GATE Projekt zu erreichen.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Das Windows-Thread-Context Problem</title>
   <link href="https://www.opengate.at/blog/2020/10/com-threads/"/>
   <published>2020-10-18T13:00:00+02:00</published>
   <updated>2020-10-18T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2020/10/com-threads</id>
   <category term="devel" />
   <summary type="text">Die wenigsten C 
APIs sind von sich aus vollständig 
thread-sicher (thread-safe). 
Aber die meisten sind thread-verträglich (thread-aware).

So lange man ein Objekt oder eine Struktur nie von mehreren Threads 
gleichzeitig parallel benutzt, passiert nichts Schlimmes.

Windows und seine COM-Architektur
machen es einem aber etwas schwerer…
</summary>
   <content type="html">&lt;p&gt;Die wenigsten &lt;a href=&quot;https://de.wikipedia.org/wiki/C_(Programmiersprache)&quot;&gt;C&lt;/a&gt; 
APIs sind von sich aus vollständig 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Threadsicherheit&quot;&gt;thread-sicher (thread-safe)&lt;/a&gt;. 
Aber die meisten sind thread-verträglich (thread-aware).&lt;/p&gt;

&lt;p&gt;So lange man ein Objekt oder eine Struktur nie von mehreren Threads 
gleichzeitig parallel benutzt, passiert nichts Schlimmes.&lt;/p&gt;

&lt;p&gt;Windows und seine &lt;a href=&quot;https://de.wikipedia.org/wiki/Component_Object_Model&quot;&gt;COM-Architektur&lt;/a&gt;
machen es einem aber etwas schwerer…
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Eigentlich bin ich ja ein Windows und vor allem auch ein COM Fanboy. Das 
Component Object Model ist ein guter Ansatz, um sprachübergreifend Daten und
Funktionen auszutauschen und eben auch deshalb basieren viele 
GATE C Objekte auf einem ähnlichen Modell.&lt;/p&gt;

&lt;p&gt;Doch die meisten Windows COM Klassen erwarten, dass sie in einem COM-Apartment
erzeugt werden und auch nur aus diesem einen benutzt werden.&lt;/p&gt;

&lt;p&gt;Natürlich gibt es auch Klassenfamilien wie z.B. &lt;a href=&quot;https://de.wikipedia.org/wiki/DirectX&quot;&gt;DirectX&lt;/a&gt;
die vollkommen “free-threaded” implementiert sind, aber die meisten Codes 
erfordern eben eine Bindung an einen Thread, für den die COM-Runtime 
initialisiert wurde.&lt;/p&gt;

&lt;p&gt;Genau das ist aber in einem Bibliotheken Framework wie beim GATE Projekt ein
ungutes Problem. Denn, dass einige Komponenten den “Aufbau des Threads” 
verändern müssen um überhaupt funktionieren zu können, ist bzw. soll dem 
Aufrufer nicht bekannt sein.&lt;br /&gt;
Hinzu kommt noch, dass eine COM-Initialisierung keine “billige Operation” ist.
Es kann schon mal etwas Dauern, bis ein Thread für COM vorbereitet wurde.&lt;/p&gt;

&lt;p&gt;Man kann es sich daher auch nicht einfach machen und beim Aufruf einer
Funktion mal schnell im Hintergrund COM initialisieren und vor dem &lt;code&gt;return&lt;/code&gt;
COM wieder zurücksetzen. Das würde erstens viel zu lange dauern und zweitens
würden initialisierte COM Objekte und Pointer plötzlich unbrauchbar werden.&lt;/p&gt;

&lt;p&gt;Alternativ könnte man COM über alles darüberlegen. Also jeder neue Thread muss
ein COM-Thread werden, damit alles darin arbeiten kann. Doch dann ergibt sich
das Mehrere-Bibliotheken-Problem: Was ist, wenn wir fremden Code ausführen, 
der im Hintergrund eigene Threads hochzieht, die nicht an COM gebunden sind,
von dort aus Aufrufe in unseren Code stattfinden, wo COM-Kontexte erwartet 
werden?&lt;/p&gt;

&lt;h3 id=&quot;queue-als-lösung&quot;&gt;Queue als Lösung&lt;/h3&gt;

&lt;p&gt;Eigentlich habe ich keine “schöne” Lösung für dieses Problem, doch ein 
möglicher Workaround ist es, den COM-spezifischen Code zu kapseln und immer
in einem eigenen Thread auszuführen. Dieser spezielle Thread ist als Queue
implementiert, die Ausführungsaufträge (z.B. Funktionszeiger + Parameter)
auslesen und durchführen kann.&lt;/p&gt;

&lt;p&gt;Erzeugt man also eine Objektinstanz, wird im Hintergrund ein paralleler
COM-Thread hochgefahren. Ruft man nun eine Objekt-Methode über eine 
Wrapperfunktion auf, wandelt diese den Aufruf in einen Queue-Auftrag um und 
übergibt ihn der COM-Ausführungsschicht und wartet dann so lange, bis die 
Queue die Fertigstellung der Bearbeitung zurückmeldet.&lt;/p&gt;

&lt;p&gt;Der Aufrufer der Objektmethode merkt also gar nicht, dass seine Anforderung
umgeleitet und in einem ganz anderen Thread-Kontext bearbeitet wurde.
Ebenso erhält der Aufrufer keine nativen COM-Objekt-Pointer zurück sondern
Handles oder andere Kapselungsformen.&lt;/p&gt;

&lt;h3 id=&quot;com-queue-im-gate-framework&quot;&gt;COM Queue im GATE Framework&lt;/h3&gt;

&lt;p&gt;Inzwischen habe ich schon ein paar Routinen mit Hilfe von COM Klasse
implementiert. Doch nun ist es an der Zeit diese “ordentlich” zu abstrahieren
und Kontext-sicher zu gestalten.&lt;br /&gt;
COM erhält dafür im Framework eine eigene Plattformerweiterung, wo nur in der
Windows Implementierung entsprechende Hilfsfunktionen und Objekte 
eingearbeitet sind.&lt;/p&gt;

&lt;p&gt;Es handelt sich hierbei zwar um öffentliche Funktionen doch deren Einsatz ist 
nur als privates Implementierungsdetail vorgesehen. Es darf also keine Apps 
geben die, explizit COM nutzen, aber die Implementierung von Unterkomponenten
dürfen sehr wohl auf diese Features frei zugreifen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Es ist schon witzig. Ich kritisiere gerne &lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt;
und den &lt;a href=&quot;https://de.wikipedia.org/wiki/Portable_Operating_System_Interface&quot;&gt;POSIX&lt;/a&gt; 
Standard, weil viel zu oft nicht auf Threads eingegangen wird und Funktionen 
in globale Variablen schreiben, die multithreading effektiv verhindern.&lt;/p&gt;

&lt;p&gt;Doch Windows als Multithreading-Umgebung hat es wieder durch Einschränkungen
und spezielle Initialisierungen extrem erschwert, dass man flüssig mit
Threads arbeiten kann.&lt;/p&gt;

&lt;p&gt;Und somit leiden viele moderne C++ Technologien wie &lt;code&gt;std::async&lt;/code&gt; darunter, 
dass man sie keinesfalls mit bestimmten Systemroutinen kreuzen darf.&lt;/p&gt;

&lt;p&gt;So gesehen bin ich mit beiden Ansätzen in Windows und Linux unglücklich.
Ich verstehe zwar, dass es immer “historische” Gründe für den Istzustand gibt,
dennoch ärgert es mich, dass ich seit über 13 Jahren in jedem neuen Projekt
gezwungen bin, Workarounds einzubauen, sobald man etwas vom Betriebssystem
haben möchte.&lt;/p&gt;

&lt;p&gt;Und noch jeder Versuch eine neue API auf den Markt zu bringen (von dotNET über
RT bis hin zu den unzähligen inkompatiblen Linux-Bibliotheken), hat mir 
gezeigt, dass es eben immer noch etwas gibt, was durch die neue APIs nicht
abgedeckt wird und letztlich kein Weg an den klassischen APIs vorbeiführt.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Aber keine Sorge, morgen wird sicher alles besser!&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>USB Sticks und Windows 98</title>
   <link href="https://www.opengate.at/blog/2020/10/win98-usb/"/>
   <published>2020-10-17T11:00:00+02:00</published>
   <updated>2020-10-17T11:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2020/10/win98-usb</id>
   <category term="software" /><category term="retro" />
   <summary type="text">Man kann Windows 98 heute
nur noch mit komplexen Mitteln (VM
in anderer VM) zum Laufen bekommen.
Ich habe jedoch alte VIA-Epia Boards, 
auf denen Vista und 
höher nicht mehr lauffähig sind.

Warum installiere ich also dieses alte OS nicht auf der alten Hardware?

Gesagt ⇨ getan ⇨ Probleme
</summary>
   <content type="html">&lt;p&gt;Man kann &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_98&quot;&gt;Windows 98&lt;/a&gt; heute
nur noch mit komplexen Mitteln (&lt;a href=&quot;https://de.wikipedia.org/wiki/Virtuelle_Maschine&quot;&gt;VM&lt;/a&gt;
in anderer VM) zum Laufen bekommen.&lt;br /&gt;
Ich habe jedoch alte &lt;a href=&quot;https://de.wikipedia.org/wiki/EPIA&quot;&gt;VIA-Epia&lt;/a&gt; Boards, 
auf denen &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_Vista&quot;&gt;Vista&lt;/a&gt; und 
höher nicht mehr lauffähig sind.&lt;/p&gt;

&lt;p&gt;Warum installiere ich also dieses alte OS nicht auf der alten Hardware?&lt;/p&gt;

&lt;p&gt;Gesagt ⇨ getan ⇨ Probleme
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;meine-via-itx-geschichte&quot;&gt;Meine VIA ITX Geschichte&lt;/h3&gt;

&lt;p&gt;Meine VIA Epia Board waren so um 2004 herum in den Läden und dienten mir als
Basis für meine Home-Server mit &lt;a href=&quot;https://de.wikipedia.org/wiki/Active_Directory&quot;&gt;Active Directory&lt;/a&gt;
und Netzlaufwerken.&lt;br /&gt;
Im Gegensatz zu “normalen” Computern, die selten unter 60 Watt für ihr häufiges
Nichts-Tun verfraßen, kamen die &lt;a href=&quot;https://de.wikipedia.org/wiki/Mini-ITX&quot;&gt;ITX Boards&lt;/a&gt;
von VIA nie über 20 Watt und bequemten sich im Leerlauf auch mit 15 Watt.&lt;/p&gt;

&lt;p&gt;In Zeiten von &lt;a href=&quot;https://de.wikipedia.org/wiki/Raspberry_Pi&quot;&gt;Raspberry PI&lt;/a&gt; ist 
das viel, aber damals war es ein Hit, der Stromkosten merklich sparen konnte.&lt;/p&gt;

&lt;p&gt;Leider haben die Boards das Jahr 2007 endgültig nicht überlebt. Windows Vista 
war wegen seltsamer IRQ Bluescreens nicht mehr installierbar und beim 
Nachfolger Windows 7 war das nicht anders.&lt;/p&gt;

&lt;p&gt;Offenbar hatte VIA (wie schon bei früheren &lt;a href=&quot;https://de.wikipedia.org/wiki/Cyrix&quot;&gt;Cyrix&lt;/a&gt; 
Prozessoren) etwas anderes implementiert oder ein paar Chips weggelassen, 
die man aber von Intel-kompatiblen System erwarteten konnte.&lt;/p&gt;

&lt;p&gt;Und so war &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_XP&quot;&gt;Windows XP&lt;/a&gt; das 
letzte Betriebssystem, was darauf lief. Auch heutige 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Linux-Distribution&quot;&gt;Linux-Distros&lt;/a&gt;, 
bzw. welche von um 2010 konnte ich nicht mehr auf dieses Board bringen.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/via-epia-board.jpg&quot; alt=&quot;VIA EPIA Board&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;windows-98&quot;&gt;Windows 98&lt;/h3&gt;

&lt;p&gt;Ohne ein verbautes CD-Laufwerk war mein Ansatz über einen 
&lt;a href=&quot;https://de.wikipedia.org/wiki/USB-Stick&quot;&gt;USB Stick&lt;/a&gt; zu booten.
In jener Zeit war dieses Feature gerade aufgekommen und so nutzte ich 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Rufus_(Software)&quot;&gt;Rufus&lt;/a&gt; um einen Stick 
&lt;a href=&quot;https://de.wikipedia.org/wiki/MS-DOS&quot;&gt;DOS&lt;/a&gt; -like zu formatieren, damit beim 
Start eine &lt;a href=&quot;https://de.wikipedia.org/wiki/FreeDOS&quot;&gt;Free-DOS&lt;/a&gt; Instanz 
hochfahren konnte, um von dort aus Windows Setup zu starten.&lt;/p&gt;

&lt;p&gt;Man musste dazu im BIOS den Bootprozess auf HDD-1 ändern anstatt von HDD-0, 
der Systemfestplatte.&lt;br /&gt;
Doch da ergab sich das Problem, dass nun der USB Stick Laufwerk C: war und die
Festplatte Laufwerk D:&lt;/p&gt;

&lt;p&gt;Ich kopierte daher Windows Setup vom Stick auf die Platte und übertrug mit
&lt;code&gt;sys D:&lt;/code&gt; die Systemdateien, damit es beim nächsten Neustart als &lt;code&gt;C:&lt;/code&gt; neu 
erkannt werden sollte.&lt;/p&gt;

&lt;p&gt;Beim Neustart wechselte ich im BIOS wieder auf den HDD-0 Boot und zog den 
Stick ab.&lt;br /&gt;
Die Installation von Windows 98 lief dann ganz regulär durch, bis …&lt;/p&gt;

&lt;h3 id=&quot;treiber-und-usb-stick-zugriff&quot;&gt;Treiber und USB Stick Zugriff&lt;/h3&gt;

&lt;p&gt;Nach der Installation waren Treiber nötig und tatsächlich hatte ich noch eine
alte CD mit passenden Versionen. Also kopierte ich diese von meinem 
Hauptrechner aus auf den USB Stick und steckte diesen am Epia Board an.&lt;/p&gt;

&lt;p&gt;Und dann kam der Dialog, man möge eine Treiber bereitstellen, damit man mit
dem Stick arbeiten kann.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;W-T-F! Ein schönes Henne-Ei Problem.&lt;/p&gt;

  &lt;p&gt;Wie soll ich denn bitte einen Treiber für den USB Stick installieren, 
wenn dieser auf dem USB Stick drauf ist?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Das gleiche Problem hatte ich auch beim Versuch des Anschlusses meines
USB-CD-Laufwerks und meines USB Disketten Laufwerks.&lt;/p&gt;

&lt;p&gt;Windows 98 kam zwar mit USB-Hostcontroller-Support aber ohne Treiber für 
Speichergeräte wie USB-Sticks, -CD-ROMs oder -Disketten.&lt;/p&gt;

&lt;p&gt;Im Netz findet man hierfür eine Lösung: Man installiert den&lt;br /&gt;
“Generic USB Mass Storage Driver” für Windows 98. Ich fand hierfür eine 
&lt;code&gt;nusb36e.exe&lt;/code&gt;. Aber auch diesen musste ich irgendwie auf das System übertragen.&lt;/p&gt;

&lt;p&gt;Folgende Lösungen wären da möglich gewesen:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Man schließt ein altes IDE-CD-Laufwerk ans Board, denn ein solches war
damals üblich und wäre lesbar gewesen.&lt;/li&gt;
  &lt;li&gt;Auf Boards mit Floppy-Controller (mein EPIA hatte keinen mehr) hätte man
auch noch ein altes Diskettenlaufwerk anschließen können um Dateien 
stückweise hinkopieren zu können.&lt;/li&gt;
  &lt;li&gt;Man bootet wieder vom USB Stick und nutzt DOS.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Die letzte Möglichkeit hat einen etwas ironischen Charakter. Denn das alte
&lt;a href=&quot;https://de.wikipedia.org/wiki/BIOS&quot;&gt;BIOS&lt;/a&gt; kann den Stick wie eine 
Festplatte aussehen lassen und z.B. wieder FreeDOS davon booten. In FreeDOS 
hat man wieder den Stick als Laufwerk C: und die Festplatte als
Laufwerk D: und kann so per &lt;code&gt;COPY&lt;/code&gt; alle notwendigen Dateien kopieren.&lt;/p&gt;

&lt;p&gt;Nach einem Neustart und Boot von der Platte kann man die Treiber in Windows 98
installieren und dann problemlos weitere Sticks oder Laufwerke per USB 
ansprechen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Vor über 20 Jahren entdeckte ich noch als Junge meine Liebe zur IT. Es ist
schlimm wie schnell die Zeit verging und wie binnen 5-10 Jahren ein “modernes”
System zum alten Eisen wird, das überhaupt nicht mehr benutzt werden kann.&lt;/p&gt;

&lt;p&gt;Gerade unsere PCs zeichnen sich theoretisch durch das höchste Maß an 
Kompatibilität aus und dennoch ist die Lebensdauer einer OS und Hardware
Generation extrem verkürzt.&lt;/p&gt;

&lt;p&gt;Meine heutige Erfahrung war ein schöner Nostalgie-Flash aber zeigt auch auf,
wie unpraktikabel es geworden ist, mit alten Systemen zu arbeiten.
Die Jungs und Mädels “von heute” können sich kaum vorstellen was für eine 
primitive Zeit das damals war … und ich vermute mal, dass auch sie in 
10-20 Jahren von der Zukunft überrascht sein werden, und wie primitiv 
die heutigen Standards dann wirken.&lt;/p&gt;

&lt;iframe width=&quot;640&quot; height=&quot;360&quot; src=&quot;/blog/redirect.html?https%3A%2F%2Fwww.youtube-nocookie.com%2Fembed%2F8ucCxtgN6sc&quot; frameborder=&quot;1&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
</content>
 </entry>
 
 <entry>
   <title>Wiener Gemeinderatswahl 2020</title>
   <link href="https://www.opengate.at/blog/2020/10/vote4vienna/"/>
   <published>2020-10-11T22:00:00+02:00</published>
   <updated>2020-10-11T22:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2020/10/vote4vienna</id>
   <category term="general" />
   <summary type="text">Die Wiener Stadtregierung hat (und das ist in Österreich inzwischen leider 
nicht mehr selbstverständlich) ihre Legislaturperiode von 5 Jahren 
durchgehalten.
Heute wird der Stadtrat, der Bürgermeister und die Bezirksvertretung neu
gewählt.

Und ich durfte wieder als Beisitzer einige Wählerlisten führen und am Ende
die Stimmzettel mit auszählen.
</summary>
   <content type="html">&lt;p&gt;Die Wiener Stadtregierung hat (und das ist in Österreich inzwischen leider 
nicht mehr selbstverständlich) ihre Legislaturperiode von 5 Jahren 
durchgehalten.&lt;br /&gt;
Heute wird der Stadtrat, der Bürgermeister und die Bezirksvertretung neu
gewählt.&lt;/p&gt;

&lt;p&gt;Und ich durfte wieder als Beisitzer einige Wählerlisten führen und am Ende
die Stimmzettel mit auszählen.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;blockquote&gt;
  &lt;p&gt;Business as usual.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;kann man da sagen. Denn es lief alles recht ähnlich wie bei meinen letzten
beiden Beisitz-Jobs ab, siehe&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;/blog/2019/09/voting/&quot;&gt;Nationalratswahl 2019&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/blog/2019/05/europe/&quot;&gt;Europa Wahl 2019&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Zusammengefasst lief es so ab:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;6:00 Uhr Ankunft im Wahllokal&lt;/li&gt;
  &lt;li&gt;Abzählen von Kuverts und Stimmzettel&lt;/li&gt;
  &lt;li&gt;Angelobung durch den Wahlleiter&lt;/li&gt;
  &lt;li&gt;7:00 Uhr: Öffnung des Wahllokals&lt;/li&gt;
  &lt;li&gt;Notierung einer fortlaufenden Nummer bei jeder abgegebenen Stimme.&lt;/li&gt;
  &lt;li&gt;17:00 Uhr: Schließung des Wahllokals&lt;/li&gt;
  &lt;li&gt;Auszählung der abgegebenen Kuverts&lt;/li&gt;
  &lt;li&gt;Aussortierung der enthaltenen Stimmzettel&lt;/li&gt;
  &lt;li&gt;Mehrfaches Durchzählen der nach Partei sortierten Stimmzettel&lt;/li&gt;
  &lt;li&gt;Prüfung der Namen bei den Vorzugsstimmen und Erfassung ihrer Kandidatennummern&lt;/li&gt;
  &lt;li&gt;Amtliche Notierung aller Informationen&lt;/li&gt;
  &lt;li&gt;Verpackung und Versiegelung aller sortierten Stimmzettel&lt;/li&gt;
  &lt;li&gt;19:30 Uhr: Verabschiedung&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;sonderfall-corona&quot;&gt;Sonderfall Corona&lt;/h3&gt;

&lt;p&gt;Auch die Wahl stand ganz im Zeichen von &lt;a href=&quot;https://de.wikipedia.org/wiki/COVID-19&quot;&gt;COVID-19&lt;/a&gt;
und so mussten wir alle entweder Mund-Nasen-Masken oder ein Kunststoffvisier
vor dem Gesicht tragen.&lt;/p&gt;

&lt;p&gt;Den Wählern erging es ebenso, auch sie mussten sich schützen.&lt;br /&gt;
Zusätzlich war vor dem Wahlleiter ein Glaswand aufgestellt, damit dieser den
Wähler gefahrlos auffordern konnte, die Maske kurz abzunehmen um das Gesicht
mit dem Ausweisfoto vergleichen zu können.&lt;/p&gt;

&lt;p&gt;Stifte lagen diesmal auch keine in den Kabinen auf. Entweder die Wähler
brachten ihre eigenen Schreibstifte mit, oder sie konnten welche vom 
Wahlleiter ausleihen, die nach Rückgabe sofort desinfiziert wurden.&lt;/p&gt;

&lt;p&gt;Das war es aber auch schon zum Thema Corona. Ansonsten lief alles regulär ab.&lt;/p&gt;

&lt;h3 id=&quot;fast-keine-probleme&quot;&gt;(Fast) Keine Probleme&lt;/h3&gt;

&lt;p&gt;Es gab einmal die Notwendigkeit der Prüfung eines Vornamens, der in der 
Wählerliste eine andere Schreibweise hatte als es auf dem Ausweis vermerkt
war. Hier konnte aber telefonisch mit dem Wahlamt abgeklärt werden, dass
es sich um die richtige Person handelte und die Wahl regulär fortgeführt
werden konnte.&lt;/p&gt;

&lt;p&gt;Bei einem zweiten Fall mussten wir feststellen, dass ein Anwohner erst nach
dem gesetzlichen Stichtag in Wien gemeldet war und somit konnte dieser nicht
an der Wahl teilnehmen.&lt;/p&gt;

&lt;p&gt;Die Stimmenauszählung verlief zwar langsam aber sehr erfolgreich.
Tatsächlich stimmten die gezählten Stimmzettel gleich am Anfang mit den 
erwarteten Zahlen aus den Listen überein.&lt;/p&gt;

&lt;p&gt;Es gab jedoch wieder einen einzigen Fall, bei dem wir uns mit der Behörde
abstimmen mussten.
Und zwar konnte man zwei Vorzugskandidaten für die Bezirksvertreterwahl
notieren. Ein Wähler schrieb hier einen richtigen und einen falschen Namen auf,
die beide auch korrekt gezählt wurden. Doch am Ende ergaben die Summen der
korrekten und nicht korrekten Stimmzettel ein größeres Ergebnis, weil der
ein Zettel sowohl zu den korrekten als auch den falschen gezählt wurde.
Also mehr Stimmen-Infos als Wahlzettel.&lt;/p&gt;

&lt;p&gt;Letztendlich war aber auch das nur eine kleine Formalität.&lt;/p&gt;

&lt;h3 id=&quot;highlights&quot;&gt;Highlights&lt;/h3&gt;

&lt;p&gt;Es löst natürlich ein Schmunzeln aus, wenn unter vielen Wählern, die alle
recht förmlich auftreten, dann auch mal ein junger Bursche in Skater-Klamotten
reinkommt, uns alle duzt und in lässiger Jugendsprache nach Einwurf seines 
Kuverts sich mit “Macht’s gut!” verabschiedet.&lt;br /&gt;
Ein “cooler” Typ eben.&lt;/p&gt;

&lt;p&gt;Unvergesslich war aber der Besitzer einer Pizzeria, der am Ende noch Werbung
für sein Restaurant machte. Als einer meiner Kollegen meinte:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Und da haben Sie uns gar nichts mitgebracht?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;meinte der gute Mann, wir hätten ja nichts bestellt und verließ sich 
freundlich verabschiedend das Wahllokal.&lt;/p&gt;

&lt;p&gt;Eine Stunde später erschien der Pizzabäcker erneut mit einer großen 
Pizzaschachtel und stellte sie uns vor die Nase. Er wollte uns einfach ein 
Geschenk machen und verließ erneut grinsend den Raum ohne Geld für seine 
Dienste anzunehmen.&lt;/p&gt;

&lt;p&gt;“Hashtag-Ehrenmann” würde man jetzt im Chat schreiben! Also diese Überraschung
war gelungen, denn niemand hatte mit dieser Tat gerechnet.
Die Pizza war vor allem so groß, dass wir sie mit den anderen uns umgebenden
Wahlzimmern teilen konnten.&lt;/p&gt;

&lt;p&gt;Diesen netten Kerl werde ich also in Zukunft noch einen Besuch abstatten und 
ihm ein entsprechendes Geschäft zukommen lassen.&lt;/p&gt;

&lt;p&gt;Vielleicht war es nur ein einfacher Werbetrick, aber er kam so sympathisch
rüber, dass man ihn dafür einfach nur lieben musste.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Wieder ist ein Tag im Namen der Demokratie vorüber gegangen. Ich hatte zwar
(wie so oft am Wochenende) etwas wenig geschlafen, aber dennoch haben mich 
die Ereignisse des Tages bei Laune gehalten und mich einen schönen angenehmen
Tag im Wahllokal mit netten Kollegen genießen lassen.&lt;/p&gt;

&lt;p&gt;Am Ende habe ich mich mit den Pizzaresten etwas überfressen … schließlich 
wollte ich das übrige köstliche Stück nicht wegwerfen.&lt;/p&gt;

&lt;p&gt;Aber sonst war das wieder mal ein schöner Tag im Dienste der Gesellschaft.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Corona Test durchgeführt!</title>
   <link href="https://www.opengate.at/blog/2020/10/corona-test/"/>
   <published>2020-10-10T13:00:00+02:00</published>
   <updated>2020-10-10T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2020/10/corona-test</id>
   <category term="general" />
   <summary type="text">Für den Beisitz bei der Wien-Wahl morgen am 11. Oktober empfiehlt die Behörde
allen Unterstützern, dass sie einen Corona
Test machen sollen.
Diesen konnte man bei der Bezirksorganisation abholen, durchführen und beim
Labor abgeben.

Ich bin jedenfalls: negativ … und das finde ich positiv.
Soll heißen: Ich bin gesund.
</summary>
   <content type="html">&lt;p&gt;Für den Beisitz bei der Wien-Wahl morgen am 11. Oktober empfiehlt die Behörde
allen Unterstützern, dass sie einen &lt;a href=&quot;https://de.wikipedia.org/wiki/COVID-19-Pandemie&quot;&gt;Corona&lt;/a&gt;
Test machen sollen.
Diesen konnte man bei der Bezirksorganisation abholen, durchführen und beim
Labor abgeben.&lt;/p&gt;

&lt;p&gt;Ich bin jedenfalls: &lt;em&gt;negativ&lt;/em&gt; … und das finde ich &lt;em&gt;positiv&lt;/em&gt;.&lt;br /&gt;
Soll heißen: &lt;em&gt;Ich bin gesund&lt;/em&gt;.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;meine-corona-test-prozedur&quot;&gt;Meine Corona-Test-Prozedur&lt;/h3&gt;

&lt;p&gt;Am Dienstag marschierte ich also nach der Arbeit noch schnell bei meiner 
Bezirksorganisationsstelle vorbei und bekam dort ohne weitere Personalangaben
ein Kuvert überreicht, in dem sich der Gurgeltest befand.&lt;/p&gt;

&lt;p&gt;Darin befanden sich ein Info-Blatt, ein Fläschchen mit der Gurgelflüssigkeit,
ein Strohhalm, ein Probenröhrchen, ein kleines Plastiksäckchen und ein größeres
versiegelbares Transportplastiksäckchen.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/corona-test-set.jpg&quot; alt=&quot;Corona Virus Test Set&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Nachdem als Voraussetzung genannt wurde, dass man 2 Stunden vor dem Test nichts
essen und trinken soll, war für mich klar, dass ich den Test am nächsten Morgen
mache.&lt;/p&gt;

&lt;p&gt;Mittwoch morgens begann ich also mit folgender Prozedur:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Fenster öffnen (keine Ahnung warum man das nicht in geschossenen Räumen 
tun soll).&lt;/li&gt;
  &lt;li&gt;Smartphone-Stopp-Uhr App vorbereiten, denn das Gurgeln soll zwischen 30 und 
60 Sekunden andauern.&lt;/li&gt;
  &lt;li&gt;Dann habe ich etwa 45 Sekunden lang die Flüssigkeit aus dem 
Fläschchen gegurgelt.&lt;/li&gt;
  &lt;li&gt;Die Flüssigkeit wird über den Strohhalm in das Probenröhrchen laufen 
gelassen, man soll sie nämlich nicht “blasen” oder spuken.&lt;/li&gt;
  &lt;li&gt;Das Probenröhrchen wird verschlossen und in das Transportsäckchen gepackt&lt;/li&gt;
  &lt;li&gt;Der Strohhalm kommt in das kleine Plastiksäckchen und soll damit im Müll
entsorgt werden. Umsichtig nenn’ ich das, so kann sich keiner an meinem
Röhrchen infizieren.&lt;/li&gt;
  &lt;li&gt;Am Ende werden noch alle Personaldaten inklusive Telefonnummer in die 
beigelegte Test-Berechtigungskarte eingetragen.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/corona-virus-test-info.jpg&quot; alt=&quot;Corona Virus Test Info&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Das war’s, nun musste der Test noch in ein Labor gebracht werden, und zwar binnen
24 Stunden, also machte ich mich auf den Weg zur nächsten Laborstelle in meinem
Bezirk. Das Ergebnis sollte binnen 48 Stunden ermittelt werden.&lt;/p&gt;

&lt;p&gt;Donnerstag Nachmittag, ich saß am Arbeitsplatz, piepte mein Mobiltelefon.
Die empfangene Kurznachricht lautete:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;SARS-CoV-2 RNA PCR Testergebnis: negativ&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Das Ergebnis war also in knapp 30 Stunden fertig geworden und ich kann nun 
am Wochenende beruhigt meinen Dienst antreten.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ich muss den Labormitarbeitern und der Stadt Wien hier ein großes Lob 
aussprechen. Das Angebot des kostenlosen Tests und die unkomplizierte 
Abarbeitung habe ich sehr positiv wahrgenommen. Einzig die Information,
dass man diese Möglichkeit überhaupt hat, wurde recht knapp per Post
ausgesendet. Das hätte man digital auch schon ein- bis zwei Wochen früher
bekannt geben können.&lt;/p&gt;

&lt;p&gt;Ich weiß nun, dass ich gesund bin und am Wochenende von mir keine Gefahr 
ausgehen wird.&lt;/p&gt;

&lt;p&gt;Dass man einige Tage danach den Test wiederholen kann um sehen, ob man sich 
nicht beim Beisitz wo angesteckt hat, rundet für mich dieses Angebot 
perfekt ab.&lt;/p&gt;

&lt;p&gt;Daumen hoch für dieses Angebot in einer schweren Zeit für alle 
“öffentlichen” Aktionen.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>2 Jahre Blogging</title>
   <link href="https://www.opengate.at/blog/2020/10/blog-year-two/"/>
   <published>2020-10-05T02:00:00+02:00</published>
   <updated>2020-10-05T02:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2020/10/blog-year-two</id>
   <category term="general" /><category term="projects" />
   <summary type="text">Naja … zwei Jahre habe ich durchgehalten.
Das heißt: es geht noch mehr.

Vor 2 Jahren schrieb ich mein erstes Posting
Inzwischen sind es 340 Stück und ein paar Extra-Tutorials liegen
bei den Projekt-Dokus
</summary>
   <content type="html">&lt;p&gt;Naja … zwei Jahre habe ich durchgehalten.&lt;br /&gt;
Das heißt: es geht noch mehr.&lt;/p&gt;

&lt;p&gt;Vor 2 Jahren schrieb ich mein &lt;a href=&quot;/blog/2018/10/main/&quot;&gt;erstes Posting&lt;/a&gt;
Inzwischen sind es 340 Stück und ein paar Extra-Tutorials liegen
bei den &lt;a href=&quot;/blog/projects&quot;&gt;Projekt-Dokus&lt;/a&gt;
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Beruflich bin ich leider … bzw. sollte man eher “Gott sei Dank” sagen,
sehr eingespannt. Und daher bleibt mir für das GATE Projekt recht wenig Zeit
und die Wartung von OpenGATE.at wird überhaupt vernachlässigt.&lt;/p&gt;

&lt;h3 id=&quot;viel-content-aber-wenige-uploads&quot;&gt;Viel Content, aber wenige Uploads&lt;/h3&gt;

&lt;p&gt;Eigentlich wollte ich dieses Jahr häufiger Blog-Updates hochladen.
… so viel zu den Vorsätzen beim Jahreswechsel.&lt;/p&gt;

&lt;p&gt;Seit dem letzten Update im Januar ist das Schreiben eigentlich munter weiter
gegangen …&lt;br /&gt;
… hätten sich da nicht jedes Monat ein bis zwei Beiträge eingeschlichen, 
die nur aus ein paar Zeilen bestanden und ich mir dachte:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Och, das schreib’ ich morgen fertig.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Und dann bleiben diese Lücken offen und wenn man mal was hochladen will,
fällt einem ein:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Hoppla, das geht noch nicht! Es fehlen noch Texte.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Und so habe ich es Monat für Monat nicht geschafft mal einen vollständigen
Satz an Beiträgen zusammenzubekommen.&lt;/p&gt;

&lt;p&gt;Problematisch waren vor allem Hardware-Beiträge, deren Ergebnis bei der 
Planung nicht eingeschätzt wurden und die Tests erst viele Wochen nach der
Erstellung des Postings fertig wurden … und dann waren natürlich noch 
Korrekturen einzufügen.&lt;/p&gt;

&lt;p&gt;Bei der Software-Entwicklung gestaltet sich das für mich einfacher, weil
ich da meistens genau das schreibe, was mir gerade “zugestoßen” ist, aber
bei Software wie Hyper-V oder dem lieben Lichee-Zero-SOC kann es schon mal 
passieren, dass die Ergebnis von der Erwartung abweichen.&lt;/p&gt;

&lt;h3 id=&quot;immer-ärger-mit-der-erwartung&quot;&gt;Immer Ärger mit der Erwartung&lt;/h3&gt;

&lt;p&gt;Da ist man mit den &lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt; Teufelchen 
beim &lt;a href=&quot;http://www.orangepi.org/&quot;&gt;Orange-PI&lt;/a&gt; gerade fertig und will 
noch kurz das Distributions-Upgrade beschreiben. Also tippt man brav die 
Standard-Kommandos ab und schreibt sie in den Blog in der Erwartung, 
das würde alles auch so funktionieren.&lt;br /&gt;
Artikel fertig - Test läuft … für zig Stunden.&lt;br /&gt;
Nächster Tag: Meldung: Upgrade abgebrochen, Boot-Partition zu klein.&lt;br /&gt;
Fuck! Der halbe Artikel falsch - anderen Weg suchen und wieder testen.&lt;/p&gt;

&lt;p&gt;Und so etwas kann sich echt lange hinziehen.&lt;/p&gt;

&lt;p&gt;Tja, however … perfekt ist das natürlich alles nicht … aber immerhin
halte ich diese Projekt weiter am Leben.&lt;/p&gt;

&lt;p&gt;… es dauert nur leider viel zu lange bis mein Geschreibsel dann 
tatsächlich im Netz landet.&lt;/p&gt;

&lt;p&gt;Wie sagte schon Großmutter?&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Gut Ding braucht Weile!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;fortsetzung-folgt&quot;&gt;Fortsetzung folgt&lt;/h3&gt;

&lt;p&gt;Alles in allem halte ich das Projekt aber weiter für sinnvoll und inzwischen
schlage ich meine eigenen Texte nach, wenn ich mal in der Arbeit bei einer
Installation hängen bleibe.&lt;br /&gt;
Damit ist ein wichtiges Projektziel erfüllt: nämlich Dokumentation.&lt;/p&gt;

&lt;p&gt;Viele Jahre habe ich das Netz durchsucht, eine Lösung gefunden, sie
vergessen und dann nie wieder gefunden.&lt;/p&gt;

&lt;p&gt;Es macht also erstaunlicherweise Sinn, mir Frust und Erkenntnis von der 
Seele zu schreiben.&lt;br /&gt;
Und deshalb heißt das Fazit hier:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Fortsetzung folgt …
Mal sehen, was die Zukunft bringt.&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>Duplikate und Klone</title>
   <link href="https://www.opengate.at/blog/2020/10/duplicate-clone/"/>
   <published>2020-10-04T13:00:00+02:00</published>
   <updated>2020-10-04T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2020/10/duplicate-clone</id>
   <category term="devel" /><category term="projects" />
   <summary type="text">Im GATE Projekt gibt es, na sagen wir mal, eine Spitzfindigkeit bei 
Strings.
Diese kann man kopieren, duplizieren und klonen.

Diese drei Formen der Vervielfältigung ist in anderen Frameworks nicht üblich.
Aber ich habe natürlich einen Grund für diese Unterscheidung…
</summary>
   <content type="html">&lt;p&gt;Im GATE Projekt gibt es, na sagen wir mal, eine Spitzfindigkeit bei 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Zeichenkette&quot;&gt;Strings&lt;/a&gt;.
Diese kann man &lt;em&gt;kopieren&lt;/em&gt;, &lt;em&gt;duplizieren&lt;/em&gt; und &lt;em&gt;klonen&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Diese drei Formen der Vervielfältigung ist in anderen Frameworks nicht üblich.
Aber ich habe natürlich einen Grund für diese Unterscheidung…
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Aktuell arbeite ich wieder mehr an den Parsern für Datenformate wie 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Extensible_Markup_Language&quot;&gt;XML&lt;/a&gt;, &lt;a href=&quot;https://de.wikipedia.org/wiki/JavaScript_Object_Notation&quot;&gt;JSON&lt;/a&gt;
und &lt;a href=&quot;https://de.wikipedia.org/wiki/YAML&quot;&gt;YAML&lt;/a&gt;. Für diese sind effiziente 
String-Routinen entscheidend und aus diesem Grund werden 3 Arten der 
Vervielfältigung von Stringinstanzen angeboten:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Kopien:&lt;br /&gt;
&lt;code&gt;gate_string_copy(target, source)&lt;/code&gt; erstellt eine vollständige Kopie eines 
Strings, der keine Verknüpfung mit dem Original hat. Die Kopie ist
inhaltsgleich, teilt jedoch weder Referenzzählung noch Speicher mit der
ursprünglichen Quelle.&lt;/li&gt;
  &lt;li&gt;Duplikat:&lt;br /&gt;
&lt;code&gt;gate_string_duplicate(target, source)&lt;/code&gt; dupliziert die Referenzen der
Quelle auf die neue String-Instanz. Bei einem verwalteten String wird
der Referenzzähler erhöht und der Text-Pointer auf die gleiche Adresse
gesetzt wie im Quellobjekt.&lt;br /&gt;
Bei unverwalteten Strings werden nur die Pointer kopiert und damit darf
die neue Instanz nicht länger benutzt werden als das Original bzw. darf
es nur so lange benutzt werden, wie die (extern verwalteten) Stringdaten
im Speicher zur Verfügung stehen.&lt;/li&gt;
  &lt;li&gt;Klone:
&lt;code&gt;gate_string_clone(target, source)&lt;/code&gt; ist quasi eine Mischung der beiden
anderen, die garantieren soll, dass der Klon nicht von der Lebensdauer
des Original beeinflusst werden darf.&lt;br /&gt;
Bei verwalteten String-Puffern wird der Referenzzähler erhöht und damit
lebt der Puffer so lange, bis die letzte Referenz erlischt.&lt;br /&gt;
Ist die Quelle aber unverwaltet, startet ein Kopiervorgang. Es wird eine
verwaltete Kopie des unverwalteten Originals erzeugt.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;performance-vs-sicherheit&quot;&gt;Performance vs. Sicherheit&lt;/h3&gt;

&lt;p&gt;Duplikate sind der schnellste Weg um Strings zu vervielfältigen, weil es bei
ihnen nie zur Allokierung von neuem Speicher kommen kann. Hat man aber mal
versehentlich einen “statischen” String dupliziert und weiterverarbeitet, 
dessen Daten auf dem Stack lagen, dann produziert man einen Crash, sobald der
Scope des originalen Puffers verlassen wird.&lt;/p&gt;

&lt;p&gt;Kopien wiederum sind die sicherste Variante, verbrauchen aber auch den 
meisten Speicher. Sie sind damit der &lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_C%2B%2B&quot;&gt;MSVC&lt;/a&gt;
Implementierung von &lt;a href=&quot;http://www.cplusplus.com/reference/string/string/&quot;&gt;&lt;code&gt;std::string&lt;/code&gt;&lt;/a&gt;
gleichgestellt, die ebenfalls immer neue Kopien anlegen.&lt;/p&gt;

&lt;p&gt;Der Vorteil von Klonen liegt in ihrer Effizienz, dass kein Overhead bei
verwalteten Strings produziert wird und das nicht-verwaltete Strings zu
verwalteten Kopien umgestaltet werden.&lt;br /&gt;
Es wird also nur einmal Speicher für eine Kopie angefordert und nicht mehrfach.&lt;/p&gt;

&lt;h3 id=&quot;einsatzorte&quot;&gt;Einsatzorte&lt;/h3&gt;

&lt;p&gt;Kopien eignen sich hervorragend für die Weitergabe von Daten zwischen Modulen 
wie DLLs oder SOs. Denn obwohl verwaltete Strings durch den Referenzzähler so 
lange im Speicher erhalten bleibt, wie die Referenz es will, so stammt 
die Destruktorfunktion dennoch aus dem Modul, mit dem der String allokiert 
wurde.&lt;br /&gt;
Wenn die &lt;a href=&quot;https://de.wikipedia.org/wiki/Dynamic_Link_Library&quot;&gt;DLL/SO&lt;/a&gt; also 
bereits entladen ist, kommt es zum Crash weil der Code zur Löschung nicht mehr
im Speicher vorhanden ist.&lt;br /&gt;
Bei einer Kopie wird jedoch die Destruktorfunktion des Moduls benutzt, in 
welchem die Kopie angestoßen wurde.&lt;/p&gt;

&lt;p&gt;Duplikate eignen sich super für synchrone Parsing-Operationen, die die 
Stringinhalte oder deren Teilmengen nicht über den Parsing-Prozess hinweg 
erhalten müssen. Während des Parsings können also zahlreiche Duplikate und 
Sub-Strings produziert werden, die alle auf die originalen Input-Daten 
verweisen. Man kann daher auch statische String problemlos in den Duplikaten
nutzen und hat garantiert keinen zusätzlichen Speicherbedarf.&lt;/p&gt;

&lt;p&gt;Und Klone verwendet man für fast alles andere, weil sie sicher und möglichst 
schnell sind und weil viele Klone maximal eine oder eben gar keine 
Allokierung anstoßen.&lt;/p&gt;

&lt;h3 id=&quot;rückgabewerte-von-string-funktionen&quot;&gt;Rückgabewerte von String-Funktionen&lt;/h3&gt;

&lt;p&gt;Aus Effizienzgründen liefern die GATE Standard-String-Routinen wie 
&lt;code&gt;gate_string_substr()&lt;/code&gt; oder &lt;code&gt;gate_string_trim()&lt;/code&gt; nur manipulierte Duplikate 
zurück. Eine nicht-verwaltete Quelle führt also zu einem nicht-verwalteten 
Resultat.&lt;br /&gt;
Und das gleiche gilt auch für den GATE C++ Wrapper, dessen Kopierkonstruktor 
ebenfalls nur &lt;code&gt;gate_string_duplicate&lt;/code&gt; einsetzt.&lt;/p&gt;

&lt;p&gt;Hier liegt nämlich das Augenmerk auf Speicherschonung, denn wenn jemand einen
nicht-verwalteten String einsetzt, soll das Framework diesen Typ nicht 
ungefragt in einen verwalteten konvertieren.&lt;/p&gt;

&lt;p&gt;Es sollte daher in den höheren Ebenen stets eine Logik eingebaut werden, die
nicht-verwaltete Strings zuerst klont oder kopiert, bevor die Daten 
langfristig weiter benutzt werden.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Die Namensgebung ist … nunja, vielleicht nicht optimal. Tatsächlich habe ich
mir schwer getan hier 3 Namen zu finden, die in etwa abdecken sollen, was
wirklich passiert.&lt;/p&gt;

&lt;p&gt;Ich gebe aber zu, dass man die Begriffe “duplizieren” und “klonen” auch genau
anders herum interpretieren kann, wie ich es letztendlich entschieden habe.&lt;/p&gt;

&lt;p&gt;Man kann es sich am besten so merken:&lt;br /&gt;
Duplikate sind quasi hirnlose maschinelle Kopien ( &lt;a href=&quot;http://www.cplusplus.com/reference/cstring/memcpy/&quot;&gt;&lt;code&gt;memcpy()&lt;/code&gt;&lt;/a&gt; ), 
während Klonen echtes Leben eingehaucht wird und diese trotz genetischer 
Verbindung zum Original eigene Wege gehen können.&lt;/p&gt;

&lt;p&gt;Wie auch immer … egal wie der String erzeugt wurde, am Ende muss er immer
mit &lt;code&gt;gate_string_release&lt;/code&gt; freigegeben werden.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Python für das alte Debian 8 und 9</title>
   <link href="https://www.opengate.at/blog/2020/10/python-debian/"/>
   <published>2020-10-03T13:00:00+02:00</published>
   <updated>2020-10-03T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2020/10/python-debian</id>
   <category term="software" />
   <summary type="text">Man braucht Python 
3.7 unter Debian 8 oder 9. 
Die beiden unterstützen das aber nicht.
Man kompiliert Python aus den Quellen, das scheitert wieder an 
OpenSSL.

Willkommen in meiner verrückten Welt der 
Linux Installationen.
</summary>
   <content type="html">&lt;p&gt;Man braucht &lt;a href=&quot;https://de.wikipedia.org/wiki/Python_(Programmiersprache)&quot;&gt;Python&lt;/a&gt; 
3.7 unter &lt;a href=&quot;https://de.wikipedia.org/wiki/Debian&quot;&gt;Debian&lt;/a&gt; 8 oder 9. 
Die beiden unterstützen das aber nicht.&lt;br /&gt;
Man kompiliert Python aus den Quellen, das scheitert wieder an 
&lt;a href=&quot;https://de.wikipedia.org/wiki/OpenSSL&quot;&gt;OpenSSL&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Willkommen in meiner verrückten Welt der 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt; Installationen.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Der Support von älteren Betriebssystem wird von Softwareherstellern sträflichst
vernachlässigt. Denn wenn auf Industriehardware ein bestimmtes System 
vorgeschrieben ist, kann man nicht einfach zum USB-Stick greifen und ein neues
OS aufziehen.&lt;/p&gt;

&lt;p&gt;Man muss also die Software dazu bringen, auf dem alten System zu laufen.&lt;/p&gt;

&lt;p&gt;In meinem Fall war die Anforderung:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Debian 8&lt;/li&gt;
  &lt;li&gt;Python 3.7&lt;/li&gt;
  &lt;li&gt;SSL Python Bibliothek und &lt;code&gt;pip&lt;/code&gt; zum Download weiterer Pakete.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nach einer Menge von Fehlschlägen möchte ich das Ergebnis nicht verheimlichen.&lt;/p&gt;

&lt;p&gt;Die bei Debian vorhandene OpenSSL 1.0.2 Bibliothek ist ebenfalls zu alt und 
muss erneuert werden bevor Python kompiliert werden kann. Wir müssen also:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Eine Build-Umgebung bereitstellen&lt;/li&gt;
  &lt;li&gt;OpenSSL Quellen herunterladen und durchbauen&lt;/li&gt;
  &lt;li&gt;OpenSSL ins System integrieren&lt;/li&gt;
  &lt;li&gt;Python Quellen herunterladen und durchbauen&lt;/li&gt;
  &lt;li&gt;Python ins System integrieren&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Meine wichtigste Erkenntnis war:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ja nicht &lt;code&gt;ldconfig -v&lt;/code&gt; vergessen !!!!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;installationsprozedur&quot;&gt;Installationsprozedur&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;Build-Umgebung bereitstellen:&lt;br /&gt;
Ich habe die Installation generell als &lt;code&gt;root&lt;/code&gt; laufen
lassen. Vermutlich wird es mit &lt;code&gt;sudo&lt;/code&gt; aber auch&lt;br /&gt;
funktionieren.
    &lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;apt install build-essential checkinstall \
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;    libreadline-gplv2-dev libncursesw5-dev \
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;    libsqlite3-dev tk-dev libgdbm-dev \
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;    libc6-dev libbz2-dev wget curl 
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;OpenSSL Quellen herunterladen und durchbauen:&lt;br /&gt;
Ich habe mich OpenSSL 1.1.1f gewählt und lasse die Datei direkt aus dem
Netz laden. Die Quellen werden in &lt;code&gt;/usr/src&lt;/code&gt; gebaut.
    &lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;cd /usr/src
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;wget http://www.openssl.org/source/old/1.1.1/openssl-1.1.1f.tar.gz
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;tar -xf openssl-1.1.1f.tar.gz
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;cd openssl-1.1.1f
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;./config shared --prefix=/usr/local/
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;make -j8
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;make install
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;mkdir lib
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;cp ./*.so ./lib
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;cp ./*.so.* ./lib
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;cp ./*.a ./lib
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;cp ./*.pc ./lib
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;OpenSSL ins System integrieren:&lt;br /&gt;
Die vorherige Installationsprozedur reicht nicht aus, dass andere
Programme OpenSSL finden, deshalb muss nun
    &lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;ldconfig -v
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
    &lt;/div&gt;
    &lt;p&gt;ausgeführt werden. Es garantiert, dass OpenSSL’s *.so Dateien geladen
werden können.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Python Quellen herunterladen und durchbauen:&lt;br /&gt;
Mein Wahl fiel auf Python 3.7.9, welches beim
Kompilieren den Pfad zu OpenSSL benötigt.
    &lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;cd /usr/src
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;wget https://www.python.org/ftp/python/3.7.9/Python-3.7.9.tar.xz
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;tar -xf Python-3.7.9.tar.xz
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;cd Python-3.7.9
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;./configure --with-openssl=/usr/src/openssl-1.1.1f
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;make -j8
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;make altinstall
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;Python ins System integrieren:&lt;br /&gt;
Das Tool &lt;code&gt;update-alternatives&lt;/code&gt; soll nun alle Links so einrichten,
dass Python im System gefunden werden kann:
    &lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;update-alternatives --install /usr/bin/python3 python3 /usr/local/bin/python3.7 1
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;update-alternatives --config python3
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;update-alternatives --install /usr/bin/pip3 pip3 /usr/local/bin/pip3.7 1
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;update-alternatives --config pip3
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
    &lt;/div&gt;
    &lt;p&gt;Wer möchte, dass Python 3 auch gleich Python 2 ersetzt, kann wie folgt 
fortfahren:&lt;/p&gt;
    &lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;update-alternatives --install /usr/bin/python python /usr/local/bin/python3.7 1
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;update-alternatives --config python
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;update-alternatives --install /usr/bin/pip pip /usr/local/bin/pip3.7 1
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;update-alternatives --config pip
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
    &lt;/div&gt;
    &lt;p&gt;Aber Vorsicht: Es kann dann auch zu Störungen kommen, wenn Python 2 Scripts
ausgeführt werden.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Die Prozedur hat bei mir sowohl unter Debian 8 als auch unter Debian 9 
funktioniert.&lt;/p&gt;

&lt;p&gt;Debian 10 hat zum Glück beide Programmversionen schon in seinem Repository.
Hier reicht ein einfaches&lt;br /&gt;
&lt;code&gt;apt install python3 python3-pip&lt;/code&gt;&lt;br /&gt;
(Ja, so einfach kann es eben auch gehen)&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Wie schon erwähnt hat mich das fehlende &lt;code&gt;ldconfig -v&lt;/code&gt; viel Zeit gekostet.
Denn Python kompiliert ansonsten ganz brav durch und meint am Ende im 
Kommentar, dass SSL nicht zur Verfügung steht, weil die nötigen Libs nicht 
gefunden wurden.&lt;/p&gt;

&lt;p&gt;Das Problem bemerkt man erst, wenn man die ersten Scripts ausführt, die dann 
an HTTPS und Co scheitern.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Ärger mit Android Apps</title>
   <link href="https://www.opengate.at/blog/2020/09/anger-app/"/>
   <published>2020-09-27T13:00:00+02:00</published>
   <updated>2020-09-27T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2020/09/anger-app</id>
   <category term="software" />
   <summary type="text">Zur Verbesserung meiner Rückenmuskulatur hat mir der Arzt 
eine App verschrieben.

Sie soll mir täglich Übungen für die Wirbelsäule vorschreiben und mir beim
Entspannen helfen.

… ich glaube aber eher, dass es das Ziel ist meinen Blutdruck zu steigern.
</summary>
   <content type="html">&lt;p&gt;Zur Verbesserung meiner Rückenmuskulatur hat mir der Arzt 
eine &lt;a href=&quot;https://de.wikipedia.org/wiki/Mobile_App&quot;&gt;App&lt;/a&gt; verschrieben.&lt;/p&gt;

&lt;p&gt;Sie soll mir täglich Übungen für die Wirbelsäule vorschreiben und mir beim
Entspannen helfen.&lt;/p&gt;

&lt;p&gt;… ich glaube aber eher, dass es das Ziel ist meinen Blutdruck zu steigern.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Die Idee, die Technik zur Behandlung von Krankheiten einzusetzen halte ich
für großartig. Und anstatt mich zu jemanden zu schicken, der mir sagt, ich
möge 5 Minuten auf einer Matte hin- und her rollen, macht es Sinn, die
Anweisungen online zu empfangen.&lt;/p&gt;

&lt;p&gt;… letztendlich sind das also alles aufgezeichnete Videos.&lt;/p&gt;

&lt;p&gt;Aber man will ja Geld verdienen, bzw. der Krankenkasse etwas verrechnen.&lt;/p&gt;

&lt;p&gt;Also stellt man die Videos nicht auf &lt;a href=&quot;https://de.wikipedia.org/wiki/YouTube&quot;&gt;YouTube&lt;/a&gt;, 
sondern legt die Dateien auf einen eigenen Server und schustert schnell eine 
“App” zusammen, die die Videos abspielt.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Alter Schwede … so etwas habe ich ja schon lange nicht mehr erlebt.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ich dachte anfangs, es läge an meinem Internet, doch nein, Streaming flutscht
perfekt.&lt;br /&gt;
Offenbar bekommt die App in einigen Fällen ihre Daten nicht schnell genug.
Sie lädt nicht im Hintergrund herunter sondern spielt direkt ab. Doch wenn
noch nicht alle Daten da sind, springt sie einfach 10 Sekunden zurück und 
wiederholt den Abschnitt so lange, bis die nächsten 10 Sekunden endlich
da sind.&lt;/p&gt;

&lt;p&gt;Ähm, es ist schon echt ironisch, wie aggressiv ich werden kann, wenn ich 
in einer 4-Minuten Übung geschlagene 5 Minuten folgende Aussage in
einer Endlosschleife höre:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Legen Sie sich auf eine Matte und entspannen Sie sich.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;bevor die Übung wirklich anfängt.&lt;br /&gt;
Und dann geht es weiter mit:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Stellen… &lt;br /&gt;
Stellen Sie…
Stellen Sie ihr…
Stellen Sie ihre…
Stellen Sie ihre Beine…
Stellen Sie ihre Beine auf…
Stellen Sie ihre Beine auf, dass…
Stellen Sie ihre Beine auf, dass ihre Knie…
Stellen Sie ihre Beine auf, dass ihre Knie zur…
Stellen Sie ihre Beine auf, dass ihre Knie zur Decke…
Stellen Sie ihre Beine auf, dass ihre Knie zur Decke zei…
Stellen Sie ihre Beine auf, dass ihre Knie zur Decke zeigen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Puh … also den Entwickler dieser App darf ich nicht in die Finger bekommen.&lt;/p&gt;

&lt;p&gt;Es dürfte offenbar von der Übung und von der Zeit abhängen, wie gut die 
Videos geladen werden können.
Seitdem ich erst nach 22:00 Uhr mit den Übungen beginne, sind nur noch einige
wenige Schluckauf-Schleifen im Video.&lt;/p&gt;

&lt;p&gt;Aber wie kann man nur so eine seltsame Rücksprung-Sache einbauen?&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Die Übungen sind nicht schlecht und tun meinem Rücken sicher gut.
Aber diese App-Umsetzung verstört mich regelrecht.&lt;/p&gt;

&lt;p&gt;Hätte ich mehr Freizeit, wäre das jetzt ein Grund zum Hersteller zu fahren,
der ohnehin hier in Wien ansässig ist, und würde die Quellcodes zwecks 
Überarbeitung einfordern.&lt;/p&gt;

&lt;p&gt;Aber so muss ich die nächsten beiden Monate wohl mit durch Schluckauf 
verlängerten Übungen leben lernen.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>TENET</title>
   <link href="https://www.opengate.at/blog/2020/09/tenet/"/>
   <published>2020-09-26T13:00:00+02:00</published>
   <updated>2020-09-26T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2020/09/tenet</id>
   <category term="entertainment" />
   <summary type="text">Das ist er also, DER Film nach der Krise, der uns nach Corona
endlich wieder ins Kino zurückholen soll.

Mit großer Verspätung habe ich den Film gesehen und endlich mal wieder einen
schönen Abend im Kino verbracht.
</summary>
   <content type="html">&lt;p&gt;Das ist er also, DER Film nach der Krise, der uns nach &lt;a href=&quot;https://de.wikipedia.org/wiki/COVID-19-Pandemie&quot;&gt;Corona&lt;/a&gt;
endlich wieder ins Kino zurückholen soll.&lt;/p&gt;

&lt;p&gt;Mit großer Verspätung habe ich den Film gesehen und endlich mal wieder einen
schönen Abend im Kino verbracht.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Zeitreisen sind ein kritischer Stoff, den nicht jeder Drehbuchautor schlüssig
umsetzen kann.&lt;br /&gt;
&lt;a href=&quot;https://de.wikipedia.org/wiki/Tenet_(Film)&quot;&gt;TENET&lt;/a&gt; kommt hier aber mit einer 
ganz neuen Idee an, deren Abläufe die kleinen grauen Zellen beim Zusehen 
ordentlich fordern können.&lt;/p&gt;

&lt;h3 id=&quot;spoiler-voraus&quot;&gt;Spoiler voraus!&lt;/h3&gt;

&lt;p&gt;Ja, die Idee, dass &lt;a href=&quot;https://de.wikipedia.org/wiki/Positron&quot;&gt;Positronen&lt;/a&gt; nur 
Elektronen sind, die sich rückwärts durch die Zeit bewegen und deshalb 
“umgekehrt” wirken wie normale Elektronen, habe ich schon mal gehört.&lt;br /&gt;
Aber dass man auf dieser Idee einen komplizierten Handlungsstrang aufbauen 
kann, bei dem man sich mal vorwärts und dann wieder rückwärts durch die Zeit 
bewegt … also das ist schon echt genial.&lt;/p&gt;

&lt;p&gt;Keine Portale, &lt;a href=&quot;https://de.wikipedia.org/wiki/Schwarzes_Loch&quot;&gt;schwarze Löcher&lt;/a&gt; 
oder schnelle Autos durchbrechen knallartig Raum und Zeit, sondern man dreht
einfach den Zeitverlauf einer Objekte oder Menschen um.&lt;/p&gt;

&lt;p&gt;Man bewegt sich selbst vorwärts wird aber von der Umgebung so wahrgenommen,
als liefe alles rückwärts ab.&lt;/p&gt;

&lt;p&gt;Und wenn dann auch noch Personen mit unterschiedlichen Zeitrichtungen 
mit einander interagieren müssen, wird es streckenweise echt kompliziert.&lt;/p&gt;

&lt;p&gt;Aber genau das macht einen guten Film aus: Man hat eine spannende Handlung
und im Nachhinein kann man immer noch sagen:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ja, jetzt am Ende macht ja doch wieder alles Sinn innerhalb der 
Logik des Films.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ich möchte gar nicht zu viel darüber schreiben sondern empfehle jedem 
sich den Film anzusehen.&lt;/p&gt;

&lt;p&gt;Einen Nachteil kann ich aber dennoch herauslesen.
Wie bei &lt;a href=&quot;https://de.wikipedia.org/wiki/The_Sixth_Sense&quot;&gt;The Sixth Sense&lt;/a&gt; 
verlieren die Effekte beim wiederholten Ansehen schnell ihren Reiz.&lt;br /&gt;
Man kennt ja bereits die Zusammenhänge, die beim ersten Ansehen
noch als extrem spannend und mysteriös empfunden wurden und erlebt diesen
allerersten Eindruck leider kein zweites mal mehr.&lt;/p&gt;

&lt;p&gt;Trotzdem war es wieder schön im Kino zu sitzen … eine Freizeitbeschäftigung,
die uns die Virus-Pandemie mehr als versaut hat in den letzten Monaten.&lt;/p&gt;

&lt;p&gt;Wäre schön, wenn es in diesem Fahrwasser so weitergehen würde, doch leider 
ist die Menge an neuen Filmen leider recht gering…&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>NT4 unter Hyper-V 2012</title>
   <link href="https://www.opengate.at/blog/2020/09/nt4-hyper-v/"/>
   <published>2020-09-20T13:00:00+02:00</published>
   <updated>2020-09-20T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2020/09/nt4-hyper-v</id>
   <category term="software" /><category term="retro" />
   <summary type="text">VM starten, man sieht noch
kurz den blauen Start-Bildschirm, plötzlich erkennt man noch schemenhaft die
Auflistung von Speicheradressen und schon ist die VM wieder offline.

Das passiert, wenn man auf Hyper-V 
2012 das Setup von Windows NT 4
von der CD starten lassen möchte.

Es kann doch nicht sein, dass NT4 unter Server 2008
noch lief und auf späteren “besseren” Hyper-V Systemen einfach crash-t.
</summary>
   <content type="html">&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Virtuelle_Maschine&quot;&gt;VM&lt;/a&gt; starten, man sieht noch
kurz den blauen Start-Bildschirm, plötzlich erkennt man noch schemenhaft die
Auflistung von Speicheradressen und schon ist die VM wieder offline.&lt;/p&gt;

&lt;p&gt;Das passiert, wenn man auf &lt;a href=&quot;https://de.wikipedia.org/wiki/Hyper-V&quot;&gt;Hyper-V&lt;/a&gt; 
2012 das Setup von &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_NT_4.0&quot;&gt;Windows NT 4&lt;/a&gt;
von der CD starten lassen möchte.&lt;/p&gt;

&lt;p&gt;Es kann doch nicht sein, dass NT4 unter &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_Server_2008&quot;&gt;Server 2008&lt;/a&gt;
noch lief und auf späteren “besseren” Hyper-V Systemen einfach crash-t.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Nachdem ich gestern ein virtualisiertes &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_Server_2003&quot;&gt;Server 2003&lt;/a&gt;
System hochziehen musste um darin per &lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_Virtual_PC&quot;&gt;Virtual-PC&lt;/a&gt; 
eine NT-4 Instanz starten zu können, war ich am Ende doch etwas frustriert, 
dass mein Hyper-V 2012 das NT-4 Setup einfach abstürzen lässt.&lt;/p&gt;

&lt;p&gt;Ich verstehe, dass der offizielle Support beendet wurde und dass z.B. die 
Integrationstools NT4 nicht mehr unterstützen … aber trotzdem müsste doch
eine generische Installation ohne Features möglich sein!&lt;/p&gt;

&lt;p&gt;Und nach einer eigentlich kurzen &lt;a href=&quot;https://virtuallyfun.com/wordpress/2014/12/09/loading-nt-4-0-windows-2000-on-hyper-v/&quot;&gt;Recherche im Netz&lt;/a&gt;
fand ich eine verblüffend einfache Lösung:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Man muss nur die Einstellung &lt;code&gt;CompatibilityForOlderOperatingSystemsEnabled&lt;/code&gt;
aktivieren, die Microsoft per UI leider nicht mehr zugänglich macht.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;Alter Schwede! So etwas ärgert mich jetzt aber richtig!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Die Software unterstützt also wesentlich mehr, und man limitiert Features 
per UI nach unten … einfach nur blöd aus meiner Sicht.&lt;/p&gt;

&lt;h3 id=&quot;lösung-einstellung-per-powershell-aktivieren&quot;&gt;Lösung: Einstellung per Powershell aktivieren&lt;/h3&gt;

&lt;p&gt;Folgende Schritte musste ich durchführen um NT4 in Hyper-V zum Laufen zu 
bekommen:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Die Powershell-Erweiterung für Hyper-V muss installiert werden.&lt;br /&gt;
Hierfür startet man das Hinzufügen von neuen Rollen und Features und 
wählt unter Features den Eintrag: 
&lt;code&gt;Remote-Administration-Tools&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;Hyper-V Management Tools&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;Hyper-V Module for Windows Powershell&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Die Powershell MUSS als &lt;code&gt;Administrator&lt;/code&gt; ausgeführt werden.&lt;/li&gt;
  &lt;li&gt;Nun nutzt man das Kommando:&lt;br /&gt;
&lt;code&gt;Set-VMProcessor &quot;Name-of-VM&quot; -CompatibilityForOlderOperatingSystemsEnabled $true&lt;/code&gt;&lt;br /&gt;
(wo man selbstverständlich “Name-of-VM” durch den richtigen Namen der VM 
ersetzt!)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Und kaum startet man die VM (per UI oder per PS &lt;code&gt;Start-VM -Name &quot;Name-of-VM&quot;&lt;/code&gt;),
bootet die zuvor eingelegte NT4 CD und die Installation läuft regulär durch.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/hyper-v-powershell-setup.png&quot; alt=&quot;NT4 in Hyper-V&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Also … ich kann nicht ganz nachvollziehen, warum man die Checkbox bei den
CPU-Optionen, die es früher mal gab, entfernt hat, über die man den NT-4
Support aktivieren kann.&lt;/p&gt;

&lt;p&gt;Das Problem mit Powershell Scripts und deren Features ist, dass sie so 
umfangreich sind, dass man sie nicht alle im Kopf behalten kann. Eben genau
dafür bedarf es einer übersichtlichen UI, um an alle Einstellungen zu kommen.&lt;/p&gt;

&lt;p&gt;Der Satz “Früher war alles besser” lässt sich schwer widerlegen, wenn 
Software nachweislich “schlechter” gemacht wird, ohne dass es einen
Nicht-Marketing Grund dafür gibt.&lt;/p&gt;

&lt;p&gt;Also Daumen runter für die Hyper-V UI, aber Daumen hoch für die Entwickler
der Hyper-V Kernfeatures, die den historischen CPU-Support integriert und
weiter gepflegt haben.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Pre-XP Softwareentwicklung</title>
   <link href="https://www.opengate.at/blog/2020/09/retro-app-dev/"/>
   <published>2020-09-19T13:00:00+02:00</published>
   <updated>2020-09-19T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2020/09/retro-app-dev</id>
   <category term="devel" /><category term="retro" />
   <summary type="text">Es ist endlich so weit: Ich teste das GATE Framework auf Windows 2000,
NT4 und 
Windows 98.

Das witzige dabei: Das Entwicklungs-Konzept hierfür stammt von den Anpassungen
für den Docker-Support für Windows Nano Server 2019.

Und so schließt sich ein Kreis von fast 25 Jahren Software-Erfahrung.

</summary>
   <content type="html">&lt;p&gt;Es ist endlich so weit: Ich teste das GATE Framework auf &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_2000&quot;&gt;Windows 2000&lt;/a&gt;,
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_NT_4.0&quot;&gt;NT4&lt;/a&gt; und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_98&quot;&gt;Windows 98&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Das witzige dabei: Das Entwicklungs-Konzept hierfür stammt von den Anpassungen
für den Docker-Support für &lt;a href=&quot;https://hub.docker.com/_/microsoft-windows-nanoserver&quot;&gt;Windows Nano Server 2019&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Und so schließt sich ein Kreis von fast 25 Jahren Software-Erfahrung.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;optionale-schnittstellen&quot;&gt;Optionale Schnittstellen&lt;/h3&gt;

&lt;p&gt;Damit GATE Software in &lt;a href=&quot;https://de.wikipedia.org/wiki/Docker_(Software)&quot;&gt;Docker&lt;/a&gt; 
Images für Server 2016 und 2019 läuft, mussten einige APIs in den 
“platform-support layer” verschoben werden.&lt;br /&gt;
Dieser verwaltet eine Tabelle von Funktionszeigern, die beim Starten
Schritt für Schritt dynamisch geladen werden (per &lt;a href=&quot;http://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryw&quot;&gt;LoadLibrary&lt;/a&gt;
und GetProcAddress).&lt;/p&gt;

&lt;p&gt;Die Idee ist, dass das GATE Framework nur gegen elementare Kernfunktionen 
einer Plattform direkt linkt und alles andere “optional” bei Bedarf
nachlädt.&lt;/p&gt;

&lt;p&gt;Das Framework kann auf diese Weise z.B.: Windows 10 Features nutzen 
(wenn verfügbar), bleibt aber weiter zu älteren Windows Versionen ohne
Anpassungen und Hacks kompatibel.&lt;/p&gt;

&lt;p&gt;So wird z.B. beim “Terminieren” von fremden Prozessen unter einem regulärem
Windows System versucht, die entsprechenden Fenster über die bevorstehende
Schließung zu benachrichtigen. &lt;br /&gt;
Aber in einer Docker-Sitzung existieren keine GUI APIs. Würden wir dieses
Feature also fix einbinden, wäre die Anwendung nicht Docker-tauglich,
doch über die “optionale” Variante läuft GATE Code eben in allen …
oder sagen wir mal: in vielen Umgebungen.&lt;/p&gt;

&lt;h3 id=&quot;antike-windows-setups&quot;&gt;Antike Windows Setups&lt;/h3&gt;

&lt;p&gt;Da nun mein aktuell “ältester” &lt;a href=&quot;https://de.wikipedia.org/wiki/Hyper-V&quot;&gt;Hyper-Visor&lt;/a&gt; 
jener von &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_Server_2012&quot;&gt;Server 2012&lt;/a&gt; 
ist, wird kein System älter als Windows XP SP3 und Server 2003 SP2 unterstützt.
Windows 2000 lässt sich zwar noch installieren und mit den Integrations-Tools
von Server 2008 sogar halbwegs benutzen, aber bei NT 4 und Win9x beißt man 
auf Granit.&lt;/p&gt;

&lt;p&gt;Und leider kann ich wegen Docker auf meinem Entwicklersystem nicht mehr
parallel &lt;a href=&quot;https://de.wikipedia.org/wiki/VirtualBox&quot;&gt;VirtualBox&lt;/a&gt; laufen lassen.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Die umständliche Lösung:&lt;/em&gt;&lt;br /&gt;
Hyper-V hosted Windows XP und dieses hostet per &lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_Virtual_PC&quot;&gt;Virtual-PC&lt;/a&gt;
die älteren Systeme.&lt;/p&gt;

&lt;p&gt;Und wenn man viel Zeit und Geduld hat, stellt man fest: Es funktioniert!&lt;/p&gt;

&lt;p&gt;Etwas unterschätzt habe ich, wie schlecht diese Sandkisten auf meinem 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Intel_Celeron&quot;&gt;Celeron&lt;/a&gt; 1.6 GHz System performen.
So weit ich erkennen kann liegt das auch zu einem großen Teil am I/O. 
Die CPU unterstützt keine I/O Virtualisierung und somit läuft der Zugriff
auf eine Festplatte in einer &lt;a href=&quot;https://de.wikipedia.org/wiki/Virtuelle_Maschine&quot;&gt;VM&lt;/a&gt;
in einer anderen VM über eine sehr sehr langsame Transportstrecke.&lt;/p&gt;

&lt;h3 id=&quot;nt-4-wiederauferstehung&quot;&gt;NT 4 Wiederauferstehung&lt;/h3&gt;

&lt;p&gt;NT4 Workstation ließ sich problemlos in Virtual PC installieren. Einzig
der alte &lt;a href=&quot;https://de.wikipedia.org/wiki/Dynamic_Host_Configuration_Protocol&quot;&gt;DHCP&lt;/a&gt;
Dienst konnte keine IP empfangen, was durch eine statische Adresse schnell 
gelöst war.&lt;br /&gt;
Umständlich war dann “meine” übliche NT-Update-Routine.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Zuerst wird das Service Pack 3 eingespielt, welches eine Voraussetzung 
für den &lt;a href=&quot;https://de.wikipedia.org/wiki/Internet_Explorer#Version_4&quot;&gt;IE 4&lt;/a&gt; 
ist. Leider musste ich erst ein deutsche Version davon finden, doch zum 
Glück stehen ja noch die alten PC-Magazin CDs in meinem Regal,
wo eine solche Version auf CD 4 von 1998 zu finden war.&lt;/li&gt;
  &lt;li&gt;Nun wird der IE 4 mit der &lt;a href=&quot;https://de.wikipedia.org/wiki/Active_Desktop&quot;&gt;Active-Desktop&lt;/a&gt;
Erweiterung installiert. Dieses Setup bringt nämlich die NT4-DLLs auf den 
Stand von Windows 98 was die UI-Kompatibilität erhöhen kann.&lt;/li&gt;
  &lt;li&gt;Jetzt wird auf das letzte verfügbare Service Pack 6a aktualisiert.&lt;/li&gt;
  &lt;li&gt;Danach werden die Virtual-PC Integration Tools eingespielt.
Diese brauchen nämlich SP6 bevor sie sich installieren lassen.&lt;/li&gt;
  &lt;li&gt;Und am Ende folgt noch der IE6 SP1 um NT4 auf die “letzte” Stufe vor
seinem Support-Ende zu bekommen. So erhält man zumindest ein paar
Verschlüsselungsroutinen in den Crypto-APIs, die zur Zeit der 
Veröffentlichung von NT4 nicht Teil des Standards waren.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nun konnte ich zuerst die GATE Tools auf den Host übertragen und von dort aus
weiter zur NT4 Installation.&lt;/p&gt;

&lt;p&gt;Beim ersten Start kam es noch zur Anzeige, dass ein Einsprungpunkt für eine
Systemfunktion nicht gefunden wurde, doch das war nur eine, die ich wohl 
vergessen hatte.&lt;br /&gt;
Das Problem war schnell gelöst und dann startete ich erfolgreich &lt;code&gt;gatecli&lt;/code&gt;
unter NT4.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ja, diese Retro-Erfahrung hat mir wieder sehr viel Spaß gemacht und ich 
wünschte, ich könnte sofort meine Sourcen zu meinem jüngeren Ich in die
Vergangenheit schicken.&lt;br /&gt;
Damals war Softwareentwicklung noch ein exotisches Neuland. Man freute sich
über jedes Steinchen am Wegrand und war froh einfach dabei zu sein.&lt;/p&gt;

&lt;p&gt;Der GATE Test belegt mir auf jeden Fall, dass das “Unabhängigkeitskonzept”
durchführbar ist und sich somit eine ganz neue Bandbreite von Zielplattformen
eröffnet.&lt;br /&gt;
Bin schon gespannt, ob ich dann demnächst unter Windows 98 auch Erfolge 
feiern kann.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>XRDP zum Debuggen</title>
   <link href="https://www.opengate.at/blog/2020/09/xrdp/"/>
   <published>2020-09-14T13:00:00+02:00</published>
   <updated>2020-09-14T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2020/09/xrdp</id>
   <category term="software" />
   <summary type="text">Seitdem mir vor einigen Jahren xrdp 
gezeigt wurde, wusste ich, dass ich damit glücklich werden kann.
Diese Implementierung des Microsoft 
Remote-Desktop-Protocols
für Linux verwandelt jede Installation in einen Terminalserver, den man 
grafisch über das Netzwerk fernsteuern kann.

Ganz besonders hilfreich ist diese Lösung für das Debuggen, wenn man eine
vollständige IDE
aus der Ferne bedienen kann.
</summary>
   <content type="html">&lt;p&gt;Seitdem mir vor einigen Jahren &lt;a href=&quot;https://en.wikipedia.org/wiki/Xrdp&quot;&gt;&lt;code&gt;xrdp&lt;/code&gt;&lt;/a&gt; 
gezeigt wurde, wusste ich, dass ich damit glücklich werden kann.&lt;br /&gt;
Diese Implementierung des Microsoft 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Remote_Desktop_Protocol&quot;&gt;Remote-Desktop-Protocols&lt;/a&gt;
für Linux verwandelt jede Installation in einen Terminalserver, den man 
grafisch über das Netzwerk fernsteuern kann.&lt;/p&gt;

&lt;p&gt;Ganz besonders hilfreich ist diese Lösung für das Debuggen, wenn man eine
vollständige &lt;a href=&quot;https://de.wikipedia.org/wiki/Integrierte_Entwicklungsumgebung&quot;&gt;IDE&lt;/a&gt;
aus der Ferne bedienen kann.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;xrdp-vs-x11-forwarding&quot;&gt;xrdp vs. X11-Forwarding&lt;/h3&gt;

&lt;p&gt;Unixianer belächeln den &lt;code&gt;xrdp&lt;/code&gt; Ansatz, weil sie seit Jahrzehnten die 
Möglichkeit kennen, dass &lt;a href=&quot;https://en.wikipedia.org/wiki/X_Window_System&quot;&gt;X11&lt;/a&gt; 
Protokoll über eine SSH Session zu tunneln und somit auf dem lokalen PC 
grafische Programme nutzen können, die auf einer anderen Maschine ausgeführt 
werden.&lt;/p&gt;

&lt;p&gt;Diese Variante habe ich öfters auch unter Microsoft Windows genutzt, vor allem
in Verbindung mit dem Programm &lt;a href=&quot;https://mobaxterm.mobatek.net/&quot;&gt;&lt;code&gt;MobaXterm&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Dennoch haben RDP Sitzung zu einem Linux-System für mich mehr Vorteile als die
Weiterleitung des X11 Protokolls:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Der RDP Client (&lt;code&gt;mstsc&lt;/code&gt;) ist seit Windows XP out-of-the-box dabei und man
braucht nichts weiteres am Client installieren.&lt;/li&gt;
  &lt;li&gt;Anzeigeelemente funktionieren im RDP-Sandkasten besser, z.B.: bedeuten
“Vollbild” oder “zentrieren” bei Mehr-Bildschirm-Systemen über X11 immer
nur Probleme.&lt;/li&gt;
  &lt;li&gt;RDP ist schneller.&lt;br /&gt;
Die “Bildschirmfotos” werden zwar mit geringerer Framerate übertragen, aber 
werden meist ohne Verzögerung angezeigt. X11 Grafikelemente übertragen 
jede Zeichenoperation separat und man kann bei langsamerer Netzwerkverbindung
gelangweilt zusehen, wie sich Linie für Linie gemächlich aufbaut.&lt;/li&gt;
  &lt;li&gt;Kontextmenüs erkennen in X11 oft den Bildschirmrand nicht.&lt;br /&gt;
Man öffnet ein Menü und dieses ragt über die Bildschirmkante hinaus. Womit
man nie die unteren Menüpunkte sehen oder auswählen kann. In RDP (also 
innerhalb der Linux-Umgebung), wird das erkannt und das Menü entsprechend 
verschoben.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;xrdp-k-develop-und-mehr&quot;&gt;xrdp, K-Develop und mehr&lt;/h3&gt;

&lt;p&gt;Innerhalb einer &lt;code&gt;xrdp&lt;/code&gt; Session nutze ich dann gerne K-Develop aus dem KDE 
Projekt, um Sourcen zu bauen und zu Debuggen. Syntaxhighlighting und 
IntelliSense funktionieren dort recht gut und man kann Breakpoints einfach
und bequem per Mauszeiger setzen.&lt;br /&gt;
Jeder, der sich schon mal per &lt;code&gt;gdb&lt;/code&gt; durch Exceptionhandler quälen musste,
lernt eine solche grafische IDE sehr zu schätzen.&lt;/p&gt;

&lt;p&gt;Am besten ist, dass K-Develop CMake Projekte unterstützt und somit das
GATE Projekt ohne Umschweife verwalten kann.&lt;/p&gt;

&lt;p&gt;Und natürlich kann man auch jede andere IDE und auch Visual Studio Code auf 
diese Weise zum Laufen bringen.&lt;/p&gt;

&lt;h3 id=&quot;installation&quot;&gt;Installation&lt;/h3&gt;

&lt;p&gt;Die Installation läuft über das Paket-Management System der Distribution.
Unterschiedlich ist, ob man etwas nachkonfigurieren muss.
Meistens muss man die Datei &lt;code&gt;/etc/xrdp/startwm.sh&lt;/code&gt; anpassen und den 
gewünschten Window-Manager dort starten (ansonsten sieht man nur ein
Konsolenfenster um Kommandos einzugeben). Man ersetzt dort am Ende die 
Zeile, die mit &lt;code&gt;exec&lt;/code&gt; beginnt.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Debian / Ubuntu:
    &lt;ul&gt;
      &lt;li&gt;xrdp Installation &lt;code&gt;apt install xrdp&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;Service starten: &lt;code&gt;/etc/init.d/xrdp start&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;xfce Installation: &lt;code&gt;apt install xfce4&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;Konfigurationsdatei: &lt;code&gt;/etc/xrdp/startwm.sh&lt;/code&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;SuSE:
    &lt;ul&gt;
      &lt;li&gt;xrdp Installation &lt;code&gt;zypper install xrdp&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;Service starten: &lt;code&gt;systemctl start xrdp&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;xfce Installation: &lt;code&gt;zypper in -t pattern xfce&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;Konfigurationsdatei: &lt;code&gt;/etc/xrdp/startwm.sh&lt;/code&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;FreeBSD:
    &lt;ul&gt;
      &lt;li&gt;xrdp Installation &lt;code&gt;pkg install xrdp&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;Service aktivieren:
        &lt;ul&gt;
          &lt;li&gt;&lt;code&gt;echo xrdp_enable=&quot;YES&quot; &amp;gt;&amp;gt; /etc/rc.conf&lt;/code&gt;&lt;/li&gt;
          &lt;li&gt;&lt;code&gt;echo xrdp_sesman_enable=&quot;YES&quot; &amp;gt;&amp;gt; /etc/rc.conf&lt;/code&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;xfce Installation: &lt;code&gt;pkg install xfce&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;Konfigurationsdatei: &lt;code&gt;/usr/local/etc/xrdp/startwm.sh&lt;/code&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;NetBSD und OpenBSD haben &lt;code&gt;xrdp&lt;/code&gt; leider nicht in ihren Repositories.&lt;/p&gt;

&lt;p&gt;Die Window-Manager Start-Scripts am Ende von &lt;code&gt;startwm.sh&lt;/code&gt; lauten wie folgt:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Gnome&quot;&gt;GNOME Desktop&lt;/a&gt;: &lt;code&gt;exec gnome-session&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/K_Desktop_Environment&quot;&gt;KDE&lt;/a&gt;: &lt;code&gt;exec startkde&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/MATE_Desktop_Environment&quot;&gt;MATE&lt;/a&gt;: &lt;code&gt;exec mate-session&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Cinnamon_(Desktop-Umgebung)&quot;&gt;Cinnamon&lt;/a&gt;: &lt;code&gt;exec cinnamon&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Xfce&quot;&gt;Xfce4&lt;/a&gt;: &lt;code&gt;exec startxfce4&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/LXDE&quot;&gt;LXDE&lt;/a&gt;: &lt;code&gt;exec startlxde&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;installation-unter-docker&quot;&gt;Installation unter Docker&lt;/h3&gt;

&lt;p&gt;Ja, auch das funktioniert. Man kann &lt;code&gt;xrdp&lt;/code&gt; und einen Window Manager auch in 
einem Docker Image installieren und dann den RDP-Port am Container freigeben.
So kann man sich dann per Remote Desktop in den laufenden Container verbinden
und arbeiten.&lt;/p&gt;

&lt;p&gt;Hier kann man also ohne eigene VM “mal schnell” ein Projekt in Docker 
auschecken, debuggen und das Ergebnis wieder zurückschreiben.&lt;br /&gt;
Es gibt zwei Spezialitäten:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;Man muss einen User-Account anlegen oder ein Root Passwort setzten, damit 
man sich per RDP auch einloggen kann.&lt;/li&gt;
  &lt;li&gt;Die Installation der GUI kann manchmal Eingaben verlangen, die man wegen
Docker deaktivieren muss. Unter Debian ruft man hierfür jeden &lt;code&gt;apt&lt;/code&gt; Befehl
mit der Environment Variable &lt;code&gt;DEBIAN_FRONTEND=noninteractive&lt;/code&gt; auf.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Mein &lt;code&gt;Dockerfile&lt;/code&gt; hierfür sie so aus.&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;FROM debian
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;# update download repository
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;RUN apt update
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;# install some system utilities
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;RUN apt install -y sudo mc nano wget curl
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;# install build tool chain
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;RUN apt install -y build-essential gdb cmake cmake-curses-gui git subversion
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;# install GUI environment
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;RUN DEBIAN_FRONTEND=noninteractive apt install -y xrdp lxde kdevelop mousepad
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;# create user &amp;quot;coder&amp;quot; with password &amp;quot;secret&amp;quot;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;RUN useradd -ms /bin/bash coder 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;RUN echo &amp;quot;coder:secret&amp;quot; | chpasswd 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;# allow user &amp;quot;coder&amp;quot; to run &amp;quot;sudo&amp;quot;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;RUN adduser coder sudo
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n21&quot; name=&quot;n21&quot;&gt;21&lt;/a&gt;&lt;/span&gt;RUN echo &apos;%sudo ALL=(ALL) NOPASSWD:ALL&apos; &amp;gt;&amp;gt; /etc/sudoers
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n22&quot; name=&quot;n22&quot;&gt;22&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n23&quot; name=&quot;n23&quot;&gt;23&lt;/a&gt;&lt;/span&gt;# switch to user account &amp;quot;coder&amp;quot; in container session
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n24&quot; name=&quot;n24&quot;&gt;24&lt;/a&gt;&lt;/span&gt;USER coder
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n25&quot; name=&quot;n25&quot;&gt;25&lt;/a&gt;&lt;/span&gt;WORKDIR /home/coder
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n26&quot; name=&quot;n26&quot;&gt;26&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n27&quot; name=&quot;n27&quot;&gt;27&lt;/a&gt;&lt;/span&gt;# on container startup -&amp;gt; load xrdp service
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n28&quot; name=&quot;n28&quot;&gt;28&lt;/a&gt;&lt;/span&gt;EXPOSE 3389
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n29&quot; name=&quot;n29&quot;&gt;29&lt;/a&gt;&lt;/span&gt;ENTRYPOINT sudo /etc/init.d/xrdp start &amp;amp;&amp;amp; /bin/bash
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;xrdp&lt;/code&gt; ist einfach ein super Werkzeug für Menschen wie mich, die mit
grafischen IDEs einfach besser auskommen als mit einer primitiven Konsole.&lt;/p&gt;

&lt;p&gt;Und die Idee, dass man sehr einfach einen Terminal-Server aufsetzen kann,
auf dem mehrere Leute arbeiten können, ist ja auch nicht schlecht.&lt;/p&gt;

&lt;p&gt;Ich habe dieses Tool leider viel zu spät kennengelernt.
Vor 15 Jahren hätte es das geben sollen!&lt;/p&gt;

&lt;p&gt;Der Punkt geht also an: “Früher war eben NICHT alles besser”&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Ich und BSD</title>
   <link href="https://www.opengate.at/blog/2020/09/bsd/"/>
   <published>2020-09-13T13:00:00+02:00</published>
   <updated>2020-09-13T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2020/09/bsd</id>
   <category term="software" />
   <summary type="text">Es ist wie die Idee von einem anderen Leben!

Hätte ich damals mit … wäre ich verheiratet mit …
würde im Haus von … und Geld wie … 
… und ganz bestimmt wäre alles viel besser.

So läuft meine Beziehung mit BSD. 
Ich träume davon, habe aber keine richtige.
</summary>
   <content type="html">&lt;p&gt;Es ist wie die Idee von einem anderen Leben!&lt;/p&gt;

&lt;p&gt;Hätte ich damals mit … wäre ich verheiratet mit …
würde im Haus von … und Geld wie … &lt;br /&gt;
… und ganz bestimmt wäre alles viel besser.&lt;/p&gt;

&lt;p&gt;So läuft meine Beziehung mit &lt;a href=&quot;https://de.wikipedia.org/wiki/Berkeley_Software_Distribution&quot;&gt;BSD&lt;/a&gt;. 
Ich träume davon, habe aber keine richtige.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Man kann es mit Latein vergleichen. Ich bin der festen Überzeugung dass nur
diese Sprache das Recht hätte zur globalen Weltsprache erhoben zu werden,
nicht dieses glitschige Englisch.&lt;/p&gt;

&lt;p&gt;Und genau so sollte ein BSD &lt;a href=&quot;https://de.wikipedia.org/wiki/Unix&quot;&gt;Unix&lt;/a&gt; alle
(nicht-Windows-) Server auskleiden und nicht dieses schmierige 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Warum kommen nicht alle anderen Menschen auch zu meiner korrekten Ansicht?&lt;/p&gt;

&lt;h3 id=&quot;bsd-als-os&quot;&gt;BSD als OS&lt;/h3&gt;

&lt;p&gt;Ich sehe den größten Vorteil der BSD-Distributionen in der Tatsache, dass sie
auf der &lt;a href=&quot;https://de.wikipedia.org/wiki/BSD-Lizenz&quot;&gt;BSD-Lizenz&lt;/a&gt; aufbauen und
weniger zersplittert sind wie die Linuxgemeinde.&lt;/p&gt;

&lt;p&gt;Die &lt;a href=&quot;https://de.wikipedia.org/wiki/GNU_General_Public_License&quot;&gt;GPL&lt;/a&gt; erweist 
sich in vielen Geschäftszweigen als absolutes Hindernis und schließt 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Open_Source&quot;&gt;OpenSource&lt;/a&gt; Software von solchen
Orten aus. Da die BSD-Lizenz kein &lt;a href=&quot;https://de.wikipedia.org/wiki/Copyleft&quot;&gt;CopyLeft&lt;/a&gt; 
erfordert, darf sie auch mit geschlossener Software gemischt verbreitet werden.&lt;/p&gt;

&lt;p&gt;Und dass es nicht hunderte Distributoren gibt, die mehr gegeneinander als 
miteinander arbeiten, macht es für die Softwareentwicklung auch einfach 
Standards zu etablieren.
(Na obwohl … da tun sich sogar schon zwischen 
&lt;a href=&quot;https://de.wikipedia.org/wiki/FreeBSD&quot;&gt;FreeBSD&lt;/a&gt;, 
&lt;a href=&quot;https://de.wikipedia.org/wiki/OpenBSD&quot;&gt;OpenBSD&lt;/a&gt; und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/NetBSD&quot;&gt;NetBSD&lt;/a&gt; Abgründe auf).&lt;/p&gt;

&lt;p&gt;Außerdem darf man nicht vergessen, dass Teile des Windows-Netzwerkstacks 
und das halbe &lt;a href=&quot;https://de.wikipedia.org/wiki/MacOS&quot;&gt;macOS&lt;/a&gt; auf BSD Code 
aufbauen … und das war sicher eine gute Entscheidung.&lt;/p&gt;

&lt;p&gt;Deshalb finde ich es Schade, dass ich noch nie ein BSD im produktiven
Einsatz erleben durfte.&lt;/p&gt;

&lt;h3 id=&quot;bsd-im-gate-projekt&quot;&gt;BSD im GATE Projekt&lt;/h3&gt;

&lt;p&gt;Das ist mein nächstes Ziel. Linux soll nicht die einzige POSIX Anbindung
im GATE Framework sein. Anstatt dessen sollen klassische UNIX Funktionen
zur Anwendung kommen.&lt;/p&gt;

&lt;p&gt;Das größte Problem sind Systeminformationen, die man in Linux “so einfach”
über das &lt;a href=&quot;https://de.wikipedia.org/wiki/Procfs&quot;&gt;procfs&lt;/a&gt; auslesen kann.&lt;br /&gt;
Das existiert in BSD grundsätzlich nicht (wenn gleich es bereits Bemühungen
gibt ein solches zu integrieren).&lt;/p&gt;

&lt;p&gt;Hier müsste man dann entweder auf native APIs ausweichen oder im schlimmsten
Fall externe Programm einsetzen um an die nötigen Infos zu kommen.&lt;/p&gt;

&lt;p&gt;… aber hey! Genau das ist der Zweck der Übung!&lt;br /&gt;
Ich möchte erfahren, wie andere Unix-Hersteller sich ihren Weg durch 
Anforderungen und Implementierungen bahnen und nicht immer nur unstete
Linux-Vorstellungen nachtippen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Und so hoffe ich also über den Umweg der Software-Entwicklung endlich mal mit
BSD näher zusammen zu kommen.&lt;br /&gt;
Es laufen ja schon ein paar Installationen auf meinem Hyper-V Server, doch
nun sollen die auch mal was “Sinnvolles” zu tun bekommen.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Rücken verrücken</title>
   <link href="https://www.opengate.at/blog/2020/09/backache/"/>
   <published>2020-09-06T13:00:00+02:00</published>
   <updated>2020-09-06T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2020/09/backache</id>
   <category term="general" />
   <summary type="text">Es war “nur” eine “fucking Kiste mit Büchern”.
Ich habe sie nur aus dem Keller ins Erdgeschoss getragen.

Doch die Frage war danach nicht, ob ich im Krankenstand bin, 
sondern wie lange …
</summary>
   <content type="html">&lt;p&gt;Es war “nur” eine “fucking Kiste mit Büchern”.&lt;br /&gt;
Ich habe sie nur aus dem Keller ins Erdgeschoss getragen.&lt;/p&gt;

&lt;p&gt;Doch die Frage war danach nicht, ob ich im Krankenstand bin, 
sondern wie lange …
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Schon seit der Kindheit dürfte bei mir eine leichte Wirbelverschiebung 
vorhanden sein, die mich etwas “schief” dastehen lässt.&lt;/p&gt;

&lt;p&gt;Das jahrelange Sitzen vor dem PC macht das natürlich nicht besser.&lt;/p&gt;

&lt;p&gt;Doch dieses Wochenende hat mich wieder den alten Spruch “spüren” lassen.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ein gesunder Mensch hat tausend Wünsche … ein kranker nur einen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Das Heben der Kiste war “nur” unangenehm, doch in der Folge wurde jede weitere
Bewegung schwieriger. Ich ging also wieder in meine Wohnung und legte mich
möglichst gerade ins Bett.&lt;/p&gt;

&lt;p&gt;Ich kann nicht in Worte fassen, welche Schmerzen sich in den folgenden 
Stunden ergeben haben. Nur absolut ruhig liegen verschaffte mir Linderung.&lt;/p&gt;

&lt;p&gt;Zum ersten Mal in meinem Leben habe ich darüber nachgedacht, bewusst ins
Bett zu pinkeln, nachdem mehrere Versuche irgendwie aufzustehen sich 
wie brutale Messerstiche in den Rücken anfühlten.&lt;/p&gt;

&lt;p&gt;Es bleibt einem die Luft weg. Das atmen ist schmerzhaft und alleine
das “Heben” eines Wasserglases wird zur Tortur.
Einen Laptop hochzuheben oder zu tragen war ausgeschlossen.&lt;/p&gt;

&lt;p&gt;Und als es nach der anstrengenden Nacht nicht besser wurde, wurde mir klar
… ich muss ins Krankenhaus. Also kroch ich erneut in einer elenden 
langsamen Prozedur aus dem Bett und schleppte mich ins Bad.
Ich wollte noch ein letzte mal Duschen, bevor ich mich um die “Abreise”
kümmern wollte.&lt;/p&gt;

&lt;p&gt;Und beim Einstieg in die Dusche passierte es:&lt;br /&gt;
Ein hörbares Knacken im Rücken, ein finaler Schmerz und plötzlich war der 
Leidensdruck weg. Oder sagen wir mal die Schmerzen gingen auf 10% zurück
und waren leicht erträglich.&lt;br /&gt;
Ich konnte wieder gehen, mich ins Bett legen und aufstehen, nur das Vorbeugen
führte zur Schmerzen (aber nicht vergleichbar mir vorher).&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Keine Ahnung was das war, vielleicht habe ich mir was “herausgedrückt” 
oder böse eingeklemmt …&lt;br /&gt;
Ich werde jedenfalls morgen zum Arzt gehen und abklären lassen, was das war 
und werde jede erdenkliche Vorkehrung treffen, dass sich dieser Schmerzfall nicht
wiederholt.&lt;/p&gt;

&lt;p&gt;Vor 15 Jahren hatte ich etwas Vergleichbares beim Schneeräumen. Auch da
konnte ich kaum gehen und die Schmerzen waren ein Alptraum, doch mein
Rücken richtete sich in 2 Wochen Bettruhe wieder ein.&lt;/p&gt;

&lt;p&gt;Eigentlich bin ich ein Idiot … ich weiß seit Jahren, dass mein Rücken
ein Problemfall ist bzw. werden wird. Aber offenbar muss immer erst etwas
passieren, bevor man aktiv wird.&lt;/p&gt;

&lt;p&gt;Diesen Fingerzeig nehme ich aber auf jeden Fall ernst …&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>OpenGL im RDP</title>
   <link href="https://www.opengate.at/blog/2020/08/opengl/"/>
   <published>2020-08-30T13:00:00+02:00</published>
   <updated>2020-08-30T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2020/08/opengl</id>
   <category term="devel" />
   <summary type="text">Oft habe ich in der Vergangenheit mit Grafik-Entwicklern über das Thema 
OpenGL in RDP
Sitzungen gestritten.
Die sagen nämlich: “Das geht nicht.”

“Das geht sehr wohl” lautet dann mein Widerspruch.


  Nein! Doch! Ohh!


</summary>
   <content type="html">&lt;p&gt;Oft habe ich in der Vergangenheit mit Grafik-Entwicklern über das Thema 
&lt;a href=&quot;https://de.wikipedia.org/wiki/OpenGL&quot;&gt;OpenGL&lt;/a&gt; in &lt;a href=&quot;https://de.wikipedia.org/wiki/Remote_Desktop_Protocol&quot;&gt;RDP&lt;/a&gt;
Sitzungen gestritten.&lt;br /&gt;
Die sagen nämlich: “Das geht nicht.”&lt;/p&gt;

&lt;p&gt;“Das geht sehr wohl” lautet dann mein Widerspruch.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Nein! Doch! Ohh!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Zwischendurch ein kurzer Ausschnitt zur bekannten “Nein! Doch! Ohh!” Szene
von &lt;a href=&quot;https://de.wikipedia.org/wiki/Louis_de_Fun%C3%A8s&quot;&gt;Louis de funess&lt;/a&gt;&lt;/p&gt;

&lt;iframe width=&quot;640&quot; height=&quot;360&quot; src=&quot;/blog/redirect.html?https%3A%2F%2Fwww.youtube-nocookie.com%2Fembed%2Fw4aLThuU008&quot; frameborder=&quot;1&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;

&lt;p&gt;Nun, wenn ich von OpenGL spreche, meine ich OpenGL 1.1 und nicht 
“das inkompatible moderne Zeug”, das heute als OpenGL 2,3,4 oder EmbeddedGL 
verkauft wird.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Shader&quot;&gt;Shader&lt;/a&gt; liefen unter Windows bis 
Version 8 nicht in RDP Sitzungen. Wie es heute aussieht, weiß ich nicht, 
aber es könnte sich vielleicht mal die Gelegenheit für ein paar Tests bieten.&lt;/p&gt;

&lt;p&gt;“Reguläre” OpenGL 1.1 Programme laufen jedenfalls üblicherweise auch nicht 
innerhalb von Remote-Desktopsitzungen, weil ihnen die APIs bei der 
Initialisierung der Zeichenoberfläche Fehler liefern.&lt;/p&gt;

&lt;p&gt;Aber:&lt;br /&gt;
Windows unterstützt ja einen OpenGL 1.1 Software-Renderer und dieser könnte
in solchen “virtuellen” Sitzungen ja sofort übernehmen, womit auch in RDP
Sitzungen OpenGL Code Grafik produzieren kann … nur eben viel langsamer.&lt;/p&gt;

&lt;p&gt;Die Initialisierung schlägt aber aus einem recht trivialen Grund meist fehl:&lt;br /&gt;
&lt;em&gt;Die Erwartungen an RDP sind zu hoch!&lt;/em&gt;&lt;/p&gt;

&lt;h3 id=&quot;16-bit-oder-weniger-müssen-reichen&quot;&gt;16 bit oder weniger müssen reichen!&lt;/h3&gt;

&lt;p&gt;Fast jeder OpenGL Code will per &lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-pixelformatdescriptor&quot;&gt;&lt;code&gt;PIXELFORMATDESCRIPTOR&lt;/code&gt;&lt;/a&gt;
mindestens 24 bits pro Pixel (also True-Color Qualität) ansteuern.&lt;br /&gt;
Aber der klassische virtuelle RDP-Grafik-Treiber ist nicht für mehr als 16 bit
ausgelegt. Windows 8 und 10 schaffen hier offenbar mehr, aber ob das immer so
ist, lässt sich schwer garantieren.&lt;/p&gt;

&lt;p&gt;In meinen Tests konnte ich mit der Änderungen auf 
&lt;code&gt;pixelformatdescriptor.cColorBits = 16&lt;/code&gt; unmittelbar zum gewünschten Ergebnis 
gelangen: Man erhält einen OpenGL-Software-Render-Kontext und kann darauf 
Zeichen … und es wird auch alles davon am Schirm sichtbar.&lt;/p&gt;

&lt;p&gt;Es macht also Sinn in der Liste der unterstützten Pixel-Formate die 
Anforderungen zu senken, und schon bekommt man ein Format zugeordnet, das 
auch in einer RDP Sitzung sofort lauffähig ist.&lt;/p&gt;

&lt;h3 id=&quot;gldrawarrays-verbindet-die-welten&quot;&gt;glDrawArrays() verbindet die Welten&lt;/h3&gt;

&lt;p&gt;Ein häufiges Argument gegen OpenGL 1.1 ist, dass sein Code nicht kompatibel
mit neueren GL Versionen ist.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;code&gt;glBegin()&lt;/code&gt; und &lt;code&gt;glEnd()&lt;/code&gt; gibt es nicht mehr!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;heißt es dann.&lt;/p&gt;

&lt;p&gt;Ja stimmt, es gibt aber noch die Funktion &lt;a href=&quot;http://docs.microsoft.com/en-us/windows/win32/opengl/gldrawarrays&quot;&gt;&lt;code&gt;glDrawArrays()&lt;/code&gt;&lt;/a&gt;, 
mit der man sehr viel machen kann, was man früher zwischen &lt;code&gt;glBegin()&lt;/code&gt; 
und &lt;code&gt;glEnd()&lt;/code&gt; geschrieben hat. Man setzt zuerst mit &lt;code&gt;glVertexPointer()&lt;/code&gt; die 
Punkte, ordnet per &lt;code&gt;glColorXX()&lt;/code&gt; die Farben zu und &lt;code&gt;glDrawArrays()&lt;/code&gt; zeichnet 
die Dreiecke, Polygone usw. auf die Oberfläche.&lt;/p&gt;

&lt;p&gt;Und schon haben wir eine Codebase, die mit OpenGL 1.1 genau so gut läuft, wie
mit OpenGL 2, 3 oder 4.&lt;/p&gt;

&lt;p&gt;Auch Texturen funktionieren in GL 1.1 super … sie haben nur die 
Einschränkung von maximal 1024 Pixel in ihren Dimensionen … aber mal 
ehrlich, wer so große Bilder braucht, kann sie auch auf ein paar Stücke 
zerteilen.&lt;/p&gt;

&lt;h3 id=&quot;unflexible-implementierungen&quot;&gt;Unflexible Implementierungen&lt;/h3&gt;

&lt;p&gt;Tatsächlich ärgere ich mich oft über Software, die - aus meiner Sicht - 
grundlos nicht RDP-tauglich ist, oder auf älteren Systemen oder Systemen
ohne aktuellen OpenGL Treiber nicht läuft.&lt;/p&gt;

&lt;p&gt;Bestes Beispiel ist die Software meines alten &lt;a href=&quot;https://de.wikipedia.org/wiki/3D-Druck&quot;&gt;3D-Druckers&lt;/a&gt;. 
Diese ist extrem primitiv und kann nur Modelle auf den Bildschirm zeichnen
und die ganze Ansicht drehen.&lt;/p&gt;

&lt;p&gt;Das kann man mit der Fixed-Function-Pipeline von OpenGL 1.1 wunderbar 
abdecken. Leider erwartet die Software aber zwingend OpenGL 2 oder 3 
mit Shadern, womit sie gleich unter folgenden Umgebungen &lt;em&gt;nicht&lt;/em&gt; läuft:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Alte Intel Onboard-Grafikkarten unterstützen nur OpenGL 1.4 per Treiber&lt;/li&gt;
  &lt;li&gt;Systeme ohne speziellen Grafiktreiber, z.B. Server-Boards&lt;/li&gt;
  &lt;li&gt;RDP Sitzungen&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ich kann daher wegen eines OpenGL-Fehlers nicht eines meiner alten 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Intel_Atom&quot;&gt;Intel-Atom&lt;/a&gt; Systeme als 3D-Druck
Dienststation einsetzen, die aus der Ferne bedient wird.&lt;/p&gt;

&lt;p&gt;Tatsächlich wäre aber nicht viel Programmierarbeit notwendig um die Software
hier lauffertig zu bekommen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Eine gute Software passt sich an das System an und stellt nicht Anforderungen,
die sie gar nicht braucht.
Man kann den 16-bit Farbmodus ja auch nur als Probier-Option vorsehen und 
bessere Grafikmodi im Nachgang oder Voraus prüfen und nur im RDP-Fall wird
dann zum 16-bit Fallback gewechselt.&lt;/p&gt;

&lt;p&gt;Niemand kann mir heute glaubhaft erzählen, dass Grafik NUR mit neuen 
OpenGL Standards funktioniert.&lt;br /&gt;
Denn wer sich an vor 2000 erinnert, an die Zeit von &lt;a href=&quot;https://de.wikipedia.org/wiki/Half-Life&quot;&gt;Half-Life-1&lt;/a&gt;, 
der weiß, dass man mit OpenGL auch mit Software-Rendering hoch komplexe 
3D-Landschaften abbilden konnte.&lt;/p&gt;

&lt;p&gt;Und heute erklärt mir eine CAD-Anwendung, dass sie wegen der Pixel-Bits in
Software kein 10x10cm Arduino-Case rendern kann?&lt;/p&gt;

&lt;p&gt;Nee … das muss nicht sein!&lt;br /&gt;
Es geht!&lt;br /&gt;
Man muss sich nur Mühe bei der Entwicklung geben!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>IP Sicherheitskameras</title>
   <link href="https://www.opengate.at/blog/2020/08/security-camera/"/>
   <published>2020-08-29T13:00:00+02:00</published>
   <updated>2020-08-29T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2020/08/security-camera</id>
   <category term="hardware" />
   <summary type="text">Aus gegebenem Anlass teste ich gerade eine IP Kamera, 
die in Zukunft den Eingangsbereich am Zweitwohnsitz “im Auge behalten” soll.

Wie viel Sicherheit kann man mit einem niederpreisigem Gerät erreichen?
</summary>
   <content type="html">&lt;p&gt;Aus gegebenem Anlass teste ich gerade eine &lt;a href=&quot;https://de.wikipedia.org/wiki/Netzwerkkamera&quot;&gt;IP Kamera&lt;/a&gt;, 
die in Zukunft den Eingangsbereich am Zweitwohnsitz “im Auge behalten” soll.&lt;/p&gt;

&lt;p&gt;Wie viel Sicherheit kann man mit einem niederpreisigem Gerät erreichen?
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Mit dem Thema “Sicherheit” wurde immer schon viel Geld verdient. Und wenn sich
der Verdacht häuft, dass “dunkle Gestalten” nahe am Wohnort herumlungern, kann
es nicht schaden - so denkt der besorgte Bürger - wenn ein digitaler Wächter
alles im Blick behält.&lt;/p&gt;

&lt;p&gt;Ab 15 Euro beginnen die Angebote für Kameras im Haus, die man über das Netz 
abfragen kann und ab 35 Euro erhält man “wasserfeste” Modelle, die von der 
Außenwand Bilder der Umgebung aufzeichnen.&lt;/p&gt;

&lt;p&gt;Ich habe mir mal so ein Einsteigermodell zusenden lassen um es mal in meiner
Wohnung zu testen, bevor es am Zielort montiert wird.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/ip-camera.jpg&quot; alt=&quot;IP Security Camera&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;nachsicht&quot;&gt;Nachsicht&lt;/h3&gt;

&lt;p&gt;“&lt;a href=&quot;https://de.wikipedia.org/wiki/Nachtsichtger%C3%A4t&quot;&gt;Nachtsicht&lt;/a&gt;” 
(Nightvision) ist hier die wichtigste Funktion und eine eben solche ist 
tatsächlich integriert und funktioniert auf den ersten Blick ganz gut.
Ich konnte auf Distanzen von 5 Metern einen dunklen Raum gut aufzeichnen
und am Monitor bzw. der Smartphone-App jede Bewegung mitverfolgen.&lt;/p&gt;

&lt;p&gt;Laut Infoblatt sollen 10 Meter drinnen sein, doch das werde ich wohl erst 
am endgültigen Montageort überprüfen können.&lt;/p&gt;

&lt;p&gt;Fenster sind leider ein natürliches Hindernis für die Nachtsichtfunktion.
Bei Tag kann man zwar relativ problemlos von innen nach außen blicken, 
doch nachts spiegelt das Glas so intensiv zurück, dass man von der Umgebung
nichts mehr wahrnehmen kann.&lt;br /&gt;
Eine “echte” Außeninstallation ist also erforderlich.&lt;/p&gt;

&lt;h3 id=&quot;schnittstellen&quot;&gt;Schnittstellen&lt;/h3&gt;

&lt;p&gt;IP-Cam bedeutet Netzwerk. Mein Modell kann über &lt;a href=&quot;https://de.wikipedia.org/wiki/Wireless_Local_Area_Network&quot;&gt;WLAN&lt;/a&gt;
erreicht werden, stellt aber auch eine &lt;a href=&quot;https://de.wikipedia.org/wiki/Local_Area_Network&quot;&gt;LAN&lt;/a&gt; 
RJ45 Buchse bereit. Und dieses Feature zahlt sich meines Erachtens aus.
Ein WLAN “out-of-the-box” Setup ist zwar vorgesehen, in dem die Kamera zuerst
als Access-Point mit einem Standard-Passwort hochfährt und dann umkonfiguriert
werden kann um sich ins bestehende Heim-WLAN zu verbinden, doch wenn es hier
Änderungen gibt, würde immer nur ein Rücksetzen auf den Werkzustand helfen.&lt;/p&gt;

&lt;p&gt;Per LAN kann man einfach seinen Laptop anschließen, und sofort auf die Kamera
per Browser zugreifen und ihre Einstellungen abändern.&lt;/p&gt;

&lt;p&gt;Ein anderes Problem offenbarte sich nach ein paar Tagen, als Kamera und WLAN
Router einfach nicht mehr miteinander reden wollten. Hierfür musste ich beide
Geräte neustarten.&lt;br /&gt;
Das heißt also in der Praxis: Man sollte täglich sowohl WLAN-Router als auch
die Kamera durchstarten lassen, damit man eventuelle Kommunikationshänger
wegbekommt.&lt;/p&gt;

&lt;p&gt;Wenn man dann noch eine &lt;a href=&quot;https://de.wikipedia.org/wiki/SD-Karte&quot;&gt;SD-Karte&lt;/a&gt; 
einsetzt lassen sich Aufnahmen auch direkt auf der Kamera speichern und dann
als Video-Datei herunterladen.&lt;br /&gt;
Das ist schon mal nicht schlecht … ansonsten müsste man zwecks 
“Beweisführung” stets ein anderes System mitlaufen lassen, das aufzeichnet.
Die Aufzeichnung lässt sich auch auf “nur bei Bewegungserkennung” einstellen.
Aber ob dann jedes vom Baum fallende Blatt ebenso einen Schnappschuss auslöst,
werden wir erst in der Praxis feststellen können.&lt;/p&gt;

&lt;h3 id=&quot;software&quot;&gt;Software&lt;/h3&gt;

&lt;p&gt;Am meisten ärgert es mich, wenn man “richtige” Software nur noch für 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Android_(Betriebssystem)&quot;&gt;Android&lt;/a&gt;
Smartphones bekommt, und dort auch noch Anforderungen gestellt werden.
Und das war auch hier der Fall.&lt;/p&gt;

&lt;p&gt;Die “App” ist zwar gut aufgebaut und unterstützt das Suchen und Finden der 
Kamera im Netz, fordert aber alle möglichen Rechte auf dem Gerät ein und lässt
mich mit dem Eindruck zurück, ich hätte dem Hersteller nun Haus und Hof
geöffnet.&lt;/p&gt;

&lt;p&gt;Positiv ist aber der Bewegungsalarm, der je nach Einstellung laut oder leise
mitteilt, dass die Kamera eine Bewegung aufgezeichnet hat.&lt;/p&gt;

&lt;p&gt;Zwar lässt sich die Kamera auch im Browser vom PC aus steuern, aber hier gibt
es einige Nachteile:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Ein Live-Video braucht &lt;a href=&quot;https://de.wikipedia.org/wiki/Adobe_Flash&quot;&gt;Flash&lt;/a&gt; 
Support im Browser. Echt jetzt? Flash? Im Jahr 2020?&lt;/li&gt;
  &lt;li&gt;Man kann die Kamera natürlich nicht “suchen lassen”, sondern muss per 
Datenblatt ein WLAN mit entsprechendem Namen verbinden und dann die
Standard-IPs im Browser abtippen.&lt;/li&gt;
  &lt;li&gt;Eine Bewegungserkennung mit Benachrichtigung gibt es hier natürlich auch nicht.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Warum gibt es nicht ein kleine klassische GUI Anwendung, die ähnliche Features 
wie die Smartphone-App bereitstellt.
Ein solches Tool könnte man doch leicht z.B.: mit &lt;a href=&quot;https://de.wikipedia.org/wiki/Qt_(Bibliothek)&quot;&gt;QT&lt;/a&gt;
für Windows und Linux entwickeln und beilegen.
… doch leider … solche Funktionen findet man offenbar selten.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Mit 1020p liefert das Modell ordentliche Bilder und hat meine Anforderungen 
erfüllt. Besonders die Nachtsicht, die ich anfangs angezweifelt habe, hat mich
überrascht.&lt;/p&gt;

&lt;p&gt;Bin schon gespannt, ob sich das Teil im Echteinsatz auch behaupten können wird.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Mobiles WLAN</title>
   <link href="https://www.opengate.at/blog/2020/08/mobile-wifi/"/>
   <published>2020-08-23T13:00:00+02:00</published>
   <updated>2020-08-23T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2020/08/mobile-wifi</id>
   <category term="hardware" /><category term="software" />
   <summary type="text">Mobiles WLAN 
… moment, das haben wird doch schon … nennt sich Tethering
und wird heute von fast jedem Smartphone unterstützt.

Aber … ich will nicht mein “Telefon” leer saugen, wenn mein Laptop, meine
Nintendo Switch oder mein ESP8266 
ins Netz gehen will …
</summary>
   <content type="html">&lt;p&gt;Mobiles &lt;a href=&quot;https://de.wikipedia.org/wiki/Wireless_Local_Area_Network&quot;&gt;WLAN&lt;/a&gt; 
… moment, das haben wird doch schon … nennt sich &lt;a href=&quot;https://de.wikipedia.org/wiki/Tethering&quot;&gt;Tethering&lt;/a&gt;
und wird heute von fast jedem Smartphone unterstützt.&lt;/p&gt;

&lt;p&gt;Aber … ich will nicht mein “Telefon” leer saugen, wenn mein Laptop, meine
Nintendo Switch oder mein &lt;a href=&quot;https://de.wikipedia.org/wiki/ESP8266&quot;&gt;ESP8266&lt;/a&gt; 
ins Netz gehen will …
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/AliExpress&quot;&gt;AliExpress&lt;/a&gt; hat für alles eine 
kostengünstige Lösung und die heißt dann “Mobile Router” oder “Mobile WIFI” 
und kostet zwischen 30 und 40 Euro. (Wie immer gibt es beim Preis nach oben 
keine Grenze für Mehr-Funktionen-Modelle.)&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/mobile-wifi.jpg&quot; alt=&quot;Mobile-WIFI&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Es sind kleine Geräte mit Akku, in die man eine &lt;a href=&quot;https://de.wikipedia.org/wiki/SIM-Karte&quot;&gt;SIM-Karte&lt;/a&gt;
steckt und die dann ein kleines WLAN für ein paar Nutzer aufbaut.&lt;/p&gt;

&lt;p&gt;Ein solches Teil nenne ich nun auch mein Eigen und möchte somit das Chaos 
um die SIM-Karte beenden, in dem ich mir einfach eine weitere für die oben
genannten Zwecke zugelegt habe.&lt;/p&gt;

&lt;p&gt;Das tolle an meinem Modell ist, dass es beim Anschließen per USB an den PC
dort als LAN Adapter erkannt wird, womit immer die Möglichkeit der 
Konfiguration über ein virtuelles LAN besteht.&lt;/p&gt;

&lt;p&gt;Per Browser lassen sich die Zugangsdaten des Providers einpflegen, sowie 
SSID und Passwort des WLANs konfigurieren.&lt;/p&gt;

&lt;p&gt;Im Anschluss stellt der kleine Zwerg meist selbst die Verbindung zum 
mobilen Breitbandanbieter her und fährt das WLAN hoch, womit sich die ersten
Geräte schon verbinden und im Netz surfen können.&lt;/p&gt;

&lt;p&gt;Etwas problematisch war mancherorts die Empfangsqualität. Riss die Verbindung 
ab, konnte sie nicht immer automatisch wiederaufgebaut werden.&lt;/p&gt;

&lt;p&gt;Man kann natürlich (auch über WLAN) die Admin-Webseite aufrufen und dort den
Verbindungsaufbau manuell auslösen. Diese “Schnittstelle” ist in sofern 
interessant, als dass man natürlich auch ein kleines Programm schreiben könnte,
das die entsprechenden Requests zum Auslesen des Verbindungsstatus und zum
Initiieren einer neuen Verbindung absetzen kann.&lt;/p&gt;

&lt;p&gt;Die &lt;code&gt;F12&lt;/code&gt; Entwickleransicht in fast jedem Browser liefert einem diese Requests 
als einfache &lt;a href=&quot;https://de.wikipedia.org/wiki/JavaScript_Object_Notation&quot;&gt;JSON&lt;/a&gt;
Datensätze auf dem Servierteller.&lt;/p&gt;

&lt;p&gt;Ein weiteres “interessantes” Feature ist die Unterstützung einer &lt;a href=&quot;https://de.wikipedia.org/wiki/MicroSD&quot;&gt;microSD Karte&lt;/a&gt;
, auf der Dateien abgelegt mit den WLAN-Nutzern geteilt werden können.
Diese müssen nur die Admin-Webseite aufrufen und können die hinterlegten
Dateien auch ohne Passwort über den Browser herunterladen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Alles in allem ein nettes kleines Spielzeug.
Da weder mein Tablet noch mein Laptop einen SIM-Karten-Slot hat und ich 
auch ständig zwischen den Geräten hin- und herwechsle, war es immer ein Graus,
stets am Smartphone das “Internet zu teilen”.&lt;/p&gt;

&lt;p&gt;Mit dem kleinen WIFI-Router im Rucksack können sich und meine Begleiter 
sowohl im Auto also auch im WLAN-freien Restaurant jederzeit das Netz nutzen
um Nachrichten zu lesen oder zu versenden.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Scherztabletten</title>
   <link href="https://www.opengate.at/blog/2020/08/fun-pills/"/>
   <published>2020-08-22T13:00:00+02:00</published>
   <updated>2020-08-22T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2020/08/fun-pills</id>
   <category term="general" /><category term="retro" />
   <summary type="text">Manchmal sind es die “einfachen” Dinge, die einen erfreuen.

Wir leben in einer Welt, in der gefühlt jeder zweite glaubt ohne 
Antidepressiva nicht leben
zu können.

Und daher freut es mich, dass ein paar Leute dieses Thema auf lustige
Weise aufgreifen.
</summary>
   <content type="html">&lt;p&gt;Manchmal sind es die “einfachen” Dinge, die einen erfreuen.&lt;/p&gt;

&lt;p&gt;Wir leben in einer Welt, in der gefühlt jeder zweite glaubt ohne 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Antidepressivum&quot;&gt;Antidepressiva&lt;/a&gt; nicht leben
zu können.&lt;/p&gt;

&lt;p&gt;Und daher freut es mich, dass ein paar Leute dieses Thema auf lustige
Weise aufgreifen.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;blockquote&gt;
  &lt;p&gt;INFO: Ich werde von niemandem bezahlt oder genötigt, Produkte zu bewerben.
Ich möchte auch nichts bewerben oder beurteilen.
Im folgenden Text schildere ich nur, was mir neulich “passiert” ist.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Also, ich stehe beim Billig-Shop mit dem gelben “T” auf blauem Hintergrund
an der Kassa und entdecke zufällig bei den dort gestapelten Süßigkeiten 
eine Sammlung von scheinbaren Medikamentenschachteln.&lt;/p&gt;

&lt;p&gt;Ich wundere mich noch, dass jetzt auch hier schon irgend welche “Pillen”
verkauft werden, als ich bemerke, dass die Packungen mit lustigen Sprüchen 
bedruckt sind.&lt;/p&gt;

&lt;p&gt;Titel wie:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Anti-Vollpfosten Pille:&lt;br /&gt;
Wirkt gegen anhaltende Dummheit&lt;/li&gt;
  &lt;li&gt;Scheißegal Pille:&lt;br /&gt;
Für Gleichgültigkeit in jeder Situation&lt;/li&gt;
  &lt;li&gt;Anti-Stress Pille:&lt;br /&gt;
Wirkt bei jeglichen Arten von Stress&lt;/li&gt;
  &lt;li&gt;Geh-mir-nicht-auf-den-Sack Pille:&lt;br /&gt;
Wirkt gegen nervtötende Menschen&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;zauberten ein andauerndes Lächeln auf mein Gesicht.&lt;/p&gt;

&lt;p&gt;Für eine solche gute und lustige Idee war ein Vorratskauf gerechtfertigt.
Ich habe mir also von jeder Packung eine genommen.&lt;/p&gt;

&lt;p&gt;In den Schachteln befindet sich die für Medikamente übliche Aluminium-Folie,
aus der man die Pillen “herausdrücken” kann.&lt;/p&gt;

&lt;p&gt;Die Pillen selbst sind rote Schokolinsen und ich kann bestätigen,
dass nach der Einnahme dieser Medikation wirklich “alles besser wird”.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Ja, mit etwas Spaß wird das Leben auch schöner. Und vielleicht würde so 
mancher auf ein richtiges “hartes” Medikament zur Beruhigung verzichten 
können, wenn ihm ein solches Scherzprodukt sprichwörtlich “den Tag versüßt”.&lt;/p&gt;

&lt;p&gt;Also Daumen hoch und 5 Sterne für diese Produktidee!&lt;/p&gt;

&lt;p&gt;Mal sehen wie gut es in meiner Firma ankommt, wenn ich die 
“Anti-Vollpfosten Pille” meinen Kollegen anbiete. 
… hey, ein bisschen Spaß muss sein!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>TLS Fehler in SVN</title>
   <link href="https://www.opengate.at/blog/2020/08/svn-tls/"/>
   <published>2020-08-16T13:00:00+02:00</published>
   <updated>2020-08-16T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2020/08/svn-tls</id>
   <category term="software" />
   <summary type="text">Wenn man nach einen Upgrade auf Debian
10 oder Ubuntu 20.04 folgenden Fehler
vor die Füße geworfen bekommt


  svn: E170013: Unable to connect to a repository at URL ‘https://…’
svn: E120171: Error running context: An error occurred during SSL communication


dann heißt es einmal: “Nicht aufregen und sehr viel tief durchatmen.”

</summary>
   <content type="html">&lt;p&gt;Wenn man nach einen Upgrade auf &lt;a href=&quot;https://de.wikipedia.org/wiki/Debian&quot;&gt;Debian&lt;/a&gt;
10 oder &lt;a href=&quot;https://de.wikipedia.org/wiki/Ubuntu&quot;&gt;Ubuntu&lt;/a&gt; 20.04 folgenden Fehler
vor die Füße geworfen bekommt&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;svn: E170013: Unable to connect to a repository at URL ‘https://…’&lt;br /&gt;
svn: E120171: Error running context: An error occurred during SSL communication&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;dann heißt es einmal: “Nicht aufregen und sehr viel tief durchatmen.”&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Herr Gott noch mal, bin ich angefressen!&lt;br /&gt;
Da bemüht man sich redlich eine vollständige &lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt;
Build-Umgebung aufzubauen und am Ende hat man dann einen 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Apache_Subversion&quot;&gt;SVN&lt;/a&gt;
&lt;a href=&quot;https://de.wikipedia.org/wiki/Transport_Layer_Security&quot;&gt;TLS&lt;/a&gt; Fehler vor sich,
der alles wieder zunichte macht.&lt;/p&gt;

&lt;p&gt;Das Problem diesmal: Der SVN Server ist ZU ALT und unterstützt nicht die 
neuesten SSL/TLS Technologien, womit die Kommunikation mit ihm immer fehlschlägt.&lt;/p&gt;

&lt;h3 id=&quot;downgrade-oder-downgrade&quot;&gt;Downgrade oder downgrade?&lt;/h3&gt;

&lt;p&gt;Nachdem mir Spielereien mit Konfigurationen nicht geholfen haben, bleiben 2
Möglichkeiten:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Man wechselt zu einem älteren Betriebssystem mit älteren SSL-Anforderungen.&lt;/li&gt;
  &lt;li&gt;Man installiert ein älteres SSL-System auf dem neueren Betriebssystem.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Anfangs startete ich mit Punkt 2 und suchte nach Paketen mit &lt;a href=&quot;https://de.wikipedia.org/wiki/OpenSSL&quot;&gt;OpenSSL&lt;/a&gt;
1.1.0 und 1.0.2. Doch deren Installation bewegten &lt;code&gt;svn&lt;/code&gt; nicht dazu die ältere
Option zu nutzen.&lt;/p&gt;

&lt;p&gt;Am Ende habe ich aufgegeben und den ersten Weg gewählt, weil das Setup von 
Debian 9 in einer &lt;a href=&quot;https://de.wikipedia.org/wiki/Virtuelle_Maschine&quot;&gt;VM&lt;/a&gt; auch
nur 15 Minuten dauert und ich vorher schon Stunden mit Paket-Installationen 
verbraten hatte.&lt;/p&gt;

&lt;p&gt;In sofern kann ich für Testzwecke und Build-Systeme diesen Weg empfehlen.
Es ist nach meiner Erfahrung leichter ein älteres System mit neuen Compilern
auszustatten, als ein neueres System mit älteren Sicherheits-Funktionen.&lt;/p&gt;

&lt;h3 id=&quot;wie-es-trotzdem-funktionieren-könnte&quot;&gt;Wie es trotzdem funktionieren könnte&lt;/h3&gt;

&lt;p&gt;Ich habe diesen Weg zwar nicht weiter überprüft, aber vermute, dass man durch
das Kompilieren einer älteren OpenSSL Version und deren Installation
per &lt;code&gt;make install&lt;/code&gt; Script gefolgt von &lt;code&gt;ldconfig -v&lt;/code&gt; eine kompatiblere
SSL-Version verfügbar hätte.&lt;/p&gt;

&lt;p&gt;Womöglich ist es auch noch erforderlich &lt;code&gt;svn&lt;/code&gt; neu zu kompilieren, denn auch 
dessen Sourcen sind im Netz zu finden.&lt;/p&gt;

&lt;p&gt;Parallel habe ich einige Hinweise gefunden, die verlangten die Option
&lt;code&gt;disable-tls1_1&lt;/code&gt; aus den Build-Rules zu entfernen.&lt;br /&gt;
Bei den original Sourcen der Distribution hatte ich damit zwar keinen Erfolg
aber vielleicht wäre der Weg zum Ziel nicht mehr weit gewesen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Wie auch immer … ich hasse es, wertvolle Lebenszeit mit solchen dummen 
Protokollspielereien zu vergeuden.&lt;br /&gt;
Viele Software-Features altern und werden standardmäßig deaktiviert.
Doch diese lassen sich per Kommandozeile meistens wiederbeleben.&lt;/p&gt;

&lt;p&gt;Warum SSL hier eine Ausnahme macht, verstehe ich nicht.
Hmm … gut, eigentlich verstehe ich es schon: Man möchte bewusst die alten
SSL/TLS Standards aussterben lassen.&lt;/p&gt;

&lt;p&gt;Aber im industriellen Bereich und leider auch an meinem Arbeitsplatz gehört
das Arbeiten mit alten Systemen zum Alltag.&lt;/p&gt;

&lt;p&gt;Und da sind solche “Störungen” eben kein Vergnügen.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Unhinged - außer Kontrolle</title>
   <link href="https://www.opengate.at/blog/2020/08/unhinged/"/>
   <published>2020-08-16T00:00:00+02:00</published>
   <updated>2020-08-16T00:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2020/08/unhinged</id>
   <category term="entertainment" />
   <summary type="text">Heute ist es endlich mal wieder so weit. Ich geh’ ins Kino.
Es ist fast 8 Monate her, als ich mit Star Wars 9
das letzte Mal vor der großen Leinwand saß.

Auch diese Erfahrung hat uns Corona COVID-19
das letzte halbe Jahr vermiest.
</summary>
   <content type="html">&lt;p&gt;Heute ist es endlich mal wieder so weit. Ich geh’ ins Kino.
Es ist fast 8 Monate her, als ich mit &lt;a href=&quot;/blog/2019/12/star-wars/&quot;&gt;Star Wars 9&lt;/a&gt;
das letzte Mal vor der großen Leinwand saß.&lt;/p&gt;

&lt;p&gt;Auch diese Erfahrung hat uns &lt;a href=&quot;https://de.wikipedia.org/wiki/COVID-19-Pandemie&quot;&gt;Corona COVID-19&lt;/a&gt;
das letzte halbe Jahr vermiest.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Angefangen hat alles wie üblich.
Im Bus sitzen alle mit den typischen Mundschutzmasken und wenn möglich sitzt 
man alleine und nicht zu Zweit in der Reihe.&lt;br /&gt;
Das ist im Berufsverkehr nicht immer so, aber am Samstag Abend ist die 
Auslastung entsprechend gering.&lt;/p&gt;

&lt;p&gt;Im Kino selbst sind - wie erwartet - Markierungen auf den Boden geklebt, damit
man sich nicht zu nahe kommt, wenn man vor der Kasse wartet.&lt;/p&gt;

&lt;p&gt;Ich hatte am Nachmittag ein Karte für den Film &lt;a href=&quot;https://en.wikipedia.org/wiki/Unhinged_(2020_film)&quot;&gt;Unhinged - außer Kontrolle&lt;/a&gt;
im Internet reserviert und war erst der 4., der sich einen Platz auf diese
Weise sicherte.&lt;br /&gt;
Von daher konnte ich nichts erkennen, ob es in den Sitzreihen zu Einschränkungen
kommt.&lt;/p&gt;

&lt;p&gt;Lediglich das Warten an der Kassa dauerte diesmal etwas länger. Keine Ahnung
ob es an der Unentschlossenheit anderer Besucher lag, oder an der 
Sitzplatzkoordination.&lt;/p&gt;

&lt;p&gt;Mit dem frischen Ticket in der Hand, wanderte ich wenige Meter weiter zu
Eingang des “Kinobereiches”, wo für gewöhnlich das Ticket beim Betreten
entwertet wird. Das freundliche Mädchen an diesem Platz bot mir eine neue
Einweg-Mund-Nasen-Maske an und erklärte mir:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Im gesamten Kinobereich (also von der Fressmeile bis zu den Toiletten)
herrscht Mund- und Nasenschutz-Pflicht, aber sobald man sich im Kinosaal
auf seinen Platz setzt, darf man sie abnehmen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Also besorgte ich mir noch Knabbereien und Getränke - natürlich mit Maske -
und wanderte dann zu “meinem” Kinosaal.&lt;/p&gt;

&lt;p&gt;In Summe waren nicht viele Personen in meinem Film, nämlich weniger als 20.
Dies Besucher waren dann in kleinen Gruppen recht verteilt im Saal angesiedelt.&lt;/p&gt;

&lt;p&gt;Man kann da aber nicht so genau sagen, ob das wirklich so “organisiert” war,
weil bei geringen Besucherzahlen immer eine recht freie Verteilung erfolgt.&lt;/p&gt;

&lt;p&gt;Für mich war der gesamte Kinobesuch also von einem regulärem überhaupt nicht
zu unterscheiden, außer eben die Maskenpflicht draußen.&lt;/p&gt;

&lt;p&gt;Ich müsste also zu einer Premiere eines neuen Films mit vielen Besuchern um
feststellen zu können, ob die Platzverteilung in Corona-Zeiten krass anders 
ist.&lt;/p&gt;

&lt;h3 id=&quot;spoiler-unhinged--außer-kontrolle&quot;&gt;Spoiler: Unhinged -Außer Kontrolle&lt;/h3&gt;

&lt;p&gt;Für meinen ersten Film seit dem letzten Weihnachtsfest war das Erlebnis echt
gut. Dieser Film, in dem &lt;a href=&quot;https://de.wikipedia.org/wiki/Russell_Crowe&quot;&gt;Russell Crowe&lt;/a&gt;
ausrastet und eine Mutter und ihren Sohn terrorisiert, birgt einige Szenen in 
denen man mitfiebert und voller Kraft hofft, dass die Gejagten schadfrei 
davon kommen.&lt;/p&gt;

&lt;p&gt;Gänsehaut bekam ich ein paar Mal als die Augen des Psychopathen im Film
gezeigt wurden, die den drohenden Gewalt-Ausbruch schon andeuteten, 
während der Schauspieler selbst noch “ruhige Mine zum bösen Spiel” vorgaukelte.&lt;/p&gt;

&lt;p&gt;In sofern also ein guter Film, der sein Geld wert war.&lt;/p&gt;

&lt;p&gt;Etwas enttäuschend empfand ich aber das Ende … vor allem als ich lange 
am Heimweg darüber nachdachte.&lt;/p&gt;

&lt;p&gt;Irgendwie bleibt bei mir die Botschaft hängen: 
Alle Amerikaner sind gestresste Geldjäger, die alle kurz vor dem Amoklauf 
stehen. Und trotzdem gibt es “gute” und “schlechte” Aggressionen, wobei die
“schlechten” am Ende immer ganz korrekt von Polizeikugeln durchlöchert werden,
und die “guten” Aggressionsträger ohne einen all zu großen Sinneswandel am
Abend heimfahren.&lt;/p&gt;

&lt;p&gt;Man z.B.: steht vor dem Verlust seines Jobs, bleibt aber dennoch im Bett 
liegen um dann genervt im Auto die anderen “nieder zu hupen”.&lt;/p&gt;

&lt;p&gt;Falls das eine Gesellschaftskritik gewesen sein soll, dann wurde sie am Ende 
leider entwertet, wo der “Psycho” in letzter Sekunde niedergestochen wird
und die auslösenden Personen für seinen “Ausbruch” ganz normal nach Hause
fahren.&lt;/p&gt;

&lt;p&gt;Ja, da hätte ich mir mehr erwartet.&lt;/p&gt;

&lt;p&gt;Selbst am Ende von Marvels &lt;a href=&quot;https://de.wikipedia.org/wiki/Black_Panther_(Film)&quot;&gt;Black Panther&lt;/a&gt;
durfte der neue junge König von Wakanda die politisch gewichtigen Worte 
sprechen:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;In Zeiten größter Not bauen die Weisen Brücken, 
während die Narren Mauern errichten.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Da hätten sie schon noch einen “Die Moral von der Geschicht’” Satz bringen
können.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Es war ein interessanter Abend und ein guter Wiedereinstieg ins Kino-Leben
Ich möchte nun wieder öfter vor der Leinwand sitzen, schließlich hat diese
Branche in letzter Zeit Federn lassen müssen.&lt;/p&gt;

&lt;p&gt;Gleichzeitig kann kein noch so guter Webstream auf meinem 24 Zoll Monitor
mit einem Projektor mithalten und das Flare von Popcorn und Nachos wirkt
zu Hause auch nur “minimalistisch”.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Windows 10 ohne PL2303</title>
   <link href="https://www.opengate.at/blog/2020/08/pl2303hxa/"/>
   <published>2020-08-15T13:00:00+02:00</published>
   <updated>2020-08-15T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2020/08/pl2303hxa</id>
   <category term="hardware" /><category term="software" />
   <summary type="text">Dass ausgerechnet die “teuerste” Hardware am kürzesten “hält” ist für mich 
schon etwas enttäuschend.
Denn mein guter alter LogiLink USB zu RS232 
Adapter wird in Windows 10 
nicht mehr unterstützt.

</summary>
   <content type="html">&lt;p&gt;Dass ausgerechnet die “teuerste” Hardware am kürzesten “hält” ist für mich 
schon etwas enttäuschend.
Denn mein guter alter LogiLink USB zu &lt;a href=&quot;https://de.wikipedia.org/wiki/RS-232&quot;&gt;RS232&lt;/a&gt; 
Adapter wird in &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_10&quot;&gt;Windows 10&lt;/a&gt; 
nicht mehr unterstützt.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Microsoft’s Windows Update bietet offenbar einen Treiber an, der meinen
USB Adapter nicht “betreiben” kann.&lt;/p&gt;

&lt;p&gt;Der angezeigte Gerätename:&lt;br /&gt;
&lt;code&gt;PL2303HXA PHASED OUT SINCE 2012. PLEASE CONTACT YOUR SUPPLIER.&lt;/code&gt;&lt;br /&gt;
lässt aufhorchen, trotzdem wird ein COM Port mit dem Gerät assoziiert.&lt;br /&gt;
Doch leider lässt sich dieser Port dann nicht von Applikationen öffnen.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/pl2303hxa-error.png&quot; alt=&quot;PL2303-Error&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Die Herstellerseite verweist darauf, dass man auf einen neueren Chipsatz
wechseln sollte, doch … warum läuft mein alter nicht mehr?&lt;/p&gt;

&lt;p&gt;Jedenfalls half mir kein Download aus diesem Bereich, auch ein älterer Treiber
führte nicht zum Erfolg.&lt;/p&gt;

&lt;p&gt;Selbst wenn das Gerät “optisch” korrekt installiert war, es blieb weiter
unmöglich den COM Port zu öffnen.&lt;/p&gt;

&lt;h3 id=&quot;lösung-zurück-zu-windows-7&quot;&gt;Lösung: Zurück zu Windows 7&lt;/h3&gt;

&lt;p&gt;Unter &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_7&quot;&gt;Windows 7&lt;/a&gt; läuft das
Gerät problemlos (auch mit aktuellen Treibern), doch ich will das Teil unter 
Windows 10 laufen sehen.&lt;/p&gt;

&lt;p&gt;Zum Glück findet man im Netz ein paar Hinweise von anderen, die ebenfalls
schon dieses Problem hatten, dass man einen älteren Windows 7 Treiber 
zum Laufen bekommen kann.&lt;/p&gt;

&lt;p&gt;Konkret wurde die Version 3.3.2 angesprochen. Doch leider konnte ich keinen
funktionierenden Link dazu finden.&lt;br /&gt;
Letztendlich fand ich aber die Version 3.2 in einem 
&lt;a href=&quot;https://drive.google.com/file/d/0B-eoaN1SwVraMU1iSlpzWk1EVHM&quot;&gt;öffentlich geteilten Ordner&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nach der Installation des Programms läuft der Treiber nicht automatisch, da Windows 
ja glaubt einen neueren und besseren zu haben, doch man kann manuell den
Treiber auf die ältere Version zurücksetzen.&lt;/p&gt;

&lt;p&gt;Und … oh Wunder … es funktioniert!&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Also mal ehrlich, ich kapiere es nicht …&lt;/p&gt;

&lt;p&gt;Wieso verteilt &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft&quot;&gt;Microsoft&lt;/a&gt; einen 
Treiber, der nicht funktioniert und meldet das sogar noch genau so, während
die ältere Windows 7 Version offenbar gut genug ist noch nie nächsten 10 Jahre
weiter eingesetzt zu werden?&lt;/p&gt;

&lt;p&gt;Ich hasse es wenn ich Lebenszeit verschwende, weil ich solchen Dummheiten
hinterherlaufen kann.&lt;/p&gt;

&lt;p&gt;Nun, diese Geschichte ist wieder eindeutig ein Punkt für&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Früher war alles besser!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Und ich fasse es nicht, dass Windows 7 jetzt zu “früher” gehört … denn sonst
meine ich mit “früher” Dinge wie &lt;a href=&quot;https://de.wikipedia.org/wiki/MS-DOS&quot;&gt;DOS&lt;/a&gt;
oder &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_NT_4.0&quot;&gt;NT 4&lt;/a&gt;.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Docker-Image für Bitbucket</title>
   <link href="https://www.opengate.at/blog/2020/08/build-docker/"/>
   <published>2020-08-12T13:00:00+02:00</published>
   <updated>2020-08-12T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2020/08/build-docker</id>
   <category term="devel" /><category term="software" /><category term="projects" />
   <summary type="text">Unlängst habe ich meine Bedenken gegen Docker
geäußert und seinen Einsatz als “Fix gegen schlechtes Distributions-Design” 
kritisiert.

Jetzt wollen wir aber mal einen wichtigen Vorteil dieser Lösung aufzeigen:
Build-Images für Linux
</summary>
   <content type="html">&lt;p&gt;Unlängst habe ich &lt;a href=&quot;/blog/2020/05/docker/&quot;&gt;meine Bedenken gegen Docker&lt;/a&gt;
geäußert und seinen Einsatz als “Fix gegen schlechtes Distributions-Design” 
kritisiert.&lt;/p&gt;

&lt;p&gt;Jetzt wollen wir aber mal einen wichtigen Vorteil dieser Lösung aufzeigen:&lt;br /&gt;
&lt;em&gt;Build-Images für Linux&lt;/em&gt;
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;vorgeschichte&quot;&gt;Vorgeschichte&lt;/h3&gt;

&lt;p&gt;Das Chaos der &lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt; Distributionen, in 
denen jeder Hersteller andere Tools und vor allem andere Versionen von Tools 
und Bibliotheken mixt, ist ja leider ein bekannter Zustand.&lt;/p&gt;

&lt;p&gt;Man kann de-facto keine Binärdateien erzeugen, die auf allen 
Linux-Distributionen laufen, außer:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Man kompiliert alles (also auch &lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B&quot;&gt;C/C++&lt;/a&gt;
Standardbibliotheken) in das Programm hinein und macht es unabhängig von 
versionierten Bibliotheken.&lt;br /&gt;
(Also das was das GATE Projekt unter anderem erreichen möchte.)&lt;/li&gt;
  &lt;li&gt;Oder man liefert gar keine Binaries, sondern verbreitet nur Sourcecodes,
die auf dem Zielsystem erst kompiliert werden müssen.
(Was Linux-Puristen am liebsten tun, aber für Endanwender meist ein 
Alptraum ist)&lt;/li&gt;
  &lt;li&gt;Oder man erstellt Binaries für jede erdenkliche Distribution und paketiert
diese im dort üblichen Paketsystem.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Klarerweise würde ich mich für die erste Methode aussprechen.
Doch nachdem leider viel zu wenige Entwickler die Vorteile von statischer
Kompilierung zu schätzen wissen, bleibt einem im Beruf als Entwickler nur 
die 3. Option, weil die Weitergabe von Sourcecode an den Endanwender entweder
generell verboten ist, oder die Zielpersonen mit Kompilier-Abenteuer meist
überfordert sind.&lt;/p&gt;

&lt;p&gt;Und genau hier kann &lt;a href=&quot;https://de.wikipedia.org/wiki/Docker_(Software)&quot;&gt;Docker&lt;/a&gt; 
seine Stärken gegenüber &lt;a href=&quot;https://de.wikipedia.org/wiki/Virtuelle_Maschine&quot;&gt;VM&lt;/a&gt;
ausspielen. Wir brauchen nämlich keine separaten Kernels oder andere Hardware,
sondern nur unterschiedliche Varianten von User-Land Bibliotheken.&lt;/p&gt;

&lt;p&gt;Wir brauchen pro Distribution eine Build-Umgebung…&lt;/p&gt;

&lt;h3 id=&quot;lösung-ein-docker-pro-distro&quot;&gt;Lösung: Ein Docker pro Distro&lt;/h3&gt;

&lt;p&gt;Nachdem der Build-Prozess unter Linux immer gleich abläuft (also Quellcodes
einspielen und dann &lt;a href=&quot;https://de.wikipedia.org/wiki/CMake&quot;&gt;&lt;code&gt;cmake&lt;/code&gt;&lt;/a&gt; und/oder 
&lt;code&gt;make&lt;/code&gt; aufrufen), erstellt man einfach pro Distribution ein Docker-Image, in 
dem die Build-Toolchain installiert ist und baut sein Projekt durch.&lt;/p&gt;

&lt;p&gt;Die Binaries linken dann genau gegen die Version von Bibliotheken, die in der
Distro eben Standard (oder nachinstalliert) sind.&lt;br /&gt;
Man könnte durchaus sagen, dass man mit Docker quasi ein Cross-Compiling-Setup
aufsetzt … nur dass es eben innerhalb des Images nichts “cross” ist und 
damit diverse fehleranfällige Vorkonfigurationen entfallen.&lt;/p&gt;

&lt;p&gt;Die Images werden mit den Standardtools aktualisiert, also &lt;code&gt;apt&lt;/code&gt; bei 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Debian&quot;&gt;Debian&lt;/a&gt; und &lt;a href=&quot;https://de.wikipedia.org/wiki/Ubuntu&quot;&gt;Ubuntu&lt;/a&gt;, 
&lt;code&gt;zypper&lt;/code&gt; bei &lt;a href=&quot;https://de.wikipedia.org/wiki/OpenSUSE&quot;&gt;SuSE&lt;/a&gt;, &lt;code&gt;yum&lt;/code&gt; für &lt;a href=&quot;https://de.wikipedia.org/wiki/CentOS&quot;&gt;CentOS&lt;/a&gt; 
oder &lt;a href=&quot;https://de.wikipedia.org/wiki/Red_Hat&quot;&gt;RedHat&lt;/a&gt;, &lt;code&gt;apk&lt;/code&gt; für
&lt;a href=&quot;https://de.wikipedia.org/wiki/Alpine_Linux&quot;&gt;Alpine&lt;/a&gt; und vieles mehr.&lt;/p&gt;

&lt;h3 id=&quot;docker-image-für-bitbucket&quot;&gt;Docker Image für Bitbucket&lt;/h3&gt;

&lt;p&gt;Auch der Build von GATE auf &lt;a href=&quot;https://bitbucket.org/&quot;&gt;BitBucket&lt;/a&gt; profitiert von
einem eigenen Image. Die bereitgestellten generischen mussten bisher bei jeder
Ausführung erneut gepatcht werden, damit alle Quellcodes durchkompiliert 
werden konnten.&lt;/p&gt;

&lt;p&gt;Aber mit einem Verweis in &lt;code&gt;bitbucket-pipelines.yml&lt;/code&gt; auf ein vorbereitetes
Docker-Image auf &lt;a href=&quot;https://hub.docker.com/&quot;&gt;Docker Hub&lt;/a&gt;, entfällt dieser
Schritt.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Man schreibt sich also ein &lt;code&gt;Dockerfile&lt;/code&gt; mit allen notwendigen 
&lt;code&gt;apt-get install&lt;/code&gt; Anweisungen (oder was auch immer das eingesetzte 
Linux braucht).&lt;/li&gt;
  &lt;li&gt;Dann lässt dann im Verzeichnis von &lt;code&gt;Dockerfile&lt;/code&gt; das Kommando &lt;br /&gt;
&lt;code&gt;docker build -t MY_DOCKERHUB_USER/MY_IMAGE_NAME:MY_TAG .&lt;/code&gt; aus.
Bei mir war das&lt;br /&gt;
&lt;code&gt;docker build -t gatelinker/cpp-build-env:ubuntu18 .&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Am Ende wird per&lt;br /&gt;
&lt;code&gt;docker push MY_DOCKERHUB_USER/MY_IMAGE_NAME:MY_TAG&lt;/code&gt; das Image auf
DockerHub hochgeladen.&lt;/li&gt;
  &lt;li&gt;Nun kann &lt;code&gt;bitbucket-pipelines.yml&lt;/code&gt; um folgende beiden &lt;a href=&quot;https://de.wikipedia.org/wiki/YAML&quot;&gt;YAML&lt;/a&gt;
Einträge erweitert werden:
    &lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;image:
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;  name: MY_DOCKERHUB_USER/MY_IMAGE_NAME:MY_TAG
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Und schon kann man sein Projekt auf dem eigenen Docker-Image laufen lassen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Viele meiner Kollegen schwören auf Docker für die Erstellung von Build-Systemen
oder für das automatische Ausführen von Tests.&lt;br /&gt;
Und damit haben sie Recht. Docker eignet sich für diese Zwecke wirklich gut,
in kurzer Zeit “ein neues Linux” aufzusetzen, ohne dass es ein vollständiges 
Linux System sein muss.&lt;/p&gt;

&lt;p&gt;Ich bleibe zwar weiter bei meiner Meinung, dass Docker viel zu oft als billiger
Patch für andere Probleme genutzt wird, kann aber den Wert der Software in 
anderen Bereichen nicht ignorieren.&lt;/p&gt;

&lt;p&gt;Von daher werde ich in Zukunft auch mehr Build-Vorgänge nur noch in Docker
Containern durchführen und nicht jedes Mal eine neue VM aufsetzen.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>CONAN-GATE</title>
   <link href="https://www.opengate.at/blog/2020/08/conan-gate/"/>
   <published>2020-08-09T13:00:00+02:00</published>
   <updated>2020-08-09T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2020/08/conan-gate</id>
   <category term="devel" /><category term="software" /><category term="projects" />
   <summary type="text">Nachdem meine Firma jetzt schon ein Jahr mit CONAN 
“herumwerkt”, wollte ich mal auch ein paar Tests bei mir zu Hause mit dem 
GATE Projekt machen.

Zusammengefasst: Vorerst “hilft” mir das System nicht wirklich … aber
in Sachen Buildserver könnte es dennoch nützlich sein.
</summary>
   <content type="html">&lt;p&gt;Nachdem meine Firma jetzt schon ein Jahr mit &lt;a href=&quot;https://conan.io/&quot;&gt;CONAN&lt;/a&gt; 
“herumwerkt”, wollte ich mal auch ein paar Tests bei mir zu Hause mit dem 
GATE Projekt machen.&lt;/p&gt;

&lt;p&gt;Zusammengefasst: Vorerst “hilft” mir das System nicht wirklich … aber
in Sachen Buildserver könnte es dennoch nützlich sein.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;herunterladen-von-abhängigkeiten&quot;&gt;Herunterladen von Abhängigkeiten&lt;/h3&gt;

&lt;p&gt;Der wichtigste Anwendungsfall von CONAN ist beim GATE-Projekt aktuell nicht
relevant: nämlich das Zusammensuchen mehrerer Bibliotheken.&lt;/p&gt;

&lt;p&gt;Ich habe sämtliche zwingend erforderlichen externen Bibliotheken wie 
&lt;code&gt;zlib&lt;/code&gt; oder &lt;code&gt;libreSSL&lt;/code&gt; in das Projekt mit allen Sourcen integriert.
Von daher brauche ich CONAN nicht um Daten von außen herunterzuladen.&lt;/p&gt;

&lt;p&gt;… mit einer Ausnahme: &lt;a href=&quot;https://de.wikipedia.org/wiki/GTK_(Programmbibliothek)&quot;&gt;GTK3&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;GTK3 wird in erster Linie für die Linux-Builds von GUI Anwendungen gebraucht.
Doch für ein effektiveres Debuggen liegen Header und vorkompilierte LIBs auch
bei den externen GATE-Bibliotheken für Windows bei.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;CMake&lt;/code&gt; sucht diese für den Link-Prozess zusammen mit:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;if(GATE_UI_GTK)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;  target_compile_definitions(${BINARY_NAME} PRIVATE GATE_UI_GTK)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  FIND_PACKAGE(PkgConfig REQUIRED)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  PKG_CHECK_MODULES(GTK REQUIRED gtk+-3.0)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  INCLUDE_DIRECTORIES(${GTK_INCLUDE_DIRS})
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;  LINK_DIRECTORIES(${GTK_LIBRARY_DIRS})
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  ADD_DEFINITIONS(${GTK_CFLAGS} ${GTK_CFLAGS_OTHER})
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;  TARGET_LINK_LIBRARIES(gateui ${GTK_LIBRARIES})
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;endif()
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Doch ob damit wirklich die richtigen Dateien gefunden werden hängt von vielen
Konfigurationsdetails ab … vor allem wenn mehrere Versionen von GTK parallel
installiert sind.&lt;/p&gt;

&lt;p&gt;CONAN könnte diese Problem eleganter lösen, indem ein Requirement auf z.B.: 
&lt;code&gt;gtk/3.24.20@bincrafters/stable&lt;/code&gt;&lt;br /&gt;
gesetzt wird.&lt;br /&gt;
Nun bräuchten nur noch die &lt;code&gt;CMake&lt;/code&gt; Include- und Link-Anweisungen gesetzt werden:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;conan_basic_setup()
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;target_link_libraries(${PROJECT_NAME} ${CONAN_LIBS})
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;und schon sollte CONAN die lästige Aufgabe übernehmen, sich alle Sourcen 
herunterzuladen und korrekte Link-Pfade zum Projekt zu senden.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ich mache zwar gelegentlich ein paar Test mit CONAN, aber aktuell läuft die
CMake Variante für mich ganz gut … so lange man die nötigen Bibliotheken 
selbst im Betriebssystem korrekt installiert hat.&lt;/p&gt;

&lt;p&gt;Ein anderer Aspekt wäre auch das Bereitstellen des GATE-Frameworks durch CONAN.
Aber ich denke mal, dass mich dieses Thema vor Mitte 2021 nicht tangieren wird,
und dann bleibt fraglich ob überhaupt.&lt;/p&gt;

&lt;p&gt;Und deshalb bleibe ich vorerst beim vertrauten Prozedere.
Aber hey … wenn sich letztlich weitere Vorteile aus dem System ziehen lassen,
wird die Priorität dafür schnell ansteigen.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Solarmodule Marke Eigenbau</title>
   <link href="https://www.opengate.at/blog/2020/08/solar-diy/"/>
   <published>2020-08-08T13:00:00+02:00</published>
   <updated>2020-08-08T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2020/08/solar-diy</id>
   <category term="hardware" /><category term="projects" />
   <summary type="text">Wenn man für 8 Euro 100 stromerzeugende Solarmodul
Plättchen kaufen kann (0.5 Volt, 500 Milliampere, 0.25 Watt das Stück), warum 
kostet dann ein fertiges 5 V USB Versorgerteil ebenso viel?

Naja, die Plättchen zerbrechen schon bei geringem Druck und müssen daher
rund-um versiegelt produziert werden … und schon wird das Endprodukt teuer.

Meine Frage war daher: Kann man das selbst auch hinbekommen?
</summary>
   <content type="html">&lt;p&gt;Wenn man für 8 Euro 100 stromerzeugende &lt;a href=&quot;https://de.wikipedia.org/wiki/Solarmodul&quot;&gt;Solarmodul&lt;/a&gt;
Plättchen kaufen kann (0.5 Volt, 500 Milliampere, 0.25 Watt das Stück), warum 
kostet dann ein fertiges 5 V USB Versorgerteil ebenso viel?&lt;/p&gt;

&lt;p&gt;Naja, die Plättchen zerbrechen schon bei geringem Druck und müssen daher
rund-um versiegelt produziert werden … und schon wird das Endprodukt teuer.&lt;/p&gt;

&lt;p&gt;Meine Frage war daher: Kann man das selbst auch hinbekommen?
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Wie gut, dass einige Pioniere diesen Weg bereits ausgetreten haben und so 
musste ich nur ein YouTube Video durchlaufen lassen um zu erfahren, wie
es funktioniert.&lt;/p&gt;

&lt;p&gt;Also, man braucht:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Solarmodule&lt;br /&gt;
Ich habe 100 Stück mit 39 x 39 mm mit einer Leistung von 0.25 Watt 
bei 0.5 Volt und angeblich bis zu 500 mA in Fernost um 8 Euro bestellt.&lt;/li&gt;
  &lt;li&gt;Tabbing Draht&lt;br /&gt;
Zum Verbinden der Solarmodule, bei mir passten 1.8 Millimeter recht gut.
Gabs auch um 4 Euro in China mitzubestellen.&lt;/li&gt;
  &lt;li&gt;Eine Kunststoffplatte als stabilisierende Unterlage&lt;br /&gt;
Konnte im Baumarkt ein 1000x500x3 mm PVC Teil um 10 Euro bekommen.
Es ließ sich recht gut mit einem Abbrechklingenmesser zerschneiden.&lt;/li&gt;
  &lt;li&gt;Epoxitkleber + Härtner&lt;br /&gt;
Den verteilt man über die Module auf ihrer Unterlage um sie zu versiegeln.
Den gab es auch im Baumarkt, wobei ich mich an den Preis nicht mehr
erinnere … wird aber unter 20 Euro gewesen sein.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;OK, erster Versuch. Los geht’s!&lt;/p&gt;

&lt;h3 id=&quot;vorsicht-zerbrechlich&quot;&gt;Vorsicht zerbrechlich!&lt;/h3&gt;

&lt;p&gt;Die Solarmodule sind in ihrer Rohform so etwas von zerbrechlich, dass man sie
sprichwörtlich nur mit Samthandschuhen anfassen sollte.&lt;/p&gt;

&lt;p&gt;Druck verkraften sie gar nicht. Ein bisschen zu viel Kraft beim Löten 
und schon brechen sie entzwei. Die Vakuumpumpe bei zu viel Lötzinn
zerstört sie garantiert und auch Aufwölbungen oder Bodenunebenheiten
sind Gift für Plättchen.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/solar-diy-01.jpg&quot; alt=&quot;DIY Solar Module 01&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;solarmodule-zusammenketten&quot;&gt;Solarmodule zusammenketten&lt;/h3&gt;

&lt;p&gt;Ich habe mich entschieden jeweils 5 Module in Serie zu verbinden.
Das ergibt in meinem Fall 2.5 Volt und verbraucht etwa 20 cm.&lt;/p&gt;

&lt;p&gt;Die Idee wäre gewesen den Tabbing-Draht auf das Modul zu legen und einfach
per Lötkolben “festzukleben”.&lt;br /&gt;
Doch das klappte bei mir nicht. Zwar war auf dem Draht Lötzinn der brav
schmolz aber nie eine Bindung mit dem Modul einging. Auch aufgetragenes
Flussmittel half nicht.&lt;/p&gt;

&lt;p&gt;Ich musste also mit etwas “frischem” Lötzinn nachhelfen.&lt;br /&gt;
Dann war es kein Problem und der Draht verband die angrenzenden Module
miteinander. Leider kames aber so auch zu einigen Aufwölbungen an 
Ober- und Unterseite durch die zusätzliche Lötmenge.&lt;/p&gt;

&lt;p&gt;Am Ende waren jeweils der Pluspol (unten) mit dem angrenzenden Minuspol (oben)
des Nachbarmoduls verbunden.&lt;/p&gt;

&lt;p&gt;Ein kurzer Test mit dem &lt;a href=&quot;https://de.wikipedia.org/wiki/Multimeter&quot;&gt;Multimeter&lt;/a&gt;
unter einer Lampe bewies, dass die Module brav Strom erzeugten.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/solar-diy-02.jpg&quot; alt=&quot;DIY Solar Module 02&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;untergrund-ausschneiden&quot;&gt;Untergrund ausschneiden&lt;/h3&gt;

&lt;p&gt;Aus der Kunststoffplatte ließen sich recht unkompliziert Rechtecke 
ausschneiden, auf denen man die Module platzieren kann.
Diese sollten einen Rand von 3-5 Millimetern rund um die Module
freilassen.&lt;/p&gt;

&lt;p&gt;In der Mitte einer jeden Platte erzeugte ich mit einem Schraubendreher eine
Spur, in welcher die Tabbing-Draht-Unebenheiten versenkt werden konnten.&lt;/p&gt;

&lt;p&gt;Ohne diese Maßnahme zerbrach beim ersten Versuch eines der Plättchen und
damit war die ganze Arbeit umsonst.&lt;/p&gt;

&lt;p&gt;Mein größter Fehler war allerdings die Rechtecke nicht ganz Herauszulösen
sondern nur anzuritzen. Ich dachte man könne die Stücke dann einfach 
“ausbrechen”, doch das führte zu einer recht unregelmäßigen Bruchkante,
die eben nicht besonders schön aussieht.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/solar-diy-03.jpg&quot; alt=&quot;DIY Solar Module 03&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;module-auf-untergrund-kleben&quot;&gt;Module auf Untergrund kleben&lt;/h3&gt;

&lt;p&gt;Mit ein paar Tröpfchen Superkleber fixierte ich die verbundenen Module 
auf dem Kunststoffrechteck.&lt;/p&gt;

&lt;p&gt;Jetzt war ein erster Test am Fenster fällig und ja, das Modul lieferte
brav Strom (zwar nur die Hälfte an Milliampere wie angegeben, aber die
Spannung stimmte dafür)&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/solar-diy-04.jpg&quot; alt=&quot;DIY Solar Module 04&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;epoxitkleber-anrühren&quot;&gt;Epoxitkleber anrühren&lt;/h3&gt;

&lt;p&gt;An der Stelle wurde es bei mir recht ungenau. Eigentlich sollte man die
Mengen zwischen Epoxit und Härtner genau abwägen, doch ich besitze
(noch) keine Grammwage für solche Zwecke.&lt;/p&gt;

&lt;p&gt;Also schüttete ich so PI mal Daumen in etwa die Mischung 3:1 zusammen
in der Hoffnung, dass es ungefähr passen sollte.&lt;/p&gt;

&lt;p&gt;Nach etwa 10 Minuten Umrühren waren ein paar Bläßchen zu sehen und ich
ließ die Mixtur für etwa 50 Minuten einwirken.&lt;br /&gt;
Das Glas in dem die Substanzen vermischt wurden, begann sich dabei etwas
zu erwärmen.&lt;/p&gt;

&lt;h3 id=&quot;module-versiegeln&quot;&gt;Module versiegeln&lt;/h3&gt;

&lt;p&gt;Den zähflüssigen Epoxitkleber verteilte ich nun auf den Modulen.
Ich rollte mit einem eingetunkten Bleistift langsam und vorsichtig hin und 
her und verteilte so den Klebstoff gleichmäßig.&lt;/p&gt;

&lt;p&gt;An einigen Stellen entstanden Blasen, die man aber leicht mit einem Zahnstocher
aufstechen konnte, womit sich der Kleber von selbst wieder gleichmäßig
verteilte.&lt;/p&gt;

&lt;p&gt;Am Ende waren alle Module auf der Platte mit Kleber bis über die Kanten 
überzogen. Nun muss man dem Kleber bis zu 24 Stunden Zeit zum Trocknen
und Verhärten geben.&lt;/p&gt;

&lt;h3 id=&quot;solarmodul-fertig&quot;&gt;Solarmodul fertig!&lt;/h3&gt;

&lt;p&gt;Meine Freude war groß, als am Folgetag die Module fast wie original gekaufte
glänzten.&lt;br /&gt;
Der Epoxitkleber hat mit wenigen Ausnahmen alles überdeckt, war hart geworden 
und schützt die Module nun vor Druck von außen.&lt;br /&gt;
Biegen sollte man die Teile selbstverständlich nicht, denn einmal zerbrochen
kann man die Dinger nur noch wegwerfen.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/solar-diy-05.jpg&quot; alt=&quot;DIY Solar Module 05&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Es ist so was von geil! Ich konnte in vertretbarer Zeit meine eigenen Module
bauen. Natürlich waren ein paar kleine Verunreinigungen im Kleber und es gibt
auch ein paar Kannten, die nicht perfekt versiegelt sind.&lt;/p&gt;

&lt;p&gt;Aber das waren ja auch erst meine ersten 10 verbauten Modulstücke.
90 weitere warten darauf verarbeitet zu werden.&lt;/p&gt;

&lt;p&gt;Ich habe eine tolle Beschäftigung gefunden und möchte so meine Fenster
in Stromgeneratoren verwandeln. Schließlich ist im Sommer bei mir 
sowieso immer verdunkelt wegen der Hitze … also warum soll man die Fenster
dann nicht gleich mit Solarmodulen verdecken?&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Und wieder so ein Billig-Gameboy-Teil</title>
   <link href="https://www.opengate.at/blog/2020/08/gameboy-on-chip/"/>
   <published>2020-08-02T13:00:00+02:00</published>
   <updated>2020-08-02T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2020/08/gameboy-on-chip</id>
   <category term="hardware" /><category term="retro" />
   <summary type="text">Als kleiner Junge hätte ich mich vermutlich wie im Himmel gefühlt, wenn ich 
mir für 10 Dollar (also etwa 9 Euro, oder damals 120 Schilling) quasi jedes
Monat ein neues digitales Spielzeug hätte leisten können.

Heute interessieren mich die Inhalte recht wenig, aber wenn so ein Teil
so billig ist, wird es mitbestellt, damit ich es zerlegen kann.
</summary>
   <content type="html">&lt;p&gt;Als kleiner Junge hätte ich mich vermutlich wie im Himmel gefühlt, wenn ich 
mir für 10 Dollar (also etwa 9 Euro, oder damals 120 Schilling) quasi jedes
Monat ein neues digitales Spielzeug hätte leisten können.&lt;/p&gt;

&lt;p&gt;Heute interessieren mich die Inhalte recht wenig, aber wenn so ein Teil
so billig ist, wird es mitbestellt, damit ich es zerlegen kann.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Dank &lt;a href=&quot;https://de.wikipedia.org/wiki/Raspberry_Pi&quot;&gt;Raspberry PI&lt;/a&gt; Zero und dem 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt; Derivat &lt;a href=&quot;http://retropie.org.uk/&quot;&gt;Retro-PIE&lt;/a&gt; 
lassen sich hunderte Spiele &lt;a href=&quot;https://de.wikipedia.org/wiki/Festwertspeicher&quot;&gt;ROMs&lt;/a&gt; 
von &lt;a href=&quot;https://de.wikipedia.org/wiki/Nintendo_Entertainment_System&quot;&gt;NES&lt;/a&gt;, 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Game_Boy&quot;&gt;Gameboy&lt;/a&gt; und anderen alten 
Konsolen heute auf dieser 10 Euro Hardware spielen.&lt;/p&gt;

&lt;p&gt;10 Euro?&lt;br /&gt;
Nö, nicht ganz, denn so viel kostet nur das Raspi-Board.
Zum Spielen braucht man ja noch ein Display, ein Gamepad oder eine 
vergleichbare Schnittstelle, eine &lt;a href=&quot;https://de.wikipedia.org/wiki/SD-Karte&quot;&gt;SD Karte&lt;/a&gt;
für die Software und der Strom sollte ja auch noch einfließen können, also
ein Netzteil.&lt;/p&gt;

&lt;p&gt;Und schon sind wir bei mindestens 40 Euro für DIY-Kits aus Fernost,
oder wir investieren einen Hunderter im Laden um die Ecke.&lt;/p&gt;

&lt;p&gt;Die ROMs bekommt man ja im Netz kostenfrei … wobei ich mich immer wieder
frage, wie es da mit den Lizenzen aussieht …&lt;/p&gt;

&lt;p&gt;Und dann gibt es Angebote, wo ein kleiner Gameboy-artiger Kasten mit 
allem Drum und Dran auch nur um die 10 Euro kostet und dann auch
noch damit wirbt 100 Spiele drauf zu haben.&lt;/p&gt;

&lt;p&gt;Ein solches Teil habe ich nun bestellt und bin über den Inhalt erstaunt.&lt;/p&gt;

&lt;h3 id=&quot;retro-gameboy&quot;&gt;Retro Gameboy&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/retro-gameboy.jpg&quot; alt=&quot;Retro-Gameboy&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Mein quasi-No-Name Retro-Gameboy kam mit vorinstallierten Spielen,
die ich großteils alle nicht kannte. Es gab ein paar Arten von 
Super-Mario, und eine Menge 1 gegen 1 Kampfspielchen.
Ich denke, dass vieles davon chinesische Nachahmungen von bekannten Titeln
sind.&lt;/p&gt;

&lt;p&gt;Einen Eintrag kannte ich aber gut: &lt;a href=&quot;https://de.wikipedia.org/wiki/Dr._Mario&quot;&gt;Dr. Mario&lt;/a&gt;
und damit hatte ich auch Freude, als ich es auf dem Gerät anspielte. 
Da es keine externe SD-Karte oder etwas ähnliches gab, konnte ich aber 
keine eigenen ROMs nachladen.&lt;/p&gt;

&lt;p&gt;Die Frage war also:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Worauf laufen diese Spiele?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Also schraubte ich das Plastikteil auf. Nachdem Display, Lautsprecher
und Platine eng miteinander verkabelt waren, fotografierte ich nur 
mit meinem &lt;a href=&quot;/blog/2019/08/body-check/&quot;&gt;Endoskop&lt;/a&gt; 
in das Gerät um Bilder von der Chipaufschrift zu erhalten und schraubte 
das Teil wieder zusammen.&lt;/p&gt;

&lt;p&gt;Im Nachhinein stellte sich heraus, dass ich leider nur den Flash Speicher
Chip abgelichtet hatte und nicht die CPU wie ich dachte.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/retro-gameboy-flash-chip.jpg&quot; alt=&quot;Retro-Gameboy Flash Chip&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Unter &lt;code&gt;M36LOR705&lt;/code&gt; findet man ein paar Infos zu diesem Bauteil, und nun weiß
ich zumindest wo die Spiele abgelegt sind.&lt;br /&gt;
Schade, denn eine interne microSD Karte oder etwas anderes leicht 
entfernbares hätte mir einen schnellen Einblick verschaffen und eine 
Möglichkeit zum Upload weitere Spiele ermöglichen können.&lt;/p&gt;

&lt;p&gt;Nachtrag:&lt;br /&gt;
Eine bessere und vor allem schärfere Aufnahme macht übrigens ein Smartphone.
Es ist schon interessant, dass mein Endoskop aus nächster Nähe ein wesentlich
schlechteres Bild machte, als das Smartphone, wenn es über 30cm entfernt ist:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/retro-gameboy-inside.jpg&quot; alt=&quot;Retro-Gameboy Inside&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/retro-gameboy-flash-chip2.jpg&quot; alt=&quot;Retro-Gameboy Flash Chip 2&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Naja … eine kleines Gerät mit schönem Display und zumindest einem 
bekannten Spiel zum Zeitvertreib. Hätte mehr sein können, aber ist
deshalb auch nicht schlecht.&lt;/p&gt;

&lt;p&gt;Ich werde das Teil vielleicht ein anderes Mal wirklich zerlegen und die 
Platine vom Display lösen.&lt;br /&gt;
Vermutlich befindet sich auf der anderen Seite der Prozessor, damit ich 
einen Eindruck erhalte, auf welcher Architektur die Spiele laufen.&lt;/p&gt;

&lt;p&gt;Denn zumindest bei Dr. Mario möchte ich wetten, dass es eine ROM-Emulation 
ist … und das bedeutet hier wurde vermutlich ein OpenSource 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Emulator&quot;&gt;Emulator&lt;/a&gt; eingesetzt.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>COVID-19 Season 2</title>
   <link href="https://www.opengate.at/blog/2020/08/covid-19-2/"/>
   <published>2020-08-01T13:00:00+02:00</published>
   <updated>2020-08-01T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2020/08/covid-19-2</id>
   <category term="general" />
   <summary type="text">
  Und jetzt kommt die zweite Welle.
Bald sind alle wieder krank.
Unsre Wirtschaft hat ne Delle,
seit der Kurs zu Boden sank.


So sollte die Pop-Rock-Band Juli 
ihren damaligen Hit “Das ist die perfekte Welle” heute neu auflegen.

</summary>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;Und jetzt kommt die zweite Welle.&lt;br /&gt;
Bald sind alle wieder krank.&lt;br /&gt;
Unsre Wirtschaft hat ne Delle,&lt;br /&gt;
seit der Kurs zu Boden sank.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So sollte die &lt;a href=&quot;https://de.wikipedia.org/wiki/Juli_(Band)&quot;&gt;Pop-Rock-Band Juli&lt;/a&gt; 
ihren damaligen Hit &lt;em&gt;“Das ist die perfekte Welle”&lt;/em&gt; heute neu auflegen.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Tja … was soll ich sagen.&lt;/p&gt;

&lt;p&gt;Als Österreicher hat mich die Panikmache unserer Regierung schwer verärgert.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Jeder wird jemanden kennen, der wegen CORONA verstorben ist.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;tönte es im März aus den Medien, dann wurden fast alle Geschäfte geschlossen
und die Angestellten auf die Straße gesetzt.&lt;/p&gt;

&lt;p&gt;Bis heute kenne ich überhaupt niemanden, der an &lt;a href=&quot;https://de.wikipedia.org/wiki/COVID-19&quot;&gt;“CORONA”&lt;/a&gt; 
verstorben ist, und vernehme nur Gerüchte, dass es in meiner Firma unter 5000
Menschen einige wenige Fälle geben soll, die sich selbst wegen Husten in 
Quarantäne begeben haben.&lt;/p&gt;

&lt;p&gt;Man könnte also fast glauben, man befände sich in Mitten einer Verschwörung,
wenn einem ein Bild von Tod geschildert wird, während man selbst nichts davon
erlebt.&lt;/p&gt;

&lt;p&gt;Dem steht natürlich das Negativbeispiel USA gegenüber. Dort wurde anfangs 
noch die Existenz von Viren geleugnet und nun häufen sich dort die Todesfälle,
denn diese haben längst den “normalen” Rahmen gesprengt.&lt;/p&gt;

&lt;p&gt;Natürlich frage ich mich da, ob mir da etwas entgangen ist, ob ich in Wien
auf der Insel der Seeligen sitze während ringsum die Welt untergeht.&lt;/p&gt;

&lt;p&gt;Aktuell wurden in Wien seit Februar 2020 etwa 5000 Menschen mit positiven
COVID-19 Befund getestet … bei einer 2 Millionenstadt eigentlich nicht viel.
Pro Tag kommen in ganz Österreich etwa 100 Neuinfektionen dazu, wobei 
durchschnittlich im ganzen Land nur 100 Personen deshalb im Krankenhaus liegen,
wovon um die 20 auf der Intensivstation schmachten.&lt;br /&gt;
Und seit Anfang des Jahres sind 720 Menschen verstorben, bei denen COVID-19
nachgewiesen wurde.&lt;/p&gt;

&lt;p&gt;Das sind weniger als jährlich an üblichen grippalen Infekten sterben und die
Gruppe zeichnet sich in der Regel durch ein höheres Alter aus.&lt;br /&gt;
Also nichts, was - so tragisch es sein mag - ungewöhnlich wäre.&lt;/p&gt;

&lt;p&gt;Ich denke, dass unterschiedliche Staaten die Pandemie auch unterschiedlich 
angehen müssen. Während unser Gesundheitssystem gut ausgestattet ist und vor
allem viele Menschen “gesund” leben und arbeiten, sieht es nicht überall so
rosig aus. In Regionen, in denen Umweltverschmutzung dominiert und niemand zum 
Arzt geht (oder gehen kann) erscheint es mir nur logisch, dass diese Menschen
weit anfälliger für Viren sind.&lt;br /&gt;
Denn leider ist der Wohlstand auf unserem Planeten nicht gleichmäßig verteilt,
und damit trifft es die ärmeren Länder immer härter.&lt;br /&gt;
Ausnahme USA, dort ist es politische Dummheit, die Todesopfer fordert.&lt;/p&gt;

&lt;p&gt;Bei der Wirtschaft sehe ich aber ein größeres Problem. Es hat fast 10 Jahre
gedauert, um die Banken-Krise von 2008 aufzuarbeiten.
Und wo die Arbeitslosigkeit gestiegen ist, stiegen auch Kriminalität und 
Gewalt an. Hier gilt die Grundregel:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Wer von seiner Arbeit und seinem Einkommen gut leben kann, der wirft nicht 
mit Bierflaschen nach Polizeibeamten.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Und die Tatsache das ganze Branchen wegen einer Pandemie schließen mussten,
lässt mich befürchten, dass es in den nächsten Jahren wesentlich rauer werden
wird, weil wir uns hiermit viele mittel- und arbeitslose Menschen “produziert”
haben.&lt;/p&gt;

&lt;p&gt;Harte Regelungen in Geschäften finde ich ja eine gute Sache. Jeder soll seinen
Mindestabstand einhalten um die Ausbreitung der Krankheit zu verhindern.
Aber hirnlos Gärtnereien, Baumärkte und Gaststätten über Monate zu schließen 
war - meines Erachtens - ein fataler Fehler.&lt;/p&gt;

&lt;p&gt;Und jetzt … wo langsam wieder so etwas wie Normalität versucht einzukehren,
wird von der “2. Welle” gesprochen, die erneut die Anzahl der Kranken und
Toten in die Höhe treiben soll.&lt;br /&gt;
Wir sollten eher daran arbeiten, die Wirtschaft und den Handel krisenfest
umzugestalten anstatt alle Menschen zu Hause einzusperren.&lt;/p&gt;

&lt;p&gt;Ich wünsche mir, dass dieser Irrsinn mit der Panikmache endlich aufhört.
Denn jeder Tag, an dem die Rede von Toten zu Schließungen führt, bedeutet
ein Monat mehr Arbeitslosigkeit in der Zukunft!&lt;/p&gt;

&lt;p&gt;Gleichzeitig erwartet ich aber auch von meinen Mitmenschen, sich an die Regeln
zu halten und nicht aus purer kindischer Trotzigkeit absichtlich gegen die
Distanz-Verordnung zu verstoßen.&lt;br /&gt;
Niemandem tut es weh, 2 Meter Abstand zu halten und ich finde es auch wesentlich
angenehmer, wenn mir im Supermarkt nicht dauernd jemand feucht in den Nacken
atmet.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Na … ich bin ja mal sehr gespannt, wie lange uns diese “Krise” noch 
begleiten wird, und wie wir uns in 10 Jahren an diese Phase erinnern werden.&lt;br /&gt;
Die Zukunft wird es zeigen …&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Verbannung von -fpermissive</title>
   <link href="https://www.opengate.at/blog/2020/07/permissive/"/>
   <published>2020-07-26T13:00:00+02:00</published>
   <updated>2020-07-26T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2020/07/permissive</id>
   <category term="devel" />
   <summary type="text">O-M-G !
Es tut mir ja echt leid, wenn ich jemanden damit beleidige, aber:


  Wenn sich ein Projekt nur noch mit -fpermissive bauen lässt,
sollte man es löschen und wieder von vorne beginnen.


Warum werden Probleme immer unter den Teppich gekehrt und wöchentlich
ein neuer Teppich gekauft, anstatt den Müll gleich am Anfang aufzusaugen??
</summary>
   <content type="html">&lt;p&gt;&lt;strong&gt;O-M-G !&lt;/strong&gt;&lt;br /&gt;
Es tut mir ja echt leid, wenn ich jemanden damit beleidige, aber:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Wenn sich ein Projekt nur noch mit &lt;code&gt;-fpermissive&lt;/code&gt; bauen lässt,
sollte man es löschen und wieder von vorne beginnen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Warum werden Probleme immer unter den Teppich gekehrt und wöchentlich
ein neuer Teppich gekauft, anstatt den Müll gleich am Anfang aufzusaugen??
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Wenn &lt;a href=&quot;https://de.wikipedia.org/wiki/Compiler&quot;&gt;Compiler&lt;/a&gt; Warnungen ausgeben, 
dann tun sie das nicht aus Jux und Tollerei.
Natürlich kann man schon mal ein Auge zudrücken, wenn ein &lt;code&gt;signed&lt;/code&gt; und ein
&lt;code&gt;unsigned&lt;/code&gt; Integer verglichen wird, wenn man selbst weiß, es werden immer 
nur positive Zahlen verglichen. (Und auch hier würde ein expliziter Cast 
alle Warnungen verschwinden lassen.)&lt;/p&gt;

&lt;p&gt;Aber wenn der Compiler einen Fehler ausgibt und klar aussagt:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Was du da geschrieben hast ergibt keinen Sinn oder ist syntaktisch falsch.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;dann ist es einfach nur dumm auch das zu ignorieren.&lt;/p&gt;

&lt;h3 id=&quot;-fpermissive&quot;&gt;“-fpermissive”&lt;/h3&gt;

&lt;p&gt;Der &lt;a href=&quot;https://de.wikipedia.org/wiki/GNU_Compiler_Collection&quot;&gt;GCC&lt;/a&gt; Parameter 
&lt;code&gt;-fpermissive&lt;/code&gt; wandelt einige “Fehlerdiagnosen” in ignorierbare Warnungen um.&lt;br /&gt;
Und leider nutzen faule Entwickler dieses “Feature” um defekten Code zum
Kompilieren zu bekommen, der eigentlich nie so übernommen werden dürfte.&lt;/p&gt;

&lt;p&gt;Dieses Problem ist wie so vieles in der IT “historisch”. Zwar gibt es am
Anfang meist einen “Standard”, doch kein Compiler setzt diesen vollständig um.
Frühere Versionen übersetzen somit Code-Konstrukte in “irgendetwas” und wenn
dieses “etwas” keine sichtbaren Abstürze produziert, wird angenommen, es
sei richtig.&lt;/p&gt;

&lt;p&gt;Kommt nun aber eine neue Compilerversion heraus, erkennt diese im alten Code
Fehler und meldet diese während die Übersetzung abgebrochen wird.&lt;/p&gt;

&lt;p&gt;Genau an der Stelle müsste jetzt der Entwickler ein paar Stunden Zeit 
investieren und sein defektes Fabrikat überarbeiten und die Welt wäre
wieder in Ordnung.&lt;/p&gt;

&lt;p&gt;Aber nein, man sucht lieber ein paar Stunden in den Dokus nach Compiler-Flags
um die Fehlermeldung zu unterdrücken und zu verheimlichen.&lt;/p&gt;

&lt;h3 id=&quot;das-kosten-problem&quot;&gt;Das Kosten-Problem&lt;/h3&gt;

&lt;p&gt;In allen Unternehmen, in denen ich bisher gearbeitet habe gilt das Prinzip:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Fehlerkorrekturen sind unnötig, weil wir nur perfekte fehlerfreie Produkte
im Sortiment haben.&lt;br /&gt;
Wir bezahlen nichts, was nicht bestellt wurde.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Und ganz furchtbar wird es dann, wenn es beim “SCRUM-Review” heißt:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Fehlerkorrektur war nicht Teil der Userstory.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Tja, und so investieren alle immer nur Zeit in Workarounds und verschlimmern
mit jeder Anpassung das Problem, weil jede weitere nicht-standard-konforme
Zeile weiteres Fehlerverhalten und Verkomplizierung bedeutet.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Es macht keinen Sinn, dass ich mich wieder darüber aufrege, dass ich 
berufsbedingt mit Code arbeiten muss, der nie hätte so geschrieben werden 
dürfen.&lt;/p&gt;

&lt;p&gt;Die Lösungen heißen natürlich &lt;em&gt;“Bildung”&lt;/em&gt; und &lt;em&gt;“Qualitätsmanagement”&lt;/em&gt;, doch 
noch nie habe ich einen Qualitäts-Planer kennen lernen dürfen, der 
Softwareentwicklung verinnerlicht hätte.&lt;br /&gt;
Dort geht es dann leider immer nur um Kosmetik nach Außen und offensichtliche
Defekte, wenn bereits ein ganzer Wirtschaftszweig zusammengebrochen ist.&lt;/p&gt;

&lt;p&gt;Dabei müsste man schon in der Architekturplanung anfangen, auf 
“korrektes Arbeiten” zu achten, aber hier fehlt es - und ich bedauere 
dieses Urteil - leider oft an Intelligenz.&lt;/p&gt;

&lt;p&gt;However, ich freue mich daher im GATE Projekt zumindest teilweise beweisen zu 
können, dass &lt;em&gt;der Compiler unser Freund ist&lt;/em&gt;. Fast jede Warnung hat mich zu 
einer fehlerhaften oder unvollständigen Implementierung geführt, die ich somit
ausbessern konnte.&lt;br /&gt;
Und so sind die wenigen verbliebenen Warnungen auf Fremdbibliotheken 
zurückzuführen.&lt;/p&gt;

&lt;p&gt;Und ich kann nicht oft genug betonen, dass die Zeit zum Bereinigen von 
Sourcecode einen Bruchteil dessen verfrisst, was man dann Herumsuchen kann, 
wenn eine ignorierte Warnung- oder Fehlermeldung mal im Produktivsystem 
“schlagend” wird.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>#define MAX_PATH 260</title>
   <link href="https://www.opengate.at/blog/2020/07/max_path/"/>
   <published>2020-07-25T13:00:00+02:00</published>
   <updated>2020-07-25T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2020/07/max_path</id>
   <category term="devel" /><category term="retro" />
   <summary type="text">Bis zum heutigen Tag habe ich selbst noch kein “System” so unglücklich 
zusammengebaut, dass ich damit die alt-bekannte maximale Pfadlänge von 260 Zeichen 
im Windows Dateisystem konzeptionell überschritten hätte.

Aber nachdem ich berufsbedingt ja immer wieder mal mit CONAN 
arbeiten darf/muss, bekommen diese Grenzwerte nun auch für mich Bedeutung.
</summary>
   <content type="html">&lt;p&gt;Bis zum heutigen Tag habe ich selbst noch kein “System” so unglücklich 
zusammengebaut, dass ich damit die alt-bekannte maximale Pfadlänge von 260 Zeichen 
im Windows Dateisystem konzeptionell überschritten hätte.&lt;/p&gt;

&lt;p&gt;Aber nachdem ich berufsbedingt ja immer wieder mal mit &lt;a href=&quot;http://conan.io/&quot;&gt;CONAN&lt;/a&gt; 
arbeiten darf/muss, bekommen diese Grenzwerte nun auch für mich Bedeutung.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;dos-win16-und-win32&quot;&gt;DOS, Win16 und Win32&lt;/h3&gt;

&lt;p&gt;Ein &lt;a href=&quot;https://de.wikipedia.org/wiki/MS-DOS&quot;&gt;DOS&lt;/a&gt; Pfad 
(erkennbar an Laufwerksbuchstaben und Doppelpunkt am Anfang) besteht aus 3 
Zeichen am Anfang um das Gerät zu beschreiben, dann bis zu 256 Zeichen für
Verzeichnisse und Dateinamen und einem NULL-Zeichen als Terminator.&lt;/p&gt;

&lt;p&gt;Das macht dann 260 Zeichen und damit wir in &lt;a href=&quot;https://de.wikipedia.org/wiki/C_(Programmiersprache)&quot;&gt;C&lt;/a&gt;
ein lokales &lt;code&gt;char&lt;/code&gt;-Array allokieren können um dort Pfade hineinzupuffern, 
stellt die &lt;code&gt;&amp;lt;windows.h&amp;gt;&lt;/code&gt; das &lt;code&gt;MAX_PATH&lt;/code&gt; Makro genau dafür bereit.&lt;/p&gt;

&lt;p&gt;Das war unter DOS und &lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_3.x&quot;&gt;Windows 3.x&lt;/a&gt; 
mehr als genug, denn mit den damals üblichen “8.3” Dateinamen kann man mit 
maximal 12 Zeichen pro Ebene + 1 Backslash mindestens 19 Unterverzeichnisebenen
in so einem Pfad unterbringen.&lt;br /&gt;
Sind die Verzeichnisnamen kürzer, geht natürlich noch viel mehr.&lt;/p&gt;

&lt;p&gt;Dass Win32 dieses Limit übernommen hat, scheint mir schon ein bisschen “dumm”, 
Dass &lt;code&gt;MAX_PATH&lt;/code&gt; aus Kompatibilitätsgründen gleichbleiben muss, ist ja OK, 
aber dass die Windows-APIs die Längen von übergebenen Pfadpuffern prüfen und 
bei Überschreitung mit Fehlern abbrechen, das hätte nicht sein müssen.
(Muss wohl so ein Windows 95-Erbe gewesen sein, das NT infiziert hat.)&lt;/p&gt;

&lt;p&gt;Und so leben wir bis heute mit einem Limit von vor 30 Jahren, obwohl seit
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_NT_4.0&quot;&gt;NT 4&lt;/a&gt; Pfade bis 
32000 Zeichen lang sein dürfen, diese müssen dann aber der NT-Nomenklatur 
folgen und dürfen nicht mit DOS-Laufwerksbuchstaben beginnen.&lt;/p&gt;

&lt;p&gt;Die Katze beißt sich dann dummerweise in den Schwanz, wenn man das Spiel zwischen
App- und OS-Entwicklern verfolgt:&lt;/p&gt;

&lt;p&gt;Wenn User manuell einen NT-Pfad eintippen, z.B.:
&lt;code&gt;\\.\C:\Windows\System32\calc.exe&lt;/code&gt; und die App den String 1 zu 1 an die
APIs übergeben würden, dann wäre alles OK.&lt;/p&gt;

&lt;p&gt;Leider sind es dann Codes wie:&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt;(path[&lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;] == &lt;span style=&quot;color:#D20&quot;&gt;&apos;:&apos;&lt;/span&gt;) &lt;span style=&quot;color:#777&quot;&gt;// &amp;lt;- expect DOS path&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;        &lt;span style=&quot;color:#777&quot;&gt;// absolute path:&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;        open_path(path);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;}
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;else&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;        &lt;span style=&quot;color:#777&quot;&gt;// relative path:&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;        open_path(get_cwd() + path);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;die “künstlich” Fehler generieren, oder wenn am Ende wirklich ein
&lt;code&gt;TCHAR localpath[MAX_PATH];&lt;/code&gt; die Pfadlänge limitiert.&lt;/p&gt;

&lt;h3 id=&quot;gate-limits&quot;&gt;GATE Limits&lt;/h3&gt;

&lt;p&gt;Tatsächlich ist die GATE Implementierung an vielen Stellen auch nicht 
perfekt, aber ich versuche die Limits weiter nach oben zu schrauben,
wo es notwendig ist.&lt;/p&gt;

&lt;p&gt;Aktuell schreibt ein GATE-Makro &lt;code&gt;3072&lt;/code&gt; Zeichen als Maximale Grenze vor.&lt;/p&gt;

&lt;p&gt;Warum das?&lt;/p&gt;

&lt;p&gt;Nun, ich gehe davon aus, dass in einer Funktion durchschnittlich nicht
mehr als 2 Dateipfade vorliegen, einmal Input und einmal Output.&lt;/p&gt;

&lt;p&gt;Mit Windows-Unicodezeichen wären das dann 12288 Bytes. Damit bleiben
weitere 4 KByte übrig bis die empfohlene Stack-Puffer-Grenze von 16 KByte 
für Funktionen erreicht wurde.&lt;/p&gt;

&lt;p&gt;Würde man größere Puffer wie 4096 einsetzen, würden Code-Analyse Tools
in den meisten Datei I/O Routinen davor warnen, den Stack zu schnell
wachsen zu lassen.&lt;br /&gt;
Dieses Limit kann man natürlich beim Kompilieren anpassen, denn es stellt
ein absolutes “Minimum” für alle Plattformen dar.&lt;/p&gt;

&lt;p&gt;Generell wird auch so weit ich weiß unter Linux empfohlen, Pfade unter
1 KB Länge zu halten und 4 KB als Obergrenze anzusehen.
Und bisher bin ich mit meinen 3 KB immer gut gefahren.&lt;/p&gt;

&lt;h3 id=&quot;das-conan-problem&quot;&gt;Das CONAN Problem&lt;/h3&gt;

&lt;p&gt;Build-Systeme wie CONAN nutzen Hashes als Unterverzeichnisse um ihre
Buildumgebungen abzutrennen. Hat man nun viele Unterverzeichnisse im
Sourcecode, summieren sich schnell Pfade über den 260 Zeichen auf.&lt;/p&gt;

&lt;p&gt;Es gibt zwar die Einstellung &lt;a href=&quot;http://docs.conan.io/en/latest/reference/conanfile/attributes.html#short-paths&quot;&gt;&lt;code&gt;short_paths&lt;/code&gt;&lt;/a&gt;,
doch auch die kann dann nicht immer helfen.&lt;/p&gt;

&lt;p&gt;Ärgerlich ist, dass man auch dieses Tool nicht dazu bringen kann, NT-Pfade
für alle Operationen einzusetzen. 
Und somit muss man wieder Workarounds ausarbeiten um die Pfade künstlich
kurz zu halten.&lt;/p&gt;

&lt;p&gt;Auch Visual Studio und sein Build System haben zu langen Pfaden Probleme.
Dabei wäre es so einfach mit einem vorangestellten &lt;code&gt;\\.\&lt;/code&gt; sämtliche Pfade
längenunabhängig zu unterstützen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Windows 10 hat die 260 Zeichengrenze bereits fallen gelassen und die WinAPI
frisst nun auch längere Parameter. Dennoch sind bei weitem nicht alle Apps
in der Lage mit mehr als 260 Zeichen arbeiten zu können.&lt;/p&gt;

&lt;p&gt;Und so lange in Frameworks der &lt;code&gt;MAX_PATH&lt;/code&gt; auch nur ein einziges Mal vorkommt,
so lange limitieren wir uns auf das vergangene Jahrhundert zurück.&lt;/p&gt;

&lt;p&gt;Ich selbst werde das Thema Pfadpuffer aber auch noch mal angehen.
Zwar bin ich mit 3K-chars fast 12x besser vorbereitet … aber “unabhängig” ist
das eben auch nicht …&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Es gibt also noch viel zu tun.&lt;/em&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>SD Karten</title>
   <link href="https://www.opengate.at/blog/2020/07/sd-cards/"/>
   <published>2020-07-19T13:00:00+02:00</published>
   <updated>2020-07-19T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2020/07/sd-cards</id>
   <category term="hardware" />
   <summary type="text">In Star Trek Next Generation
war mal die Rede von Naniten, die 1 GB Speicher hätten haben sollen.


  Das ist wirklich utopisch bzw. pure Übertreibung


dachte ich damals in den 90ern.

Und heute haben SD-Karten kleiner 
als ein Daumennagel Kapazitäten von einem Terabyte und mehr. … also kann 
man schon sagen, dass 1 GB Daten nur mehr die Größe ein paar Körperzellen 
hat …
</summary>
   <content type="html">&lt;p&gt;In &lt;a href=&quot;https://de.wikipedia.org/wiki/Raumschiff_Enterprise_%E2%80%93_Das_n%C3%A4chste_Jahrhundert&quot;&gt;Star Trek Next Generation&lt;/a&gt;
war mal die Rede von Naniten, die 1 GB Speicher hätten haben sollen.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Das ist wirklich utopisch bzw. pure Übertreibung&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;dachte ich damals in den 90ern.&lt;/p&gt;

&lt;p&gt;Und heute haben &lt;a href=&quot;https://de.wikipedia.org/wiki/SD-Karte&quot;&gt;SD-Karten&lt;/a&gt; kleiner 
als ein Daumennagel Kapazitäten von einem Terabyte und mehr. … also kann 
man schon sagen, dass 1 GB Daten nur mehr die Größe ein paar Körperzellen 
hat …
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;SD-Karten wurden anfangs als Ersatz für Datenspeicher in Videokameras 
entwickelt und waren im PC nur eine Art “Zusatzspeicher”.&lt;br /&gt;
Doch nach und nach wurden sie eine günstige Alternative zu normalen
Festplatten und &lt;a href=&quot;https://de.wikipedia.org/wiki/Solid-State-Drive&quot;&gt;SSDs&lt;/a&gt; 
von denen Betriebssysteme gestartet werden konnten. 
Der &lt;a href=&quot;https://de.wikipedia.org/wiki/Raspberry_Pi&quot;&gt;Raspberry PI&lt;/a&gt; und alle 
seine &lt;a href=&quot;https://de.wikipedia.org/wiki/System-on-a-Chip&quot;&gt;SoC&lt;/a&gt; Verwandten tun das.&lt;/p&gt;

&lt;p&gt;Aber auch für &lt;a href=&quot;https://de.wikipedia.org/wiki/Mikrocontroller&quot;&gt;Mikrocontroller&lt;/a&gt;
sind die Karten eine interessante Lösung um entweder Daten zu lesen oder 
Informationen zu speichern.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/sd-card-spi-boards.jpg&quot; alt=&quot;SD-Card-SPI-Board&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;spi-als-schnittstelle-zur-sd-karte&quot;&gt;SPI als Schnittstelle zur SD Karte&lt;/h3&gt;

&lt;p&gt;Das &lt;a href=&quot;https://de.wikipedia.org/wiki/Serial_Peripheral_Interface&quot;&gt;Serial Peripheral Interface&lt;/a&gt;
(kurz SPI) setzt 4 Leitungen ein, die direkt mit entsprechenden Pins der 
SD-Karte verbunden werden, denn jede SD-Karte sollte den SPI-Modus zur 
Datenübertragung unterstützen.&lt;/p&gt;

&lt;p&gt;Nachdem unsere Controller der &lt;a href=&quot;https://de.wikipedia.org/wiki/Master/Slave&quot;&gt;Master und die Karte der Slave&lt;/a&gt;
ist, werden Bits am &lt;code&gt;MOSI&lt;/code&gt; Anschluss vom der MCU zur Karte gesendet, während 
gleichzeitig die Karte über &lt;code&gt;MISO&lt;/code&gt; Daten zurücksenden kann. 
Ob ein Bit mit 0 oder 1 übertragen wird, wird über den Taktgeber
(&lt;code&gt;SCK&lt;/code&gt; - Clock) ermittelt. Immer wenn die von LOW auf HIGH wechselt,
wird gemessen, ob an &lt;code&gt;MOSI&lt;/code&gt; oder &lt;code&gt;MISO&lt;/code&gt; ein Spannung (HIGH) anliegt.
Beim Arduino UNO liegen &lt;code&gt;SCK&lt;/code&gt; auf Pin 13, &lt;code&gt;MOSI&lt;/code&gt; auf Pin 12 und 
&lt;code&gt;MISO&lt;/code&gt; auf Pin 11.&lt;/p&gt;

&lt;p&gt;Die 4. Leitung heißt Chip-Select (CS) manchmal auch Slave-Select (SS) genannt
und ist seitens der MCU ein Output-Pin auf HIGH wenn KEINE Kommunikation
stattfinden soll. Sobald Daten ausgetauscht werden sollen, muss CS/SS 
auf LOW wechseln.&lt;br /&gt;
So lassen sich mehrere SPI-Slaves parallel betreiben, die abwechselnd auf
LOW (an) und HIGH (aus) geschaltet werden.
Beim Arduino Uno ist laut Standard Pin 10 für &lt;code&gt;CS&lt;/code&gt; vorgesehen, aber es kann
auch jeder andere digitale Pin genutzt werden um ein Gerät für SPI zu 
aktivieren.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/arduino-uno-i2c-spi-pins.jpg&quot; alt=&quot;Arduino UNO SPI&quot; /&gt;
&lt;img src=&quot;/blog/assets/img/sd-card-spi-boards-back.jpg&quot; alt=&quot;SD-Card-SPI-Board Backside&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;dateisysteme-nutzen&quot;&gt;Dateisysteme nutzen&lt;/h3&gt;

&lt;p&gt;Das binäre Protokoll ist im SD-Standard dokumentiert, aber man kann es sich
auch aus der SD-Bibliothek herleiten, die bei der Arduino IDE mitgeliefert
wird.&lt;/p&gt;

&lt;p&gt;Neben Initialisierung und Zustandsinfos abfragen fall die Read- und
Write-Kommandos ins Auge. Sie lassen einen Block durch eine 32 Bit
Adressierung auslesen. Bei einer üblichen Block-Größe von 512 Bytes
kommen wir also auf ein Maximum von 2 Terabyte, die man über diese
Schnittstelle bearbeiten kann.&lt;/p&gt;

&lt;p&gt;Ebenfalls in der Arduino SD-Bibliothek integriert ist ein kleiner 
&lt;a href=&quot;https://de.wikipedia.org/wiki/File_Allocation_Table&quot;&gt;FAT und FAT32&lt;/a&gt; Treiber, 
der Dateisystemoperationen einfachst auf SD-Karten Blocklese- und 
Schreibaktionen übersetzt.&lt;/p&gt;

&lt;p&gt;Man kann so per Code Dateien anlegen und mit z.B. Sensorwerten befüllen.&lt;br /&gt;
Umgekehrt lassen sich natürlich auch Dateien öffnen und auslesen, womit
man Stück für Stück ein Bild auslesen und z.B.: auf ein LCD-Display
zeichnen kann.&lt;/p&gt;

&lt;p&gt;Das muss man natürlich Stückweise tun, denn die 2 KByte RAM eines 
Arduino UNO können unmöglich ein 320x240 Pixel Bild als Ganzes 
aufbewahren.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Die Tatsache, dass es heute so unglaublich einfach ist auch reguläre
Speichermedien wie SD-Karten mit einer Hand voll Zeilen auf einer MCU 
anzusprechen, versetzt mich immer wieder ins Staunen.&lt;/p&gt;

&lt;p&gt;Wenn ich daran denke, wie kompliziert im Vergleich &lt;a href=&quot;https://de.wikipedia.org/wiki/BIOS&quot;&gt;BIOS&lt;/a&gt;
Aufrufe am PC zu &lt;a href=&quot;https://de.wikipedia.org/wiki/MS-DOS&quot;&gt;DOS&lt;/a&gt; Zeiten früher 
waren um Bytes auf eine Diskette zu schreiben, dagegen ist die Programmierung 
eines SD-Karten Datenloggers heute ein Klacks.&lt;/p&gt;

&lt;p&gt;Ich gebe zu bisher eher wenig mit SD-Karten auf MCUs in der Praxis gearbeitet
zu haben, schließlich muss ich bei mir zu Hause nichts loggen … und wenn 
ich es müsste, wäre immer die Einstellung der Uhrzeit ein kritisches Thema.&lt;/p&gt;

&lt;p&gt;Aber diese Technik - davon bin ich überzeugt - wird mir in künftigen
Projekten noch sehr gute und vor allem notwendige Dienste leisten. 
Denn Parameter für ein Embedded System lassen sich über dieses 
Medium immer noch am leichtesten übertragen. 
Einfach eine Karte in den PC stecken, Datei anlegen, in den MCU-
SD-Slot stecken und der dort laufende Code liest die Änderungen
aus um sie anzuwenden.&lt;/p&gt;

&lt;p&gt;Ja, so stelle ich mir das vor!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>SEN-ACT</title>
   <link href="https://www.opengate.at/blog/2020/07/senact/"/>
   <published>2020-07-18T13:00:00+02:00</published>
   <updated>2020-07-18T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2020/07/senact</id>
   <category term="devel" /><category term="projects" />
   <summary type="text">Das SENsor-ACTor-Protokoll, kurz SENACT, ist mein aktueller Versuch meine
heimischen IoT Experimente 
unter einen Hut zu bekommen.

Und ja, es soll eine Eigenlösung sein … weil … ich habe einfach überhaupt
keine Freude daran “etwas Fertiges” herunterzuladen, was dann am Ende eben
nicht so funktioniert, wie ich es möchte.
</summary>
   <content type="html">&lt;p&gt;Das SENsor-ACTor-Protokoll, kurz SENACT, ist mein aktueller Versuch meine
heimischen &lt;a href=&quot;https://de.wikipedia.org/wiki/Internet_der_Dinge&quot;&gt;IoT&lt;/a&gt; Experimente 
unter einen Hut zu bekommen.&lt;/p&gt;

&lt;p&gt;Und ja, es soll eine Eigenlösung sein … weil … ich habe einfach überhaupt
keine Freude daran “etwas Fertiges” herunterzuladen, was dann am Ende eben
nicht so funktioniert, wie ich es möchte.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;zielsetzung&quot;&gt;Zielsetzung&lt;/h3&gt;

&lt;p&gt;Ich hätte gerne eine Codebase, die überall (und zwar wirklich überall) läuft
und numerische Werte mit ein paar Metadaten senden und empfangen kann.&lt;/p&gt;

&lt;p&gt;Gesteuert werden soll:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Das Anfragen bzw Publizieren von Abmessungen von Sensoren&lt;/li&gt;
  &lt;li&gt;Das setzen von Zuständen in Aktoren (wie z.B. Motoren oder Status-LEDs)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;handycap-bitte-ohne-memcpy&quot;&gt;Handycap: Bitte ohne memcpy()&lt;/h3&gt;

&lt;p&gt;Tja, ein bisschen schwierig soll es schon sein. Und nachdem ich ohnehin dezent
verstört bin, wie unterschiedlich die unterstützen Funktionen in Embedded- und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Mikrocontroller&quot;&gt;MCU&lt;/a&gt;-Dev-Kits sind, soll die 
Bibliothek auf gar nichts von außen angewiesen sein.&lt;/p&gt;

&lt;p&gt;Aber mal ehrlich, &lt;code&gt;memcpy()&lt;/code&gt; ist auf 8-bit System selten etwas anderes als:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt; memcpy(&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;* dst, &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt;* src, size_t count)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt;* ptr_dst = (&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt;*)dst;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt;* ptr_src = (&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt;*)dst;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;while&lt;/span&gt;(count-- != &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  {
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;    *(ptr_dst++) = *(ptr_src++);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;  }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Und diesen 10-Zeiler kann man ja auch selbst ausliefen und schon ist man von
der Standard-Bibliothek (bzw. deren nicht-vorhanden-sein) unabhängig.&lt;/p&gt;

&lt;h3 id=&quot;zeilen-basierte-kommunikation&quot;&gt;Zeilen-basierte Kommunikation&lt;/h3&gt;

&lt;p&gt;Die Bibliothek übersetzt eine Anfrage in einen Byte-Puffer, der auf der 
Zielplattform nur noch versendet werden muss. Umgekehrt kann aus einem
gelesenen Byte-Puffer wieder eine Nachricht dekodiert werden.&lt;/p&gt;

&lt;p&gt;Trennzeichen ist &lt;code&gt;LF&lt;/code&gt; (also das von Linux bekannt Line-Feed Zeichen) oder
alternativ &lt;code&gt;CR&lt;/code&gt; (also ENTER), oder beide, die ein Zeilenende beschreiben.&lt;/p&gt;

&lt;p&gt;Die Daten in der Zeile sollen nur aus Text-Zeichen (Zahlen und Buchstaben)
bestehen. Womit man eine Steuerung per Tastatur manuell durchführen kann.&lt;/p&gt;

&lt;p&gt;Im Unterschied zu AT-Kommandos sind Anfragen und Antworten aber immer
einzeilig, was ein komplexes Parsing von mehrzeiligen Blöcken verhindert.&lt;/p&gt;

&lt;p&gt;Vorgesehen ist auch ein optionaler User-Parameter in Anfragen, der bei
Antworten wieder zurückgeschickt wird. So können viele Anfragen parallel
verschickt und die Antworten exakt zugeordnet werden.&lt;/p&gt;

&lt;h3 id=&quot;status&quot;&gt;Status&lt;/h3&gt;

&lt;p&gt;Die Implementierung findet zwar im Rahmen des GATE Projektes statt, ist aber
vollkommen davon unabhängig und eine simple C-Header-Only Lösung.&lt;br /&gt;
Ich überlege allerdings hieraus ein eigenes Projekt zu machen und diese
mit Anbindungen an Arduino und an GATE auszustatten.&lt;/p&gt;

&lt;p&gt;Am Ende soll der gleiche Code am Mikrocontroller und in einer GATE
App die Kommunikationsübersetzung vornehmen. Dann sind nur noch Treiber
für die gewünschten Geräte an SENACT anzubinden und schon kann man 
(fast) alles fernsteuern.&lt;/p&gt;

&lt;p&gt;Ich hoffe mir bleibt ausreichend Zeit, die Umsetzung vorantreiben.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>RS232 nach TTL mit dem MAX3232</title>
   <link href="https://www.opengate.at/blog/2020/07/rs232-to-ttl/"/>
   <published>2020-07-12T13:00:00+02:00</published>
   <updated>2020-07-12T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2020/07/rs232-to-ttl</id>
   <category term="hardware" />
   <summary type="text">Wer seinen Arduino UNO oder 
anderen Lieblings-Mikrocontroller direkt an die seriellen PINs des PCs
ansteckt, grillt diesen gut durch.

Denn die -12 V bis +12 V Signale von RS232
sind für 0 - 3.3 Volt oder 0 - 5 Volt der Chips VIEL zu VIEL.

Also schiebt man einen Logikwandler
dazwischen, der die Signale entweder hoch- oder heruntertransformiert.

Und der MAX3232
ist ein solches Teil … also auf zum Lötkolben.
</summary>
   <content type="html">&lt;p&gt;Wer seinen &lt;a href=&quot;https://en.wikipedia.org/wiki/Arduino_Uno&quot;&gt;Arduino UNO&lt;/a&gt; oder 
anderen Lieblings-Mikrocontroller direkt an die seriellen PINs des PCs
ansteckt, grillt diesen gut durch.&lt;/p&gt;

&lt;p&gt;Denn die -12 V bis +12 V Signale von &lt;a href=&quot;https://de.wikipedia.org/wiki/RS-232&quot;&gt;RS232&lt;/a&gt;
sind für 0 - 3.3 Volt oder 0 - 5 Volt der Chips VIEL zu VIEL.&lt;/p&gt;

&lt;p&gt;Also schiebt man einen &lt;a href=&quot;https://de.wikipedia.org/wiki/Pegelumsetzer&quot;&gt;Logikwandler&lt;/a&gt;
dazwischen, der die Signale entweder hoch- oder heruntertransformiert.&lt;/p&gt;

&lt;p&gt;Und der &lt;a href=&quot;https://www.maximintegrated.com/en/products/interface/transceivers/MAX3232.html&quot;&gt;MAX3232&lt;/a&gt;
ist ein solches Teil … also auf zum Lötkolben.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Für Arduino-zu-PC-Verbindungen nutze ich gerne Chips wie den 
&lt;a href=&quot;https://www.silabs.com/interface/usb-bridges/classic/device.cp2102&quot;&gt;CP2102&lt;/a&gt;, 
der über &lt;a href=&quot;https://de.wikipedia.org/wiki/Universal_Serial_Bus&quot;&gt;USB&lt;/a&gt; eine 
virtuelle COM-Schnittstelle einrichtet, damit man Daten austauschen kann.&lt;/p&gt;

&lt;p&gt;Allerdings haben ja auch heute noch viele PCs (und vor allem meine kleinen
&lt;a href=&quot;https://de.wikipedia.org/wiki/Mini-ITX&quot;&gt;ITX&lt;/a&gt; Kisten) eine native serielle 
Schnittstelle verbaut.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Warum kann man denn diese nicht nutzen?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;frage ich mich schon länger … und mit dem MAX3232 wird das nun auch möglich.&lt;/p&gt;

&lt;p&gt;10 Stück des kleinen Chips, bekommt man in Fernost um unter 2 Euro 
(exklusive Versand). Das nenne ich ein Geschenk, und deshalb habe ich mir damit
sofort eine Freude gemacht.&lt;/p&gt;

&lt;p&gt;Die kleine Platine gestattet nur das Senden und Empfangen von Daten und
verzichtet darauf, weitere RS232 Leitungen bereitzustellen, die der Chip 
sehr wohl übersetzen kann.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/serial-max3232.jpg&quot; alt=&quot;MAX3232&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Aber für kleine Arduino Datenaustauschereien reichen TX und RX vollkommen aus
und genau deshalb ist der kleine Chip eine gute (und vor allem preiswerte)
Investition gewesen.&lt;/p&gt;

&lt;h3 id=&quot;rs232-gerät-on-board&quot;&gt;RS232 Gerät “on-board”&lt;/h3&gt;

&lt;p&gt;Tatsächlich haben viele Mainboards immer noch einen COM1 Port der aber gar 
nicht mehr als Buchse nach außen geleitet wird.&lt;br /&gt;
Man kann aber einen Flachbandstecker im Gehäuse nutzen um an die Pins zu 
kommen.&lt;/p&gt;

&lt;p&gt;Hier lässt sich der kleine Chip problemlos “dazwischen klemmen” um einen
Mikrocontroller anzusprechen.&lt;/p&gt;

&lt;p&gt;Eine klassische Anwendung wäre die Steuerung eines Lüfters über die 
Umgebungstemperatur, die eine MCU übernimmt und parallel ihre Daten zum
Mainboard sendet und Konfigurationen entgegennimmt.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/serial-max3232-soldered.jpg&quot; alt=&quot;MAX3232&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;externer-adapter-marke-eigenbau&quot;&gt;Externer Adapter Marke Eigenbau&lt;/h3&gt;

&lt;p&gt;Nachdem der Lötkolben schon warm war, lag es mir nicht fern, auch noch einen
&lt;a href=&quot;https://de.wikipedia.org/wiki/D-Sub&quot;&gt;DSUB&lt;/a&gt; 9 Stecker mit dem neuen Chip zu 
basteln.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/serial-max3232-board.jpg&quot; alt=&quot;MAX3232&quot; /&gt;&lt;/p&gt;

&lt;p&gt;So lassen sich auch meine älteren Boards ohne Verschwendung eines
USB Ports direkt mit einem Mikrocontroller verbinden.&lt;br /&gt;
Einiger Nachteil: Die MCU muss den Chip mit Strom versorgen.&lt;/p&gt;

&lt;p&gt;Allerdings unterlief mir bei der Herstellung ein fataler Fehler:&lt;br /&gt;
Ich verwechselte die PIN-Reihenfolge und verdrahtete anfangs alles
spiegelverkehrt.&lt;/p&gt;

&lt;p&gt;Zum Glück hat der Chip die Verpolung gut überstanden und ließ sich
nach der Korrektur der Anschlussreihenfolge regulär betreiben.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Wieder ein Teil bzw. eine Teileserie, die mir Freude bereit hat.
So billig kann ich also USB Ports einsparen.&lt;br /&gt;
Nicht schlecht!&lt;/p&gt;

&lt;p&gt;Kurz gesagt: Dieses Teil sollte in keiner IOT Bastlerwerkstatt fehlen!&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Fun-Fact am Rande: Eigentlich ist der MAX3232 aktuell für mich 
“nicht notwendig”. Denn da ich wegen der Corona-Krise dachte, dass
eine Bestellung abgebrochen wurde, habe ich eine Serien von CP2102 
Modulen erneut bestellt.&lt;br /&gt;
Am Ende kamen beide Lieferungen an und somit habe ich aktuell gerade
einen Überfluss an CP2102 Chips.&lt;br /&gt;
Trotzdem, die USB-freie Variante gefällt mir einfach.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Versionierung</title>
   <link href="https://www.opengate.at/blog/2020/07/version/"/>
   <published>2020-07-11T13:00:00+02:00</published>
   <updated>2020-07-11T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2020/07/version</id>
   <category term="software" /><category term="projects" />
   <summary type="text">Das für mich wichtigste Feature an SVN
war die zentrale inkrementell hochgezählte Revisionsnummer, aus welcher man 
herrlich eine “Programmversion” bauen konnte.

Doch mit GIT also Versionskontrollsystem 
muss man sich etwas anderes überlegen.

Wie werden also Software Versionen
für Releases erstellt?
</summary>
   <content type="html">&lt;p&gt;Das für mich wichtigste Feature an &lt;a href=&quot;https://de.wikipedia.org/wiki/Apache_Subversion&quot;&gt;SVN&lt;/a&gt;
war die zentrale inkrementell hochgezählte Revisionsnummer, aus welcher man 
herrlich eine “Programmversion” bauen konnte.&lt;/p&gt;

&lt;p&gt;Doch mit &lt;a href=&quot;https://de.wikipedia.org/wiki/Git&quot;&gt;GIT&lt;/a&gt; also Versionskontrollsystem 
muss man sich etwas anderes überlegen.&lt;/p&gt;

&lt;p&gt;Wie werden also &lt;a href=&quot;https://en.wikipedia.org/wiki/Software_versioning&quot;&gt;Software Versionen&lt;/a&gt;
für Releases erstellt?
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;früher-war-alles-einfach-mit-svn&quot;&gt;Früher war alles einfach (mit SVN)&lt;/h3&gt;

&lt;p&gt;Besonders von Windows aber auch ganz allgemein kennen wir alle das Schema:&lt;br /&gt;
&lt;code&gt;major.minor.patch.build&lt;/code&gt;, also&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Hauptversion&lt;/li&gt;
  &lt;li&gt;Nebenversion&lt;/li&gt;
  &lt;li&gt;Fehlerbehebung&lt;/li&gt;
  &lt;li&gt;Fortlaufende Nummer pro Kompilat&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;code&gt;major&lt;/code&gt; und &lt;code&gt;minor&lt;/code&gt; Version definieren den “Feature-Level”, sollen also 
Fortschritte bei der Funktionalität festlegen und das Patch-Level erhöht sich
bei jedem Neubau wegen einer Fehlerbehebung.
Eindeutig identifiziert wird jedes gebaute Produkt aber durch die Build-Nummer, 
die Systeme wie SVN automatisch (und vor allem zentral) hochzählt.&lt;/p&gt;

&lt;p&gt;Die Entwicklungsabteilung kann also ihre Arbeit machen und Releases mit einer
speziellen Build-Nummer bereitstellen, die dann getestet werden.&lt;br /&gt;
Läuft alles wie gewünscht erfolgt die Freigabe und man kann die Build-Nummer 
einfrieren und später von diesem Stand aus neue Patches implementieren.&lt;/p&gt;

&lt;h3 id=&quot;git-ist-eben-anders&quot;&gt;GIT ist eben anders&lt;/h3&gt;

&lt;p&gt;Fortlaufende Build-Nummern sind mit GIT unmöglich, da das Aufspalten und
spätere Zusammenführen von Entwicklungsständen keinem linearen Schema
folgt - es fehlt die zentrale Versionskontrolle. Somit hat jeder Commit zwar
einen eindeutigen Hash-Wert, dieser ist aber nicht chronologisch sortierbar.&lt;/p&gt;

&lt;p&gt;Anstatt dessen wird dem “Release-Management” aufgebürdet sich eine “passende”
Versionsnummer auszudenken, die dann mit einem spezifischen Commit verknüpft
wird. Man “tagged” also den Stand, den man mit einer Version verbinden möchte.&lt;/p&gt;

&lt;p&gt;Aber wie sieht dieser Tag nun aus?&lt;/p&gt;

&lt;p&gt;Eigentlich besteht er nur aus &lt;code&gt;major.minor&lt;/code&gt; oder &lt;code&gt;major.minor.patch&lt;/code&gt;
falls man einen Fehler ausbessern möchte.&lt;/p&gt;

&lt;p&gt;Für mich bedeutet das aber, dass &lt;code&gt;minor&lt;/code&gt; nun viel spezifischer darstellen
muss, was eine Software beinhaltet. Schließlich gibt es keine 
chronologische Buildnummer mehr, die zwischen einem “alten” und “neueren”
Stand differenziert.&lt;/p&gt;

&lt;h3 id=&quot;das-status-dilemma&quot;&gt;Das Status-Dilemma&lt;/h3&gt;

&lt;p&gt;Im GATE Projekt gibt es für mich aktuell keinen festen Entwicklungsplan 
(leider), dennoch kann ich grob Feature-Wünsche nennen.&lt;br /&gt;
Bibliotheken unterscheiden sich von “einfachen” Programmen durch an anderes
Maß an Funktionalität. Dieses ist generischer und weniger konkret ausgeprägt,
als dies bei spezifischen Applikationen der Fall ist.&lt;/p&gt;

&lt;p&gt;Eine Lib-Funktion nach dem Schema: &lt;em&gt;“Kann mit XYZ Geräten kommunizieren”&lt;/em&gt;
ist komplizierter zu vervollständigen also ein einfaches:
&lt;em&gt;“Hat einen Button um Gerät XYZ das Kommando ABC zu senden”&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Zweiteres ist nur eine Untermenge von ersterem.&lt;/p&gt;

&lt;p&gt;Hinzu kommt außerdem, dass für mehrere Plattformen mehrere Implementierung 
notwendig sein können.&lt;/p&gt;

&lt;p&gt;Eine mögliche inkrementelle Versionierung wäre dann als Summe aller 
implementierten Features möglich.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Windows Filehandling&lt;/li&gt;
  &lt;li&gt;Linux Filehandling&lt;/li&gt;
  &lt;li&gt;Windows Messagebox&lt;/li&gt;
  &lt;li&gt;X11/Linux Messagebox&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;würden zu einer Feature-ID oder Minor-Verison &lt;code&gt;x.4&lt;/code&gt; führen.
Eine Erhöhung der Major-Version würde dann den bestehen Featurestand
fixieren und Minor wieder bei Null weiterzählen lassen.&lt;/p&gt;

&lt;p&gt;Ich überlege mir daher aktuell eine Art von Feature-Textdatei anzulegen,
aus der dann automatisch eine Versionsnummer generiert werden kann.
Dafür wäre es aber wichtig alle Änderungen und Feature-Updates mit 
einer Überschrift zu versehen.&lt;br /&gt;
Das wäre auch gleichzeitig eine Historie, die jeder “Version” einen
Featurestand textual zuordnen könnte.&lt;/p&gt;

&lt;p&gt;Es gäbe auch die Möglichkeit die Anzahl der Commits im Entwicklungszweig
zu zählen und daraus eine ID zu erstellen.&lt;br /&gt;
&lt;code&gt;git rev-list --count master&lt;/code&gt; wäre ein solches Beispiel.
Ein solcher Commit-Counter könnte in einen Tag übernommen werden,
wenn ein Stand eingefroren wird.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Kurz gesagt, ich weiß noch nicht so recht, wie ich hier weiter vorgehen
werde. Aber eine Form der Versionierung wird auch im GATE Projekt notwendig
werden.&lt;/p&gt;

&lt;p&gt;Es ist schließlich auch für einen selbst wichtig den Fortschritt nachvollziehen
zu können und die “Feature”-Zählung scheint mir für eine Bibliothek durchaus
schlüssig.&lt;/p&gt;

&lt;p&gt;Mal sehen ob sich das Schema für mich bewährt.&lt;/p&gt;

&lt;p&gt;PS: Es bleibt natürlich die Frage offen, wann genau die Major-Version erhöht
wird … aber das ist wie so oft rein “subjektiv” zu entscheiden.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>UI Fallhöhe gestern und heute</title>
   <link href="https://www.opengate.at/blog/2020/07/ui-height/"/>
   <published>2020-07-05T13:00:00+02:00</published>
   <updated>2020-07-05T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2020/07/ui-height</id>
   <category term="hardware" /><category term="software" />
   <summary type="text">In den Anfängen von Windows (OK, ich meine in Wahrheit ab 3.x)
war die Sache ganz einfach:
Die Standardauflösung von Monitoren (und Grafikkarten) lag bei 640 x 480 Pixel.
Und somit waren alle Anwendungen und UI Dialoge
auf dieses Maximum ausgelegt.

Heute hingegen lassen sich Systeme mit Monitoren mit maximal 480 Pixel Höhe
einfach nicht mehr bedienen.

W-T-F …
</summary>
   <content type="html">&lt;p&gt;In den Anfängen von &lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_3.x&quot;&gt;Windows (OK, ich meine in Wahrheit ab 3.x)&lt;/a&gt;
war die Sache ganz einfach:&lt;br /&gt;
Die Standardauflösung von Monitoren (und Grafikkarten) lag bei 640 x 480 Pixel.
Und somit waren alle Anwendungen und &lt;a href=&quot;https://de.wikipedia.org/wiki/Dialog_(Benutzeroberfl%C3%A4che)&quot;&gt;UI Dialoge&lt;/a&gt;
auf dieses Maximum ausgelegt.&lt;/p&gt;

&lt;p&gt;Heute hingegen lassen sich Systeme mit Monitoren mit maximal 480 Pixel Höhe
einfach nicht mehr bedienen.&lt;/p&gt;

&lt;p&gt;W-T-F …
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Mein 35 Euro teurer 7 Zoll Mini-Monitor wurde eigentlich nur für das lokale 
Setup von Test-Systemen angeschafft.&lt;br /&gt;
Mit einer Auflösung von 800 x 480 Pixel kann es Problemlos Text-Konsolen
anzeigen und somit die wichtigsten Schritte abdecken.&lt;/p&gt;

&lt;p&gt;… dachte ich, denn sowohl &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows&quot;&gt;Windows&lt;/a&gt;
wie auch &lt;a href=&quot;https://de.wikipedia.org/wiki/X_Window_System&quot;&gt;grafische Linux&lt;/a&gt; 
Setups bauen heute ihre Setup-Dialog mit offenbar “höheren” Anforderungen aus.
Und dann sind plötzlich die “OK” und “Weiter” Schaltflächen außerhalb des
Anzeigebereiches.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/monitor-7inch.jpg&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Manchmal kann man diese Dialogfenster noch irgendwie per Tastatur so 
verschieben, dass mal der obere Teil und mal der untere Teil nicht sichtbar
ist und das jeweilige Gegenteil “bedienbar” wird.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ALT + Leertaste&lt;/code&gt; öffnet unter Windows übrigens das Fenster-Menü, wo man das 
“Verschieben” starten kann und per Pfeiltasten das Fenster in den 
und aus dem Bildschirmbereich bewegen kann.&lt;/p&gt;

&lt;p&gt;Aber auch das klappt nicht immer.&lt;/p&gt;

&lt;p&gt;Am schlimmsten ist aber ein “modernes” &lt;a href=&quot;https://de.wikipedia.org/wiki/BIOS&quot;&gt;BIOS&lt;/a&gt;
Setup, das natürlich auch grafisch sein muss.&lt;br /&gt;
Da ist man dann nämlich “echt im Arsch”, wenn der Setup-Screen für den 
angeschlossenen Monitor zu groß ist.&lt;/p&gt;

&lt;p&gt;Wieso gibt es denn da keine &lt;em&gt;Use-Text-Interface&lt;/em&gt;-Taste?&lt;/p&gt;

&lt;h3 id=&quot;lösung-scrollbars-in-apps-einbauen&quot;&gt;Lösung: Scrollbars in Apps einbauen&lt;/h3&gt;

&lt;p&gt;Natürlich würde eine kluge Anwendung feststellen, dass sie zu groß für den
Monitor ist und sich selbst verkleinern um dann per Scrollbars
(auch &lt;a href=&quot;https://de.wikipedia.org/wiki/Bildlaufleiste&quot;&gt;Bildlaufleiste&lt;/a&gt; genannt)
zum gewünschten Element navigieren zu können.&lt;/p&gt;

&lt;p&gt;Aber genau darauf wird bei “Dialogen” gerne vergessen.&lt;br /&gt;
Und das verstehe ich, mache ich doch eigentlich seit 20 Jahren genau den 
gleichen Fehler.&lt;br /&gt;
Man geht immer von seinem eigenen Monitor aus, der immer groß genug ist um
alles anzuzeigen und setzt voraus, dass jeder Anwender mindestens ebenso 
gut bestückt ist.&lt;/p&gt;

&lt;h3 id=&quot;lösung-2-remote-access&quot;&gt;Lösung 2: Remote Access&lt;/h3&gt;

&lt;p&gt;Wenn man “irgendwie” durch das Standardsetup durchgekommen ist, sollte 
man sofort auf Fernsteuerung umstellen.&lt;br /&gt;
In Windows sollte der &lt;a href=&quot;https://de.wikipedia.org/wiki/Remote_Desktop_Protocol&quot;&gt;RDP&lt;/a&gt;
aktiviert werden (hoffentlich sind dessen Einstellungsdialoge nutzbar) und 
unter Linux kann das Paket &lt;code&gt;xrdp&lt;/code&gt; eine vergleichbare UI Lösung bieten.&lt;/p&gt;

&lt;p&gt;Ansonsten hilft vielleicht auch noch eine 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Virtual_Network_Computing&quot;&gt;VNC Variante&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Ähm … das betrifft natürlich nur UI Anwendungen, weil “die richtige”
Administration sollte ja ohnehin per Kommandozeile über &lt;a href=&quot;https://de.wikipedia.org/wiki/PowerShell&quot;&gt;PowerShell&lt;/a&gt;,
&lt;a href=&quot;https://en.wikipedia.org/wiki/Windows_Remote_Management&quot;&gt;WinRM&lt;/a&gt;, 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Secure_Shell&quot;&gt;SSH&lt;/a&gt; oder Webinterface stattfinden.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Tja, ich habe da wirklich Nachholbedarf im GATE Projekt.&lt;br /&gt;
Das “automatische” Aufbauen eines Scrollbar-Systems wenn notwendig habe
ich nämlich derzeit noch nicht implementiert.&lt;/p&gt;

&lt;p&gt;Aber genau so ein UI-Feature sollte zur Verfügung stehen um es einfach
einschalten zu können. Denn niemand (wie die meisten Apps zeigen)
implementiert für jeden seiner Dialoge manuell Scrollbar-Features.&lt;/p&gt;

&lt;p&gt;Nun, dass Microsoft heute 800x600 für &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_PE&quot;&gt;Windows PE&lt;/a&gt;
erzwingt, habe ich ja erwartet, aber dass auch Linux-Setups nicht “intelligent”
genug sind, den Schirm besser zu erkennen, enttäuscht mich etwas.&lt;br /&gt;
Zum Glück kann man bei Linux zumindest meistens noch beim Booten im
“Advanced” Modus eine 80x25 Text-UI aktivieren … zumindest heute noch.
Wer weiß schon, was morgen zum Standard erhoben wird …&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;… früher, als alles noch auf 640x480 ausgerichtet war, gab es 
jedenfalls (fast) keine Anzeigeprobleme mit übergroßen Fenstern.&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>Using Namespace</title>
   <link href="https://www.opengate.at/blog/2020/07/using-namespace/"/>
   <published>2020-07-04T13:00:00+02:00</published>
   <updated>2020-07-04T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2020/07/using-namespace</id>
   <category term="devel" />
   <summary type="text">Und wieder geht ein Tag voller Heldentaten zu Ende … die keiner bemerkt hat.

Über 3 Stunden mühsame Tipparbeit sind vollbracht um die Sünden von 10 Jahren
Achtlosigkeit zu beheben.

Warum zur Hölle verwenden so viele Leute “using namespace”?
</summary>
   <content type="html">&lt;p&gt;Und wieder geht ein Tag voller Heldentaten zu Ende … die keiner bemerkt hat.&lt;/p&gt;

&lt;p&gt;Über 3 Stunden mühsame Tipparbeit sind vollbracht um die Sünden von 10 Jahren
Achtlosigkeit zu beheben.&lt;/p&gt;

&lt;p&gt;Warum zur Hölle verwenden so viele Leute “using namespace”?
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Leider steht es ja auch so meinem allerersten &lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B&quot;&gt;C++&lt;/a&gt;
Buch von 1998 so drinnen:&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color:#B44;font-weight:bold&quot;&gt;&amp;lt;iostream.h&amp;gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;using&lt;/span&gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;namespace&lt;/span&gt; std;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; main()
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  cout &amp;lt;&amp;lt; &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Hello World&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Und dieses Krebsgeschwür infiziert bis heute Sourcen in aller Welt … und 
ganz besonders in internen bzw. proprietären Programmen in Unternehmen.&lt;/p&gt;

&lt;h3 id=&quot;vor-unserer-zeit&quot;&gt;Vor unserer Zeit&lt;/h3&gt;

&lt;p&gt;Tatsächlich waren Namensräume vor der Standardisierung 1998 kein weit 
verbreitetes Feature. Auf &lt;code&gt;cin&lt;/code&gt; und &lt;code&gt;cout&lt;/code&gt; hatte man sich schon verständigt, 
aber nicht auf &lt;code&gt;std&lt;/code&gt;.&lt;br /&gt;
Und als der Standard festgelegt wurde, wurden viele Softwarestücke zum 
Non-Standard, weil sie &lt;code&gt;std&lt;/code&gt; eben nicht kannten.&lt;/p&gt;

&lt;p&gt;Die Lösung war also:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Schreibt einfach &lt;code&gt;using namespace std;&lt;/code&gt; in alle Header, dann läuft wieder
alles.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;heute-eigentlich-gestern&quot;&gt;Heute (eigentlich gestern)&lt;/h3&gt;

&lt;p&gt;Und dann kam &lt;a href=&quot;https://de.wikipedia.org/wiki/Boost_(C%2B%2B-Bibliothek)&quot;&gt;BOOST&lt;/a&gt; 
und dann kamen &lt;a href=&quot;https://en.wikipedia.org/wiki/C%2B%2B11&quot;&gt;C++11&lt;/a&gt;, C++14 
und seine weiteren Geschwister.&lt;br /&gt;
Auch Applikationen, die BOOST nutzen, pflegen die Unart &lt;code&gt;using namespace boost;&lt;/code&gt;
zu schreiben, um alle seine Klassen in den globalen (bzw. eigenen) Namespace
zu importieren.&lt;/p&gt;

&lt;p&gt;Das lief bis 2011 auch ganz gut, weil BOOST und die STL sich nicht in die 
Quere kamen.&lt;br /&gt;
Doch dann entstanden &lt;code&gt;std::thread&lt;/code&gt; und &lt;code&gt;std::mutex&lt;/code&gt; parallel zu &lt;code&gt;boost:thread&lt;/code&gt; 
und &lt;code&gt;boost::mutex&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Wer jetzt &lt;code&gt;using namespace&lt;/code&gt; für beide Namensräume einsetzte bekam plötzlich 
&lt;em&gt;Ambiguity Errors&lt;/em&gt;, weil der Compiler nicht riechen kann, ob er jetzt &lt;code&gt;std::ABC&lt;/code&gt; 
oder &lt;code&gt;boost::ABC&lt;/code&gt; nutzen soll.&lt;/p&gt;

&lt;h3 id=&quot;heute-in-der-firma&quot;&gt;Heute in der Firma&lt;/h3&gt;

&lt;p&gt;Bei der Migration auf C++14 liefern mir 33% der Komponenten immer wieder solche
Fehler.&lt;br /&gt;
Und heute hat es mir gereicht!&lt;/p&gt;

&lt;p&gt;Ich machte also eine Suche nach &lt;code&gt;using namespace std&lt;/code&gt; und löschte jede solche 
Zeile. &lt;code&gt;using namespace boost&lt;/code&gt; blieb vorerst bestehen, da mit Ausnahme von 
&lt;code&gt;std::string&lt;/code&gt; wesentlich mehr BOOST Nutzungen im Code waren, folglich sollte 
nur &lt;code&gt;std&lt;/code&gt; explizit angegeben werden, wo es fehlte.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Meine Fresse, war das eine Fehleinschätzung, wie viele Typen plötzlich 
nicht mehr lauffähig waren!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ich dachte mit ein bisschen Suchen+Ersetzen ist das in 30 Minuten erledigt.&lt;br /&gt;
Aber Fehlanzeige! Unzählige &lt;code&gt;string&lt;/code&gt;, &lt;code&gt;*stream&lt;/code&gt;, &lt;code&gt;copy&lt;/code&gt; und &lt;code&gt;min/max&lt;/code&gt;
Token lagen kreuz und quere über alle möglichen Projekte verstreut.&lt;/p&gt;

&lt;p&gt;Da hilft dann nichts anderes, als jede Zeile manuell zu fixen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Mir brummt immer noch der Schädel!
Von allen Arbeiten ist das eine der dämlichsten, die man in der 
Programmierung machen kann … aber Hey, es hält nun hoffentlich lange.&lt;/p&gt;

&lt;p&gt;Und sollte ich bei der nächsten Suche nach &lt;code&gt;using namespace std&lt;/code&gt; noch 
etwas finden, dann mache ich den Kollegen ausfindig und tue im weh!&lt;/p&gt;

&lt;p&gt;Also an alle lieben C++ Kollegen da draußen:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;code&gt;using namespace&lt;/code&gt; ist seit 1998 Tabu! Es hat nur in ganz wenigen Fällen
(z.B.: &lt;code&gt;swap&lt;/code&gt;) eine Existenzberechtigung, oder wenn man eigenen privaten
Code von &lt;em&gt;NUR EINEM&lt;/em&gt; Namespace aus schreibt.
Ansonsten sind immer alle Typen korrekt zu adressieren, oder mit einem
&lt;code&gt;typedef nspace::some_type my_type;&lt;/code&gt; zu importieren.
Zur Not kann man auch &lt;code&gt;using nspace::some_type;&lt;/code&gt; gelten lassen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Der wirkliche Skandal ist aber, dass &lt;code&gt;using namespace&lt;/code&gt; gerne benutzt wird,
um ein anderes Problem zu bekämpfen: Nämlich Namespaces, die unerträglich
langatmig definiert sind.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Bitte führt keine &lt;code&gt;namespace cool_app_code_assembly&lt;/code&gt; Bezeichnungen ein, die 
viel zu lange sind, um sie jedem Typen voran zu stellen.&lt;br /&gt;
Eine richtig kurze “coole” Abkürzung tut es auch, z.B.: &lt;code&gt;namespace caca&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>Geil, geiler, ... Dark</title>
   <link href="https://www.opengate.at/blog/2020/06/dark/"/>
   <published>2020-06-28T13:00:00+02:00</published>
   <updated>2020-06-28T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2020/06/dark</id>
   <category term="entertainment" />
   <summary type="text">Wie schön, dass es im Jahr 2020 endlich mal wieder eine “TV-Serie” gibt, die
mich überraschen und begeistern konnte, obwohl sie gar nicht im TV lief.

Wenn man die ersten (aus meiner Sicht) sehr verwirrenden Folgen von 
“Dark” überstanden
hat, erlebt man eine neue Geschichte, die Zeitreisen und ihre Konsequenzen 
in einer mir bisher unbekannten Weise schildert.

Kurz gesagt: Ich liebe diese Serie.
</summary>
   <content type="html">&lt;p&gt;Wie schön, dass es im Jahr 2020 endlich mal wieder eine “TV-Serie” gibt, die
mich überraschen und begeistern konnte, obwohl sie gar nicht im TV lief.&lt;/p&gt;

&lt;p&gt;Wenn man die ersten (aus meiner Sicht) sehr verwirrenden Folgen von 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Dark_(Fernsehserie)&quot;&gt;“Dark”&lt;/a&gt; überstanden
hat, erlebt man eine neue Geschichte, die Zeitreisen und ihre Konsequenzen 
in einer mir bisher unbekannten Weise schildert.&lt;/p&gt;

&lt;p&gt;Kurz gesagt: Ich liebe diese Serie.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Jetzt kann ich endlich mit reinem Gewissen behaupten: Die monatliche Netflix
Gebühr zahlt sich aus.&lt;br /&gt;
DARK, eine deutsche Serie rund um ein Atomkraftwerk und mysteriösen Zeitsprüngen
im 33-Jahre-Rhythmus, hat es mir echt angetan und so wurde dieses Wochenende zum
&lt;a href=&quot;https://de.wikipedia.org/wiki/Binge_Watching&quot;&gt;Dauer-Binge&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Und wie es der Zufall (nein die Vorsehung!) wollte, kam genau an diesem 
Wochenende auch noch die finale 3. Staffel heraus, die die gesamte Geschichte
zu einem unerwarteten und dennoch genialen Ende führte.&lt;/p&gt;

&lt;p&gt;“Zeitreisen” waren von &lt;a href=&quot;https://de.wikipedia.org/wiki/Star_Trek&quot;&gt;StarTrek&lt;/a&gt; bis 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Pok%C3%A9mon&quot;&gt;Pokemon&lt;/a&gt; leider immer ein Indiz 
dafür, dass eine Serie händeringend nach anderen Locations sucht. Und 
dementsprechend schlecht wirken die meisten Episoden mit solchen Handlungen.
(Ausnahmen bestätigen die Regel!)&lt;/p&gt;

&lt;p&gt;DARK zeigt jedoch eine Welt auf, die (offenbar schon ewig) in einer 
Zeitschleife gefangen ist und sich auf einen apokalyptischen Endpunkt
zubewegt, der immer wieder verhindert werden soll … was ihn aber
erst auslöst … und doch nicht … und doch noch …&lt;/p&gt;

&lt;p&gt;Das Großvater-Paradoxon sucht man vergeblich, denn die Manipulation 
“des jüngeren Ichs” gehört zum Konzept der Serie und schildert gleichsam 
die Unausweichbarkeit des Schicksals wie auch immer wieder neue Wendungen,
die die Handlung anfangs verkomplizieren und sich am Ende dennoch logisch
auflösen (zumindest meistens).&lt;/p&gt;

&lt;p&gt;Man darf hier leider nicht zu viel verraten, um die Spannung nicht zu rauben,
aber dennoch bedarf es einem kleinen Anrempler um neue Zuseher bei der 
Stange zu halten.&lt;br /&gt;
Denn gerade die ersten Folgen “muss man durchhalten”. Da fliegen einem
Namen und Lebenssituationen zu, die komplexer nicht sein könnten und die
sich dann auch noch im Verlauf “von selbst” uminterpretieren.&lt;/p&gt;

&lt;p&gt;Hat man diese Lernkurve aber mal absolviert, fiebert man bis zur letzten
Episode mit, wie es nun wohl ausgehen wird.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Empfehlung! Absolut.&lt;br /&gt;
Mehr gibt es einfach nicht zu sagen.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Sic mundus creatus est!&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>Das Abenteuer Lichee PI Zero</title>
   <link href="https://www.opengate.at/blog/2020/06/licheepi-zero/"/>
   <published>2020-06-27T13:00:00+02:00</published>
   <updated>2020-06-27T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2020/06/licheepi-zero</id>
   <category term="hardware" /><category term="software" /><category term="projects" />
   <summary type="text">Wie man sich einen Lichee PI Zero herrichtet, 
habe ich nun in einem eigenen How-To Bericht zusammengefasst: 
LicheePI Zero einrichten

Damit wäre zu dem Thema alles gesagt.
Nun ja … nicht ganz. Hier ein paar Sidequests und Fun-Facts:

</summary>
   <content type="html">&lt;p&gt;Wie man sich einen &lt;a href=&quot;https://www.licheepizero.us/&quot;&gt;Lichee PI Zero&lt;/a&gt; herrichtet, 
habe ich nun in einem eigenen How-To Bericht zusammengefasst: 
&lt;a href=&quot;/blog/projects/lichee/&quot;&gt;LicheePI Zero einrichten&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Damit wäre zu dem Thema alles gesagt.&lt;br /&gt;
Nun ja … nicht ganz. Hier ein paar &lt;em&gt;Sidequests&lt;/em&gt; und &lt;em&gt;Fun-Facts&lt;/em&gt;:&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/lichee-zero.jpg&quot; alt=&quot;Lichee Zero v2&quot; /&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Tatsächlich liegt der LicheePI Zero schon seit einem Jahr bei mir herum,
aber wegen einer schlechten Lötstelle an den seriellen Pins, dachte ich 
lange, dass ich das Gerät bereits versehentlich zerstört hätte.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Dynamic_Host_Configuration_Protocol&quot;&gt;DHCP&lt;/a&gt; 
ist Gift. Der &lt;code&gt;dhcpclient&lt;/code&gt; belegt relativ viel RAM und führte bei 
mir dadurch häufiger zu Crashes wegen Speicherknappheit.&lt;br /&gt;
Daher sollte man den LicheePI immer nur mit statischen IPs werken lassen.&lt;/li&gt;
  &lt;li&gt;Die &lt;a href=&quot;https://de.wikipedia.org/wiki/SD-Karte&quot;&gt;SD-Karte&lt;/a&gt; quer zwischen die 
Pin-Header zu spannen ist ein totaler Designfehler. Ich habe eine Karte fast
zerbrochen, als ich sie mehrmals zwecks neuem Kernel wechseln wollte. 
Die Pins an der anderen Seite anzulöten ist bei der 2. Generation 
(breiteres Board) leider auch keine Alternative, weil meine Breadboards 
alle nicht breit genug waren um die Pins dann nutzen zu können.&lt;br /&gt;
Wenn möglich verlötet man nur TX und RX (oder gar nichts, wenn er einen 
LCD-Screen montiert hat), damit man die Karte leichter wechseln kann.&lt;/li&gt;
  &lt;li&gt;Anfangs wusste ich nicht, ob ein “Darüberkopieren” einer neuen Kernel-Datei
auch wirklich ausgeführt wurde, oder ab eine absolute Adresse vielleicht
noch das alte Kernel-Image nutzte.&lt;br /&gt;
Doch zum Glück schreibt der Kernel-Build-Prozess den PC Namen samt User, 
Datum und Uhrzeit ins Image, welches bei jedem Start von 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt; ganz am Anfang auf die Konsole
ausgegeben wird.&lt;/li&gt;
  &lt;li&gt;Den Linux Kernel zu bauen ist mit 4 Kernen kein Spaß. Auch das Script ging 
von 16 Stück aus (&lt;code&gt;-j16&lt;/code&gt;). Wer also häufig Kernel kompiliert braucht einen
stärkeren Rechner, als ich dafür genutzt habe.&lt;/li&gt;
  &lt;li&gt;Ich habe den LicheePI Linux Kernel übrigens in Windows 10 mit dem Linux
Subsystem und Ubuntu 20.4 erstellt.&lt;br /&gt;
Wer hätte je gedacht, dass man Linux in einem Windows bauen lassen kann?&lt;/li&gt;
  &lt;li&gt;Man kann ein paar Pins der SD-Karte offenbar im laufenden Betrieb digital 
“umpolen”, aber spätestens beim CMD-Pin ist es dann vorbei.
Linux verfängt sich dann in einer Endlosschleife an Fehlern, nicht mehr
auf die Karte schreiben zu können. Und das führt zu Logging und erneutem
Versagen auf die Karte zu schreiben.&lt;br /&gt;
Da hilft dann nur ein Reset bzw. Stromentzug.&lt;/li&gt;
  &lt;li&gt;Das Lesen und Schreiben der Images von und auf SD-Karte durfte &lt;code&gt;vBinCopy&lt;/code&gt;
aus dem GATE Projekt übernehmen. Und das funktionierte offenbar ganz gut.
Dateisystem-Reparaturen nach Crashes musste ich aber am Raspberry-PI 4 
machen, der mit &lt;code&gt;fsck&lt;/code&gt; nötige Reparaturen an der SD-Karte durchführen
konnte.&lt;/li&gt;
  &lt;li&gt;Mein erster versuch eines Debian-Upgrades dauerte über 6 Stunden, weil die
Downloads stets zusammenbrachen und ich die Netzwerkschnittstelle neu 
starten musste.&lt;br /&gt;
Während dessen konnte ich mir einige Folgen der genialen Serie “Dark” 
reinziehen ;)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Der Lichee PI und meine Artikel dazu hat die Veröffentlichung des Blogs
um ein halbes Jahr verzögert.&lt;/p&gt;

&lt;p&gt;Nun sollte aber mein Experimentier- und Schreibbedarf zu diesem Gerät
für die nächste Zeit abgedeckt sein.&lt;/p&gt;

&lt;p&gt;… vorläufig zumindest, weil wenn es um Ressourcen-Knappheit geht, ist
dieses System perfekt dafür ausgelegt, das Verhalten von Linux darauf
zu testen.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Wenn aus einer SD-Karte eine SATA-Festplatte wird</title>
   <link href="https://www.opengate.at/blog/2020/06/sd2sata/"/>
   <published>2020-06-21T13:00:00+02:00</published>
   <updated>2020-06-21T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2020/06/sd2sata</id>
   <category term="hardware" />
   <summary type="text">Also … Anfang des Jahres habe ich entdeckt, dass man altes XORO-Note-Netbook 
einen unbenutzen SATA Anschluss in 
seinem Inneren hatte, der leer war.


  Da kann man ja noch eine Festplatte parallel zum Flash-Speicher anhängen.


dachte ich mir.

Doch übliche SATA 2.5 Zoll Platten sind um einen Millimeter zu dick, sie 
passen zwar rein, wölben dann aber die Tastatur nach oben.

Die Lösung: eine SD-Karte am 
SATA Port anschließen.
</summary>
   <content type="html">&lt;p&gt;Also … Anfang des Jahres habe ich entdeckt, dass man altes XORO-Note-Netbook 
einen unbenutzen &lt;a href=&quot;https://de.wikipedia.org/wiki/Serial_ATA&quot;&gt;SATA&lt;/a&gt; Anschluss in 
seinem Inneren hatte, der leer war.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Da kann man ja noch eine Festplatte parallel zum Flash-Speicher anhängen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;dachte ich mir.&lt;/p&gt;

&lt;p&gt;Doch übliche SATA 2.5 Zoll Platten sind um einen Millimeter zu dick, sie 
passen zwar rein, wölben dann aber die Tastatur nach oben.&lt;/p&gt;

&lt;p&gt;Die Lösung: eine &lt;a href=&quot;https://de.wikipedia.org/wiki/SD-Karte&quot;&gt;SD-Karte&lt;/a&gt; am 
SATA Port anschließen.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Mein “XORO Note 11” ist ein kleiner &lt;a href=&quot;https://de.wikipedia.org/wiki/Intel_Atom&quot;&gt;Intel Atom&lt;/a&gt;
Laptop mit 2 GB RAM und einem 32 GB Flashspeicher und 11 Zoll Screen, auf dem
man wenig machen konnte.&lt;br /&gt;
Das vorinstallierte &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_10&quot;&gt;Windows 10&lt;/a&gt; 
lies bei seiner Suche nach Updates die CPU hochtakten, was binnen Kurzem zu 
viel Wärme für das passive gekühlte Gerät erzeugte und die CPU dann auf wenige
100 MHz zurücktaktete.&lt;/p&gt;

&lt;p&gt;In dem Zustand war das Gerät unbenutzbar.&lt;/p&gt;

&lt;p&gt;Die Lösung hieß dann: &lt;em&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Aber das war auch Mist, weil es dafür wieder keinen WLAN-Treiber gab und ich 
musste unendlich lange herumfuhrwerken, bis ich ein alternatives Kernelmodul
halbwegs im neu installierten Debian 10 zum Laufen gebracht hatte.&lt;/p&gt;

&lt;p&gt;Das Ding eignet sich aber als McDonalds Laptop, also ein Teil, das man immer
überall hin mitschleifen kann um in paar freien Minuten z.B. einen 
Blog-Artikel abzutippen.&lt;br /&gt;
Sollte es gestohlen werden, ist nicht viel verloren … wobei … wer außer
mir würde so ein Ding überhaupt nutzen wollen/können?&lt;/p&gt;

&lt;p&gt;Wie auch immer, nun beherbergt das Gerät weitere 64 GB als SD Karte, die
sich aber als Festplatte meldet.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/sd-2-sata.jpg&quot; alt=&quot;SD to SATA Adapter&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Eigentlich kann ich überhaupt nichts “besonderes” berichten, weil man einfach
nur die SD-Karte in den Slot des Konverterboards steckt und diesen wieder an
den SATA Port klemmt.&lt;/p&gt;

&lt;p&gt;Das Board hat nur etwa 2/3 der Länge einer üblichen SSD und ist vor allem nicht
so dick.
Damit passt es spielend in die SSD-Ausnehmung im Laptop und bewirkt auch nicht
die Wölbung der darüberliegenden Tastatur, wie es normale Festplatten tun
würden.&lt;/p&gt;

&lt;p&gt;Dort habe ich nun genug Platz frei um ein paar Videodateien abzulegen, damit 
mich das Gerät auch medial unterhalten kann.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/laptop-sd-card-ssd.jpg&quot; alt=&quot;Laptop SSD&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Auch wieder mal schön zu berichten, dass Hardware out-of-the-box ohne Probleme
ausgepackt und angeschlossen wird und dann umgehend so funktioniert, wie man
es erwartet bzw. erhofft.&lt;/p&gt;

&lt;p&gt;Ach ja, natürlich hätte ich auch eine Alternative angehen können:&lt;br /&gt;
Man kann die Ummantellung der meisten SSDs abnehmen und dann bleibt nur
die Platine mit den Speicherchips und den SATA Anschlüssen übrig.&lt;/p&gt;

&lt;p&gt;Das hätte dann “viel besser” in den Laptop gepasst.&lt;/p&gt;

&lt;p&gt;Aber die vorher verbaute 120 GB Platte kann in einem anderen System besser 
dienen, also auf dem Laptop, der ohnehin nicht oft im Einsatz ist.&lt;/p&gt;

&lt;p&gt;Auf eines bin ich aber gespannt:
Wie lange wird die SD Karte wohl “halten” ?&lt;/p&gt;

&lt;p&gt;Tja, witzig. Ich hatte so einen SD-to-SATA Konverter schon letztes Jahr 
für ein paar Euro in Fernost mitbestellt, so nach dem Gedanken:&lt;br /&gt;
&lt;em&gt;“Vielleicht brauche ich das mal.”&lt;/em&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Abenteuer mit Laufwerk A:</title>
   <link href="https://www.opengate.at/blog/2020/06/floppy/"/>
   <published>2020-06-20T13:00:00+02:00</published>
   <updated>2020-06-20T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2020/06/floppy</id>
   <category term="hardware" /><category term="retro" />
   <summary type="text">Endlich, nach vielen Jahren (ähm schon fast Jahrzehnten), sind es 
Disketten, die mir bei einer 
wichtigen Problemstellung helfen konnten:


  Wie simuliert man Datenträgerfehler?


Alte Disketten aus den vor-2000ern haben dieses “Feature” inzwischen 
häufig integriert, also ab ins USB-Laufwerk und los…
</summary>
   <content type="html">&lt;p&gt;Endlich, nach vielen Jahren (ähm schon fast Jahrzehnten), sind es 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Diskette&quot;&gt;Disketten&lt;/a&gt;, die mir bei einer 
wichtigen Problemstellung helfen konnten:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Wie simuliert man Datenträgerfehler?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Alte Disketten aus den vor-2000ern haben dieses “Feature” inzwischen 
häufig integriert, also ab ins USB-Laufwerk und los…
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;code&gt;vBinCopy&lt;/code&gt; ist aktuell mein liebstes GATE-Referenzprojekt, weil es nicht nur 
wichtige Features des Frameworks nutzt und abtestet, sondern weil es auch
einen guten praktischen Nutzen hat:&lt;br /&gt;
Das Kopieren und Beschreiben von &lt;a href=&quot;https://de.wikipedia.org/wiki/SD-Karte&quot;&gt;SD-Karten&lt;/a&gt; 
für &lt;a href=&quot;https://de.wikipedia.org/wiki/System-on-a-Chip&quot;&gt;SOC&lt;/a&gt; Geräte.&lt;/p&gt;

&lt;p&gt;Aber was passiert eigentlich, wenn ein Sektor fehlerhaft ist?&lt;/p&gt;

&lt;p&gt;Genau diesen Fall möchte ich schließlich auch abdecken, aber Festplattenfehler
sind schwer zu simulieren.&lt;/p&gt;

&lt;p&gt;Bei SD-Karten ist das auch mühsam, weil diese zwar gerne Daten verlieren, sich
aber nicht als “fehlerhaft” beim OS anmelden.&lt;/p&gt;

&lt;p&gt;Disketten hingegen kriegen leicht einen Kratzer ab und schon meldet das OS
unterschiedlichste Fehlercodes, wenn ein Sektor nicht gelesen werden kann.&lt;/p&gt;

&lt;p&gt;So kam also mein USB-Floppy-Disk-Drive wieder mal zum Einsatz, um das 
Verhalten beim Lesen und Schreiben von Disketten zu beobachten.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/usb-floppy-drive.jpg&quot; alt=&quot;USB Floppy Drive&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Folgende Erkenntnisse durfte ich dabei machen:&lt;/p&gt;

&lt;h3 id=&quot;kein-windows-device-link-im-globalen-namensraum&quot;&gt;Kein Windows Device-Link im globalen Namensraum&lt;/h3&gt;

&lt;p&gt;Festplatten haben im Windows Object-Manager einen Device-Eintrag z.B.: 
&lt;code&gt;\Device\HarddiskN&lt;/code&gt; und dieser ist im globalen Namensraum dann mit 
&lt;code&gt;\\.\PhysicalDriveN&lt;/code&gt; verlinkt und das ist der Pfad, den wir mit 
&lt;a href=&quot;http://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilew&quot;&gt;&lt;code&gt;CreateFile&lt;/code&gt;&lt;/a&gt;
auch öffnen können.&lt;/p&gt;

&lt;p&gt;Floppy-Disk-Drives haben (meines Wissensstandes) einen solchen Eintrag nicht, man
kann aber den Gerätepfad, den man von der Setup-API bekommt ebenso mit 
&lt;code&gt;CreateFile&lt;/code&gt; öffnen und dann direkt die Sektoren per &lt;code&gt;ReadFile&lt;/code&gt; und &lt;code&gt;WriteFile&lt;/code&gt;
bearbeiten.&lt;/p&gt;

&lt;h3 id=&quot;usb-floppys-sind-in-linux-entfernbare-festplatten&quot;&gt;USB-Floppys sind in Linux “entfernbare” Festplatten&lt;/h3&gt;

&lt;p&gt;Dass sich mein USB-Floppy-Drive im &lt;code&gt;sysfs&lt;/code&gt; und in &lt;code&gt;/dev&lt;/code&gt; als &lt;code&gt;sda&lt;/code&gt; meldet hat 
mich schon etwas überrascht. Zwar kann ich das gerade nicht nachprüfen, aber 
ich erinnere mich noch, dass früher die nativ verbauten Floppy-Controller als
&lt;code&gt;/dev/fdN&lt;/code&gt; ansprechbar waren um sich von den IDE Festplatten mit &lt;code&gt;/dev/hdX&lt;/code&gt; zu
unterscheiden.&lt;br /&gt;
&lt;code&gt;/dev/sdX&lt;/code&gt; steht doch eigentlich für SCSI und/oder SATA … keine Ahnung 
warum sich das so abbildet.&lt;/p&gt;

&lt;p&gt;However, &lt;code&gt;open&lt;/code&gt; kann den Floppydisk Pfad problemlos ansprechen.&lt;/p&gt;

&lt;h3 id=&quot;ergebnisse&quot;&gt;Ergebnisse&lt;/h3&gt;

&lt;p&gt;Nun, bei einem Lesefehler wird das wie erwartet bei &lt;code&gt;ReadFile&lt;/code&gt; und 
&lt;code&gt;read&lt;/code&gt; zurückgeliefert.&lt;/p&gt;

&lt;p&gt;Um solche Sektoren zu umgehen, setzt man den Datenzeiger einfach auf die
Startadresse des nächsten Sektors und versucht dort weiterzulesen.
Den übersprungenen Sektor muss man eben durch Füllbytes repräsentieren.&lt;/p&gt;

&lt;p&gt;Und schon hat man ein primitives Reparatur-Tool, das auch defekte Medien
lesen kann und nicht einfach abbricht (was eine Tools leider machen).&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ich freue mich mit &lt;code&gt;vBinCopy&lt;/code&gt; ein kleines Tool zum binären Lesen,
Schreiben und reparieren von Laufwerken, Partitionen und einfachen
Dateien im Sortiment zu haben, das ausschließlich auf dem GATE
Framework aufbaut.&lt;/p&gt;

&lt;p&gt;Gespannt bin ich vor allem, ob die genutzte Implementierung auch
auf älteren Windows Plattformen oder exotischen Unix-Derivaten
anwendbar ist.&lt;/p&gt;

&lt;p&gt;Die Zukunft wird es zeigen …&lt;/p&gt;

&lt;p&gt;PS: Hier noch ein schöner Ausschnitt, der mich an vergangene Zeiten erinnert:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;C:\Windows\system32&amp;gt;format a:
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;Legen Sie eine neue Diskette in Laufwerk A: ein,
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;und drücken Sie die EINGABETASTE.
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;Der Typ des Dateisystems ist RAW.
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;Das neue Dateisystem ist FAT.
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;Überprüfung von 1.44 MB
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;Die Dateizuordnungstabelle (FAT) wird initialisiert...
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;Volumebezeichnung (11 Zeichen, EINGABETASTE für keine)?
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;Formatieren beendet.
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;       1,4 MB Speicherplatz auf dem Datenträger insgesamt.
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;       1,4 MB sind verfügbar.
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;          512 Bytes in jeder Zuordnungseinheit
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;        2 847 Zuordnungseinheiten auf dem Datenträger verfügbar
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;           12 Bits in jedem FAT-Datensatz.
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;Volumeseriennummer : 4884-4783
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;Weiteren Datenträger formatieren (J/N)?
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>Windows 10 - 2004 Update</title>
   <link href="https://www.opengate.at/blog/2020/06/win10-2004/"/>
   <published>2020-06-14T13:00:00+02:00</published>
   <updated>2020-06-14T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2020/06/win10-2004</id>
   <category term="software" />
   <summary type="text">Offiziell hieß es Windows 10 -
Update 2004, aber bei mir wurde daraus ärgerlicherweise eine komplette 
Neuinstallation.

Warum nur werden Setups und Updates heute so kompliziert gestaltet, dass
man bei jedem Anlauf bangen muss, sein System verschrotten zu müssen?
</summary>
   <content type="html">&lt;p&gt;Offiziell hieß es &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_10&quot;&gt;Windows 10&lt;/a&gt; -
&lt;em&gt;Update&lt;/em&gt; 2004, aber bei mir wurde daraus ärgerlicherweise eine komplette 
Neuinstallation.&lt;/p&gt;

&lt;p&gt;Warum nur werden Setups und Updates heute so kompliziert gestaltet, dass
man bei jedem Anlauf bangen muss, sein System verschrotten zu müssen?
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;update-versuch&quot;&gt;Update Versuch&lt;/h3&gt;

&lt;p&gt;Seit fast zwei Monaten versuchte ich “regulär” auf das neue Windows 10 
Version 20/04  (auch 20/H1 genannt) zu wechseln.&lt;br /&gt;
In den vergangenen Jahren klappte das eigentlich immer problemlos:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Setup lud alle Daten herunter&lt;/li&gt;
  &lt;li&gt;Die Installation baute eine zweite Windows-Installation auf der 
Systempartition auf&lt;/li&gt;
  &lt;li&gt;Beim nächsten Hochfahren wurden alle “persönlichen Daten” migriert&lt;/li&gt;
  &lt;li&gt;Und ab dem nächsten Login war man im “neuen Windows” mit allen
Einstellungen und Daten von früher.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Tja… und diesmal?&lt;/p&gt;

&lt;p&gt;Diesmal lief der Download- und Setup-Schritt extrem lange und brach dann bei
ca. 90 % mit der Meldung ab, dass&lt;br /&gt;
&lt;em&gt;“Windows zur Zeit noch nicht aktualisiert werden könne”&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Keine Ahnung an welcher meiner Softwareinstallationen sich Setup gestoßen
hatte (es könnten Treiber, &lt;a href=&quot;https://de.wikipedia.org/wiki/Hyper-V&quot;&gt;Hyper-V&lt;/a&gt;
oder Dev-Tools gewesen sein), aber nach wöchentlichen Fehlschlägen gab ich
letztendlich auf.&lt;/p&gt;

&lt;h3 id=&quot;komplette-neuinstallation&quot;&gt;Komplette Neuinstallation&lt;/h3&gt;

&lt;p&gt;Windows 10 20/04 wurde auf einen USB-Stick kopiert (&lt;a href=&quot;https://de.wikipedia.org/wiki/Rufus_(Software)&quot;&gt;Rufus&lt;/a&gt;
lässt grüßen) und das Setup “außerhalb” von Windows gestartet.&lt;/p&gt;

&lt;p&gt;Damit verliert man natürlich die Möglichkeit Apps und persönliche Daten
in die Neuinstallation mitzunehmen … aber das war mir letztendlich 
auch egal.&lt;/p&gt;

&lt;p&gt;Für die Neuinstallation musste ich dann von Hyper-V bis Visual-Studio wieder
alles neu installieren und das ist leider immer noch recht zeitaufwendig.&lt;/p&gt;

&lt;p&gt;Interessanter war für mich aber die Beobachtung, wie “groß” inzwischen 
diverse Windows Apps geworden sind, die natürlich auch erst wieder eingerichtet
werden mussten:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Windows Rechner: 13 MB&lt;/li&gt;
  &lt;li&gt;Mail: 84 MB&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;mal als Beispiel genannt.&lt;br /&gt;
Ähm, Wow! 13 MB für einen Taschenrechner.&lt;/p&gt;

&lt;p&gt;Dieses Programm existiert seit den ersten Windows Versionen und war meines
Wissens nie über ein paar 100 KByte groß.&lt;br /&gt;
Was zur Hölle braucht da drinnen jetzt mehrere Megabytes??&lt;br /&gt;
Denn mir kann ja niemand erklären, dass der neue Einheiten-Umrechner, den
es früher nicht gab, der App soviel Code hinzugefügt hat.&lt;/p&gt;

&lt;p&gt;An dieser Stelle wünsche ich mir die alten Zeiten zurück, wo 
Softwareentwicklung noch unter dem Motto lief:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Jedes Byte ist ein Dollar. Wer Bytes verschwendet schafft
unbezahlbare Produkte, die sich keiner leisten kann.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Hmm … das gilt wohl beim “Windows Rechner” nicht mehr … leider.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Auf meinem Laptop und einem Tablet klappte das Upgrade übrigens 
“out-of-the-box” problemfrei.&lt;br /&gt;
Warum es meinen Hauptrechner nicht leiden konnte, bleibt für mich ein Rätsel,
dass mich aber nicht weiter belasten soll.&lt;/p&gt;

&lt;p&gt;Letztendlich hat jede Neuinstallation etwas Gutes:&lt;br /&gt;
Man fängt mit einem etwas mehr aufgeräumteren System an …&lt;br /&gt;
… die Frage ist: Wie lange bleibt es so.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Nie wieder exFAT</title>
   <link href="https://www.opengate.at/blog/2020/06/exfat/"/>
   <published>2020-06-13T13:00:00+02:00</published>
   <updated>2020-06-13T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2020/06/exfat</id>
   <category term="software" />
   <summary type="text">Wenn man den Inhalt einer 2 TB 
Festplatte auf eine 4 TB Platte kopiert und am Ende die Meldung kommt:


  Es ist nicht genügend Speicherplatz verfügbar um den Vorgang abzuschließen.


dann ist entweder die Zielfestplatte kaputt oder man hat als Dateisystem
exFAT eingesetzt.

W-T-F
</summary>
   <content type="html">&lt;p&gt;Wenn man den Inhalt einer 2 &lt;a href=&quot;https://en.wikipedia.org/wiki/Terabyte&quot;&gt;TB&lt;/a&gt; 
Festplatte auf eine 4 TB Platte kopiert und am Ende die Meldung kommt:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Es ist nicht genügend Speicherplatz verfügbar um den Vorgang abzuschließen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;dann ist entweder die Zielfestplatte kaputt oder man hat als Dateisystem
&lt;a href=&quot;https://en.wikipedia.org/wiki/ExFAT&quot;&gt;exFAT&lt;/a&gt; eingesetzt.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;W-T-F&lt;/strong&gt;
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;ein-bisschen-geschichtsunterricht&quot;&gt;Ein bisschen Geschichtsunterricht&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Diskette&quot;&gt;Disketten&lt;/a&gt; waren Scheiben, auf denen 
Daten in Spuren (auch &lt;em&gt;“Cylinder”&lt;/em&gt; oder &lt;em&gt;“Track”&lt;/em&gt; genannt) von innen nach 
außen gespeichert wurden. Eine Spur wurde in mehrere Sektoren unterteilt und
man hatte sich (bei IBM) darauf geeinigt, dass ein Sektor einer Spur immer 
512 Bytes speichern können soll.&lt;/p&gt;

&lt;p&gt;Dieses Schema galt auch für Festplatten und wurde erst zwischen den Jahren 2007
bis 2010 auf 4 KBytes pro Sektor umgestellt.&lt;/p&gt;

&lt;p&gt;Die ersten Dateisysteme (z.B: &lt;a href=&quot;https://de.wikipedia.org/wiki/File_Allocation_Table#FAT12&quot;&gt;FAT12&lt;/a&gt;
für Disketten) nutzten diese kleinste Blockeinheit 1 zu 1 um jeden Sektor 
adressieren zu können.&lt;/p&gt;

&lt;p&gt;Doch als Festplatten größer als 512 MB wurden, gab es ein Problem:
Die alte &lt;a href=&quot;https://de.wikipedia.org/wiki/BIOS&quot;&gt;BIOS&lt;/a&gt; Spezifikation sah vor, 
dass ein Speichermedium nur maximal 1024 Spuren mit 63 Sektoren haben durfte 
und maximal 255 Platten parallel laufen konnten. So errechnet sich 
&lt;code&gt;1024 * 63 * 255 * 512 = 528 482 304 Bytes&lt;/code&gt;.
Also wurde das BIOS erweitert um mit einer 24-Bit ID Sektoren einzeln zu 
adressieren. Die Übersetzung auf Spuren und Köpf geschah somit im Hintergrund
und wir konnten uns auf Festplatten mit bis zu 8 GB freuen.&lt;/p&gt;

&lt;p&gt;Parallel dazu hatte das &lt;a href=&quot;https://de.wikipedia.org/wiki/File_Allocation_Table#FAT16&quot;&gt;FAT16&lt;/a&gt;
Dateisystem ein internes Limit von 65538 (2^16) Blöcken. Man führte dort
sogenannte “Cluster” ein, womit ein “logischer” Datenblock mehrere physische
Sektoren zusammenfasste.&lt;br /&gt;
Eine Clustergröße von 512 Bytes konnte also maximal 32 MB pro Partition 
ansprechen, mit 8 KByte Clustern waren 512 MB adressierbar und mit 32 KByte 
pro Cluster waren maximal 2 GByte möglich (64 KByte Cluster gab es zwar, waren
aber eine Spezialität von &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_NT_4.0&quot;&gt;NT 4&lt;/a&gt;
und unter DOS oder Win 9x nicht möglich).&lt;/p&gt;

&lt;p&gt;Eine Datei belegt in diesen Dateisystemen immer ein Vielfaches der 
Clustergröße. Je größer der Cluster, desto mehr Bytes fallen dem Verlust
zum Opfer, wenn die wahren Dateigrößen kein genaues Vielfaches eines
Clusters sind.&lt;/p&gt;

&lt;p&gt;Mit FAT32 und &lt;a href=&quot;https://de.wikipedia.org/wiki/NTFS&quot;&gt;NTFS&lt;/a&gt; pendelten sich
Clustergrößen übrigens bei 4 KByte ein und das ist bis heute aus meiner Sicht
ein vernünftiger Wert. Im Schnitt verliert man hier also 2 KB pro Datei ans 
Cluster-Alignment.&lt;/p&gt;

&lt;h3 id=&quot;heute--exfat&quot;&gt;Heute … exFAT&lt;/h3&gt;

&lt;p&gt;Ich kaufe mir also eine neue externe Festplatte mit 4 TB für Backups und
stehe vor der Wahl des Dateisystems. Und da denke ich mir:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Probieren wir es mal mit exFAT, denn &lt;code&gt;NTFS&lt;/code&gt; ist zu Windows spezifisch und
FAT32 ist mit seinen Limits unpassend.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ohne viel Nachsehen wird mit &lt;code&gt;exFAT&lt;/code&gt; formatiert und der Kopiervorgang startet.
Es dauert ewig lange bis alle meine vielen Quellcodes und Dokumente kopiert
sind und kurz vor Ende des Jobs bricht mir der Kopiervorgang ab und meldet
die Festplatte sei voll.&lt;/p&gt;

&lt;p&gt;Wie kann es sein, dass beim Kopieren von 1.8 TB auf eine 3.6 TB Partition 
die Platte voll ist?&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Nun, die unglaubliche Clustergröße von 1 MB erklärt das Problem verdammt gut.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Ja, eh klar. Einzelne Quellcodes sind wenige Kilobytes groß, belegen aber 
mindestens einen Cluster von 1 MB. Damit belegt jede Datei intern mindestens
1 MB und nicht die paar Kilobytes, die sie wirklich groß ist.&lt;/p&gt;

&lt;p&gt;Und wenn das hunderttausende Male passiert (ja ich habe viele Quellcodes),
dann benötigt exFAT weit mehr als 1.5 TB um meine 400 GB Codes zu sichern.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/exfat-files.png&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Videos und Fotos sind hier statistisch kein Problem. Sie sind in der Regel 
mehrere Megabytes bis Gigabytes groß, aber im Verhältnis gering in der Anzahl. 
Damit geht wenig Speicherplatz verloren.&lt;/p&gt;

&lt;p&gt;Eine 100 KB Datei produziert mit 1 MB eine Verzehnfachung des Speicherbedarfs, 
also 900% Zuwachs, während eine 1 GB Video Datei nur maximal ein Tausendstel,
also 0.1% Speicherverlust generiert.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Ab sofort mag ich exFAT nicht mehr!&lt;/em&gt;&lt;br /&gt;
Vermutlich kann man die Clustergröße manuell einstellen, aber dass ohne
Angaben die Standardeinstellungen 1 MB benutzt wird ist nur für Filme in 
Ordnung. Jede andere Form von Datenmaterial wird damit exponentiell 
aufgebläht.&lt;/p&gt;

&lt;p&gt;Ich darf jetzt alle Daten wieder zurückkopieren, die Platte neu partitionieren
und wieder von Vorne beginnen.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;NTFS&lt;/code&gt; ist am Ende doch die beste Lösung, weil es kleine Dateien in seiner 
&lt;a href=&quot;https://de.wikipedia.org/wiki/NTFS#Aufbau_%E2%80%93_MFT&quot;&gt;MFT&lt;/a&gt; speichert
und somit das Cluster-Verlust-Problem effizient umgeht.&lt;/p&gt;

&lt;p&gt;Es gibt auch noch die Alternative alle Verzeichnisse als ZIP oder 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Tar_(Packprogramm)&quot;&gt;TAR&lt;/a&gt; Dateien 
abzulegen. Das verringert die Anzahl der Dateien und somit auch den Verlust 
von Speicher an Cluster-Enden.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>PS/2 und USB Adapter</title>
   <link href="https://www.opengate.at/blog/2020/06/ps2/"/>
   <published>2020-06-07T13:00:00+02:00</published>
   <updated>2020-06-07T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2020/06/ps2</id>
   <category term="hardware" /><category term="retro" />
   <summary type="text">In den letzten 20 Jahren habe ich immer wieder mal 
KVM-Switches gekauft um mehrere
PCs an einem Monitor und einem Tastatur-Maus-Set zu betreiben.

Ärgerlicherweise kann ich viele davon heute nicht mehr einsetzen, weil sich
zwei Dinge geändert haben:

Es gibt keinen VGA 
Video-Ausgang mehr und Tastaturen wie Mäuse schließt man inzwischen über USB
und nicht wie damals an PS/2 Anschlüssen an.

Was kann ich also dagegen bzw. dafür tun?
</summary>
   <content type="html">&lt;p&gt;In den letzten 20 Jahren habe ich immer wieder mal 
&lt;a href=&quot;https://de.wikipedia.org/wiki/KVM-Switch&quot;&gt;KVM-Switches&lt;/a&gt; gekauft um mehrere
PCs an einem Monitor und einem Tastatur-Maus-Set zu betreiben.&lt;/p&gt;

&lt;p&gt;Ärgerlicherweise kann ich viele davon heute nicht mehr einsetzen, weil sich
zwei Dinge geändert haben:&lt;/p&gt;

&lt;p&gt;Es gibt keinen &lt;a href=&quot;https://de.wikipedia.org/wiki/VGA-Anschluss&quot;&gt;VGA&lt;/a&gt; 
Video-Ausgang mehr und Tastaturen wie Mäuse schließt man inzwischen über USB
und nicht wie damals an PS/2 Anschlüssen an.&lt;/p&gt;

&lt;p&gt;Was kann ich also dagegen bzw. dafür tun?
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;gestern-vs-heute&quot;&gt;Gestern vs Heute&lt;/h3&gt;

&lt;p&gt;Das gute alte analoge VGA ist eigentlich nicht tot. Es wird zwar mehr und 
mehr von &lt;a href=&quot;https://de.wikipedia.org/wiki/Digital_Visual_Interface&quot;&gt;DVI&lt;/a&gt;, 
&lt;a href=&quot;https://de.wikipedia.org/wiki/High_Definition_Multimedia_Interface&quot;&gt;HDMI&lt;/a&gt; 
und &lt;a href=&quot;https://de.wikipedia.org/wiki/DisplayPort&quot;&gt;DisplayPort&lt;/a&gt; verdrängt, 
doch die meisten Mainboards haben eine Onboard-Grafik wo noch eine VGA-Buchse
nach außen geführt wird.&lt;br /&gt;
Vor allem Server-Mainboards verzichten auf diese “gute alte” 
Schnittstelle nicht.&lt;/p&gt;

&lt;p&gt;Bei Mäusen und Tastaturen sieht es schon ganz anders aus. &lt;a href=&quot;https://de.wikipedia.org/wiki/PS/2-Schnittstelle&quot;&gt;PS/2&lt;/a&gt;
ist hier grundsätzlich tot. Zwar haben Server-Mainboards oft noch einen einzelnen
Tastaturanschluss für Notfälle, aber auf Consumer-Hardware sind diese
Buchsen schon sehr sehr selten geworden.&lt;/p&gt;

&lt;p&gt;Und schon alleine deshalb sind meine alten KVM-Switches heute nicht mehr
zu gebrauchen…&lt;/p&gt;

&lt;p&gt;… außer: Man hat einen PS/2 zu USB Adapter.&lt;br /&gt;
Ich habe mir ein paar dieser Kabel-Adapter aus Fernost für wenige Euros
zusenden lassen und bin positiv beeindruckt.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/ps2-adapter.jpg&quot; alt=&quot;PS/2 to USB Adapter&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Der USB Chip wird interessanterweise als “Barcode-Scanner” betitelt, liefert
dann aber problemlos Tastatur und Maussignale, die von einem PS/2 Port 
kommen.&lt;/p&gt;

&lt;p&gt;Das ist lustigerweise das Gegenteil von dem, wie es sich in der IT vor über
15 Jahren entwickelt hat.
Damals wurden USB Tastaturen und Mäuse entwickelt, die einen USB zu PS/2
Adapter dabei hatten.&lt;/p&gt;

&lt;p&gt;Man konnte das Gerät also direkt per USB betreiben oder über den Adapter
auch am PS/2 Port einstöpseln.&lt;/p&gt;

&lt;p&gt;Heute mache ich es umgekehrt. Ich wandle die PS/2 Signale meines KVM-Switches
in USB um, damit ein modernes Board ohne PS/2 damit betrieben werden kann.&lt;/p&gt;

&lt;h3 id=&quot;heute-fast-kein-ps2-support-mehr&quot;&gt;Heute fast kein PS/2 Support mehr&lt;/h3&gt;

&lt;p&gt;An einer Stelle benötige ich jedoch immer noch die “alte” Konvertierung von
USB zu PS/2, nämlich wenn ich meine USB Tastatur und Maus an den KVM-Switch
anschließen möchte.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/usb-to-ps2-adapter.jpg&quot; alt=&quot;USB to PS/2 Adapter&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Und genau das macht Probleme. Denn diese Konvertierung wird offenbar kaum mehr
unterstützt.&lt;/p&gt;

&lt;p&gt;Wenn ich eine meiner Mäuse über die alten Adapter von damals anschließen will,
passiert … gar nichts.&lt;/p&gt;

&lt;p&gt;Komisch, denn ich dachte, dass es eine generische Konvertierung von USB zu 
PS/2 gibt. Doch es stellte sich heraus, dass der Adapter nicht “konvertiert”,
sondern nur Datenleitung von USB zu PS/2 durchschaltet.&lt;/p&gt;

&lt;p&gt;Das Geräte (also die Tastatur oder die Maus) muss erkennen, ob es an einem
USB oder PS/2 Port betrieben wird und dementsprechend andere Signale über
die Leitungen schicken.&lt;/p&gt;

&lt;p&gt;Und während ab dem Jahr 2000 alle “modernen” USB-Geräte intern noch den 
Fall-Back auf PS/2 in Hardware implementiert hatten, laufen heute nur noch 
billige USB-Controller, die von PS/2 keine Ahnung haben.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Letztendlich musste ich mir noch eine neue Tastatur und eine neue Maus
besorgen, die noch PS/2-fähig war. Die gibt es im freien Handel noch, 
aber man muss meist das Datenblatt befragen, wo diese Info verzeichnet 
ist.&lt;/p&gt;

&lt;p&gt;Ich vermute mal, dass über 90% der heute verkauften Tastaturen und Mäuse
die alten Schnittstellen nicht mehr unterstützen. Es gilt also die 
letzten Universal-Genies aus der grauen Menge herauszupicken.&lt;/p&gt;

&lt;p&gt;Mit meinem alten Switch bin ich aber glücklich. Er schaltet problemlos
zwischen meinen sekundären Testgeräten hin und her, und kann damit
vor der Verschrottung bewahrt werden.&lt;br /&gt;
Und am Zweitwohnsitz habe ich noch einige alte Tastaturen “von damals”,
die mit PS/2 aufgewachsen sind.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>CTRL + ALT + Serial</title>
   <link href="https://www.opengate.at/blog/2020/06/ctrl-alt-serial/"/>
   <published>2020-06-06T13:00:00+02:00</published>
   <updated>2020-06-06T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2020/06/ctrl-alt-serial</id>
   <category term="devel" /><category term="hardware" />
   <summary type="text">Man klemmt auf der einen Seite TX, RX und Ground an die PINs eines Systems
und auf der anderen Seite alles an einen USB-to-
Serial Konverter.

Schon kann man fast jedes Linux-System “fernwarten”. Vorausgesetzt, dieses
Linux ist mit einer seriellen Konsole 
konfiguriert.

Tja, aber wie unterbricht man dort einen laufenden Prozess?
CTRL + C würde normalerweise helfen.
… aber wie überträgt man die Tasten CTRL + C über eine serielle
Verbindung?
</summary>
   <content type="html">&lt;p&gt;Man klemmt auf der einen Seite TX, RX und Ground an die PINs eines Systems
und auf der anderen Seite alles an einen USB-to-
&lt;a href=&quot;https://de.wikipedia.org/wiki/Serielle_Schnittstelle&quot;&gt;Serial&lt;/a&gt; Konverter.&lt;/p&gt;

&lt;p&gt;Schon kann man fast jedes Linux-System “fernwarten”. Vorausgesetzt, dieses
&lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt; ist mit einer seriellen Konsole 
konfiguriert.&lt;/p&gt;

&lt;p&gt;Tja, aber wie unterbricht man dort einen laufenden Prozess?
&lt;code&gt;CTRL + C&lt;/code&gt; würde normalerweise helfen.&lt;br /&gt;
… aber wie überträgt man die Tasten &lt;code&gt;CTRL + C&lt;/code&gt; über eine serielle
Verbindung?
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Die Lösung lautet einfach: &lt;a href=&quot;https://de.wikipedia.org/wiki/American_Standard_Code_for_Information_Interchange&quot;&gt;ASCII&lt;/a&gt;
Code 3.&lt;/p&gt;

&lt;p&gt;Alle &lt;code&gt;CTRL&lt;/code&gt; + Buchstabe Kombinationen werden auf die ASCII-Codes 1 bis 26 
abgebildet.&lt;/p&gt;

&lt;p&gt;… wieder was gelernt.&lt;/p&gt;

&lt;h3 id=&quot;ctrl-------64&quot;&gt;Ctrl + ? == ? - 64&lt;/h3&gt;

&lt;p&gt;Das bedeutet natürlich, dass manche Tastenkombinationen etwas Besonderes
bedeuten, z.B.: hat &lt;code&gt;Ctrl + M&lt;/code&gt; dann den Code &lt;code&gt;13&lt;/code&gt; und ist damit der 
&lt;code&gt;ENTER&lt;/code&gt; Taste gleichgesetzt.&lt;br /&gt;
Eigentlich läuft alles nach der Formel: &lt;code&gt;Ctrl + {chr} = ASCII({chr}) - 64&lt;/code&gt;&lt;br /&gt;
Und das hört nicht bei &lt;code&gt;Z -&amp;gt; 26&lt;/code&gt; auf sondern geht bis &lt;code&gt;_ -&amp;gt; 31&lt;/code&gt; weiter.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: right&quot;&gt;ASCII&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Kombination&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Taste&lt;/th&gt;
      &lt;th&gt;Bedeutung&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;3&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;CTRL + C&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt; &lt;/td&gt;
      &lt;td&gt;Programm abbrechen&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;7&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;CTRL + G&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt; &lt;/td&gt;
      &lt;td&gt;\a Bell, akustisches Signal&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;8&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;CTRL + H&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;BACKSPACE&lt;/td&gt;
      &lt;td&gt;\b Zeichen löschen&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;9&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;CTRL + I&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;TAB&lt;/td&gt;
      &lt;td&gt;\t Tabulator einrücken&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;10&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;CTRL + J&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt; &lt;/td&gt;
      &lt;td&gt;\n Line Feed&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;11&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;CTRL + K&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt; &lt;/td&gt;
      &lt;td&gt;\v Vertikaler Tabulator&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;12&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;CTRL + L&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt; &lt;/td&gt;
      &lt;td&gt;\f Form feed, neue Seite&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;13&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;CTRL + M&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;ENTER&lt;/td&gt;
      &lt;td&gt;\r Wagenrücklauf&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;26&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;CTRL + Z&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt; &lt;/td&gt;
      &lt;td&gt;Substitute, Eingabe-Ende&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;27&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;CTRL + [&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;ESCAPE&lt;/td&gt;
      &lt;td&gt;Escape-Sequenz einleiten&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;28&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;CTRL + \&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt; &lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;29&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;CTRL + ]&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt; &lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;30&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;CTRL + ^&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt; &lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;31&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;CTRL + _&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt; &lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h3 id=&quot;weitere-kombinationen&quot;&gt;Weitere Kombinationen&lt;/h3&gt;

&lt;p&gt;Wenn es um die F-Tasten, Pfeiltasten oder &lt;code&gt;Alt + *&lt;/code&gt; geht, wird es leider 
kompliziert. Hier hängt es nämlich vom Terminal-Standard der Zielkonsole
ab. Linux setzt hier auf &lt;a href=&quot;https://de.wikipedia.org/wiki/VT100&quot;&gt;VT-100&lt;/a&gt;
und das generiert Escape-Codes für alle möglichen Tasten und 
Tastenkombinationen.&lt;/p&gt;

&lt;p&gt;Schlimmer ist es beim Einlesen dieser Zeichen über STDIN, denn hier
findet ein Mapping von den Sondertasten auf Buchstaben statt, die mit
einem Präfix Code eingeleitet werden, oft der ASCII Code 0 (NUL).
Oder es werden ebenso Escape-Codes erzeugt.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Die CTRL - Formel ist super und auch schon im GATE Projekt zum Teil
in &lt;code&gt;system/keyboards.h&lt;/code&gt; und &lt;code&gt;system/terminals.h&lt;/code&gt; implementiert.&lt;/p&gt;

&lt;p&gt;Die Sondertasten und &lt;code&gt;Alt&lt;/code&gt; bleiben für mich noch offen. Da ist es 
wichtig eine gutes generisches Mapping zu finden, in welches von
den nativen APIs aus übersetzt wird, damit man gut damit weiterarbeiten
kann.&lt;/p&gt;

&lt;p&gt;CTRL + C ist aber so ziemlich die wichtigste Kombination überhaupt, denn
ohne sie ist es schwierig laufende (oder bockige) Konsolenprogramm zu 
beenden.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Orange-PI 2G-IOT und i96</title>
   <link href="https://www.opengate.at/blog/2020/05/orange-pi/"/>
   <published>2020-05-31T13:00:00+02:00</published>
   <updated>2020-05-31T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2020/05/orange-pi</id>
   <category term="hardware" /><category term="software" />
   <summary type="text">Neben meinem Orange PI Zero besitze ich inzwischen auch die Modelle
Orange PI 2G-IoT und einen 
Orange PI i96.

Aber im Gegensatz zu meinem “Zero”, der Out-of-the-box mit mir reden wollte,
zierten sich die beiden größeren Brüder und forderten eine 
Sonderbehandlung ein.
</summary>
   <content type="html">&lt;p&gt;Neben meinem Orange PI Zero besitze ich inzwischen auch die Modelle
&lt;a href=&quot;http://www.orangepi.org/OrangePi2GIOT/&quot;&gt;Orange PI 2G-IoT&lt;/a&gt; und einen 
&lt;a href=&quot;http://www.orangepi.org/OrangePii96/&quot;&gt;Orange PI i96&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Aber im Gegensatz zu meinem “Zero”, der Out-of-the-box mit mir reden wollte,
zierten sich die beiden größeren Brüder und forderten eine 
Sonderbehandlung ein.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Die wichtigsten Erkenntnisse, die ich durch den beiden Orange PIs gewonnen 
habe, waren:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;em&gt;Es existiert eine Baud-Rate von 921600&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;ALSA ist Schuld und muss weg!&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ansonsten treten bei langen Aktualisierungen gelegentlich Abbrüche auf,
woran aber überforderte SD-Karten Schuld sein können.&lt;br /&gt;
Ansonsten läuft Linux auf den kleinen Rechenknechten ganz gut und das 
wiederum lässt sich schön per serieller Verbindung aufsetzen.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Orange PI i96
&lt;img src=&quot;/blog/assets/img/orange-pi-i96.jpg&quot; alt=&quot;Orange PI i96&quot; /&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Orange PI 2G-IoT
&lt;img src=&quot;/blog/assets/img/orange-pi-iot-2g.jpg&quot; alt=&quot;Orange PI 2G-IoT&quot; /&gt;&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;manche-orange-pis-arbeiten-mit-baudraten-von-921600&quot;&gt;Manche Orange PIs arbeiten mit Baudraten von 921600&lt;/h3&gt;

&lt;p&gt;Bis zu diesem Setup wusste ich nicht, dass serielle Verbindungen mit einer 
so hohen Übertragungsrate arbeiten können.&lt;/p&gt;

&lt;p&gt;Das liegt auch daran, dass die WinAPI mit der Konstante CBR_256000 einen 
Höchstwert festlegt, von dem ich dachte, dass man ihn nicht überschreiten 
könne. Und auch Tools wie &lt;code&gt;hterm&lt;/code&gt; lassen in ihrer Drop-Down Box nur maximal
256000 zu.&lt;/p&gt;

&lt;p&gt;Unser Allrounder &lt;code&gt;PuTTY&lt;/code&gt; lässt uns den Wert aber frei befüllen und plötzlich
tauchten auf der seriellen Konsole tatsächlich lesbare Zeichen auf.&lt;/p&gt;

&lt;p&gt;Also gut, &lt;code&gt;921600&lt;/code&gt; ist das neue &lt;code&gt;0815&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;der-sound-support-ist-buggy-und-muss-weg&quot;&gt;Der Sound Support ist buggy und muss weg&lt;/h3&gt;

&lt;p&gt;Mit den neuen &lt;a href=&quot;https://de.wikipedia.org/wiki/Debian&quot;&gt;Debian&lt;/a&gt; Stretch 
und &lt;a href=&quot;https://de.wikipedia.org/wiki/Ubuntu&quot;&gt;Ubuntu&lt;/a&gt; 18.04 Images machte ich 
folgende schlechte Erfahrung:&lt;br /&gt;
&lt;em&gt;Sie starten genau einmal.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Bis zum Reboot läuft alles perfekt, denn für das WLAN-Setup braucht man genau
so einen … und spätestens dann ist Schluss. 
Das System friert beim Start ein.&lt;/p&gt;

&lt;p&gt;Im Forum fand ich aber die Info für den 2G-IoT, die auch für den i96
galt: &lt;em&gt;Man muss sofort nach dem ersten Boot ALSA deinstallieren.&lt;/em&gt;&lt;br /&gt;
Und das erreicht man über&lt;/p&gt;

&lt;p&gt;&lt;code&gt;apt-get purge –auto-remove alsa-utils&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Und tatsächlich, diesmal friert das System nicht mehr ein, im Gegensatz
zu früheren Tests.&lt;/p&gt;

&lt;p&gt;Man kann dann problemlos &lt;code&gt;orangepi-config&lt;/code&gt; ausführen (was einem beim 
Login empfohlen wird), und danach beliebig oft neustarten.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Meine beiden Neuzugänge waren zwar etwas mühsam bei der Inbetriebnahme, aber
ich durfte wieder etwas über Linux und seine Eigenheiten bzw. Eigenschaften
lernen.&lt;/p&gt;

&lt;p&gt;Jetzt mache ich noch ein Distributions-Update auf Debian Buster und wenn 
alles gut läuft, kann ich ja auch mal eine Build-Kette auf den kleinen
Rechenzwergen ausprobieren.&lt;/p&gt;

&lt;p&gt;Alles in allem als doch noch ein erfolgreicher Tag.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Platinen waschen</title>
   <link href="https://www.opengate.at/blog/2020/05/circuit-clean-up/"/>
   <published>2020-05-30T13:00:00+02:00</published>
   <updated>2020-05-30T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2020/05/circuit-clean-up</id>
   <category term="hardware" />
   <summary type="text">
  Platinen und Flüssigkeit? Nee, bloß nicht.


denk man sich. Aber wie bekommt man die Dinger sauber?
Oder sollen die lieber dreckig bleiben?
</summary>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;Platinen und Flüssigkeit? Nee, bloß nicht.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;denk man sich. Aber wie bekommt man die Dinger sauber?
Oder sollen die lieber dreckig bleiben?
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Gerade auf Experimentierplatinen, wo man fette Spuren aus Lötzinn zwischen
den Kontakten zieht, versaut man die Platine mehr und mehr mit Flussmittel
und klebrigen Lötfettspritzern.&lt;/p&gt;

&lt;p&gt;Im Fachhandel gibt es dafür eigene Leiterplatinenreiniger mit denen man die
Platine einsprühen und dann mit einer Bürste (z.B. einer alten Zahnbürste)
reinigen kann.&lt;/p&gt;

&lt;p&gt;Die Entfernung von Flussmittelresten soll generell gut sein, weil die 
Substanz die Korrosion der Lötkontakte über die Zeit fördern und eine Lötstelle 
somit nach und nach kaputt gehen kann.&lt;/p&gt;

&lt;p&gt;Wenn man aber nicht zum teuren Chemieprodukt greifen möchte, empfehlen
diverse DIY Bastler einen billigen Trick, den ich jetzt auch mehr und mehr 
nutze:&lt;/p&gt;

&lt;p&gt;Man kauft sich eine günstige Flasche Brennspiritus und bürstet damit seine
Platinen ab.&lt;br /&gt;
Wenn man parallel keine Zigaretten raucht (Vorsicht, das Zeug brennt gut!),
hat man damit ein alternatives Reinigungsmittel gefunden, mit dem vergleichbar
gute Ergebnisse erzielt werden, Geld gespart wird und nicht ganz so “scharfe”
Chemie zu Hause eingesetzt werden muss.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Das Wissen um solche einfachen Hausmittel sollte stets verbreitet werden,
was ich hiermit auch getan hätte.&lt;/p&gt;

&lt;p&gt;Natürlich macht es aber Sinn, dem Verschmutzen von Platinen im Vorfeld
vorzubeugen. Ich ziehe daher nach Möglichkeit keine dicken Lötspuren mehr
quer über die Platine, sondern nutze die abgetrennten Beinchen von 
Widerständen und Kondensatoren um Wegstrecken zu überbrücken.&lt;/p&gt;

&lt;p&gt;Das erspart nicht nur eine Menge Lötzinn sondern reduziert auch 
den Reinigungsbedarf.&lt;/p&gt;

&lt;p&gt;… und am Ende sind alle glücklich.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Windows Nano Server API</title>
   <link href="https://www.opengate.at/blog/2020/05/nano-server/"/>
   <published>2020-05-24T13:00:00+02:00</published>
   <updated>2020-05-24T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2020/05/nano-server</id>
   <category term="devel" /><category term="software" />
   <summary type="text">2016 ließ Microsoft mit dem Titel Nano Server
aufhorchen. Offenbar war ihnen der Server-Core
doch wieder zu groß geworden und so wurde eine neue Abspeck-Kur vollzogen, die
eine Installation von Windows Server unter einem Gigabyte Festplattenplatz 
möglich machte.

Für mich stellte sich nun die Frage:


  Welche APIs sind da wohl herausgefallen?


</summary>
   <content type="html">&lt;p&gt;2016 ließ Microsoft mit dem Titel &lt;a href=&quot;https://en.wikipedia.org/wiki/Windows_Server_2016#Nano_Server&quot;&gt;Nano Server&lt;/a&gt;
aufhorchen. Offenbar war ihnen der &lt;a href=&quot;https://en.wikipedia.org/wiki/Server_Core&quot;&gt;Server-Core&lt;/a&gt;
doch wieder zu groß geworden und so wurde eine neue Abspeck-Kur vollzogen, die
eine Installation von Windows Server unter einem Gigabyte Festplattenplatz 
möglich machte.&lt;/p&gt;

&lt;p&gt;Für mich stellte sich nun die Frage:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Welche APIs sind da wohl herausgefallen?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Die Antwort war schnell gefunden auf &lt;a href=&quot;http://docs.microsoft.com/en-us/previous-versions/windows/desktop/legacy/mt588480(v=vs.85)&quot;&gt;docs.microsoft.com&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Software, die gegen andere &lt;a href=&quot;https://de.wikipedia.org/wiki/Programmierschnittstelle&quot;&gt;APIs&lt;/a&gt;
linkt als die aufgelisteten, wird unter Nano Server einfach nicht laufen.&lt;/p&gt;

&lt;p&gt;Natürlich musste ich das umgehend mit &lt;code&gt;gatecli&lt;/code&gt; testen und stellte mit Bedauern
fest: das GATE-Framework ist nicht Nano-Server-tauglich.&lt;/p&gt;

&lt;p&gt;Das konnte ich natürlich nicht auf mir sitzen lassen und durchforstete die 
Quellcodes. Denn eigentlich sollten reine Konsolenanwendungen keine
UI-Funktionen nutzen und nur wenige rudimentäre Windows APIs einsetzen.&lt;/p&gt;

&lt;p&gt;Fündig wurde ich überraschenderweise bei den Prozess-APIs.
Ich hatte dort eingebaut, dass &lt;code&gt;gate_process_terminate()&lt;/code&gt; die Fenster eines
Prozesses ausfindig machen soll um denen ein Exit-Signal zu senden.
Und eben diese Funktionen stoßen beim Nano Server auf Ablehnung.&lt;/p&gt;

&lt;p&gt;Die Lösung war aber denkbar einfach: Auch diese Funktionen wandern in den
Platform-Support-Layer und werden nur geladen und genutzt, wenn sie auch
vorhanden sind.&lt;/p&gt;

&lt;p&gt;Und nach ein paar anderen Kleinigkeiten testete ich ein neues Release
diesmal mit Erfolg.&lt;br /&gt;
Ich kann somit offiziell behaupten, dass das GATE Framework 
Nano-Server-tauglich ist und ich vermute mal, dass diesem Kriterium 
nicht jede Bibliothek gerecht wird.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ein guter Tag und eine schöne neue gewonnene Erkenntnis.
So kann das Leben gerne weiterlaufen.&lt;/p&gt;

&lt;p&gt;Der Nano Server war ursprünglich für &lt;a href=&quot;https://de.wikipedia.org/wiki/Virtuelle_Maschine&quot;&gt;VMs&lt;/a&gt; 
gedacht, doch in Zeiten von &lt;a href=&quot;https://de.wikipedia.org/wiki/Docker_(Software)&quot;&gt;Docker&lt;/a&gt;
hat Microsoft den Fokus neu ausgerichtet.&lt;br /&gt;
Mit dem &lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_Server_2019&quot;&gt;Server 2019&lt;/a&gt; sind 
Nano Server Instanzen nur noch Docker-Enterprise Container und zeichnen sich
durch ihre geringe Größe aus. Nur noch wenige hundert Megabytes benötigt ein 
Nano-Image und das spart bei vielen Instanzen enorm viel Speicherplatz.&lt;/p&gt;

&lt;p&gt;Ich werde diese Zielplattform also im Auge behalten und vermute,
dass auch in Zukunft immer wieder kleine Änderungen deshalb notwendig sein
werden.&lt;/p&gt;

&lt;p&gt;… aber hey, ein paar Herausforderungen braucht man schließlich!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Docker - Eine komische Tragödie</title>
   <link href="https://www.opengate.at/blog/2020/05/docker/"/>
   <published>2020-05-23T13:00:00+02:00</published>
   <updated>2020-05-23T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2020/05/docker</id>
   <category term="software" />
   <summary type="text">
  Die Existenz von Docker beweist, dass alles, was nur hätte schief gehen
können, auch schief gegangen ist.


So in etwa würde ich ein Kapitel meiner Autobiografie einleiten.
Gefolgt von:


  Und Schuld hat Linux.


Aber man sagt auch, ich würde zu Übertreibungen neigen …

</summary>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;Die Existenz von Docker beweist, dass alles, was nur hätte schief gehen
können, auch schief gegangen ist.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So in etwa würde ich ein Kapitel meiner Autobiografie einleiten.&lt;br /&gt;
Gefolgt von:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Und Schuld hat Linux.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Aber man sagt auch, ich würde zu Übertreibungen neigen …&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Bevor man mir Negativität vorwirft sei erwähnt, dass ich die Software 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Docker_(Software)&quot;&gt;Docker&lt;/a&gt; besonders für einige 
ihrer Einsatzorte sehr schätzen gelernt habe. Besonders die Arbeit am 
&lt;a href=&quot;https://en.wikipedia.org/wiki/Windows_Server_2016#Nano_Server&quot;&gt;Windows Nano Server&lt;/a&gt;
beweist, dass Container auch ein Segen sein können.&lt;br /&gt;
Und ich könnte mir größere Linux-Buildumgebungen ohne dieses Tool 
heute nur mehr schwer vorstellen.&lt;/p&gt;

&lt;p&gt;Doch hier möchte ich mal mein Leid klagen, welches schon vor dem Jahr 2000 
begann:&lt;/p&gt;

&lt;h3 id=&quot;die-dll-hell-saga&quot;&gt;Die DLL-Hell Saga&lt;/h3&gt;

&lt;p&gt;Mir liegen immer noch die zynischen Kommentare der &lt;a href=&quot;https://de.wikipedia.org/wiki/Chaosradio&quot;&gt;Chaos Radio&lt;/a&gt;
Moderatoren in den Ohren, die &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_95&quot;&gt;Windows 95&lt;/a&gt;
und 98 (zu Recht!) verteufelten, und nur all zu gerne die &lt;a href=&quot;https://de.wikipedia.org/wiki/DLL-Konflikt&quot;&gt;DLL-Hölle&lt;/a&gt;
als Schwachpunkt nannten.&lt;/p&gt;

&lt;p&gt;Das Problem bei der Weiterentwicklung von Software ist, dass man zwangsläufig
Kompatibilität verliert, weil neue Technologien immer weniger zu alten 
Schnittstellen passen.&lt;br /&gt;
Die DLL-Hölle entstand, wenn die Installationsroutine einer älteren Software 
neue DLLs des Systems durch ältere Versionen ersetzte, oder umgekehrt, wenn 
neue Software ältere Komponenten stillschweigend erweiterten.&lt;/p&gt;

&lt;p&gt;Damit funktionierte immer nur die zuletzt installierte Software während 
andere Produkte plötzlich grafisch fehlerhaft wurden oder gleich ganz 
abstürzten.&lt;/p&gt;

&lt;p&gt;Und so erlangte Windows den Ruf, kein brauchbares System zu sein, weil 
“nicht mal” eine einfache Versionsverwaltung für Systemkomponenten hatte.&lt;/p&gt;

&lt;p&gt;Ein solches Feature wurde dann schritteweise eingeführt und mit &lt;a href=&quot;https://en.wikipedia.org/wiki/Side-by-side_assembly&quot;&gt;SxS&lt;/a&gt;
(auch als Side-by-Side-Assemblies bekannt) etabliert.
Nun konnten mehrere DLLs parallel installiert werden und ein Programm bekam
nur jene Version zu sehen, die zu ihm passte.&lt;/p&gt;

&lt;h3 id=&quot;container-weil--warum&quot;&gt;Container, weil … warum?&lt;/h3&gt;

&lt;p&gt;Mich stört, dass seit ein paar Jahren krampfhaft mit “Docker” versucht
wird ein vergleichbares Feature auch auf Linux zu etablieren.&lt;/p&gt;

&lt;p&gt;Denn die anfangs so gelobte Versionsverwaltung zeigt bei allen Distributionen
ihre Grenzen und so laufen unter Linux viele Programme nur dann, wenn 
andere Programme NICHT installiert sind, oder nur in einer bestimmten
Version vorliegen.&lt;/p&gt;

&lt;p&gt;Brauchte man zwei sich nicht leiden wollende Programme auf einem System, 
musste man entweder auf eines verzichten oder durfte sich mit Softwarefehlern
herumschlagen.&lt;/p&gt;

&lt;p&gt;Docker-Container lösen dieses Problem durch eine besondere Trennschicht
zwischen den Prozessen namens &lt;a href=&quot;https://en.wikipedia.org/wiki/Cgroups&quot;&gt;cgroups&lt;/a&gt;. 
Während nur ein Kernel läuft, kann das Userland in mehreren Instanzen 
(==Containern) parallel laufen ohne sich sehen oder stören zu können.&lt;/p&gt;

&lt;p&gt;So können auch unterschiedliche inkompatible Bibliotheken parallel genutzt
werden. Und rein theoretisch wäre das eine gute Sache …&lt;/p&gt;

&lt;h3 id=&quot;warum-nicht-gleich-alles-richtig-machen&quot;&gt;Warum nicht gleich alles richtig machen?&lt;/h3&gt;

&lt;p&gt;Bibliotheken stören sich grundsätzlich nicht gegenseitig … außer man 
programmiert sie so störrisch.&lt;/p&gt;

&lt;p&gt;Meist sind es Kleinigkeiten, wie ein globaler &lt;a href=&quot;https://de.wikipedia.org/wiki/Socket_(Software)&quot;&gt;Socket&lt;/a&gt;
oder eine named &lt;a href=&quot;https://de.wikipedia.org/wiki/Pipe_(Informatik)&quot;&gt;Pipe&lt;/a&gt;.
Vielleicht eine temporäre Datei oder ein bestimmter laufender Prozess.
Am häufigsten kam mir jedoch eine unterschiedliche Version der C-Runtime unter.&lt;/p&gt;

&lt;p&gt;… aber alle reden sie doch mit dem exakt gleichen Kernel. Und genau das ist 
der Punkt. Die Kernelschnittstelle ist standardisiert. Egal was eine 
Bibliothek tut, am Ende nutzen alle den gleichen Kernel, auch ohne Docker.&lt;/p&gt;

&lt;p&gt;Würden also die Bibliotheken “ordentlich” ausprogrammiert sein und 
sich nicht gegenseitig stören und z.B. die C-Runtime statisch linken, so 
gäbe es keinen Grund nicht alles parallel zu installieren und ohne
Docker störungsfrei auszuführen.&lt;/p&gt;

&lt;p&gt;Und wer mit dem Argument Sicherheit kommt, dem möchte ich hiermit
&lt;a href=&quot;https://de.wikipedia.org/wiki/Chroot&quot;&gt;&lt;code&gt;chroot&lt;/code&gt;&lt;/a&gt; vorstellen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Es fällt mir daher schwerer die guten Seiten von Docker zu bewundern, wenn
ich es als Mogelwerkzeug in der Softwareentwicklung sehe. Und deshalb werde
ich weiter dafür kämpfen, dass Software so entwickelt wird, dass sie ohne 
Virtualisierungskäfige störungsfrei betrieben werden kann.&lt;/p&gt;

&lt;p&gt;Man vergisst auch gerne, dass Docker-Container wie kleine VMs betrieben 
werden und einmal aufgesetzt auch Wartung und Updates bräuchten. Doch mit
der Quantität sinkt die Qualität und so laufen dann unzählige Container
mit veralteten Softwareständen und -fehlern weiter.&lt;/p&gt;

&lt;p&gt;Aber genug gelästert. Es bleibt mir wohl auch nichts anderes übrig als diese
Technologie “mitzumachen”, weil es die anderen auch tun.&lt;/p&gt;

&lt;p&gt;Einen Vorteil hat es für mich aber: Ich kann schneller an andere 
Linux-Distributions-Eigenheiten herankommen, als wenn ich sie in VMs mühsam
aufsetzen müsste.&lt;/p&gt;

&lt;p&gt;In diesem Sinne: &lt;code&gt;docker pull *&lt;/code&gt;!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>VT-100 Terminal Emulation</title>
   <link href="https://www.opengate.at/blog/2020/05/vt100/"/>
   <published>2020-05-17T13:00:00+02:00</published>
   <updated>2020-05-17T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2020/05/vt100</id>
   <category term="devel" /><category term="software" /><category term="retro" />
   <summary type="text">Wer kennt eigentlich noch ANSI.SYS, den alten DOS
Treiber, ohne den diverse ASCII
Spiele nicht funktionierten?

Ich habe früher nie verstanden warum es diese Escape-Codes
gibt, doch heute, mit Linux Konsolen 
und den neuen Windows 10 Features lerne ich diesen Uralt-Standard schätzen…
</summary>
   <content type="html">&lt;p&gt;Wer kennt eigentlich noch &lt;code&gt;ANSI.SYS&lt;/code&gt;, den alten &lt;a href=&quot;https://de.wikipedia.org/wiki/MS-DOS&quot;&gt;DOS&lt;/a&gt;
Treiber, ohne den diverse &lt;a href=&quot;https://de.wikipedia.org/wiki/American_Standard_Code_for_Information_Interchange&quot;&gt;ASCII&lt;/a&gt;
Spiele nicht funktionierten?&lt;/p&gt;

&lt;p&gt;Ich habe früher nie verstanden warum es diese &lt;a href=&quot;https://de.wikipedia.org/wiki/Escape-Sequenz&quot;&gt;Escape-Codes&lt;/a&gt;
gibt, doch heute, mit &lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt; Konsolen 
und den neuen Windows 10 Features lerne ich diesen Uralt-Standard schätzen…
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;historisches&quot;&gt;Historisches&lt;/h3&gt;

&lt;p&gt;Texte in Farben auf den Schirm zu bringen war früher wie heute “Hexenwerk”.&lt;/p&gt;

&lt;p&gt;Unter DOS konnte man einfach in das Speichersegment &lt;code&gt;B800h&lt;/code&gt; schreiben, denn 
dort lagen in &lt;a href=&quot;https://de.wikipedia.org/wiki/Color_Graphics_Adapter&quot;&gt;CGA&lt;/a&gt; 
und &lt;a href=&quot;https://de.wikipedia.org/wiki/Video_Graphics_Array&quot;&gt;VGA&lt;/a&gt; Grafikkarten die 
Bytes für Text und Farbcode hintereinander. Zuerst schrieb man das ASCII 
Zeichen in die Zelle mit gerader Adresse und ein Byte weiter dann das 
“Attribut” mit 4 Bits für Hintergrund und 4 Bits für Text-Farbe.&lt;/p&gt;

&lt;p&gt;Die Hintergrundfarbe war je nach Grafik-Modus oft nur mit 3-Bit ausgestattet 
und das letzte (höchste) Bit schaltete ein automatisches Blinken des Textes
aus und ein.&lt;/p&gt;

&lt;p&gt;Den blinkenden Cursor konnte man entweder per BIOS-Aufruf (&lt;code&gt;ah=2, int 10h&lt;/code&gt;) 
oder ein paar &lt;a href=&quot;https://wiki.osdev.org/Text_Mode_Cursor&quot;&gt;Bitänderungen in IO-Registern&lt;/a&gt;
auf eine bestimmte Position des 80 Zeichen x 25 Zeilen Schirmes setzen.&lt;/p&gt;

&lt;p&gt;Die Sache hatte nur einen Haken: Es war “zu” hardware-nah.
Man konnte zwar alles über das BIOS jagen, aber auch diese Aufrufe 
waren vom Grafikkarten-Standard abhängig.&lt;/p&gt;

&lt;p&gt;Mein &lt;a href=&quot;/blog/2019/09/toshiba-t300/&quot;&gt;Toschiba T300&lt;/a&gt; 
nutzte z.B. das Segment &lt;code&gt;0xB000&lt;/code&gt; für die Farbausgabe, wo auf IBM-PCs
früher der Monochrom-Bereich angelegt war, und sein BIOS war leider ebenso
nicht PC-konform.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Die Lösung:&lt;/em&gt; Man schafft eine OS-Schnittstelle, mit der Kontroll-Zeichen, 
die überall gleich sind, in die nativen grafischen Aufrufe übersetzt werden.&lt;/p&gt;

&lt;h3 id=&quot;vt100&quot;&gt;VT100&lt;/h3&gt;

&lt;p&gt;Das &lt;a href=&quot;https://en.wikipedia.org/wiki/VT100&quot;&gt;VT100&lt;/a&gt; war ein Terminal aus den 
späten 70ern … und mehr weiß ich darüber nicht.&lt;br /&gt;
Aber es war wohl eines der ersten, das “ANSI Escape Codes” benutzt hat,
um Textgrafik darstellen zu können.&lt;br /&gt;
Und eben die Technik nutzt jedes Linux/Unix heute für seine “farbigen”
Konsolenausgaben, wie auch &lt;code&gt;ANSI.SYS&lt;/code&gt; unter DOS und seit neuem kann es
sogar Windows 10 (25 Jahre zu spät!).&lt;/p&gt;

&lt;p&gt;Man nutzt den ASCII Code &lt;code&gt;ESC&lt;/code&gt; numerisch 27 (entspricht auch der Escape-Taste
auf dem Keyboard) um eine solche Sequenz einzuleiten.
Die folgenden Zeichen sind dann Kommandos und Parameter für z.B.:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;das Setzen von Text- und Hintergrundfarbe&lt;/li&gt;
  &lt;li&gt;das Bewegen des Cursors zu neuen Positionen&lt;/li&gt;
  &lt;li&gt;das Ein/Ausschalten des blinkenden Cursors&lt;/li&gt;
  &lt;li&gt;das Löschen des gesamten Bildschirms&lt;/li&gt;
  &lt;li&gt;u. v. m.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Will man also ein “Hallo Welt” farbig auf die Konsole schreiben, nutzt man:
&lt;code&gt;&quot;\x1b[1;33;44m Hello \x1b[0;32;47m World &quot;&lt;/code&gt;
um ein&lt;/p&gt;

&lt;div style=&quot;font-family:Courier New,Courier,monospace&quot;&gt;
&lt;span style=&quot;background-color:#000099;color:#ffff00;&quot;&gt; Hello &lt;/span&gt;&lt;span style=&quot;background-color:#999999;color:#009900;&quot;&gt; World &lt;/span&gt;
&lt;/div&gt;

&lt;p&gt;zu sehen. Die drei Parameter werden mit &lt;code&gt;[&lt;/code&gt; eingeleitet, mit Semikolons &lt;code&gt;;&lt;/code&gt;
getrennt und bedeuten:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Attribut der Textfarbe (0=dunkel, 1=hell)&lt;/li&gt;
  &lt;li&gt;Textfarbe 30 - 37 für die Farben:
    &lt;ul&gt;
      &lt;li&gt;30: schwarz / dunkel-grau&lt;/li&gt;
      &lt;li&gt;31: rot / hellrot&lt;/li&gt;
      &lt;li&gt;32: grün / hellgrün&lt;/li&gt;
      &lt;li&gt;33: orange / gelb&lt;/li&gt;
      &lt;li&gt;34: blau / hellblau&lt;/li&gt;
      &lt;li&gt;35: magenta&lt;/li&gt;
      &lt;li&gt;36: cyan /&lt;/li&gt;
      &lt;li&gt;37: grau / weiß&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Hintergrundfarbe 40 - 47&lt;br /&gt;
Die gleiche Belegung wie Textfarbe + 10&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Und terminiert bzw. identifiziert wird mit einem finalen &lt;code&gt;m&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Den Cursor bewegt man per &lt;code&gt;\x1b[80;25H&lt;/code&gt; zur rechten unteren Ecke eines 
80x25 Systems.&lt;br /&gt;
Also: &lt;code&gt;&quot;\x1b[&quot; + x + &quot;;&quot; + y + &quot;H&quot;&lt;/code&gt;
wobei wir mit 1 zu zählen beginnen (und nicht bei Null).&lt;/p&gt;

&lt;p&gt;Die gesamte Konsolenausgabe löschen kann man mit: &lt;code&gt;\x1b[2J&lt;/code&gt;
Wobei man vorher die Text- und Hintergrundfarbe setzen sollte, denn die
gelöschte Konsole wird mit den aktuellen Farbinfos geflutet.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Im GATE Projekt kümmert sich der &lt;code&gt;system/terminals.h&lt;/code&gt; Header um ein Interface
zu realen und virtuellen Konsolen. Während die &lt;code&gt;WINAPI&lt;/code&gt; Implementierung auch 
&lt;a href=&quot;http://docs.microsoft.com/en-us/windows/console/console-functions&quot;&gt;native Funktionen&lt;/a&gt; 
einsetzt um Farben und Cursor zu manipulieren, läuft unter 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Portable_Operating_System_Interface&quot;&gt;POSIX&lt;/a&gt; und 
unter Windows per Flag auf Wunsch im Hintergrund stets eine einfache 
Übersetzung nach VT-100 Escape Sequenzen.&lt;br /&gt;
(Erweiterte Funktionen sind vorläufig nicht von Nöten.)&lt;/p&gt;

&lt;p&gt;Und ich finde diesen Standard zwar “etwas seltsam” in der Art wie er 
definiert ist, aber letztendlich mag ich ihn.&lt;/p&gt;

&lt;p&gt;Besonders wenn man per serieller Schnittstelle verbunden ist, lassen sich durch
VT-100 Codes auch hilfreiche Text-UIs übertragen und anzeigen.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/PuTTY&quot;&gt;PuTTY&lt;/a&gt;, &lt;a href=&quot;http://mobaxterm.mobatek.net/&quot;&gt;MobaXterm&lt;/a&gt;
und viele andere Tools unterstützen diesen Standard unter Windows und unter
Linux ist er sowieso Pflicht.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Windows Management Instrumentation</title>
   <link href="https://www.opengate.at/blog/2020/05/wmi/"/>
   <published>2020-05-16T13:00:00+02:00</published>
   <updated>2020-05-16T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2020/05/wmi</id>
   <category term="devel" />
   <summary type="text">Es gibt zahlreiche Infos zu WMI, 
der Windows Management Instrumentation, im Netz. Die ältesten und reinsten 
davon entspringen der VBScript 
Zeit rund um die 2000er. Heute ersetzen oft dotNET
und PowerShell Konstrukte all das, 
was im Hintergrund bis heute mit WMI erledigt wird.

Wenn man aber in C++ “gegen” WMI programmiert, braucht man einige 
Meta-Informationen, die man nicht sofort findet, wenn man “WMI” in die 
Suchanfrage tippt.
</summary>
   <content type="html">&lt;p&gt;Es gibt zahlreiche Infos zu &lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_Management_Instrumentation&quot;&gt;WMI&lt;/a&gt;, 
der Windows Management Instrumentation, im Netz. Die ältesten und reinsten 
davon entspringen der &lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_Basic_Script&quot;&gt;VBScript&lt;/a&gt; 
Zeit rund um die 2000er. Heute ersetzen oft &lt;a href=&quot;https://de.wikipedia.org/wiki/.NET_Framework&quot;&gt;dotNET&lt;/a&gt;
und &lt;a href=&quot;https://de.wikipedia.org/wiki/PowerShell&quot;&gt;PowerShell&lt;/a&gt; Konstrukte all das, 
was im Hintergrund bis heute mit WMI erledigt wird.&lt;/p&gt;

&lt;p&gt;Wenn man aber in C++ “gegen” WMI programmiert, braucht man einige 
Meta-Informationen, die man nicht sofort findet, wenn man “WMI” in die 
Suchanfrage tippt.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Im GATE Projekt übernimmt die Bibliothek &lt;code&gt;gate/system/management.h&lt;/code&gt;
die Kommunikation mit Verwaltungsroutinen des Betriebssystems.
Unter Windows wird hier WMI implementiert.&lt;/p&gt;

&lt;p&gt;Das ganze ist ein Baum von Pfaden und Objekten, die Einstellungen und Methoden
bereitstellen, also all das, was WMI selbst auch bietet.&lt;/p&gt;

&lt;p&gt;Doch während Scripts für spezifische Aufgaben diverse WMI Pfade “hardcoden”,
verlangt der generische Ansatz, dass Infos darüber, was verfügbar ist und was
nicht, zur Laufzeit ausgelesen wird.&lt;/p&gt;

&lt;h3 id=&quot;besondere-wql-anfragen&quot;&gt;Besondere WQL Anfragen&lt;/h3&gt;

&lt;p&gt;Ein paar dieser WMI-Qery-Language (WQL) Suchanfragen möchte ich hier mal 
zusammenfassen:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code&gt;SELECT * FROM __NAMESPACE&lt;/code&gt;&lt;br /&gt;
Die Instanzen von &lt;code&gt;__NAMESPACE&lt;/code&gt; sind die Unternamensräume des
aktuell verbundenen. Wenn man also zum Namespace &lt;code&gt;ROOT&lt;/code&gt; verbunden ist,
erhält man unter anderem den bekannten Eintrag &lt;code&gt;CIMV2&lt;/code&gt;.&lt;br /&gt;
Das Objekt enthält die Eigenschaft &lt;code&gt;Name&lt;/code&gt;, dessen Inhalt direkt
zur Erzeugung des Pfades benutzt werden kann.
Beispiel-Ergebnis-Pfad: &lt;code&gt;\\MYPCNAME\ROOT:__NAMESPACE.Name=&quot;Hardware&quot;&lt;/code&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code&gt;SELECT * FROM META_CLASS&lt;/code&gt;&lt;br /&gt;
So listet man alle Klassen in einem Namespace auf.
Die Objekte haben zwar keine Eigenschaften, aber der Pfad endet eben auf den
Klassennamen. Man kann ihn einfach nach dem Doppelpunkt auslesen.&lt;br /&gt;
Beispiel-Ergebnis-Pfad: &lt;code&gt;\\MYPCNAME\ROOT\CIMV2:Win32_PrinterShare&lt;/code&gt;&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Mit diesen Routinen kann man sich bereits einen WMI Namespace aussuchen und #
alle seine Objekt auflisten.&lt;/p&gt;

&lt;p&gt;Hat man dann eine Auflistung von &lt;code&gt;IWbemClassObject&lt;/code&gt; Instanzen, kann man über
&lt;code&gt;BeginEnumeration&lt;/code&gt; zwei Arten von Eigenschaften auslesen:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Das Flag &lt;code&gt;WBEM_FLAG_SYSTEM_ONLY&lt;/code&gt; bewirkt, dass nur die 
Infrastruktur-Eigenschaften wie &lt;code&gt;__PATH&lt;/code&gt; oder &lt;code&gt;__CLASS&lt;/code&gt; zurückgegeben werden.
So findet man den direkten Pfad eines Objektes, den man für spätere Aufrufe
brauchen kann.&lt;/li&gt;
  &lt;li&gt;Mit dem Flag &lt;code&gt;WBEM_FLAG_NONSYSTEM_ONLY&lt;/code&gt; erhält man alle Eigenschaften, die
Daten des Objektes beinhalten, also alles was uns eigentlich interessiert.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Natürlich gibt es noch ein paar andere Flags um z.B. vererbte Eigenschaften 
auszuschließen usw., doch für meine Zwecke waren diese bisher nie erforderlich.&lt;/p&gt;

&lt;h3 id=&quot;anwendungen&quot;&gt;Anwendungen&lt;/h3&gt;

&lt;p&gt;Über WMI lässt sich verdammt viel in Windows anstellen. Nicht nur, dass alle 
möglichen Einstellungen des OS oder von Geräten und Treiber ausgelesen werden
können, sondern wir erhalten hier exklusiv Zugriff auf Dienste wie:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/IP-Adresse&quot;&gt;IP Addressen&lt;/a&gt; 
und deren Konfiguration (Routen, etc.)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Hyper-V&quot;&gt;Hyper-V&lt;/a&gt; Einstellungen und VMs&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://docs.microsoft.com/en-us/windows-hardware/customize/enterprise/unified-write-filter&quot;&gt;Write Filter&lt;/a&gt; (in Windows 10 IOT)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/BIOS&quot;&gt;BIOS&lt;/a&gt;/EFI Parameter&lt;/li&gt;
  &lt;li&gt;Boot Optionen&lt;/li&gt;
  &lt;li&gt;Dienste und ihre Konfiguration&lt;/li&gt;
  &lt;li&gt;Die &lt;a href=&quot;https://de.wikipedia.org/wiki/Registrierungsdatenbank&quot;&gt;Windows Registry&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Event Logs (und zwar bereits mit ausgewerteten Texten)&lt;/li&gt;
  &lt;li&gt;Installierte Programme&lt;/li&gt;
  &lt;li&gt;Netzwerkfreigaben und das Dateisystem 
(man kann sogar noch Dateien mit Mustern suchen lassen)&lt;/li&gt;
  &lt;li&gt;Zahlreiche Windows (und Windows Server) Dienste&lt;/li&gt;
  &lt;li&gt;und vieles mehr&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Kurz gesagt: Alles was der Admin braucht, findet er in WMI. Und deshalb 
basiert auch vieles in der PowerShell, der Remote-Shell und dem dotNET
Namespace &lt;code&gt;System.Management&lt;/code&gt; auf dieser Technologie.&lt;/p&gt;

&lt;p&gt;Einen Nachteil möchte ich nicht verschweigen: WMI wurde als synchrone API
konzipiert und seine Reaktionszeiten sind … naja, nicht immer schnell.&lt;/p&gt;

&lt;p&gt;Frameworks gestatten zwar die asynchrone Nutzung von WMI und erlauben somit
auch Abbrüche von Anfragen, doch das beendet in der Regel nicht den Prozess
im Hintergrund, der die Daten sammelt.&lt;/p&gt;

&lt;p&gt;Wer also viel mit WMI “parallel” machen möchte, wird schnell seine CPU 
Auslastung hochtreiben.&lt;/p&gt;

&lt;p&gt;Wie auch immer … für Administrationsaufgaben ist diese Schnittstelle
unabdingbar.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Server 2016 mit Powershell ohne TLS</title>
   <link href="https://www.opengate.at/blog/2020/05/powershell-tls/"/>
   <published>2020-05-10T13:00:00+02:00</published>
   <updated>2020-05-10T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2020/05/powershell-tls</id>
   <category term="software" />
   <summary type="text">Boah! Bin ich wieder angefressen!
Ich wollte nur eine kleine Installation starten, doch die brauchte 
NuGet.
Und dessen Installation meinte:


  1Unable to download from URI 
2&apos;https://go.microsoft.com/fwlink/?LinkID=627338&amp;amp;clcid=0x409&apos; to &apos;&apos;.  
3Install-PackageProvider : No match was found for 
4the specified search criteria for the provider &apos;NuGet&apos;. 
5The package provider requires &apos;PackageManagement&apos; and &apos;Provider&apos; tags. 
6Please check if the specified package has the tags.




Was zur Hölle geht denn da wieder ab?
</summary>
   <content type="html">&lt;p&gt;Boah! Bin ich wieder angefressen!&lt;br /&gt;
Ich wollte nur eine kleine Installation starten, doch die brauchte 
&lt;a href=&quot;https://de.wikipedia.org/wiki/NuGet&quot;&gt;NuGet&lt;/a&gt;.
Und dessen Installation meinte:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;Unable to download from URI 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;&apos;https://go.microsoft.com/fwlink/?LinkID=627338&amp;amp;clcid=0x409&apos; to &apos;&apos;.  
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;Install-PackageProvider : No match was found for 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;the specified search criteria for the provider &apos;NuGet&apos;. 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;The package provider requires &apos;PackageManagement&apos; and &apos;Provider&apos; tags. 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;Please check if the specified package has the tags.
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Was zur Hölle geht denn da wieder ab?
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;also-gleich-zur-lösung&quot;&gt;Also gleich zur Lösung:&lt;/h3&gt;

&lt;p&gt;Das betroffene System war: &lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_Server_2016&quot;&gt;Windows Server 2016&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Offenbar war eine Einstellung bezüglich &lt;a href=&quot;https://de.wikipedia.org/wiki/Transport_Layer_Security&quot;&gt;TLS&lt;/a&gt;
(also HTTPS) falsch.
Die Zeile&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;reparierte dann den Fehler und NuGet ließ sich per&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;Install-PackageProvider -Name NuGet -RequiredVersion 2.8.5.201 -Force
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;einrichten.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Aber langsam pisst es mich echt an, dass man keinen Download und kein Update
mehr durchführen kann, ohne dass man Einstellungen für TLS oder 
Zertifikate abändern (oder noch schlimmer: deaktivieren) muss.&lt;/p&gt;

&lt;p&gt;Ich erwarte mir von einer Installationsprozedur von einer Microsoft-Seite,
dass diese entweder die nötigen Einstellungen dokumentiert, oder dass eine
Standardinstallation so gefertigt ist, dass sie auch ohne solche billigen
Tricks auskommt.&lt;/p&gt;

&lt;p&gt;Ist es denn zu viel verlangt, dass Software länger als 1 Jahr nach dem
Release funktioniert?&lt;br /&gt;
Denn offenbar leiden immer mehr Projekte am Krypto-Problem, dass sie 
spätestens zwei Jahre nach Veröffentlichung nicht mehr dem aktuellen
Verschlüsselungsstandard entsprechen und deshalb gesperrt werden.&lt;/p&gt;

&lt;p&gt;Tja, unter &lt;a href=&quot;https://de.wikipedia.org/wiki/MS-DOS&quot;&gt;DOS&lt;/a&gt; musste ich mich 
seinerzeit mit so etwas nicht ärgern!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>BitBucket mit CMake und Caches</title>
   <link href="https://www.opengate.at/blog/2020/05/bitbucket/"/>
   <published>2020-05-09T13:00:00+02:00</published>
   <updated>2020-05-09T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2020/05/bitbucket</id>
   <category term="software" /><category term="projects" />
   <summary type="text">Der Source-Hoster BitBucket bietet neben 
GIT zur reinen Quellcodeverwaltung
auch Tools zum automatischen Bauen von Software an.
Dieses Continuous Integration 
Features (oder kurz “CI”) bietet Support für unterschiedliche Werkzeuge für 
alles mögliche Zeugs von dotNET Core
bis Java.

Das wichtigste fehlt natürlich: nämlich CMake.
Zum Glück kann man sich das aber selbst hinbiegen.
</summary>
   <content type="html">&lt;p&gt;Der Source-Hoster &lt;a href=&quot;https://bitbucket.org/&quot;&gt;BitBucket&lt;/a&gt; bietet neben 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Git&quot;&gt;GIT&lt;/a&gt; zur reinen Quellcodeverwaltung
auch Tools zum automatischen Bauen von Software an.
Dieses &lt;a href=&quot;https://de.wikipedia.org/wiki/Kontinuierliche_Integration&quot;&gt;Continuous Integration&lt;/a&gt; 
Features (oder kurz “CI”) bietet Support für unterschiedliche Werkzeuge für 
alles mögliche Zeugs von &lt;a href=&quot;https://de.wikipedia.org/wiki/.NET_Core&quot;&gt;dotNET Core&lt;/a&gt;
bis &lt;a href=&quot;https://de.wikipedia.org/wiki/Java_(Programmiersprache)&quot;&gt;Java&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Das wichtigste fehlt natürlich: nämlich &lt;a href=&quot;https://de.wikipedia.org/wiki/CMake&quot;&gt;CMake&lt;/a&gt;.
Zum Glück kann man sich das aber selbst hinbiegen.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;kein-cmake-auf-bitbucket&quot;&gt;Kein CMake auf BitBucket?&lt;/h3&gt;

&lt;p&gt;OK, bevor man mir vorwirft die Unwahrheit zu sagen, sollte man präzisieren:
BitBucket bietet kein fertiges &lt;a href=&quot;https://de.wikipedia.org/wiki/Docker_(Software)&quot;&gt;Docker&lt;/a&gt;
Image an, auf welchem &lt;code&gt;CMake&lt;/code&gt; vorkonfiguriert ist, lässt einen aber andere 
Images vom Docker Hub einbinden.&lt;/p&gt;

&lt;p&gt;Aber “nur wegen” einem “kleinen” &lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B&quot;&gt;C oder C++&lt;/a&gt;
Projekt habe ich keine Lust extern auch noch an Docker herumzudoktoren
(zumindest heute nicht).&lt;/p&gt;

&lt;p&gt;Die Frage ist daher:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Kann man nicht ein Standard-Image so “umkonfigurieren”, dass es
CMake builds anstoßen kann?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Die Antwort lautet: &lt;em&gt;Ja&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Man muss nur bei jedem Build-Vorgang die nötigen Tools und Bibliotheken 
nachinstallieren. Und nachdem die BitBucket Images auf &lt;a href=&quot;https://de.wikipedia.org/wiki/Ubuntu&quot;&gt;Ubuntu Linux&lt;/a&gt;
basieren, reicht ein entsprechendes &lt;code&gt;apt-get&lt;/code&gt; aus.&lt;/p&gt;

&lt;h3 id=&quot;die-lösung-apt-get-install-cmake&quot;&gt;Die Lösung: &lt;code&gt;apt-get install cmake&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;Liegt im Root eines BitBucket-Repositories eine Datei namens 
&lt;code&gt;bitbucket-pipelines.yml&lt;/code&gt; mit korrektem Inhalt, startet nach jedem Code-Update
die Build-Pipeline.&lt;br /&gt;
Kostenlos stehen einem im Monat 50 Minuten Build-Zeit zur Verfügung, wer mehr 
braucht, kann natürlich Münzen einwerfen.&lt;/p&gt;

&lt;p&gt;Mein ursprüngliches &lt;code&gt;yml&lt;/code&gt; Script für das GATE Projekt sah so aus:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;image:
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;  name: atlassian/default-image:2
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;pipelines:
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  default:
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;    - step:
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;        name: Build
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;        script:
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;          - apt-get update -qq
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;          - apt-get install cmake libasound2-dev -y --force-yes
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;          - apt-get install v4l-utils libv4l-dev -y --force-yes
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;          - apt-get install unixodbc-dev libgtk-3-dev -y --force-yes
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;          - mkdir -p build-cmake
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;          - cd build-cmake
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;          - cmake ../src
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;          - make
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Das &lt;code&gt;default-image:2&lt;/code&gt; sollte benutzt werden, weil es auf Ubuntu 16.04 aufbaut.
Fehlt dieser Eintrag, so landet man beim Image &lt;code&gt;1&lt;/code&gt; mit Ubuntu 14.04 und dort 
ist CMake nur schwer veraltet nachinstallierbar und auch das nur nach dem 
Hinzufügen entsprechender Installationsquellen aus dem Netz.&lt;/p&gt;

&lt;p&gt;Der Ablauf sieht in etwa so aus:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Wir aktualisieren &lt;code&gt;apt&lt;/code&gt; auf den neuesten Stand und installieren dann &lt;code&gt;CMake&lt;/code&gt; 
und alle anderen Entwicklungsbibliotheken für unsere Zwecke.&lt;/li&gt;
  &lt;li&gt;Wir erzeugen ein Unterverzeichnis, in dem CMake arbeiten können soll.&lt;/li&gt;
  &lt;li&gt;Wir wechseln in dieses Verzeichnis und führen dort &lt;code&gt;cmake&lt;/code&gt; so aus, dass es 
die Dateien aus den Quellcodeverzeichnis abarbeitet. Beim GATE Projekt ist 
das &lt;code&gt;/src&lt;/code&gt; und somit muss der relative Pfad &lt;code&gt;../src&lt;/code&gt; für CMake benutzt 
werden.&lt;/li&gt;
  &lt;li&gt;Danach wird einfach &lt;code&gt;make&lt;/code&gt; aufgerufen, das die von CMake generierten
Anweisungen ausführt.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;That’s it!&lt;/em&gt;&lt;/p&gt;

&lt;h3 id=&quot;caches&quot;&gt;Caches&lt;/h3&gt;

&lt;p&gt;Seit noch gar nicht so lange (Stand 2020) bewirbt BitBucket, dass es nun 
“Caches” unterstützt.&lt;br /&gt;
Während normalerweise jeder Build-Vorgang mit einem leeren Image 
beginnt, können mit aktivierten Caches die Ergebnisse eines Builds bzw. die
Inhalte von bestimmten Verzeichnissen gesichert und beim folgenden Build 
weiter benutzt werden.&lt;/p&gt;

&lt;p&gt;Anfangs dachte ich mir:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Hey das ist DIE Lösung für das Nachinstallieren von Programmen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Doch Fehlanzeige!&lt;/strong&gt; Zwar kann man teilweise die &lt;code&gt;apt&lt;/code&gt; Ergebnisse sichern, doch 
das Herunterladen dieser Datenmengen dauert genau so lange, wie wenn man die 
Installation gleich von vorne beginnt … zumindest bei meinen Paketen 
verhält es sich so.&lt;/p&gt;

&lt;p&gt;Aber an einer anderen Stelle bewirken “Caches” kleine Wunder:&lt;br /&gt;
Und zwar bei den &lt;code&gt;CMake&lt;/code&gt; und &lt;code&gt;make&lt;/code&gt; Build-Verzeichnissen.&lt;/p&gt;

&lt;p&gt;Die sind nur einige Megabytes groß und können daher relativ schnell gesichert
und wiederhergestellt werden, aber die Ersparnis beim Kompilieren, wo nur
noch Änderungen übersetzt werden müssen, ist enorm.&lt;/p&gt;

&lt;p&gt;Mein finales GATE Script sieht daher so aus:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;image:
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;  name: atlassian/default-image:2
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;pipelines:
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  default:
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;    - step:
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;        name: Build
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;        caches:
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;          - buildjob
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;        script:
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;          - rm -rf build-cmake/bin-output
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;          - apt-get update -qq
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;          - apt-get install cmake libasound2-dev -y --force-yes
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;          - apt-get install v4l-utils libv4l-dev -y --force-yes
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;          - apt-get install unixodbc-dev libgtk-3-dev -y --force-yes
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;          - cmake --version          
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;          - mkdir -p build-cmake
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;          - cd build-cmake
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;          - cmake ../src
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;          - make
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;          - cd ..
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n21&quot; name=&quot;n21&quot;&gt;21&lt;/a&gt;&lt;/span&gt;        artifacts:
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n22&quot; name=&quot;n22&quot;&gt;22&lt;/a&gt;&lt;/span&gt;          - build-cmake/bin-output/**
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n23&quot; name=&quot;n23&quot;&gt;23&lt;/a&gt;&lt;/span&gt;definitions:
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n24&quot; name=&quot;n24&quot;&gt;24&lt;/a&gt;&lt;/span&gt;  caches:
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n25&quot; name=&quot;n25&quot;&gt;25&lt;/a&gt;&lt;/span&gt;    buildjob: build-cmake
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ohne Caches braucht ein gesamter Build zwischen 3,5 und 4 Minuten.
Davon etwa 30 Sekunden upload/download von Daten, etwa 30 Sekunden für &lt;code&gt;apt&lt;/code&gt;, 
und der Rest sind &lt;code&gt;CMake&lt;/code&gt; und &lt;code&gt;make&lt;/code&gt;, also zwischen 2 und 3 Minuten.&lt;/p&gt;

&lt;p&gt;Abhängig von der Menge der Änderungen dauert ein “inkrementeller” Build mit
Caches aber ebenso nur noch 30 Sekunden.&lt;br /&gt;
Das liegt vor allem an der &lt;a href=&quot;https://de.wikipedia.org/wiki/LibreSSL&quot;&gt;libreSSL&lt;/a&gt;. 
Diese wird von mir (außer bei halbjährlichen Updates) nicht geändert und macht
den Großteil der Buildzeit aus.&lt;/p&gt;

&lt;p&gt;Die GATE Sourcen sind da genügsamer und in etwa 30 Sekunden durchgeackert.
Und da im kostenlosen Angebot nur 50 Minuten pro Monat für Buildpipelines 
inkludiert sind, macht sich der Cache durchaus “bezahlt”.&lt;/p&gt;

&lt;p&gt;Abschließend wird innerhalb von CMAKE mit&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin-output 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;    CACHE PATH &amp;quot;Shared library target directory&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin-output 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;    CACHE PATH &amp;quot;Executable target directory&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin-output 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;    CACHE PATH &amp;quot;Static library target directory&amp;quot;)
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;definiert, dass die Resultate im Verzeichnis &lt;code&gt;bin-output&lt;/code&gt; untergebracht 
werden sollen. Dieses wandert dann ins Build-Artifactory und somit kann das 
Ergebnis eines Builds bequem als ZIP heruntergeladen werden.&lt;/p&gt;

&lt;p&gt;Ursprünglich dachte ich&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ach was, das brauch ich doch nicht.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Doch nun gefällt mir der BitBucket Linux Build mehr und mehr, vor allem wenn
ich von Extern mal schnell die aktuellste Version eines Tools für Linux brauche.&lt;/p&gt;

&lt;p&gt;Jetzt fehlt mir noch ein Windows-Build … doch der ist (vorerst) hier nicht
zu bekommen.&lt;/p&gt;

&lt;p&gt;PS: Natürlich kann man mit &lt;code&gt;make -j4&lt;/code&gt; durch Parallelisierung auch die 
Build-Zeit reduzieren, doch da die Ressourcen von mehreren Usern gebraucht 
werden, gibt es keine Garantie, dass schnell gebaut wird. Die Reduktion
des Build-Materials ist also &lt;em&gt;immer&lt;/em&gt; eine gute Idee.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Visual C++ 6 mit Freud und Leid</title>
   <link href="https://www.opengate.at/blog/2020/05/vc6/"/>
   <published>2020-05-02T13:00:00+02:00</published>
   <updated>2020-05-02T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2020/05/vc6</id>
   <category term="devel" /><category term="retro" />
   <summary type="text">Als ich anfangs der 2000er mit VB6
meine ersten “richtigen” Programme anfing, war stets das gesamte 
Visual Studio
auch mit C++ installiert.

Gemacht habe ich damit aber nicht viel … schließlich verstand ich dieses
“seltsame C++” sowieso nicht und VB war deshalb “viel besser”.

Heute bekommt dieser “seltsamste” aller C++ Compiler einen besonderen Platz
bei mir eingeräumt. Und das GATE Projekt nimmt ihn offiziell in seine 
Supportliste auf.
</summary>
   <content type="html">&lt;p&gt;Als ich anfangs der 2000er mit &lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_Basic_Classic&quot;&gt;VB6&lt;/a&gt;
meine ersten “richtigen” Programme anfing, war stets das gesamte 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_Studio#Version_6.0&quot;&gt;Visual Studio&lt;/a&gt;
auch mit &lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B&quot;&gt;C++&lt;/a&gt; installiert.&lt;/p&gt;

&lt;p&gt;Gemacht habe ich damit aber nicht viel … schließlich verstand ich dieses
“seltsame C++” sowieso nicht und VB war deshalb “viel besser”.&lt;/p&gt;

&lt;p&gt;Heute bekommt dieser “seltsamste” aller C++ Compiler einen besonderen Platz
bei mir eingeräumt. Und das GATE Projekt nimmt ihn offiziell in seine 
Supportliste auf.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Das Studio 98 kam zu einer sehr blöden Zeit auf den Markt. C++ wurde 1998
standardisiert und erklärte viele bis dahin gebräuchlichen Verhaltensweisen
als “falsch”. Microsoft C++ 6 war Teil von Studio 98 und wurde damit vor
der Standardisierung entwickelt, war damit &lt;em&gt;Nicht-Standard-Konform&lt;/em&gt; aber wurde
dennoch bis 2002 als primärer Windows-Compiler eingesetzt und formal erst
im Jahr 2010 endgültig abgelöst.&lt;br /&gt;
(Wer erinnert sich noch an die Meldung “10 is the new 6”, als MSVC10 rauskam?)&lt;/p&gt;

&lt;p&gt;Das ist natürlich gefundenes Fressen für alle Windows-Kritiker, die somit zu 
Recht behaupten konnten, dass Windows auf extrem wackeligen Beinen steht.&lt;/p&gt;

&lt;p&gt;Die Workarounds in &lt;a href=&quot;https://en.wikipedia.org/wiki/Boost_(C%2B%2B_libraries)&quot;&gt;BOOST&lt;/a&gt; 
und anderen Bibliotheken für diesen Sonder-Compiler sind schon fast legendär,
so “pervers” waren sie geschrieben.&lt;/p&gt;

&lt;h3 id=&quot;typische-vc6-problemchen&quot;&gt;Typische VC6 Problemchen&lt;/h3&gt;

&lt;p&gt;Über folgende Probleme bin ich schon mehrmals gestolpert:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;new&lt;/code&gt; wirft im Fehlerfall keine Exception sondern gibt einen NULL-Pointer 
zurück. Das kann man sogar durch einen angepassten &lt;code&gt;operator new&lt;/code&gt; fixen, 
aber hier streiten sich dann gerne die Libs, wer den Operator zuerst 
überladen darf.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;template&lt;/code&gt; Funktionen mit void-Return Value erzeugen Fehler.&lt;br /&gt;
Folgender Code kompiliert nicht:
    &lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;template&lt;/span&gt;&amp;lt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;R&lt;/span&gt;&amp;gt; R foo()
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; R();
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;}
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; main()
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;  foo&amp;lt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;&amp;gt;();
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
    &lt;/div&gt;

    &lt;p&gt;Nun gut, man könnte meinen, dass es auch wenig Sinn macht einen “void”
zurückgeben, aber spätestens seit dem C++03 Update und in MSVC 2003
wird dieser Code gültig. Man braucht ihn vor allem für Delegates oder
andere Formen von Methoden- oder Funktions-Dispatchern.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Variadic_macro&quot;&gt;Variadic Macros&lt;/a&gt; existieren nicht.&lt;br /&gt;
Ärgerlich, weil manche Debugging-Macros ähnlich wie &lt;code&gt;printf&lt;/code&gt; mehrere 
Argumente so aneinanderreihen.&lt;/li&gt;
  &lt;li&gt;Makros in Makros brauchen teils weitere Makros um zu funktionieren.&lt;br /&gt;
Ein Makro kann nicht ein anderes Parameter-freies Makro einbauen, nein,
man braucht ein drittes Makro, dem man das gewollte Makro als Parameter
übergibt, welches das Makro selbst wieder zurückgibt (bzw. dessen Auswertung).&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;char&lt;/code&gt; ist entweder zu &lt;code&gt;signed char&lt;/code&gt; oder zu &lt;code&gt;unsigned char&lt;/code&gt; identisch und 
kein eigener Typ.
Tatsächlich sind bei &lt;code&gt;template&lt;/code&gt; Instanzen die Typen &lt;code&gt;char&lt;/code&gt;, &lt;code&gt;signed char&lt;/code&gt; 
und &lt;code&gt;unsigend char&lt;/code&gt; insgesamt 3 unterschiedliche Typen. Nur nicht in VC6.
Da sind &lt;code&gt;char&lt;/code&gt; und &lt;code&gt;signed char&lt;/code&gt; identisch, außer man setzt eine 
Compileroption, die &lt;code&gt;char&lt;/code&gt; einem &lt;code&gt;unsigned char&lt;/code&gt; gleichsetzt.&lt;/li&gt;
  &lt;li&gt;Zwei Kopierkonstruktoren mit konstantem und nicht-konstantem Argument führen zu Fehlern.
Zugegeben, das ist in C++ generell seltsam, dass man die Kopierkonstruktoren
    &lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;type(type &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt;&amp;amp; src);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;type(type&amp;amp; src);
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
    &lt;/div&gt;
    &lt;p&gt;definieren kann. Welcher genommen wird, ist oft schwer nachvollziehbar, weil
sich der konstante auch um die nicht-konstanten Aufrufe kümmern darf.
VC6 erfindet aber bei einem &lt;code&gt;type(type&amp;amp; src);&lt;/code&gt; ohne den anderen einen 
selbstgestrickten &lt;code&gt;memcpy()&lt;/code&gt; basierten &lt;code&gt;type(type const&amp;amp; src);&lt;/code&gt; dazu,
und dann ist die Kacke meist am Dampfen.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code&gt;for&lt;/code&gt; Schleifen dürfen in C keine Typendeklarationen einführen.&lt;br /&gt;
Ein &lt;code&gt;for(int i = 0; ...)&lt;/code&gt; ist falsch, &lt;code&gt;int i;&lt;/code&gt; muss vor der Schleife stehen.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;long long&lt;/code&gt; existiert nicht, anstatt dessen haben wir &lt;code&gt;__int64&lt;/code&gt;&lt;br /&gt;
Das bereitet oft die meisten Schmerzen und eine Vielzahl an Libs beinhaltet
deshalb Codes wie:
    &lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#if&lt;/span&gt; defined(_MSC_VER)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;typedef&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;unsigned&lt;/span&gt; __int64        my_ui64_t;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;typedef&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;signed&lt;/span&gt; __int64                my_i64_t;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#else&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;typedef&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;unsigned&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;long&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;long&lt;/span&gt;        my_ui64_t;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;typedef&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;signed&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;long&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;long&lt;/span&gt;        my_i64_t;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#endif&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;… und sicher gibt es noch viel mehr, das mich entweder nicht betroffen haben, 
oder was ich schon verdrängt habe.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Aus C++ Sicht ist der VC6 heute immer noch der größte Alptraum aller Zeiten,
und das liegt an vielen Codes, die damals entstanden sind und unter neuen
Compilern Probleme bereiteten.&lt;br /&gt;
Deshalb wird er so gut wir gar nicht mehr offiziell unterstützt.&lt;/p&gt;

&lt;p&gt;Da das Projekt aber auf dem älteren C89 Standard aufsetzt und C++ nur einen
dünnen Layer darüber darstellt, möchte ich dennoch versuchen diesen
Dinosaurier am Leben zu erhalten.&lt;br /&gt;
Wenn ich einmal meine heutigen Codes in die Vergangenheit schicken kann,
sind diese vermutlich die einzigen, die damals kompilierbar gewesen wären.
Und irgendwie reizt mich dieser Gedanke.&lt;/p&gt;

&lt;p&gt;Wenn man also ein paar Makros und &lt;code&gt;typedef&lt;/code&gt;s einsetzt und brav alle Typen am
Beginn der Funktion deklariert, kann man dynamisch eingebundene 
Windows 10 - Features unter einem &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_98&quot;&gt;Windows 98&lt;/a&gt; 
mit MSVC6 kompilieren und am Ende in der Azur Cloud ausführen …&lt;br /&gt;
&lt;strong&gt;Na, das nenn’ ich mal eine Challenge!&lt;/strong&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>DLLExport und visibility default</title>
   <link href="https://www.opengate.at/blog/2020/05/dllexport/"/>
   <published>2020-05-01T13:00:00+02:00</published>
   <updated>2020-05-01T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2020/05/dllexport</id>
   <category term="devel" /><category term="projects" />
   <summary type="text">So, die Umstellung läuft und meine Finger dampfen.
In Zukunft bekommt das GATE Projekt die Fähigkeit, die Core-Libs dynamisch
zu erstellen und zu linken.

Und jetzt könnte ich mich grün und blau ärgern, dass ich erst nach dem 
Hinzufügen von etwa 600 Makros feststellte, dass sie an der falschen standen ….
</summary>
   <content type="html">&lt;p&gt;So, die Umstellung läuft und meine Finger dampfen.&lt;br /&gt;
In Zukunft bekommt das GATE Projekt die Fähigkeit, die Core-Libs dynamisch
zu erstellen und zu linken.&lt;/p&gt;

&lt;p&gt;Und jetzt könnte ich mich grün und blau ärgern, dass ich erst nach dem 
Hinzufügen von etwa 600 Makros feststellte, dass sie an der falschen standen ….
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;vorgeschichte&quot;&gt;Vorgeschichte&lt;/h3&gt;

&lt;p&gt;Das GATE wird für mich immer eine statische Bibliothek bleiben und das ist
auch gut so. Doch auf Grund seiner nun doch schon recht zahlreichen Funktionen
(alleine 600 in der Core-Lib - also ohne IO, System, usw.) kann man durchaus
überdenken, diese “Features” auch dynamisch von einer &lt;a href=&quot;https://de.wikipedia.org/wiki/Dynamic_Link_Library&quot;&gt;DLL/SO&lt;/a&gt; 
importierbar zu machen.&lt;/p&gt;

&lt;p&gt;Nun, dank &lt;a href=&quot;https://de.wikipedia.org/wiki/CMake&quot;&gt;CMake&lt;/a&gt; ist das alles kein 
Problem, man definiert die Option&lt;br /&gt;
&lt;code&gt;BUILD_SHARED_LIBS&lt;/code&gt; und entfernt bei&lt;br /&gt;
&lt;code&gt;add_library(my_lib_name STATIC ...)&lt;/code&gt;
einfach das &lt;code&gt;STATIC&lt;/code&gt;.&lt;br /&gt;
Denn wieder was gelernt: &lt;code&gt;BUILD_SHARED_LIBS&lt;/code&gt; fügt automatisch bei allen 
&lt;code&gt;add_library&lt;/code&gt; Funktionen ein &lt;code&gt;SHARED&lt;/code&gt; ein während ansonsten &lt;code&gt;STATIC&lt;/code&gt; als 
Standard angenommen wird.&lt;/p&gt;

&lt;p&gt;Aber die eigentlich interessanteste Frage des Tages lautet:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Steht jetzt &lt;code&gt;__declspec(dllexport)&lt;/code&gt; vor der Funktionsdeklaration oder
zwischen Return-Value und Namen?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Die einfache Antwort: It depends … &lt;code&gt;also mal so und mal so.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Nachdem ich selbst schon länger keine DLLs mehr erstellt habe, hab ich 
einfach in den &lt;a href=&quot;https://de.wikipedia.org/wiki/Zlib&quot;&gt;ZLIB&lt;/a&gt; Source hineingeblickt
und dort die zweite Variante gefunden … bzw. ich dachte, ich hätte die
zweite Variante gesehen.&lt;/p&gt;

&lt;p&gt;Also wurden brav Macros definiert, die entweder auf &lt;code&gt;dllexport&lt;/code&gt; oder 
&lt;code&gt;dllimport&lt;/code&gt; ausgelegt waren und anschließend alle Funktionen der GATE Corelib
auf die Signatur:&lt;br /&gt;
&lt;code&gt;ret_type_t GATE_CORE_API some_function(arg_t arg, ...);&lt;/code&gt;
umgestellt.&lt;/p&gt;

&lt;p&gt;Ein kurzer Test nach den ersten paar Funktionen verlief natürlich mit Erfolg,
wie sich später herausstellte war er falsch konfiguriert.&lt;/p&gt;

&lt;p&gt;So, 600 Funktionen umgestellt und da kam der hier hunderte Male:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;code&gt;error C2059: syntax error: &apos;type&apos;&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;portable-lösung&quot;&gt;Portable Lösung&lt;/h3&gt;

&lt;p&gt;Wie es aussieht, sind die Toleranzen für C und C++ Projekte im 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_C%2B%2B&quot;&gt;MSVC&lt;/a&gt; etwas unterschiedlich. 
Während man bei C++ Übersetzungseinheiten durchaus&lt;br /&gt;
&lt;code&gt;ret_type_t GATE_CORE_API some_function(arg_t arg, ...);&lt;/code&gt;&lt;br /&gt;
nutzen darf, sollte man auch laut Empfehlung auf der MSDN&lt;br /&gt;
&lt;code&gt;GATE_CORE_API ret_type_t some_function(arg_t arg, ...);&lt;/code&gt;&lt;br /&gt;
benützen.&lt;br /&gt;
Das macht, wenn man darüber nachdenkt, auch Sinn.&lt;/p&gt;

&lt;p&gt;Und wie sieht es beim &lt;a href=&quot;https://de.wikipedia.org/wiki/GNU_Compiler_Collection&quot;&gt;GCC&lt;/a&gt;
unter &lt;a href=&quot;https://de.wikipedia.org/wiki/Portable_Operating_System_Interface&quot;&gt;POSIX&lt;/a&gt; 
aus?&lt;/p&gt;

&lt;p&gt;Ein &lt;code&gt;__declspec(dllexport)&lt;/code&gt; entspräche hier einem 
&lt;code&gt;__attribute__((visibility (&quot;default&quot;)))&lt;/code&gt;, wenn man mit die Übersetzung mit 
dem Parameter &lt;code&gt;-fvisibility=hidden&lt;/code&gt; ausführt. Ohne die Default-Visibility 
&lt;code&gt;hidden&lt;/code&gt; würde der GCC alles exportieren was kein &lt;code&gt;static&lt;/code&gt; davor hat, 
und damit auch einiges was privat bleiben sollte 
(z.B. nicht statische Klassenmethoden).&lt;/p&gt;

&lt;p&gt;Der &lt;code&gt;dllimport&lt;/code&gt; hat in dem Scenario kein Äquivalent und wird durch ein leeres
Makro auf Linux portiert.&lt;/p&gt;

&lt;p&gt;Und obwohl die GCC Dokumentation zur Variante&lt;br /&gt;
&lt;code&gt;ret_type_t GATE_CORE_API some_function(arg_t arg, ...);&lt;/code&gt;&lt;br /&gt;
rät, so akzeptiert der Compiler auch die Alternative.&lt;/p&gt;

&lt;p&gt;Nun gut, die finale Lösung heißt also:&lt;br /&gt;
&lt;code&gt;GATE_CORE_API ret_type_t some_function(arg_t arg, ...);&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Und so habe ich die Projekt Konvertierung auch weiter durchgeführt.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://anadoxin.org/blog/control-over-symbol-exports-in-gcc.html&quot;&gt;HIER&lt;/a&gt;
gibt es übrigens noch eine tolle Zusammenfassung zum Thema GCC-Visibility.&lt;/p&gt;

&lt;h3 id=&quot;und-die-perfekte-lösung&quot;&gt;Und die perfekte Lösung?&lt;/h3&gt;

&lt;p&gt;Um wieder zum Anfang zurück zu kommen: Eine annähernd perfekte Lösung
setzt die &lt;code&gt;ZLIB&lt;/code&gt; ein.&lt;/p&gt;

&lt;p&gt;Sie nutzt nämlich zwei Makros, eines vorne und eines in der Mitte:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;ZEXTERN &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt; * ZEXPORT zlibVersion OF((&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;));
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Und hier kam mein Irrtum zustande, denn ich dachte hinter &lt;code&gt;ZEXPORT&lt;/code&gt;
verbirgt sich der &lt;code&gt;dllexport&lt;/code&gt; und tatsächlich war diese Variante für 
das Betriebssystem BEOS mal gültig, doch bei den MSVC Zweigen sieht 
man deutlich, dass in Wahrheit &lt;code&gt;ZEXTERN&lt;/code&gt; den Export übernimmt und 
&lt;code&gt;ZEXPORT&lt;/code&gt; leer bleibt.&lt;/p&gt;

&lt;p&gt;Ich habe wieder was gelernt:&lt;br /&gt;
Unsere Vielzahl an Compilern hat offenbar eine Vielzahl an Möglichkeiten
geschaffen Export-Schlüsselworte einzusetzen. Da braucht man wohl ein
paar Optionen mehr, damit man jede erdenkliche Spielerei abfangen kann.&lt;/p&gt;

&lt;p&gt;Wie auch immer … für meine Zwecke reicht mir meine Erkenntnis.
Und nachdem dynamische Libs keine hohe Priorität haben, kann ich
das Thema vorerst wieder auf Eis legen.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Wie mich die Firma überwacht...</title>
   <link href="https://www.opengate.at/blog/2020/04/surveillance/"/>
   <published>2020-04-25T13:00:00+02:00</published>
   <updated>2020-04-25T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2020/04/surveillance</id>
   <category term="general" /><category term="software" />
   <summary type="text">Es haben alle immer Angst vor “dem Staat” und spinnen dann herum, sie würden
rund um die Uhr überwacht …
OK, da gibt es schon ein paar Kleinigkeiten … aber:

Gefährlicher wird es, wenn man in “private” Unternehmen hineinblickt.

Denn dort heißt es oft: Big boss is watching you.
</summary>
   <content type="html">&lt;p&gt;Es haben alle immer Angst vor “dem Staat” und spinnen dann herum, sie würden
rund um die Uhr überwacht …&lt;br /&gt;
OK, da gibt es schon ein paar Kleinigkeiten … aber:&lt;/p&gt;

&lt;p&gt;Gefährlicher wird es, wenn man in “private” Unternehmen hineinblickt.&lt;/p&gt;

&lt;p&gt;Denn dort heißt es oft: &lt;em&gt;Big boss is watching you.&lt;/em&gt;
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Diese Woche war es notwendig einen Test auf einem “frischen” System zu machen.
Das tat ich durch eine Neuinstallation von Windows in einer VM.&lt;/p&gt;

&lt;p&gt;Und als das erledigt war und ich in dieser &lt;a href=&quot;https://de.wikipedia.org/wiki/Virtuelle_Maschine&quot;&gt;VM&lt;/a&gt; 
den Browser öffnete um noch &lt;a href=&quot;https://de.wikipedia.org/wiki/7-Zip&quot;&gt;7Zip&lt;/a&gt; 
herunterzuladen, wurde dies verweigert.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Von &lt;code&gt;google.com&lt;/code&gt; wurde ein ungültiges Zertifikat heruntergeladen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;… und da fiel es mir wieder ein: Ja, die Firma nutzt &lt;a href=&quot;https://de.wikipedia.org/wiki/Proxy_(Rechnernetz)&quot;&gt;Proxy&lt;/a&gt;
Dienste, die &lt;a href=&quot;https://de.wikipedia.org/wiki/Digitales_Zertifikat&quot;&gt;Zertifikate&lt;/a&gt; 
fälschen um den Datenverkehr mitlesen zu können.&lt;br /&gt;
Bei den firmeneigenen Systemen, die alle am Active Directory hängen werden 
diese Zertifikate als vertrauenswürdig deklariert … aber meine jungfräuliche
Testinstallation wusste nicht, dass sie hier “ein Auge zudrücken” sollte.&lt;/p&gt;

&lt;p&gt;Also so viel zum Thema “Zertifikate machen das Internet sicher”.&lt;br /&gt;
&lt;em&gt;Nein! Sie machen es bestenfalls etwas sicherer, garantieren aber nichts.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Wem ich persönlich “vertrauen” kann und wem nicht, wir mir durch meine 
Erziehung in frühen Jahren vermittelt … oder später, wenn ich dann einfach
irgend jemanden als “vertrauenswürdig” einschätze und einfach so drauf los
vertraue.&lt;/p&gt;

&lt;p&gt;Aber wenn meine Informationen zu diesem Zeitpunkt schon manipuliert werden,
wie z.B. die Updates für meine Liste an vertrauten Zertifikaten, dann sehe
ich die Welt schon durch jene Brille, die mir nur das zeigt, was andere
wollen, das ich sehe.&lt;/p&gt;

&lt;p&gt;Das Schlimme daran ist, dass ich als Administrator diese Schritte in den
Firmen durchaus nachvollziehen kann.&lt;br /&gt;
Vielen Menschen machen Blödsinn und dann haftet erst einmal das Unternehmen, 
wenn sich jemand Kinderpornos auf seinen Rechner herunterlädt.&lt;/p&gt;

&lt;p&gt;Früher war über HTTP ja ohnehin alles frei einschaubar womit zahlreiche
Schurken enttarnt und zur Rede gestellt werden konnten. Doch mit der
Einführung von HTTPS blieb der Datenaustausch etwas “geheimer”.
Man sieht zwar, welche IP angesteuert wurde, doch in Zeiten von Cloud-Clustern,
Load-Balancing und &lt;a href=&quot;https://de.wikipedia.org/wiki/Content_Delivery_Network&quot;&gt;Content-Delivery-Networks&lt;/a&gt;
weiß man als Admin nicht, welche Daten über die Leitungen fließen, weil alles
vom gleichen IP-Bereich stammt.&lt;/p&gt;

&lt;p&gt;Würde man Zertifikate einfach “dumm” selbst erstellen und als “Mittelsmann”
(man in the middle) alles abhören, bekäme der User vom Browser eine Warnung,
dass Zertifikat und Ziel nicht zusammenpassen.&lt;/p&gt;

&lt;p&gt;Hat man aber die Zertifikatsverwaltung unter Kontrolle, denk man als User,
alles wäre abhörsicher, und dennoch kann alles am Proxy oder Gateway dekodiert
und inspiziert werden.&lt;/p&gt;

&lt;p&gt;Nun, es stört mich nicht, wenn die Firma sieht, welche News ich zwischen den 
Kompiliervorgängen durchlese, aber wenn ich dann auf eine private E-Mail meines
Arztes reagiere und hierfür im Webmail mein Passwort eintippe … ja dann 
wird es um so wichtiger, dass das Unternehmen “meine Daten” schützt.&lt;/p&gt;

&lt;p&gt;Und in der Tat hatte ich vor 15 Jahren als Praktikant in einer IT Abteilung 
Zugriffsmöglichkeiten, die jeden Datenschutzbeauftragten hätten erzittern
lassen müssen …&lt;br /&gt;
Wer garantiert mir also, dass nicht auch heute ein bevollmächtigter
Praktikant im Serverraum sitzt und meine Passwörter abschreibt um am Abend 
dann PayPal und Bankverbindungen damit ausprobiert?&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;In diesem Sinne sollte jeder, der nicht sein eigenes privates Internet nutzt,
darüber nachdenken, welche Seiten er über fremde Netze und fremde Rechner 
aufruft. Die Werbeaussage “Mit HTTPS ist alles absolut sicher” ist 
gleichzusetzen mit einem “Das beste Produkt überhaupt” aus der
Waschmittelwerbung.&lt;/p&gt;

&lt;p&gt;Ich für meinen Teil bin absolut sicher, dass kein Staat so viele sensible 
Daten über mich gesammelt hat, wie die Firmen für die ich bisher gearbeitet
habe.&lt;/p&gt;

&lt;p&gt;Ob das gut oder schlecht ist, wage ich aber nicht zu beurteilen.
Ich “vertraue” vorerst darauf, dass sie mir (bewusst) nichts Böses antun wollen.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Luft Ionisator atomisieren</title>
   <link href="https://www.opengate.at/blog/2020/04/air-ionizer/"/>
   <published>2020-04-24T13:00:00+02:00</published>
   <updated>2020-04-24T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2020/04/air-ionizer</id>
   <category term="hardware" />
   <summary type="text">Seit über einem Jahr läuft mein “IonizAIR” 
von P3 International und reichert die Luft mit Ozon an um sie zu desinfizieren
und organische Duftstoffe (auch Gestank genannt) aufzulösen.

Und typisch, gerade jetzt wo COVID-19 
täglich für den Tod einer meiner Nerven verantwortlich ist, schaltet das Gerät
einfach auf “rot” und tut nichts mehr.
</summary>
   <content type="html">&lt;p&gt;Seit über einem Jahr läuft mein “&lt;a href=&quot;https://en.wikipedia.org/wiki/Air_ioniser&quot;&gt;IonizAIR&lt;/a&gt;” 
von P3 International und reichert die Luft mit Ozon an um sie zu desinfizieren
und organische Duftstoffe (auch Gestank genannt) aufzulösen.&lt;/p&gt;

&lt;p&gt;Und typisch, gerade jetzt wo &lt;a href=&quot;https://de.wikipedia.org/wiki/COVID-19&quot;&gt;COVID-19&lt;/a&gt; 
täglich für den Tod einer meiner Nerven verantwortlich ist, schaltet das Gerät
einfach auf “rot” und tut nichts mehr.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;ionisierung-der-luft&quot;&gt;Ionisierung der Luft&lt;/h3&gt;

&lt;p&gt;Nach Gewittern und in Bergen soll die Luft leicht negativ geladen sein, was
wir als angenehm empfinden sollen, und im Gegensatz dazu produzieren unsere 
elektronischen Geräte positiv geladenen Staub, der ungesund sein soll.&lt;/p&gt;

&lt;p&gt;Die Lösung: Man jagt ein paar tausend Volt durch sehr nahe Metallplatten,
wo dann an ihren Kanten die lustigerweise so heißende “Korona-Entladung”
stattfindet und die Luft zum elektrischen Medium wird.
(Das hat natürlich nichts mit unserem Todes-Virus COVID-19 zu tun!)&lt;/p&gt;

&lt;p&gt;Dabei sollen geladene Luftteilchen und Ozon entstehen, die die
oben genannten “positiven” Eigenschaften haben, obwohl sie negativ geladen
sind.&lt;/p&gt;

&lt;p&gt;Solche Ionisierer kann man je nach Raumgröße für 20 € (USB Teil fürs Auto)
oder wie in meinem Fall für 65 Euro für eine kleine Wohnung kaufen.&lt;/p&gt;

&lt;p&gt;Und genau dieses Teil tut nicht mehr …&lt;br /&gt;
Man schaltet es ein, es leuchtet kurz grün um in weniger als einer Sekunde
wieder auf rot zu schalten, worauf man eigentlich die Ladungsplatten reinigen
sollte … doch das half nicht.&lt;/p&gt;

&lt;p&gt;Warum nur?&lt;/p&gt;

&lt;h3 id=&quot;1000-volt-tun-weh&quot;&gt;1000 Volt tun weh!&lt;/h3&gt;

&lt;p&gt;Man hätte es sich denken können, aber hier gleich als Warnung:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Das Gerät 6 Stunden vom Strom zu nehmen reicht nicht aus um die
Kondensatoren vollständig zu entladen. Als ich beim Öffnen an die Platte 
kam, fuhr mir die Restladung durch den Körper.&lt;br /&gt;
Es ist nicht tödlich weil kein Strom dahintersteht, aber die Pratze
tat mir trotzdem etwas weh!&lt;br /&gt;
Also ja nicht an die Teile fassen, wenn das Gerät eingeschaltet ist!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ich hatte die Hoffnung, dass ich dort einen “kleinen” defekten Kondensator
vorfinde, diesen auslöte, einen neuen einsetze und alles wieder perfekt
läuft.&lt;/p&gt;

&lt;p&gt;So war es aber nicht.&lt;/p&gt;

&lt;h3 id=&quot;experimente&quot;&gt;Experimente&lt;/h3&gt;

&lt;p&gt;Unter dem Fuß des Geräts saß eine Platine mit wenigen Bauteilen, die die
Strompulse erzeugen und die Spannungen messen sollte.
Dort war nichts offensichtlich Defektes, was ich hätte ersetzen können 
und die “großen” Kondensatoren und Spulen für die Hochspannung waren
ein Stockwerk darüber mit Kleber übergossen. Sie wirkten aber äußerlich
ebenso nicht defekt.&lt;/p&gt;

&lt;p&gt;Nach meinem “Schlag” beim Öffnen wollte ich auf keinen Fall mit dem Gerät
herumexperimentieren, wenn es lief.
Dumm gelaufen also …&lt;/p&gt;

&lt;p&gt;Also wieder alles zusammengeschraubt.&lt;/p&gt;

&lt;p&gt;Dann nahm ich mir die Ladungsplatten vor, die auf einer leicht entfernbaren
Kartusche angebracht waren.&lt;br /&gt;
Man sollte diese auch laut Anleitung einfach mit Wasser waschen können, 
weil diese im Laufe der Zeit Staub ansetzen.&lt;/p&gt;

&lt;p&gt;Also bog ich die Metallzähne, zwischen denen die Koronaentladung erzeugt
wird, etwas auseinander und dann wieder auf einander zu.&lt;br /&gt;
Ergebnis: Es wird auch nicht besser.&lt;/p&gt;

&lt;h3 id=&quot;mit-mehr-nein-weniger-power&quot;&gt;Mit mehr, nein, weniger Power!&lt;/h3&gt;

&lt;p&gt;Dann dachte ich mir: “Ist eh schon egal, das Ding ist tot!”,
und schloss es ans Labornetzteil an.&lt;/p&gt;

&lt;p&gt;Und weil &lt;a href=&quot;https://de.wikipedia.org/wiki/H%C3%B6r_mal,_wer_da_h%C3%A4mmert#Tim_Taylor&quot;&gt;Tim Taylor&lt;/a&gt;
gerne sagte &lt;em&gt;“Mehr Power”&lt;/em&gt;, setzte ich die zugeführte Betriebsspannung, 
die mit dem Sollwert 12 Volt angegeben war, mal auf 14 Volt hoch.&lt;br /&gt;
… Gleiches Ergebnis.&lt;/p&gt;

&lt;p&gt;Doch beim Herunterdrehen sprang das Teil plötzlich an und lief 
ein paar Sekunden.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;OK … kann das bedeuten, dass “weniger Power” die Lösung ist?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ja, so scheint es zu sein.&lt;/p&gt;

&lt;p&gt;Betreibe ich mein Gerät mit etwa 10.5 Volt läuft es stabil.
Ab spätestens 11.5 Volt schaltet das Gerät auf “rot” und hört
auf zu arbeiten.&lt;/p&gt;

&lt;p&gt;Ich vermute mal, dass die innere Spannung gemessen wird und wenn 
diese nicht “abgeführt” wird, schaltet sich das Teil aus.
Vielleicht ist ein Bauteil halb-defekt oder hat seine Spezifikation 
verlassen und reagiert nun auf die “volle” Spannung mit Abschaltung.&lt;/p&gt;

&lt;p&gt;Mit geringerer zugelieferter Spannung wird vermutlich auch weniger Luft
ionisiert, aber es wird immerhin ionisiert. Das kann man am Luftzug
spüren und riechen und im Dunkeln an den kleinen Entladungsblitzen
auch sehen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ich hatte noch ein kleines DIY-Kleinnetzteil mit bis zu 14 Volt für
ein paar Hundert Milliampere übrig. Wenn man das voll aufdreht und 
an den Ionisierer anschließt, brechen die 14 Volt auf etwa 9 zusammen,
können das Gerät aber gerade so an der Grenze betreiben.&lt;/p&gt;

&lt;p&gt;Na gut: Problem gelöst.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/air-ionizer.jpg&quot; alt=&quot;DIY-Ionizer-Power-Supply&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Einzig die dort verbaute Anzeige und die LEDs darin verbraten zusätzlich 
noch völlig unnötig Strom &lt;br /&gt;
… aber hey … sagen wir einfach, es ist nebenbei auch noch eine Lichtorgel.&lt;/p&gt;

&lt;p&gt;Somit wurde wieder ein Teil vor dem Müll gerettet und ich bin zufrieden.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Plattform-weite Sperren</title>
   <link href="https://www.opengate.at/blog/2020/04/platform-lock/"/>
   <published>2020-04-19T13:00:00+02:00</published>
   <updated>2020-04-19T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2020/04/platform-lock</id>
   <category term="devel" />
   <summary type="text">Irgendwann zwischen den Jahren 2002 und 2008 - so glaube ich mich zu erinnern -
meldeten alle großen OS und 
Kernel Hersteller, sie hätten das Global-Lock Problem gelöst.

Dieser “globale Mutex”, der das gesamte
System sperrt bis eine kritische Aufgabe erledigt ist, war offenbar seit 
langem tief in den Kernelquellen eingedrungen und konnte nur durch 
Designabänderungen an vielen Stellen wieder entfernt werden.

Tja … und ich ärgere mich, dass ich genau so einen Dinosaurier jetzt
bewusst wieder im User-Space 
einbauen muss, damit er Steinzeit-Trolle bekämpft.
</summary>
   <content type="html">&lt;p&gt;Irgendwann zwischen den Jahren 2002 und 2008 - so glaube ich mich zu erinnern -
meldeten alle großen &lt;a href=&quot;https://de.wikipedia.org/wiki/Betriebssystem&quot;&gt;OS&lt;/a&gt; und 
Kernel Hersteller, sie hätten das Global-Lock Problem gelöst.&lt;/p&gt;

&lt;p&gt;Dieser “globale &lt;a href=&quot;https://de.wikipedia.org/wiki/Mutex&quot;&gt;Mutex&lt;/a&gt;”, der das gesamte
System sperrt bis eine kritische Aufgabe erledigt ist, war offenbar seit 
langem tief in den Kernelquellen eingedrungen und konnte nur durch 
Designabänderungen an vielen Stellen wieder entfernt werden.&lt;/p&gt;

&lt;p&gt;Tja … und ich ärgere mich, dass ich genau so einen Dinosaurier jetzt
bewusst wieder im &lt;a href=&quot;https://en.wikipedia.org/wiki/User_space&quot;&gt;User-Space&lt;/a&gt; 
einbauen muss, damit er Steinzeit-Trolle bekämpft.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Die beiden Funktionen &lt;code&gt;gate_platform_lock()&lt;/code&gt; und &lt;code&gt;gate_platform_unlock()&lt;/code&gt;
bedienen ab sofort einen globalen Mutex im GATE Framework.&lt;br /&gt;
Es widert mich zwar an, zu solchen Konstrukten greifen zu müssen, doch
dank schlechter Plattformschnittstellen blieb mir keine Alternative.&lt;/p&gt;

&lt;p&gt;Das Problem sind klassische &lt;a href=&quot;https://de.wikipedia.org/wiki/C_(Programmiersprache)&quot;&gt;C APIs&lt;/a&gt; 
aus den 80er Jahren, die ihre Ergebnisse in globale Variablen schreiben und 
per Definition nicht thread-safe sind.&lt;/p&gt;

&lt;p&gt;Dass jetzt einige (wenige) dieser Funktionen inzwischen über diverse Tricks
wie “Thread-local-storage” oder ähnliche Technologien multithreading-tauglich
sind, mag ja schön sein, garantiert ist das jedoch nicht.&lt;/p&gt;

&lt;p&gt;Und wenn man zwischen unterschiedlichen &lt;a href=&quot;https://de.wikipedia.org/wiki/Portable_Operating_System_Interface&quot;&gt;POSIX&lt;/a&gt;
Plattformen wechselt, dann stellt man leider fest, dass die neueren auf 
&lt;code&gt;_r&lt;/code&gt; -endenden Funktionen nicht überall verfügbar sind.&lt;/p&gt;

&lt;p&gt;Die einzig wirklich portable Lösung ist also die Funktion mit ihren globalen 
Variablen nur innerhalb eines gesperrten Mutex auszuführen und ihre 
Ergebnisse herauszukopieren bevor man diese Sperre wieder aufhebt.&lt;/p&gt;

&lt;p&gt;Die typischen Verdächtigen heißen beispielsweise:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Environment Variablen lesen und schreiben&lt;/li&gt;
  &lt;li&gt;Account Informationen auslesen&lt;/li&gt;
  &lt;li&gt;Globale Prozess-Flags&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;C Funktionen wie &lt;code&gt;strtok&lt;/code&gt; erwähne ich gleich gar nicht, weil sie ohnehin
durch thread-sichere Varianten im GATE Framework ersetzt werden.&lt;/p&gt;

&lt;p&gt;Am effizientesten wäre es natürlich, für jede Funktion einen eigenen Mutex
zu nutzen, doch deren Initialisierung ist “etwas” komplizierter und daher
reduziere ich dies auf eine einzige globale Sperre.&lt;br /&gt;
Und das natürlich in der Hoffnung, dass die geschützten Systemfunktionen
entsprechend selten aufgerufen werden und daher keinen Performanceverlust
generieren.&lt;/p&gt;

&lt;h3 id=&quot;problemfall-global-initialisierung&quot;&gt;Problemfall: Global Initialisierung&lt;/h3&gt;

&lt;p&gt;In C haben wir (offiziell) keine globalen Konstruktoren … und selbst wenn
dann wäre deren Aufrufreihenfolge nicht garantiert.&lt;br /&gt;
Wir können nur flache Datenstrukturen mit Zahlen initialisieren.
Aber ein Mutex braucht sowohl unter Windows als auch unter POSIX einen 
Funktionsaufruf zur Initialisierung.&lt;/p&gt;

&lt;p&gt;Wir könnten uns (was mehrere Libs tun) auf eine bestimmte &lt;code&gt;init()&lt;/code&gt; Funktion
einigen, die (durch den Entwickler explizit eingebaut) vor allen anderen 
aufgerufen werden muss.
Doch wer garantiert, das dies geschieht?&lt;/p&gt;

&lt;p&gt;Aus diesem Grund prüft der Aufruf von &lt;code&gt;gate_platform_lock()&lt;/code&gt;, ob die 
Initialisierung schon stattgefunden hat und wenn nicht, so wird dies
(genau einmal) durchgeführt.&lt;/p&gt;

&lt;p&gt;Also, man braucht:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Die Mutex-Instanz selbst als globale Variable&lt;/li&gt;
  &lt;li&gt;Ein globales &lt;code&gt;mutex-ready&lt;/code&gt; Flag, das uns sagt, ob der Mutex schon nutzbar ist&lt;/li&gt;
  &lt;li&gt;Einen globalen Spinlock, der die Initialisierung gegen mehrfache parallele
Aufrufe absichert.&lt;/li&gt;
  &lt;li&gt;Ein globales &lt;code&gt;init-done&lt;/code&gt; Flag, welches innerhalb des Mutex nur dem ersten
Aufrufer gestattet, den Systemaufruf zur Initialisierung abzusetzen.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Das ganze sieht dann vereinfacht etwa so aus:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;static&lt;/span&gt; system_mutex_t global_mutex;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt; global_mutex_init()
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;static&lt;/span&gt; atomic_bool_t global_mutex_ready = &lt;span style=&quot;color:#069&quot;&gt;false&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;static&lt;/span&gt; atomic_bool_t global_mutex_init_done = &lt;span style=&quot;color:#069&quot;&gt;false&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;static&lt;/span&gt; spinlock_t spinner = spinlock_init_value;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;  
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt;(!atomic_bool_get(&amp;amp;global_mutex_ready))
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;    spinlock_begin(&amp;amp;spinner); &lt;span style=&quot;color:#777&quot;&gt;/* block parallel execution */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt;(!atomic_bool_get(&amp;amp;global_mutex_init_done))
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;    { &lt;span style=&quot;color:#777&quot;&gt;/* only the first thread will initialize the mutex */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;      system_mutex_init(&amp;amp;global_mutex);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;          atomic_bool_set(&amp;amp;global_mutex_init_done, &lt;span style=&quot;color:#069&quot;&gt;true&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;          atomic_bool_set(&amp;amp;global_mutex_ready, &lt;span style=&quot;color:#069&quot;&gt;true&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;    }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;    spinlock_end(&amp;amp;spinner);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;  }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;}
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n21&quot; name=&quot;n21&quot;&gt;21&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt; global_mutex_lock()   
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n22&quot; name=&quot;n22&quot;&gt;22&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n23&quot; name=&quot;n23&quot;&gt;23&lt;/a&gt;&lt;/span&gt;  global_mutex_init();
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n24&quot; name=&quot;n24&quot;&gt;24&lt;/a&gt;&lt;/span&gt;  system_mutex_lock(&amp;amp;global_mutex);  
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n25&quot; name=&quot;n25&quot;&gt;25&lt;/a&gt;&lt;/span&gt;}
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n26&quot; name=&quot;n26&quot;&gt;26&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt; global_mutex_unlock() 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n27&quot; name=&quot;n27&quot;&gt;27&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n28&quot; name=&quot;n28&quot;&gt;28&lt;/a&gt;&lt;/span&gt;  system_mutex_unlock(&amp;amp;global_mutex);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n29&quot; name=&quot;n29&quot;&gt;29&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Jetzt das ganze noch mit Fehlerbehandlung ausstatten und wir haben eine 
thread-sichere Lösung geschaffen, die nach der erstmaligen Initialisierung 
nur noch ganz wenig Overhead produziert und zwar beim Prüfen &lt;code&gt;global_mutex_ready&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Wer es natürlich ganz perfekt machen will, der schreibt zwei Funktionen und
einen globalen Funktionszeigern.&lt;br /&gt;
Der Funktionszeiger verweist am Anfang auf die &lt;code&gt;init&lt;/code&gt;-Routine welche nach dem
ersten Aufruf den Funktionszeiger auf eine zweite Funktion umbiegt, wo nicht
mehr initialisiert wird.&lt;/p&gt;

&lt;p&gt;Wie auch immer, ich hasse es, dass gerade wichtige Systemfunktionen im Jahr
2020 immer noch “so blöd” gebaut sind, dass man globale Sperren um sie
errichten muss um zu garantieren, dass nichts Schlimmes passiert.&lt;/p&gt;

&lt;p&gt;Das üble ist, dass viele Bibliotheken das nicht tun und von der Hoffnung leben,
dass solche Initialisierungen nie von zwei Threads gleichzeitig angestiftet
werden.&lt;br /&gt;
Und ja, ich gebe zu, dass das in verdammt vielen Fällen “eh immer” 
funktioniert.&lt;/p&gt;

&lt;p&gt;… und dann kommt eben der 10000ste Aufruf und die EXE crashed, und keiner
weiß was passiert ist und es werden Hexen, das Wetter oder Politiker 
verdächtigt.&lt;/p&gt;

&lt;p&gt;Aber nein … es sind immer Programmierfehler!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Kein shared_ptr?</title>
   <link href="https://www.opengate.at/blog/2020/04/shared-ptr/"/>
   <published>2020-04-18T13:00:00+02:00</published>
   <updated>2020-04-18T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2020/04/shared-ptr</id>
   <category term="devel" /><category term="projects" />
   <summary type="text">Bisher gab es im GATE Projekt keine Äquivalent zum std::shared_ptr.
Der Grund dafür war einfach: Alle C-Objekte implementieren ihr eigenes
intrusive Reference-Counting 
und die C++ Objekte sind daher nur leichtgewichtige Wrapper.

Damit sind die meisten GATE C++ Objekte bereits eine typisierte Abart 
von std::shared_ptr.

Doch ab nun ist alles anders …
</summary>
   <content type="html">&lt;p&gt;Bisher gab es im GATE Projekt keine Äquivalent zum &lt;code&gt;std::shared_ptr&lt;/code&gt;.
Der Grund dafür war einfach: Alle C-Objekte implementieren ihr eigenes
&lt;em&gt;intrusive &lt;a href=&quot;https://de.wikipedia.org/wiki/Referenzz%C3%A4hlung&quot;&gt;Reference-Counting&lt;/a&gt;&lt;/em&gt; 
und die C++ Objekte sind daher nur leichtgewichtige Wrapper.&lt;/p&gt;

&lt;p&gt;Damit sind die meisten GATE C++ Objekte bereits eine typisierte Abart 
von &lt;code&gt;std::shared_ptr&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Doch ab nun ist alles anders …
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Eine der interessantesten Fähigkeiten von &lt;a href=&quot;https://de.wikipedia.org/wiki/Intelligenter_Zeiger&quot;&gt;Smart-Pointern&lt;/a&gt;
wie &lt;code&gt;std::shared_ptr&lt;/code&gt; ist es Objekte ohne Referenzzählung durch eben eine 
solche zu “erweitern”. Genau genommen wird ein Zählerobjekt geschaffen, 
das einen Pointer zum Zielobjekt hat.&lt;/p&gt;

&lt;p&gt;Wir sprechen hier somit vom &lt;em&gt;non-intrusive reference counting&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Schnittstellen-technisch sind diese Konstrukte also eine Art von Hülle um
die eigentlichen Objekte, die auf diese Weise neue Features hinzufügen.&lt;/p&gt;

&lt;p&gt;Mit der neuen C-Objekt Klasse der &lt;code&gt;gate_wrapper_t*&lt;/code&gt; existiert nun auch
im GATE Framework eine Struktur, die beliebige Objekt “aufnehmen” und eine
Speicherverwaltung für diese bereitstellen kann.&lt;/p&gt;

&lt;p&gt;Und auf der C++ Seite übernimmt das Template &lt;code&gt;gate::Wrapper&amp;lt;T&amp;gt;&lt;/code&gt; die “schönere”
Repräsentation dieses Features.&lt;/p&gt;

&lt;h3 id=&quot;make_shared-nach-c-portieren&quot;&gt;make_shared nach C portieren&lt;/h3&gt;

&lt;p&gt;Die noch wichtigere Eigenschaft von &lt;code&gt;std::shared_ptr&lt;/code&gt; ist jedoch die Fähigkeit,
das Datenobjekt und die Referenzzählung in einen Speicherblock zu packen,
und diese Aufgabe übernimmt für gewöhnlich die Funktion &lt;code&gt;std::make_shared&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Wenn man mit dem “unschönen” Code&lt;/p&gt;
&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;std::shared_ptr&amp;lt;T&amp;gt; my_ptr(&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;new&lt;/span&gt; T);
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;arbeitet, generiert man zwei Probleme:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;code&gt;new T&lt;/code&gt; generiert ein Speicherfragment und der Konstruktor von 
&lt;code&gt;std::shared_ptr&lt;/code&gt; erzeugt ein weiteres, die mit einem Pointer 
aneinander gekettet werden.&lt;br /&gt;
Problem: Speicherfragmentierung&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;new T&lt;/code&gt; könnte gut gehen, aber dem &lt;code&gt;std::shared_ptr&lt;/code&gt; könnte der freie
Speicher ausgehen. Es fliegt eine Exception und schon wäre das vorhergehende
&lt;code&gt;new T&lt;/code&gt; zu einem unauflösbaren Memory-Leak geworden.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;code&gt;make_shared&lt;/code&gt; Erzeugt aber einen übergroßen Puffer in &lt;code&gt;shared_ptr&lt;/code&gt; und 
konstruiert eine &lt;code&gt;T&lt;/code&gt; Instanz in diesen Puffer hinein. Damit liegen beide 
Objekte hintereinander in einem Speicherblock und reduzieren die 
Fragmentierung. Und egal an welcher Stelle eine Exception fliegt, es wird 
alles sauber aufgeräumt.&lt;/p&gt;

&lt;p&gt;Das gleiche Konzept ist auch mit &lt;code&gt;gate_wrapper_t&lt;/code&gt; möglich, doch nachdem wir 
hier tief in der C Welt stecken, bedarf es der Speicherung von 
Funktionszeigern zu den entsprechenden Kon- und Destruktoren.&lt;/p&gt;

&lt;p&gt;Der C-Teil kann nur flachen Speicher bereitstellen und diesen wieder freigeben.
Daher muss sich der C++-Teil darum kümmern das finale Objekt auf den Speicher
zu konstruieren. … nun gut, das geht beim Erstellen des Objektes in einem
Schritt und findet alles auf der C++ Seite statt.&lt;/p&gt;

&lt;p&gt;Doch die Löschung findet im C-Teil statt und somit muss der C++ Teil schon
beim Erzeugen des Objektes eine Destruktor-Funktion miterstellen und diese
dem C-Teil übergeben, damit sie dieser bei der finalen Löschung aufrufen kann.&lt;/p&gt;

&lt;p&gt;Ein Vorteil dieser Lösung - meines Erachtens nach - ist, dass man nun C++
Objekte verwaltet durch viele Programmschichten (in C und anderen Sprachen) 
weiterreichen kann, um sie am Ende in einem anderen C++ Abschnitt
weiterverarbeiten zu können.&lt;/p&gt;

&lt;p&gt;Ich hatte am Anfang lange überlegt, ob man diese Hilfskonstrukt nicht als 
“Carrier” bezeichnen soll und offen gesagt erinnert die API eher an ein
“Trägerobjekt”. Doch in der Anwendung und vor allem auf der C++ Seite 
wirkt die Schnittstelle (danke Templates) eben wie ein SmartPointer wo man
ein Objekt über ein anderes aufgerufen wird … und dafür passt dann 
“Wrapper” besser.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Es ist somit quasi das vierte Mal in meinem Leben, dass ich eine von 
&lt;code&gt;std::share_ptr&lt;/code&gt; inspirierte SmartPointer Implementierung selbst schreibe.&lt;/p&gt;

&lt;p&gt;Und dadurch, dass die GATE Lösung sich nach C abbilden und mit C++ 
interagieren kann, handelt es sich somit im die mächtigste dieser 
Implementierungen.&lt;/p&gt;

&lt;p&gt;Gleichzeitig muss ich aber eingestehen, dass die Umwege über Funktionszeiger
in der Praxis ein klein bisschen Performance kosten werden. Denn bei einer
reinen C++ Implementierung über Templates hatte der Compiler eine größere
Chance auf Optimierungspotential.&lt;br /&gt;
C Funktionszeiger reduzieren diese Möglichkeiten etwas, doch gerade in 
meinen Bereichen steht Kompatibilität stets über der Performance.&lt;/p&gt;

&lt;p&gt;… und ganz nebenbei … wer weiß ob diese Unterschiede in der Praxis 
überhaupt messbar sind.&lt;/p&gt;

&lt;p&gt;Wie auch immer … ein schöner Tag geht für mich zu Ende.
Ich liebe es, sich mit solche Details zu befassen, die den meisten anderen
gar nicht erst auffallen.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Easter Eggs</title>
   <link href="https://www.opengate.at/blog/2020/04/easter-eggs/"/>
   <published>2020-04-12T13:00:00+02:00</published>
   <updated>2020-04-12T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2020/04/easter-eggs</id>
   <category term="software" /><category term="retro" />
   <summary type="text">Dass Programmierer immer ein paar Geheimnisse in ihren Werken hinterlassen,
ist vermutlich schon seit Anbeginn der IT so.

Neben der schwachen Story im Film Ready Player One
fand ich am Ende (Achtung Spoiler!) die Idee aber sehr nett, dass ein
uraltes “Easter-Egg” des Rätsels Lösung war.
</summary>
   <content type="html">&lt;p&gt;Dass Programmierer immer ein paar Geheimnisse in ihren Werken hinterlassen,
ist vermutlich schon seit Anbeginn der IT so.&lt;/p&gt;

&lt;p&gt;Neben der schwachen Story im Film &lt;a href=&quot;https://de.wikipedia.org/wiki/Ready_Player_One_(Film)&quot;&gt;Ready Player One&lt;/a&gt;
fand ich am Ende (Achtung Spoiler!) die Idee aber sehr nett, dass ein
uraltes “Easter-Egg” des Rätsels Lösung war.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Meine ersten Programme in &lt;a href=&quot;https://en.wikipedia.org/wiki/QBasic&quot;&gt;QBasic&lt;/a&gt; und 
&lt;a href=&quot;https://en.wikipedia.org/wiki/Turbo_Pascal&quot;&gt;TurboPascal&lt;/a&gt; schrieb ich noch ganz
ohne Einfluss des Internet. Ich kannte daher den Begriff Easter-Egg nicht
und hatte auch kein “kulturelles” Vorbild, an dem ich mich orientieren 
konnte.&lt;/p&gt;

&lt;p&gt;Und dennoch war der Reiz vorhanden “etwas” ins Programm einzubauen, das
man regulär nicht finden konnte, und nur durch eine nicht dokumentierte
Tastensequenz ausgelöst werden konnte.&lt;/p&gt;

&lt;p&gt;Dabei handelte es sich um einen speziellen Bildschirm, der 
(ganz &lt;a href=&quot;https://de.wikipedia.org/wiki/Star_Trek&quot;&gt;Star-Trek&lt;/a&gt;-like) eine 
&lt;em&gt;Selbstzerstörungssequenz&lt;/em&gt; auslösen oder eine Softwarekopie anlegen konnte.&lt;/p&gt;

&lt;p&gt;Nicht sehr originell und auch nicht sonderlich nützlich, aber am Ende 
beider Routinen kam dann ein Verweis auf den Meister - also auf mich selbst.&lt;/p&gt;

&lt;p&gt;… hört sich heute etwas peinlich an, aber als Jugendlicher findet man 
das eben “cool”.&lt;/p&gt;

&lt;p&gt;Mit dem Internet nach den 2000ern erkannte ich aber, dass solche Spielereien
in zahlreichen großen Softwareprodukten eingebaut worden war.&lt;br /&gt;
Von Microsoft Office bis zur VB 6 IDE gab es Anweisungen, wie man zu 
speziellen Fenstern gelangen konnte, die die Macher auflisteten oder ein
paar Animationen zeigten oder diverse Farben in der Software umstellten.&lt;/p&gt;

&lt;p&gt;Vielleicht liegt es daran, dass “wir” Softwareentwickler immer darunter zu 
leiden haben, dass nur die Oberflächen unserer Werke gesehen und anerkannt 
werden, doch die komplexen Abläufe unter der Motorhaube stets verborgen 
bleiben.&lt;br /&gt;
Es mag verletzter Stolz sein, der uns glauben lässt, wir müsste 
“noch präsenter” sein, weil uns niemand bemerkt, und daher arbeiten wir 
weitere “Geheimnisse” in unsere Produkte ein, um sie mystischer wirken 
zu lassen und um uns zu freuen, wenn der eine oder andere Fan das Rätsel
löst und unsere “Easter-Eggs” per Zufall oder durch langes Suchen findet.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Wie auch immer … heute ist Ostersonntag, und auch wenn mich der religiöse
Hintergrund wenig tangiert, so gehört dieser Feiertag dennoch zu unserer
Tradition.&lt;br /&gt;
Und während Eltern sich daran erfreuen, dass ihr Nachwuchs die Eier im 
Garten sucht, die sie selbst Minuten zuvor versteckt haben, so tüftle ich 
eben an eine paar Ideen, wie man Easter-Eggs in Bibliotheken einbauen kann,
ohne dass sie schadhaftes Verhalten auslösen.&lt;/p&gt;

&lt;p&gt;In diesem Sinne: &lt;strong&gt;Frohe Ostern!&lt;/strong&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Youtube Video Downloader</title>
   <link href="https://www.opengate.at/blog/2020/04/youtube-downloader/"/>
   <published>2020-04-11T13:00:00+02:00</published>
   <updated>2020-04-11T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2020/04/youtube-downloader</id>
   <category term="software" />
   <summary type="text">Ziemlich genau vor einem Jahr habe ich zum ersten mal für eine Software 
bezahlt, die ich schon seit Jahren kostenlos nutzte.

Und heute stelle ich fest, dass sich die Software gleich das Recht
herausgenommen hat, sich selbst weiter zu finanzieren.

Es handelt sich um: YTD, You-Tube-Downloader
</summary>
   <content type="html">&lt;p&gt;Ziemlich genau vor einem Jahr habe ich zum ersten mal für eine Software 
bezahlt, die ich schon seit Jahren kostenlos nutzte.&lt;/p&gt;

&lt;p&gt;Und heute stelle ich fest, dass sich die Software gleich das Recht
herausgenommen hat, sich selbst weiter zu finanzieren.&lt;/p&gt;

&lt;p&gt;Es handelt sich um: &lt;a href=&quot;http://www.ytddownloader.com/&quot;&gt;YTD, You-Tube-Downloader&lt;/a&gt;
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Wir sind heute gewohnt, dass alles Online und stets verfügbar ist.
Doch ist das wirklich so? Nein, denn es gehen täglich zahlreich Inhalte 
dauerhaft offline.&lt;br /&gt;
Hat man sie nicht “gesichert”, sieht man sie vielleicht nie wieder.&lt;/p&gt;

&lt;p&gt;Und da beziehe ich mich nicht auf urheberrechtlich geschütztes Material,
sondern auf eben genau jene Videos, die in Eigenregie erstellt und auf
YouTube hochgeladen wurden.&lt;/p&gt;

&lt;p&gt;Immer wieder passiert es, dass die Macher sich mit ihren Erstlingswerken
nicht mehr identifizieren können und schon bedienen sie den Löschknopf.&lt;/p&gt;

&lt;p&gt;Und das ist Schade, wenn auf diese Weise Dokus oder lustige Sketche verloren
gehen.&lt;br /&gt;
Deshalb lautet meine Devise:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Downloaden! Downloaden! Downloaden!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Den Downloader habe ich schon vor Jahren entdeckt und mit damals als
Freeware mit Werbung heruntergeladen.&lt;/p&gt;

&lt;p&gt;Hat man eine interessante Video-Seite gefunden kopiert man den Link
und bei der Aktivierung des YTD-Fensters schlägt dieser gleich den
Download vor.&lt;/p&gt;

&lt;p&gt;Mir gefällt besonders die eingebaute Konverter-Funktion mit der ich viele
meiner geschätzten Video-Podcasts als MP3 ausgegeben habe um sie unterwegs
am Smartphone zu hören.&lt;/p&gt;

&lt;h3 id=&quot;die-pro-versions-falle&quot;&gt;Die PRO-Versions Falle&lt;/h3&gt;

&lt;p&gt;Etwas enttäuscht bin ich, dass ich den Leuten mit dem Kauf einer Lizenz
in die Falle gegangen bin.&lt;br /&gt;
Man kauft nämlich Jahreslizenzen um 30 Euro. Und die war es mir auch mal
wert.
Und ich dachte, dass ich nach einem Jahr wieder auf die alte Werbevariante
zurücksteigen werde.&lt;/p&gt;

&lt;p&gt;Doch die findigen Geldeintreiber haben gleich ohne Nachfrage die nächste
Jahreslizenz abgebucht. Das hätte ich zwar noch reklamieren können, aber
sei’s drum. Die Entwicklung soll auch was haben.&lt;br /&gt;
Mich ärgert nur diese stille und heimliche Abbuchung.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Wer also nicht täglich neue Videos offline verfügbar bar, sondern nur 
gelegentlich sich sein “Schmankerl” sichern will, kommt mit der
kostenfreien Version gut zurecht.&lt;/p&gt;

&lt;p&gt;Dort kann man zwar nur einzelne Downloads hintereinander laufen lassen,
aber das ist nicht schlimm.&lt;/p&gt;

&lt;p&gt;Wirklich ausgezahlt hat sich meine PRO-Lizenz nicht, weil ich nur noch selten
neue Videos im Netz suche und gleich herunterlade … aber die 
Konverterfunktion nutze ich nach wie vor gerne um Videos zu verkleinern oder
als Podcast MP3 umzukodieren.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Dialoge</title>
   <link href="https://www.opengate.at/blog/2020/04/dialogs/"/>
   <published>2020-04-10T13:00:00+02:00</published>
   <updated>2020-04-10T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2020/04/dialogs</id>
   <category term="devel" />
   <summary type="text">Es war - glaube ich - im Religionsunterricht in der Schule, wo lang und breit
erklärt wurde DIA und LOGOS bedeutet, dass zwei miteinander reden, also Worte 
auswechseln.

Um so verwirrter war ich, als ich Microsoft Word
und Excel die Erstellung von “Dialogen” vorfand. 
… wie sollte denn der PC mit mir “reden”?

In der Programmierung sind Dialog-Fenster
und besonders die “modalen” Dialoge ein Spezialfall, dessen Implementierung 
seine Tücken haben kann.
</summary>
   <content type="html">&lt;p&gt;Es war - glaube ich - im Religionsunterricht in der Schule, wo lang und breit
erklärt wurde DIA und LOGOS bedeutet, dass zwei miteinander reden, also Worte 
auswechseln.&lt;/p&gt;

&lt;p&gt;Um so verwirrter war ich, als ich &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Word&quot;&gt;Microsoft Word&lt;/a&gt;
und Excel die Erstellung von “Dialogen” vorfand. 
… wie sollte denn der PC mit mir “reden”?&lt;/p&gt;

&lt;p&gt;In der Programmierung sind &lt;a href=&quot;https://de.wikipedia.org/wiki/Dialog_(Benutzeroberfl%C3%A4che)&quot;&gt;Dialog-Fenster&lt;/a&gt;
und besonders die “modalen” Dialoge ein Spezialfall, dessen Implementierung 
seine Tücken haben kann.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;definition&quot;&gt;Definition&lt;/h3&gt;

&lt;p&gt;Dialoge geben dem Benutzer die Möglichkeit sich mit dem Programm
“auszutauschen”.&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;Der Benutzer will etwas haben und öffnet ein Dialog-Fenster.&lt;/li&gt;
  &lt;li&gt;Das Programm will etwas wissen, der Benutzer gibt es ein.&lt;/li&gt;
  &lt;li&gt;Der Benutzer fordert ein Ergebnis ein, das Programm liefert.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Theoretisch ist jede GUI, wo man mit einem Eingabegerät etwas ändern kann
und eine Anzeige etwas präsentiert eine Form von Dialog.&lt;/p&gt;

&lt;p&gt;In der Entwicklung (in erster Linie unter Windows), finden wir aber 
unterschiedliche Definitionen dazu:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;em&gt;Ein Fenster wird mit einer &lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/menurc/dialog-resource&quot;&gt;DIALOG&lt;/a&gt; Resource erstellt.&lt;/em&gt;&lt;br /&gt;
Das witzige daran ist, dass man per Windows Ressourcen keine
Nicht-Dialoge erzeugen kann. Man könnte also behaupten, jede UI,
die auf einer Resource-Datei (*.rc) basiert ist ein Dialog, und alles
was man per API erzeugt ist eben keiner … 
OK, Spaß bei Seite, aber so sind Dialoge entstanden. Es gab ein
Hauptfenster, dass man individuell zusammengecodet hatte, und für die
Einstellungen wurden Unterfenster angezeigt, wo man Text und Checkboxen
verändern konnte. Und für diese einfachen Label, Textbox und Checkbox
Zusammenstellungen hat Microsoft ein eigenes Resource-Format bereitgestellt
um diese Art der Entwicklung zu vereinfachen.&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;Man kann zwischen Controls mit der TAB-Taste hin- und herwechseln.&lt;/em&gt;&lt;br /&gt;
Genau, denn wer in seiner Message-Pump zwischen &lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getmessage&quot;&gt;GetMessage()&lt;/a&gt;
und &lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-translatemessage&quot;&gt;TranslateMessage()&lt;/a&gt;
den Aufruf von &lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-isdialogmessagew&quot;&gt;IsDialogMessage()&lt;/a&gt;
vergisst, wird feststellen, dass TABs nicht funktionieren.&lt;br /&gt;
Wenn ich das also richtig deute, ist die Steuerung per TAB Taste ein
essentieller Bestandteil von Dialogen.&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;Ein Fenster wird über einem anderen angezeigt und das hintere ist so lange deaktiviert, bis das Dialog-Fenster geschlossen wird.&lt;/em&gt;&lt;br /&gt;
Das nennt man einen “modalen” Dialog. Er blockiert die restliche UI, bis man
mit den Eingaben auf dem Dialog fertig ist. In fast allen Frameworks wird
das als eigener Fall behandelt. Man kann ein Fenster “anzeigen”, oder es
als “modalen Dialog anzeigen” lassen.
Offenbar bin ich nicht der einzige, der hier zu anderen Codekunststücken 
greifen muss als bei “normalen” Fenstern.&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;Ein Programm wartet so lange (blockiert), bis der Benutzer eine Eingabe getätigt und diese bestätigt hat.&lt;/em&gt;&lt;br /&gt;
Das trifft auf jeden Kommandozeileninterpreter zu und auch diese Form 
der Kommunikation zwischen Benutzer und Programm wird gelegentlich als 
Dialog bezeichnet. Nun gut … das ist eine andere Geschichte&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Und ich behaupte: &lt;em&gt;Wenn etwas einen “OK” und einen “Cancel” Button hat, ist es ein klassischer Dialog.&lt;/em&gt;&lt;br /&gt;
Ist doch klar, seit den ersten Windows Versionen steht in den Hilfen und 
Bedienanleitungen:&lt;/p&gt;

    &lt;blockquote&gt;
      &lt;p&gt;Um XYZ anzuwenden, öffnen Sie den Dialog mit &lt;em&gt;ABC&lt;/em&gt;, nehmen Sie die 
entsprechenden Änderungen vor und Klicken Sie auf “OK” um die Änderungen
zu bestätigen oder auf “Abbrechen” um mit dem vorherigen Zustand 
weiterzuarbeiten.&lt;/p&gt;
    &lt;/blockquote&gt;

    &lt;p&gt;Also: Dialoge haben einen “OK” und “Cancel” Button.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;gate-implementierung&quot;&gt;GATE Implementierung&lt;/h3&gt;

&lt;p&gt;Im GATE Projekt zählt eigentlich nur die Anzeige eines “modalen” Fensters als
Dialog. TABs sollten auch auf Nicht-Dialogen arbeiten.&lt;/p&gt;

&lt;p&gt;Doch unter den Gesichtspunkten der Plattformunabhängigkeit ist die Umsetzung 
herausfordernd.&lt;/p&gt;

&lt;p&gt;Unter Windows wäre alles so einfach. Man könnte ein blockierende Funktion
erdenken, z.B.: &lt;code&gt;showAsDialog(form)&lt;/code&gt; die intern eine zweite Nachrichtenschleife
implementiert und diese erst mit einem Dialog-Close Event wieder verlässt.&lt;/p&gt;

&lt;p&gt;So könnte man das Ergebnis des Dialogs sogar als Rückgabewert “verkaufen”.&lt;/p&gt;

&lt;p&gt;Doch andere Frameworks unterstützen diese Methode nicht. Deren Nachrichtenschleife
ist eine Blackbox, die genau einmal aufgerufen werden darf.&lt;/p&gt;

&lt;p&gt;Also bleibt mir nur die Möglichkeit, die Fenster in die richtigen Zustände zu
versetzen und das ganze über zwei Routinen laufen zu lassen:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;gate_ui_form_begin_dialog();&lt;/code&gt; zeigt eine Form als Dialog über ihrem Owner an,
nachdem sie eben diesen &lt;code&gt;disabled&lt;/code&gt; hat.&lt;/li&gt;
  &lt;li&gt;und &lt;code&gt;gate_ui_form_end_dialog();&lt;/code&gt; setzt den Zustand zurück, indem die Dialog-Form
unsichtbar geschaltet wird und der Owner wieder &lt;code&gt;enabled&lt;/code&gt; wird.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Wie jetzt Dialog-Ergebnisse ausgetauscht werden, muss jeweils separat 
implementiert werden. Doch nachdem man aus dem unsichtbaren Dialog die Werte
seiner Controls noch extrahieren kann, ist das gut machbar.&lt;/p&gt;

&lt;p&gt;Tja, was soll man machen …
In &lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_Basic_Classic&quot;&gt;Visual Basic 6&lt;/a&gt; war 
das noch schön, wo man über &lt;code&gt;form.Show vbModal&lt;/code&gt; quasi den laufenden Code 
blockieren konnte ohne die UI zu blockieren.&lt;br /&gt;
Aber man kann eben nicht alles bekommen.&lt;/p&gt;

&lt;p&gt;Wobei … ein paar “Dialoge” haben sehr wohl das blockierende Verhalten:
Und zwar FilePicker und seine Verwandten. Deren APIs waren immer schon 
so gestrickt, dass die UI weiterlief aber der Funktionsaufruf selbst 
blockierte. Nur sind die eben wieder eine Blackbox und nicht direkt 
nachstellbar.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Selbstgestrickte Dialoge sind nun also auch im GATE UI Framework.
Und dort werden sie auch dringend benötigt. Man kann mit ihnen hervorragend
Auswahlmöglichkeiten und Einstellung abbilden ohne “das Hauptprogramm” 
damit zu stören.&lt;/p&gt;

&lt;p&gt;Und ich bin auch kein Fan dieser aus der Webentwicklung stammenden Unart
ein Panel über das Hauptfenster zu ziehen und darauf Dialog-Inhalt 
darzustellen.&lt;br /&gt;
Diese Dinger sind eben keine echten Top-Level Fenster und können nicht auf
dem Bildschirm verschoben werden. Sie verdeckten zwangsläufig Daten am
Hauptfenster und es gibt immer wieder Situationen wo das extrem nervt,
wenn man basierend auf Daten dort Änderungen im Dialog machen möchte
… und eben diese sieht man dann nicht und kann den “Dialog” auch nicht
bei Seite schieben.&lt;/p&gt;

&lt;p&gt;Wie auch immer … Mission accomplished!&lt;/p&gt;

&lt;p&gt;Also ab zur nächsten Aufgabe.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Final Fantasy VII</title>
   <link href="https://www.opengate.at/blog/2020/04/ff7/"/>
   <published>2020-04-05T13:00:00+02:00</published>
   <updated>2020-04-05T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2020/04/ff7</id>
   <category term="entertainment" />
   <summary type="text">Während sich die Welt über das Remake von Final Fantasy VII
freuen darf, habe ich das “beste Rollenspiel aller Zeiten” von 1997 nochmal 
für die Nintendo Switch gekauft.

Hmm … da werden wieder schöne Erinnerungen wach 
… aber nicht an vorgestern sondern nur an gestern.
</summary>
   <content type="html">&lt;p&gt;Während sich die Welt über das Remake von &lt;a href=&quot;https://de.wikipedia.org/wiki/Final_Fantasy_VII&quot;&gt;Final Fantasy VII&lt;/a&gt;
freuen darf, habe ich das “beste Rollenspiel aller Zeiten” von 1997 nochmal 
für die &lt;a href=&quot;https://de.wikipedia.org/wiki/Nintendo_Switch&quot;&gt;Nintendo Switch&lt;/a&gt; gekauft.&lt;/p&gt;

&lt;p&gt;Hmm … da werden wieder schöne Erinnerungen wach 
… aber nicht an vorgestern sondern nur an gestern.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Vor dem Jahr 2000 kannte ich wenig. Und außer einem Nintendo Gameboy 
besaß ich auch keine Spielekonsolen.&lt;/p&gt;

&lt;p&gt;Rollenspiele wurden mir erst mit dem Millenniumswechsel zugänglich und
zwar über &lt;a href=&quot;https://de.wikipedia.org/wiki/Emulator&quot;&gt;Emulatoren&lt;/a&gt;. Ich habe zwar 
noch kein &lt;a href=&quot;https://de.wikipedia.org/wiki/Super_Nintendo_Entertainment_System&quot;&gt;SNES&lt;/a&gt; 
aus der Nähe gesehen, doch den ZSNES Emulator für DOS und Windows lernte ich 
damals kennen und lieben.&lt;/p&gt;

&lt;p&gt;Und da waren es Final Fantasy 4, 5 und 6, die meine ganz besondere 
Aufmerksamkeit genossen. Die abwechslungsreichen Geschichten um eine 
Gruppe von Helden, die im mittelalterlichen Schwertkampfstil in einer 
Steampunk-Welt mit Magie gegen Monster kämpfen mussten bot ein Spektrum
an Ideen, Eindrücken und unerwarteten Wendungen, dich ich bis heute
sehr schätze und genieße.&lt;/p&gt;

&lt;p&gt;Da die Playstation 1 aber lange Zeit nicht ordentlich am PC emuliert werden
konnte (kurz nach 2000), entwickelte ich auch keinen Bedarf an Spielen für 
diese Konsole … und dennoch hörte man immer in nebenbei, dass das beste
aller Final Fantasys eben auf diesem Gerät spielbar sei.&lt;/p&gt;

&lt;p&gt;Es muss so um 2007 gewesen sein, als ich einen Versuch unternahm, die PS-One
Umgebung bei mir zum Laufen zu bekommen und auch die 3 CD-ISOs von FF7 konnte
ich in einem dunklen Winkel des Netzes finden.&lt;br /&gt;
Funktioniert hat es aber anfangs nicht, doch ich fand relativ schnell ein paar
Optionen im Emulator, die in der Beschreibung den Titel &lt;em&gt;Hack for FF7&lt;/em&gt; oder 
so ähnlich hatten … und siehe da: es lief!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;O-M-G!&lt;/em&gt; Was war das für ein Erlebnis und wie sehr ärgerte ich mich, diesen
Titel nicht schon viel früher gespielt zu haben.&lt;br /&gt;
Zwar kann man fast alle Hauptcharaktere der klassischen Final Fantasy Reihe als
“Cooler Junge mit Schwert” bezeichnen, aber &lt;a href=&quot;https://finalfantasy.fandom.com/de/wiki/Cloud_Strife&quot;&gt;Cloud Strife&lt;/a&gt; 
wurde für mich der Inbegriff dieser Benennung.&lt;/p&gt;

&lt;p&gt;Neben der 3D Außenwelt und den schön gestalteten Ortshintergründen waren auch
die Kämpfe ein Augenschmaus verglichen mit den älteren Spielen der Serie.&lt;br /&gt;
Aber die Story übertraf dann auch meine bisherigen Lieblinge FF6 und 
&lt;a href=&quot;https://en.wikipedia.org/wiki/Lufia_II:_Rise_of_the_Sinistrals&quot;&gt;Lufia 2&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Man kann es schwer in Worte fassen … 
nein, dieses Abenteuer muss man erlebt haben!&lt;/p&gt;

&lt;p&gt;Und so war Final Fantasy ein paar Jahre später sofort gekauft und 
heruntergeladen, als ich meine &lt;a href=&quot;https://de.wikipedia.org/wiki/PlayStation_Portable&quot;&gt;PSP&lt;/a&gt; 
in Betrieb nahm. 
Und das Wiedererleben der geliebten Story war erneut eine Freude.&lt;/p&gt;

&lt;p&gt;Apropos Playstation Portable … dort erschien auch das Prequel 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Crisis_Core:_Final_Fantasy_VII&quot;&gt;Crisis Core FF7&lt;/a&gt;, 
welches ich selbstverständlich haben musste.&lt;br /&gt;
Doch im Vergleich zum Haupttitel war es eine Enttäuschung.&lt;br /&gt;
An diesem Beispiel wurde mir klar, dass eine filmreife Grafik einen
unguten Soundtrack und langweilige Dialoge nicht wettmachen können.
Das Spiel war zwar nicht “schlecht”, aber an seinen Vorgänger kommt es nie
und nimmer heran.&lt;/p&gt;

&lt;p&gt;Doch nun im Jahr 2020 möchte ich mich erneut an “die gute alte Zeit” erinnern
und als ich sah, dass FF7 für die Nintendo Switch angeboten wurde, musste 
die Kreditkarte wieder etwas leichter werden um den Download anwerfen zu 
können.&lt;/p&gt;

&lt;p&gt;Und auch wenn die Grafik von damals mit heutigen Augenweiden wie 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Xenoblade_Chronicles_2&quot;&gt;Xenoblade Chronicles 2&lt;/a&gt; 
nicht mithalten kann, so schätze ich den genialen Soundtrack und die kurzen 
prägnanten Dialoge der Charaktere.&lt;/p&gt;

&lt;p&gt;Ich denke, die Spielemacher von heute sehen sich so unter Druck, immer feinere
und detailreichere Grafiken einzubauen, dass sie auf die Flüssigkeit des
Spielverlaufs vergessen.&lt;br /&gt;
Und wenn alle 20 Minuten eine 10 Minuten lange Cutscene einsetzt wo sich 
die Charaktere in langen philosophischen Debatten über den Sinn ihrer Aufgabe
unterhalten, so vermisse ich Cloud, der einfach nur 
“Interessiert mich doch nicht!” ausspuckt und zum nächsten Kampf marschiert.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;FF7 auf der Switch ist ein toller Retro-Spaß nebenbei.&lt;br /&gt;
Ich muss aber leider melden, dass die Emulation nicht ganz sauber läuft.
Zwei mal ist mir das Spiel bereits eingefroren und hat mich damit um 
einige bereits erkämpfte Ziele gebracht.&lt;/p&gt;

&lt;p&gt;… es bleibt daher die alte Prämisse aufrecht:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Alle paar Schritte sofort wieder speichern!&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>CMake für Windows von gestern</title>
   <link href="https://www.opengate.at/blog/2020/04/cmake-yesterday/"/>
   <published>2020-04-04T13:00:00+02:00</published>
   <updated>2020-04-04T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2020/04/cmake-yesterday</id>
   <category term="software" />
   <summary type="text">Wo CMake ganz brav das GATE Projekt verwaltet, 
stellt sich für mich auch die Frage:


  Wie sieht es mit älteren Plattformen aus?


Denn unter Windows 7 und 10 
mit Visual Studio 2017 läuft alles reibungslos.
Aber schon für Windows XP 
und Studio 2005 hat das aktuelle CMake Release keinen Support mehr integriert.
</summary>
   <content type="html">&lt;p&gt;Wo &lt;a href=&quot;https://de.wikipedia.org/wiki/CMake&quot;&gt;CMake&lt;/a&gt; ganz brav das GATE Projekt verwaltet, 
stellt sich für mich auch die Frage:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Wie sieht es mit älteren Plattformen aus?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Denn unter &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_10&quot;&gt;Windows 7 und 10&lt;/a&gt; 
mit Visual Studio 2017 läuft alles reibungslos.
Aber schon für &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_XP&quot;&gt;Windows XP&lt;/a&gt; 
und Studio 2005 hat das aktuelle CMake Release keinen Support mehr integriert.&lt;br /&gt;
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;aufgabe-cmake-für-alte-plattformen&quot;&gt;Aufgabe: CMake für alte Plattformen&lt;/h3&gt;

&lt;p&gt;Zu meinem Leidwesen entfernen Softwarehersteller immer viel zu schnell den 
Support für ältere Systeme, das trifft auch für CMake zu.&lt;/p&gt;

&lt;p&gt;Konnte man damit früher Projekte für Visual Studio 6 bis 2015 erzeugen,
können wir das heute nur noch mit Studio 2015 - 2019 tun.&lt;/p&gt;

&lt;p&gt;Jetzt ist aber die Kompatibilität zu alten Systemen ein Kernziel des GATE
Projektes … also was tun?&lt;/p&gt;

&lt;h3 id=&quot;windows-xp--visual-studio-6&quot;&gt;Windows XP + Visual Studio 6&lt;/h3&gt;

&lt;p&gt;Visual Studio 6 läuft offiziell nur bis Windows XP. Ab Vista und Windows 7 
werden die IDEs offiziell nicht mehr unterstützt (und bei VB 6 gab es auch 
zahlreiche Probleme mit neueren Windows Versionen).&lt;/p&gt;

&lt;p&gt;Daher macht es Sinn VS6 immer mit Windows XP z.B. in einer VM zu betreiben.
Viele Produkte unterstützen dieses alte Windows leider nicht mehr und somit 
muss man auf die jüngste der älteren Versionen zurückgreifen, die XP noch
unterstützen.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.microsoft.com/en-US/download/details.aspx?id=8483&quot;&gt;Windows Installer 4.5 Update&lt;/a&gt;&lt;br /&gt;
Ohne dieses Update lassen sich nachfolgende Installationsprogramme nicht 
ausführen.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/git-for-windows/git/releases/tag/v2.10.0.windows.1&quot;&gt;GIT 2.10&lt;/a&gt;&lt;br /&gt;
Tja, ohne &lt;a href=&quot;https://de.wikipedia.org/wiki/Git&quot;&gt;GIT&lt;/a&gt; wird das “Besorgen” von 
Quellcode mühsam, Git 2.10 ist die letzte Version, die Windows XP noch 
unterstützt.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://download.tortoisegit.org/tgit/1.8.16.0/&quot;&gt;TortoiseGIT 1.8.16&lt;/a&gt;&lt;br /&gt;
Damit wir GIT im Explorer grafisch einsetzen können, darf TortoiseGIT 
nicht fehlen. Version 1.8.16 ist hier die “neueste” mit XP Support.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://cmake.org/files/v3.5/&quot;&gt;CMake 3.5.2&lt;/a&gt;&lt;br /&gt;
Für MSVC 6 müssen wir leider bis zur Version 3.5.2 zurücksteigen.
Neuere Versionen können keine Projektdateien für VC 6 mehr erstellen.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.microsoft.com/en-us/download/details.aspx?id=9183&quot;&gt;Service Pack 6&lt;/a&gt;
für Visual Studio 6&lt;br /&gt;
Seit Anfang 2000 habe ich keine Installation mehr ohne dieses Update
gesehen. Es sollte auf keinem VS6-System fehlen.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Mit dieser Toolchain ist es möglich 32-bit Kompilate zu erstellen, die auch
noch unter Windows 95 und NT 4.0 laufen.&lt;br /&gt;
(Dies ist zwar kein Hauptziel des GATE Projektes … aber wenn Zeit bleibt,
wieso nicht).&lt;/p&gt;

&lt;h3 id=&quot;einschränkungen&quot;&gt;Einschränkungen&lt;/h3&gt;

&lt;p&gt;Die wichtigste Einschränkung ist der C89 Compiler. Viele moderne C-Bibliotheken
setzen C99 voraus. Im GATE Projekt trifft das leider die libReSSL und somit 
müsste diese in CMake ausgeschlossen werden.&lt;br /&gt;
Eine Alternative wäre eine (möglicherweise ältere) Version von OpenSSL, die
noch unter Studio 6 erstellbar wäre.&lt;/p&gt;

&lt;p&gt;Viele C++ Features sind ebenfalls problematisch. Das GATE Projekt versucht 
diese zwar nicht einzusetzen, dennoch ist es auch als Anwendungsentwickler 
schwierig hier nicht in alle möglichen Fallen zu treten.&lt;/p&gt;

&lt;p&gt;Dass &lt;code&gt;new&lt;/code&gt; keine Exception wirft und im Fehlerfall einfach NULL zurückgibt, 
ist so eine Spezialität, die schnell zu “seltsamen” Abstürzen führen kann.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ja, als Code-Archäologe hat man es nicht immer leicht.&lt;br /&gt;
Doch andererseits sind es genau die Spezialitäten dieser alten Systeme und
Build-Umgebungen, die einem die Entwicklungsgeschichte der heutigen IT
offenlegen.&lt;/p&gt;

&lt;p&gt;Zumindest freue ich mich, dass es mir mit diesem Setup möglich ist,
meine heutigen Sourcen auch noch auf antiken Systemen bauen lassen zu können.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Masquerade</title>
   <link href="https://www.opengate.at/blog/2020/03/masquerade/"/>
   <published>2020-03-29T13:00:00+02:00</published>
   <updated>2020-03-29T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2020/03/masquerade</id>
   <category term="general" />
   <summary type="text">OK, ich gebe zu, ich habe mich geirrt.

Wir befinden uns den größten Krise seit Menschen-Gedenken.

Denn seit Anbeginn der Zeit (bzw. Zeitrechnung) hat es noch nie
ein Jahr gegeben, in denen die Pokemon
Vorentscheide für die Weltmeisterschaft vorerst abgesagt wurden …
</summary>
   <content type="html">&lt;p&gt;OK, ich gebe zu, ich habe mich geirrt.&lt;/p&gt;

&lt;p&gt;Wir befinden uns den größten Krise seit Menschen-Gedenken.&lt;/p&gt;

&lt;p&gt;Denn seit Anbeginn der Zeit (bzw. Zeitrechnung) hat es noch nie
ein Jahr gegeben, in denen die &lt;a href=&quot;https://de.wikipedia.org/wiki/Pok%C3%A9mon-Spiele&quot;&gt;Pokemon&lt;/a&gt;
Vorentscheide für die Weltmeisterschaft vorerst abgesagt wurden …
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Und wieder mal ein Bericht von der Front:&lt;/p&gt;

&lt;p&gt;Ich wagte einen etwas längeren Spaziergang über die Wiener
Favoritenstraße um beim Kaufhaus Müller Rasierschaum und eine
CO2-Ersatzflasche für meinen Sprudelautomat zu kaufen.&lt;/p&gt;

&lt;p&gt;Als ich dabei war um die Ecke durch die Eingangstür zu schwenken,
kam mir schon ein Mann mit umgehängter Ausweiskarte entgegen,
und wies mich freundlich an, ich möge mich in die Schlange einreihen.&lt;/p&gt;

&lt;p&gt;Und ja, tatsächlich, bei genauerem Hinsehen bemerkte ich, dass einige
Menschen mit breitem Sicherheitsabstand von 3 Metern quer über die Straße
standen und warteten, ins Geschäft gebeten zu werden, wann immer ein
vorhergehender Kunde den Laden verließ.&lt;/p&gt;

&lt;p&gt;Wegen des großen Abstandes sah es so aus, als würden die Menschen einfach
so rumstehen … denn eine “Schlange” war ich anders gewohnt.&lt;br /&gt;
Also marschierte ich zu deren Ende und 5 Minuten später durfte ich bereits
eintreten.&lt;/p&gt;

&lt;p&gt;Lustig war aber die Szene dazwischen, als eine Frau im hohen Alter ebenso 
aufgeklärt wurde, sie müsse sich hinten anstellen.&lt;br /&gt;
Und sie reagierte in typischer Wiener Art mit:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;I bin a 28er-Jahrgang. Ned amal im Krieg hat’s so was ‘geben.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Nun gut, das glaube ich ihr jetzt so zwar nicht, denn die unmittelbare
Zeit nach dem 2. Weltkrieg war nicht gerade von Überfluss gekennzeichnet,
doch dass wegen eines Krankheitserreger Geschäfte ihre Kunden nur mehr 
gestaffelt eintreten lassen … ja, das gab es offenbar wirklich noch nicht.&lt;/p&gt;

&lt;p&gt;Natürlich versehe ich, dass vor allem die Mitarbeiter im Handel geschützt
sein müssen, und dass man unnötige Drängeleien verhindern sollte.&lt;/p&gt;

&lt;p&gt;Trotzdem kommt mir die Sache jetzt langsam mehr und mehr überzogen vor.&lt;/p&gt;

&lt;p&gt;Ab Mittwoch (1. April - und das ist kein Scherz!) tritt auch noch eine
Schutzmaskenpflicht für Kunden in Kraft.&lt;br /&gt;
Wir müssen dann also am Eingang eine Maske überziehen, und noch steht 
nicht bei allen Läden fest, ob diese gratis verteilt oder “zwangsverkauft” 
wird.&lt;/p&gt;

&lt;p&gt;Und obwohl ich diese Maßnahme nicht als Bedrohung meiner persönlichen 
Freiheit sehe, kommt in mir doch mehr und mehr der Gedanke auf, dass man
vielleicht eher jene Personen, die zwischen Januar und Februar trotz
öffentlicher Warnungen in der halben Welt herumgereist sind hätte 
einsperren sollen, anstatt die Restbevölkerung mit Einschränkungen zu
quälen.&lt;/p&gt;

&lt;p&gt;Schließlich ist es dem dekadenten Massentourismus zu verdanken, dass sich
Krankheiten wie Covid-19 aka Corona weltweit verbreiten konnten.&lt;/p&gt;

&lt;p&gt;Ich habe es nie verstanden, warum so viele Menschen in jedem Quartal einer 
Urlaubswoche entgegenfiebern, in der sie nur an Flucht denken und ins
Ausland reisen um dort “die Sau rauszulassen”.
Wäre es nicht besser “die Sau” anzubinden und sich aufs Sofa zu legen 
und ein Buch zur Entspannung zu lesen?&lt;/p&gt;

&lt;p&gt;Eines finde ich aber interessant. Als es um Klimaschutz ging, war der
Aufschrei laut, man könne doch nicht den Flugverkehr oder die Wirtschaft
gefährden, in dem man unseren Lebensstandard einschränkt.&lt;/p&gt;

&lt;p&gt;Offenbar geht das aber ganz leicht, wenn ein paar Politiker sich hinstellen
und von der größten Krise aller Zeit sprechen.&lt;/p&gt;

&lt;p&gt;Dass unsere Wirtschaft jetzt auf Talfahrt geht ist nun “vorprogrammiert”.
Die Arbeitslosigkeit ist im vergangenen Monat auf Rekordzahlen angestiegen,
und die Börsenkurse haben sich halbiert.&lt;/p&gt;

&lt;p&gt;Tja … mal sehen, wie sich das Chaos jetzt weiterentwickeln wird …&lt;/p&gt;

&lt;p&gt;Ich habe immer noch kein Klopapier gekauft, obwohl es aber wieder lieferbar
sein dürfte.&lt;br /&gt;
Und ich vertraue darauf, dass noch ein paar besonnene Köpfe die Versorgung
der Gesellschaft sicherstellen.
Trotzdem wundere ich mich aktuell wirklich sehr über “die Menschen” und ihre
Reaktionen, wie schnell das gestrige “Nein” heute zu einem “Ja” wurde, und
wie die Polizei heute Strafen einzieht, wenn mehr als 2 Personen gemeinsam
in der Öffentlichkeit herumlaufen.&lt;/p&gt;

&lt;p&gt;Mich trifft das Gott sei Dank nicht, und dank Home-Working erlebe ich 
momentan eine sehr entspannte Zeit. Ich bin aber sicher, dass es nicht allen 
so ergeht, die nun um ihre Existenz bangen müssen.&lt;/p&gt;

&lt;hr /&gt;

&lt;blockquote&gt;
  &lt;p&gt;Hallo älteres Ich, der du diesen Text in 10 Jahren vielleicht wieder lesen
wirst.&lt;br /&gt;
Und? Was sagst du?&lt;br /&gt;
Weißt du noch, wie das damals im Jahr 2020 ausgegangen ist?&lt;/p&gt;

  &lt;p&gt;War doch eine verrückte Zeit damals, oder?&lt;br /&gt;
Wie geht’s dir und wie oft haben solchen Aktionen noch stattfinden müssen?
Gab es im Laufe der Zeit politische Unruhen? 
Haben sie ein Heilmittel gefunden?
Oder ist ein Enzym mutiert und hat darauf gesunde Menschen in Zombies verwandelt?
Sorry für das Chaos, dass wir heute geschaffen haben, und woran du vielleicht
noch zu leiden hast.&lt;/p&gt;

  &lt;p&gt;Alles Gute und bleib gesund!&lt;/p&gt;

  &lt;p&gt;Ich geh’ jetzt aufs Klo … noch ist Papier da.&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>HTTP Upload unterbrechen</title>
   <link href="https://www.opengate.at/blog/2020/03/http-reset/"/>
   <published>2020-03-28T12:00:00+01:00</published>
   <updated>2020-03-28T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2020/03/http-reset</id>
   <category term="devel" />
   <summary type="text">In den vergangenen Wochen beschäftigte mich das Thema 
HTTP 
wieder einmal.

Und ich freue mich stets aufs Neue, wenn nach langem herumprobieren
sogar meine Kollegen zu folgendem Schluss kommen (den auch ich immer
favorisiere):


  Wir MÜSSEN einen eigenen Client bzw. einen eigenen Server schreiben.


</summary>
   <content type="html">&lt;p&gt;In den vergangenen Wochen beschäftigte mich das Thema 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Hypertext_Transfer_Protocol&quot;&gt;HTTP&lt;/a&gt; 
wieder einmal.&lt;/p&gt;

&lt;p&gt;Und ich freue mich stets aufs Neue, wenn nach langem herumprobieren
sogar meine Kollegen zu folgendem Schluss kommen (den auch ich immer
favorisiere):&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Wir MÜSSEN einen eigenen Client bzw. einen eigenen Server schreiben.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Wenn ein HTTP &lt;a href=&quot;https://de.wikipedia.org/wiki/Client&quot;&gt;Client&lt;/a&gt; vom 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Server&quot;&gt;Server&lt;/a&gt; Daten herunterlädt und während 
dieses Vorganges darauf kommt, dass er die Daten nicht mehr braucht, schließt
er einfach die Verbindung.&lt;br /&gt;
Der Server scheitert dann beim Nachpumpen weiterer Daten an einem
geschlossenen Socket, bricht ab, und alles ist gut.&lt;/p&gt;

&lt;p&gt;Doch wie sieht es meinem Upload aus?&lt;/p&gt;

&lt;p&gt;Theoretisch genau so. Will ein Server mit einem Client nicht mehr reden,
legt er auf … ähm, schließt die Verbindung und lässt den Client in
einen Socket-Fehler bzw eine Exception hineinlaufen.&lt;/p&gt;

&lt;p&gt;Aber ist das auch “gut” so?&lt;/p&gt;

&lt;p&gt;Nun, besser wäre es, dem Client mitzuteilen, dass man aus bestimmten Gründen
keine Daten mehr von ihm haben möchte, also warum nicht einen HTTP Status Code
zurücksenden …&lt;br /&gt;
und genau hier beginnen die Probleme.&lt;/p&gt;

&lt;h3 id=&quot;http-ist-nur-half-duplex-fähig&quot;&gt;HTTP ist nur half-duplex fähig!&lt;/h3&gt;

&lt;p&gt;Wie bei den klassischen &lt;a href=&quot;https://de.wikipedia.org/wiki/Star_Trek&quot;&gt;Star Trek&lt;/a&gt;
Serien kann immer nur einer Reden, die anderen schweigen aus Respekt und 
warten bis sie dran sind.&lt;/p&gt;

&lt;p&gt;Und so sind auch die meisten APIs von HTTP Implementierungen designt. Es
läuft immer nach dem gleichen Schema ab.&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;auto&lt;/span&gt;&amp;amp;&amp;amp; source = openSourceToBeUploaded();
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;auto&lt;/span&gt;&amp;amp;&amp;amp; request = createHttpRequest(toDestinationServer);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;auto&lt;/span&gt;&amp;amp;&amp;amp; upload = request.createUploadStream();
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;while&lt;/span&gt;(!source.endOfStream())
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  {
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt; buffer[&lt;span style=&quot;color:#00D&quot;&gt;4096&lt;/span&gt;];
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;    size_t bytes_received = source.read(buffer, &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;sizeof&lt;/span&gt;(buffer));
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;    upload.write(buffer, bytes_received);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;  }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  upload.close();
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;auto&lt;/span&gt;&amp;amp;&amp;amp; response = sendHttpRequest(request);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;auto&lt;/span&gt;&amp;amp;&amp;amp; statusCode = response.getHttpStatusCode();
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; statusCode;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Jetzt haben aber Kollegen in meiner Firma ein Protokoll spezifiziert,
wo während eines Uploads die Daten am Server validiert werden und im Falle
eines Fehlers abgebrochen werden soll.&lt;/p&gt;

&lt;p&gt;Schließlich macht es keinen Sinn 1 GB Daten hochzuladen, wenn schon nach den
ersten 10 Bytes erkannt wird, dass die Upload-Daten nicht verarbeitet werden 
können.&lt;/p&gt;

&lt;p&gt;In der Theorie (und eigentlich auch in der Praxis) kann man jetzt am Server
bei einem Fehler das weitere Lesen des eintreffenden Uploads aussetzen und
gleich einen HTTP Response zurückschicken und danach die Verbindung
“irgendwie” schließen.&lt;/p&gt;

&lt;p&gt;Unsere Implementierung in &lt;a href=&quot;http://pocoproject.org/&quot;&gt;POCO&lt;/a&gt; macht das auch 
offenbar so, doch dann ergibt sich folgendes Problem:&lt;/p&gt;

&lt;p&gt;Der vom Server (nachweislich) versendete HTTP Status Header wird am Client
nicht empfangen, sondern alles läuft auf einen TCP-Connection Reset hinaus.&lt;/p&gt;

&lt;p&gt;Das ist eigentlich auch logisch, denn wie der obige Pseudocode zeigt,
befinden wir uns in einer Upload-Schleife, die bröckchenweise Daten verschifft,
doch sobald die andere Seite aufhört zu lesen, wird auch das Schreiben am
Client blockiert. Ein &lt;code&gt;socket.send()&lt;/code&gt; wartet also so lange, bis der Server
alles (bzw. etwas) verarbeitet hat um dann fortsetzen zu können.&lt;/p&gt;

&lt;p&gt;Wird dann auch noch während dessen die Verbindung geschlossen, kommt es zu 
einem Fehler beim Senden und diese Exception schlägt dann “durch” und verhindert das 
Empfangen der HTTP Antwort.&lt;/p&gt;

&lt;p&gt;Was man bräuchte, wäre eine Funktion &lt;code&gt;tryReceiveResponse()&lt;/code&gt;, die man vor 
und/oder nach jedem Sendevorgang aufruft um zu Prüfen, ob schon etwas 
empfangen wurde.&lt;/p&gt;

&lt;p&gt;So eine Methode existiert aber bei den gängigen HTTP Clients nicht.&lt;br /&gt;
&lt;em&gt;An der Stelle freue ich mich, dass ich noch mit Sockets umgehen&lt;/em&gt;
&lt;em&gt;und so etwas selbst schreiben kann.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Doch auch das reicht nicht. Der Sendefehler muss ebenso abgefangen und 
an der Stelle noch ein Versuch gestartet werden, eine Antwort zu empfangen.&lt;/p&gt;

&lt;p&gt;Damit würde unser Code dann theoretisch etwa so aussehen:&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;auto&lt;/span&gt;&amp;amp;&amp;amp; source = openSourceToBeUploaded();
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;auto&lt;/span&gt;&amp;amp;&amp;amp; request = createHttpRequest(toDestinationServer);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;auto&lt;/span&gt;&amp;amp;&amp;amp; upload = request.createUploadStream();
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;try&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  {
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;while&lt;/span&gt;(!source.endOfStream())
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;    {
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt; buffer[&lt;span style=&quot;color:#00D&quot;&gt;4096&lt;/span&gt;];
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;      size_t bytes_received = source.read(buffer, &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;sizeof&lt;/span&gt;(buffer));
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;      &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;auto&lt;/span&gt;&amp;amp;&amp;amp; response = tryReceiveResponse(request);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt;(response)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;      {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;        &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;auto&lt;/span&gt;&amp;amp;&amp;amp; statusCode = response.getHttpStatusCode();
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;        &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; statusCode;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;      }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;      upload.write(buffer, bytes_received);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;      upload.close();
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;    }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;  }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;catch&lt;/span&gt;(...)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n21&quot; name=&quot;n21&quot;&gt;21&lt;/a&gt;&lt;/span&gt;  {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n22&quot; name=&quot;n22&quot;&gt;22&lt;/a&gt;&lt;/span&gt;  }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n23&quot; name=&quot;n23&quot;&gt;23&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;auto&lt;/span&gt;&amp;amp;&amp;amp; response = sendHttpRequest(request);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n24&quot; name=&quot;n24&quot;&gt;24&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;auto&lt;/span&gt;&amp;amp;&amp;amp; statusCode = response.getHttpStatusCode();
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n25&quot; name=&quot;n25&quot;&gt;25&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; statusCode;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Mit der Variante kommt man schon ein Stückchen weiter, aber perfekt
ist das leider auch nicht.&lt;/p&gt;

&lt;p&gt;Hier kommt es nämlich auf den Server an, und die meisten Implementierungen
schließen ihren Empfangskanal, sobald sie eine Antwort gesendet haben.
Und das führt - wie erwähnt - zu einem TCP Connection Reset am Client, 
doch es kann auch bewirken, dass durch das Betriebssystem Daten am Socket 
verworfen werden, die zwar empfangen aber noch nicht an den Usermode Client
ausgeliefert wurden.&lt;/p&gt;

&lt;p&gt;Mit anderen Worten: &lt;code&gt;tryReceiveResponse&lt;/code&gt; liefert nicht immer ein Ergebnis.&lt;br /&gt;
Und daran sind der Server Schuld.&lt;/p&gt;

&lt;h3 id=&quot;wie-könnte-man-es-richtig-lösen&quot;&gt;Wie könnte man es richtig lösen?&lt;/h3&gt;

&lt;p&gt;Nun, würden die Server ihre Sockets nach dem Antwort-Versand nicht schließen
(bzw. receive-shutdown-nen) und würden Clients nicht mit hirnlos mit &lt;code&gt;send()&lt;/code&gt;
arbeiten, sondern per &lt;code&gt;select()&lt;/code&gt; oder &lt;code&gt;poll()&lt;/code&gt; nur dann Lesen und Schreiben,
wenn es gerade möglich ist, dann könnten wir recht zuverlässig 
HTTP Upload Unterbrechungen mit “Out-of-order-HTTP-Responses” zurückweisen und
die Clients könnten “freiwillig” ihren Upload einstellen und am Ende trennen
beide Seiten im Einvernehmen ihre Verbindungen.&lt;/p&gt;

&lt;p&gt;Doch leider funktionieren die Implementierungen, die ich kenne, nicht so.&lt;/p&gt;

&lt;h3 id=&quot;meine-poco-server-lösung&quot;&gt;“Meine” POCO-Server Lösung&lt;/h3&gt;

&lt;p&gt;Der POCO HTTP Server lässt uns nicht kontrollieren, wann der Socket geschlossen
wird. Ein künstliches &lt;code&gt;sleep()&lt;/code&gt; in der Empfangsroutine hilft auch nicht, weil
POCO Nachrichten erst dann verschickt, wenn aus der benutzerdefinierten 
Behandlungsroutine zurückgekehrt wird (wir also die Kontrolle abgegeben haben).&lt;/p&gt;

&lt;p&gt;Einen kleinen Trick gibt es aber:&lt;br /&gt;
&lt;a href=&quot;https://en.wikipedia.org/wiki/Chunked_transfer_encoding&quot;&gt;Chunked HTTP Transfer&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Aktiviert man diesen beim Client und am Server, erhält man von POCO einen 
HTTP-Response Stream, in den man den Download schreiben sollte. Der HTTP Header
wird zuvor jedoch abgeschlossen und zum Client geschickt.&lt;/p&gt;

&lt;p&gt;Hier kann ein &lt;code&gt;sleep()&lt;/code&gt; Wunder wirken.
Wir wollen nämlich nur einen HTTP-Response-Header verschicken, wo der Status 
drinnen steht und das können wir.
Nun wartet der Client aber noch auf Content, auf den wir ihn kurz warten 
lassen. Dann senden wir “nichts” und geben die Kontrolle im Anschluss an POCO 
zurück. Dieses schreibt dann eine Chunked-End-of-stream Nachricht.&lt;/p&gt;

&lt;p&gt;An dieser Stelle kann jetzt genau das Gleiche passieren, wie oben auch:
Nämlich ein Server-Socket-Close verhindert, dass diese letzte Nachricht 
empfangen wird. Aber wir haben zumindest den Header mit dem Status empfangen 
können und wissen nun, dass der Server den Upload nicht haben wollte.&lt;/p&gt;

&lt;p&gt;Der Ablauf sieht dann so aus:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Client schickt seinen Header (mit Transfer-Encoding: chunked).&lt;/li&gt;
  &lt;li&gt;Server nimmt Header an und springt in die Behandlungsroutine.&lt;/li&gt;
  &lt;li&gt;Client schickt stückweise den Upload und versucht parallel auch eine 
Antwort zu lesen.&lt;/li&gt;
  &lt;li&gt;Server stellt einen Fehler fest und sendet den Response-Header mit 
dem HTTP Status&lt;/li&gt;
  &lt;li&gt;Client empfängt den Header und bricht seine weiteren Lese und 
Schreibvorgänge ab.&lt;/li&gt;
  &lt;li&gt;Server schließt den chunked Transfer ab (ohne Content zu senden)
und trennt die Verbindung&lt;/li&gt;
  &lt;li&gt;Client empfängt
    &lt;ol&gt;
      &lt;li&gt;entweder den Chunk-Abschluss und schließt seine Verbindung&lt;/li&gt;
      &lt;li&gt;alternativ einen Connection-Reset und schließt ebenso seine Verbindung&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;HTTP/1 is a bitch!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Einfache Fälle sind dank vieler verfügbarer Implementierungen “einfach” zu 
behandeln. Aber sobald man etwas über den Tellerrand hinausblicken möchte, 
wird es kompliziert und ohne Eigenimplementierungen teilweise sogar unmöglich.&lt;/p&gt;

&lt;p&gt;Aber … eben genau solche Aufgaben erfreuen mich sehr.&lt;br /&gt;
Da hat man als Programmierer endlich mal wieder Chance “ein Wundermittel” zu 
erfinden, dass es sonst nirgendwo auf der Welt gibt.&lt;/p&gt;

&lt;p&gt;OK … es sind keine Wundermittel sondern “dirty hacks” … aber es ist 
trotzdem geil sie anwenden zu können.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Der ATmega2560 entfacht Träume</title>
   <link href="https://www.opengate.at/blog/2020/03/mega2560/"/>
   <published>2020-03-22T12:00:00+01:00</published>
   <updated>2020-03-22T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2020/03/mega2560</id>
   <category term="hardware" />
   <summary type="text">Wegen der Corona Krise und 
meines aktuellen Exils am Land komme ich aktuell leider so gut wie gar nicht
mehr dazu, mit meinen MCUs 
zu spielen.

Zwar hätte ich meinen PI-Top 
dabei, doch wenn keine ordentliche Lötstation in der Nähe ist, was soll man 
da schon was Interessantes anstellen?

Aber man kann planen … da fiel mir wieder ein, dass ich die Lösung
gegen Pin-Mangel schon lange in der Tasche habe, sie aber noch nie
eingesetzt habe: den ATmega2560
</summary>
   <content type="html">&lt;p&gt;Wegen der &lt;a href=&quot;https://de.wikipedia.org/wiki/COVID-19-Pandemie&quot;&gt;Corona Krise&lt;/a&gt; und 
meines aktuellen Exils am Land komme ich aktuell leider so gut wie gar nicht
mehr dazu, mit meinen &lt;a href=&quot;https://de.wikipedia.org/wiki/Mikrocontroller&quot;&gt;MCUs&lt;/a&gt; 
zu spielen.&lt;/p&gt;

&lt;p&gt;Zwar hätte ich meinen &lt;a href=&quot;/blog/2019/11/pi-top/&quot;&gt;PI-Top&lt;/a&gt; 
dabei, doch wenn keine ordentliche Lötstation in der Nähe ist, was soll man 
da schon was Interessantes anstellen?&lt;/p&gt;

&lt;p&gt;Aber man kann planen … da fiel mir wieder ein, dass ich die Lösung
gegen Pin-Mangel schon lange in der Tasche habe, sie aber noch nie
eingesetzt habe: den &lt;a href=&quot;http://www.microchip.com/wwwproducts/en/ATmega2560&quot;&gt;ATmega2560&lt;/a&gt;
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;der-traum-vom-eigenen-os&quot;&gt;Der Traum vom eigenen OS&lt;/h3&gt;

&lt;p&gt;Für PCs ein OS zu schreiben ist zwar nicht unmöglich, aber zumindest
unnötig geworden. Man kann nicht mehr so wie in den 90ern sich in
Assembler ein “besseres” &lt;a href=&quot;https://de.wikipedia.org/wiki/Disk_Operating_System&quot;&gt;DOS&lt;/a&gt; 
schreiben, das auch wirklich etwas bringt.&lt;/p&gt;

&lt;p&gt;Aber bei den Mikrocontrollern, da wäre es schon super, eine stabile
Binär-API zu haben, oder dass man Skripts auf sie hochlädt und nicht 
ganze Sketches.&lt;/p&gt;

&lt;p&gt;Doch das Problem beim &lt;a href=&quot;https://en.wikipedia.org/wiki/Arduino_Uno&quot;&gt;Arduino UNO&lt;/a&gt;: 
Zu wenig RAM und zu wenig Anwendungsmöglichkeiten.&lt;/p&gt;

&lt;p&gt;Wenn man ohnehin nur 1 oder 2 &lt;a href=&quot;https://de.wikipedia.org/wiki/Serial_Peripheral_Interface&quot;&gt;SPI&lt;/a&gt; 
oder &lt;a href=&quot;https://de.wikipedia.org/wiki/I%C2%B2C&quot;&gt;I2C&lt;/a&gt; Module anstecken kann, wozu
dann ein “Treiber Framework” aufbauen. Und mit 2 KB RAM und 1 KB &lt;a href=&quot;https://de.wikipedia.org/wiki/Electrically_Erasable_Programmable_Read-Only_Memory&quot;&gt;EEPROM&lt;/a&gt;
Speicher kommt man auch nicht sonderlich weit.&lt;/p&gt;

&lt;p&gt;Doch der ATmega2560, der große Bruder vom Arduino UNO ATmega328, 
der könnte eher für so etwas geeignet sein.&lt;/p&gt;

&lt;h3 id=&quot;der-atmega2560&quot;&gt;Der ATmega2560&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;8 KB RAM, also 4 mal soviel wie der ATmega328, da lassen sich schon einige
Datenstrukturen ablegen.&lt;/li&gt;
  &lt;li&gt;4 KB EEPROM, da könnte man tatsächlich schon Scripts ablegen … ist zwar
immer noch kein “Datenträger”, aber immerhin ebenso 4 mal größer als beim
UNO&lt;/li&gt;
  &lt;li&gt;256 KB Programmspeicher: Die ersten DOS Versionen waren wesentlich kleiner ;)&lt;/li&gt;
  &lt;li&gt;100 Pins, da kann man also schon so einiges anstecken&lt;/li&gt;
  &lt;li&gt;1 x I2C: OK gleich stark wie der UNO&lt;/li&gt;
  &lt;li&gt;2 x 8-bit und 4 x 16-bit Timer: Für Interrupts ist also auch gut vorgesorgt.&lt;/li&gt;
  &lt;li&gt;4 x UART und 5 x SPI: genau hier fängt der OS Gedanke an Sinn zu machen …&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/atmega2560.jpg&quot; alt=&quot;ATmega2560&quot; /&gt;&lt;/p&gt;

&lt;p&gt;In dem Moment, wo man zwischen mehr als 2 Geräten und 2 Kommunikationskanälen
wechseln kann, beginnt es Sinn zu machen, einen “Verwalter”, also ein 
Betriebssystem zwischen den Endpunkten zu etablieren.&lt;/p&gt;

&lt;p&gt;Für kleinere Aufgaben (wie ein Gerät und eine UART) verdrahtet man die Logik
besser fest, doch wenn man die Möglichkeit hat, mehrere Geräte dynamisch ein
und auszuschalten, und wenn man z.B. einen Steuer- und einen Datenkanal
separat bedienen kann … ja, da macht das schon mehr Sinn …&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Pfeif&apos; aufs Menü</title>
   <link href="https://www.opengate.at/blog/2020/03/no-menu/"/>
   <published>2020-03-21T12:00:00+01:00</published>
   <updated>2020-03-21T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2020/03/no-menu</id>
   <category term="devel" />
   <summary type="text">Eine mittlere Katastrophe bei der Implementierung von GUI
Frameworks ist das “Menü”.

Ich meine damit diese Zeile, wo Datei und Bearbeiten usw. steht, auch
“Pull-down-menu” genannt.

Wieso können nicht alle Frameworks und Plattformen das gleichartig umsetzen?
</summary>
   <content type="html">&lt;p&gt;Eine mittlere Katastrophe bei der Implementierung von &lt;a href=&quot;https://de.wikipedia.org/wiki/Grafische_Benutzeroberfl%C3%A4che&quot;&gt;GUI&lt;/a&gt;
Frameworks ist das “&lt;a href=&quot;https://en.wikipedia.org/wiki/Menu_(computing)&quot;&gt;Menü&lt;/a&gt;”.&lt;/p&gt;

&lt;p&gt;Ich meine damit diese Zeile, wo &lt;code&gt;Datei&lt;/code&gt; und &lt;code&gt;Bearbeiten&lt;/code&gt; usw. steht, auch
“Pull-down-menu” genannt.&lt;/p&gt;

&lt;p&gt;Wieso können nicht alle Frameworks und Plattformen das gleichartig umsetzen?
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;ul&gt;
  &lt;li&gt;Ein übliches &lt;a href=&quot;https://en.wikipedia.org/wiki/Microsoft_Windows&quot;&gt;Windows&lt;/a&gt; und
&lt;a href=&quot;https://de.wikipedia.org/wiki/MacOS&quot;&gt;MacOS&lt;/a&gt; erklären “das Menü” zur 
Chefsache und lassen diese Ressource vom System verwalten.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_CE&quot;&gt;Windows CE&lt;/a&gt; ist sich 
nicht schlüssig und bietet je nach Plattform-Baukasten unterschiedliche 
Methoden an.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/X_Window_System&quot;&gt;X11&lt;/a&gt; und diverse UI 
Frameworks nehmen es selbst in die Hand und zeichnen die Menüzeile auf das 
Hauptfenster.&lt;/li&gt;
  &lt;li&gt;Und bei &lt;a href=&quot;https://de.wikipedia.org/wiki/Smartphone&quot;&gt;Smartphone&lt;/a&gt; Apps gibt es
Pulldown-Menüs de facto gar nicht mehr.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Wie soll man da jetzt eine Kapselung hinbekommen, die alle diese Fälle 
intelligent abstrahiert um “plattformübergreifend” agieren zu können?&lt;br /&gt;
Das schlimmste ist, dass auch noch das Koordinatensystem der Fenster 
durcheinander gebracht wird.&lt;/p&gt;

&lt;h3 id=&quot;windows&quot;&gt;Windows&lt;/h3&gt;

&lt;p&gt;Die “MenuBar” ist eine spezielle Zusatzressource eines Fensters. Ist ein Menü
vorhanden, liegt es in der &lt;a href=&quot;http://docs.microsoft.com/en-us/windows/win32/gdi/nonclient-area&quot;&gt;Non-Client-Area&lt;/a&gt;. 
Das bedeutet Kindfenster “sehen” es nicht und die Client-Area beginnt mit den 
Koordinaten (0, 0) direkt unter dem Menü.&lt;/p&gt;

&lt;h3 id=&quot;macos&quot;&gt;MacOS&lt;/h3&gt;

&lt;p&gt;In MacOS haben die Fenster selbst kein Menü, sondern dieses integriert sich
in die Menüzeile, die oben am Bildschirm eingeblendet ist.
In sofern gibt es für ein Programmfenster keinen Unterschied, ob ein Menü
da ist oder nicht, denn wenn eines existiert, wird es außerhalb verwaltet.&lt;/p&gt;

&lt;h3 id=&quot;x11&quot;&gt;X11&lt;/h3&gt;

&lt;p&gt;Das X Window System kennt bekanntlich überhaupt nichts und somit muss ein 
UI Framework sich sein Menü selbst zeichnen. Man ist also völlig frei, 
wo man das tut, aber meistens wird die “Windows” Variante gewählt, wo die 
Menüzeile unter der Titelzeile des Fenster eingeblendet wird.&lt;br /&gt;
Und das verschiebt natürlich alle anderen Controls des Fenster um die 
Höhe der Zeile nach unten.&lt;/p&gt;

&lt;h3 id=&quot;und-was-machen-ui-frameworks&quot;&gt;Und was machen UI Frameworks?&lt;/h3&gt;

&lt;p&gt;Die können und wollen sich nicht auf Plattform-Spezialitäten verlassen und 
verzichten auf vom System verwaltete Menüs und zeichnen gleich alles selbst.&lt;br /&gt;
Und das immer! (OK, “meistens” um genau zu sein.)&lt;/p&gt;

&lt;p&gt;Um alle Elemente sauber zu positionieren, müssen sie wieder eigene 
Container-Konstellationen einführen, damit sich das Menü oben und der Rest
darunter automatisch einrichtet.&lt;/p&gt;

&lt;p&gt;Jetzt kommt noch hinzu, dass eben die Frameworks ob ihrer “Selbstverwaltung”
das übliche Verhalten der Plattform nicht korrekt nachbauen.&lt;/p&gt;

&lt;p&gt;Wie oft musste ich schon erleben, dass Menüs unter Windows nicht durch die
ALT Taste aktiviert werden konnten? Und so etwas macht mich echt sauer, wenn
jedes Programm anders bedient werden muss bzw. sich nicht an etablierte 
Standards hält.&lt;/p&gt;

&lt;h3 id=&quot;implementierung-im-gate-projekt&quot;&gt;Implementierung im GATE Projekt&lt;/h3&gt;

&lt;p&gt;Ja, wie gesagt, ein Chaos.&lt;/p&gt;

&lt;p&gt;Am meisten zu schaffen macht mir Windows CE, in dem Menüs kein durchgängig
standardisierter Bestandteil der API sind.&lt;br /&gt;
Windows CE Desktop-Style-Apps könnten mit &lt;a href=&quot;http://docs.microsoft.com/en-us/previous-versions/windows/embedded/ms908131(v=msdn.10)&quot;&gt;&lt;code&gt;CommandBar_Create()&lt;/code&gt;&lt;/a&gt;
arbeiten, doch das würde Windows Mobile (das ja auf CE basiert) nicht 
unterstützen.&lt;/p&gt;

&lt;p&gt;Dafür hat man dann die &lt;a href=&quot;https://docs.microsoft.com/en-us/previous-versions/windows/embedded/ms907090(v=msdn.10)&quot;&gt;AYGShell&lt;/a&gt; 
Erweiterung erfunden, die es ermöglichen soll, ein paar Features 
(darunter auch &lt;a href=&quot;https://docs.microsoft.com/en-us/previous-versions/windows/embedded/aa453678%28v%3dmsdn.10%29&quot;&gt;Menüs&lt;/a&gt;
) portabel zu gestalten.&lt;/p&gt;

&lt;p&gt;Doch auch hier muss man mit eigenen Fenstern agieren, sie richtig positionieren
und dann auch noch Resource-Dateien einbinden … also kurz gesagt: Pfui!&lt;/p&gt;

&lt;p&gt;Aber auch &lt;a href=&quot;https://de.wikipedia.org/wiki/GTK_(Programmbibliothek)&quot;&gt;GTK&lt;/a&gt; macht
mir das Leben hier nicht gerade leichter, wo ich für das Menü eigens Platz 
schaffen muss und die anderen Kind-Elemente in einem Layout-Container 
unterbringen muss.&lt;/p&gt;

&lt;p&gt;Hier liegt dann das Problem, dass ein Fenster mit Menü sich anders verhalten
muss (z.B. beim Ändern der Größe) als ein Fenster ohne Menü.&lt;/p&gt;

&lt;p&gt;Nun gut, jetzt mögen manche sagen:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Selbst schuld!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Denn GTK hat ja sein eigenes Container-Management für diese Zwecke, doch
dieses lässt mir leider nicht den Spielraum, den ich eben haben möchte.
Auch anders herum, wenn GTK das führende Verhalten wäre, müsste man die 
gesamte Container-Logik wieder auf die WinAPI portieren … also auch kein
Spaß.&lt;/p&gt;

&lt;p&gt;Mobile Apps lasse ich jetzt mal außen vor.&lt;/p&gt;

&lt;p&gt;Diese unterscheiden sich derartig vom Aufbau von Desktop Apps, dass es bisher
noch niemandem gelungen ist, Desktop-Features dort hin zu übernehmen.&lt;br /&gt;
Das macht man eher umgekehrt, nämlich dass mobile Apps mit ihren primitiven
Funktionen dann auf dem Desktop erscheinen … aber das ist eine andere
Geschichte.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Seit &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_3.1&quot;&gt;Windows 3.1&lt;/a&gt; kenne
ich Menüs und seit meinen ersten &lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_Basic_Classic&quot;&gt;Visual Basic&lt;/a&gt; 
Tagen nutze ich diese.&lt;/p&gt;

&lt;p&gt;Es ist eine extrem effiziente Möglichkeit eine Vielzahl von Funktionen gut
zu strukturieren und unsichtbar zu lagern, die nur bei Bedarf angezeigt 
werden.&lt;/p&gt;

&lt;p&gt;Während man bei mobilen Apps mit ihren 2 bis 10 Features keine Menüs braucht,
sind sie bei professionellen Anwendungen einfach unverzichtbar.&lt;br /&gt;
Da muss man eben die Möglichkeit haben durch X Hierarchien das Feature 
Nr. 217 schnell zu finden.&lt;/p&gt;

&lt;p&gt;Und eben deshalb bleibt es mir nicht erspart, Menüs in vollem Umfang auf allen
Plattformen zu unterstützen.&lt;/p&gt;

&lt;p&gt;Wie auch immer … manchmal nervt die Implementierung eben sehr!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Ausverkauft</title>
   <link href="https://www.opengate.at/blog/2020/03/sold-out/"/>
   <published>2020-03-16T12:00:00+01:00</published>
   <updated>2020-03-16T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2020/03/sold-out</id>
   <category term="general" />
   <summary type="text">
  Keine Zwiebeln und Aufbackbrötchen, dafür aber Homeworking.


Wow, so schnell kann’s gehen mit dem Weltuntergang.

Und weil man darin die Universallösung für alles sieht, haben psychotische
Menschen in ganz Österreich wegen der steigenden Anzahl an COVID-19
Corona-Infektionen die Läden gestürmt um vor allem Klopapier zu hamstern.
</summary>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;Keine Zwiebeln und Aufbackbrötchen, dafür aber Homeworking.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Wow, so schnell kann’s gehen mit dem Weltuntergang.&lt;/p&gt;

&lt;p&gt;Und weil man darin die Universallösung für alles sieht, haben psychotische
Menschen in ganz Österreich wegen der steigenden Anzahl an &lt;a href=&quot;https://de.wikipedia.org/wiki/COVID-19&quot;&gt;COVID-19&lt;/a&gt;
Corona-Infektionen die Läden gestürmt um vor allem Klopapier zu hamstern.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;leere-supermärkte-&quot;&gt;Leere Supermärkte ?&lt;/h3&gt;

&lt;p&gt;Da mache ich neulich noch Witze über die übertrieben geschilderte 
&lt;a href=&quot;/blog/2020/03/corona/&quot;&gt;CoVid-19 Epidemie&lt;/a&gt;, 
und heute stelle ich beim Einkaufen fest, dass “sich etwas verändert hat.”&lt;/p&gt;

&lt;p&gt;Nach Medienberichten sollen zahlreiche Geschäfte und Supermärkte ausverkauft
sein, weil am Freitag, den 13. März (Hmm, interessant!) und am Samstag 
Menschenmassen Notvorräte anlegen wollten.&lt;/p&gt;

&lt;p&gt;Warum ausgerechnet Klopapier ein Verkaufsplus von 600% hatte ist mir absolut
schleierhaft, aber wie mehrere Psychologen anmerkten, lassen sich panische
Hamsterkäufe ohnehin nicht rational erklären.&lt;/p&gt;

&lt;p&gt;Ich merkte heute beim Einkauf zwar schon, dass einige Stellen in Regalen leer
waren, und dabei sind mir vor allem fehlende Zwiebel und Aufbackbrötchen 
aufgefallen, gleichzeitig gab es aber Jungzwiebel und eingelegte Zwiebel wie
auch Toastbrot weiter im Überfluss.&lt;/p&gt;

&lt;p&gt;Und ja, Klopapier wie auch alle Formen von Desinfektionsmittel fehlten, wie
auch manche Formen von Dosenfutter wie Linsen.&lt;br /&gt;
Thunfisch-Konserven oder Fertignudelgerichte waren aber noch reichlich 
vorhanden.&lt;/p&gt;

&lt;p&gt;Kurz gesagt: Ich kapiere nicht, was da wieder abgegangen ist in den Köpfen
meiner Mitmenschen.&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;Der neue Corona-Virenstamm zielt auf die Atemwege ab, 
nicht auf die Verdauung!!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Warum haben die Menschen jetzt also vor “mehr Scheiße zu bauen” als sonst??&lt;/p&gt;

&lt;h3 id=&quot;homeworking&quot;&gt;Homeworking&lt;/h3&gt;

&lt;p&gt;Aber das wirklich geile an unserer Viren-Epidemie ist, dass meine Firma, 
die uns Homeworking gerne ausreden möchte und lieber alle in den Büros sitzen
sehen möchte, alle ermutigt zu Hause zu bleiben.&lt;/p&gt;

&lt;p&gt;Noch besser ist, dass unsere IT Abteilung sogar Netzwerkzugänge in Windeseile
einrichten konnte, für die wir das letzte Jahr immer wieder gekämpft hatten
und am Ende mit sehr fadenscheinigen Argumenten abgelehnt wurden.&lt;/p&gt;

&lt;p&gt;Das wirft natürlich kein besonders gutes Licht auf jene Abteilungen, weil 
es jetzt so aussieht, als wären die Personen einfach nur zu faul gewesen,
die nötigen Schritte einzuleiten.&lt;br /&gt;
Doch wenn der Chef anruft und auf den Tisch haut, geht es plötzlich in 
5 Minuten.&lt;/p&gt;

&lt;p&gt;Und das Abhalten der Meetings per &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Teams&quot;&gt;MS Teams&lt;/a&gt; 
Konferenz ist einfach nur super.&lt;br /&gt;
Wir wurden teilweise schneller fertig als sonst und ich konnte mit 
stumm geschaltetem Wireless-Headset mehrfach aufs Klo gehen während Themen
besprochen wurden, und war dennoch auf dem Laufenden.&lt;/p&gt;

&lt;p&gt;Das klappt bei normalen Meetings im schlecht belüfteten Konferenzzimmer selten
so gut.&lt;/p&gt;

&lt;p&gt;Kurz gesagt ich finde es toll, was uns das Virus digital-technisch jetzt alles
ermöglicht, was bis vor kurzem mit “ineffizient” bis “unmöglich” abgestempelt 
wurde.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Natürlich darf man nicht vergessen, dass nun täglich die Zahlen der 
Verstorbenen steigen werden. Und das ist natürlich tragisch.&lt;br /&gt;
Auch meine Mutter und ihr Lebensgefährte gehören wegen des Alters und 
diverser Krankheiten zur Risikogruppe.&lt;/p&gt;

&lt;p&gt;Die nun gültige Ausgangs-Einschränkung bewirkt jedenfalls, dass weniger Autos
auf den Straßen fahren, was die Umwelt schont und das verordnete Verweilen
in den eigenen 4 Wänden führt dazu, dass Themen wie e-Learning und 
Home-Working endlich den Stellwert bekommen, den sie eigentlich schon seit
10 Jahren haben sollten.&lt;/p&gt;

&lt;p&gt;Ich will daher nicht dramatischen Entwicklungen der Pandemie kleinreden,
sondern stelle fest:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Es muss leider immer erst etwas “passieren”, bis man die Bremsen
des Fortschrittes lockert.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Schon letzte Woche bemerkte ich mit Freude in der Firma, dass sich 
neuerdings alle Männer nach dem Pinkeln die Hände waschen aus Angst
vor dem Virus.&lt;br /&gt;
Abgesehen davon, dass es traurig ist, dass Basis-Hygiene offenbar nicht
“jedermanns” Sache ist, halte ich das für einen echten Fortschritt!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Visual Leak Detector ohne Callstack</title>
   <link href="https://www.opengate.at/blog/2020/03/vld-msvc14/"/>
   <published>2020-03-15T12:00:00+01:00</published>
   <updated>2020-03-15T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2020/03/vld-msvc14</id>
   <category term="devel" />
   <summary type="text">Und alle paar Monate das gleiche Problem:


  Verdammt, den Fehler kenne ich … das hatte ich schon mal …
Wie war noch gleich die Lösung?


Unsere heutige Episode aus der Serie Was ich mir merken sollte heißt: 
“Visual Leak Detector ohne Callstack”
</summary>
   <content type="html">&lt;p&gt;Und alle paar Monate das gleiche Problem:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Verdammt, den Fehler kenne ich … das hatte ich schon mal …
Wie war noch gleich die Lösung?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Unsere heutige Episode aus der Serie &lt;em&gt;Was ich mir merken sollte&lt;/em&gt; heißt: 
“&lt;a href=&quot;http://kinddragon.github.io/vld/&quot;&gt;Visual Leak Detector&lt;/a&gt; ohne Callstack”
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Die erste Lektion heißt:&lt;/p&gt;

&lt;h3 id=&quot;voraussetzung-immer-die-neueste-version-installieren&quot;&gt;Voraussetzung: Immer die neueste Version installieren&lt;/h3&gt;

&lt;p&gt;Wenn man auf vielen Maschinen arbeitet, kommt es schon mal vor, dass
man z.B. für &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_7&quot;&gt;Windows 7&lt;/a&gt; 
eine Version herunterlädt (oder geladen und abgelegt hat), die super 
funktioniert.&lt;br /&gt;
Doch die gleiche Version produziert unter &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_10&quot;&gt;Windows 10&lt;/a&gt;
Crashes beim Start eines Programms.&lt;/p&gt;

&lt;p&gt;Die Lösung: &lt;em&gt;Neueste Version installieren&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Denn mit jeder neuen Version von &lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_Studio&quot;&gt;Visual Studio&lt;/a&gt;, 
der C Runtime oder dem Betriebssystemkern sind Anpassungen am 
&lt;a href=&quot;/blog/2019/03/leaks/&quot;&gt;Leak-Detector &lt;/a&gt; 
erforderlich. 
Das Teil “hackt” sich schließlich zwischen die &lt;a href=&quot;https://de.wikipedia.org/wiki/Programmierschnittstelle&quot;&gt;APIs&lt;/a&gt;
um Fehler zu finden, wenn da was nicht passt, wird das Tool ungewollt zur 
Malware, die jede Menge undefiniertes Verhalten und seltsame Crashes 
produzieren kann.&lt;/p&gt;

&lt;h3 id=&quot;problem-keine-debug-infos-beim-callstack-vorhanden&quot;&gt;Problem: Keine Debug Infos beim Callstack vorhanden&lt;/h3&gt;

&lt;p&gt;Das “geilste” Feature des Leak Detectors ist, dass er am Ende des Programms
den Allokierungs-Callstack des Leaks anzeigt (weil er den immer brav mitloggt).&lt;/p&gt;

&lt;p&gt;Und eben diese Aufrufliste wird mit Quellcode-Datei und Zeilennummer schön
ordentlich ausgegeben, damit Visual Studio per Doppelklick sofort zur 
Leak-Zeile springen kann.&lt;/p&gt;

&lt;p&gt;Das funktionierte von Studio 2005 bis 2012 “out-of-the-box”.
Doch seit Studio 2015 werden zwar Code-Adressen angezeigt, der Verweis zur
Quelldatei fehlt aber … folglich hilft einem die Info recht wenig.&lt;/p&gt;

&lt;p&gt;Es sieht dann so aus:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;WARNING: Visual Leak Detector detected memory leaks!
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;---------- Block 290 at 0x000000003222D1C0: 100 bytes ----------
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  Leak Hash: 0x47A1C106, Count: 1, Total 100 bytes
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  Call Stack (TID 11700):
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;    ntdll.dll!RtlAllocateHeap()
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;    vbincopy.exe!0x00007FF68312B5AA()
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;    vbincopy.exe!0x00007FF68312B32D()
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;    vbincopy.exe!0x00007FF68312EF9F()
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;    vbincopy.exe!0x00007FF6830E0F3E()
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h3 id=&quot;lösung-debug-info-vollständig-generieren&quot;&gt;Lösung: Debug Info VOLLSTÄNDIG generieren&lt;/h3&gt;

&lt;p&gt;Kurz gesagt:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Man muss bei den &lt;code&gt;Project Properties&lt;/code&gt; unter 
&lt;code&gt;Linker&lt;/code&gt; - &lt;code&gt;Debugging&lt;/code&gt; - &lt;code&gt;Generate Debug Info&lt;/code&gt; die Option&lt;br /&gt;
&lt;code&gt;Generate Debug Information optimized for sharing and publishing&lt;/code&gt;&lt;br /&gt;
aktivieren oder den Switch &lt;code&gt;/DEBUG:FULL&lt;/code&gt; anfügen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In den neueren Studio-Versionen wurde ein neues verkleinertes Format für
die guten alten PDB Dateien als Standard eingeführt.&lt;/p&gt;

&lt;p&gt;Damit kann der Detector nicht mehr Datei und Zeilennummer auflösen.
Mit der genannten Einstellung funktioniert aber wieder alles wie gewohnt.&lt;/p&gt;

&lt;p&gt;… und es sieht dann so aus:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;WARNING: Visual Leak Detector detected memory leaks!
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;---------- Block 290 at 0x00000000736EE2D0: 100 bytes ----------
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  Leak Hash: 0x36F1F623, Count: 1, Total 100 bytes
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  Call Stack (TID 16100):
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;    ntdll.dll!RtlAllocateHeap()
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;    new_array.cpp (29): vbincopy.exe!operator new[]()
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;    vbincopy.cpp (141): vbincopy.exe!gate::VBinCopy::Form_Closed() + 0xA bytes
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;    delegates.hpp (278): vbincopy.exe!gate::Delegate2&amp;lt;gate::ui::Form *,
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;               gate::ui::EventArg *&amp;gt;::method_dispatcher_impl&amp;lt;gate::VBinCopy&amp;gt;()
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;    delegates.c (37): vbincopy.exe!gate_delegate_invoke() + 0x14 bytes
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;&lt;em&gt;Ah, eine Allokation in Form_Closed()? Wozu denn das?&lt;/em&gt;&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Bin gespannt, wie lange es jetzt dauert, bis ich wieder vor einem 
“nicht funktionierenden” Leak Detector stehe und mich wieder frage: &lt;em&gt;“Warum?”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Es wäre eine Überlegung wert die Option &lt;code&gt;/DEBUG:FULL&lt;/code&gt; durch CMake hinzuzufügen.
Aber letztendlich nutze ich für die aktive Entwicklung im GATE Projekt 
ohnehin meine selbst erstellten Projektdateien, weil ich nicht immer CMake
bemühen möchte, wenn ich 2 neue Dateien hinzufüge.&lt;/p&gt;

&lt;p&gt;Und damit bleibt die Frage weiter aktiv:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Wie lange wird es wohl dauern, bis ich diese Einstellung wieder vergesse.&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>Corona: Wir werden alle sterben</title>
   <link href="https://www.opengate.at/blog/2020/03/corona/"/>
   <published>2020-03-13T12:00:00+01:00</published>
   <updated>2020-03-13T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2020/03/corona</id>
   <category term="general" />
   <summary type="text">Die ganze Welt dreht durch und ich drehe mich auch mit.

Ist das nicht bescheuert, wenn alle von einem erwarten ebenso nervös zu sein?

Beinahe habe ich ein schlechtes Gewissen, weil mir die ganze Sache ziemlich 
gleichgültig ist … zumindest noch …
</summary>
   <content type="html">&lt;p&gt;Die ganze Welt dreht durch und ich drehe mich auch mit.&lt;/p&gt;

&lt;p&gt;Ist das nicht bescheuert, wenn alle von einem erwarten ebenso nervös zu sein?&lt;/p&gt;

&lt;p&gt;Beinahe habe ich ein schlechtes Gewissen, weil mir die ganze Sache ziemlich 
gleichgültig ist … zumindest noch …
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Tja, jetzt ist es so weit, das Todesvirus &lt;a href=&quot;https://de.wikipedia.org/wiki/COVID-19&quot;&gt;COVID-19&lt;/a&gt;
gehörig zur CORONA Familie hat jetzt also auch schon kleine Dörfer am Land 
erreicht.&lt;br /&gt;
Eine Freundin meiner Mutter hat eine Enkelin, die sich angesteckt haben soll.&lt;/p&gt;

&lt;p&gt;Also Zeit für Panik … oder nicht?&lt;/p&gt;

&lt;p&gt;Natürlich soll man nicht herunterspielen, dass jedes Jahr tausende vor allem
vorerkrankte Menschen an Grippevirusstämmen sterben und dass das neue 
Corona Virus ebenso Gefahren birgt.&lt;/p&gt;

&lt;p&gt;Doch aktuell denke ich mir, dass mit der Sperrung von Schulen und dem Verbot
von Veranstaltungen mit über 100 Personen die ganze Sache doch etwas zu weit
geht.&lt;/p&gt;

&lt;p&gt;Nach Januar, als Städte in China bereits stark an Corona zu leiden begannen 
und wir uns noch in Sicherheit wiegten, ging die Meldung in meiner früheren 
Heimatgemeinde um, dass die halbe Schulbelegschaft (wie fast jedes Jahr) 
geschlossen im Krankenbett lag.&lt;br /&gt;
Denn wenn ein Kind die &lt;a href=&quot;https://de.wikipedia.org/wiki/Windpocken&quot;&gt;Windpocken&lt;/a&gt; 
oder &lt;a href=&quot;https://de.wikipedia.org/wiki/Influenza&quot;&gt;Influenza&lt;/a&gt; einschleppt, hat 
es eine Woche später die halbe Klasse.&lt;br /&gt;
… das war auch zu meiner Kinderzeit so.&lt;br /&gt;
Zwei bis vier Wochen später sind wieder alle anwesend und das Leben geht
weiter.&lt;/p&gt;

&lt;p&gt;Jetzt mag COVID-19 einen etwas schwereren Krankheitsverlauf haben und 
besonders ältere Mitmenschen stärker treffen, doch man soll nicht vergessen, 
dass Risikogruppen Tag aus Tag ein an “kleineren” Infektionen versterben.&lt;/p&gt;

&lt;p&gt;Wer böses denkt, wittert hier natürlich eine Verschwörung.&lt;/p&gt;

&lt;p&gt;Wie war das mit der &lt;a href=&quot;https://de.wikipedia.org/wiki/Vogelgrippe_H5N1&quot;&gt;Vogelgrippe&lt;/a&gt;? 
Sofort wurden Unsummen in Impfstoffe investiert um dann festzustellen, 
die Vogelgrippe ist nur halb so gefährlich wie die “normale” Grippe und so 
schnell wie die Welt damals panisch wurde, so schnell hat sie die Vogelgrippe
auch wieder vergessen.&lt;/p&gt;

&lt;p&gt;Es werden also wieder einige Leute reicher werden, nämlich all jene, die 
“schnelle Hilfsmittel” anbieten. Desinfektionsmittel sind schon lange 
vergriffen und im Supermarkt sind erstmals die Nudeln ausgegangen, weil die 
ersten Hamsterkäufe eingesetzt haben.&lt;/p&gt;

&lt;p&gt;Parallel dazu spielt natürlich der Aktienkurs verrückt. Grund genug gleich 
mal ein paar “unwichtige” Arbeiter zu entlassen um zu sparen.&lt;/p&gt;

&lt;p&gt;Und unsere Regierung, die bisher nicht erklären konnte, wie sie die nächsten
Steuerentlastung realisieren will, kann jetzt mit ernster Miene
sagen: “Wegen der Corona-Krise können wir leider auf keinen Cent verzichten.”&lt;/p&gt;

&lt;p&gt;Ich setze mich also weiter in den Bus, fahre zur Arbeit und rede mit Kollegen.
Mama werde ich auch nicht verstoßen, nur weil sie jemanden kennt, der jemanden
kennt, der erkrankt ist und meine Hardwarepäckchen aus China werde ich auch 
weiter bestellen.&lt;/p&gt;

&lt;p&gt;Sollte mich tatsächlich ein solches Virus besuchen, dann werde ich eben 
(wie alle paar Jahre) zu Hause bleiben, Hühnersuppe aus Dosen schlürfen und 
die Sache aussitzen. Und wenn es doch schlimmer werden sollte, dann vertraue
ich auf unser Gesundheitssystem, dass mir - so hoffe ich - mit Rat und guter
Medizin zur Seite stehen wird.&lt;/p&gt;

&lt;p&gt;Ich halte nichts von dieser Weltuntergangsstimmung.&lt;br /&gt;
Wir mit Hirn und Verstand zu Hause im Bett bleibt wenn er Fieber hat und
nicht zur Arbeit geht um darüber zu jammern, wie schlecht es ihm geht,
der wird auch keinen anderen anstecken und so die Ausbreitung eindämmen.&lt;/p&gt;

&lt;p&gt;Da macht mir die Wirtschaft und die weltweite Panik schon mehr Sorgen.
Wer weiß wie lange es dauern wird, bis alle Covid-19 bedingten Arbeitslosen
wieder eine Job gefunden haben …&lt;/p&gt;

&lt;p&gt;Infektionskrankheiten erleben wir jährlich und nachdem uns der Maja-Kalender 
nicht umbringen konnte, werden es auch Viren nicht von heute auf morgen 
schaffen die Menschheit auszurotten.&lt;/p&gt;

&lt;p&gt;Gemessen an dem Schaden, den Menschen tätlich an der Natur anrichten und 
gegen den viel zu wenig unternommen wird, sind die Alarmsirenen bei jedem 
Husten übertrieben.&lt;br /&gt;
Tja, bleibt nur zu hoffen, dass ich die aktuelle Situation nicht unterschätze, 
aber mich tagtäglich fertig zu machen bringt genau so nichts.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Etwas Gutes hat die Pandemie aber:&lt;/p&gt;

&lt;p&gt;Die Leute waschen sich jetzt endlich mehr und intensiver die Hände.
Aber dass es dafür erst eine Massenpanik braucht und warum das nicht für 
jeden selbstverständlich ist … ja, dieses Rätsel muss ich wohl noch lösen …&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>varargs vs. arrays</title>
   <link href="https://www.opengate.at/blog/2020/03/varargs-vs-arrays/"/>
   <published>2020-03-11T12:00:00+01:00</published>
   <updated>2020-03-11T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2020/03/varargs-vs-arrays</id>
   <category term="devel" />
   <summary type="text">Nachdem ich im GATE Projekt die C-Delegate-Lösung 
mit varargs umgesetzt 
hatte, war ich glücklich diese Methode einmal “zielführend” wo eingesetzt zu 
haben.

Wenn man aber reguläre APIs mit varargs überfüttert, schafft man sich damit 
aber mehr Probleme als Vorteile.
Und das kann man am Beispiel GTK+ 
gut nachvollziehen.

</summary>
   <content type="html">&lt;p&gt;Nachdem ich im GATE Projekt die &lt;a href=&quot;/blog/2019/07/c-delegates/&quot;&gt;C-Delegate-Lösung&lt;/a&gt; 
mit &lt;a href=&quot;https://en.wikipedia.org/wiki/Variadic_function#In_C&quot;&gt;varargs&lt;/a&gt; umgesetzt 
hatte, war ich glücklich diese Methode einmal “zielführend” wo eingesetzt zu 
haben.&lt;/p&gt;

&lt;p&gt;Wenn man aber reguläre APIs mit &lt;code&gt;varargs&lt;/code&gt; überfüttert, schafft man sich damit 
aber mehr Probleme als Vorteile.&lt;br /&gt;
Und das kann man am Beispiel &lt;a href=&quot;https://de.wikipedia.org/wiki/GTK_(Programmbibliothek)&quot;&gt;GTK+&lt;/a&gt; 
gut nachvollziehen.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Dass man beliebig viele Argumente mit beliebig unterschiedlichen Typen an 
eine Funktion übergeben kann, hört sich auf den ersten Blick verlockend an.&lt;/p&gt;

&lt;p&gt;Eine Funkion kann damit unterschiedlichste Aufrufszenarien abdecken.&lt;/p&gt;

&lt;p&gt;Bestes Beispiel:&lt;/p&gt;
&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;printf(format, ...);
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Leider hat dieses Vorgehen aber einen großen Nachteil: Es ist “hard-coded”
und damit nicht zur Laufzeit abänderbar.&lt;/p&gt;

&lt;p&gt;Ob &lt;code&gt;printf()&lt;/code&gt; jetzt einen &lt;code&gt;char*&lt;/code&gt; oder einen &lt;code&gt;int&lt;/code&gt; abhandelt, wird fest in
Code gegossen, und man kann zur Laufzeit die Aufrufparameter nicht abändern. 
Da müsste man schon für jeden erdenklichen Fall per &lt;code&gt;if&lt;/code&gt; eine Verzweigung 
schaffen.&lt;/p&gt;

&lt;p&gt;Für solche Fälle nutzt man daher besser keine &lt;code&gt;varargs&lt;/code&gt;, sondern
Arrays von &lt;em&gt;variablen Typen&lt;/em&gt;, wie z.B.: Unions, &lt;code&gt;boost::any&lt;/code&gt; oder &lt;code&gt;void*&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;GTK+ nutzt z.B.: bei seinen Methoden für das Model-Controller-View Schema
einige APIs mit &lt;code&gt;varargs&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Hier kommen oft Parameter-Gruppen zum Einsatz die folgendes Schema umsetzen:&lt;/p&gt;
&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt; foo(&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;* obj_ptr, ...);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;...
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;foo(obj_ptr, NOW_COMES_A, a, NOW_COMES_B, b, NOW_COMES_C, c, END_MARK);
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Solche &lt;code&gt;NOW_COMES_*&lt;/code&gt; Identifier sind meist Integer die man leicht durch Variablen
ersetzen kann. Doch die Typen der eigentlichen Argumente sind feststehend.&lt;/p&gt;

&lt;p&gt;Folgt das Ganze aber dem Schema:&lt;/p&gt;
&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;struct&lt;/span&gt; my_param
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; param_type_id;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;union&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  {
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;    type_a_t        param_type_a;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;    type_b_t        param_type_b;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;    type_c_t        param_type_c;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;    type_d_t        param_type_d;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;};
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt; foo(&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;* obj_ptr, &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;struct&lt;/span&gt; my_param* params, size_t param_count);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;...
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;struct&lt;/span&gt; my_param params[&lt;span style=&quot;color:#00D&quot;&gt;3&lt;/span&gt;];
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;...
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;foo(obj_ptr, params, &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;sizeof&lt;/span&gt;(params) / &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;sizeof&lt;/span&gt;(params[&lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;]));
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;dann können die Parameter zur Laufzeit “frei” zusammengestellt werden.
Man befüllt das Array wie man will in Sachen Anzahl und Typen.&lt;/p&gt;

&lt;p&gt;Und das ist ein wichtige Erkenntnis. Während &lt;code&gt;varargs&lt;/code&gt; auf den ersten Blick
einfach und elegant wirken, fehlt ihnen ein großes Maß an Flexibilität beim
dynamischen Zusammenstellen von Parametern.&lt;/p&gt;

&lt;p&gt;Bei der Arbeit mit GTK+ ist mir dieses Schema wieder untergekommen, nämlich
beim Erstellen von Store Objekten für das 
&lt;a href=&quot;https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller&quot;&gt;Model-View-Controller&lt;/a&gt;
Konstrukt bei Listviews.&lt;br /&gt;
Hier wäre das Befüllen des Models mit &lt;code&gt;vararg&lt;/code&gt; Funktionen problematisch, weil
zur Entwurfszeit vielleicht noch gar nicht feststeht, wie viele Spalten die 
Listview anzeigen soll.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Die Codebeispiele für die GTK Listview hatten mich befürchten lassen, dass
alles über &lt;code&gt;vararg&lt;/code&gt; Funktionen gemacht werden muss.&lt;br /&gt;
Zum Glück fand ich in der Doku schnell auch alternative Funktionen um das
Listview-Modell zu manipulieren.&lt;/p&gt;

&lt;p&gt;Offenbar waren sowohl die Vorteile wie auch die Nachteile von &lt;code&gt;varargs&lt;/code&gt; 
auch den GTK+ Leuten bekannt und sie haben deshalb beide Varianten 
implementiert.&lt;/p&gt;

&lt;p&gt;Auch im GATE Projekt werden für Datenausgaben in Strings und Stream 
&lt;code&gt;vararg&lt;/code&gt;-Print-Routinen benutzt. Aber auch hier sind diese nur vereinfachende
Weiterleitungen auf Funktionen mit festen Argumenten.&lt;/p&gt;

&lt;p&gt;Irgendwie schön zu sehen, dass viele Entwickler in unterschiedlichen Projekten
ohne sich zu kennen immer wieder auf die gleichen Ergebnisse kommen, wenn
es um Schnittstellendefinition geht.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>double free wegen const std::string</title>
   <link href="https://www.opengate.at/blog/2020/03/double-free/"/>
   <published>2020-03-08T12:00:00+01:00</published>
   <updated>2020-03-08T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2020/03/double-free</id>
   <category term="devel" />
   <summary type="text">Nun gut, wenn mir wieder mal die 
GCC Fehlermeldung


  double free or corruption


um die Ohren fliegt, dann weiß ich in Zukunft, wie ich reagieren soll.

… aber dieses Wochenende hat mir jene Nachricht sprichwörtlich versaut!
</summary>
   <content type="html">&lt;p&gt;Nun gut, wenn mir wieder mal die 
&lt;a href=&quot;https://de.wikipedia.org/wiki/GNU_Compiler_Collection&quot;&gt;GCC&lt;/a&gt; Fehlermeldung&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;code&gt;double free or corruption&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;um die Ohren fliegt, dann weiß ich in Zukunft, wie ich reagieren soll.&lt;/p&gt;

&lt;p&gt;… aber dieses Wochenende hat mir jene Nachricht sprichwörtlich versaut!
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;em&gt;Gleich die Lösung am Anfang für alle, denen das auch schon passiert ist:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Voraussetzung:
    &lt;ul&gt;
      &lt;li&gt;Wir arbeiten mit GCC unter &lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;Wir nutzen eine statische Bibliothek (*.a) mit einigen Konstanten.&lt;/li&gt;
      &lt;li&gt;Die statische Bibliothek wird in eine dynamische Bibliothek (*.so) 
eingebunden.&lt;/li&gt;
      &lt;li&gt;Die statische Bibliothek wird außerdem in ein Programm eingebunden, 
das die dynamische Bibliothek ebenso lädt und nutzt.&lt;/li&gt;
      &lt;li&gt;Am Ende des Programms kommt es zur Fehlermeldung 
&lt;code&gt;double free or corruption&lt;/code&gt;, die manchmal das Beenden verhindert 
und/oder das Programm einfrieren lässt.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Lösung:
    &lt;ul&gt;
      &lt;li&gt;Alle globalen konstanten Text-Variablen des Typs 
&lt;code&gt;const std::string&lt;/code&gt; durch &lt;code&gt;char const* const&lt;/code&gt; ersetzen&lt;/li&gt;
      &lt;li&gt;Eventuell auch alle anderen globalen Objekte, die im Konstruktor 
oder Destruktor Code allokieren und freigeben, 
durch “flache” Alternativen ersetzen&lt;/li&gt;
      &lt;li&gt;Oder: Globale Objekte nicht frei herumliegen lassen, sondern als 
statische Objekte (&lt;code&gt;static type_t const instance;&lt;/code&gt;) in eine Funktion packen,
die eine Referenz auf ein solches “verstecktes” globales Objekt 
zurückgeben.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;und-hier-die-ganze-geschichte&quot;&gt;Und hier die ganze Geschichte&lt;/h3&gt;

&lt;p&gt;Ich arbeite an Kommunikationsplugins, die je nach Projekt unterschiedliche
Daten transportieren sollen. Doch alle Projekte nutzen das gleiche 
Container-Format.&lt;/p&gt;

&lt;p&gt;Damit kommt der Container-Code in eine statische Lib 
und jedes Projektimplementierung wird eine 
&lt;a href=&quot;https://en.wikipedia.org/wiki/Dynamic-link_library&quot;&gt;DLL (Windows)&lt;/a&gt; oder SO 
(Linux), die auf der statischen Lib aufbaut und die projektabhängigen 
Spezialitäten anfügt.&lt;/p&gt;

&lt;p&gt;Und das funktionierte “eigentlich” ganz gut so.&lt;/p&gt;

&lt;p&gt;Um die Features zu testen wird (wie so oft) ein Unit-Test für jedes Projekt
angelegt, der alle Funktionen ausführen und abprüfen soll.&lt;/p&gt;

&lt;p&gt;Und eben diese Unit-Tests weigerten sich plötzlich nach einigen Codeupdates
korrekt zu terminieren. Die Tests liefen alle, doch beim Beenden kam es zur
gefürchteten Nachricht &lt;code&gt;double free or corruption&lt;/code&gt;, was der Buildserver 
gar nicht gern sehen wollte.&lt;/p&gt;

&lt;p&gt;Das Ganze war ein reines Linux/GCC Problem, denn unter Windows mit
&lt;a href=&quot;https://en.wikipedia.org/wiki/Microsoft_Visual_C%2B%2B&quot;&gt;MSVC&lt;/a&gt; gab es solche
Exit-Crashes nicht.&lt;/p&gt;

&lt;p&gt;Mit Hilfe der &lt;a href=&quot;/blog/2019/03/leaks/&quot;&gt;Address-Sanitizer&lt;/a&gt; 
Funktionen wurde die Fehlermeldung zwar etwas konkreter, nämlich dass es sich 
wohl um globale Variablen handelte, die vor &lt;code&gt;main&lt;/code&gt; erzeugt und nach &lt;code&gt;main&lt;/code&gt; 
zerstört wird und dass zum ersten Erzeugen eine private Methode von 
&lt;code&gt;std::string&lt;/code&gt; im Einsatz war …&lt;br /&gt;
aber aus der Speicheradresse konnte ich überhaupt keine Rückschlüsse auf 
den wahren Übeltäter ziehen.&lt;/p&gt;

&lt;p&gt;Obwohl ich es eigentlich nicht erwartet hatte (oder nicht wahr haben wollte),
wendete sich mein Verdacht mehr und mehr auf die statische Bibliothek zu.&lt;/p&gt;

&lt;p&gt;Ich bin ein bekennender Fan von &lt;a href=&quot;/blog/2018/10/antistatic/&quot;&gt;statischen&lt;/a&gt;
Bibliotheken und würde gerne viele dynamische Libs durch statische ersetzen.&lt;br /&gt;
Doch mir ist wohl bewusst, dass gerade beim Mischen von statischen und 
dynamische Code, besonders bei C++ Objekten, Fehler auftreten, die 
schwer zu finden sind.&lt;/p&gt;

&lt;p&gt;Und so fand ich bei einer Suche im Netz den Beitrag
&lt;a href=&quot;https://gcc.gnu.org/ml/gcc-help/2010-10/msg00248.html&quot;&gt;Global variable in static library - double free or corruption error&lt;/a&gt;
wo schon vor 10 Jahren gemeldet wurde, dass der GCC gerne mal Symbole aus 
zwei Quellen in einen Speicherbereich zusammenlegt.&lt;/p&gt;

&lt;p&gt;Wenn also meine statische Container-Bibliothek einmal in die SO und einmal
direkt ins Programm geladen wird, so würde ich mir erwarten, dass die globalen
Objekt zweimal vorhanden sind.&lt;br /&gt;
Doch der GCC Linker erkennt den gemeinsamen Ursprung und legt sie zusammen.
Leider gilt das aber nicht für Konstruktoren und Destruktoren.&lt;/p&gt;

&lt;p&gt;Und deshalb werden die globalen Pseudokonstanten zweimal konstruiert 
(was “nur” ein Memory Leak wäre), aber sie werden auch am Ende zweimal 
zerstört, wobei der erste &lt;code&gt;operator delete&lt;/code&gt; gut geht und der zweite dann mit
kaputten Zeigern und falschen Speicherbereichen konfrontiert wird.&lt;/p&gt;

&lt;h3 id=&quot;ende-gut-alles-gut&quot;&gt;Ende gut, alles gut&lt;/h3&gt;

&lt;p&gt;Also habe ich einfach mal schnell alle Zeilen des Typs&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt; std::&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;string&lt;/span&gt; SomeClass::some_global_constant(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Hello World&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;);
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;durch&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt;* &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt; SomeClass::some_global_constant(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Hello World&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;);
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;ersetzt.&lt;/p&gt;

&lt;p&gt;Denn “die guten alten C-Strings” liegen flach im Datensegment und brauchen
keine Kon- und Destruktoren. Zweimal freigeben gibt es hier einfach nicht.&lt;/p&gt;

&lt;p&gt;Und schon waren die Unit-Tests und Linux wieder lauffähig.&lt;br /&gt;
… und zumindest der letzte Teil des Wochenendes ist gerettet.&lt;/p&gt;

&lt;p&gt;Das einzig ungute an der ganze Sache ist:&lt;br /&gt;
Weil ich durch das GATE Projekt aktuell viel C-Syntax (auch in C++) einsetze, 
bekomme ich (zu Recht) im Code-Review zu hören:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ersetze bitte deine &lt;code&gt;char const* const&lt;/code&gt; durch &lt;code&gt;std::string const&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Und das wäre ja auch die “schönere” Variante für C++ …
aber manchmal sind die “guten alten C Strukturen” eben doch die 
stabilisierenden Elemente … vor allem, wenn man statische und dynamische 
Bibliotheken mixt.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>VPN - Soll ich wieder eines aufbauen?</title>
   <link href="https://www.opengate.at/blog/2020/03/vpn/"/>
   <published>2020-03-07T12:00:00+01:00</published>
   <updated>2020-03-07T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2020/03/vpn</id>
   <category term="software" /><category term="retro" />
   <summary type="text">Corona Covid-19 macht’s möglich: 
Wir arbeiten von zu Hause!

Und wie? Natürlich per VPN. 
Dann sieht es zu Hause so aus, als stünde unser Laptop mitten in der Firma 
und “sieht” alle dortigen Ressourcen.

Hmm … eigentlich könnte ich das mit “meinem” Netzwerk auch wieder mal 
machen …
</summary>
   <content type="html">&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/COVID-19&quot;&gt;Corona Covid-19&lt;/a&gt; macht’s möglich: 
Wir arbeiten von zu Hause!&lt;/p&gt;

&lt;p&gt;Und wie? Natürlich per &lt;a href=&quot;https://de.wikipedia.org/wiki/Virtual_Private_Network&quot;&gt;VPN&lt;/a&gt;. 
Dann sieht es zu Hause so aus, als stünde unser Laptop mitten in der Firma 
und “sieht” alle dortigen Ressourcen.&lt;/p&gt;

&lt;p&gt;Hmm … eigentlich könnte ich das mit “meinem” Netzwerk auch wieder mal 
machen …
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;damals-&quot;&gt;Damals …&lt;/h3&gt;

&lt;p&gt;VPNs sind für mich eigentlich ein alter Hut.&lt;br /&gt;
Als ich so um 2005 mit &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_Server_2003&quot;&gt;Windows Server 2003&lt;/a&gt;
meine eigene &lt;a href=&quot;https://de.wikipedia.org/wiki/Active_Directory&quot;&gt;AD-Domäne&lt;/a&gt;
erstellt hatte, war ein VPN-Zugang ebenso Pflicht.&lt;/p&gt;

&lt;p&gt;Was heute vermutlich als “Wahnsinn” abgestempelt wird, war damals
für mich ganz normal:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Der Windows Server hing direkt (also ohne Hardware Firewall) am Internet&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Point-to-Point_Tunneling_Protocol&quot;&gt;PPTP&lt;/a&gt; 
wurde als VPN Protokoll gewählt&lt;/li&gt;
  &lt;li&gt;Authentifiziert wurde direkt über das Active Directory 
… also mit meinem regulären Benutzerkonto.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Und warum war das ein “Wahnsinn”?&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Die Windows-Server Firewall gilt heute als unzureichend … gut darüber
kann man streiten, denn bei mir hat sie “funktioniert”, allerdings wäre
es mir auch kaum aufgefallen, wenn sie jemand durchbrochen hätte.&lt;/li&gt;
  &lt;li&gt;Nach 2010 wurden einige Bugs im PPTP Protokoll publik, die aber schon 
Jahre zuvor diskutiert wurden. Es ging darum, dass es einfach möglich 
sei, die Verschlüsselung im VPN zu brechen in dem man nur eine Weile
den Datenstrom mitschneiden und analysieren musste.&lt;/li&gt;
  &lt;li&gt;Dass die Authentifizierung mit AD Accounts stattfand war der Einfachheit
geschuldet. Natürlich nutzte ich eigene VPN-Accounts und nicht mein
Arbeitskonto, doch ein Seiteneffekt vom Windows VPN war, dass mit einem
akzeptierten Login der verbundene PC bereits “Domain-User” Rechte hatte.
Man konnte bereits auf nicht eigens geschützte Ressourcen zugreifen, ohne
ein weiteres Passwort zu kennen.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;unternehmenszugänge&quot;&gt;Unternehmenszugänge&lt;/h3&gt;

&lt;p&gt;In den Firmen, in den ich bereits gearbeitet habe, gehörten VPNs meist zum 
Standard. Die größeren nutzten Kombinationen aus Hard- bzw. SoftToken
Lösungen für die Authentifizierung, während die kleineren bei Standard Windows
VPNs via PPTP und &lt;a href=&quot;https://de.wikipedia.org/wiki/Layer_2_Tunneling_Protocol&quot;&gt;L2TP&lt;/a&gt; 
verblieben.&lt;/p&gt;

&lt;p&gt;Die Unternehmenslösungen, die meist mit &lt;a href=&quot;https://de.wikipedia.org/wiki/Cisco_Systems&quot;&gt;Cisco&lt;/a&gt; 
zu tun hatten, sind deshalb erwähnenswert, weil sie ein für die Firmen 
wichtiges Feature forcieren, nämlich das Sperren von lokalen Verbindungen 
während der VPN Sitzung.&lt;/p&gt;

&lt;p&gt;Man ist also quasi “wirklich” nur noch im Firmennetzwerk und kann weder
lokale Rechner noch das Internet von zu Hause aus kontaktieren.&lt;br /&gt;
Das führt natürlich wieder zu Problemen, wenn man den eigenen Netzwerkdrucker
nicht mehr zum Drucken nutzen kann, oder aber die Web Anfragen von privaten 
Apps plötzlichen über den Firmen-Proxy laufen, der alles fleißig mitloggt.&lt;/p&gt;

&lt;p&gt;Als Administrator verstehe ich diese Vorgehensweise jedoch, schließlich möchte
man sich ja nicht mit jeder neuen VPN Verbindung eine Brücke von außen ins
Unternehmen hinein bauen.&lt;/p&gt;

&lt;h3 id=&quot;und-was-nun&quot;&gt;Und was nun?&lt;/h3&gt;

&lt;p&gt;Auch wenn ich mich vor gezielten Hackerangriffen nicht zu fürchten brauche
weil ich nichts Relevantes auf meinen Maschinen horte, werde ich vermutlich
keinen Windows Server mehr direkt mit VPN Aufgaben betrauen.&lt;br /&gt;
Zwar vertraue ich auf Microsoft grundsätzlich, dennoch werden genau wegen 
seiner Verbreitung viele automatisierte Attacken gegen dessen Protokolle
und Funktionen gefahren … und es wäre doch peinlich, wenn gerade ich so 
zum Opfer werden würde.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/OpenVPN&quot;&gt;OpenVPN&lt;/a&gt; am &lt;a href=&quot;https://de.wikipedia.org/wiki/Raspberry_Pi&quot;&gt;Raspberry PI&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Das wäre also meine Vorstellung: eine Netzwerkbrücke über OpenVPN, die einer
meiner älteren Raspberry PIs für wenig Strom bereitstellt.&lt;br /&gt;
Bisher hatte ich immer nur mit Passwörtern bzw. Pre-Shared Keys zu tun,
aber wenn ich hier neu starte, sollten es Zertifikate werden.&lt;br /&gt;
Mal sehen, wie gut bzw. schlecht sich das einrichten lässt.&lt;/p&gt;

&lt;p&gt;Wenn endlich mal Zeit bleibt so etwas aufzubauen und alles auch gut 
funktioniert, gibt es sicher einen weiteren Beitrag dazu …&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Fun-Fact am Rande: VPN-Routing ins Firmennetzwerk.&lt;/p&gt;

&lt;p&gt;Als ich die Firmen-IT-Administration unterstützt prüfte ich gelegentlich auch 
die  Firewall Logs im Unternehmen.
Eines Tages fiel mir dort eine Häufung von Aufrufen einer Pornoseite auf.
Ich kann mir nicht vorstellen, dass jemand in der Firma solche Inhalte aufruft,
doch es passiert leicht, dass jemand per VPN “noch schnell was erledigen will”
und danach den VPN-Disconnect vergisst.&lt;br /&gt;
Tja und dann laufen ALLE Anfragen eben über die Infrastruktur der Firma.&lt;/p&gt;

&lt;p&gt;Also aufpassen, wer mit VPN arbeitet. Immer schön zwischen beruflichen und
privaten Surfen trennen … oder der Admin erfährt brisante “Details”.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>DllMain unter Linux</title>
   <link href="https://www.opengate.at/blog/2020/03/dllmain/"/>
   <published>2020-03-01T12:00:00+01:00</published>
   <updated>2020-03-01T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2020/03/dllmain</id>
   <category term="devel" />
   <summary type="text">Windows-API Nutzer kennen 
natürlich die globale Funktion DllMain, die vom Betriebssystem automatisch
beim Laden und Entladen einer DLL 
ausgeführt wird. (Dass das auch bei jedem neuen Thread geschieht lassen wir 
hier mal unter den Tisch fallen.)

Und Linux? Kann man auch in Linux 
erzwingen, dass Code ausgeführt wird, ohne dass explizit eine Funktion 
aufgerufen wird?
</summary>
   <content type="html">&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Windows_API&quot;&gt;Windows-API&lt;/a&gt; Nutzer kennen 
natürlich die globale Funktion &lt;code&gt;DllMain&lt;/code&gt;, die vom Betriebssystem automatisch
beim Laden und Entladen einer &lt;a href=&quot;https://en.wikipedia.org/wiki/Dynamic-link_library&quot;&gt;DLL&lt;/a&gt; 
ausgeführt wird. (Dass das auch bei jedem neuen Thread geschieht lassen wir 
hier mal unter den Tisch fallen.)&lt;/p&gt;

&lt;p&gt;Und &lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt;? Kann man auch in Linux 
erzwingen, dass Code ausgeführt wird, ohne dass explizit eine Funktion 
aufgerufen wird?
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Ein erfahrener &lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B&quot;&gt;C++&lt;/a&gt; Entwickler käme
jetzt auf die Idee, dass “globale” Objekte die Lösung wären.&lt;br /&gt;
Denn der Standard garantiert, dass diese vor dem Aufruf von &lt;code&gt;main&lt;/code&gt; konstruiert
und nach dem Verlassen von &lt;code&gt;main&lt;/code&gt; zerstört werden. Also etwas Code in den
&lt;a href=&quot;https://de.wikipedia.org/wiki/Konstruktoren_und_Destruktoren&quot;&gt;Konstruktor und Destruktor&lt;/a&gt; 
und wir sind fertig …&lt;/p&gt;

&lt;p&gt;Allerdings steht im C/C++ Standard nichts über DLLs oder SOs, also 
Bibliotheken, die erst zur Laufzeit geladen und entladen werden.&lt;/p&gt;

&lt;p&gt;Zum Glück haben alle mir bekannten Compiler Hersteller diesen undefinierten
Bereich genutzt und mit jener Regel ausgefüllt:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Globale Objekte werden beim Laden die Bibliothek konstruiert noch bevor
die Lade-Routine (&lt;code&gt;LoadLibrary&lt;/code&gt; bzw. &lt;code&gt;dlopen&lt;/code&gt;)
zurückkehrt. Und sie werden ebenso zerstört, bevor das Entladen
(&lt;code&gt;FreeLibrary&lt;/code&gt; bzw. &lt;code&gt;dlclose&lt;/code&gt;) abgeschlossen ist.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Natürlich gibt es keine Reihenfolge, wie das ablaufen soll, außer dass das 
Ausnullen von globalen Datenfeldern noch vor den Konstruktoren stattfindet.&lt;/p&gt;

&lt;p&gt;Doch Betriebssysteme wissen nichts von C++ Objekten, also wie läuft das 
intern ab?&lt;/p&gt;

&lt;p&gt;Nun, ein Blick in die Implementierung der C Runtime hilft einem da weiter:&lt;/p&gt;

&lt;h3 id=&quot;windows&quot;&gt;Windows&lt;/h3&gt;

&lt;p&gt;Unter Windows führt das System in Wahrheit nicht &lt;code&gt;DllMain&lt;/code&gt; aus, sondern
&lt;code&gt;CRTDllMain&lt;/code&gt;. Und diese Funktion implementieren alle Windows Compiler 
automatisch mit Code, der die Liste der globalen Objekte durchgeht und 
deren Konstruktoren aufruft, nachdem elementare CRT Initialisierungsroutinen
durchgelaufen sind.&lt;br /&gt;
Ist das erledigt, wird die “programmierbare” &lt;code&gt;DllMain(..., DLL_PROCESS_ATTACH, ...)&lt;/code&gt; aufgerufen.&lt;/p&gt;

&lt;p&gt;Beim Entladen läuft das ganze rückwärts ab.
&lt;code&gt;CRTDllMain(..., DLL_PROCESS_DETACH, ...)&lt;/code&gt; ruft zuerst “unsere” &lt;code&gt;DllMain&lt;/code&gt; auf,
um im Anschluss alle globalen Objekte per Destruktor-Funktion zu zerstören.&lt;/p&gt;

&lt;h3 id=&quot;linux&quot;&gt;Linux&lt;/h3&gt;

&lt;p&gt;Das unter Linux verbreitete &lt;a href=&quot;https://en.wikipedia.org/wiki/Executable_and_Linkable_Format&quot;&gt;ELF Format&lt;/a&gt; 
für ausführbare Binärdateien beinhaltet Spezifikationen für besondere 
Sektionen (&lt;code&gt;.ctors&lt;/code&gt; und &lt;code&gt;.dtors&lt;/code&gt;). Wenn der Linker dort Funktionen ablegt, 
werden diese beim Laden und Entladen der Bibliothek hintereinander ausgeführt.&lt;/p&gt;

&lt;p&gt;Im GCC erreicht man den Eintrag einer Funktion in solche Sektionen mit den
Attributen &lt;code&gt;__attribute__((constructor))&lt;/code&gt; und &lt;code&gt;__attribute__((destructor))&lt;/code&gt;.&lt;br /&gt;
Linux schreibt selbst also keinen binären Standard vor, doch an dieser Stelle 
springt der GCC ein und setzt einen de-facto Standard&lt;/p&gt;

&lt;p&gt;Es gibt somit keine sichtbare zentrale Funktion (wie &lt;code&gt;DllMain&lt;/code&gt;), die man 
implementieren kann, sondern man schreibt sich einfach selbst Funktionen wie:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt; __attribute__((constructor)) SO_init()
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;/* do some global initialization */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;}
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt; __attribute__((destructor)) SO_uninit()
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;/* do some global cleanup */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Für globale C++ Objekte legt der GCC automatisch entsprechende 
Funktionseinträge an.&lt;/p&gt;

&lt;h3 id=&quot;wozu-braucht-man-das&quot;&gt;Wozu braucht man das?&lt;/h3&gt;

&lt;p&gt;Es herrscht in einigen (fremden) Projekten die Meinung vor:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;DllMain sollte nicht benutzt werden, da es nicht auf Linux portiert werden
kann.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Nun, das stimmt nicht.&lt;/p&gt;

&lt;p&gt;Wenn es möglich ist, sollte man stets vor dem Entladen eines Bibliothek
versuchen, Ressourcen freizugeben und Datenverknüpfungen zu lösen.&lt;/p&gt;

&lt;p&gt;Natürlich sollte eine “gute” Bibliothek ein &lt;code&gt;init&lt;/code&gt; und ein &lt;code&gt;uninit&lt;/code&gt;
anbieten, doch wer garantiert uns, dass der Anwender diese Funktionen
zur rechten Zeit aufruft.&lt;/p&gt;

&lt;p&gt;Daher sollte man solche Spezialitäten auch beim Entladen durchführen und 
zwar für alles, was nicht schon zuvor freigegeben wurde.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Übrigens, kleiner Fun-Fact am Rande:&lt;br /&gt;
Da hat sich wohl jemand als Hacker versucht und eine tolle Doku
erstellt, wie man sogar eine 
&lt;a href=&quot;http://www.codeproject.com/Articles/1045674/Load-EXE-as-DLL-Mission-Possible&quot;&gt;EXE Datei wie eine DLL laden&lt;/a&gt;
und nutzen kann.&lt;/p&gt;

&lt;p&gt;Das Thema hört sich spannend an und ich nehme es hiermit in meine Liste
der “hoch interessanten” Themen auf.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Hüfte schwingen leicht gemacht?</title>
   <link href="https://www.opengate.at/blog/2020/02/new-haunch/"/>
   <published>2020-02-29T12:00:00+01:00</published>
   <updated>2020-02-29T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2020/02/new-haunch</id>
   <category term="general" />
   <summary type="text">Im vergangenen Monat hat sich meine Mutter eine Hüftoperation
unterzogen und ein künstliches Gelenk eingesetzt bekommen.
Als externer Beobachter des Genesungsprozesses und als Analytiker
komme ich nicht drum herum die ganze Sache kritisch zu diskutieren.
</summary>
   <content type="html">&lt;p&gt;Im vergangenen Monat hat sich meine Mutter eine &lt;a href=&quot;https://de.wikipedia.org/wiki/H%C3%BCftgelenk&quot;&gt;Hüftoperation&lt;/a&gt;
unterzogen und ein künstliches Gelenk eingesetzt bekommen.&lt;br /&gt;
Als &lt;em&gt;externer&lt;/em&gt; Beobachter des Genesungsprozesses und als &lt;em&gt;Analytiker&lt;/em&gt;
komme ich nicht drum herum die ganze Sache kritisch zu diskutieren.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;blockquote&gt;
  &lt;p&gt;Alles gut gegangen!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Das will man sowohl als Betroffener als auch als Angehöriger hören, wann immer
“tiefe” medizinische Eingriffe vollzogen werden.&lt;br /&gt;
Dass das Attribut “gut” aber im Auge des Betrachters liegt, sollte man dabei 
aber nicht vergessen.&lt;/p&gt;

&lt;p&gt;Nachdem bei einer Krankenzimmergenossin die Operation zwar gut verlaufen war,
dieser aber kurz danach der Knochen zersplittert ist und damit an ganzer Berg
an Komplikationen anstand, war Mama’s Stimmung durchaus von Sorge geprägt.&lt;/p&gt;

&lt;p&gt;Man kann nie ausschließen, dass das Einsetzen neuer Gelenke (oder anderer Organe)
schief geht.&lt;/p&gt;

&lt;p&gt;Zum Glück war dem in unserem Fall aber nicht so, die Operation verlief gut und
auch die erste Nachuntersuchung brachte positive Resultate.&lt;/p&gt;

&lt;p&gt;Doch wegen der jahrelangen körperlichen Fehlstellung auf Grund des schlechten 
Gelenkes, hatten sich Muskeln verkürzt und mussten während der OP stark gedehnt
werden um den Eingriff überhaupt erst durchführen zu können.&lt;/p&gt;

&lt;p&gt;Und das bedeutet dann: Schmerzen, Schmerzen und noch mehr Schmerzen.
Das sind die “Kleinigkeiten”, über die man zwar aufgeklärt wird, die man aber
als unwahrscheinlich abtut und ignoriert.&lt;/p&gt;

&lt;p&gt;Ärgerlich ist dann aber, wenn das Pflegepersonal - unaufgeklärt über den Zustand -
die Schmerzbekundung als unnötiges Lamentieren abtut.&lt;br /&gt;
&lt;em&gt;Empfehlung an Pflegekräfte&lt;/em&gt;: Erst mal davon ausgehen, dass wenn über 
Schmerzen geklagt wird, diese auch tatsächlich da sind und kein Wunsch nach
Aufmerksamkeit sind!&lt;/p&gt;

&lt;p&gt;Dass dann ausgerechnet im Krankenhaus der Zugang zur Toilette nicht 
Rollator-gerecht gebaut ist, sollte man den Architekten und Innenausstattern 
ebenso rückmelden. Mir ist schon klar, dass beim Bau von Gebäuden nicht immer 
schon alles im Vorhinein bekannt sein kann … dennoch sollte hier die Devise
sein: Lieber 10 cm mehr Platz zwischen Tür und Toilette freilassen, damit man 
auch mit Gehbehinderung einigermaßen zurecht kommt.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Behindert ist man nicht, behindert wird man!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Viel interessanter wird es dann aber nach einer Woche Spital bei der 
Entlassung:&lt;br /&gt;
Das Krankenhaus überreicht dabei ein paar Zettel mit täglich zu machenden
Übungen um den Heilungsprozess zu fördern.&lt;br /&gt;
Der behandelnde Arzt und Operateur sagt dazu jedoch in der Nachbesprechung:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Machen Sie auf keinen Fall eine der Übungen, die im Krankenhaus empfohlen
wurden, die sind Gift für die Genesung. Versuchen Sie nur mehrmals am
Tag normal zu gehen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;OK … das wäre in meiner Welt zu vergleichen mit:&lt;br /&gt;
Ich: &lt;em&gt;“Ich habe einen neuen Laptop, was nun?”&lt;/em&gt;&lt;br /&gt;
Techniker 1: “Schließen Sie sofort eine externe Maus an!”&lt;br /&gt;
Techniker 2: “Schließen auf gar keinen Fall eine externe Maus an!”&lt;/p&gt;

&lt;p&gt;Hmm … wer hat jetzt also recht? Was soll ich tun, fragt man sich.&lt;br /&gt;
Natürlich glaubt man dem behandelnden Arzt mehr, als der überreichten
Broschüre, aber es bleiben schon ein paar Fragezeichen zurück, wenn 
zwei sich gegenseitig ausschließende “Lösungen” empfohlen werden.&lt;/p&gt;

&lt;p&gt;Zuhause angekommen läuft es dann auch bei Weitem nicht so reibungslos,
wie man sich das vorgestellt hat … oder wie es Bekannte geschildert
haben, die einen solchen Eingriff schon miterlebt hatten.&lt;/p&gt;

&lt;p&gt;Aus:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Die ersten zwei Wochen braucht man Betreuung, dann geht schon alles 
von selbst.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;werden eher 6 - 8 Wochen, in denen es unverantwortlich ist, einen Menschen
in diesem Zustand alleine zu lassen.
Ja natürlich, ein gesunder junger Mensch mag sich nach so einem Eingriff
(wenn er den überhaupt braucht) vermutlich schneller regenerieren, aber 
bei Personen der Gruppe 60+ kommen viele Kleinigkeiten dann schwerer zu 
tragen.&lt;/p&gt;

&lt;p&gt;Hier hätte ich mir erwartet, dass auch von Seiten der Ärzte bzw. des 
Krankenhauses der Worst-Case beschrieben wird, damit man sich darauf
einstellen kann und nicht in Erwartung des Best-Case Szenarios glaubt,
dass alles in ein paar Tagen wieder gut ist.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Am Ende muss ich allerdings schon die Wunder der heutigen Medizin würdigen.
Ja, ein paar Dinge hätte man wirklich besser abklären und vorbereiten können,
aber dennoch freue ich mich melden zu können, dass Mama jeden Tag mit kleinen
Fortschritten ihre neue Hüfte besser unter Kontrolle bekommt.&lt;/p&gt;

&lt;p&gt;Es wird wohl noch einiges an Zeit vergehen, bis “alles” endgültig wieder gut 
ist, doch dafür wird sie mit der neuen Hüfte hoffentlich noch zahlreiche Jahre
mobil und selbstversorgend bleiben.
… denn es ist kein Spaß, wenn einem jeder Schritt Scherzen bereitet, so
wie das die Jahre zuvor bereits war.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>tag, userdata, userparam und LPARAM</title>
   <link href="https://www.opengate.at/blog/2020/02/userparam/"/>
   <published>2020-02-23T12:00:00+01:00</published>
   <updated>2020-02-23T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2020/02/userparam</id>
   <category term="devel" />
   <summary type="text">Wenn man eigene Konstrukte mit jenen einer anderen C
Bibliothek verknüpfen muss, braucht man mindestens an einer Stelle ein 
Verbindungsglied oder einen Ankerhaken, mit dem man Datenstrukturen, 
die sich gegenseitig nicht kennen, verknüpfen kann.

Und genau deshalb hat jede “gute” C-Bibliothek in seinen Objekten 
(bzw. structs) ein Feld, wo man einen Fremdwert eintragen kann, der 
überall hin mitgenommen werden kann …
… also ein freien Parameter für den Anwender: ein userparam
</summary>
   <content type="html">&lt;p&gt;Wenn man eigene Konstrukte mit jenen einer anderen &lt;a href=&quot;https://de.wikipedia.org/wiki/C_(Programmiersprache)&quot;&gt;C&lt;/a&gt;
Bibliothek verknüpfen muss, braucht man mindestens an einer Stelle ein 
Verbindungsglied oder einen Ankerhaken, mit dem man Datenstrukturen, 
die sich gegenseitig nicht kennen, verknüpfen kann.&lt;/p&gt;

&lt;p&gt;Und genau deshalb hat jede “gute” C-Bibliothek in seinen Objekten 
(bzw. &lt;code&gt;struct&lt;/code&gt;s) ein Feld, wo man einen Fremdwert eintragen kann, der 
überall hin mitgenommen werden kann …&lt;br /&gt;
… also ein freien Parameter für den Anwender: ein &lt;code&gt;userparam&lt;/code&gt;
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Im GATE Projekt sind viele Objekte Wrapper um native OS-spezifische Objekte.
Das gilt vor allem bei &lt;a href=&quot;https://de.wikipedia.org/wiki/Grafische_Benutzeroberfl%C3%A4che&quot;&gt;GUI&lt;/a&gt; 
Operationen, woran ich zur Zeit wieder etwas weiterarbeite.&lt;/p&gt;

&lt;p&gt;Nun möchte ich, dass eine generische C-Struktur im GATE-Framework unter allen 
Systemen ohne Anpassung nutzbar wird.
Das lässt sich am einfachsten mit einem Pointer und dem 
&lt;a href=&quot;https://en.wikipedia.org/wiki/Opaque_pointer&quot;&gt;PIMPL Idiom&lt;/a&gt;
(&lt;strong&gt;P&lt;/strong&gt;ointer to &lt;strong&gt;IMPL&lt;/strong&gt;ementation) realisieren:&lt;br /&gt;
Jedes “äußere” Objekt hält einen Pointer zur nativen Implementierung.
Und je nach Plattform sieht diese dann anders aus, während sich das Objekt 
selbst immer gleich nach außen präsentiert.&lt;/p&gt;

&lt;p&gt;Das funktioniert aber nur in eine Richtung, nämlich vom GATE Framework zur
nativen Komponente. Für den anderen Weg, z.B. &lt;a href=&quot;https://de.wikipedia.org/wiki/R%C3%BCckruffunktion&quot;&gt;Callbacks&lt;/a&gt;
für Events, braucht die Komponente irgend einen “Marker” um das sie kapselnde
Objekt zu finden.&lt;/p&gt;

&lt;p&gt;Aus der Windows UI Programmierung hat die &lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_Application_Programming_Interface&quot;&gt;WinAPI&lt;/a&gt;
auch für viele Nicht-UI-Bereiche den &lt;code&gt;LPARAM&lt;/code&gt; etabliert. Dieser Integer hat 
stets eine Pointer-Größe (&lt;code&gt;void*&lt;/code&gt;), weshalb man auch einen auf &lt;code&gt;LPARAM&lt;/code&gt; 
gecasteten Pointer auf diese Weise übergeben kann.&lt;/p&gt;

&lt;p&gt;Man hat also sein eigenes Objekt (oder die eigene Datenstruktur), ruft die API
mit der Adresse dazu auf und kann im Callback über den zuvor gesicherten
Parameter wieder zu seinem eigenen Objekt zurückkommen.&lt;/p&gt;

&lt;p&gt;Doch was macht man, wenn dieser “Parameter” nicht ausreicht, um das abzubilden,
was man braucht?&lt;/p&gt;

&lt;h3 id=&quot;fehlerfall-int-oder-gar-nichts&quot;&gt;Fehlerfall: &lt;code&gt;int&lt;/code&gt; oder gar nichts&lt;/h3&gt;

&lt;p&gt;Ein &lt;code&gt;userparam&lt;/code&gt; ist nur dann hilfreich, wenn er vom Typ &lt;code&gt;void*&lt;/code&gt;, &lt;code&gt;intptr_t&lt;/code&gt; 
oder &lt;code&gt;uintptr_t&lt;/code&gt; ist. All jene, die nur einen &lt;code&gt;int&lt;/code&gt; oder &lt;code&gt;unsigned int&lt;/code&gt; dafür 
gebrauchen, haben meist verloren.&lt;br /&gt;
Denn &lt;code&gt;int&lt;/code&gt; ist auf einigen Plattformen kleiner als &lt;code&gt;intptr_t&lt;/code&gt; (z.B. Win64) 
und braucht laut C-Standard überhaupt nur 16-bit groß sein.&lt;/p&gt;

&lt;p&gt;Das teuflische dabei: Alter Code (16/32 bit) scheint portabel zu sein, doch 
beim Einsatz auf z.B. einer 64-bit Architektur hängt es von Compiler und OS ab,
ob sich ein Objektzeiger ohne Bitverlust in 32 Bits darstellen lässt.&lt;/p&gt;

&lt;p&gt;Genau so schlimm ist es, wenn Objekte gar keine Möglichkeit einbringen, mit 
eigenen Strukturen verknüpft zu werden.&lt;/p&gt;

&lt;p&gt;Was soll man dann tun?&lt;/p&gt;

&lt;h3 id=&quot;lösung-verknüpfungs-registrierung-implementieren&quot;&gt;Lösung: Verknüpfungs-Registrierung implementieren&lt;/h3&gt;

&lt;p&gt;Ich hasse mich dafür es laut zu sagen, aber die Lösung heißt:&lt;br /&gt;
&lt;em&gt;Globale Variablen&lt;/em&gt; und zwar globale Mapping-Tabellen, die eine fremde
Ressource mit der eigenen verknüpfen.&lt;/p&gt;

&lt;p&gt;Dafür brauchen wir mindestens:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Eine Funktion zur Verknüpfung&lt;br /&gt;
e.g. &lt;code&gt;void register_object_link(void* foreign_object, void* my_object)&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Eine Funktion zur Lösung dieser Verknüpfung&lt;br /&gt;
e.g. &lt;code&gt;void unregister_object_link(void* foreign_object)&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Eine Funktion zur Verfolgung der Verknüpfung&lt;br /&gt;
e.g. &lt;code&gt;void* resolve_my_object(void* foreign_object)&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Optional auch noch eine Funktion zur Rückverfolgung einer Verknüpfung&lt;br /&gt;
e.g. &lt;code&gt;void* resolve_foreign_object(void* my_object)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Mit &lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B&quot;&gt;C++&lt;/a&gt; wäre das mit einer einfachen
&lt;code&gt;std::map&lt;/code&gt; leicht realisierbar.
Allerdings sollte man auch stets noch einen globalen &lt;a href=&quot;https://de.wikipedia.org/wiki/Mutex&quot;&gt;Mutex&lt;/a&gt;
beimengen, denn wenn Registrierungen und Auflösungen aus unterschiedlichen 
Threads eintreffen schafft eine solche &lt;em&gt;globale&lt;/em&gt; Registrierungsstelle mehr 
Probleme als Lösungen.&lt;/p&gt;

&lt;p&gt;Diese Notfall-Strategie wird im GATE Projekt an einigen Stellen genutzt um 
GATE-Objekte an ihr natives Gegenstück zu koppeln, damit man aus Callbacks 
der nativen Welt in die GATE-Welt und umgekehrt wechseln kann.&lt;/p&gt;

&lt;hr /&gt;

&lt;s&gt;
Ein besonders übler Fall von Callback befindet sich in Bibliothek `libssh2`.
Siehe [`libssh2_userauth_keyboard_interactive_ex`](https://libssh2.org/libssh2_userauth_keyboard_interactive_ex.html)  
Wer einen interaktiven Login durchführen will (was ja recht häufig bei [SSH](https://de.wikipedia.org/wiki/Secure_Shell)
passiert), muss dies über einen Callback realisieren, der nicht mit dem
Objekt verknüpft ist, das den Callback auslöst.  
Man dachte wohl, *&quot;interactive&quot;* bedeutet, man liest von STDIN und gibt
die eingetippten Zeichen einfach zurück.  
Doch damit kann man die `libssh2` nicht mehr als flexible Komponente und
schon gar nicht multithreaded ausführen.

Die einzige Lösung, die mir bei so einer Implementierung noch einfällt, 
ist die gesamte SSH-Login Aufrufprozedur durch einen Mutex zu schützen und 
die Kommunikation über weitere globale Variablen durchzuführen.
&lt;/s&gt;

&lt;blockquote&gt;
  &lt;p&gt;NACHTRAG: Unvollständige Schilderung, veraltetes Wissen meinerseits!&lt;br /&gt;
Die Authentifizierungsfunktionen bieten zwar keine Möglichkeit, einen 
&lt;code&gt;userparam&lt;/code&gt; mitzugeben, aber die SSH Session selbst schon.&lt;br /&gt;
Man muss hier &lt;code&gt;libssh2_session_init_ex&lt;/code&gt; statt &lt;code&gt;libssh2_session_init&lt;/code&gt;
einsetzen.&lt;br /&gt;
Man kann also dort ein “Kontext-Objekt” anhängen und über den &lt;code&gt;abstract&lt;/code&gt;
Pointer im Callback darauf zugreifen und ein Passwort auch so übergeben.&lt;br /&gt;
NACHTRAG-ENDE&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Daher, liebe Bibliotheken Entwickler, vergesst nicht:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Jedes öffentliche Objekt sollte die Möglichkeit bereitstellen,
mit einem Fremdobjekt verknüpft zu werden.
JEDES!&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>Der kleine Lichee Nano</title>
   <link href="https://www.opengate.at/blog/2020/02/lichee-nano/"/>
   <published>2020-02-22T12:00:00+01:00</published>
   <updated>2020-02-22T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2020/02/lichee-nano</id>
   <category term="hardware" />
   <summary type="text">Na endlich … mit großer Verzögerung, habe ich meinen 
Lichee Nano zum Laufen gebracht.

Mit ein bisschen mehr Doku wäre es vermutlich schneller gegangen.

Also dann, berichten wir mal …
</summary>
   <content type="html">&lt;p&gt;Na endlich … mit großer Verzögerung, habe ich meinen 
Lichee Nano zum Laufen gebracht.&lt;/p&gt;

&lt;p&gt;Mit ein bisschen mehr Doku wäre es vermutlich schneller gegangen.&lt;/p&gt;

&lt;p&gt;Also dann, berichten wir mal …
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Der &lt;a href=&quot;http://www.seeedstudio.com/Sipeed-Lichee-Nano-Linux-Development-Board-16M-Flash-WiFi-Version-p-2893.html&quot;&gt;Lichee Nano&lt;/a&gt;
ist ein Chip etwas größer als eine &lt;a href=&quot;https://de.wikipedia.org/wiki/SD-Karte&quot;&gt;SD-Karte&lt;/a&gt;
(die große, nicht die Micro!) und stellt einen &lt;a href=&quot;https://de.wikipedia.org/wiki/ARM-Architektur&quot;&gt;ARM&lt;/a&gt;
Prozessor mit 16 MB RAM bereit, der von einer eingebauten Micro-SD-Karte 
ein vollständiges &lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt; booten kann.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/lichee-nano.jpg&quot; alt=&quot;Lichee Nano&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Mit zahlreichen Pins und einer geringen Stromaufnahme liegt er 
zwischen einem Raspberry PI (Zero) und den Arduino-Varianten.&lt;/p&gt;

&lt;p&gt;Das &lt;em&gt;coole&lt;/em&gt; am Lichee Nano ist Linux, man hat also ein &lt;em&gt;richtiges&lt;/em&gt;
OS mit Multithreading und Prozessen.
Doch wegen der geringen Taktrate und dem kleinen RAM braucht man
weniger Strom um das System zu versorgen.&lt;/p&gt;

&lt;p&gt;Damit wäre es für kleinere &lt;a href=&quot;https://de.wikipedia.org/wiki/Internet_der_Dinge&quot;&gt;IoT&lt;/a&gt; 
Projekte ein interessantes Tool um einerseits Daten “professionell” zu 
verarbeiten und gleichzeitig weniger Strom zu fressen.&lt;/p&gt;

&lt;p&gt;Das größte Problem: Es gibt kein Standard-Linux für den Chip.
Wer also nach etwas wie &lt;a href=&quot;https://de.wikipedia.org/wiki/Raspberry_Pi#Raspberry_Pi_OS&quot;&gt;Raspbian&lt;/a&gt;
oder Ubuntu IoT sucht, sucht lange.&lt;/p&gt;

&lt;p&gt;Für den Lichee zahlt es sich aus, ein Linux Image selbst zu bauen 
und dann mit &lt;code&gt;dd&lt;/code&gt; an die richtige Adresse der SD-Karte zu schreiben,
damit der Chip auch booten kann. … also richtig Hardcore für unsere 
heutigen Zeiten.&lt;/p&gt;

&lt;h3 id=&quot;lichee-image&quot;&gt;Lichee Image&lt;/h3&gt;

&lt;p&gt;Unter &lt;a href=&quot;http://dl.sipeed.com/LICHEE/Nano/Image&quot;&gt;dl.sipeed.com/LICHEE/Nano/Image&lt;/a&gt;
liegen ein paar Beispiel-Images zum Download bereit.
Man kann die &lt;code&gt;*.dd&lt;/code&gt; Dateien über die Tools &lt;code&gt;dd&lt;/code&gt; oder den &lt;code&gt;Win32DiskImager&lt;/code&gt; auf 
eine SD-Karte bringen. Die Images zielen auf ein System mit Display ab
und liegen daher mit Dateinamen vor, die die gewünschte Auflösung beinhalten.&lt;/p&gt;

&lt;p&gt;Ich habe aber ohnehin kein Display und möchte den Chip per 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Serielle_Daten%C3%BCbertragung&quot;&gt;serieller Verbindung&lt;/a&gt; 
steuern.&lt;/p&gt;

&lt;h3 id=&quot;serielle-verbindung-aufbauen&quot;&gt;Serielle Verbindung aufbauen&lt;/h3&gt;

&lt;p&gt;Liegt der Chip auf der Seite mit der SD-Karte, so ist der USB-Anschluss auf der
Oberseite. Legt man den Chip so auf, dass der USB-Anschluss oben und der 
Display-Anschluss unten ist, dann befinden sich die UART Pins auf der linken
Seite:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: right&quot;&gt;Pin Nr.&lt;/th&gt;
      &lt;th&gt;Funktion&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;1&lt;/td&gt;
      &lt;td&gt;auslassen&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;2&lt;/td&gt;
      &lt;td&gt;UART 0 TX&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;3&lt;/td&gt;
      &lt;td&gt;UART 0 RX&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;4&lt;/td&gt;
      &lt;td&gt;+5 Volt&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;5&lt;/td&gt;
      &lt;td&gt;Ground&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Man verbindet also die Pins &lt;code&gt;2&lt;/code&gt;, &lt;code&gt;3&lt;/code&gt; und &lt;code&gt;5&lt;/code&gt; mit einem TTL Serial to USB 
Adapter, startet PuTTY oder ein anderes serielles Terminalprogramm und 
konfiguriert den COM Port mit einer BAUD-Rate von &lt;code&gt;115200&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Dann versorgt man Chip über den USB Anschluss mit Strom und sollte
in der Konsole bereits Aktivität feststellen.&lt;/p&gt;

&lt;p&gt;Bei mir war die erste Kommunikation noch fehlerhaft, aber nach etwas
Zeit nach dem Booten hat sich der Chip “gefangen” und begann eine
Login-Maske auf der Konsole zu zeigen.&lt;/p&gt;

&lt;p&gt;Mit&lt;/p&gt;

&lt;p&gt;User: &lt;code&gt;root&lt;/code&gt;&lt;br /&gt;
Password: &lt;code&gt;licheepi&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;konnte ich mich erfolgreich einloggen und ein an paar Linux Kommandos
ausprobieren.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Es macht Spaß auf einem “Computer” halb so groß wie ein Raspberry PI Zero 
oder Orange PI Zero zu arbeiten. Es ist schon beeindruckend, dass Linux 
mit 16 MB RAM tatsächlich lauffähig ist.&lt;/p&gt;

&lt;p&gt;Noch fehlt mir eine Netzwerkmöglichkeit, aber vielleicht kann ich per
USB ein &lt;a href=&quot;https://de.wikipedia.org/wiki/Local_Area_Network&quot;&gt;LAN&lt;/a&gt; oder 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Wireless_Local_Area_Network&quot;&gt;WLAN&lt;/a&gt; Modul 
zum Laufen bekommen.
Dann wäre es tatsächlich möglich mit dem Gerät “zu arbeiten”.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Im Reich der zügellosen Geister - Teil 2</title>
   <link href="https://www.opengate.at/blog/2020/02/disability-teil-2/"/>
   <published>2020-02-16T12:00:00+01:00</published>
   <updated>2020-02-16T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2020/02/disability-teil-2</id>
   <category term="general" />
   <summary type="text">Neben all den einzigartigen Erlebnissen, die ich bei 
“den zügellosen Geistern”,
also in meiner Gruppe mit geistig behinderten Menschen erleben durfte, 
gab es neben Licht auch Schatten.

Bis heute lässt mich die Frage:


  Wie weit darf man gehen?


immer wieder an einige Szenen von damals denken.
</summary>
   <content type="html">&lt;p&gt;Neben all den einzigartigen Erlebnissen, die ich bei 
&lt;a href=&quot;/blog/2020/02/disability/&quot;&gt;“den zügellosen Geistern”&lt;/a&gt;,
also in meiner Gruppe mit geistig behinderten Menschen erleben durfte, 
gab es neben Licht auch Schatten.&lt;/p&gt;

&lt;p&gt;Bis heute lässt mich die Frage:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Wie weit darf man gehen?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;immer wieder an einige Szenen von damals denken.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Genau in jenen Tagen, als mein Zivildienst am Laufen war, gab
es parallel in den Medien die Debatte, wie man Misshandlungen von Menschen
verhindern kann.&lt;/p&gt;

&lt;p&gt;Auslöser waren Berichte über aggressives Verhalten von Betreuern in 
Altersheimen, die - so der Medienbericht - gerne mal die Klienten ohrfeigten
oder andere Böswilligkeiten an den oft bettlegrigen Menschen ausließen.&lt;/p&gt;

&lt;p&gt;Dass es für ein solches Verhalten überhaupt keine Entschuldigung gibt und 
eine Strafverfolgung einzusetzen ist, ist für mich klar.&lt;br /&gt;
Schlimm sind aber Fälle, die in Grauzonen auf einen lauern, wo es extrem
schwierig ist, die “richtige” Entscheidung zu treffen.&lt;/p&gt;

&lt;h3 id=&quot;gleichheit-versus-arm-gegen-reich&quot;&gt;‘Gleichheit’ versus ‘Arm gegen Reich’&lt;/h3&gt;

&lt;p&gt;Vom Verhalten her waren viele meiner Klienten mit Kindern vergleichbar.
Und welches Kind freut sich nicht über ein Stück Schokolade.
… vorausgesetzt man bekommt je eines …&lt;/p&gt;

&lt;p&gt;Abhängig vom sozialen Status der Familie des Klienten, kommt zu manchen
Klienten wöchentlich oder monatlich ein Verwandter oder Sachwalter,
der aus dem dafür vorgesehenen Budget “Goodies” für seinen Schützling kauft,
oder eben nicht.&lt;/p&gt;

&lt;p&gt;Der Staat und die Heimleitung stellt hingegen nur die “Grundversorgung” 
sicher, hat aber kein Budget, dass jeder sein “gerechtes” Stück Schokolade
bekommt.&lt;/p&gt;

&lt;p&gt;Wenn nun also in einer Wohngruppe von 12 Personen, die eine Hälfte regelmäßig
ausgiebig beschenkt wird und die zweite Hälfte mit offenen Augen und 
tropfenden Mündern daneben stehen muss, ist Streit “vorprogrammiert”.&lt;br /&gt;
Und solche Spannungen können auch gehörig ins Auge gehen.&lt;/p&gt;

&lt;p&gt;Als Betreuer hat man nun die Möglichkeit “umzuverteilen”, denn geistig 
behinderten Menschen etwas einzureden, kann manchmal recht leicht sein.&lt;/p&gt;

&lt;p&gt;Man schafft also ein für alle angenehmes Klima, in welchem der reichere auf
einen kleinen Anteil seines “Eigentums” verzichtet und die Ärmeren dafür einen
Funken Glück verspüren dürfen … eine Freude für alle Sozialisten ;).&lt;/p&gt;

&lt;p&gt;Aber ist das wirklich gerecht? 
Widerspricht das nicht auf allen Ebenen der korrekten Behandlung von 
beeinträchtigten Menschen?
Darf man, nur weil es gerade leicht geht, manipulieren und den Leuten
“etwas einreden”?&lt;/p&gt;

&lt;p&gt;Ich behaupte einfach: Ja, weil die Konsequenzen im anderen Fall negativer
ausfallen.&lt;br /&gt;
Die korrekte Lösung wäre natürlich, dass eine solche Ungleichheit erst gar 
nicht auftritt. Jeder behinderte Mensch sollte einen Sachwalter haben, der für
ihn eben auch solche Kleinigkeiten einkauft, damit erst gar keine Ungleichheit
aufkommt.
Doch dem war damals leider nicht so.&lt;/p&gt;

&lt;h3 id=&quot;-bis-der-arzt-kommt&quot;&gt;… bis der Arzt kommt&lt;/h3&gt;

&lt;p&gt;Ein ganz schwieriges Thema sind offen ausgelebte Aggressionen.&lt;br /&gt;
Wann immer Menschen auf engem Raum von Problemen umgeben sind, kann es leicht
passieren, dass irgend wer “Dampf ablassen” will und schon steht die Bude
in Flammen.&lt;/p&gt;

&lt;p&gt;In der Theorie geht man als Betreuer ruhig auf den Mitmenschen zu und 
überzeugt ihn mit Worten sein schädliches Verhalten einzustellen.&lt;br /&gt;
Bei Star Trek werden so sogar galaktische Kriege verhindert.
Doch in Praxis läuft es leider nicht immer so harmonisch ab.&lt;/p&gt;

&lt;p&gt;(Ich will dabei gar nicht leugnen, dass es oft auch so positiv verläuft,
doch eben leider nicht immer.)&lt;/p&gt;

&lt;p&gt;Wenn also die Situation mit diplomatischen und verbalen Methoden nicht 
gelöst werden kann … ja was dann?&lt;/p&gt;

&lt;p&gt;Offiziell dürfen “einfache” Betreuer Klienten in keinster Weise 
festhalten oder fixieren. Wenn also jemand ausrastet muss die Polizei
verständigt werden, die den Klienten fixiert bis ein Arzt anwesend ist,
der medikamentös eingreift und im weiteren Sinne die Medikation so 
weit hinaufsetzt, dass der Mensch gar nicht mehr in der Lage ist
“Aggressionen herauszulassen”.&lt;/p&gt;

&lt;p&gt;Das ist rechtlich abgesichert und wurde gelegentlich auch so praktiziert.
Der Schaden, der durch diese medizinische Methode angewendet wird steht
aber im krassen Widerspruch zum Motto, dass jene Menschen für ein 
“normales” Leben vorbereitet werden sollen.&lt;/p&gt;

&lt;p&gt;Und dann gibt es da noch inoffiziell die Schock-Methode, die “offiziell” 
natürlich “nie” angewendet wurde:&lt;br /&gt;
Mit einem lauten dominierenden Schrei und donnernden Zurechtweisungen
wird die Eskalation in wenigen Sekunden beendet.&lt;/p&gt;

&lt;p&gt;Diese Methode wirkt äußerlich brutal, doch sie zeigte sich zu 100%
wirksam.&lt;br /&gt;
Manche Personen steigerten sich systematisch in ihren “Wahnsinn” hinein. 
Ruhiges zureden wirkte da wie Brennstoff um noch lauter zu erwidern
bis die ersten Gegenstände durch die Luft flogen.&lt;br /&gt;
Doch ein dominanter Schrei, der alle im Raum zusammenzucken ließ, 
brachte wieder Ordnung in die Gruppe.&lt;/p&gt;

&lt;p&gt;Ja, es war, als wäre man unter Tieren. Wenn ein Leitwolf den Ton angab,
herrschte Frieden, doch fehlte diese Bestimmtheit, kam es alle 1-2 Wochen
zu Zwischenfällen.&lt;/p&gt;

&lt;p&gt;Und was ist jetzt besser?&lt;br /&gt;
Im autoritären Stil Unruhen im Vorfeld abzuwenden, oder den diplomatischen
Weg gehen, der dann zum Polizeieinsatz führt und den Klienten chemisch
die nächsten Monate ruhigstellt.&lt;/p&gt;

&lt;p&gt;Dieser Fall ist besonders schwierig, denn wenn man als Betreuer selbst zu
härteren Geschützen greift, stellt sich die Frage, ab wann man die Grenze
des Akzeptablen überschreitet.&lt;/p&gt;

&lt;p&gt;Ich kann zwar garantieren, dass es in meiner Zeit nie zu Gewalt oder
überzogener verbaler Brutalität kam, aber besonders ein Außenstehender muss
bei der Beobachtung einer solchen Handlung einen “merkwürdigen” Eindruck
erhalten.&lt;br /&gt;
Und was passiert mit einem, wenn man diesen Job sein ganzes Leben lang macht?
Bei mir war nach 2 Jahren Schluss, aber wer weiß wie ich mich entwickelt 
hätte, wären solche wöchentlichen Belastungen zu meinem Beruf geworden.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ja, man muss diesen Berufszweig durchaus auch kritisch betrachten.
Mit Menschen zu arbeiten ist weit aus schwerer, als Maschinen zu warten,
denn jeder - wirklich jeder - reagiert anders.&lt;/p&gt;

&lt;p&gt;Jede Woche treten mehrere Situationen auf, die man weder mit Ja oder Nein,
noch mit Gut oder Böse klassifizieren kann und trotzdem muss man in der 
Sekunde eine Entscheidung treffen.&lt;/p&gt;

&lt;p&gt;Dennoch möchte ich für meine damaligen Kollegen ausnahmslos eine Lanze 
brechen und hiermit dokumentieren, dass sie stets im besten Gewissen 
gehandelt haben.&lt;/p&gt;

&lt;p&gt;Die Frage, ob ein Betreuer in einer kritischen Situation richtig oder
falsch gehandelt hat sollte hinter folgende eingereiht werden:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Hat die Verwaltung / die Gesellschaft / der Staat ausreichend unterstützt
und Mittel zur Verfügung gestellt.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Meine Antwort für damals ist: &lt;strong&gt;Nein!&lt;/strong&gt;&lt;br /&gt;
Es fehlte vor allem an Personal. Gäbe es für jeden Klienten einen Betreuer, 
wäre die optimale Betreuung nahezu garantiert.&lt;br /&gt;
Wenn aber 2 Diensthabende zwischen 10 und 15 Menschen quasi gleichzeitig alle
unterstützen und kontrollieren sollen, wird es schwierig. Denn während einer
notwendige Besorgungen macht oder das Mittagessen kocht, ist der zweite 
gefordert alle Personen über 6 Räume hinweg im Überblick zu behalten und 
neben Toilettgängen und persönlicher Unterstützung auch noch “die Ordnung” 
in der Gruppe aufrecht zu halten.&lt;/p&gt;

&lt;p&gt;Und genau dafür sollte mehr Verständnis und Anerkennung geschaffen werden.
Ja, Betreuung und Pflege ist teuer, und obwohl sich vieles verbessert hat,
wird leider immer zuerst in diesem Bereich gespart.&lt;/p&gt;

&lt;p&gt;Daher nochmals ein kräftiges &lt;strong&gt;Danke&lt;/strong&gt; an all jene guten Seelen, die ihr
Leben den “schwierigeren” Mitmenschen widmen.&lt;br /&gt;
&lt;strong&gt;Bleibt eurem guten Werk und den besten Vorsätzen treu!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Und fordert auch &lt;strong&gt;von uns&lt;/strong&gt; Außenstehenden die nötigen Mittel ein, die
ihr für eure Aufgaben benötigt.&lt;br /&gt;
Denn wenn es um die Fragen geht:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Bauen wir eine weitere Autobahnspur?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;oder&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Finanzieren wir ausreichend Betreuer in den Heimen?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;sollte es keine Sekunde dauern, bis dem letzteren zuerst einstimmig der
Geldfluss genehmigt wird.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>`static` bei C Funktionen</title>
   <link href="https://www.opengate.at/blog/2020/02/static-function/"/>
   <published>2020-02-15T12:00:00+01:00</published>
   <updated>2020-02-15T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2020/02/static-function</id>
   <category term="devel" />
   <summary type="text">Ich wurde gelegentlich schon in unterschiedlichen Projekten gefragt, wieso ich
vor Funktionen häufig ein static davor setze.

Die kurze Antwort darauf ist einfach:


  Weil es dort hingehört.


Doch wie so oft im Leben, liegt auch hier viel individuelle Meinung vor,
die ich aber gerne zu rechtfertigen bereit bin.
</summary>
   <content type="html">&lt;p&gt;Ich wurde gelegentlich schon in unterschiedlichen Projekten gefragt, wieso ich
vor Funktionen häufig ein &lt;code&gt;static&lt;/code&gt; davor setze.&lt;/p&gt;

&lt;p&gt;Die kurze Antwort darauf ist einfach:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Weil es dort hingehört.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Doch wie so oft im Leben, liegt auch hier viel individuelle Meinung vor,
die ich aber gerne zu rechtfertigen bereit bin.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Eine freie globale Funktion hat in &lt;a href=&quot;https://de.wikipedia.org/wiki/C_(Programmiersprache)&quot;&gt;C&lt;/a&gt;
und &lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B&quot;&gt;C++&lt;/a&gt; von Natur aus den Status einer
&lt;code&gt;extern&lt;/code&gt;-en Sichtbarkeit, nur dass in reinem C eine C-Nomenklatur zum Einsatz
kommt, während in CPP Dateien eine C++-Benamung stattfindet 
(siehe: &lt;a href=&quot;https://en.wikipedia.org/wiki/Name_mangling&quot;&gt;Name mangling&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Und dieser Umstand fällt vor allem dann auf, wenn 
(unter Nicht-Windows-Systemen) eine dynamische Bibliothek erstellt wird.&lt;br /&gt;
Alle Funktionen werden dort automatisch exportiert und sind von außen 
aufrufbar, außer man deaktiviert die Sichtbarkeit per Compiler-Parameter.&lt;/p&gt;

&lt;p&gt;Und so kommt es, dass große Softwarehersteller in ihren mitgelieferten 
Bibliotheken öffentliche Funktionen mitliefern, die viele Dinge bewirken,
die der Hersteller gar nicht wollte.&lt;br /&gt;
Am lustigsten sind Funktionen, die einen Lizenz- oder Kopierschutz deaktivieren
oder eine Entschlüsselung von sensiblen Daten anbieten, die eigentlich 
verborgen sein sollten.&lt;/p&gt;

&lt;p&gt;Eine &lt;code&gt;static&lt;/code&gt; Funktion ist nur in der Übersetzungseinheit (also in DER &lt;code&gt;*.c&lt;/code&gt; 
oder &lt;code&gt;*.cpp&lt;/code&gt; Datei) sichtbar, wo sie implementiert ist. Sie kann nicht 
(ohne Kunstgriffe) von außen aufgerufen oder in einer &lt;a href=&quot;https://en.wikipedia.org/wiki/Dynamic-link_library&quot;&gt;DLL&lt;/a&gt;
oder SO exportiert
werden.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Daher nun meine lange Antwort auf die ursprüngliche Frage:&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Jede Hilfsfunktion ist zwingend als &lt;code&gt;static&lt;/code&gt; zu deklarieren, außer man 
wünscht explizit, dass sie in öffentlichen Schnittstellen aufscheint.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Und so ist ja meistens. Wir haben im Header eine Funktion deklariert, die
entweder intern oder extern sichtbar sein soll. Und die Implementierung
dieser Funktion nutzt eine Vielzahl kleiner Hilfsroutinen um den Code
besser zu strukturieren, doch eben diese Helfer wollen wir nicht öffentlich
aufscheinen lassen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ich glaube, dass &lt;code&gt;static&lt;/code&gt; ein bisschen in Vergessenheit geraten ist und 
bemerkte schon in unterschiedlichen Projekten, dass DLLs und SOs mit 
zahlreichen Funktionsnahmen gefüllt sind, die eigentlich nicht veröffentlicht
werden sollten.&lt;/p&gt;

&lt;p&gt;Deshalb habe ich mir angewöhnt &lt;code&gt;static&lt;/code&gt; so häufig wie möglich einzusetzen.
Das Resultat sind dann aufgeräumtere Export-Tabellen.&lt;/p&gt;

&lt;p&gt;… sollte sich also wieder mal wer wundern warum im GATE Code oder anderen
meiner Schreibereien so oft &lt;code&gt;static&lt;/code&gt; vorkommt, dann sei dies hier die 
Rechtfertigung. ;)&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Lichtverschmutzung, der Nacht-Modus und das Web</title>
   <link href="https://www.opengate.at/blog/2020/02/nightmode/"/>
   <published>2020-02-09T12:00:00+01:00</published>
   <updated>2020-02-09T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2020/02/nightmode</id>
   <category term="software" /><category term="projects" />
   <summary type="text">
  Fuck! Mein Monitor ist defekt!


dachte ich mir vor ein paar Jahren, als plötzlich die Farben der Anzeige
kräftig nachließen. Ich startete meinen Rechner neu und bemerkte, dass 
wieder alles in Ordnung war, bis der Windows-Login fertig war und
plötzlich dunkelte sich die Anzeige wieder seltsam etwas rötlich ab.

Kurz das Netz befragt und wieder etwas gelernt:
Windows hat den Nacht-Modus aktiviert.
</summary>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;Fuck! Mein Monitor ist defekt!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;dachte ich mir vor ein paar Jahren, als plötzlich die Farben der Anzeige
kräftig nachließen. Ich startete meinen Rechner neu und bemerkte, dass 
wieder alles in Ordnung war, bis der Windows-Login fertig war und
plötzlich dunkelte sich die Anzeige wieder seltsam etwas rötlich ab.&lt;/p&gt;

&lt;p&gt;Kurz das Netz befragt und wieder etwas gelernt:&lt;br /&gt;
&lt;strong&gt;Windows hat den Nacht-Modus aktiviert.&lt;/strong&gt;&lt;br /&gt;
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;So ist das mit neuen Features die sich entweder von selbst oder 
“versehentlich” durch einen falsch verstandenen Klick aktivieren und 
anfangs scheinbar keine Wirkung haben.&lt;br /&gt;
Doch Stunden später steht die Welt still.&lt;/p&gt;

&lt;p&gt;Den neuen “Nacht-Modus” findet man unter &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_10&quot;&gt;Windows 10&lt;/a&gt;, 
wenn man die &lt;code&gt;Einstellungen&lt;/code&gt; App öffnet, dort auf &lt;code&gt;System&lt;/code&gt; geht und den linken
Menüpunkt &lt;code&gt;Anzeige&lt;/code&gt; auswählt. Dort lässt er sich ein- und ausschalten und auch 
definieren, ab welcher Uhrzeit die Nacht anfängt bzw. wann sie endet.&lt;/p&gt;

&lt;p&gt;Wird der Modus aktiv senkt Windows einerseits die Leuchtkraft des Bildes
(macht es also dunkler) und gleichzeitig werden Farben etwas ins rötliche
verschoben.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;So ein sinnloser Schwachsinn&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;dachte ich damals und deaktivierte die Funktion umgehend.&lt;br /&gt;
Doch eines Tages lernte ich zufällig durch ein YouTube Video, dass wir
durch unsere Nachtbeleuchtung unsere Augen und unser Hirn demolieren.&lt;/p&gt;

&lt;h3 id=&quot;lichtverschmutzung&quot;&gt;Lichtverschmutzung&lt;/h3&gt;

&lt;p&gt;Einiger Forscher untersuchen, wie die Menschheit durch künstliches Licht
den Nachtzyklus unterbricht und damit nicht nur sich selbst sondern auch 
der Tier- und Pflanzenwelt schadet.&lt;/p&gt;

&lt;p&gt;Mehr dazu hier:&lt;/p&gt;

&lt;iframe width=&quot;640&quot; height=&quot;360&quot; src=&quot;/blog/redirect.html?https%3A%2F%2Fwww.youtube-nocookie.com%2Fembed%2FOAOXyxZpFgs&quot; frameborder=&quot;1&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;

&lt;p&gt;Und da fiel mir gleich wieder dieser “Nacht-Modus” ein und zusammen mit 
dem Video verstand ich nun, warum diese Rot-Verschiebung der Farben 
implementiert wurde.&lt;/p&gt;

&lt;p&gt;Denn das kalte blaue &lt;a href=&quot;https://de.wikipedia.org/wiki/Leuchtdiode&quot;&gt;LED&lt;/a&gt; Licht, 
das uns bei weißen Bildschirmhintergründen anstrahlt stört unser 
Schlafempfinden. Und nachdem für mich das Thema Schlafen ohnehin ein ungutes
ist, wurde ich aufmerksam. Wenn das Licht aber (wie bei der Sonne oder einer 
klassischen Glühlampe) ins Rot oder gelbliche verschoben wird kommen wir 
offenbar besser damit zurecht.&lt;br /&gt;
Der Rotstich des Monitorbildes ist also “gesund”.&lt;/p&gt;

&lt;p&gt;Nun gut, also wurde der Nachtmodus wieder reaktiviert.&lt;/p&gt;

&lt;p&gt;Ich werde deshalb zwar nicht 10 Jahre länger leben, aber es stimmt schon, 
dass meine Augen durch den grellen weißen Hintergrund oft in den späten
Abendstunden schmerzen … also richtig weh tun. Und wenn das mit etwas 
weniger Blauweiß besser wird, so ist mir das sehr willkommen.&lt;/p&gt;

&lt;h3 id=&quot;dunkler-modus&quot;&gt;Dunkler Modus&lt;/h3&gt;

&lt;p&gt;Es gibt aber noch eine Einstellung, die unsere grellen Monitore beruhigt,
und das ist der “Dunkel” Modus für Apps.&lt;br /&gt;
Man findet es unter &lt;code&gt;Einstellungen&lt;/code&gt;, &lt;code&gt;Personalisierung&lt;/code&gt; unter dem Punkt 
&lt;code&gt;Farben&lt;/code&gt;. Dort lägt man die bevorzugte Gestaltung der Apps fest. Während
mit &lt;code&gt;Hell&lt;/code&gt; ein dunkler Text auf hellem (weißen) Hintergrund liegt,
macht &lt;code&gt;Dunkel&lt;/code&gt; das Gegenteil. Die Fenster werden schwarz und die Texte darauf
sind nun mehr weiß.&lt;/p&gt;

&lt;p&gt;Dieses Features ist eine jüngere Neuerung in Windows 10 und betrifft in erster
Linie die &lt;a href=&quot;https://en.wikipedia.org/wiki/Universal_Windows_Platform_apps&quot;&gt;UWP Apps&lt;/a&gt; 
(Modern Apps) und keine klassischen Desktop Programme. Der Explorer, der sich 
hier als Mischling einreiht ist teilweise bis heute fehlerhaft, indem er 
grundsätzlich schwarz ist, aber Plugin-Menüleisten dann plötzlich weiß 
herausblitzen und so die Bedienung erschweren.&lt;/p&gt;

&lt;p&gt;Dennoch ist dieser Modus empfehlenswert, weil er nachts nicht nur die Augen
schont, sondern er führt auch zu einem geringeren Energieverbrauch und 
möglicherweise auch zu einer Verlängerung der Lebensdauer des Monitors.&lt;/p&gt;

&lt;p&gt;Coole Sache also!&lt;/p&gt;

&lt;h3 id=&quot;dunkle-webseiten-entwickeln&quot;&gt;Dunkle Webseiten entwickeln&lt;/h3&gt;

&lt;p&gt;Nicht das Darknet, sondern die Erkennung des “Nacht-Modus” in Webseiten 
wäre doch ein tolles Feature. Ich hatte auch mal ein per Cookie umschaltbares
Seiten-Design erstellt, womit der Benutzer aus einer hellen eine dunkle 
Webseite machen konnte.&lt;/p&gt;

&lt;p&gt;Doch neulich fiel mir auf, dass &lt;a href=&quot;https://de.wikipedia.org/wiki/DuckDuckGo&quot;&gt;DuckDuckGo&lt;/a&gt; 
offenbar “erkennt”, welcher App-Modus gerade läuft. 
Und da wurde ich neugierig.&lt;/p&gt;

&lt;p&gt;Tatsächlich befinden wir uns gerade bei der Standardisierung des Features,
welches schon seit 1-2 Jahren von einigen Browsern implementiert wurde.&lt;br /&gt;
Es gibt einen neues &lt;code&gt;@media&lt;/code&gt; Feature namens &lt;code&gt;prefers-color-scheme: dark&lt;/code&gt;&lt;br /&gt;
für &lt;a href=&quot;https://de.wikipedia.org/wiki/Cascading_Style_Sheets&quot;&gt;CSS&lt;/a&gt;, das bei 
einer dunklen Einstellung ein anderes Farbdesign in einer Webseite laden kann.&lt;/p&gt;

&lt;p&gt;So nutze ich z.B. den CSS Code:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;body {
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;  background-image: url(&amp;quot;../img/cubes.jpg&amp;quot;);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  background-color: white;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  color: #333333;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;}
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;@media (prefers-color-scheme: dark) {
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;body {
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;  background-image: url(&amp;quot;../img/cubes_dark.jpg&amp;quot;);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  background-color: #333333;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;  color: GhostWhite;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;}
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;...
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;um im Nachtmodus ein anderes Hintergrundbild und eine inverse 
Textfarbendarstellung hier im Blog bereitzustellen.&lt;/p&gt;

&lt;p&gt;Dieses Features finde ich wirklich genial, denn so kann man ohne üble 
Javascript-Hacks die Anzeige einer Seite an die Wünsche des Nutzers
anpassen.&lt;/p&gt;

&lt;p&gt;Das machen leider viel zu wenige Webseiten (obwohl es langsam mehr werden)
und so wird man entweder nachts von grellen Werbeseiten verstört oder man 
verzweifelt tagsüber an schwarzen Webseiten, während die Sonne auf den 
Monitor strahlt.&lt;/p&gt;

&lt;p&gt;Der “Nach-Modus” und das “dunkle” App-Design sind zwei exzellentes Features, 
mit denen man dieses Problem in den Griff bekommen kann.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Also ihr DesignerInnen da draußen: Nutzt bitte diese Funktion!&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>Im Reich der zügellosen Geister - Teil 1</title>
   <link href="https://www.opengate.at/blog/2020/02/disability/"/>
   <published>2020-02-08T12:00:00+01:00</published>
   <updated>2020-02-08T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2020/02/disability</id>
   <category term="general" />
   <summary type="text">Der Schauspieler und Author Joachim Meyerhoff
veröffentlichte im Jahr 2013 sein Buch 
“Wann wird es endlich wieder so wie es nie war”.

Und ich bedauere zu tiefst, es bis heute nicht gelesen zu haben.
Doch als er es damals im Fernsehen vorstellen konnte und seine 
Kindheitserinnerungen zum Besten gab, erinnerte ich mich an eine
ganz besondere, etwas eigenartige und vielleicht wichtigste
Zeit in meinem Leben: Der Arbeit mit Menschen mit geistiger Behinderung.
</summary>
   <content type="html">&lt;p&gt;Der Schauspieler und Author &lt;a href=&quot;https://de.wikipedia.org/wiki/Joachim_Meyerhoff&quot;&gt;Joachim Meyerhoff&lt;/a&gt;
veröffentlichte im Jahr 2013 sein Buch 
&lt;em&gt;“Wann wird es endlich wieder so wie es nie war”&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Und ich bedauere zu tiefst, es bis heute nicht gelesen zu haben.
Doch als er es damals im Fernsehen vorstellen konnte und seine 
Kindheitserinnerungen zum Besten gab, erinnerte ich mich an eine
ganz besondere, etwas eigenartige und vielleicht wichtigste
Zeit in meinem Leben: Der Arbeit mit Menschen mit geistiger Behinderung.&lt;br /&gt;
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;YouTube hat die &lt;a href=&quot;https://www.youtube-nocookie.com/embed/VsvYmUKxWgM?start=1424&quot;&gt;Aufnahme von Joachim Meyerhoff bei Markus Lanz&lt;/a&gt;
zum Glück konserviert, und so kann ich auch heute noch lebhaft darüber lachen.&lt;/p&gt;

&lt;iframe width=&quot;640&quot; height=&quot;360&quot; src=&quot;/blog/redirect.html?https%3A%2F%2Fwww.youtube-nocookie.com%2Fembed%2FVsvYmUKxWgM%3Fstart%3D1424&quot; frameborder=&quot;1&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;

&lt;p&gt;Im Nachgang kreisen meine Gedanken aber stets um eine Gruppe Menschen, die 
ich vor über 15 Jahren kennenlernen durfte. Einige werden heute vermutlich
nicht mehr am Leben sein.&lt;/p&gt;

&lt;h3 id=&quot;zivildienst&quot;&gt;Zivildienst&lt;/h3&gt;

&lt;p&gt;Wer weiß schon, was auf ihn zukommt, wenn er im Zuge der militärischen 
Musterung den “Zivildienst” als Alternative zur Grundwehrausbildung wählt.
In meinem Fall war es zu einem großen Teil die Ablehnung einer 
“Befehlsstruktur” und auch das Wissen, dass meine Unsportlichkeit mir im 
erwarteten Laufschrittdrill nur Probleme liefern würde.&lt;br /&gt;
Und &lt;a href=&quot;https://de.wikipedia.org/wiki/Stanley_Kubrick&quot;&gt;Stanley Kubriks&lt;/a&gt; Film 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Full_Metal_Jacket&quot;&gt;Full Metal Jacket&lt;/a&gt; war dann
der letzte Sargnagel für das Thema Grundwehrdienst.&lt;/p&gt;

&lt;p&gt;Heute würde ich aber sagen, dass genau das ein schlechter Grund ist, sich 
für die Zivildienst zu melden. Man sollte viel mehr die Chance sehen, einen
Arbeitsbereich kennenzulernen, den man weder schulisch noch literarisch 
vermittelt bekommt.&lt;/p&gt;

&lt;p&gt;Und so verschlug es mich ein Jahr lang in ein Heim für Menschen mit geistiger
Behinderung, um in einer Wohngruppe mit 12 Personen Tag aus Tag ein den 
dortigen “Alltag” zu unterstützen.&lt;br /&gt;
Nie zuvor hätte mir gedacht, dass ich diesen “Dienst” um ein weiteres Jahr 
verlängern würde … doch so geschah es.&lt;/p&gt;

&lt;h3 id=&quot;die-wohngruppe&quot;&gt;Die Wohngruppe&lt;/h3&gt;

&lt;p&gt;In vier Zimmern wohnten:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Bernhard, Walter, Christian, Adolf&lt;/li&gt;
  &lt;li&gt;Bernhard, Erwin, Ulrich, Eduard,&lt;/li&gt;
  &lt;li&gt;Alfred und Walter&lt;/li&gt;
  &lt;li&gt;Johann und “Hansi”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Und dass ich diese “besonderen” Herrschaften heute noch im Kopf habe, nachdem
ich mich an die Namen von Kollegen von vor zwei Jahren schon nicht mehr
erinnern kann, liegt wohl daran, dass es vermutlich die “persönlichsten”
Begegnungen meines Lebens waren.&lt;/p&gt;

&lt;p&gt;Theoretisch war die Aufgabe einfach:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Jeden Morgen ab 7:00 Uhr alle bei der Morgentoilette unterstützen und 
für die Arbeitsgruppe fertig machen.&lt;/li&gt;
  &lt;li&gt;Die Wäsche in die Waschmaschinen schaffen.&lt;/li&gt;
  &lt;li&gt;Dann war bis 14:00 Uhr Freizeit&lt;/li&gt;
  &lt;li&gt;Am Nachmittag alle Leute wieder zurückholen.&lt;/li&gt;
  &lt;li&gt;Ein paar Beschäftigungen und Spiele begleiten.&lt;/li&gt;
  &lt;li&gt;Das Abendessen vorbereiten.&lt;/li&gt;
  &lt;li&gt;Bei der Einnahme der Mahlzeit unterstützen und danach die 
Medikamentenausgabe überprüfen und die Einnahme sicherstellen.&lt;/li&gt;
  &lt;li&gt;Alle Leute bettfertig machen und ab 20:00 Uhr an den Nachtdienst übergeben.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;… aber so nüchtern lief das fast nie ab …&lt;/p&gt;

&lt;h3 id=&quot;gute-zeiten-schlechte-zeiten&quot;&gt;Gute Zeiten, schlechte Zeiten&lt;/h3&gt;

&lt;p&gt;Viele Arbeiten waren mit der Altenbetreuung verwandt. Und als 18-jähriger ist
es schon recht abstrakt darüber nachzudenken, dass auch für einen selbst mal 
die Zeit kommt, wo ein anderer einen ausziehen und in die Dusche führen muss.
Dass man gewaschen wird, oder ein Fremder die Zahnbürste führt, die die letzten
drei Zähne putzt.&lt;/p&gt;

&lt;p&gt;Vermutlich sind es dann genau diese intimen Dienste, die eine ganz andere 
Verbindung zu Menschen aufbaut, so wie man das weder in der Schulzeit und 
schon gar nicht in der regulären Arbeitswelt vorfindet.&lt;/p&gt;

&lt;p&gt;Und als einer meiner “Klienten” (ja so heißt das offiziell), nämlich 
“Bernhard”, nach dem Abendessen zu mir:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Danke, Vater&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;sagte, war es gleichsam verstörend wie auch tief berührend für mich.&lt;/p&gt;

&lt;p&gt;Denn eine Behinderung macht Menschen abhängig. Und da kann man immer wieder
neunmalklug behaupten:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Behindert ist man nicht, behindert wird man.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Aber am Ende sehen jene Menschen selbst, dass sie eben “anders” sind, dass 
sie mit der sich selbst als “normal” bezeichnenden Welt nicht zurecht kommen 
und sie sehen, dass es andere gibt, die keine Probleme haben.&lt;/p&gt;

&lt;p&gt;Da spielt es weniger eine Rolle, dass man seine Hand nicht unter Kontrolle
hat und einen Buntstift nicht halten kann, sondern das Wissen, dass “andere”
das spielend leicht hinbekommen.&lt;/p&gt;

&lt;p&gt;Zorn und Wut, die ich an manchen Tagen dort miterleben durfte, würden für 
Außenstehende extrem wirken und das sofortige Abschotten auslösen.&lt;br /&gt;
Wenn man aber miterlebt, wie hart der Kampf gegen die eigene Natur und die
Anforderungen der Umgebung ist, dann wird einem einerseits bewusst, wie 
unglaublich glücklich man sein sollte, selbst keinen Einschränkungen zu 
unterliegen, und wie verständlich eine “ungute” Reaktion überhaupt erst
entsteht.&lt;/p&gt;

&lt;p&gt;Und es tut einem selbst weh, die blutverschmierten zerbrochenen Wandfliesen 
wegräumen zu müssen, nachdem mein “Mensch-ärgere-dich-nicht” Mitspieler von 
vor einer Stunde, plötzlich seinen Kopf mit aller Wucht gegen die Wand schlug,
um seine Frustration abzureagieren.&lt;/p&gt;

&lt;p&gt;Und dann gab es noch diese unglaublich vielen anderen Momente, wo eine 
kindliche Umarmung und ein Ausdruck wie an Weihnachten den Raum erhellte,
weil das Lieblingsessen auf dem Tisch stand, oder eine Zeichnung einer
Blumenwiesen gelungen war.&lt;/p&gt;

&lt;p&gt;Zu den schönsten Erinnerungen zählt für mich der Tag, an dem “Hansi”, der
wegen seiner spastischen Lähmung kaum sprechen konnte, mir über Handzeichen
und Wiederholung von einigen wenigen Worten vermitteln konnte, dass seine
Betreuerin Geburtstag hätte und er ihr gerne etwas schenken würde.&lt;/p&gt;

&lt;p&gt;Ich hatte das nicht so bedeutend gefunden und ging daher am Vormittag
an einem Blumenladen vorbei und nahm ein kleines Sträußchen für ihn mit.&lt;/p&gt;

&lt;p&gt;Und als ich am Nachmittag Hansi im Rollstuhl aus seiner Arbeitsgruppe holte
und ihm das Sträußchen auf den Schoß legte, erlebte ich ein Abenteuer:&lt;/p&gt;

&lt;p&gt;Ich habe in meinem gesamten Leben nie wieder einen Menschen so nervös und
aufgeregt erlebt, als wir 10 Minuten von Gebäude A nach B fuhren.
Und als wir bei seiner Betreuerin ankamen wurde es noch intensiver.
Unter Tränen schaffte es Hansi gerade noch “Danke, Danke” und ein paar
Silben von “Geburtstag” herauszubekommen und im gleichen Augenblick 
brauch auch sein Gegenüber in Tränen aus.&lt;/p&gt;

&lt;p&gt;Das mag jetzt äußerlich kitschig wirken, aber für mich war das derart
befremdlich und gleichsam so herzzerreißend, dass “ein paar billige Blumen”
so eine Reaktion auslösen konnten.
Vielleicht war es das erste Mal in seinem Leben, dass Hansi - er war damals um 
die 60 Jahre alt - einem anderen etwas “geben” konnte.
Und ich möchte behaupten, dass die Möglichkeit, dass er selbst etwas 
herschenken konnte, ihm mehr Freude bereitet hat, als wenn man ihm 100
Geschenke übergeben hätte.&lt;/p&gt;

&lt;p&gt;Diese Szene hat mich mehr zum Nachdenken gebracht, als es 10 Bücher oder
Filme zu dem Thema hätten tun können. Es war eine neue Erfahrung was
“Wertschätzung” bedeuten kann, und wie unglaublich abgestumpft ich selbst
und die “normale” Welt da draußen eigentlich waren.&lt;br /&gt;
Eine solche starke Kraft von Emotionen und Freude erleben wir nur noch 
selten im Alltag, obwohl diese Fähigkeit in uns allen innewohnt.&lt;/p&gt;

&lt;p&gt;Es mag eine Ironie in sich sein, dass ich ausgerechnet in einem Heim, 
in dem offiziell Menschen mit “reduzierten menschlichen Fähigkeiten” leben,
mehr Menschlichkeit erleben durfte, als anderorts.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Heute sitze ich - wie alle paar Monate - wieder vor meinem Foto-Verzeichnis
und denke an meine beiden Jahre im “Reich der zügellosen Geister” zurück.
Dort wo das Innere ohne Maske nach Außen drang und wo mein Spiegelbild
aufhörte zweidimensional zu reflektieren.&lt;/p&gt;

&lt;p&gt;Auch wenn mein Lebensweg in eine andere Richtung ging - und ja, das
musste so sein, denn ich hätte nicht in beiden Welten gleichzeitig leben 
können - ich werde jene besonderen Seelen von damals niemals vergessen können.&lt;/p&gt;

&lt;p&gt;Danke an euch für die schöne Zeit und diese kostbare Erfahrung!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Mac Mini 2009, tot und lebendig</title>
   <link href="https://www.opengate.at/blog/2020/02/mac-mini/"/>
   <published>2020-02-02T12:00:00+01:00</published>
   <updated>2020-02-02T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2020/02/mac-mini</id>
   <category term="hardware" /><category term="software" /><category term="retro" />
   <summary type="text">Im Film WALL-E - Der Letzte räumt die Erde auf
hat Apple wieder mal ein perfektes Product-Placement vollzogen.
Denn immer wenn der niedliche titelgebende Roboter seine Batterien aufgeladen
hatte, ertönte der bekannte Gong, der beim Einschalten eines 
Apple Macintosh abgespielt wird.

Heute habe ich meine kleine weiße Box aus dem Jahr 2010 wieder entstaubt
und angeschlossen um zu sehen, ob der Apfel darauf noch “Biss hat”.

</summary>
   <content type="html">&lt;p&gt;Im Film &lt;a href=&quot;https://de.wikipedia.org/wiki/WALL%C2%B7E_%E2%80%93_Der_Letzte_r%C3%A4umt_die_Erde_auf&quot;&gt;WALL-E - Der Letzte räumt die Erde auf&lt;/a&gt;
hat Apple wieder mal ein perfektes Product-Placement vollzogen.&lt;br /&gt;
Denn immer wenn der niedliche titelgebende Roboter seine Batterien aufgeladen
hatte, ertönte der bekannte Gong, der beim Einschalten eines 
&lt;a href=&quot;https://en.wikipedia.org/wiki/Macintosh&quot;&gt;Apple Macintosh&lt;/a&gt; abgespielt wird.&lt;/p&gt;

&lt;p&gt;Heute habe ich meine kleine weiße Box aus dem Jahr 2010 wieder entstaubt
und angeschlossen um zu sehen, ob der Apfel darauf noch “Biss hat”.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Tatsächlich war das “erste GATE-Projekt” vor 10 Jahren der Grund dafür, dass 
ich mir einen &lt;a href=&quot;https://de.wikipedia.org/wiki/Mac_mini&quot;&gt;Mac Mini&lt;/a&gt; kaufte.&lt;br /&gt;
Ziel war die Prüfung der Portierung des damaligen GATE C++ Codes auf eben 
diese Plattform.&lt;/p&gt;

&lt;p&gt;Meine Erkenntnis daraus war, dass &lt;a href=&quot;https://de.wikipedia.org/wiki/Portable_Operating_System_Interface&quot;&gt;POSIX&lt;/a&gt;
Code und &lt;a href=&quot;https://de.wikipedia.org/wiki/Xlib&quot;&gt;XLIB&lt;/a&gt; UIs ganz gut auf 
einem Mac kompiliert und ausgeführt werden konnte.&lt;br /&gt;
Wenn ich mich recht erinnere, hatte ich nur an einer Stelle Probleme, wo ein 
POSIX-Typ in einen &lt;code&gt;intptr_t&lt;/code&gt; gepackt werden sollte. Da war ich von Linux 
Umgebungen gewohnt, dass diverse integrale Typen nie größer als &lt;code&gt;size_t&lt;/code&gt; 
bzw. &lt;code&gt;intptr_t&lt;/code&gt; oder &lt;code&gt;uintptr_t&lt;/code&gt; waren.&lt;br /&gt;
Nur der 32-bittige Mac Mini nutzte hier interessanterweise 64 bits.&lt;/p&gt;

&lt;p&gt;Mit dem damals stark aufstrebenden &lt;a href=&quot;https://de.wikipedia.org/wiki/Objective-C&quot;&gt;Objective-C&lt;/a&gt; 
konnte ich mich aber überhaupt nicht anfreunden. Ich bin eben auf die C, 
Java, Pascal und Basic Syntax eingestellt und kann Spielereien wie&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;[object method: arguments] 
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;nicht leiden, wenn man&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;object.method(arguments);
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;meint.&lt;/p&gt;

&lt;h3 id=&quot;einschalten-startet-läuft--oder&quot;&gt;Einschalten, startet, läuft … oder?&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/mac-mini.jpg&quot; alt=&quot;Mac Mini&quot; /&gt;
&lt;img src=&quot;/blog/assets/img/mac-mini-back.jpg&quot; alt=&quot;Mac Mini&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Auf den ersten Blick sieht es so aus, als würde der Mac heute so hochfahren,
als wäre er gestern erst abgeschaltet worden.
Tatsächlich war er aber 2014 laut Log das letzte Mal online.&lt;/p&gt;

&lt;p&gt;Mit verbundenem Netzwerk holt er sich die aktuelle Zeit und sucht nach Updates.
Da findet er aber nur ein neues &lt;a href=&quot;https://de.wikipedia.org/wiki/ITunes&quot;&gt;iTunes&lt;/a&gt; 
… also nichts relevantes.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/os-x-upgrade-03.jpg&quot; alt=&quot;Mac Mini System&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Parallel konnte ich abrufen, was für ein Gerät und welchen Softwarestand ich 
vor mir hatte:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Mac OS X Version 10.6.8 “Snow Leopard”&lt;/li&gt;
  &lt;li&gt;Intel Core 2 Duo 2.26 GHz&lt;/li&gt;
  &lt;li&gt;2 GB RAM DDR3&lt;/li&gt;
  &lt;li&gt;160 GB Festplatte&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/os-x-upgrade-04.jpg&quot; alt=&quot;Mac Mini System&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Doch wenn man den Browser Safari startet, erlebt man schnell die erste
Enttäuschung…&lt;br /&gt;
Denn zwischen 2013 und 2014 fand das weltweite Umdenken und der Wechsel zu 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Hypertext_Transfer_Protocol_Secure&quot;&gt;HTTPS&lt;/a&gt; 
statt. Viele Webseiten bieten heute gar kein reines HTTP-Interface 
mehr an sondern nur noch eine Zwangsumleitung auf eine “sichere” HTTPS
Verbindung.&lt;br /&gt;
Und genau da hakt es, nämlich bei den SSL Zertifikaten. Diese sind meist nur
auf 2 bis 5 Jahre ausgestellt und somit muss ein OS regelmäßig seine 
Root-Zertifikate aktualisieren um alle Webseiten aufrufen zu können.&lt;/p&gt;

&lt;p&gt;Doch diese Updates fehlen dem Mac und somit kann er (von &lt;a href=&quot;http://www.opengate.at/&quot;&gt;OpenGate.AT&lt;/a&gt; 
mal abgesehen) nur wenige Seiten öffnen.&lt;/p&gt;

&lt;p&gt;Bei &lt;a href=&quot;https://de.wikipedia.org/wiki/Mozilla_Firefox&quot;&gt;Firefox&lt;/a&gt; ist das genau so, 
doch die von mir damals installierte Version 24, ließ sich tatsächlich noch 
auf Version 48 automatisch hochleveln und somit haben wir einen Stand aus 
dem Jahr 2017, womit man im Web noch deutlich weiter kommt.&lt;/p&gt;

&lt;p&gt;Firefox hatte nach Version 48 den Support für mein altes MacOS X eingestellt
und empfahl ein OS-Update.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/os-x-upgrade-02.jpg&quot; alt=&quot;Mac Mini Firefox&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Und genau dieses wollte ich somit wagen.
Apple erklärt auf seiner Webseite, dass Version 10.15 namens Catalina gerade
aktuell ist, doch dass ältere Systeme (wie meines) zuerst auf Version 10.11
(genannt El Capitan) gebracht werden müssen.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/os-x-upgrade-01.jpg&quot; alt=&quot;Mac Mini System&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Also startete ich den Download und wartete das Beziehen von 5.6 GB der 
Datei &lt;code&gt;InstallMacOSX.dmg&lt;/code&gt; ab.&lt;br /&gt;
Diese wurde dann ausgeführt und schon lief die Vorbereitung und anschließend
die Durchführung des Mac-OS Upgrades auf die nächste Version.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/os-x-upgrade-05.jpg&quot; alt=&quot;Mac Mini Upgrade&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Und nach einem längeren Updatevorgang fährt der Mac wieder hoch und meldet:
El Capitan. 10.11.6&lt;/p&gt;

&lt;p&gt;Firefox aktualisierte sich sogleich auf Version 72 und ist somit wieder auf dem
Stand von “heute” was das Web anbelangt.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/os-x-upgrade-06.jpg&quot; alt=&quot;Mac Mini El Capitan&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;das-ende-naht&quot;&gt;Das Ende naht&lt;/h3&gt;

&lt;p&gt;An dieser Stelle unterbrach ich meine Update-Serie und verzichtete auf weitere
Aktualisierungen. Denn durch die neue MacOS Version war die Performance des 
Systems bereits merkbar gesunken.&lt;/p&gt;

&lt;p&gt;Natürlich kann man noch mit dem System “arbeiten”, doch das Laden von Apps 
dauert nun relativ lange. Fuhren Apps wie &lt;em&gt;Finder&lt;/em&gt; und Co vor dem Update in 5
Sekunden hoch, dauerten solche Starts nun fast bis zu 15 Sekunden.&lt;br /&gt;
Das ist schon ein ziemlicher Demotivationsfaktor und ich befürchte, dass
weitere Updates das ganze noch weiter verschlechtern.&lt;/p&gt;

&lt;p&gt;Leider werden Betriebssystem immer komplexer und führen intensive
kryptographische Prüfungen für Softwarepakete ein, die auf alter Hardware
stetig mehr Leistung fressen.&lt;/p&gt;

&lt;p&gt;Damit zeigt sich leider erneut, dass Betriebssysteme Hardware schon nach 
wenigen Jahren degradieren. Das kennen wir ja von Windows zur Genüge und 
zwingt uns dort ebenso alle paar Jahre auf leistungsfähigere Hardware
umzusteigen.&lt;/p&gt;

&lt;p&gt;Naja, und mit seinen 10 Jahren hat mein kleiner Mac Mini sein “natürliches”
Ende eindeutig erreicht.&lt;br /&gt;
Schade, dass ich ihn nur so wenig genutzt habe, doch er wir als “Retro-System”
weiter in meiner Sammlung bleiben und vielleicht auch mal wieder ein paar
Test-Aufgaben bekommen. z.B.: Wenn das GATE Projekt eine neue Zielplattform
sucht.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>SUBST permanent machen</title>
   <link href="https://www.opengate.at/blog/2020/02/subst/"/>
   <published>2020-02-01T12:00:00+01:00</published>
   <updated>2020-02-01T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2020/02/subst</id>
   <category term="software" />
   <summary type="text">Neulich in der Firma fragte ein Kollege, wie man eine Partition auf zwei 
Laufwerke aufteilen kann, ohne Partitionen selbst verändern zu müssen.

Mir fiel dazu ein:


  Früher unter DOS gab es 
dafür SUBST … aber keine Ahnung, ob es das unter Windows noch gibt.


</summary>
   <content type="html">&lt;p&gt;Neulich in der Firma fragte ein Kollege, wie man eine Partition auf zwei 
Laufwerke aufteilen kann, ohne Partitionen selbst verändern zu müssen.&lt;/p&gt;

&lt;p&gt;Mir fiel dazu ein:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Früher unter &lt;a href=&quot;https://de.wikipedia.org/wiki/MS-DOS&quot;&gt;DOS&lt;/a&gt; gab es 
dafür &lt;code&gt;SUBST&lt;/code&gt; … aber keine Ahnung, ob es das unter Windows noch gibt.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Das “gute alte” DOS konnte im Grunde genommen nicht recht viel. Datei- und 
Verzeichnisnamen waren auf 8.3 Zeichen beschränkt und Laufwerke wie A: und C:
waren fix dem Diskettenlaufwerk (A:) und der Bootpartition (C:) zugeordnet.&lt;/p&gt;

&lt;p&gt;Um auf der Festplatte etwas mehr Ordnung und Übersicht zu erhalten, wurde aber
die Möglichkeit eingeführt, dass ein beliebiges Unterverzeichnis zu einem 
eigenen virtuellen Laufwerk werden konnte.&lt;/p&gt;

&lt;p&gt;Die Idee: Man “SUBSTituiert” einen kurzen Pfad im Hintergrund durch einen 
längeren.&lt;/p&gt;

&lt;p&gt;Das DOS Kommando &lt;code&gt;SUBST G: C:\APPS\GAMES&lt;/code&gt; erzeugte also das Laufwerk &lt;code&gt;G:&lt;/code&gt;,
dessen Inhalt die Dateien und Unterverzeichnisse von &lt;code&gt;C:\APPS\GAMES&lt;/code&gt; 
beinhaltete.&lt;/p&gt;

&lt;p&gt;Das brachte vor allem Vorteile beim Kopieren und Navigieren. Denn statt
&lt;code&gt;CD C:\APPS\GAMES\&lt;/code&gt; musste man nur noch &lt;code&gt;G:&lt;/code&gt; und &lt;code&gt;ENTER&lt;/code&gt; tippen, um 
zu seinen Spielen zu gelangen. Auch das fehleranfällige Tippen von langen
Pfaden wurde somit reduziert.&lt;/p&gt;

&lt;p&gt;Unter DOS packte man daher seine bevorzugten &lt;code&gt;SUBST&lt;/code&gt; Kommandos einfach in 
die Datei &lt;code&gt;C:\AUTOEXEC.BAT&lt;/code&gt;, die bei jedem Start ausgeführt wurde, und 
schon lief das System “schön sortiert”.&lt;/p&gt;

&lt;h3 id=&quot;die-windows-lösung&quot;&gt;Die Windows Lösung&lt;/h3&gt;

&lt;p&gt;Microsoft hat es hier wieder einmal geschafft, dass ein tolles Feature, das
bis heute funktioniert, in Vergessenheit geraten zu lassen.&lt;br /&gt;
Denn wer in seiner Kommandozeile (&lt;code&gt;cmd&lt;/code&gt;) ein &lt;code&gt;SUBST W: C:\Windows&lt;/code&gt; eintippt,
wird Sekunden später ein W: Laufwerk im Explorer finden, das eben genau
den Inhalt von &lt;code&gt;C:\Windows&lt;/code&gt; spiegelt.&lt;/p&gt;

&lt;p&gt;Doch mein findiger Kollege tippte &lt;code&gt;SUBST&lt;/code&gt; in seine Suchmaschine und fand 
prompt unter den ersten Ergebnissen einen Weg, wie man &lt;code&gt;SUBST&lt;/code&gt; auch unter
Windows 10 (wo es &lt;code&gt;AUTOEXEC.BAT&lt;/code&gt; ja nicht mehr gibt) zu einer permanenten
Lösung machen kann.&lt;/p&gt;

&lt;p&gt;Diese möchte ich hier wiedergeben in der Hoffnung, dass sie sich verbreitet
und weiteren Menschen bei der Arbeit und Datensortierung hilft:&lt;/p&gt;

&lt;h3 id=&quot;per-registry-virtuelle-laufwerke-für-verzeichnisse-anlegen&quot;&gt;Per Registry virtuelle Laufwerke für Verzeichnisse anlegen&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;regedit&lt;/code&gt; starten&lt;/li&gt;
  &lt;li&gt;In den Registry-Zweig: 
&lt;code&gt;HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\DOS Devices&lt;/code&gt;
wechseln&lt;/li&gt;
  &lt;li&gt;Dort per &lt;code&gt;Bearbeiten&lt;/code&gt; - &lt;code&gt;Neu&lt;/code&gt; - &lt;code&gt;Zeichenfolge&lt;/code&gt; (bzw. &lt;code&gt;Edit&lt;/code&gt; -&amp;gt; &lt;code&gt;New&lt;/code&gt; -&amp;gt; &lt;code&gt;String Value&lt;/code&gt;)
einen Eintrag erstellen.&lt;/li&gt;
  &lt;li&gt;Sein Namen muss auf den Laufwerksbuchstaben und Doppelpunkt lauten, z.B. &lt;code&gt;G:&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Und der Wert muss mit &lt;code&gt;\DosDevices\&lt;/code&gt; (oder &lt;code&gt;\??\&lt;/code&gt;) beginnen, gefolgt vom 
üblich Pfad, wohin man umleiten möchte, z.B.: &lt;code&gt;\DosDevices\C:\apps\games&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;alternativen&quot;&gt;Alternativen&lt;/h3&gt;

&lt;p&gt;Man kann natürlich auch das &lt;code&gt;SUBST&lt;/code&gt; Kommando bei jedem Benutzer-Login ausführen lassen,
in dem man einen Task in der Aufgabenverwaltung (in der Computerverwaltung) definiert
oder im Registry-Zweig &lt;code&gt;HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run&lt;/code&gt;
einen String-Eintrag mit Namen &lt;code&gt;G-Laufwerk&lt;/code&gt; und dem Wert &lt;code&gt;SUBST G: C:\apps\games&lt;/code&gt; 
anlegt.&lt;/p&gt;

&lt;p&gt;Auch kann man den Weg über localhost-Netzwerkverbindungen gehen wo man über die
administrative Freigabe “C$” ein Unterverzeichnis an ein anderes Laufwerk bindet.
z.B. mit dem Kommando &lt;code&gt;net use G: \\localhost\c$\apps\games&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Wie auch immer … es ist jedenfalls gut zu wissen, dass es dieses Feature seit
30 Jahren im System gibt und dass wir es weiter nutzen können um schneller an
unsere Daten zu kommen.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Träume und Visionen</title>
   <link href="https://www.opengate.at/blog/2020/01/scifi/"/>
   <published>2020-01-31T12:00:00+01:00</published>
   <updated>2020-01-31T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2020/01/scifi</id>
   <category term="general" /><category term="retro" />
   <summary type="text">Bis heute habe ich Mitleid mit Wil Wheaton, 
dem Darsteller der Figur des Whesley Crusher 
aus Star Trek Next Generation. 
Seine Rolle wurde unter Fans schnell als dumm und unrealistisch abgetan.
Doch für mich, der die Serie damals in den 90er Jahren fast täglich im 
Nachmittagsprogramm sehen MUSSTE, war er DAS Vorbild:
Ein hochbegabter Junge, stets wissbegierig, DER Computerexperte schlecht hin
und immer bemüht durch kreative Ideen den Tag zu retten.

Nun, heute denke ich mir:


  Was wäre wohl aus mir geworden, wenn z.B.: ein Mad Max mein Vorbild 
geworden wäre?


</summary>
   <content type="html">&lt;p&gt;Bis heute habe ich Mitleid mit &lt;a href=&quot;https://de.wikipedia.org/wiki/Wil_Wheaton&quot;&gt;Wil Wheaton&lt;/a&gt;, 
dem Darsteller der Figur des &lt;a href=&quot;http://memory-alpha.fandom.com/de/wiki/Wesley_Robert_Crusher&quot;&gt;Whesley Crusher&lt;/a&gt; 
aus &lt;a href=&quot;https://de.wikipedia.org/wiki/Raumschiff_Enterprise_%E2%80%93_Das_n%C3%A4chste_Jahrhundert&quot;&gt;Star Trek Next Generation&lt;/a&gt;. 
Seine Rolle wurde unter Fans schnell als dumm und unrealistisch abgetan.&lt;br /&gt;
Doch für mich, der die Serie damals in den 90er Jahren fast täglich im 
Nachmittagsprogramm sehen MUSSTE, war er DAS Vorbild:&lt;br /&gt;
Ein hochbegabter Junge, stets wissbegierig, DER Computerexperte schlecht hin
und immer bemüht durch kreative Ideen den Tag zu retten.&lt;/p&gt;

&lt;p&gt;Nun, heute denke ich mir:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Was wäre wohl aus mir geworden, wenn z.B.: ein Mad Max mein Vorbild 
geworden wäre?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;scifi&quot;&gt;SciFi&lt;/h3&gt;

&lt;p&gt;In der IT finden wir eine recht große Menge an &lt;a href=&quot;https://de.wikipedia.org/wiki/Science-Fiction&quot;&gt;SciFi&lt;/a&gt;
Fans, und das ist gut so!&lt;br /&gt;
Ich gebe aber zu, dass die Intensionen der Fans völlig unterschiedlich sind.
Star Trek und unzählige Referenzen darauf finden wir nicht nur in 
Computerspielen sondern auch in Programm- oder Komponentennamen. Gleiches
geschieht auch mit anderen Fantasy-Titeln wie z.B.: &lt;a href=&quot;https://de.wikipedia.org/wiki/Der_Herr_der_Ringe&quot;&gt;Herr der Ringe&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Ich war von Kindesbeinen an fasziniert von Raumschiffen. Und vor allem 
interessierte mich dort stets der “Maschinenraum” und der entsprechende 
Ingenieur, der mit kryptischen Schalter- und Tastenkombinationen dramatische 
Situationen herbeiführen oder auflösen konnte.&lt;/p&gt;

&lt;p&gt;Und so unterteilte ich die Serienfolgen in die Kategorien: Herz-Schmerz-Psycho 
und Technik.&lt;br /&gt;
Immer wenn eine Folge mit einem fremden Menschen begann, wusste ich, dass 
sich wer verlieben und dann jemand getötet wird und das langweilte mich sofort.
Wurde aber ein rätselhaftes Signal empfangen, war es sicher eine neue 
Lebensform oder ein astrologischen Phänomen, dass dem Schiff zuerst Schaden 
würde und nur durch technische Kniffe würde man die Situation auflösen können.
Genau das liebte ich und konnte mir diese Folgen in Endlosschleife durchgehend
ansehen.&lt;/p&gt;

&lt;h3 id=&quot;wenn-sich-das-weltbild-ändert&quot;&gt;Wenn sich das Weltbild ändert&lt;/h3&gt;

&lt;p&gt;Ich glaube, dass diese sich wiederholende Prämisse:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Wir können alles durch kreative neue Ideen in der Technik lösen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;meinen weiteren Lebensweg deutlich gezeichnet hat. Und als ich meinen ersten 
PC erhielt waren Spiele zwar auch interessant, doch die Vorstellung, man 
könnte dort “etwas erschaffen”, das dann auf Knopfdruck ein Problem 
selbstständig löst, führte mich unweigerlich zur Programmierung.&lt;/p&gt;

&lt;p&gt;Ich weiß nicht, ob mir dieser Weg wirklich so vorbestimmt war, oder ob er
mir durch bunte Bilder aus Film- und Fernsehen anerzogen wurde, aber ich 
bin mir sicher, dass ohne diesen Einfluss vieles anders verlaufen wäre.&lt;/p&gt;

&lt;p&gt;Obwohl ich die Folgen der “Herz-Schmerz-Psycho” Kategorie gerne mal 
übersprungen habe, stelle ich aber dennoch fest, dass sie einen womöglich
tieferen Eindruck hinterlassen haben, als ich das damals angenommen hätte.
Denn in jenen Szenen wurden oft gesellschaftskritische Ideen und Andeutungen
ausgestrahlt, die einen unterbewusst nachdenken lassen, ob unsere Welt nicht
an einigen Stellen schwer erkrankt ist, und wo wir durch “Technik” alleine
nichts bewirken können, sondern wo wir nur durch sich weiterentwickelnde 
Menschlichkeit und Anstand Verbesserungen erzielen können.&lt;/p&gt;

&lt;p&gt;Als der &lt;a href=&quot;https://en.wikipedia.org/wiki/Quark_(Star_Trek)&quot;&gt;Ferengi Quark&lt;/a&gt; in 
DS9 sich über sozialere Gesetzesentwürfe mit den 
Worten:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Wo kommen wir da hin, wenn man von seinen Angestellten nicht mal mehr
sexuelle Zuwendungen einfordern kann.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;lästert, habe ich damals gelacht.&lt;br /&gt;
Doch heute, nach einer &lt;a href=&quot;https://de.wikipedia.org/wiki/MeToo&quot;&gt;#Me-Too&lt;/a&gt; Debatte 
und mit der Lebenserfahrung wie unanständig es mancherorts zugeht, fällt mir 
mehr und mehr auf, dass diese subtile Szene damals meine heutige 
Aufmerksamkeit abändert.&lt;br /&gt;
Und ich bedauere, dass viele Mitmenschen diesen Blick nicht haben oder 
solche Missstände aktiv leugnen.&lt;/p&gt;

&lt;p&gt;Und es gäbe zahlreiche andere Beispiel zum Thema Kapitalismus, Populismus
und Umweltschutz, die ebenso durch plakative Szenen damals schon 
kommuniziert wurden.&lt;/p&gt;

&lt;h3 id=&quot;scifi-als-wegweiser-oder-realitätsflucht&quot;&gt;SciFi als Wegweiser oder Realitätsflucht&lt;/h3&gt;

&lt;p&gt;Ich bin der festen Überzeugung, das SciFi eine essenzielle Notwendigkeit für 
den Fortschritt ist. Wir brauchen jene kreativen Köpfe die sich eine Zukunft 
in bunten Bildern ausmalen und bei uns anderen die Sehnsucht auslösen, diese
Bilder Wirklichkeit werden zu lassen.&lt;br /&gt;
Wir brauchen auch Abstraktion und die Verlegung unserer aktuellen Problem in
eine fiktive Welt, wo wir sie mit fiktiven Lösungen bekämpfen können.&lt;br /&gt;
Denn nur so bekommen wir das sprichwörtliche Brett vor dem Kopf mal kurzfristig
abgelegt, damit wir aus der Vogelperspektive die Probleme der Realität erkennen
und angehen können.&lt;/p&gt;

&lt;p&gt;Oft beklagen wir aktuelle Verhältnisse aber sind unfähig selbst einen 
Lösungsweg zu erdenken, der allgemein gültig und nicht rein egoistisch motiviert
ist. Doch mit “erfundenen Modellen aus der Zukunft” können wir Denkhilfen 
nutzen und aus der Fallgrube namens &lt;em&gt;“Da-kann-man-eh-nix-machen”&lt;/em&gt; befreien.&lt;/p&gt;

&lt;p&gt;Doch nicht immer sind SciFi Produktionen der Weg zu Lösung. Und so bedauere
ich, dass ausgerechnet die modernen Mittel der Technik das SciFi Genre 
zumindest auf der Leinwand degenerieren lassen.&lt;/p&gt;

&lt;p&gt;Denn wenn man unter der Prämisse “Sex sells” keine 30 Minuten ohne einen
nackten Busen aufzeichnen kann, so wird SciFi leider immer mehr zur digitalen
Blitzgewitterschlacht.&lt;br /&gt;
Anstatt einer intelligenten Story, liegt das Hauptaugenmerk auf 
Spezieleffekten. Und es fließen Millionen in die Findung der richtigen Farbe 
eines Laserstrahls, während die Figuren keine vernünftigen Dialoge mehr 
abbekommen.&lt;/p&gt;

&lt;h3 id=&quot;fazit-denkt-an-die-zukunft&quot;&gt;Fazit: Denkt an die Zukunft!&lt;/h3&gt;

&lt;p&gt;Ich hoffe daher, dass einerseits die Autoren aber noch viel mehr die 
Produzenten von SciFi Titeln in Zukunft wieder mehr an die geistige Wirkung 
ihres Schaffens denken, als an reine Farbenspiele und schnelle Effekthascherei.&lt;/p&gt;

&lt;p&gt;Die Erfinder von Mobiltelefonen haben schon lange bekannt gegeben, dass 
Captain Kirks “Kommunikator” die Vorlage ihrer Idee war.&lt;br /&gt;
Und es gibt wohl auch keinen Astrophysiker, der nicht schon einmal über den
Warp-Antrieb nachgedacht hat.&lt;/p&gt;

&lt;p&gt;Daher ist es also wichtig “neue” Ideen aufkommen zu lassen um sie Stück für
Stück in die Köpfe der Menschen zu bringen. Vielleicht geht die eine oder 
andere Saat dort auf und wir können dann beruhigt ins Utopia von Morgen 
übersiedeln und schaffen es dort vielleicht unnötige Angewohnheiten wie
Krieg und Zerstörung hinter uns zu lassen.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>18650 Akku zu groß ???</title>
   <link href="https://www.opengate.at/blog/2020/01/accu-size/"/>
   <published>2020-01-26T12:00:00+01:00</published>
   <updated>2020-01-26T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2020/01/accu-size</id>
   <category term="hardware" />
   <summary type="text">Der 3D-Drucker hat das 
Modell fertig gedruckt, inklusive einem Fach für einen 
Lithium-Ionen Akku des Typs 18650.
Die Akkus wurden bestellt und geliefert.

Und dann …
… dann passen die Kack-Dinger nicht ins Gehäuse weil sie um 3-5 Millimeter
zu lang sind.
WTF ?
</summary>
   <content type="html">&lt;p&gt;&lt;a href=&quot;/blog/2019/01/ender-3/&quot;&gt;Der 3D-Drucker&lt;/a&gt; hat das 
Modell fertig gedruckt, inklusive einem Fach für einen 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Lithium-Ionen-Akkumulator&quot;&gt;Lithium-Ionen Akku des Typs 18650&lt;/a&gt;.&lt;br /&gt;
Die Akkus wurden bestellt und geliefert.&lt;/p&gt;

&lt;p&gt;Und dann …&lt;br /&gt;
… dann passen die Kack-Dinger nicht ins Gehäuse weil sie um 3-5 Millimeter
zu lang sind.&lt;br /&gt;
&lt;em&gt;WTF ?&lt;/em&gt;
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Viele Projekt-Modelle mit Akkus auf &lt;a href=&quot;https://www.thingiverse.com/&quot;&gt;thingiverse.com&lt;/a&gt;
bauen auf einer 18650 Lithium-Ionen Zelle auf.&lt;br /&gt;
Die Dinger sind ja auch wirklich super, können einen &lt;a href=&quot;https://de.wikipedia.org/wiki/Raspberry_Pi&quot;&gt;Raspberry PI&lt;/a&gt;
für Stunden, oder einen &lt;a href=&quot;https://de.wikipedia.org/wiki/Arduino_(Plattform)&quot;&gt;Arduino&lt;/a&gt; samt Sensoren
über Tage betreiben.&lt;br /&gt;
Sie liefern Energie von 2 bis etwas über 3 &lt;a href=&quot;https://de.wikipedia.org/wiki/Amperestunde&quot;&gt;Amperestunden&lt;/a&gt;
bei 3.7 Volt und sind in Kombination mit einem Step-Up Wandler auf 5 Volt 
(&lt;a href=&quot;https://de.wikipedia.org/wiki/Universal_Serial_Bus&quot;&gt;USB&lt;/a&gt; ) in recht vielen 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Powerbank&quot;&gt;Powerbanks&lt;/a&gt; verbaut.&lt;/p&gt;

&lt;p&gt;Sie sind höher und etwas dicker als handelsübliche &lt;a href=&quot;https://de.wikipedia.org/wiki/Alkali-Mangan-Zelle&quot;&gt;AA-Batterien&lt;/a&gt;.&lt;br /&gt;
Und man sollte (wie bei AA Batterien) erwarten, dass alle Akkus des Typs 18650
exakt gleich hoch gebaut sind.
OK, einige haben noch ein Höckerchen am 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Elektrischer_Pol&quot;&gt;Pluspol&lt;/a&gt; und sind um einen 
Millimeter höher, während dieser bei anderen Produktionen fehlt.&lt;/p&gt;

&lt;p&gt;Doch meine neu gelieferten Akkus waren mit 68 mm, 70 mm mit Pol, gegenüber
dem Standard von 65 mm um 5 Millimeter zu lang.&lt;br /&gt;
Denn die Nummer 18 &lt;strong&gt;65&lt;/strong&gt; 0 soll genau die 18 mm Breite und 65 mm Höhe 
ausdrücken.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/18650-sizes.jpg&quot; alt=&quot;18650-different-sizes&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;ursache-schutzschaltung&quot;&gt;Ursache: Schutzschaltung&lt;/h3&gt;

&lt;p&gt;Auf der Plastikfolienummantelung steht jedoch der Grund abgedruckt.&lt;br /&gt;
Denn die Akkus dieses Herstellers haben einen 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Lithium-Ionen-Akkumulator#(Integrierte)_Elektronik&quot;&gt;Überladungs- und Tiefentladungs-Schutz&lt;/a&gt;
eingebaut.&lt;/p&gt;

&lt;p&gt;Einerseits verzweifelt wegen der falschen Größe, andererseits neugierig 
auf “den Schutz” begann ich also einen meiner neuen Akkus zu zerlegen.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Warnung! Vorsicht ist hier geboten!&lt;/strong&gt; Wer in den Akku ein Loch hineinbohrt,
braucht erstens die Feuerwehr und zusätzlich noch eine Portion Glück.&lt;br /&gt;
Daher niemals eine Aktion setzen, die den Akku selbst in irgend einer Weise
beschädigt!!&lt;/p&gt;

&lt;p&gt;Nachdem sie mit einem Messer angeritzt wurde, ließ sich die Plastikfolie 
ähnlich leicht abziehen, wie das Plastiketikett einer Limonadeflasche.&lt;br /&gt;
Darunter wurde der Grund des Größenunterschiedes sofort sichtbar:&lt;br /&gt;
&lt;img src=&quot;/blog/assets/img/18650-dismantled.jpg&quot; alt=&quot;18650-dismantled&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Am Minuspol war ein runder Chipaufsatz angebracht, der mit einem dünnen 
Leiterstreifen entlang des Zylinders zum Pluspol verbunden war.
Dieser sollte also über seinen eigenen freiliegenden Minuspol den Strom 
zum richtigen Minuspol unterbrechen, wenn der Akku über- oder tiefentladen
werden würde.&lt;/p&gt;

&lt;p&gt;Der Leiterstreifen war mit einer weiteren Plastikfolie abisoliert, die 
ebenfalls leicht abgezogen werden konnte.&lt;br /&gt;
&lt;img src=&quot;/blog/assets/img/18650-dismantled-2.jpg&quot; alt=&quot;18650-dismantled-2&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Und mein kleiner Seitenschneider trennte den Schutzchip spielend leicht vom
Akku ab.&lt;br /&gt;
Nun hatte ich einen “echten” 18650-er in der Hand, der genau 65 mm lang war
und wieder perfekt in mein gedrucktes Gehäuse passte.&lt;br /&gt;
Mein Tag (und mein Projekt) ist wieder gerettet und die neuen Akkus können
also mit ein paar “Ent-wicklungs-Schritten” einsetzbar gemacht werden.&lt;br /&gt;
&lt;img src=&quot;/blog/assets/img/18650-parts.jpg&quot; alt=&quot;18650-parts&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;ergebnis&quot;&gt;Ergebnis&lt;/h3&gt;

&lt;p&gt;Eigentlich ist es ja blöd, dass man die Schutzschaltung entfernen muss. Sie
würde den Chip schließlich vor Schäden schützen.&lt;br /&gt;
Doch nachdem in Bastelprojekten meist ohnehin ein anderer 
&lt;a href=&quot;/blog/2019/11/lipo/&quot;&gt;Schutz-Chip&lt;/a&gt; zum Einsatz 
kommt, können wir davon mal absehen.&lt;/p&gt;

&lt;p&gt;Wichtig ist vor allem die Größe des Akkus, denn mit abweichenden Längen wird
es unmöglich (bzw. äußerst schwer) 3D-gedruckte Gehäusemodelle zu nutzen.&lt;br /&gt;
Ich hätte noch nicht einmal das Modell erweitern können, weil es dafür zu
komplex gestaltet war.&lt;/p&gt;

&lt;p&gt;Der Schutz-Chip wird aber aufgehoben und kommt in meine Sammellade.&lt;br /&gt;
Denn wenn gleich er momentan keinen Zweck erfüllt, so heißt das nicht,
dass es nicht morgen noch ein Projekt geben wird, wo sein Einsatz dankbar
angenommen wird.&lt;br /&gt;
Da er perfekt an den Akku angepasst ist, kann man ihn leicht wieder auf einen
solchen mit ein paar Drähten und etwas Lötzinn verpfropfen, oder ihn anderswo
z.B. zwischen ein Solarmodul oder einen 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Mikrocontroller&quot;&gt;MCU&lt;/a&gt; klemmen.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/18650-protection-chip.jpg&quot; alt=&quot;18650-protection-chip&quot; /&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>auto&amp;&amp; mit Tücken</title>
   <link href="https://www.opengate.at/blog/2020/01/auto-ref-ref/"/>
   <published>2020-01-25T12:00:00+01:00</published>
   <updated>2020-01-25T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2020/01/auto-ref-ref</id>
   <category term="devel" />
   <summary type="text">Dieses auto ist cool
schrieb ich mal. Und das stimmt auch weiter. Trotzdem muss ich jetzt ergänzen:


  Es ist cool, wenn man es richtig einsetzt und nicht mit Vollgas gegen 
die Wand fährt.


</summary>
   <content type="html">&lt;p&gt;Dieses &lt;a href=&quot;/blog/2019/09/auto-history/&quot;&gt;&lt;code&gt;auto&lt;/code&gt; ist cool&lt;/a&gt;
schrieb ich mal. Und das stimmt auch weiter. Trotzdem muss ich jetzt ergänzen:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Es ist cool, wenn man es richtig einsetzt und nicht mit Vollgas gegen 
die Wand fährt.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Ich musste mich jetzt wieder mal sehr über mich selbst ärgern.&lt;br /&gt;
Ein seltsames Problem trat auf, wobei unter &lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt;
eine spezielle Dateisuche mit &lt;a href=&quot;https://www.boost.org/doc/libs/1_62_0/libs/filesystem/doc/index.htm&quot;&gt;&lt;code&gt;boost::filesystem&lt;/code&gt;&lt;/a&gt;
fehlschlug, die unter &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows&quot;&gt;Windows&lt;/a&gt;
brav arbeitete.&lt;/p&gt;

&lt;p&gt;… oder sagen wir mal, unter Windows im Debug-Modus brav arbeitete …&lt;/p&gt;

&lt;p&gt;Nach einer quälenden Suche an den falschen Stellen, landete ich irgendwann
bei der Zeile:&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;auto&lt;/span&gt;&amp;amp;&amp;amp; dirname = dirpath.filename().&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;string&lt;/span&gt;();
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;&lt;code&gt;dirname&lt;/code&gt; beinhaltete nach der Zeile nur noch defekte Datenblöcke.&lt;/p&gt;

&lt;p&gt;Hmm … Habe ich nicht mal gesagt, dass &lt;code&gt;auto&amp;amp;&amp;amp;&lt;/code&gt; die &lt;em&gt;beste&lt;/em&gt;
Möglichkeit ist, den Rückgabewert einer Funktion generisch anzunehmen?&lt;/p&gt;

&lt;p&gt;Ja, das stimmt auch, aber nur wenn der Typ auch stabil bleibt, und das
ist in dem Beispiel nicht der Fall.&lt;/p&gt;

&lt;p&gt;Denn &lt;code&gt;dirpath.filename()&lt;/code&gt; erzeugt ein neues temporäres Objekt und 
&lt;code&gt;.string()&lt;/code&gt; gibt eine konstante String-Referenz auf einen seiner Member 
zurück.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;auto&amp;amp;&amp;amp;&lt;/code&gt; macht dann genau das, was es gut kann, nämlich den 
&lt;code&gt;std::string const &amp;amp;&lt;/code&gt; entgegenzunehmen.&lt;/p&gt;

&lt;p&gt;Doch nach dieser Zeile wird das temporäre Objekt von &lt;code&gt;dirpath.filename()&lt;/code&gt;
zerstört und die konstante String-Referenz zeigt jetzt auf freigegebenen
ungültigen Speicher.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;Gefahr erkannt, Gefahr gebannt&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;würde ich sagen … aber es ärgert mich, dass mir das nicht gleich 
aufgefallen ist.
&lt;code&gt;auto&amp;amp;&amp;amp;&lt;/code&gt; ist nur &lt;em&gt;gut&lt;/em&gt;, wenn es einen Rückgabewerte der ersten Ebene
direkt erhält, wie z.B.:&lt;br /&gt;
&lt;code&gt;auto&amp;amp;&amp;amp; subtext = text.substr(...);&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Die Lösung des Code-Problems ist aber einfach:&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;auto&lt;/span&gt; dirname = dirpath.filename().&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;string&lt;/span&gt;();
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Hier wird &lt;code&gt;auto&lt;/code&gt; in einen einfachen &lt;a href=&quot;https://en.cppreference.com/w/cpp/string/basic_string&quot;&gt;&lt;code&gt;std::string&lt;/code&gt;&lt;/a&gt;
aufgelöst, und der bewirkt eine Kopie des Elements aus dem temporären 
Objektes.&lt;br /&gt;
Diese Kopie überlebt dann auch regulär die Zerstörung der temporären
Instanz und kann gefahrlos weiter eingestetzt werden.&lt;/p&gt;

&lt;p&gt;Alternative hätte man aber natürlich auch:&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;auto&lt;/span&gt;&amp;amp;&amp;amp; dirpath_filename = dirpath.filename();
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;auto&lt;/span&gt;&amp;amp;&amp;amp; dirname = dirpath_filename.&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;string&lt;/span&gt;();
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;schreiben können. … doch das sieht etwas seltsam aus.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>MSVC: afxres.h vs winresrc.h</title>
   <link href="https://www.opengate.at/blog/2020/01/afxres/"/>
   <published>2020-01-19T12:00:00+01:00</published>
   <updated>2020-01-19T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2020/01/afxres</id>
   <category term="devel" />
   <summary type="text">Da arbeitet man schier ewig mit Visual Studio
an einem C++ Projekt, und eines Tages
ist es so weit: Man bekommt einen neuen PC, installiert MSVC, lädt sein 
Projekt, kompiliert … und dann erscheint die Meldung:


  fatal error RC1015: cannot open include file &apos;afxres.h&apos;.


Wie kann das nur sein?
Warum braucht eine Resource-Datei (*.rc)
diesen Header und warum existiert er plötzlich nicht mehr?
</summary>
   <content type="html">&lt;p&gt;Da arbeitet man schier ewig mit &lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_Studio&quot;&gt;Visual Studio&lt;/a&gt;
an einem &lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B&quot;&gt;C++&lt;/a&gt; Projekt, und eines Tages
ist es so weit: Man bekommt einen neuen PC, installiert MSVC, lädt sein 
Projekt, kompiliert … und dann erscheint die Meldung:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;code&gt;fatal error RC1015: cannot open include file &apos;afxres.h&apos;.&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Wie kann das nur sein?&lt;br /&gt;
Warum braucht eine &lt;a href=&quot;http://docs.microsoft.com/en-us/windows/win32/menurc/about-resource-files&quot;&gt;Resource-Datei (*.rc)&lt;/a&gt;
diesen Header und warum existiert er plötzlich nicht mehr?
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;die-lösung&quot;&gt;Die Lösung&lt;/h3&gt;

&lt;p&gt;Handelt es sich um ein &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Foundation_Classes&quot;&gt;MFC Projekt&lt;/a&gt;
(denn &lt;code&gt;afxres.h&lt;/code&gt; stammt aus dieser Richtung), dann hat man vergessen den 
MFC-Support bei der Installation von Visual Studio zu installieren. Manchmal 
soll auch &lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B/CLI&quot;&gt;C++/CLI&lt;/a&gt; notwendig und 
deshalb mitinstalliert sein.&lt;br /&gt;
Also &lt;code&gt;Visual Studio Installer&lt;/code&gt; aufrufen und die fehlenden Haken für die 
Nachinstallation setzen.&lt;/p&gt;

&lt;p&gt;Es kommt aber auch gerne vor, dass eine Resource-Datei den Header 
“versehentlich” einfordert und ihn gar nicht braucht. Dann sollte die 
Problem-Include-Zeile durch&lt;br /&gt;
&lt;code&gt;#include &amp;lt;winresrc.h&amp;gt;&lt;/code&gt;&lt;br /&gt;
ersetzt werden.&lt;/p&gt;

&lt;h3 id=&quot;wozu-das-alles&quot;&gt;Wozu das alles?&lt;/h3&gt;

&lt;p&gt;In einer Resource-Datei stehen viele selbst definierte Symbole, unter denen
dann Texte, &lt;a href=&quot;https://de.wikipedia.org/wiki/ICO_(Dateiformat)&quot;&gt;Symboldatei-Links (*.ico)&lt;/a&gt;
oder Menü- und Dialogeinträge definiert werden. Und nicht zu vergessen, 
die &lt;a href=&quot;http://docs.microsoft.com/en-us/windows/win32/menurc/versioninfo-resource&quot;&gt;&lt;code&gt;VS_VERSION_INFO&lt;/code&gt; Struktur&lt;/a&gt;, 
die Metainformationen über Datei-Version und Hersteller standardisiert in eine
&lt;a href=&quot;https://de.wikipedia.org/wiki/EXE&quot;&gt;EXE&lt;/a&gt; oder 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Dynamic_Link_Library&quot;&gt;DLL&lt;/a&gt; einbettet.&lt;/p&gt;

&lt;p&gt;All diese Resource-Einträge mit ihren Text-Namen sind nichts anderes als 
&lt;a href=&quot;https://de.wikipedia.org/wiki/C-Pr%C3%A4prozessor&quot;&gt;C-Makros&lt;/a&gt;, die in der 
Regel auf Integerkonstanten verweisen.&lt;/p&gt;

&lt;p&gt;Und genau deshalb müssen Header eingebunden werden, die diese Makros 
definieren.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;winresrc.h&lt;/code&gt; ist eigentlich der korrekte Header für eine Windows-Applikation,
doch Bibliotheken wie MFC und &lt;a href=&quot;https://de.wikipedia.org/wiki/Active_Template_Library&quot;&gt;ATL&lt;/a&gt;
stellen ihre eigenen Wrapper bereit, um eigene Zusätze beizumengen, nachdem 
sie selbst intern &lt;code&gt;winresrc.h&lt;/code&gt; einbinden. &lt;code&gt;afxres.h&lt;/code&gt; macht das auch so.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Es passiert mir auch alle heiligen Zeiten wieder, dass ich über das Problem
stolpere, mich wundere, dann nachdenke und mir noch einfällt:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ah, da war doch was … aber was … ?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Hiermit hätte ich das mal auf den &lt;a href=&quot;https://de.wikipedia.org/wiki/Blog&quot;&gt;Blog&lt;/a&gt;
gestellt und hoffe, dass ich mich an ihn erinnere, wenn mir &lt;code&gt;afxres.h&lt;/code&gt; das 
nächste mal vor die Füße läuft.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Zugang zum Internet</title>
   <link href="https://www.opengate.at/blog/2020/01/internet/"/>
   <published>2020-01-18T12:00:00+01:00</published>
   <updated>2020-01-18T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2020/01/internet</id>
   <category term="software" /><category term="hardware" /><category term="retro" />
   <summary type="text">Samstag Nachmittag … und ich ärgere mich wie gewohnt über 
das Internet.
Eigentlich nicht über das Internet, sondern meinen Zugang dazu.

Während ich also “warten muss”, bis ein Update langsam fertig wird, bleibt
etwas Zeit um über die Vergangenheit nachzudenken.

War “das Internet” früher besser?
</summary>
   <content type="html">&lt;p&gt;Samstag Nachmittag … und ich ärgere mich wie gewohnt über 
das &lt;a href=&quot;https://de.wikipedia.org/wiki/Internet&quot;&gt;Internet&lt;/a&gt;.
Eigentlich nicht über das Internet, sondern meinen Zugang dazu.&lt;/p&gt;

&lt;p&gt;Während ich also “warten muss”, bis ein Update langsam fertig wird, bleibt
etwas Zeit um über die Vergangenheit nachzudenken.&lt;/p&gt;

&lt;p&gt;War “das Internet” früher besser?
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Das Internet ging bis zum Jahr 2000 an mir spurlos vorüber. Man hörte oder 
las zwar im Häuschen auf dem Lande, dass es das gibt, aber für einen selbst 
war es viel zu teuer und damit unerreichbar.&lt;/p&gt;

&lt;p&gt;Als kurz vor der Jahrtausendwende die ersten Schulkollegen berichteten, Papa
hätte jetzt ein &lt;a href=&quot;https://de.wikipedia.org/wiki/Modem&quot;&gt;Modem&lt;/a&gt; und man könne 
jetzt im Internet “surfen”, entstand natürlich weitere Neugier.&lt;/p&gt;

&lt;p&gt;Meine Schule hatte zwar “einen” Internet-Zugang für alle eingerichtet, doch
das sah so aus:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;1 einzelnes Modem stellte eine Verbindung ins Netz her&lt;/li&gt;
  &lt;li&gt;Die Maximalgeschwindigkeit waren 56 KBit, also 7 Kilobyte pro Sekunde,
und bestenfalls erreicht wurden vielleicht 5 KB/s&lt;/li&gt;
  &lt;li&gt;Über einen &lt;a href=&quot;https://de.wikipedia.org/wiki/Proxy_%28Rechnernetz%29&quot;&gt;Proxy-Server&lt;/a&gt; 
wurde diese Verbindung auf alle PCs verteilt.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Wenn man also bis spät am Nachmittag (kurz bevor der letzte Bus heim fuhr) 
alleine im Gebäude sitzen blieb, konnte man tatsächlich die eine oder 
andere Seite öffnen, um Grafiken oder ein paar kleine 
&lt;a href=&quot;https://de.wikipedia.org/wiki/ZIP-Dateiformat&quot;&gt;ZIP-Dateien&lt;/a&gt; herunterladen.&lt;br /&gt;
Während der regulären Schulzeit dauerte das Aufrufen von Seiten teilweise
3 bis 5 Minuten und Downloads liefen (kein Witz!) mit 200 Bytes pro Sekunde.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Man kann es sich heute einfach nicht mehr vorstellen.&lt;/em&gt;&lt;br /&gt;
Und so meinte ich damals, dass das Internet zwar eine nette Spielerei sei,
aber Daten und Medien dennoch weiter auf &lt;a href=&quot;https://de.wikipedia.org/wiki/Diskette&quot;&gt;Disketten&lt;/a&gt;
und CDs verbreitet werden würden.&lt;/p&gt;

&lt;p&gt;Na jedenfalls bekam ich dann im Jahr 2000 das gebrauchte 
&lt;a href=&quot;/blog/2019/03/56k-modem/&quot;&gt;Modem&lt;/a&gt; eines Freundes
und konnte so die heimische Telefonleitung als Datenzugang nutzen.
Das lief übrigens in Verbindung mit meinem Prepaid-&lt;a href=&quot;https://de.wikipedia.org/wiki/Mobiltelefon&quot;&gt;Mobiltelefon&lt;/a&gt;.&lt;br /&gt;
Denn wer damals bei &lt;a href=&quot;http://www.a1.net&quot;&gt;A1&lt;/a&gt; eine Nummer hatte, bekam auch 
eine Einwahlnummer dazu, um über ein Festnetzmodem ins Internet zu kommen.
Abgerechnet wurde das dann aber beim Besitzer des Festnetzanschlusses, 
also bei Mama.&lt;/p&gt;

&lt;p&gt;Bereits ein Jahr später erlebte ich durch die Übersiedelung nach Wien 
das &lt;a href=&quot;https://de.wikipedia.org/wiki/Breitband-Internetzugang&quot;&gt;Breitbandwunder&lt;/a&gt;. 
Über Telekabel strömten bis zu 300 KBit/s in meine Wohnung, und durch 
Downloads mit 30 KB/s erreichte ich dieses Limit häufiger.&lt;br /&gt;
Das Internet war in Wien also 10 mal schneller als am Land über Modem.&lt;/p&gt;

&lt;p&gt;Jetzt muss ich aber hinzufügen, dass im alten Heim das 56K Modem weiter
als primäres Internet bestehen blieb.&lt;br /&gt;
Es war ein regelrechter Alptraum am Wochenende ins andere Zuhause zu wechseln,
wo man sich dann wie in der digitalen Steinzeit fühlte, während wochentags 
stets ein frischer Datenwind durch die Leitungen floss.&lt;/p&gt;

&lt;p&gt;Zu dieser Zeit war für mich klar: &lt;em&gt;Internet braucht man einfach.&lt;/em&gt;
Und trotzdem ließ ich mich zu der heute witzigen Aussagen hinreißen:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Für’s Internet kann man alte 10 MBit Netzwerkkarten nutzen, weil das
Internet an diese Geschwindigkeit wohl erst in Jahrzehnten herankommen
wird.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;Chello&lt;/em&gt;, so hieß das Internet-Produkt von &lt;a href=&quot;https://de.wikipedia.org/wiki/UPC_Austria&quot;&gt;UPC Telekabel Wien&lt;/a&gt; 
damals, nutzte eigene &lt;a href=&quot;https://de.wikipedia.org/wiki/Kabelmodem&quot;&gt;Kabelmodems&lt;/a&gt;, 
die direkt über den &lt;a href=&quot;https://de.wikipedia.org/wiki/RJ-Steckverbindung&quot;&gt;RJ45 Port&lt;/a&gt;
der Netzwerkkarte an den PC angeschlossen wurden. Man musste die eigene 
&lt;a href=&quot;https://de.wikipedia.org/wiki/MAC-Adresse&quot;&gt;MAC-Adresse&lt;/a&gt; für sein Modem 
registrieren lassen um damit ins Netz zu kommen.&lt;br /&gt;
Eine Einwahl gab es dafür nicht, war das Kabelmodem eingeschaltet, war
man im Netz … ein Novum für damals.&lt;/p&gt;

&lt;p&gt;Während am Zweitwohnsitz die 5 KB pro Sekunde immer unerträglicher wurden,
wurde die Datenrate in Wien stetig gesteigert.
Zuerst waren es 600 KBit, dann 1 MBit, 2 MBit, 4 MBit, 6 MBit und ich 
glaube so gegen 2007 waren die 10 MBit erreicht. Jedenfalls hatte ich 
damals einen Screenshot erstellt, wo ein Download mit 1.5 MByte/s 
heruntergeladen werden konnte.&lt;br /&gt;
Zum Glück war ich da schon lange auf eine 100 MBit Netzwerkkarte umgestiegen.&lt;/p&gt;

&lt;p&gt;Korrekterweise muss man hinzufügen, dass im Telekabelnetz die Uploadraten
etwa ein viertel der Downloadrate betrugen. z.B.: 10 MBit Downstream, aber nur
2 - 3 MBit Upstream, doch zum Glück war dies alles einer 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Flatrate&quot;&gt;Flatrate&lt;/a&gt; zugeordnet.&lt;br /&gt;
Die Kosten lagen pro Monat bei um die 30 bis 40 Euro. Nachdem der Internet-Zugang
mit dem Kabelfernsehen verknüpft war, kann ich das nicht mehr so genau sagen.
Doch in Summe waren anfangs 50 und später 70 Euro im Monat fällig.&lt;/p&gt;

&lt;p&gt;Irgendwann um 2010 kaufte ich mir zusätzlich einen &lt;a href=&quot;https://de.wikipedia.org/wiki/UMTS-Modem&quot;&gt;USB UMTS Stick&lt;/a&gt;, 
der meinen &lt;a href=&quot;https://en.wikipedia.org/wiki/Laptop&quot;&gt;Laptop&lt;/a&gt; auch unterwegs mit 
“Internet” versorgen sollte.&lt;br /&gt;
Das war dann ein merkbarer Rückschritt, denn dort wurde pro Übertragung 
abgerechnet (und zwar 4 Euro pro GB), und außerdem waren die Datenraten 
wesentlich geringer.&lt;br /&gt;
Aber für unterwegs war das OK und in den folgenden Jahren wurde das auch 
schrittweise besser.&lt;/p&gt;

&lt;p&gt;2015 kam es dann zwischen mir und UPC Telekabel zum Bruch. Als nun 15-jähriger
Altkunde sah ich die Preispolitik als absolute Abzocke an. Mir wurden pro Monat
70 Euro abgerechnet, während Neukunden im ersten Jahr 10-15 und nachfolgend
20-25 Euro für den gleichen Internettarif abgerechnet bekamen.&lt;/p&gt;

&lt;p&gt;Nach mehreren ignoranten E-Mails seitens des Supports, kündigte ich den 
Vertrag und wechselte zum Mobilfunker &lt;a href=&quot;http://www.drei.at&quot;&gt;Drei.at&lt;/a&gt;, der 
über &lt;a href=&quot;https://de.wikipedia.org/wiki/Long_Term_Evolution&quot;&gt;LTE&lt;/a&gt; eine 30 MBit 
Flatrate für 25 Euro anbot.&lt;br /&gt;
Der Vorteil war aus meiner Sicht, die kleine Funk-Box, die überall im Lande 
funktionieren sollte und nicht nur in meiner Wohnung.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/lte-tube.jpg&quot; alt=&quot;LTE Modem&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Technisch betrachtet war das aber ein Rückschritt, denn UPC hatte zu dieser
Zeit seine Geschwindigkeit schon auf 30 MBit hochgeschraubt und diese sollte
künftig weiter anwachsen … keine Ahnung wo sie heute ist.&lt;/p&gt;

&lt;p&gt;Doch ich muss sagen, selbst Videos lassen sich mit den 30 MBit für mich immer
noch gut beziehen, und ob mich ein ISO-Image-Download jetzt 40 oder 20 
Minuten kostetet, ist mir zur Zeit ziemlich gleichgültig.&lt;/p&gt;

&lt;h3 id=&quot;-mit-einer-ausnahme&quot;&gt;… mit einer Ausnahme:&lt;/h3&gt;

&lt;p&gt;An Wochenenden merke ich leider dann doch, dass ich mit einem mobilen 
Breitbandnetz in einem geteilten Netzwerk koexistiere, dessen Geschwindigkeit
mit jedem weiteren Nutzer sinkt.&lt;br /&gt;
Und da fallen die Downloads schon mal gerne auf ein paar hundert Kilobyte pro
Sekunde zurück, was bei heutigen Updates und Videos nervig ist.&lt;/p&gt;

&lt;p&gt;Mein großes Glück ist jedoch, dass ich hauptsächlich Nachts im Internet 
unterwegs bin. Und je später die Stunde um besser wird das Netz.&lt;br /&gt;
Früher war das übrigens auch so … aber vorwiegend, weil die Server tagsüber
schneller ausgelastet waren und nachts Kapazitäten frei wurden.&lt;/p&gt;

&lt;p&gt;Und nachdem der Ausbau des neuen &lt;a href=&quot;https://de.wikipedia.org/wiki/5G&quot;&gt;5G Netzes&lt;/a&gt; 
angelaufen ist, wird es für mich in Zukunft wohl auch eine schnellere 
Alternative geben, zu der ich wechseln kann.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Oh … die Downloads des neuen &lt;a href=&quot;https://de.wikipedia.org/wiki/Raspberry_Pi&quot;&gt;Raspberry PI&lt;/a&gt;
Images sind fertig. Na, dann kann’s ja weitergehen, und “mein Internet” darf
sich ein bisschen ausruhen.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Wenn gmtime() das Zeitliche segnet</title>
   <link href="https://www.opengate.at/blog/2020/01/timeless/"/>
   <published>2020-01-12T12:00:00+01:00</published>
   <updated>2020-01-12T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2020/01/timeless</id>
   <category term="devel" />
   <summary type="text">Ich weiß leider schon heute, dass mir in diesem Leben nicht mehr genug Zeit 
bleiben wird, das Zeit-API 
Chaos weltweit zu lösen.

Seit meinem Einstieg in die C++ 
Programmierung muss ich mit dem Thema Zeit und Zeitzonen kämpfen und es ist 
unerträglich, dass es bis ins Jahr 2020 nicht einheitlich möglich war, eine 
genormte Schnittstelle dafür zu schaffen.
</summary>
   <content type="html">&lt;p&gt;Ich weiß leider schon heute, dass mir in diesem Leben nicht mehr genug Zeit 
bleiben wird, das Zeit-&lt;a href=&quot;https://de.wikipedia.org/wiki/Programmierschnittstelle&quot;&gt;API&lt;/a&gt; 
Chaos weltweit zu lösen.&lt;/p&gt;

&lt;p&gt;Seit meinem Einstieg in die &lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B&quot;&gt;C++&lt;/a&gt; 
Programmierung muss ich mit dem Thema Zeit und Zeitzonen kämpfen und es ist 
unerträglich, dass es bis ins Jahr 2020 nicht einheitlich möglich war, eine 
genormte Schnittstelle dafür zu schaffen.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Theoretisch hatten die &lt;a href=&quot;https://de.wikipedia.org/wiki/C_(Programmiersprache)&quot;&gt;C&lt;/a&gt; 
und &lt;a href=&quot;https://de.wikipedia.org/wiki/Portable_Operating_System_Interface&quot;&gt;POSIX&lt;/a&gt; 
Erfinder einen korrekten Grundstein gesetzt.
Es gibt eine integrale Einheit um Zeitpunkte einfach darzustellen, nämlich den 
Integer Typ &lt;code&gt;time_t&lt;/code&gt;, der die Sekunden seit dem 1. 1. 1970 UTC zählt, und dann
haben wir noch mit der &lt;code&gt;struct tm&lt;/code&gt; die Möglichkeit der Umwandlung in den 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Gregorianischer_Kalender&quot;&gt;gregorianischen Kalender&lt;/a&gt;, 
also DEM Standard-Kalender dieser Welt.&lt;/p&gt;

&lt;p&gt;Dass der C Standard nicht auch noch andere Kalender oder Nanosekunden kennt, 
ist der Prämisse geschuldet eine platzsparende Implementierung zu besitzen 
und außerdem kann diese Aufgabe auch eine Drittbibliothek übernehmen.&lt;/p&gt;

&lt;p&gt;Und Funktionen wie &lt;a href=&quot;http://www.cplusplus.com/reference/ctime/gmtime/&quot;&gt;&lt;code&gt;gmtime&lt;/code&gt;&lt;/a&gt;,
&lt;a href=&quot;http://www.cplusplus.com/reference/ctime/localtime/&quot;&gt;&lt;code&gt;localtime&lt;/code&gt;&lt;/a&gt;, und
&lt;a href=&quot;http://www.cplusplus.com/reference/ctime/mktime/&quot;&gt;&lt;code&gt;mktime&lt;/code&gt;&lt;/a&gt; können zwischen
dem Zeitstempel und dem Kalenderdatum hin und her konvertieren.
Die Problemkinder &lt;a href=&quot;https://de.wikipedia.org/wiki/Zeitzone&quot;&gt;Zeitzonen&lt;/a&gt; und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Sommerzeit&quot;&gt;Sommerzeit&lt;/a&gt; lassen wir hier mal aus.&lt;/p&gt;

&lt;p&gt;Und dann wurde bei diesen APIs die schwersten Fehler überhaupt gemacht.
Denn &lt;code&gt;gmtime&lt;/code&gt; und &lt;code&gt;localtime&lt;/code&gt; schreiben ihr Ergebnis in eine private 
&lt;a href=&quot;https://en.wikipedia.org/wiki/Global_variable&quot;&gt;globale Variable&lt;/a&gt;
und geben einen Pointer darauf zurück.&lt;/p&gt;

&lt;p&gt;Das ist deshalb so unglaublich dumm, weil die meisten C APIs immer schon 
mit dem Konzept arbeiteten, dass man einen Byte-Puffer an eine Funktion
übergibt, diese den Puffer befüllt und schon hat man seine Daten an der
gewünschten Stelle. Doch nein, Kalender liegen in einer fremden globalen
Variable, die bei jedem Aufruf überschrieben wird.&lt;/p&gt;

&lt;p&gt;Das bring natürlich jedes Programm zum Absturz (oder zumindest korrumpierte
Ergebnisse), welches mit mehr als einem Thread läuft.&lt;/p&gt;

&lt;p&gt;Doch dieses Problem wurde in den 90ern erkannt und hier hätte (wie in vielen
anderen Beispielen) eine neue API das Problem lösen können. 
… aber Fehlanzeige!&lt;/p&gt;

&lt;p&gt;Microsoft implementierte daher die Funktionen &lt;a href=&quot;http://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/gmtime-s-gmtime32-s-gmtime64-s?view=vs-2019&quot;&gt;&lt;code&gt;gmtime_s&lt;/code&gt;&lt;/a&gt;
und &lt;a href=&quot;http://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/localtime-s-localtime32-s-localtime64-s?view=vs-2019&quot;&gt;&lt;code&gt;localtime_s&lt;/code&gt;&lt;/a&gt;, 
im Rahmen seiner Safe-CRT, während die POSIX-Community eine vorgeblich
bessere Erfindung machte, nämlich &lt;a href=&quot;http://www.unix.com/man-page/POSIX/3posix/gmtime_r/&quot;&gt;&lt;code&gt;gmtime_r&lt;/code&gt;&lt;/a&gt; und 
&lt;a href=&quot;http://www.unix.com/man-page/POSIX/3posix/localtime_r/&quot;&gt;&lt;code&gt;localtime_r&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Diese beiden APIs tun exakt das gleiche, sie konvertieren einen &lt;code&gt;time_t&lt;/code&gt; in 
eine &lt;code&gt;struct tm&lt;/code&gt;, welcher vom Aufrufer allokiert werden muss.&lt;br /&gt;
Doch intelligenterweise nutzen die beiden Konventionen eine
gegengleiche Funktionssignatur.&lt;/p&gt;

&lt;p&gt;Noch dümmer wurde es, als die Microsoft-API-Namen in den C-Standard
wanderten (der von POSIX wiederum ignoriert wird), aber die Signatur
der POSIX Routinen trägt.&lt;/p&gt;

&lt;p&gt;Am Ende sind alle diese API-Ansätze vollkommen nutzlos für portable Programme.&lt;/p&gt;

&lt;p&gt;Und dass C++ dieses Manko erst im kommenden Standard &lt;a href=&quot;https://en.wikipedia.org/wiki/C%2B%2B20&quot;&gt;C++20&lt;/a&gt; 
ausgleichen will, indem es &lt;a href=&quot;http://en.cppreference.com/w/cpp/chrono&quot;&gt;&lt;code&gt;std::chrono&lt;/code&gt;&lt;/a&gt;
mit ein paar neuen Konvertern ausstatten will halte ich heute, 15 Jahre zu 
spät, für eine Frotzelei.&lt;/p&gt;

&lt;h3 id=&quot;workaround&quot;&gt;Workaround&lt;/h3&gt;

&lt;p&gt;Ich hasse so etwas wirklich, aber was bleibt einem übrig außer folgendes
zu schreiben:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color:#B44;font-weight:bold&quot;&gt;&amp;lt;time.h&amp;gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#ifdef&lt;/span&gt; WIN32
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;inline&lt;/span&gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;struct&lt;/span&gt; tm *gmtime_r(&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt; time_t *timep, &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;struct&lt;/span&gt; tm *result)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt;(&lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt; == gmtime_s(result, timep))
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;  {
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; result;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;else&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;  {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color:#069&quot;&gt;NULL&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;  }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;}
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;  
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;inline&lt;/span&gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;struct&lt;/span&gt; tm *localtime_r(&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt; time_t *timep, &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;struct&lt;/span&gt; tm *result)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt;(&lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt; == localtime_s(result, timep))
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n21&quot; name=&quot;n21&quot;&gt;21&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; result;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n22&quot; name=&quot;n22&quot;&gt;22&lt;/a&gt;&lt;/span&gt;  }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n23&quot; name=&quot;n23&quot;&gt;23&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;else&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n24&quot; name=&quot;n24&quot;&gt;24&lt;/a&gt;&lt;/span&gt;  {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n25&quot; name=&quot;n25&quot;&gt;25&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color:#069&quot;&gt;NULL&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n26&quot; name=&quot;n26&quot;&gt;26&lt;/a&gt;&lt;/span&gt;  }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n27&quot; name=&quot;n27&quot;&gt;27&lt;/a&gt;&lt;/span&gt;}
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n28&quot; name=&quot;n28&quot;&gt;28&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#endif&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ich bin jedes mal wieder sauer, wenn ich im Zuge eines Projektes über diese
Katastrophe stoße.&lt;br /&gt;
Bei all den wirklich gut designten Elementen von C und C++ ist die 
“Verwaltung der Zeit” ein Zeugnis von Unwilligkeit untereinander
sich auf einen Standard zu einigen, dass es weh tut.&lt;/p&gt;

&lt;p&gt;Und ja, ich weiß … man könnte &lt;a href=&quot;https://de.wikipedia.org/wiki/Boost_(C%2B%2B-Bibliothek)&quot;&gt;BOOST&lt;/a&gt;
dafür nutzen, welches viele unterschiedliche Ansätze für Zeitrechnungen
bereitstellt.&lt;br /&gt;
Aber ich sehe nicht ein, warum die einfache Konvertierung von &lt;code&gt;time_t&lt;/code&gt; auf
&lt;code&gt;struct tm&lt;/code&gt; nicht schon 1998 bzw. spätestens 2011 im Standard aktualisiert 
wurde.&lt;/p&gt;

&lt;p&gt;Im GATE Projekt ist das jedenfalls schon lange implementiert … mehr als 
einen Tag Arbeitszeit kostet das schließlich auch nicht!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Der Schalter wars</title>
   <link href="https://www.opengate.at/blog/2020/01/lamp-switch/"/>
   <published>2020-01-11T12:00:00+01:00</published>
   <updated>2020-01-11T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2020/01/lamp-switch</id>
   <category term="hardware" />
   <summary type="text">Wieviel Hardware habe ich wohl in den vergangenen beiden Jahrzehnten in den
Müll geworfen, weil sie nicht mehr funktionierte?

Heute nehme ich mit Schrecken zur Kenntnis, dass Vieles mit einigen wenigen
Handgriffen repariert werden kann und vermutlich war das auch bei meinem
früheren Müll so.

Und so hat nun meine alte IKEA Tischlampe ebenso ein zweites Leben erhalten.
</summary>
   <content type="html">&lt;p&gt;Wieviel Hardware habe ich wohl in den vergangenen beiden Jahrzehnten in den
Müll geworfen, weil sie nicht mehr funktionierte?&lt;/p&gt;

&lt;p&gt;Heute nehme ich mit Schrecken zur Kenntnis, dass Vieles mit einigen wenigen
Handgriffen repariert werden kann und vermutlich war das auch bei meinem
früheren Müll so.&lt;/p&gt;

&lt;p&gt;Und so hat nun meine alte IKEA Tischlampe ebenso ein zweites Leben erhalten.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Neulich konnte ich einen für den Mistplatz vorgesehenen Fernseher retten.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Der lässt sich nicht mehr einschalten.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;hieß es. Doch mit meinem alten &lt;a href=&quot;https://de.wikipedia.org/wiki/Mini-ITX&quot;&gt;ITX&lt;/a&gt; 
PC-Netzteil, lief er plötzlich wieder. Mit 10 Euro für ein neues
externes Netzteil wurde somit eine 100-200 Euro Neuanschaffung abgewendet.&lt;/p&gt;

&lt;p&gt;Ist doch echt Wahnsinn, wie leicht man Müll verhindern kann, wenn man nur mal
“einen anderen Stecker” ausprobiert.&lt;/p&gt;

&lt;p&gt;So auch mit meiner über 10 Jahre alten IKEA Tischlampe.
Im letzten Jahr begann sie gelegentlich seltsam zu flackern bis sie dann
eines Tages nur noch mit halber Kraft leuchtete und sich manchmal gar nicht
mehr einschalten ließ.&lt;/p&gt;

&lt;p&gt;Ich dachte mir, dass ihr Netzteil defekt wäre, das direkt im Stecker
integriert war und wollte mir damit keine weiteren Mühen machen.
Doch zufällig merkte ich, dass bei bestimmten Bewegungen der Lampe 
plötzlich wieder volle Leuchtkraft herrschte.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ist das also bloß ein Wackelkontakt?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;dachte ich mir und begann weiter an den Kabeln herum zu rütteln.
Und man glaubt es kaum, das Problem lag wohl am Kabel direkt am
Schalter der Lampe.&lt;/p&gt;

&lt;p&gt;Der Schalter war ohne Schrauben über 4 Stifte einfach zusammengesteckt und
konnte leicht mit einem Schraubenzieher und etwas Hebelwirkung geöffnet 
werden.&lt;/p&gt;

&lt;p&gt;Und schon sah ich, dass auf einer Seite der Draht fast durchgerissen war.
Nur wenige Litzen waren im Schalterkontakt eingeklemmt.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/ikea_lamp_switch.jpg&quot; alt=&quot;IKEA Lamp Switch&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Die Lösung war denkbar einfach, der abgerissene Teil wurde weggeschnitten
und das frisch abisolierte Drahtstück durch einer Adernhülse mit einer
Presszange an den Kontakt gebunden.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/jointing-clamp.jpg&quot; alt=&quot;Jointing clamp&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Zur Sicherheit ließ ich noch ein bisschen Lötzinn über die Verbindung laufen,
damit das ganze mehr Halt bekommt.&lt;/p&gt;

&lt;p&gt;Fertig!&lt;/p&gt;

&lt;p&gt;Unglaublich aber wahr, die Lampe leuchtet wieder mit voller Kraft und darf
nun wieder meinen Arbeitsplatz ausleuchten.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/ikea_lamp.jpg&quot; alt=&quot;IKEA Lamp&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Nichts achtlos wegwerfen!!&lt;/strong&gt;&lt;br /&gt;
Selbst wenn der Schalter erneut versagt, ein Ersatzschalter und frische Kabel
kosten wenig und sind mit geringem Aufwand verbaut.&lt;br /&gt;
Hätte ich die Lampe in den Müll geworfen wäre sie ziemlich sicher zerstört
worden und hätte vollkommen sinnlos eine Deponie gefüllt.&lt;/p&gt;

&lt;p&gt;So kann sie mir hoffentlich noch viele Jahre in späten Abendstunden einen
schönen Ausblick verschaffen.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Fun-Fact am Rande:&lt;/em&gt;&lt;br /&gt;
Als ich mir die Adernhülsen-Presszange auch so vor 10 Jahren zulegte, 
dachte ich mir:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Naja, die brauchst du jetzt einmal und dann liegt sie sinnlos herum.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Da konnte ich natürlich noch nicht wissen, wie viele Pin-Stecker ich durch
sie zusammenklipsen würde.&lt;/p&gt;

&lt;p&gt;Jedenfalls kostete die Zange weniger als zwei reparierte Geräte … und ich
hab schon mehrere Geräte damit wiederbelebt.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Non-Client Area</title>
   <link href="https://www.opengate.at/blog/2020/01/non-client-area/"/>
   <published>2020-01-05T12:00:00+01:00</published>
   <updated>2020-01-05T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2020/01/non-client-area</id>
   <category term="devel" />
   <summary type="text">Microsoft Windows stellt 
für seine Fenster einen Mechanismus bereit, der in vielen Frameworks nicht 
abgebildet wird.

Neben dem grafischen Inhalt des Fensters, der sogenannten Client-Area darf
es optional auch noch einen Rahmen drum herum geben, die Non-Client-Area.

</summary>
   <content type="html">&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows&quot;&gt;Microsoft Windows&lt;/a&gt; stellt 
für seine Fenster einen Mechanismus bereit, der in vielen Frameworks nicht 
abgebildet wird.&lt;/p&gt;

&lt;p&gt;Neben dem grafischen Inhalt des Fensters, der sogenannten Client-Area darf
es optional auch noch einen Rahmen drum herum geben, die Non-Client-Area.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;wozu-sind-non-client-areas-gut&quot;&gt;Wozu sind Non-Client-Areas gut?&lt;/h3&gt;

&lt;p&gt;Zwischen dem &lt;a href=&quot;https://de.wikipedia.org/wiki/X_Window_System&quot;&gt;X11&lt;/a&gt; Fenstersystem
und Windows gibt es einen wichtigen Unterschied:&lt;br /&gt;
X11 beauftragt den installierten Window-Manager, sich um die “Umrahmung” eines
Fensters zu kümmern. Der Entwickler erstellt per &lt;a href=&quot;https://de.wikipedia.org/wiki/Programmierschnittstelle&quot;&gt;API&lt;/a&gt;
sein Fenster und kann nur dessen Inhalt kontrollieren und der Window-Manager 
zeichnet eine Titelleiste, Min- und Maximierungsbuttons “von selbst” dazu,
wenn man es ihm nicht explizit untersagt.&lt;/p&gt;

&lt;p&gt;Microsoft hatte in den Anfängen von Windows aber nicht die Kapazitäten, Fenster
durch mehrere “Teilnehmer” zusammensetzen zu lassen und brachte daher alles im
Anwendungsprozess unter.&lt;br /&gt;
Wenn man nun die Koordinatensysteme für den Inhalt eines Fensters und sein
“Drum-herum” trennen möchte, dann kommt man eben zur Idee der Client- und 
Non-Client-Area.&lt;/p&gt;

&lt;p&gt;Primär wird dieses Feature für Programmfenster (Frame-Windows) benutzt, 
die eine Titelleiste haben. Diese Leiste wird von der 
&lt;a href=&quot;https://en.wikipedia.org/wiki/WindowProc&quot;&gt;&lt;code&gt;DefWindowProc()&lt;/code&gt;&lt;/a&gt;
automatisch nach den eingestellten Designvorgaben gezeichnet, doch das kann 
vom Entwickler stets überschrieben werden.&lt;br /&gt;
Manche Programme wollen eben ihr eigenes Design so hervorheben, doch die 
meisten Apps belassen es zum Glück beim Standard Design.&lt;/p&gt;

&lt;p&gt;Es ist aus meiner Sicht auch kontraproduktiv, das Standardverhalten eines 
Rahmenfensters abzuändern, schließlich fügen sich nur so alle Programme in 
ein Einheitliches Look-and-Feel ein.&lt;/p&gt;

&lt;h3 id=&quot;wie-manipuliert-man-non-client-areas&quot;&gt;Wie manipuliert man Non-Client-Areas?&lt;/h3&gt;

&lt;p&gt;Es gibt vor allem zwei Fensternachrichten, die man Abfangen und bearbeiten
muss, wenn man die Non-Client-Area verändern möchte:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://docs.microsoft.com/en-us/windows/win32/winmsg/wm-nccalcsize&quot;&gt;&lt;code&gt;WM_NCCALCSIZE&lt;/code&gt;&lt;/a&gt;:
Die wird beim Verändern der Größe des Fensters aufgerufen oder bei einem
entsprechenden &lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setwindowpos&quot;&gt;&lt;code&gt;SetWindowPos()&lt;/code&gt;&lt;/a&gt;
und gibt dem Entwickler die Möglichkeit festzulegen, wie breit der Rahmen
der Non-Client-Area um die Client-Area herum sein soll.
&lt;code&gt;lparam&lt;/code&gt; zeigt dabei immer auf eine &lt;code&gt;RECT&lt;/code&gt; Struktur, die die gesamte 
Fenstergröße abdeckt. Verkleinert man dieses Rechteck 
(left und top werden erhöht während bottom und right verkleinert werden),
schafft man damit eine neue kleinere Client-Area, und was dann eben 
“nicht” Client-Area ist, ist die Non-Client-Area.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/gdi/wm-ncpaint&quot;&gt;&lt;code&gt;WM_NCPAINT&lt;/code&gt;&lt;/a&gt;:
Diese spezielle PAINT Routine soll dann in die Non-Client-Area 
hineinzeichnen, was man eben sehen möchte.
Sie wird vor WM_PAINT aufgerufen, arbeitet aber nicht mit &lt;a href=&quot;http://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-beginpaint&quot;&gt;&lt;code&gt;BeginPaint()&lt;/code&gt;&lt;/a&gt;
und EndPaint(). Man kann sich aber mit &lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowdc&quot;&gt;&lt;code&gt;GetWindowDC()&lt;/code&gt;&lt;/a&gt;
den Gerätekontext zum Zeichnen selbst holen und loslegen.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;wozu-kann-man-non-client-areas-noch-nutzen&quot;&gt;Wozu kann man Non-Client-Areas noch nutzen?&lt;/h3&gt;

&lt;p&gt;Mein konkretes Beispiel ist: Ein Frame-Panel.&lt;/p&gt;

&lt;p&gt;Wir kennen alle die “inneren” Rahmen zur Strukturierung von Fensterformularen.
Diese Rahmen sind aber in Windows nicht als Container konzipiert wo man 
Kindelemente wie Textboxen und Buttons hineinlegen kann.&lt;/p&gt;

&lt;p&gt;Anstatt dessen sind es in Wahrheit Buttons mit einem speziellen 
&lt;a href=&quot;http://docs.microsoft.com/en-us/windows/win32/controls/button-styles&quot;&gt;Button-Style&lt;/a&gt;, 
die man nicht anklicken kann.&lt;br /&gt;
Das war wohl so gedacht, dass man zuerst einen Innenrahmen auf sein
Programmfenster legt und dann Buttons, Texte und Checkboxen einfach 
darüber legt.&lt;/p&gt;

&lt;p&gt;Das sieht dann optisch so aus, als wären die Elemente Kinder des
Innenrahmens, doch in Wahrheit liegt alles auf dem Programmfenster.&lt;/p&gt;

&lt;p&gt;Im GATE Projekt stört mich dieser Ansatz der WinAPI, weil auch GTK
sein &lt;a href=&quot;https://developer.gnome.org/gtk3/stable/GtkFrame.html&quot;&gt;&lt;code&gt;GtkFrame&lt;/code&gt;&lt;/a&gt;
als Container (&lt;code&gt;GtkBin&lt;/code&gt;) implementiert hat.&lt;/p&gt;

&lt;p&gt;Wenn man also in der WinAPI einen Button als Innenrahmen erzeugt und 
Kinder hineinsteckt, dann passt das Koordinatensystem nicht, denn auf
&lt;code&gt;(0, 0)&lt;/code&gt; wird das Rechteck und der Text gezeichnet. Man müsste die Kinder
also künstlich einrücken lassen.&lt;/p&gt;

&lt;p&gt;Genau hier kommt die Non-Client-Area ins Spiel:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Wir definieren ein neues Kind-Fenster, das als Container fungieren
kann (&lt;code&gt;WS_EX_CONTROLPARENT&lt;/code&gt;).&lt;/li&gt;
  &lt;li&gt;In dem Fenster überschreiben wir dann &lt;code&gt;WM_NCCALCSIZE&lt;/code&gt; und zwacken
links, rechts und unten ein paar Pixel ab, und oben stehlen wir mindestens
so viel, wie wir für die Schriftart brauchen.&lt;/li&gt;
  &lt;li&gt;In der umgeleiteten Nachricht &lt;code&gt;WM_NCPAINT&lt;/code&gt; holen wir mit &lt;a href=&quot;http://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowdc&quot;&gt;&lt;code&gt;GetWindowDC()&lt;/code&gt;&lt;/a&gt;
den &lt;code&gt;DC&lt;/code&gt; des gesamten Fensters (und damit der Non-Client-Area) und
stellen mit FillRect, DrawEdge und DrawText das Aussehen des
Innenrahmens nach.&lt;/li&gt;
  &lt;li&gt;Mit &lt;code&gt;SetWindowPos(..., SWP_DRAWFRAME | SWP_FRAMECHANGED)&lt;/code&gt; garantieren 
wir beim Erstellen des Fensters, dass &lt;code&gt;WM_NCCALCSIZE&lt;/code&gt; auch tatsächlich
aufgerufen wird.
(Das ist regulär nicht erforderlich, wenn man seine eigene WindowProc
richtig geschrieben hat, doch im GATE Projekt erfolgen im UI 
Zwischenschritte (Stichwort Subclassing), wo &lt;code&gt;WM_NCCALCSIZE&lt;/code&gt; ganz am Anfang 
noch nicht umgeleitet ist.)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Fertig!&lt;br /&gt;
Jetzt haben wir ein Container-Control, dessen Kinder mit dem Koordinatensystem
&lt;code&gt;(0, 0)&lt;/code&gt; innerhalb des vorhin selbst gezeichneten Rahmens starten.&lt;br /&gt;
Das macht das Arbeiten dann wesentlich einfacher und hilft auch dabei 
seinen Code besser kapseln zu können.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Tatsächlich ist es jetzt hier gerade das erste mal in meinem Leben, dass ich
die Non-Client-Area in einem Kind-Element nutze. Es war bisher nicht 
erforderlich.&lt;/p&gt;

&lt;p&gt;Das obige Beispiel mit dem “Innenrahmen” hatte ich vor über 10 Jahren schon 
mal vor meinen Augen, doch damals versuchte ich es mit Koordinatenumrechnungen
und musste dann feststellen, dass das Button-Control im Frame-Modus 
sehr hässlich zu flimmern begann, wenn sich die Fensterbreite änderte.
Und dieser Bug wurde dann wieder mit 
&lt;a href=&quot;http://docs.microsoft.com/en-us/windows/win32/gdi/wm-paint&quot;&gt;&lt;code&gt;WM_PAINT&lt;/code&gt;&lt;/a&gt;
Hacks gelöst.&lt;/p&gt;

&lt;p&gt;Mit der Non-Client-Area Methode ist die Sache meines Erachtens viel besser
gelöst und nebenbei auch portabler zu anderen Frameworks.&lt;/p&gt;

&lt;p&gt;Jedenfalls find ich’s cool, dass der Ansatz out-of-the-box funktionierte.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Windows 5</title>
   <link href="https://www.opengate.at/blog/2020/01/retro-windows/"/>
   <published>2020-01-04T12:00:00+01:00</published>
   <updated>2020-01-04T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2020/01/retro-windows</id>
   <category term="software" /><category term="retro" />
   <summary type="text">Die 4. Windows Generation endete mit Windows NT 4.0 
bzw. Windows Millennium im Jahre 1999.
Und dann startete mit “NT 5” ein neues Jahrtausend.

Heute war es wieder einmal Zeit, meine alten VMs
durchzugehen um zu sehen, ob sie noch laufen … und dabei wurde auch gleich 
der Softwarestand miterfasst.
</summary>
   <content type="html">&lt;p&gt;Die 4. Windows Generation endete mit &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_NT_4.0&quot;&gt;Windows NT 4.0&lt;/a&gt; 
bzw. &lt;a href=&quot;https://en.wikipedia.org/wiki/Windows_Me&quot;&gt;Windows Millennium&lt;/a&gt; im Jahre 1999.&lt;br /&gt;
Und dann startete mit “NT 5” ein neues Jahrtausend.&lt;/p&gt;

&lt;p&gt;Heute war es wieder einmal Zeit, meine alten &lt;a href=&quot;https://de.wikipedia.org/wiki/Virtuelle_Maschine&quot;&gt;VMs&lt;/a&gt;
durchzugehen um zu sehen, ob sie noch laufen … und dabei wurde auch gleich 
der Softwarestand miterfasst.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;windows-2000-nt-50&quot;&gt;Windows 2000, NT 5.0&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_2000&quot;&gt;Windows 2000&lt;/a&gt; kam Ende 
1999 heraus und war DER große Generationswechsel.&lt;br /&gt;
Es wurden neue Treibermodelle eingeführt, die sich von Windows NT 4.0 
abhoben und die Windows API erlebte einen ordentliches Update,
wo auch viele sich unterscheidende Schnittstellen von NT 4 und Win 9x jetzt
endlich gemeinsam untergebracht waren.&lt;/p&gt;

&lt;p&gt;Denn zwischen den Jahren 95 und 99 musste Software oft doppelt herausgebracht
werden, einmal als &lt;code&gt;*_NT.exe&lt;/code&gt; und dann noch als &lt;code&gt;*_9x.exe&lt;/code&gt;.&lt;br /&gt;
Ich erinnere mich noch dunkel an die Clean-Up und Tuning-Tools, die immer auf 
den Heft-CDs mit dabei waren, wo diese Suffix-Nomenklatur häufiger anzutreffen 
war.&lt;/p&gt;

&lt;h3 id=&quot;nt-50-software&quot;&gt;NT 5.0 Software&lt;/h3&gt;

&lt;p&gt;Wenn man heute noch mit einem Windows 2000 arbeiten wollen würde, dann hätte
man relativ viele Probleme damit. Das letzte Service-Pack war SP4 und der 
Support seitens Microsoft endete final im Jahr 2010. Die Online-Seite von 
Windows Update ist nicht mehr erreichbar und so bleiben mir heute nur noch 
meine mit &lt;a href=&quot;/blog/2018/12/nlite/&quot;&gt;nLite&lt;/a&gt; erstellten 
CD-Images aus den Jahren 2010, wo die bis dahin erschienenen Updates alle 
integriert waren.&lt;/p&gt;

&lt;p&gt;Ausgestattet mit dem &lt;a href=&quot;https://en.wikipedia.org/wiki/Internet_Explorer_5&quot;&gt;IE 5.0&lt;/a&gt; 
kann man de facto gar nichts mehr im Web machen und nach der Installation von 
&lt;a href=&quot;https://en.wikipedia.org/wiki/Internet_Explorer_6&quot;&gt;IE 6 SP1&lt;/a&gt; ist seitens 
Microsoft auch Schluss gemacht worden.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Mozilla_Firefox&quot;&gt;Firefox&lt;/a&gt; 
unterstützte Windows 2000 bis zur 
&lt;a href=&quot;https://ftp.mozilla.org/pub/firefox/releases/10.0.12esr/win32/&quot;&gt;Version 10.0.12&lt;/a&gt;
und so wird dessen Setup auf meinem Fileserver für eben diese Windows Version
aufgehoben. So kommt man zumindest noch auf einige Seiten, wenn man sich 
nicht mit HTTPS und zu neuen Zertifikaten verhaspelt.&lt;/p&gt;

&lt;p&gt;Mit dem uralten &lt;a href=&quot;https://de.wikipedia.org/wiki/Outlook_Express&quot;&gt;Outlook Express&lt;/a&gt; 
kommt man heute auch nicht mehr besonders weit, denn seit 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Transport_Layer_Security#Geschichte&quot;&gt;SSLv3&lt;/a&gt; 
abgeschaltet ist, laufen deren Anfragen ins Leere. Zum Glück gibt es ja noch 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Mozilla_Thunderbird&quot;&gt;Thunderbird&lt;/a&gt;, das bis zur 
&lt;a href=&quot;https://ftp.mozilla.org/pub/thunderbird/releases/12.0.1/win32/en-US/&quot;&gt;Version 12.0.1&lt;/a&gt;
auf Win2K lauffähig ist. Folglich liegt auch dessen Setup bei mir am Dateiserver.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Microsoft_Office_2003&quot;&gt;Office 2003&lt;/a&gt; ist 
Microsoft’s letzte Arbeitsumgebung auf dieser Plattform und kann leider auch 
nicht mehr mit aktuellen Dokumentformaten umgehen.&lt;br /&gt;
&lt;a href=&quot;https://en.wikipedia.org/wiki/Apache_OpenOffice&quot;&gt;Apache OpenOffice&lt;/a&gt; 
unterstützt Win2K - und das find ich &lt;em&gt;“echt cool”&lt;/em&gt; - bis zur aktuellen Version 4.1.7.
Wer also seinen kleinen privaten elektronischen Schreibtisch mit Windows 2000
umsetzen will, findet also bis ins Jahr 2020 eine Lösung.&lt;/p&gt;

&lt;h2 id=&quot;windows-xp-nt-51&quot;&gt;Windows XP, NT 5.1&lt;/h2&gt;

&lt;p&gt;Nicht mal 2 Jahre nach Win2K kam im Jahr 2001 mit dem Titel 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_XP&quot;&gt;Windows XP&lt;/a&gt;
die Version Windows NT 5.1 auf den Markt.&lt;br /&gt;
Dieses System blieb bis ins Jahr 2014 offiziell unterstützt und war viel zu 
lange einfach nicht tot zu kriegen.&lt;/p&gt;

&lt;p&gt;Doch seit der Einführung von &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_Vista&quot;&gt;Windows Vista&lt;/a&gt;
im Jahr 2006/2007 muss man ehrlich sagen, nahm die Stabilität neuerer Software
unter XP auch mehr und mehr ab. 2008 kam das letzte Service Pack 3 für XP 
ins Land und eben dieser Status der WinAPI ist teilweise bis heute eine 
Wassermarke für Applikationen, was sie einfordern dürfen, um gerade noch
XP-tauglich zu sein.&lt;/p&gt;

&lt;p&gt;2009 brachte Microsoft mit Windows XP Embedded 2009 noch eine Version
auf den Markt, die für Terminals in Industrie und Wirtschaftssystemen zum Einsatz
kommen sollte. Daher hielt ich bis letztes Jahr meine Aussage aufrecht:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Wegen XP Embedded 2009 müssen wir mindestens bis 2019 XP als Plattform
unterstützen, weil einige Kunden dieses System damals anschafften und es
bis zu dessen Support-Ende im Einsatz halten werden.&lt;br /&gt;
Damit ist auch der IE 8 Support weiter wichtig.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Jap, genau, &lt;a href=&quot;https://en.wikipedia.org/wiki/Internet_Explorer_8&quot;&gt;IE 8&lt;/a&gt; war die
letzte Version für Windows XP und das ist wohl der größte Alptraum auf 
einem solchen System.
Hinweis: Wer Windows XP heute noch aktualisieren will (was noch geht), muss 
den IE 8 installieren, denn ohne ihn läuft Windows Update nicht mehr.&lt;/p&gt;

&lt;p&gt;Firefox drehte seinen XP-Support mit &lt;a href=&quot;https://ftp.mozilla.org/pub/firefox/releases/52.9.0esr/win32/en-US/&quot;&gt;Version 52.9&lt;/a&gt;
erst im Jahr 2018 ab, womit wir auch heute noch viele Webseiten besuchen 
können, wenn gleich nach und nach moderne Scripts zunehmend instabiler 
darauf laufen.&lt;/p&gt;

&lt;p&gt;Als Mail-Client bietet sich die letzte 
&lt;a href=&quot;https://archive.mozilla.org/pub/thunderbird/releases/38.5.0/win32/en-GB/&quot;&gt;Thunderbird Version 38.5&lt;/a&gt;
an, die im Jahr 2015 veröffentlicht wurde und neben &lt;a href=&quot;https://de.wikipedia.org/wiki/Post_Office_Protocol&quot;&gt;POP3&lt;/a&gt; 
und &lt;a href=&quot;https://de.wikipedia.org/wiki/Internet_Message_Access_Protocol&quot;&gt;IMAP&lt;/a&gt; 
auch schon ein paar modernere Web-Authentifizierungen anbietet.&lt;/p&gt;

&lt;p&gt;Mit &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Office_2010&quot;&gt;MS Office 2010&lt;/a&gt; kann
man noch einigermaßen mit aktuellen Dokumenten und Servern arbeiten.
Natürlich steht mit OpenOffice auch hier noch die aktuellste Version zur 
Verfügung.&lt;/p&gt;

&lt;h3 id=&quot;server-2003-nt-52&quot;&gt;Server 2003, NT 5.2&lt;/h3&gt;

&lt;p&gt;NT 5.2 war der Kern von &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_Server_2003&quot;&gt;Server 2003&lt;/a&gt;
und auch von Windows XP 64-bit. Man könnte also sagen, dass 64-bit XPs die 
moderneren Systeme sind.&lt;br /&gt;
In Sachen Kompatibilität würde ich jedoch zum klassischen XP (NT 5.1) raten,
denn mir sind ein paar Problemchen mit Treibern und vor allem bei Video-Codecs
untergekommen, wo die Umleitung von 32-bit APIs auf die 64-bit Architektur
fehlerhaft war.&lt;/p&gt;

&lt;p&gt;Aber grundsätzlich sollte gelten: 
&lt;em&gt;Alles was unter NT 5.1 lief, läuft auch unter NT 5.2.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In Sachen Server Software von Microsoft kann man grundsätzlich sagen, dass 
alle Titel, die eine Jahreszahl kleiner 2008 in sich tragen 2K3 tauglich sind,
alles ab größer 2007 dann nur noch auf Server 2008 (also NT 6.0) und höher läuft.&lt;/p&gt;

&lt;p&gt;Als Webserver kommt der IIS 6 zum Einsatz, weshalb bei Zusatzsoftware auf 
Kompatibilität für diese Plattform geachtet werden muss.&lt;/p&gt;

&lt;p&gt;Ein ganz lästiges Problem ist übrigens 
&lt;a href=&quot;https://en.wikipedia.org/wiki/Microsoft_Virtual_Server&quot;&gt;Virtual Server 2005&lt;/a&gt;, 
der große Bruder von Virtual PC. Denn die Server-Variante war nur noch per 
Browser steuerbar. Die HTML Seite nutzt aber furchtbare MS-IE-only Scripts, 
die nur mit dem IE 6 allesamt laufen. Bereits der IE 8 konnte diese nicht 
mehr korrekt darstellen, weil er (wie witzig!) bereits weiter an den 
HTML Standard angenähert war.&lt;br /&gt;
Wer also Virtualisierung auf Altsystemen haben will, braucht “zwingend”
ein originales nicht-aktualisiertes Windows XP.
Oder aber man quält sich mit dem IE 6 vom Server 2003, welcher aber im
Standard wiederum so konfiguriert ist, dass er überhaupt keine Scripts 
und ActiveX Controls zulässt.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Diese Systeme haben meinen “vollen” Einstieg in die IT und die Programmierung
begleitet. Ich werde sie daher stets zu schätzen wissen und in Erinnerung
behalten.&lt;/p&gt;

&lt;p&gt;Trotzdem sind auch viele lästige Bugs in ihnen enthalten, und ich bin froh,
dass diese der Vergangenheit angehören und mich heute nicht mehr “behindern”.&lt;/p&gt;

&lt;p&gt;Ach ja… einen “besonderen” Einsatzort haben diese System noch bei mir:
Und zwar auf meinen &lt;a href=&quot;https://en.wikipedia.org/wiki/EPIA&quot;&gt;Epia Boards&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Die alten &lt;a href=&quot;https://de.wikipedia.org/wiki/Cyrix&quot;&gt;Cyrix&lt;/a&gt; Prozessoren 
(und/oder das BIOS) werden von Windows Vista und neuer nicht unterstützt. 
Es kommt während oder nach der Installation zu Bluescreens. Doch mit 
Windows 2000, Windows XP und Server 2003 laufen “meine Vorläufer” von 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Intel_Atom&quot;&gt;Intel Atom&lt;/a&gt; problemlos und 
angemessen flüssig.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Maus-Scroll-Ersatz</title>
   <link href="https://www.opengate.at/blog/2020/01/scrolling/"/>
   <published>2020-01-02T12:00:00+01:00</published>
   <updated>2020-01-02T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2020/01/scrolling</id>
   <category term="devel" /><category term="hardware" />
   <summary type="text">Mama hat einen neuen Laptop, aber das Touchpad
ist Mist. Wer im Browser damit “scrollen” will, braucht eine Dosis 
Antidepressiva.

Hmmm … ich hatte doch noch einen ATmega32U4
und eine Joystick Breakout-Platine in der Lade liegen …
</summary>
   <content type="html">&lt;p&gt;Mama hat einen neuen Laptop, aber das &lt;a href=&quot;https://de.wikipedia.org/wiki/Touchpad&quot;&gt;Touchpad&lt;/a&gt;
ist Mist. Wer im Browser damit “scrollen” will, braucht eine Dosis 
Antidepressiva.&lt;/p&gt;

&lt;p&gt;Hmmm … ich hatte doch noch einen &lt;a href=&quot;http://www.microchip.com/wwwproducts/en/ATmega32U4&quot;&gt;ATmega32U4&lt;/a&gt;
und eine Joystick Breakout-Platine in der Lade liegen …
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Auf manchen &lt;a href=&quot;https://de.wikipedia.org/wiki/Arduino_(Plattform)&quot;&gt;Arduino&lt;/a&gt; 
Seiten hat der “Leonardo” keinen besonders guten Ruf.&lt;br /&gt;
Das liegt unter anderem daran, dass er die serielle Schnittstelle etwas
anders einsetzt, als das ein UNO oder MEGA tun.&lt;br /&gt;
(Und damit meine ich nicht den Code der Gegenseite, 
&lt;a href=&quot;/blog/2018/10/leonardo-handshake/&quot;&gt;sieht damals&lt;/a&gt;…)&lt;/p&gt;

&lt;p&gt;Der Arduino Leonardo basiert auf dem ATmega32U4 und im Gegensatz zum
ATmega328p beim UNO hat er keinen separaten &lt;a href=&quot;https://de.wikipedia.org/wiki/Universal_Serial_Bus&quot;&gt;USB&lt;/a&gt;
Chip für die Sketch-Uploads, weil er die USB-Kommunikation selbst beherrscht.&lt;/p&gt;

&lt;p&gt;Und deshalb wird er auch etwas anders programmiert.
Die übliche &lt;a href=&quot;http://www.arduino.cc/reference/en/language/functions/communication/serial/&quot;&gt;&lt;code&gt;Serial&lt;/code&gt;&lt;/a&gt; 
Schnittstelle (sollte eigentlich &lt;code&gt;Serial0&lt;/code&gt; heißen und) ist hier dem virtuellen 
USB-COM-Port zugeordnet und nicht den Pins &lt;code&gt;0&lt;/code&gt; und &lt;code&gt;1&lt;/code&gt; auf der Platine.&lt;/p&gt;

&lt;p&gt;Für die Pins ist &lt;code&gt;Serial1&lt;/code&gt; instanziiert.&lt;/p&gt;

&lt;p&gt;Doch eben gerade wegen der Einbettung von USB in den Mikrocontroller, können
wir USB auch auf Code-Ebene manipulieren.&lt;br /&gt;
&lt;em&gt;Und daraus ergeben sich ungeahnte Möglichkeiten&lt;/em&gt;&lt;/p&gt;

&lt;h3 id=&quot;problemstellung-ein-virtuelle-maus&quot;&gt;Problemstellung: Ein virtuelle Maus&lt;/h3&gt;

&lt;p&gt;Ohne Hardwareunterstützung oder vernünftige Software-Emulation über Gesten
ist es durch ein Touchpad nicht ordentlich möglich, ein Scrollen auszulösen.&lt;br /&gt;
Man kann nur den Mauszeiger zu einer Scroll-Leiste schicken und dort auf
ein Pfeilchen oder die Leiste klicken.&lt;br /&gt;
Ein Touchpad hat eben kein Scroll-Rad … leider.&lt;/p&gt;

&lt;p&gt;Doch über den Header &lt;code&gt;mouse.h&lt;/code&gt; bietet die Arduino-IDE “out-of-the-box” eine
Bibliothek an, mit der man eine &lt;a href=&quot;https://en.wikipedia.org/wiki/USB_human_interface_device_class&quot;&gt;HID&lt;/a&gt;
konforme Maus über den Chip nachbilden kann.
Das bedeutet, der Chip wird vom PC wie eine Maus erkannt und nun können wir
per Code Mausbewegungen und Aktionen zum PC senden, der diese dann umsetzt
und visualisiert.&lt;/p&gt;

&lt;p&gt;Und wo bekommen wir die Infos her, in welche Richtung gescrollt werden soll?&lt;br /&gt;
Natürlich vom Joystick, der im Hintergrund für jede Achse einen verstellbaren
Widerstand nutzt um seine Ausrichtung zu melden.&lt;br /&gt;
&lt;a href=&quot;https://www.arduino.cc/reference/en/language/functions/analog-io/analogread/&quot;&gt;&lt;code&gt;analogRead()&lt;/code&gt;&lt;/a&gt;
gibt eine Wert zwischen 0 und 1023 zurück, je nachdem wie weit der Stick nach
oben oder unten (Y) bzw. links oder rechts (X) bewegt wurde.&lt;/p&gt;

&lt;p&gt;Werte rund um 512 sollten die Mittelstellung darstellen.
Wenn einem nur rauf oder runter bzw. links oder rechts Infos genügen, kann
man sich einen Grenzwert für den gemessenen Pegel setzen, z.B.:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;alles kleiner 256 bedeutet Richtung A&lt;/li&gt;
  &lt;li&gt;alles größer 768 bedeutet Richtung B&lt;/li&gt;
  &lt;li&gt;und dazwischen bedeutet keine Richtung&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;atmega32u4--widerstand--joystick&quot;&gt;ATmega32U4 + Widerstand = Joystick&lt;/h3&gt;

&lt;p&gt;Also lötet man den Joystick auf eine etwas größere Platine, wo man den ATmega32U4
auch draufsetzen kann, verbindet seine Achsen mit den analogen Eingängen, wie
auch die Stromzu- und -abfuhr, schreibt etwas Code und fertig ist der Prototyp.&lt;/p&gt;

&lt;p&gt;Man kann also mit ein paar Zeilen wie:&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt; loop()
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; sensor = analogRead(joystick_pin);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt;(senser &amp;lt; &lt;span style=&quot;color:#00D&quot;&gt;256&lt;/span&gt;)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  {
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;    Mouse.move(&lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;, &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;, -&lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  }
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;else&lt;/span&gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt;(sensor &amp;gt; &lt;span style=&quot;color:#00D&quot;&gt;768&lt;/span&gt;)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;  {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;    Mouse.move(&lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;, &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;, +&lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;  }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;  delay(&lt;span style=&quot;color:#00D&quot;&gt;100&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;bereits seinen eigenen Scroll-Controller realisieren. &lt;strong&gt;Cool!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Etwas Ähnliches wäre auch mit Keyboard-Eingaben möglich und natürlich
lassen sich noch andere USB-HID Standards nachahmen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ich liebe unser Zeitalter. Dass man so schnell ein kleines Tool bauen kann,
mit dem man Scroll-Eingaben an den PC senden kann, ist einfach nur genial.&lt;/p&gt;

&lt;p&gt;Natürlich war das Spielzeug in erster Linie ein Proof-of-Concept und etwas
Zeitvertreib.&lt;br /&gt;
Mama fand es ein paar Minuten witzig, wollte dann aber doch lernen, wie man 
mit dem Touchpad ohne den Zusatzsteuerknüppel dort hinkommt, wo man eben
hin will.&lt;/p&gt;

&lt;p&gt;Und dafür braucht es etwas Übung, bis man mit den Fingern schneller wird.&lt;/p&gt;

&lt;p&gt;Ich habe die Testplatine so gebaut, dass die MCU ein- und absteckbar ist 
und kann das Teil somit noch für andere Zwecke recyclen.&lt;br /&gt;
Von daher ist keine Hardware verschwendet worden.&lt;/p&gt;

&lt;p&gt;Und ja, ich weiß, mit meinem Arduino &lt;a href=&quot;/blog/2018/12/esplora/&quot;&gt;Esplora&lt;/a&gt; 
wäre das ganze auch ohne Lötkolben in Sekundenschnelle fertig gewesen.&lt;br /&gt;
Aber hey … ein bisschen Beschäftigung an der Lötstation braucht man eben …&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>2020 startet</title>
   <link href="https://www.opengate.at/blog/2020/01/new-year/"/>
   <published>2020-01-01T12:00:00+01:00</published>
   <updated>2020-01-01T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2020/01/new-year</id>
   <category term="general" />
   <summary type="text">Gute Vorsätze im Gepäck und Motivation sind die halbe Miete.
Aber nicht umsonst lautet das Sprichwort:


  Wer Gott zum Lachen bringen will, der macht einen Plan.


Na dann auf zur Projektplanung …
</summary>
   <content type="html">&lt;p&gt;Gute Vorsätze im Gepäck und Motivation sind die halbe Miete.
Aber nicht umsonst lautet das Sprichwort:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Wer Gott zum Lachen bringen will, der macht einen Plan.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Na dann auf zur Projektplanung …
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Nur zur Dokumentation damit ich in einem Jahr nachlesen kann,
was ich erreichen wollte, hier eine kleine Liste:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Den Blog häufiger aktualisieren … jüngst stellte sich da ein
6-Monats-Stau ein&lt;/li&gt;
  &lt;li&gt;GATE Demo Releases fertig machen, die im letzten April hätten fertig
sein sollen !!!&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/GTK&quot;&gt;GTK+&lt;/a&gt; Kinderkrankheiten im GATE UI auskurieren&lt;/li&gt;
  &lt;li&gt;Endlich mal weitere Plattformen neben Windows und Linux anbinden&lt;/li&gt;
  &lt;li&gt;Webservices und GATE Connectors planen und umsetzen.&lt;/li&gt;
  &lt;li&gt;Meine Server Infrastruktur aktualisieren und Backups nicht vergessen !!!&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Raspberry_Pi&quot;&gt;Raspberry PI&lt;/a&gt; und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Docker_(Software)&quot;&gt;Docker&lt;/a&gt; 
eine “produktivere” Rolle in meinen Umgebungen 
zuordnen.&lt;/li&gt;
  &lt;li&gt;Weniger Geld für Fernost-Bestellungen ausgeben&lt;/li&gt;
  &lt;li&gt;Strombedarf reduzieren (und bei Gelegenheit mal messen)&lt;/li&gt;
  &lt;li&gt;Weniger Zeit mit &lt;a href=&quot;https://de.wikipedia.org/wiki/Minecraft&quot;&gt;Minecraft&lt;/a&gt; totschlagen&lt;/li&gt;
  &lt;li&gt;und ich sollte den Ideen von Kollegen mehr Aufgeschlossenheit entgegenbringen
(selbst wenn sie Worte wie Docker und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Python_%28Programmiersprache%29&quot;&gt;Python&lt;/a&gt; beinhalten …)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Gut, ich denke, das reicht um am Jahresende wieder zu sehen, was alles nicht 
geklappt hat … oder vielleicht freue ich mich ja, wenn was dabei herausgekommen ist.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prosit Neujahr!&lt;/strong&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Das Jahr 2019</title>
   <link href="https://www.opengate.at/blog/2019/12/year-2019/"/>
   <published>2019-12-31T12:00:00+01:00</published>
   <updated>2019-12-31T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2019/12/year-2019</id>
   <category term="general" />
   <summary type="text">Schon ist das Jahr 2019 wieder vorbei.

Und es war eines der schönsten Jahre, an die ich mich zurückerinnern kann.
</summary>
   <content type="html">&lt;p&gt;Schon ist das Jahr 2019 wieder vorbei.&lt;/p&gt;

&lt;p&gt;Und es war eines der schönsten Jahre, an die ich mich zurückerinnern kann.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Natürlich lag das vor allem daran, dass ich mit Anfang des Jahres Herr meiner
eigenen Zeit war und für mich einiges weiter ging.&lt;br /&gt;
Hardwarebasteleien und das GATE-Projekt auf Softwareseite waren definitiv
ein Highlight und ich kann nur sagen, dass so eine Phase des Entdeckens
und Selbst-Verwirklichens ein Segen für einen sein kann.&lt;/p&gt;

&lt;p&gt;Viel zu starr und öde ist die IT in ihrer kommerziellen Form heute 
geworden.&lt;br /&gt;
Und dort wo früher motiviert und vor allem “frei” an neuen Ideen und 
Technologien gearbeitet werden konnte, da sitzen heute elende Wirtschaftler,
die mit der Devise:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Arbeiter schlecht bezahlen und immer das Maximum herauspressen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;auch noch das letzte bisschen Menschlichkeit und Initiative auf ihrem 
Geldaltar opfern.&lt;/p&gt;

&lt;p&gt;Und daher beherzige ich die weise Aussage eines lieben Kollegen, der meinte&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Die Arbeit ist nur zum Geldverdienen da. Etwas Sinnvolles macht man 
privat, am besten als OpenSource - Lösung.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Und deshalb starte ich 2020 wider mit guter Laune, weil ich gegen allfällige
Demotivationstendenzen der Gesellschaft finanziell gut abgesichert bin und 
viele weitere spannende Themenbereiche offen sind, um die ich mich kümmern 
kann.&lt;/p&gt;

&lt;p&gt;Es vergeht keine Woche, wo nicht wieder eine neue Mikrocontroller-Spielerei
im Netz auftaucht, die ich nachbauen und daraus lernen kann und parallel
dazu schreitet auch der C++ Standard weiter voran, womit mehr und mehr
alter BOOST Code durch stabile (sich nicht ständig ändernde) Zeilen 
ersetzt werden kann.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Willkommen 2020!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Und allen da draußen einen guten Rutsch ins neue Jahr.&lt;/em&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Socket select() unterbrechen</title>
   <link href="https://www.opengate.at/blog/2019/12/socket-select/"/>
   <published>2019-12-28T12:00:00+01:00</published>
   <updated>2019-12-28T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2019/12/socket-select</id>
   <category term="devel" /><category term="projects" />
   <summary type="text">Hmm … ich könnte schwören über das Thema schon was geschrieben zu haben,
doch ich finde nichts …

Kurze Frage: Wie unterbricht man ein laufendes 
select() ?

Kurze Antwort: Mit close() 
bzw. closesocket()
</summary>
   <content type="html">&lt;p&gt;Hmm … ich könnte schwören über das Thema schon was geschrieben zu haben,
doch ich finde nichts …&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Kurze Frage:&lt;/em&gt; Wie unterbricht man ein laufendes 
&lt;a href=&quot;http://pubs.opengroup.org/onlinepubs/007908799/xsh/select.html&quot;&gt;&lt;code&gt;select()&lt;/code&gt;&lt;/a&gt; ?&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Kurze Antwort:&lt;/em&gt; Mit &lt;a href=&quot;http://pubs.opengroup.org/onlinepubs/009695399/functions/close.html&quot;&gt;&lt;code&gt;close()&lt;/code&gt;&lt;/a&gt; 
bzw. &lt;a href=&quot;http://docs.microsoft.com/en-us/windows/win32/api/winsock/nf-winsock-closesocket&quot;&gt;&lt;code&gt;closesocket()&lt;/code&gt;&lt;/a&gt;
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Und schon werden die &lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt; Benutzer
laut aufschreien …&lt;br /&gt;
Doch diesmal haben sie recht: 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows&quot;&gt;Windows&lt;/a&gt; ist Schuld!&lt;/p&gt;

&lt;p&gt;Alle &lt;a href=&quot;https://de.wikipedia.org/wiki/Socket_(Software)&quot;&gt;Socket&lt;/a&gt; Entwickler 
kennen natürlich &lt;code&gt;select()&lt;/code&gt;, was benutzt wird, um auf Änderungen von
Sockets oder deren Datenpuffer effizient zu reagieren.&lt;/p&gt;

&lt;p&gt;Man übergibt eine Liste von Sockets mit einer Bitmaske an select() und
dieses wartet entweder bis zu einem gesetzt Timeout um “nichts” zu melden,
oder im Moment einer Änderung (wie “hab-etwas-empfangen”) sofort 
zurückzukehren.&lt;/p&gt;

&lt;p&gt;So weit, so gut.&lt;/p&gt;

&lt;p&gt;Doch was ist, wenn man selbst ein laufendes &lt;code&gt;select()&lt;/code&gt; unterbrechen möchte?
Es zwingen möchte, noch vor dem zuvor gesetzten Timeout abzubrechen?&lt;/p&gt;

&lt;p&gt;Unter &lt;a href=&quot;https://de.wikipedia.org/wiki/Unix&quot;&gt;Unix&lt;/a&gt; Systemen ist die Sache 
einfach. Man erstellt eine &lt;a href=&quot;https://de.wikipedia.org/wiki/Pipe_(Informatik)&quot;&gt;Pipe&lt;/a&gt;
und hängt den Lese-Deskriptor zu den Sockets. Will man &lt;code&gt;select()&lt;/code&gt; von außen 
unterbrechen, schreibt man einfach ein Byte in den Schreibe-Deskriptor und 
&lt;code&gt;select()&lt;/code&gt; kehrt sofort mit der Meldung zurück, dass auf dem Lese-Teil ein 
Byte angekommen ist.&lt;/p&gt;

&lt;p&gt;Doch unter Windows funktioniert &lt;code&gt;select()&lt;/code&gt; ausschließlich mit Sockets und nicht
mit anderen Handles wie z.B. denen von Pipes. Der Unix-Trick funktioniert also nicht.&lt;/p&gt;

&lt;p&gt;Jetzt könnte man unter Windows einen weiteren Socket erstellen und binden und
auch dort auf ein Byte warten, das bei der gewünschten Unterbrechung versendet
wird. Doch der Nachteil liegt klar auf der Hand: Die Software wird hackbar,
weil per Socket eine Außenverbindung möglich wird.&lt;/p&gt;

&lt;p&gt;Es gibt aber noch einen anderen Trick:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Man erstelle einen ungebundenen Socket&lt;/li&gt;
  &lt;li&gt;Der ungebundene Socket kommt ebenso in die &lt;code&gt;select()&lt;/code&gt; Liste&lt;/li&gt;
  &lt;li&gt;Bei der Unterbrechung wird Socket einfach per &lt;code&gt;closesocket()&lt;/code&gt; geschlossen.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Zieht man einem Windows-&lt;code&gt;select()&lt;/code&gt; einen Socket-Sessel unter’m Hintern weg, 
so kehrt es ebenso sofort mit einer Fehlermeldung zurück.&lt;/p&gt;

&lt;p&gt;Das ist zwar nicht so schön wie Unix-Pipe Variante, doch ich setze sie 
schon erfolgreich auf Windows und 
&lt;a href=&quot;https://en.wikipedia.org/wiki/Windows_Embedded_Compact&quot;&gt;Windows CE&lt;/a&gt; 
seit 10 Jahren ein.&lt;/p&gt;

&lt;p&gt;Man muss natürlich dazu sagen, dass das Verhalten nicht konkret ausformuliert
ist. Und es wäre möglich, dass Windows diesen Verhaltenszug in kommenden
Versionen abändert. Wahrscheinlich ist das aber nicht.&lt;/p&gt;

&lt;p&gt;Ich gewann durch diese Methode die Möglichkeit, das “Unterbrechen” von 
&lt;code&gt;select()&lt;/code&gt; von Linux auf Windows zu portieren und konnte bisher keine weiteren
Probleme damit feststellen.&lt;/p&gt;

&lt;p&gt;Aktuell beschäftigt mich diese Routine wieder im GATE-Project, wo dieser
Trick natürlich auch in der Socket-Group und dem Socket-Selector zum
Einsatz kommt.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Star Wars Episode 9</title>
   <link href="https://www.opengate.at/blog/2019/12/star-wars/"/>
   <published>2019-12-27T12:00:00+01:00</published>
   <updated>2019-12-27T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2019/12/star-wars</id>
   <category term="entertainment" />
   <summary type="text">Was für ein Glück, dass ich zur Star Trek
Fangemeinde zähle.

Damit muss ich mich jetzt nicht selbst hinterfragen, nachdem mich
der neueste Star Wars Film 
gleichwegs viel gelangweilt hat, wie die Filme davor.

Trotzdem “muss” man diese Filmreihe, die die Populärkultur so geprägt hat,
einfach gesehen haben.
</summary>
   <content type="html">&lt;p&gt;Was für ein Glück, dass ich zur &lt;a href=&quot;https://de.wikipedia.org/wiki/Star_Trek&quot;&gt;Star Trek&lt;/a&gt;
Fangemeinde zähle.&lt;/p&gt;

&lt;p&gt;Damit muss ich mich jetzt nicht selbst hinterfragen, nachdem mich
der neueste &lt;a href=&quot;https://de.wikipedia.org/wiki/Star_Wars&quot;&gt;Star Wars&lt;/a&gt; Film 
gleichwegs viel gelangweilt hat, wie die Filme davor.&lt;/p&gt;

&lt;p&gt;Trotzdem “muss” man diese Filmreihe, die die Populärkultur so geprägt hat,
einfach gesehen haben.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Eigentlich verstehe ich es ja selbst nicht so ganz, warum mich jede Form von
Fantasy und &lt;a href=&quot;https://de.wikipedia.org/wiki/Science-Fiction&quot;&gt;SciFi&lt;/a&gt; 
interessiert, und dass mich Star Wars “relativ” kalt lässt.&lt;/p&gt;

&lt;p&gt;Vielleicht liegt es an der Mischung aus der dargestellten 70er-Jahre-Technik, 
die stets mehr schlecht als recht funktioniert und dann das Mysterium der
“Macht”, die es dann richten soll.&lt;/p&gt;

&lt;p&gt;Doch unabhängig von der erzählten Geschichte “in einer weit entfernten Galaxie”
muss man neidlos zugestehen, dass Star Wars in Sachen Bild und Tontechnik die
Vorreiterrolle gegenüber anderen Projekten eingenommen hat und nimmt.&lt;/p&gt;

&lt;p&gt;Das beginnt schon bei den “Außerirdischen”, die in Star Trek immer nur Menschen
mit Plastiknasen sind, wie &lt;a href=&quot;https://de.wikipedia.org/wiki/Gregor_Kartsios&quot;&gt;Gregor Kartsios&lt;/a&gt; 
mal treffend bemerkte, während Star Wars weit über den Tellerrand 
hinausblickte und viel exotischere Körperfarben und -formen erschuf.&lt;/p&gt;

&lt;h3 id=&quot;starwars-9&quot;&gt;StarWars 9&lt;/h3&gt;

&lt;p&gt;Und das muss man dem 9. und angeblich finalen Film der Reihe lassen:&lt;br /&gt;
Es wird einem ein grafisch überwältigendes Spektakel geboten, wenn gleich ich
immer noch verstutzt bin, dass in einer Welt, in der jeder zweite Handgriff 
von “intelligenten” Robotern ausgeführt die Raumschiffe immer noch so aussehen,
wie analoge Schaltpulte, und wo man einfach eine Klappe öffnet, ein Kabelgewirr
rausholen kann, zwei Drähte verbindet und damit etwas kurzschließt, damit 
sich eine Tür öffnet.&lt;/p&gt;

&lt;p&gt;Tja … und die Story …&lt;br /&gt;
Sie beginnt mit dem legendären schrägen Lauftext und offenbart in der ersten 
Filmminute, dass der &lt;a href=&quot;https://en.wikipedia.org/wiki/Palpatine&quot;&gt;Imperator&lt;/a&gt;, der 
im 6. Film getötet wurde, einfach wieder da ist, keiner weiß warum. Auch im 7. 
und 8. Film gab es keine Hinweise, dass dieser Charakter irgendwo herumsitzt.&lt;/p&gt;

&lt;p&gt;Vielleicht ist genau das mein Problem mit Star Wars.&lt;br /&gt;
Die Filme zeigen immer einen Ausschnitt aus dem Leben in der fernen Galaxie
und was dazwischen geschieht scheint immer extrem bedeutsam, wird aber nie
gezeigt. Es wirkt stets als würden Jahre zwischen den Filmen vergehen.
Dafür sehe ich dann aber Figuren, die immer in jedem neuen Film emotional 
genau dort weitermachen, wo der letzte Film endete.&lt;br /&gt;
Da passen die Laufgeschwindigkeiten einfach nicht zusammen.&lt;/p&gt;

&lt;p&gt;Ja, ich glaube, ich hätte mit Star Wars wesentlich mehr Freude, wenn die 
3 Filme einer Gruppe in einer Serie mit 20-30 Episoden erzählte werden
würden, wo Handlung und Verlauf schlüssiger übermittelt werden können.&lt;/p&gt;

&lt;p&gt;Hmm … ja, das wäre dann so wie bei Star Trek, denn seien wir mal ehrlich,
auch dort kommen die Filme nicht im entferntesten an die genialen Stories 
vieler Staffelepisoden heran.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ja, man muss StarWars 9 gesehen haben. Das steht für mich fest.&lt;br /&gt;
Aber ein echter Fan werde ich wohl auch weiter nicht werden.&lt;/p&gt;

&lt;p&gt;Mit der Kinokarte um 13 Euro + 6 Euro für die “Kiddy-Box”, dem kleinsten
Fresspaket an der Kassa, hat damit einen netten Nachmittag gestaltet.
Wenn gleich ich auch nicht darüber nachdenken darf, dass 
“Herr der Ringe 2” mich seinerzeit 5,50 Euro kostete … da denke ich mir
schon, dass das nicht nur die Inflation ist, was wir heute für Filme
bezahlen müssen.&lt;br /&gt;
(Und die 13 Euro sind für 2D, bei 3D geht’s bei 15 Euro aufwärts los).&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/darth-vader.jpg&quot; alt=&quot;Darth Vader&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Image by &lt;a href=&quot;https://pixabay.com/vectors/darth-vader-light-sabre-funny-147014/&quot;&gt;Pixabay&lt;/a&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Ein frohes Fest 2019</title>
   <link href="https://www.opengate.at/blog/2019/12/merry-xmas/"/>
   <published>2019-12-24T12:00:00+01:00</published>
   <updated>2019-12-24T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2019/12/merry-xmas</id>
   <category term="general" />
   <summary type="text">Auch wenn mir persönlich religiös festgesetzte Sondertage wenig bis gar 
nichts bedeuten, so haben diese Tage dennoch eine wichtige Bedeutung in 
der Gesellschaft.

Es ist durchaus wichtig, dass wir ein paar “besondere” Tage im Jahr 
herausgreifen um uns zu besinnen.
</summary>
   <content type="html">&lt;p&gt;Auch wenn mir persönlich religiös festgesetzte Sondertage wenig bis gar 
nichts bedeuten, so haben diese Tage dennoch eine wichtige Bedeutung in 
der Gesellschaft.&lt;/p&gt;

&lt;p&gt;Es ist durchaus wichtig, dass wir ein paar “besondere” Tage im Jahr 
herausgreifen um uns zu besinnen.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Ich erinnere mich vor allem immer an die Gebete in meiner Kindheit, welche
unter’m Christbaum von allen mitgesprochen wurde.&lt;br /&gt;
Ein &lt;a href=&quot;https://de.wikipedia.org/wiki/Vaterunser&quot;&gt;Vater-unser&lt;/a&gt; und ein 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Ave_Maria&quot;&gt;Ave Maria&lt;/a&gt; für einige Anliegen.&lt;/p&gt;

&lt;p&gt;Jedes Gebetswiederholung hatte ein Thema.&lt;br /&gt;
Es war jedes Jahr ein bisschen anders, aber lief oft so ab:&lt;/p&gt;

&lt;h3 id=&quot;für-den-neugeborenen-heiland-&quot;&gt;“Für den neugeborenen Heiland …”*&lt;/h3&gt;

&lt;p&gt;Als Kind wirkten die Christkind Geschichten natürlich wesentlich intensiver 
als das heute der Fall ist. Aber man sollte nicht unterschätzen, das in jeder
Religion “der gute Vorsatz” eine breite Saat an guten Taten gepflanzt hat.
Daher sollte man die alten Schriften und Gleichnisse für ihre Funktion
als moralische Wegweiser ehren.&lt;/p&gt;

&lt;p&gt;Im Anschluss hieß es:&lt;/p&gt;

&lt;h3 id=&quot;für-unserer-verstorbenen-eltern-und-großeltern-&quot;&gt;“Für unserer verstorbenen Eltern und Großeltern …”&lt;/h3&gt;

&lt;p&gt;Es wäre schon interessant, was Oma und Opa heute sagen würden,
wie sich die Welt und auch wir uns verändert haben.
Und wir könnten Ihnen einfach “Danke” sagen, für das, was sie
aufgebaut und uns hinterlassen haben.&lt;br /&gt;
Man vergisst all zu schnell, dass unser eigener Erfolg meist
ohne die Mühen der Vorfahren nie zustande gekommen wäre.&lt;/p&gt;

&lt;p&gt;Dann kam:&lt;/p&gt;

&lt;h3 id=&quot;dafür-dass-wir-alle-gesund-sind-&quot;&gt;“Dafür, dass wir alle gesund sind …”&lt;/h3&gt;

&lt;p&gt;Man sagt:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Der Gesunde hat tausend Wünsche, der Kranke nur einen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ja, wir vergessen gerne, wie zerbrechlich unser Körper sein kann,
und sind schon bei einem kleinen Schnupfen überrascht, wie schnell
sich das Blatt wenden kann.&lt;/p&gt;

&lt;p&gt;Und ein Gebet fehlte ebenso nie:&lt;/p&gt;

&lt;h3 id=&quot;für-alle-an-die-niemand-denkt-&quot;&gt;“Für alle, an die niemand denkt …”&lt;/h3&gt;

&lt;p&gt;Den Sinn dieses Gebets konnte ich als Kind nie verstehen.&lt;br /&gt;
Einerseits zogen die Geschenke unter’m Baum schon die Aufmerksamkeit
auf sich, andererseits konnte ich mir diese 
“anderen, an die niemand denkt” nicht wirklich vorstellen.&lt;/p&gt;

&lt;p&gt;Heute denke ich, dass dieses Gebet zu den wichtigeren zählt, denn es ist
nicht das übliche “Bitten” für einen selbst, sondern der Wunsch, dass es
uns allen gut gehen möge, auch jenen, die alleine sind.&lt;/p&gt;

&lt;p&gt;Wenn ich mich recht an den Lateinunterricht und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Marcus_Tullius_Cicero&quot;&gt;Ciceros&lt;/a&gt; Werke erinnere,
so schrieb er doch in etwa:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Menschen bilden Gemeinschaften nicht aus Schwäche,
sondern sie kommen zusammen, weil es ihre Natur ist.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ein schöner Gedanke, dass wir uns um andere kümmern und sorgen, weil
es uns Inne wohnt und nicht, weil wir uns etwas erwarten.&lt;/p&gt;

&lt;p&gt;Versuchen WIR heute nicht nur an die Familie, die Freunde und Kollegen
zu denken, sondern auch an die Tatsache, dass es viele andere da draußen gibt.&lt;/p&gt;

&lt;p&gt;Das laufende 21. Jahrhundert wird eine große Herausforderung für alle werden.
Und wir werden es wohl am besten meistern, wenn wir es gemeinsam beschreiten.
Wenn wir uns nicht von Habgier leiten lassen, sondern auf einander vertrauen
lernen.&lt;/p&gt;

&lt;p&gt;… wie gut, dass endlich wieder mal Zeit war, auch darüber nachzudenken.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Euch allen ein frohes Weihnachtsfest!&lt;/strong&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>MSDN Abo-Check</title>
   <link href="https://www.opengate.at/blog/2019/12/msdn/"/>
   <published>2019-12-22T12:00:00+01:00</published>
   <updated>2019-12-22T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2019/12/msdn</id>
   <category term="software" />
   <summary type="text">Anfang 2019 habe ich mir ja erstmals ein privates 
MSDN Abo gegönnt.
Und nun fragt mich Microsoft, ob 
ich nicht weitere tausend Euro für eine Verlängerung einzahlen möchte.

Hmm … eine schwierige Frage.
</summary>
   <content type="html">&lt;p&gt;Anfang 2019 habe ich mir ja erstmals ein privates 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Developer_Network&quot;&gt;MSDN&lt;/a&gt; Abo gegönnt.
Und nun fragt mich &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft&quot;&gt;Microsoft&lt;/a&gt;, ob 
ich nicht weitere tausend Euro für eine Verlängerung einzahlen möchte.&lt;/p&gt;

&lt;p&gt;Hmm … eine schwierige Frage.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Also, wäre das Jahr so wie geplant verlaufen, oder anders gesagt,
hätte ich keinen fixen Dienstvertrag unterschrieben und wäre in ich in meiner
Zeiteinteilung frei geblieben, so hätte ich wohl wesentlich mehr Zeit in die
Softwareangebote investieren können.&lt;/p&gt;

&lt;p&gt;Nun frage ich mich, ob die Developer-Subscription gemessen an meiner geringen
Nutzung nicht etwas überteuert war.&lt;br /&gt;
Denn außer ein paar Windows-Installationen und meiner 
&lt;a href=&quot;https://en.wikipedia.org/wiki/Windows_Server_2016&quot;&gt;Server 2016&lt;/a&gt; Lizenz,
konnte ich fast nichts nutzen, nicht einmal geplanten Windows Embedded Tests
habe ich gestartet.&lt;/p&gt;

&lt;p&gt;Hinzu kommt nun auch noch die Tatsache, dass mein aktuelles Arbeitsverhältnis
einen weiteren MSDN Zugang beinhaltet wo ich - nach Absprache - auch die eine
oder andere Lizenz zu Hause nutzen dürfte.&lt;/p&gt;

&lt;p&gt;Wieso also dann nochmals zahlen ?&lt;/p&gt;

&lt;p&gt;Tja, einerseits spielt es finanziell keine Rolle, und über diese glückliche
Tatsache freue ich mich auch sehr … andererseits bin ich aber nicht so 
erzogen worden, einfach Geld für Sinnloses hinauszuwerfen.&lt;/p&gt;

&lt;p&gt;Mit einem eigenen Abo wäre ich aber unabhängig und auch wenn ich nicht davon
ausgehe, dass sich meine berufliche Situation in den nächsten Wochen ändert,
so wäre es doch gut in diesem Fall sofort für etwas Neues “einsatzfähig” zu
sein.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Das Thema MSDN-Abo wird mich also noch die nächsten Tage beschäftigen, 
wo ich dann wahrscheinlich an den letzten Monatstagen entscheiden werde,
ob ich noch schnelle alle unbenutzten Lizenzschlüssel freischalte und
bei mir speichere, oder einfach in die Verlängerung gehe …&lt;/p&gt;

&lt;p&gt;Mal sehen was die Zukunft bring ;)&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Die Windows &apos;Filme&apos; App</title>
   <link href="https://www.opengate.at/blog/2019/12/uwp-movies/"/>
   <published>2019-12-21T12:00:00+01:00</published>
   <updated>2019-12-21T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2019/12/uwp-movies</id>
   <category term="software" />
   <summary type="text">Zum größten Totalversagen seitens Microsoft zählt aus meiner Sicht die 
gesamte UWP (Universal Windows Platform)
und deren Standard-Apps, die alle offline-unfähig und online-fehlerhaft sind.

Und die schlimmste Ausprägung davon ist die “Filme” App (Movie-App), 
mit der man sich die Filme und Serien ansehen kann (bzw. können sollte), 
die man teuer im Microsoft Store
gekauft hat.
</summary>
   <content type="html">&lt;p&gt;Zum größten Totalversagen seitens Microsoft zählt aus meiner Sicht die 
gesamte &lt;a href=&quot;https://de.wikipedia.org/wiki/Universal_Windows_Platform&quot;&gt;UWP (Universal Windows Platform)&lt;/a&gt;
und deren Standard-Apps, die alle offline-unfähig und online-fehlerhaft sind.&lt;/p&gt;

&lt;p&gt;Und die schlimmste Ausprägung davon ist die “Filme” App (Movie-App), 
mit der man sich die Filme und Serien ansehen kann (bzw. können sollte), 
die man teuer im &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Store&quot;&gt;Microsoft Store&lt;/a&gt;
gekauft hat.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;problem&quot;&gt;Problem&lt;/h3&gt;

&lt;p&gt;Es ist wieder mal so weit. Heute möchte ich mir einen der Filme ansehen,
die ich vor ein oder zwei Jahren im MS-Store online gekauft und 
heruntergeladen habe.&lt;/p&gt;

&lt;p&gt;Ich starte die App und den Film, die ersten 10 Sekunden scheint alles OK
zu sein, und dann passiert es:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Das Bild beginnt mehr und mehr zu stocken bis es letztendlich einfriert.&lt;/li&gt;
  &lt;li&gt;Parallel dazu laufen plötzlich auch die Anzeigen aller anderen offenen 
Programme immer schleppender, bis auch sie einfrieren.&lt;/li&gt;
  &lt;li&gt;Anfangs klappt das Umschalten zwischen Fenstern noch, bis auch das nicht
mehr bearbeitet wird.&lt;/li&gt;
  &lt;li&gt;Selbst &lt;a href=&quot;https://en.wikipedia.org/wiki/Control-Alt-Delete&quot;&gt;STRG + ALT + DEL&lt;/a&gt;
funktioniert dann scheinbar auch nicht.&lt;/li&gt;
  &lt;li&gt;Der PC (bzw. die Festplatte) scheint hart zu arbeiten, doch die Maschine
regiert nicht.&lt;/li&gt;
  &lt;li&gt;Ein RESET lässt Windows zwar ganz korrekt neu hochfahren, doch sobald 
man die tückische Movie-App wieder öffnet, wiederholt sich der Zirkus.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;lösung&quot;&gt;Lösung&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Es gibt keine!&lt;/strong&gt; Man braucht einfach nur viel Geduld und Zeit.&lt;/p&gt;

&lt;p&gt;Da sich in einer solchen Phase auch der &lt;a href=&quot;https://de.wikipedia.org/wiki/Taskmanager&quot;&gt;Windows Task-Manager&lt;/a&gt; 
nicht starten lässt, ist es schwer zu analysieren, was da abgeht.&lt;br /&gt;
Wenn man &lt;code&gt;TaskMgr&lt;/code&gt; schon vor der Filme-App startet, kann man sehen, wie die
Auslastung eines Systemdienst-Prozesses namens “Web Account Manager” ansteigt, 
doch dann friert auch diese Anzeige ein.&lt;/p&gt;

&lt;p&gt;Nun, es sieht so aus, als würde eine Online-Validierung des Videomaterials 
stattfinden und die Videoabspielung dadurch behindert.&lt;/p&gt;

&lt;p&gt;Warum das allerdings auch alle anderen Prozesse einfrieren lässt, ist mir ein 
Rätsel…&lt;br /&gt;
Denn eigentlich sollte jeder NT-Prozess, sogar jeder Treiber-Task unabhängig
laufen und fremde Applikationen nicht beeinflussen, es sei denn diese würden
einen Datenaustausch mit der bockigen Komponente durchführen wollen.&lt;/p&gt;

&lt;p&gt;Das Problem löst sich nach 5 bis 15 Minuten ganz von selbst. Denn plötzlich
laufen das Video und auch alle anderen Prozesse wieder ordnungsgemäß weiter.
Hat man STRG + ALT + DEL gedrückt erscheint verspätet der Sperrbildschirm.&lt;/p&gt;

&lt;p&gt;Wahrscheinlich ist die Onlineprüfung dann beendet und alle blockierten
Systemaufrufe werden wieder normal weiterverarbeitet.&lt;/p&gt;

&lt;p&gt;Ich weiß ja nicht, wer hier die Drähte aller User-Mode und Kernel-Tasks so 
verwoben hat, dass so ein verhalten auftritt, aber denjenigen möchte ich gerne
mal in die Finger bekommen.&lt;br /&gt;
Denn Windows hatte solche Kinderkrankheiten eigentlich schon lange 
ausgestanden.&lt;br /&gt;
Dass wir so eine Dummheit in UWP Apps mit &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_10&quot;&gt;Windows 10&lt;/a&gt;
wieder hereinbekommen haben ärgert mich ungemein!&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Tja, jetzt müsste ich eigentlich sagen:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Keine Videos im Store kaufen, sondern wo anders “besorgen”.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Denn klassische Video Apps kommen mit fast allen Formaten zurecht
und blockieren bei Problemen nicht gleich das ganze System.&lt;/p&gt;

&lt;p&gt;Nur dieser &lt;a href=&quot;https://de.wikipedia.org/wiki/Digitale_Rechteverwaltung&quot;&gt;DRM&lt;/a&gt; Mist
mit digital signierten Medien, die nur in speziellen Apps laufen, machen 
fortlaufend Probleme!&lt;/p&gt;

&lt;p&gt;Also ein fetter Daumen nach unten für Microsoft!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Meine alten Bücher</title>
   <link href="https://www.opengate.at/blog/2019/12/books/"/>
   <published>2019-12-15T12:00:00+01:00</published>
   <updated>2019-12-15T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2019/12/books</id>
   <category term="retro" />
   <summary type="text">
  Aristoteles, Empedokles, Aeneas, Parmenides.
Und Nikomachos, Diogenes,Antiochos, Maimonides!
Schon beim Riechen, spür’n wir die Weisheit der Griechen.
Mark Aurel und Augustinus. Tacitus, Tibull, und Plato.
Peregrinus und Taquinus. Caesar, Cicero und Cato.
Schon beim Tasten wird man zum Enthusiasten!


So beginnt im Musical Tanz der Vampire
Professor Abronsius’ Lobhymne auf die große Bibliothek des Grafen Krolock.

Gemessen an den vielen Dingen, die ich aus 
Büchern lernen durfte bzw. 
musste, sollte auch ich ein solches Lied anstimmen …
</summary>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;Aristoteles, Empedokles, Aeneas, Parmenides.&lt;br /&gt;
Und Nikomachos, Diogenes,Antiochos, Maimonides!&lt;br /&gt;
Schon beim Riechen, spür’n wir die Weisheit der Griechen.&lt;br /&gt;
Mark Aurel und Augustinus. Tacitus, Tibull, und Plato.&lt;br /&gt;
Peregrinus und Taquinus. Caesar, Cicero und Cato.&lt;br /&gt;
Schon beim Tasten wird man zum Enthusiasten!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So beginnt im &lt;a href=&quot;https://de.wikipedia.org/wiki/Tanz_der_Vampire_(Musical)&quot;&gt;Musical Tanz der Vampire&lt;/a&gt;
Professor Abronsius’ Lobhymne auf die große Bibliothek des Grafen Krolock.&lt;/p&gt;

&lt;p&gt;Gemessen an den vielen Dingen, die ich aus 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Buch&quot;&gt;Büchern&lt;/a&gt; lernen durfte bzw. 
musste, sollte auch ich ein solches Lied anstimmen …
&lt;!--more--&gt;&lt;/p&gt;

&lt;video controls=&quot;&quot;&gt;
  &lt;source src=&quot;/blog/assets/video/tanz-der-vampire-buecher-1.mp4&quot; type=&quot;video/mp4&quot; /&gt;
  Your browser does not support the HTML5 VIDEO tag.
&lt;/video&gt;

&lt;hr /&gt;

&lt;p&gt;Jungs und Mädls “von heute” können natürlich nicht wissen, dass “wir”
vor dem Jahr 2000 kein Google (oder &lt;a href=&quot;http://www.duckduckgo.com&quot;&gt;duckduckgo.com&lt;/a&gt;)
hatten.&lt;/p&gt;

&lt;p&gt;Wissen und auch die Kunst des Programmierens lernten wir damals aus 
zusammengebundenen Papierblättern, auch bekannt als “Bücher”.&lt;br /&gt;
Das waren die Vorläufer der &lt;a href=&quot;https://de.wikipedia.org/wiki/Portable_Document_Format&quot;&gt;PDF&lt;/a&gt;s 
und &lt;a href=&quot;https://de.wikipedia.org/wiki/E-Book&quot;&gt;E-Books&lt;/a&gt;, die wenn sie einmal 
“gedruckt” waren, energie-autark und systemunabhängig benutzbar waren.&lt;br /&gt;
Sie wurden per Touchkommandos benutzt, primär durch geziehltes “Wischen”
an der Kante um von einer zur anderen Seite umzublättern.&lt;/p&gt;

&lt;p&gt;… OK, Spaß bei Seite.&lt;/p&gt;

&lt;p&gt;Meine “ältesten” Bücher zur Programmierung waren aber nicht meine ersten.
Sie behandelten &lt;a href=&quot;https://de.wikipedia.org/wiki/BASIC&quot;&gt;BASIC&lt;/a&gt; auf 
&lt;a href=&quot;https://de.wikipedia.org/wiki/MSX&quot;&gt;MSX&lt;/a&gt; und &lt;a href=&quot;https://de.wikipedia.org/wiki/Commodore_64&quot;&gt;C64&lt;/a&gt;, 
sowie &lt;a href=&quot;/blog/2019/12/assembler/&quot;&gt;Assembler auf dem Z80&lt;/a&gt;, 
doch diese erwarb ich erst so um das Jahr 2000 beim Abverkauf im Bücherladen.&lt;br /&gt;
&lt;img src=&quot;/blog/assets/img/book-basic-programming.jpg&quot; alt=&quot;Book about old BASIC&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Bei mir begann die Programmiergeschichte ja mit 
&lt;a href=&quot;https://de.wikipedia.org/wiki/QBasic&quot;&gt;QBasic&lt;/a&gt;, und das lernte ich Mitte der 
90er eigentlich hoch-modern “online”, aber nicht “internet-online” 
sondern am “eingeschalteten PC” über die eingebaute Befehlshilfe. 
Doch fehlte es dort an einer vernünftigen Lektüre für Datenstrukturen 
oder wie man BASIC-Befehlen strukturiert umgeht.&lt;br /&gt;
Dementsprechend sahen auch meine Programme aus … aus heutiger Sicht 
unerträglich.&lt;/p&gt;

&lt;h3 id=&quot;visual-basic&quot;&gt;Visual Basic&lt;/h3&gt;

&lt;p&gt;Mit dem Kauf von &lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_Basic_Classic#1996%E2%80%931998:_Visual_Basic_4%E2%80%936_%E2%80%93_32_Bit_und_COM&quot;&gt;Visual Basic 4.0&lt;/a&gt;
lieferte Microsoft auch gleich 3 fette Wälzer mit, von denen ich zumindest 2 
(teilweise mehrfach) durchgelesen hatte. Das Buch “Sprachverzeichnis” war 
bitter notwendig, weil &lt;a href=&quot;https://de.wikipedia.org/wiki/IntelliSense&quot;&gt;IntelliSense&lt;/a&gt; 
noch nicht erfunden war und man selbst wissen musste, wie alle Funktionen 
und Objektmethoden hießen.&lt;br /&gt;
&lt;img src=&quot;/blog/assets/img/book-vb4.jpg&quot; alt=&quot;Books about Visual Basic&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Lehrreicher war jedoch das “Programmierhandbuch”, denn dort wurden Konzepte
und Funktionsweisen erklärt, sodass auch ein Neuling wie ich verstehen 
konnte, was Objektinstanzen und indizierte 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Feld_(Datentyp)&quot;&gt;Datenfelder&lt;/a&gt; sind.&lt;/p&gt;

&lt;p&gt;Das 3. Buch behandelte &lt;a href=&quot;https://de.wikipedia.org/wiki/Datenbank&quot;&gt;Datenbanken&lt;/a&gt; 
und &lt;a href=&quot;https://de.wikipedia.org/wiki/Component_Object_Model&quot;&gt;COM&lt;/a&gt; …
doch die dort benutzten Begriffe verstand ich nicht und ließ es bleiben.&lt;/p&gt;

&lt;p&gt;Nachtrag: Meine alten VB4 Setup Disketten funktionieren sogar noch.
Allerdings sehen sie nach über 23 Jahren schon sehr mitgenommen aus.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/visual-basic-4-floppies.jpg&quot; alt=&quot;VB4-Floppies&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Zwar bin ich meiner Schule dankbar, dass ich sie von dort bekommen habe,
allerdings war damals schon VB5 am Übernehmen, als sie in meinem Besitz
übergingen, womit ich (wie so oft) mit Altlasten statt mit Innovationen
arbeitete.&lt;/p&gt;

&lt;h3 id=&quot;pascal&quot;&gt;Pascal&lt;/h3&gt;

&lt;p&gt;Parallel dazu schenkte mir ein Bekannter eines Nachbarn seine 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Pascal_(Programmiersprache)&quot;&gt;Pascal&lt;/a&gt; Bücher,
die er in seiner Studienzeit genutzt hatte. Sie stammten wohl aus den 80er
Jahren und waren aus meiner Sicht extrem “mathematisch” aufgebaut.&lt;br /&gt;
Vieles über “Zeiger” und “verkettete Listen” verstand ich ganz und gar nicht,
doch bleiben einige Begriffe und Konzepte wie “Rekursionen” und “Schleifen”
in meinem Kopf hängen.&lt;br /&gt;
&lt;img src=&quot;/blog/assets/img/book-pascal.jpg&quot; alt=&quot;Books about Pascal&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;c&quot;&gt;C++&lt;/h3&gt;

&lt;p&gt;Im Jahr 2000 kam ich tatsächlich schon auf die Idee &lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B&quot;&gt;C++&lt;/a&gt;
lernen zu wollen und schaffte hierzu einen dicken Schmöcker an, der mich 
allerdings schon im ersten Kapitel so überforderte, dass ich das Buch ins 
Regal stellte und für viele Jahre dort verstauben ließ.&lt;br /&gt;
Das war vermutlich der aller größte Fehler meines Lebens, denn wie weit 
könnte ich heute sein, hätte ich diese Jahre gleich “beim Meister” gelernt.&lt;br /&gt;
&lt;img src=&quot;/blog/assets/img/book-cpp.jpg&quot; alt=&quot;Book about C++&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;java-und-asp&quot;&gt;Java und ASP&lt;/h3&gt;

&lt;p&gt;Weiter ging es 2002 und 2003. Da standen das Internet, 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Java_(Programmiersprache)&quot;&gt;Java&lt;/a&gt;, 
&lt;a href=&quot;https://de.wikipedia.org/wiki/PHP&quot;&gt;PHP&lt;/a&gt; und &lt;a href=&quot;https://de.wikipedia.org/wiki/Active_Server_Pages&quot;&gt;ASP&lt;/a&gt; 
auf dem Programm.&lt;br /&gt;
Aus heutiger Sicht ist es schon witzig, dass jedes beliebige Tutorial im
Internet gleich gut oder besser aufgebaut ist, als diese “professionellen”
Bücher es damals waren. Doch trotz der steigenden Verbreitung der digitalen
Online-Informationen, waren damals Bücher immer noch die besseren, 
vollständigeren und strukturierteren Datenquellen.&lt;br /&gt;
&lt;img src=&quot;/blog/assets/img/book-java-asp.jpg&quot; alt=&quot;Book about Java and ASP&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Besonders in deutscher Sprache gab es nur wenige Webseiten, die Anfängern 
ein gutes Lernmaterial boten … doch das sollte sich ändern.&lt;/p&gt;

&lt;p&gt;Ich glaube so ab dem Jahr 2004/2005 war es dann für mich mit dem Buchzeitalter 
endgültig vorbei. Selbiges kann man auch von Zeitschriften und ähnlichem 
sagen. Denn ab dieser Zeit war das Internet bereits wesentlich schneller in 
der Verbreitung von neuem Wissen in der eigenen Landessprache. Wer auf Bücher
wartete, die immer erst 1 bis 2 Jahre später erschienen, blieb de facto auf 
veraltetem Wissen sitzen.&lt;br /&gt;
Oder es gab überhaupt keine auf Papier gedruckten Informationen zu einer 
neuen Programmiersprache oder Technologie mehr.&lt;/p&gt;

&lt;p&gt;Und als ich in den Jahren 2006/2007 endlich zu C++ wechselte um beruflich
als Entwickler zu arbeiten, waren mein praktisches Wissen und Englischvokabular 
ausgeprägt genug, um Fachartikel direkt aus dem Internet herauszupicken.&lt;/p&gt;

&lt;h3 id=&quot;heute-&quot;&gt;Heute …&lt;/h3&gt;

&lt;p&gt;Heute habe ich mein Bücherregal (das eher ein DVD-Regal ist) etwas entstaubt
und dabei meinen alten Lesestoff “von vor 20 Jahren” wieder gefunden.&lt;/p&gt;

&lt;p&gt;Ich würde gerne behaupten:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Pah! Das habe ich doch gar nicht gebraucht. 
Ich habe ohnehin alles selbst herausgefunden.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Doch das stimmt nicht. Jedes Buch, egal zu welcher Programmiersprache,
hat mir irgend etwas neues über den Aufbau von Funktionen oder Algorithmen
beigebracht, was ich aus dem reinen Lesen von fremden Quellcodes wohl
übersehen oder nicht verstanden hätte.&lt;/p&gt;

&lt;p&gt;Und auch wenn klassische Bücher im 21. Jahrhundert wohl nach 500 Jahren als 
Grundsicherung der Wissensvermittlung abgeschafft werden, so werden dennoch
ihre Nachfolger als digitale Literatur mit ähnlichem Aufbau diese wichtige
Funktion in die Zukunft weitertragen.&lt;/p&gt;

&lt;p&gt;Anmerkung:&lt;br /&gt;
Etwas haben gedruckte Bücher den Bits und Bytes voraus:&lt;br /&gt;
Bei guter Lagerung können Papierbücher Jahrhunderte, wenn nicht sogar 
Jahrtausende überdauern.&lt;/p&gt;

&lt;p&gt;… doch wer kann heute noch ein 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Word#Versionen_f%C3%BCr_Windows_(16-Bit)&quot;&gt;Word 2.0&lt;/a&gt;
Dokument auf seinem PC oder Tablet öffnen?&lt;br /&gt;
Tja, Formate und Kompatibilität sind die &lt;a href=&quot;https://de.wikipedia.org/wiki/Achillesferse&quot;&gt;Archillesferse&lt;/a&gt;
unserer modernen Gesellschaft. Denn was heute modern ist, gilt morgen als 
vergessen, und so besteht die Möglichkeit, dass gerade in der digitalen 
Epoche Wissen wegen seiner proprietären Speicherung verloren geht.&lt;br /&gt;
Die &lt;a href=&quot;https://de.wikipedia.org/wiki/Johannes_Gutenberg&quot;&gt;Gutenberg&lt;/a&gt; Bibel 
hingegen hat Word 2.0 Dokumente auf jeden Fall schon überlebt … mal sehen 
was sie sonst noch alles entstehen und untergehen sehen wird.&lt;/p&gt;

&lt;p&gt;Die am Anfang erwähnte Musical-Szene endet jedenfalls mit folgenden Worten:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Millionen Bücher blieben&lt;br /&gt;
Von den Menschen die mal waren&lt;br /&gt;
Hätten sie’s nicht aufgeschrieben&lt;br /&gt;
Könnten wir es nicht bewahren&lt;br /&gt;
Eine Welt von Ignoranten&lt;br /&gt;
Würde nichts davon erfahren&lt;br /&gt;
Alle Bücher sind Garanten&lt;br /&gt;
Für den Fortschritt und für menschliche Kultur&lt;/p&gt;

  &lt;p&gt;Na, hast du dir das gemerkt, mein Junge?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;video controls=&quot;&quot;&gt;
  &lt;source src=&quot;/blog/assets/video/tanz-der-vampire-buecher-2.mp4&quot; type=&quot;video/mp4&quot; /&gt;
  Your browser does not support the HTML5 VIDEO tag.
&lt;/video&gt;
</content>
 </entry>
 
 <entry>
   <title>Assembler</title>
   <link href="https://www.opengate.at/blog/2019/12/assembler/"/>
   <published>2019-12-14T12:00:00+01:00</published>
   <updated>2019-12-14T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2019/12/assembler</id>
   <category term="devel" /><category term="retro" />
   <summary type="text">Man könnte es als pubertäre Selbstüberschätzung werten, als ich schon in
frühen Jugendjahren meinte:


  Ach, Programmieren kann ich so gut, ich muss jetzt die schwerste Art
Code zu schreiben lernen, nämlich Assembler.


Hmm … aus heutiger Sicht war das recht überheblich. Ich weiß nun,
dass ich heute in Summe immer noch recht wenig (viel zu wenig) verstanden
habe … und vor 20 Jahren war das noch viiieeel schlimmer.

Und trotzdem, bis heute profitiere ich aus den Experimenten und dem Wissen 
von damals …
</summary>
   <content type="html">&lt;p&gt;Man könnte es als pubertäre Selbstüberschätzung werten, als ich schon in
frühen Jugendjahren meinte:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ach, Programmieren kann ich so gut, ich muss jetzt die schwerste Art
Code zu schreiben lernen, nämlich &lt;a href=&quot;https://de.wikipedia.org/wiki/Assemblersprache&quot;&gt;Assembler&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Hmm … aus heutiger Sicht war das recht überheblich. Ich weiß nun,
dass ich heute in Summe immer noch recht wenig (viel zu wenig) verstanden
habe … und vor 20 Jahren war das noch viiieeel schlimmer.&lt;/p&gt;

&lt;p&gt;Und trotzdem, bis heute profitiere ich aus den Experimenten und dem Wissen 
von damals …
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;In meiner kleinen Welt stand am Anfang &lt;a href=&quot;https://de.wikipedia.org/wiki/QBasic&quot;&gt;QBASIC&lt;/a&gt;, 
gefolgt von &lt;a href=&quot;https://de.wikipedia.org/wiki/Pascal_(Programmiersprache)&quot;&gt;Pascal&lt;/a&gt;. 
Und in beiden Fällen waren die Grenzen schnell erreicht. In QBASIC fehlte es 
vor allem an “ordentlichen” Dateisystem-Routinen und in Pascal an “schneller”
Grafik.&lt;/p&gt;

&lt;p&gt;Durch QuickBasic 4.5 bekam ich etwas von &lt;a href=&quot;/blog/2019/02/bios-interrupts/&quot;&gt;Interrupts&lt;/a&gt;
mit, die über die Bibliothek &lt;code&gt;QB.BI&lt;/code&gt; möglich gemacht wurden.&lt;br /&gt;
Und in Turbo Pascal 6 fand ich immer mehr Beispiele, wie diese Interrupts 
benutzt wurden um “geheime” Systemfunktionen auszulösen.&lt;/p&gt;

&lt;p&gt;So ganz nebenbei ergab sich daraus das Wissen, dass der Prozessor mit 
ganz besonderen “Variablen” arbeitet, die als Register bekannt sind.&lt;br /&gt;
Eigentlich kann der Prozessor überhaupt nur mit Werten in seinen Registern
rechnen und Daten aus Variablen im Speicher, die wir aus Programmiersprachen 
kennen, müssen stets in Register geladen oder aus diesen gespeichert werden.&lt;/p&gt;

&lt;p&gt;… und das macht man in: Assembler.&lt;/p&gt;

&lt;h3 id=&quot;maschinensprache&quot;&gt;Maschinensprache&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Assembler&lt;/em&gt; ist eigentlich &lt;em&gt;KEINE&lt;/em&gt; Programmiersprache wie 
&lt;a href=&quot;https://de.wikipedia.org/wiki/C_(Programmiersprache)&quot;&gt;C&lt;/a&gt; oder 
&lt;a href=&quot;https://de.wikipedia.org/wiki/BASIC&quot;&gt;BASIC&lt;/a&gt;.
Jeder Prozessortyp versteht eine bestimmte Menge an Operationscodes,
die durch Bytesequenzen kodiert sind. Und da wir Menschen uns recht schwer
tun, uns hunderte Bytecodes mit ihren Verknüpfungen zueinander zu merken,
wurden menschen-lesbare Codes eingeführt (&lt;a href=&quot;https://de.wikipedia.org/wiki/Assemblersprache#Mnemonic&quot;&gt;Mnemonics&lt;/a&gt;
genannt), mit denen wir Maschinenbefehle als Textbefehle darstellen können.&lt;/p&gt;

&lt;p&gt;… und das heißt dann Assembler, sieht aber für jede Plattform anders aus.&lt;/p&gt;

&lt;p&gt;Eigentlich wurden Programmiersprache (sogenannte “Hochsprachen” oder 
“high-level languages”) eingeführt, damit wir bequem mit Variablen und 
Funkionen arbeiten können und uns nicht um maschinen-nahe Details kümmern
müssen.&lt;br /&gt;
Fakt ist aber, dass auch der beste &lt;a href=&quot;https://de.wikipedia.org/wiki/Compiler&quot;&gt;Compiler&lt;/a&gt;
der besten Hochsprache immer von einer genialen Programmieridee ausgestochen
werden kann.&lt;br /&gt;
Das heißt also: Theoretisch kann man in Assembler “das perfekte Programm” 
schreiben, in anderen Sprachen sind sie nur “annähernd perfekt” oder “gut”.&lt;/p&gt;

&lt;p&gt;Genau das war wohl auch mein Ehrgeiz, hier in die Tiefe zu gehen.&lt;/p&gt;

&lt;p&gt;Und tatsächlich war es zu Zeiten von &lt;a href=&quot;https://de.wikipedia.org/wiki/MS-DOS&quot;&gt;MS-DOS&lt;/a&gt; 
möglich und auch teils notwendig, Programmteile mit Assembler-Tricks zu 
optimieren. Denn die damaligen Compiler waren gezwungen mit wenig RAM und 
CPU-Kraft auszukommen und konnten keine Codeanalysen durchführen, die sie
heute problemlos schaffen.&lt;/p&gt;

&lt;p&gt;Und so wurde ein Funktionsaufruf einer Hochsprache oft sehr linear in 
Maschinenbefehle übersetzt.&lt;br /&gt;
Genau hier konnte man die Zugriffe auf Variablen im RAM reduzieren und 
mehr aus den Registern herausholen.&lt;/p&gt;

&lt;h3 id=&quot;das-z80-problem&quot;&gt;Das Z80 Problem&lt;/h3&gt;

&lt;p&gt;Nun, hätte mir damals schon jemand gesagt, dass mein PC einen 
&lt;a href=&quot;https://de.wikipedia.org/wiki/X86-Prozessor&quot;&gt;X86&lt;/a&gt; Prozessor beinhaltet und 
ich somit nur mit einem X86-Assembler darauf programmieren kann, wäre mir das
folgende peinliche Missgeschick wohl erspart geblieben.&lt;/p&gt;

&lt;p&gt;Selbstbewusst lief ich nämlich in den Bücherladen und wollte ein 
Assembler-Buch kaufen. Die dortige Angestellte fischte sogleich eines aus 
ihrer Liste, bestellte es und eine Woche später hielt ich es in meinen 
Händen.&lt;/p&gt;

&lt;p&gt;Die ersten Seiten zeigten bereits, dass das Buch wohl etwas “alt” war …
aber egal, schließlich hatte ich ja auch 15 Jahre alte Pascal Bücher gelesen
und die Befehle dort funktionierten alle noch.&lt;br /&gt;
Doch die Befehle im Buch waren mir alle fremd und passten so überhaupt nicht
zu jenen, die ich in Pascal schon kennen gelernt hatte.&lt;/p&gt;

&lt;p&gt;Tja, das Buch behandelte den &lt;a href=&quot;https://de.wikipedia.org/wiki/Zilog_Z80&quot;&gt;Z80&lt;/a&gt;
Prozessor, der so gut wie gar nichts mit den PC-Prozessoren gemein hatte.&lt;br /&gt;
Hmm, dumm gelaufen … also blieb meine Quelle für Assemblerwissen weiter
nur die eine oder andere PC-Zeitschrift, wo mal ein bisschen ASM-Quellcode 
abgedruckt war.&lt;br /&gt;
&lt;img src=&quot;/blog/assets/img/book-z80.jpg&quot; alt=&quot;Book about Z80 Assembler&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Dennoch las ich das Buch und versuchte mich in die dort beschriebene Welt
hineinzudenken. Und das war gold-richtig.&lt;/p&gt;

&lt;h3 id=&quot;gameboy-emulationen-und-pokemon&quot;&gt;Gameboy-Emulationen und Pokemon&lt;/h3&gt;

&lt;p&gt;Ich wusste es damals noch nicht, doch einen Z80 Prozessor hatte ich schon
einmal besessen. Er war in meinem Nintendo &lt;a href=&quot;https://de.wikipedia.org/wiki/Game_Boy&quot;&gt;Gameboy&lt;/a&gt;
verbaut, den ich Dummkopf kurz vor meinem Engagement für Assembler verkauft 
hatte um (heute unvorstellbar) eine legale Visual Basic Edition zu kaufen.&lt;/p&gt;

&lt;p&gt;Und so lag das Buch und das Z80 Wissen nutzlos bis zum Jahr 2000 herum,
als mir ein Schulfreund einen Download aus dem Internet aufschwatzte.
Es war der “gute alte” Gameboy-Emulator &lt;a href=&quot;http://gbdev.gg8.se/wiki/articles/No$gmb&quot;&gt;&lt;code&gt;NO$GMB&lt;/code&gt;&lt;/a&gt;, 
der auch auf meiner alten Gebraucht-Hardware flüssig lief.&lt;br /&gt;
&lt;img src=&quot;/blog/assets/img/app-no$gmb.png&quot; alt=&quot;NO$GMB Emulator&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;NO$GMB&lt;/code&gt; war nicht nur ein Emulator, sondern enthielt auch einen Assembler-
Debugger, mit dem die Z80-Opcodes als Mnemonics dargestellt wurden …
also genau die Befehle, die mein Z80 Buch beschrieb.&lt;/p&gt;

&lt;p&gt;An dieser Stelle hätte es eigentlich passieren können, dass ich mich zum
Z80-Assembler-Spezialist hätte entwickeln können … doch leider 
Fehlanzeige. Denn mein lieber Freund packte auch das damals beliebteste
Gameboy Spiel dem Emulator bei, und das war: 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Pok%C3%A9mon_Rote_und_Blaue_Edition&quot;&gt;&lt;em&gt;Pokemon - Blaue Edition&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Damit dauerte es nicht lange, dass ich das Buch wieder bei Seite legte und
eine bis heute andauernde Zuneigung zu den kleinen virtuellen Kreaturen
aufbaute.&lt;/p&gt;

&lt;h3 id=&quot;perfektion&quot;&gt;Perfektion&lt;/h3&gt;

&lt;p&gt;Eines habe ich aber sehr schnell zu respektieren gelernt: Die Macher von
Gameboy-Spielen, die aus Platzgründen häufig direkt in Assembler arbeiten
mussten, waren absolute Genies der Programmierung.&lt;br /&gt;
Sie schafften es, mit wenigen Maschinenbefehlen das hinzubekommen, wofür
Compiler hunderte Bytes hätten generieren müssen.&lt;/p&gt;

&lt;p&gt;Das beginnt bei Limitierungen, wie einer fehlenden Multiplikationseinheit
auf der CPU und endet bei der Nutzung von einer Hand voll Bytes, die 
reichten um den ganzen Bildschirm mit Grafiken zu füllen.&lt;/p&gt;

&lt;p&gt;Ja ich bewundere jene Vollblutentwickler, die sich in Maschinencodes 
hineindenken und “perfekte” Lösungen für ein Problem schaffen. Und es ist
fast schade, dass die heutigen Leistungsdaten unserer Computer und der
gebotene Komfort unserer Compiler uns diese alte ehrwürdige Kunst langsam
vergessen lassen.&lt;/p&gt;

&lt;h3 id=&quot;x86-assembler&quot;&gt;X86 Assembler&lt;/h3&gt;

&lt;p&gt;Nach dem Z80-Buch-Kauf folgte der Kauf meiner &lt;a href=&quot;https://de.wikipedia.org/wiki/Turbo_Assembler&quot;&gt;Turbo-Assembler 4.0&lt;/a&gt;
CD (die im Jahr 2000 auch schon etwas veraltet war). Damit hatte ich die 
folgenden Jahre immer wieder Spaß, brachte aber leider keine wirklich
konkreten Programme hervor. Ein DOS-basierter Text-Editor war so ziemlich
das höchste der Gefühle.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/turbo-assembler-4.jpg&quot; alt=&quot;Turbo Assembler 4 CD&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Sehr interessant waren allerdings viele auf der CD gesammelten Codebeispiele,
für die unterschiedlichsten Probleme aus der “guten alten DOS-Welt”.&lt;br /&gt;
Doch leider wurde auch dieses Wissen mit dem Jahr 2000 mehr und mehr 
obsolet. Und sowohl unter Windows als auch unter Linux nahmen C und C++ mit
ihren immer besser werdenden Compilern den Assembler-Gurus den Wind aus 
den Segeln.&lt;/p&gt;

&lt;p&gt;Der 32-bit X86 Assembler begleitet mich jedoch bis heute weiter. Wenn es darum
geht, den Callstack einer Exception-Behandlung nachzuvollziehen oder zu sehen,
ob ein Template-Konstrukt besser ist als ein Makro, dann schalte ich für C++ 
den Assembler-Source-Generator ein, um zu sehen, wie der C++ Compiler meine 
Anweisungen übersetzt.&lt;/p&gt;

&lt;p&gt;Da kommen oft interessante Ergebnisse zum Vorschein, wie dass Template-Code
mal besser aber leider auch mal schlechter kompiliert wird, als mehrere 
makro-isierte statische Funktionen.&lt;/p&gt;

&lt;p&gt;Am interessantesten sind aber Funktionen, wo der Compiler intelligente 
mathematische Zusammenhänge erkennt, die mir als Programmierer verborgen
blieben. z.B.: wenn ich einen &lt;code&gt;switch(...)&lt;/code&gt; Block nutze um unterschiedlich
Return-Codes zurückzugeben und der Compiler das in 3 oder 4 Rechenzeilen
übersetzt, wo der “geswitchte” Code ohne Vergleiche in die Returncodes 
umgerechnet wird. (Und damit meine ich nicht nur simple Additionen und 
Multiplikationen).&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Assembler ist und bleibt für die höchste Disziplin in der Programmierung.&lt;br /&gt;
Wirtschaftlich relevant ist sie heute leider nicht mehr. Die einzige
Branche, die sie noch aktiv nutzt, sind die Compilerbauer selbst,
gefolgt von einigen wenigen Mikrocontroller-Puristen und gelegentlich mal
bei einem Treiber.&lt;/p&gt;

&lt;p&gt;Hier sehne ich mich doch etwas nach der Zeit, wo alles noch “schlechter”
war, weil man dann mit Assemblerwissen ein kleiner Wunderheiler sein konnte.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Der kleine Retro-Pie</title>
   <link href="https://www.opengate.at/blog/2019/12/retro-pi/"/>
   <published>2019-12-07T12:00:00+01:00</published>
   <updated>2019-12-07T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2019/12/retro-pi</id>
   <category term="hardware" /><category term="software" /><category term="retro" />
   <summary type="text">Für den kleinen Raspberry PI Zero 
gibt es ein interessantes Aufsteckmodul, das den Platinen-PC in eine 
Mini-Konsole verwandeln kann.

Man braucht noch ein Gehäuse, einen Akku und ein entsprechendes OS, und 
schon haben wir einen kleinen Do-It-Yourself Gameboy.

Mal sehen, ob das geht …
</summary>
   <content type="html">&lt;p&gt;Für den kleinen &lt;a href=&quot;https://en.wikipedia.org/wiki/Raspberry_Pi&quot;&gt;Raspberry PI&lt;/a&gt; Zero 
gibt es ein interessantes Aufsteckmodul, das den Platinen-PC in eine 
Mini-Konsole verwandeln kann.&lt;/p&gt;

&lt;p&gt;Man braucht noch ein Gehäuse, einen Akku und ein entsprechendes OS, und 
schon haben wir einen kleinen Do-It-Yourself &lt;a href=&quot;https://de.wikipedia.org/wiki/Game_Boy&quot;&gt;Gameboy&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Mal sehen, ob das geht …
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;bauteil-aufbau&quot;&gt;Bauteil-Aufbau&lt;/h3&gt;

&lt;p&gt;Das &lt;a href=&quot;https://www.aliexpress.com/item/32970035492.html&quot;&gt;Modell Game Zero 1.54 inch&lt;/a&gt;
kommt mit einem 240 x 240 Pixel LCD Display, 6 Font- und 2 Schultertasten 
sowie einem digitalen Joystick.&lt;/p&gt;

&lt;p&gt;Man steckt es auf den Pin-Header eines Raspberry PI und hat die Basis
der Konsole schon mal fertig.&lt;/p&gt;

&lt;p&gt;Etwas tricksen muss man bei der Stromzufuhr. Ich benutze hier wieder einen 
600 mA &lt;a href=&quot;https://de.wikipedia.org/wiki/Lithium-Polymer-Akkumulator&quot;&gt;LiPo Akku&lt;/a&gt;,
der 3.7 Volt liefern würde zusammen mit einen USB-Akku-Lader-Chip,
der den 5 Volt USB Strom umwandelt um einerseits den Akku zu laden, und
gleichzeitig die 3.7 Volt des selbigen wieder auf 5 Volt hochschraubt um
die Raspberry PI damit zu betreiben.&lt;/p&gt;

&lt;p&gt;Damit das klappt wird der Ausgang des Lade-Chips mit den Pins 2 (+5 V) und 
6 (GND) des Headers für den RPI zusammen gelötet. Um das Gerät vollständig 
aus- und einschalten zu können, wird der Ground über einen Schalter geleitet.&lt;/p&gt;

&lt;p&gt;Das sieht dann so aus:&lt;br /&gt;
&lt;img src=&quot;/blog/assets/img/retro-pi-parts.jpg&quot; alt=&quot;RetroPI-Parts&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;gehäuse&quot;&gt;Gehäuse&lt;/h3&gt;

&lt;p&gt;Auf geht’s zum  &lt;a href=&quot;/blog/2019/01/ender-3/&quot;&gt;3D-Drucker&lt;/a&gt;.&lt;br /&gt;
Ich liebe &lt;a href=&quot;http://www.thingiverse.com&quot;&gt;thingiverse.com&lt;/a&gt;, denn dort haben 
begabte Designer auch gleich Modelle für eine solche Mini-Konsole abgelegt.
Wie z.B. &lt;a href=&quot;https://www.thingiverse.com/thing:3585013&quot;&gt;dieses hier&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nachdem das Front- und Bodenteil gedruckt waren, folgten noch die 6 Button
Verlängerungen und die beiden Schultertasten.&lt;/p&gt;

&lt;h3 id=&quot;die-mini-konsole-wird-zusammengesetzt&quot;&gt;Die Mini-Konsole wird zusammengesetzt&lt;/h3&gt;

&lt;p&gt;Nun wird alles zusammengesetzt. Leider hatte ich keinen Außenschalter, der
perfekt in die Öffnung des Gehäuses passte. Doch dafür gibt es die 
Heißklebepistole. So wurde der etwas zu kleine Schalter an der richtigen 
Stelle fixiert.&lt;/p&gt;

&lt;p&gt;Nun werden wie Komponenten von unten nach oben übereinander gestapelt:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Der Raspberry PI Zero bildet die Basis&lt;/li&gt;
  &lt;li&gt;Darüber liegt der längliche Akku, der mit einem doppelseitigem 
Klebestreifen fixiert wird&lt;/li&gt;
  &lt;li&gt;Über dem Akku wird der Lade-Chip ebenfalls mit einem Klebestreifen
fixiert, und zwar so, dass der USB-Port über die entsprechende
Öffnung des Gehäuses nutzbar ist.&lt;/li&gt;
  &lt;li&gt;Am Ende wird das Display- und Steuermodul von oben auf den Raspberry PI 
Header gesteckt.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Das ganze wird nun vom Gehäuse ummantelt, nachdem die Button Verlängerungen
und Schultertasten zwischen Board und Gehäuse platziert wurden.&lt;/p&gt;

&lt;p&gt;Nach dem Zusammenstecken von Ober- und Unterteil hält das Gehäuse von selbst, 
von daher ist vorerst nichts weiter zu tun.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/retro-pi-front.jpg&quot; alt=&quot;RetroPI-Front&quot; /&gt;&lt;br /&gt;
&lt;img src=&quot;/blog/assets/img/retro-pi-right.jpg&quot; alt=&quot;RetroPI-Right&quot; /&gt;&lt;br /&gt;
&lt;img src=&quot;/blog/assets/img/retro-pi-top.jpg&quot; alt=&quot;RetroPI-Top&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;die-software&quot;&gt;Die Software&lt;/h3&gt;

&lt;p&gt;Der Hersteller SpotPear, bei dem ich bestellt habe, bietet fertige
&lt;a href=&quot;http://spotpear.com/download/image/RPi-1.54inch-LCD/retropie-image/&quot;&gt;Raspbian und Retro-PI Images&lt;/a&gt;
zum Download an, in denen der Display Treiber bereits integriert ist.&lt;/p&gt;

&lt;p&gt;Man lädt die komprimierten Images herunter, entpackt sie und spielt sie
z.B. mit dem &lt;a href=&quot;https://sourceforge.net/projects/win32diskimager/&quot;&gt;Win32DiskImager&lt;/a&gt; 
auf eine SD Karte.&lt;br /&gt;
Die wird in Mini-Konsole gesteckt und das Gerät dann eingeschaltet.&lt;/p&gt;

&lt;p&gt;Nach dem Booten landet man dann auf dem &lt;a href=&quot;https://retropie.org.uk/&quot;&gt;Retro-PI&lt;/a&gt; 
UI Bildschirm, wo man bereits vorinstallierte Spiele über den Joystick und 
die anderen Steuertasten auswählen und starten kann.&lt;/p&gt;

&lt;p&gt;Von daher also ein Kinderspiel.&lt;/p&gt;

&lt;p&gt;Ich hätte dann noch versucht eine Konsole zu starten um von dort aus das WLAN
einzurichten. Das war extrem mühsam, denn ich konnte zwar über den USB-Port
des Raspberry PI eine Tastatur anstecken, doch die Auflösung des 240 x 240 
Displays wird per Software auf 480 x 480 interpoliert.&lt;/p&gt;

&lt;p&gt;Das bewirkt leider, das die Schriftart der Konsolenanwendung in der Größe 
halbiert wird und man nur noch einen Pixelbrei aus Graustufen sieht, anstatt von 
weißen Buchstaben auf einem schwarzen Hintergrund.&lt;/p&gt;

&lt;p&gt;Doch es gelang mir dennoch, eine WLAN Verbindung einzurichten und dann per
&lt;code&gt;sudo apt-get update&lt;/code&gt; und &lt;code&gt;sudo apt-get upgrade&lt;/code&gt; einige Updates 
herunterzuladen.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Das hätte ich besser nicht tun sollen.&lt;/strong&gt;&lt;br /&gt;
Denn ab dem nächsten Neustart bootete das System nur noch in die Konsole
und nicht mehr in das grafische Retro PI Menü.&lt;/p&gt;

&lt;p&gt;Nun gut, das ist also noch eine offene Baustelle, aber mit dem originalen
Image läuft das Gerät zufriedenstellend und vielleicht lässt sich das
Update-Problem ja noch irgendwie beheben.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/retro-pi-screen.jpg&quot; alt=&quot;RetroPI-Screen&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Das kleine Teil ist echt witzig und ich hatte Freude daran es zusammen zu
bauen.&lt;/p&gt;

&lt;p&gt;Leider werde ich es zum Spielen kaum benutzen können …&lt;br /&gt;
Es mag an meinen alternden Augen liegen, aber auf diesem kleinen Display
erkenne ich leider viel zu wenig, um daran Spielfreuden zu erleben.&lt;/p&gt;

&lt;p&gt;Vielleicht liegt es auch an der Software-Emulation auf 480 x 480 Pixel,
die unnötig Unschärfe erzeugt. Natürlich wird man keine aufwendigen Spiele
darauf genießen können, doch der Gameboy mit seinem 160 x 144 Pixel und der
Gameboy Advanced mit 240 x 160 Pixel ließe sich ohne verkleinernde
Pixelinterpolation darstellen.&lt;br /&gt;
Beim NES und SNES mit 256 x 240 Pixel gibt es bereits Problemchen, was
die Auswahl natürlich einschränkt.&lt;/p&gt;

&lt;p&gt;Aber hey, dieser Schlüsselanhänger ist auch nicht für stundenlanges 
Daddeln gedacht … aber für eine kurze &lt;a href=&quot;https://de.wikipedia.org/wiki/Tetris&quot;&gt;Tetris&lt;/a&gt;
Session zwischendurch ist es wie geschaffen.&lt;/p&gt;

&lt;p&gt;Vielleicht habe ich ja mal Zeit hier ein kleines Tool für WLAN-Sniffing
auf der Konsole umzusetzen … das wär doch mal was ;)&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Frage: Wozu ist ein Betriebsrat da?</title>
   <link href="https://www.opengate.at/blog/2019/12/work-council/"/>
   <published>2019-12-06T12:00:00+01:00</published>
   <updated>2019-12-06T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2019/12/work-council</id>
   <category term="general" />
   <summary type="text">Antwort: Aus Sicht meiner Arbeitswelt, zu gar nichts.
Und das ist schon etwas frustrierend, wenn man davon ausgeht, dass die
offizielle Funktion die “Vertretung der Arbeitnehmer in einem Betrieb ist”.

Doch in den letzten 15 Jahren habe ich noch kein Unternehmen kennenlernen
dürfen, in welchem “meine” Interessen je vertreten wurden.
</summary>
   <content type="html">&lt;p&gt;Antwort: Aus Sicht meiner Arbeitswelt, zu gar nichts.&lt;br /&gt;
Und das ist schon etwas frustrierend, wenn man davon ausgeht, dass die
offizielle Funktion die “Vertretung der Arbeitnehmer in einem Betrieb ist”.&lt;/p&gt;

&lt;p&gt;Doch in den letzten 15 Jahren habe ich noch kein Unternehmen kennenlernen
dürfen, in welchem “meine” Interessen je vertreten wurden.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Eines muss ich natürlich vorausschicken:&lt;br /&gt;
Grundsätzlich halte ich die Besetzung von Vertretungsorganen aller Gruppen in
einem Unternehmen für absolut notwendig und in einer Demokratie auch für 
selbstverständlich.&lt;/p&gt;

&lt;p&gt;Wenn es aber um den IT Bereich geht, wird für mich leider immer wieder 
deutlich, dass diese Institutionen irgendwo in den 70er Jahren des 
letzten Jahrhunderts stehen geblieben sind und daher 
(“Es gilt die Unschuldsvermutung!”) nicht fähig sind, die Herausforderungen
und Bedürfnisse von IT-Mitarbeitern zu erkennen und schon gar nicht diese 
vor anderen Gruppen (wie der Geschäftsführung) zu vertreten.&lt;/p&gt;

&lt;p&gt;Meine Erfahrungen mit “meinen” Betriebsräten beginnen damit, dass sie auf 
Anfragen per &lt;a href=&quot;https://de.wikipedia.org/wiki/E-Mail&quot;&gt;E-Mail&lt;/a&gt; nicht reagieren. 
Anstatt dessen wird bei ihren seltenen inspektorischen Rundgängen immer 
angekündigt, man möge doch einfach persönlich bei Ihnen vorbeischauen, 
was dann natürlich dazu führt, dass sie NIE im Büro sind, wenn man eben mal 
vorbeischauen möchte.&lt;/p&gt;

&lt;p&gt;Da sollte man glauben, dass hochmoderne Kommunikationsformen wie “E-Mail”,
genau das verbessern könnte … aber natürlich nur, wenn der Betriebsrat 
dieses Medium nicht ablehnt.&lt;/p&gt;

&lt;p&gt;Ging es darum die Arbeitssituation zu verbessern, freute ich mich einmal
sogar, dass mit betroffenen Gesichtern abgenickt wurde, dass eine 
suboptimale Büroraumplanung sofort überarbeitet werden sollte.&lt;br /&gt;
Doch das war vor den Arbeiterkammerwahlen, wo es darum ging sich als
Betriebsrat öffentlich und interessiert zu zeigen.&lt;br /&gt;
Die versprochene Unterstützung kam - wie konnte es sonst sein? - natürlich 
nie.&lt;/p&gt;

&lt;p&gt;Und dann kommt ein für mich wichtiges Thema, nämlich die Weiterbildung.&lt;br /&gt;
Da ist es schon schlimm genug, dass meine Arbeitgeber entweder keinen 
Plan haben oder kein Budget bereit stellen wollten, denn wozu sollte man
sich in der IT bzw. der Programmierung weiterbilden?&lt;br /&gt;
Nein, schlimm sind die leeren Gesichter von Betriebsräten, wenn man 
sie nach Weiterbildungsoptionen und -modellen befragt.&lt;/p&gt;

&lt;p&gt;Denn ich habe schon die Erwartungshaltung, dass “meine Vertretung” als 
Arbeitnehmer zumindest weiß, was meine Arbeit ist.&lt;br /&gt;
Doch Fehlanzeige, in Sachen IT sitzt hier zumeist ein beliebiger
“Büromensch” vor mir, der dann auch oft ehrlich zugibt, dass er nicht mehr
tun kann, als ein paar Listen durchzugehen, wo von Kursen für Word Excel
und PowerPoint die Rede ist.&lt;br /&gt;
… und an der Stelle ist dann das Gespräche aus meiner Sicht beendet.&lt;/p&gt;

&lt;p&gt;Also liegt es als Arbeitnehmer alleine bei mir, mir ein Seminar oder
FH Lehrgang irgendwo selbst herauszusuchen um diese dann mit einen
Vorgesetzten zu vereinbaren.&lt;/p&gt;

&lt;p&gt;Das ist ja auch OK, aber wozu es dann noch eine “Arbeitnehmervertretung”
gibt, die mich bei solchen Angelegenheiten unterstützen soll um “das Beste”
für mich rauszuholen, weiß ich offen gesagt nicht.&lt;/p&gt;

&lt;h3 id=&quot;betriebsrat-abschaffen&quot;&gt;Betriebsrat abschaffen?&lt;/h3&gt;

&lt;p&gt;In IT Betrieben: Ja, wieso nicht …&lt;/p&gt;

&lt;p&gt;Aber mal im Ernst:&lt;br /&gt;
Die besten Erfahrungen mit Betriebsräten habe ich vor 15 Jahren bei 
Industriearbeitern gemacht. Die dortigen Personen saßen selbst am 
Gabelstapler und kannten daher den Job und wussten was “ihre Jungs”
brauchten. Da konnte man klar und deutlich sehen, wie sinnvoll es ist,
dass jemand für die Belegschaft mal was beim Chef durchsetzt.&lt;/p&gt;

&lt;p&gt;Doch in der IT sind mir solche Charaktere leider noch nie begegnet.&lt;br /&gt;
&lt;em&gt;Und genau das ist das Problem.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Also &lt;strong&gt;Nein, man soll Betriebsräte nicht abschaffen&lt;/strong&gt;, aber es wäre im 21. 
Jahrhundert mal verdammt notwendig, dass dieser Berufsstand den 
Sprung ins neue Zeitalter schafft und nicht davon ausgeht, dass WIR
Programmierer mit Ochsenkarren Felder pflügen und daher neue 
Winterstiefel brauchen.&lt;/p&gt;

&lt;p&gt;Vielleicht ist es ein Jammern auf “hohem Niveau” bei mir, denn zu meist
geht es den Software-Entwicklern nicht “so” schlecht.&lt;br /&gt;
Dennoch erwarte ich mir von “meiner Arbeitnehmervertretung” ein 
Mindestmaß an “Kompatibilität” für die Herausforderungen in modernen
Arbeitsumfeldern.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Altes CD/DVD Laufwerk zerlegen</title>
   <link href="https://www.opengate.at/blog/2019/12/dvd-disassemble/"/>
   <published>2019-12-01T12:00:00+01:00</published>
   <updated>2019-12-01T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2019/12/dvd-disassemble</id>
   <category term="hardware" /><category term="retro" />
   <summary type="text">Ja, in den letzten 20 Jahren hatte ich so einiges Hardware. Und neben einigen
defekten Netzteilen und Festplatten, habe ich auch einige 
CD- und DVD Laufwerke, welche 
zwar noch “anspringen” aber kein einziges Medium mehr lesen oder beschreiben 
können.

Also wieder was für die Elektroschrottsammlung … oder … wer sehen mal,
was wir da noch rausholen können.
</summary>
   <content type="html">&lt;p&gt;Ja, in den letzten 20 Jahren hatte ich so einiges Hardware. Und neben einigen
defekten Netzteilen und Festplatten, habe ich auch einige 
&lt;a href=&quot;https://de.wikipedia.org/wiki/CD-ROM-Laufwerk&quot;&gt;CD- und DVD Laufwerke&lt;/a&gt;, welche 
zwar noch “anspringen” aber kein einziges Medium mehr lesen oder beschreiben 
können.&lt;/p&gt;

&lt;p&gt;Also wieder was für die Elektroschrottsammlung … oder … wer sehen mal,
was wir da noch rausholen können.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Was kann man zum Basteln von einem alten Laufwerk benutzen?&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Es müsste der eine oder andere &lt;a href=&quot;https://de.wikipedia.org/wiki/Elektromotor&quot;&gt;Elektromotor&lt;/a&gt;
darin verbaut sein.&lt;/li&gt;
  &lt;li&gt;Das Gehäuse könnte man nutzen um etwas anderes daran zu verbauen um es
dann wieder in einem PC einzusetzen&lt;/li&gt;
  &lt;li&gt;Es sind Anschlüsse für Audio, Strom, &lt;a href=&quot;https://de.wikipedia.org/wiki/Serial_ATA&quot;&gt;S-ATA&lt;/a&gt;
oder &lt;a href=&quot;https://en.wikipedia.org/wiki/Parallel_ATA&quot;&gt;IDE (P-ATA)&lt;/a&gt; verbaut, 
die man auslöten könnte.&lt;/li&gt;
  &lt;li&gt;Und vielleicht ist auf den Platinen etwas interessantes drauf.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Machen wir uns also dran, das Ding mal auseinander zu nehmen.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;So sah er aus, einer meiner frühen &lt;a href=&quot;https://de.wikipedia.org/wiki/Brenner_(Hardware)&quot;&gt;DVD Brenner&lt;/a&gt;. 
Vor 15-10 Jahren, also vor den “großen” USB Sticks, waren sie ein Muss 
für die Datensicherung.&lt;br /&gt;
&lt;img src=&quot;/blog/assets/img/dvd-disassemble-1.jpg&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Zum Glück kann man das Laufwerk mit ein paar herausgedrehten Schrauben
und dem Hineindrücken einiger Plastikhaken öffnen.&lt;br /&gt;
&lt;img src=&quot;/blog/assets/img/dvd-disassemble-2.jpg&quot; alt=&quot;Image&quot; /&gt;&lt;/li&gt;
  &lt;li&gt;Hat man die Frontblende erst mal ab, kommt einem ordentlich Dreck entgegen.
Was sich da alles angesammelt hat …&lt;br /&gt;
&lt;img src=&quot;/blog/assets/img/dvd-disassemble-3.jpg&quot; alt=&quot;Image&quot; /&gt;&lt;/li&gt;
  &lt;li&gt;Interessant, dass ein Flachbandkabel fest auf den Platinen verlötet war
(das andere war in einer Klemme eingespannt).
Doch mit etwas Flussmittel und kurzem Kontakt mit dem Lötkolben lösten
es sich und die Platinen konnten getrennt von einander losgeschraubt 
werden.&lt;br /&gt;
&lt;img src=&quot;/blog/assets/img/dvd-disassemble-4.jpg&quot; alt=&quot;Image&quot; /&gt;&lt;/li&gt;
  &lt;li&gt;Unter der Platine für die Frontanschlüsse verbarg sich der gut
brauchbare Motor, der die CD/DVD Lade aus und einziehen konnte.
Ein einfacher Gleichstrommotor, wie ich ihn schon 
&lt;a href=&quot;/blog/2019/06/bike-power/&quot;&gt;früher mal&lt;/a&gt;
wiederverwenden konnte.&lt;br /&gt;
&lt;img src=&quot;/blog/assets/img/dvd-disassemble-5.jpg&quot; alt=&quot;Image&quot; /&gt;&lt;/li&gt;
  &lt;li&gt;Unter der Hauptplatine kommt das Fahrwerk des Lasers zum Vorschein.
Ein Motor, der eine Welle antreibt, die einen Bügel mit dem Laser
hin- und herbewegen kann.&lt;br /&gt;
&lt;img src=&quot;/blog/assets/img/dvd-disassemble-6.jpg&quot; alt=&quot;Image&quot; /&gt;&lt;/li&gt;
  &lt;li&gt;Tja, und so sieht dann der Kern und Hülle eines CD/DVD Laufwerks aus:
&lt;img src=&quot;/blog/assets/img/dvd-disassemble-7.jpg&quot; alt=&quot;Image&quot; /&gt;&lt;/li&gt;
  &lt;li&gt;Drei Motoren kann ich also erbeuten, neben dem Gleichstromteil noch zwei
&lt;a href=&quot;https://de.wikipedia.org/wiki/Schrittmotor&quot;&gt;Schrittmotoren&lt;/a&gt;. Hmm, da 
könnte noch ein schönes Arduino-Projekt daraus werden.
&lt;img src=&quot;/blog/assets/img/dvd-disassemble-8.jpg&quot; alt=&quot;Image&quot; /&gt;&lt;/li&gt;
  &lt;li&gt;Tja, und der Laser … den kann man vermutlich nicht so leicht ansteuern.
Somit wandert er mal in meine Sammelkiste … aber wer weiß, was die 
Zukunft bringt.
&lt;img src=&quot;/blog/assets/img/dvd-disassemble-9.jpg&quot; alt=&quot;Image&quot; /&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;So, das war wieder mal eine nette Abendbeschäftigung.&lt;/p&gt;

&lt;p&gt;Also, defekte Hardware nicht einfach wegwerfen!&lt;br /&gt;
Wäre doch blöd, wenn man heute sein DVD Laufwerk verschrottet und morgen 
wieder einen Motor neu kauft, obwohl so ein Teil aus dem Laufwerk noch 
super funktioniert.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Wann fing das mit dem DMA an?</title>
   <link href="https://www.opengate.at/blog/2019/11/dma-speed/"/>
   <published>2019-11-30T12:00:00+01:00</published>
   <updated>2019-11-30T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2019/11/dma-speed</id>
   <category term="software" /><category term="retro" />
   <summary type="text">Warum dauert die Installation von Windows 2000
in einer modernen VM auf einer SSD trotzdem noch so lange, wo die Daten 
heute schon in 5 Minuten fertig sein müssten?

Ich habe keine Ahnung … aber eine Vermutung.
Denn früher war es mein erster Job nach einer Windows Installation,
DMA zu aktivieren.
</summary>
   <content type="html">&lt;p&gt;Warum dauert die Installation von &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_2000&quot;&gt;Windows 2000&lt;/a&gt;
in einer modernen VM auf einer SSD trotzdem noch so lange, wo die Daten 
heute schon in 5 Minuten fertig sein müssten?&lt;/p&gt;

&lt;p&gt;Ich habe keine Ahnung … aber eine Vermutung.&lt;br /&gt;
Denn früher war es mein erster Job nach einer Windows Installation,
&lt;a href=&quot;https://de.wikipedia.org/wiki/Speicherdirektzugriff&quot;&gt;DMA&lt;/a&gt; zu aktivieren.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Um das Jahr 2000 war man als interessierter Tüftler gerne gefragt, um aus dem 
PC mehr Leistung herauszubekommen.&lt;br /&gt;
Neben einigen Tricks, die man jedes Monat von einer anderen PC-Zeitschrift 
vorgekaut bekam, gab es eine interessante Einstellung für Festplatten und
CD bzw. DVD Laufwerke, die bei manchen Systemen wahre Wunder auslöste.&lt;/p&gt;

&lt;p&gt;Ich meine die “Direct Memory Access” Option, kurz D.M.A. für Festplatten und
CD Laufwerke.&lt;/p&gt;

&lt;p&gt;Wenn ein Programm unter DOS Daten von einem Datenträger lesen oder schreiben 
wollte, war der Ablauf sehr linear und synchron.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Programm nutzt eine Datei-API&lt;/li&gt;
  &lt;li&gt;DOS (INT 21h) übersetzte das Dateisystem in Hardware-Aufrufe&lt;/li&gt;
  &lt;li&gt;Der BIOS-Code (INT 13h) las Sektor für Sektor und kopierte die Bytes in 
kleine Datenpuffer&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Bei jedem dieser Schritte war die CPU voll ausgelastet.&lt;/p&gt;

&lt;p&gt;Und dann kam präemptives Multitasking womit Threads es möglich machten,
dass sich mehrere Prozesse die CPU-Leistung aufteilten.&lt;br /&gt;
Doch nach dem alten Schema bedeutete jede IO-Operation auf den Datenträgern,
dass keine CPU-Zeit für die Prozesse da war, weil die CPU voll und ganz mit
IO und Bytekopierereien beschäftigt war.&lt;/p&gt;

&lt;p&gt;Und dann kam DMA. … naja, eigentlich gab es das Konzept schon recht lange,
aber der PC lernte es erst recht spät und die Windows Treiber noch später.&lt;/p&gt;

&lt;p&gt;Die Idee: Eine Hardware-Komponente darf direkt ins RAM schreiben, hat also 
eigene Datenleitungen und die CPU sagt ihr lediglich, woher sie Daten lesen
und wohin sie diese speichern soll.&lt;br /&gt;
Und schon ist die CPU kein Flaschenhals mehr, der tausende Taktzyklen blockiert
ist, sondern gibt nur noch Kommandos weiter, die dann von “untergebenen”
Mikrocontrollerschaltungen erledigt werden.&lt;/p&gt;

&lt;p&gt;Und die Welt wäre so schön, wenn das auch alles gleich von Anfang an 
funktioniert hätte …&lt;br /&gt;
Doch leider war die Unterstützung von DMA für Festplatten (oder allgemeiner
&lt;a href=&quot;https://de.wikipedia.org/wiki/ATA/ATAPI&quot;&gt;IDE&lt;/a&gt;-Geräten) bei einigen wenigen 
Chip-Modellen fehlerhaft.&lt;/p&gt;

&lt;p&gt;Das wiederum rief die OS-Hersteller auf den Plan, die diese Technologie zwar
implementierten aber deaktiviert ließen, zumindest während der Installation bis
sie von am Ende installierten speziellen Treibersetups für den eigenen PC
aktiviert wurden.&lt;/p&gt;

&lt;p&gt;Tja, und so hatte ich bei vielen Besuchen von Freunden, Verwandten und 
Bekannten die Aufgabe, ihre PCs durch die Aktivierung der DMA-Funktion auf
Vordermann zu bringen.&lt;/p&gt;

&lt;p&gt;Tatsächlich kamen da so Fragen wie:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Du, der PC geht eigentlich, aber wir können keine Videos ansehen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ja klar, Videos brauchen viele Daten auf einmal und ohne DMA schaffte es auch 
eine schnelle CPU nicht, die nötigen Bytes einzeln von A nach B zu übertragen.&lt;/p&gt;

&lt;p&gt;Sobald also im entsprechenden Reiter des “Primären oder Sekundären IDE 
Controllers” der DMA Modus aktiviert war, durfte man sich als Wunderheiler 
feiern lassen, der das Ansehen von Filmen am PC möglich gemacht hatte.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/win2k-dma.png&quot; alt=&quot;Windows DMA&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;… ach, das war schon auch eine schöne Zeit.&lt;br /&gt;
Nicht wegen den schlechten Hardware/Treibergegebenheiten, sondern weil man noch
mit einfachsten Handgriffen “was erreichen” konnte.&lt;/p&gt;

&lt;p&gt;Das wurde in den folgenden Jahren bedeutungslos und seitdem Updates automatisch
über das Internet eingespielt werden, sollte es gar nicht erst möglich sein,
dass ein Windows im uralt-Modus Daten herumschiebt. Da kann man nur noch 5% 
Leistung mit ein paar Registry-Einstellungen verbessern, und nicht wie damals
50-100% “gefühlten” Geschwindigkeitsgewinn herbeizaubern.&lt;/p&gt;

&lt;p&gt;In sofern vermisse ich diese Tage als Wunderheiler …
… und bin trotzdem froh, dass man sich mit so einem Blödsinn heutzutage nicht
mehr beschäftigen muss.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Ein Pokemon mit Schwert</title>
   <link href="https://www.opengate.at/blog/2019/11/pokemon-sword/"/>
   <published>2019-11-24T12:00:00+01:00</published>
   <updated>2019-11-24T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2019/11/pokemon-sword</id>
   <category term="entertainment" /><category term="retro" />
   <summary type="text">Schon ist die erste Woche seit dem 
Pokemon Schwert/Schild
Release wieder um, und das bedeutet, dass ich den Hauptteil durchgespielt 
habe.

Der Umstieg auf die Nintendo Switch
ist ja eigentlich schon vor einem Jahr mit 
Pokemon Let’s go Pikachu/Evoli
erfolgt, doch dabei handelte es sich nicht um einen Teil der Hauptreihe.

Jetzt sind wir also mit knapp 900 Pokemon in der 8. Generation angelangt.
</summary>
   <content type="html">&lt;p&gt;Schon ist die erste Woche seit dem 
&lt;a href=&quot;http://www.pokewiki.de/Pok%C3%A9mon_Schwert_und_Schild&quot;&gt;Pokemon Schwert/Schild&lt;/a&gt;
Release wieder um, und das bedeutet, dass ich den Hauptteil durchgespielt 
habe.&lt;/p&gt;

&lt;p&gt;Der Umstieg auf die &lt;a href=&quot;https://de.wikipedia.org/wiki/Nintendo_Switch&quot;&gt;Nintendo Switch&lt;/a&gt;
ist ja eigentlich schon vor einem Jahr mit 
&lt;a href=&quot;http://pokewiki.de/Pok%C3%A9mon:_Let%E2%80%99s_Go,_Pikachu!_und_Let%E2%80%99s_Go,_Evoli!&quot;&gt;Pokemon Let’s go Pikachu/Evoli&lt;/a&gt;
erfolgt, doch dabei handelte es sich nicht um einen Teil der Hauptreihe.&lt;/p&gt;

&lt;p&gt;Jetzt sind wir also mit knapp 900 Pokemon in der 8. Generation angelangt.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;damals-als-&quot;&gt;Damals als …&lt;/h3&gt;

&lt;p&gt;Es ist ziemlich genau 20 Jahre her, dass mir Pokemon “zugetragen” wurde.
Meinen Nintendo Gameboy hatte ich da schon lange verkauft, und so entdeckte
ich diese Spielereihe per Emulator, konkret über 
&lt;a href=&quot;http://gbdev.gg8.se/wiki/articles/No$gmb&quot;&gt;NO$GMB&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Witzig daran war eigentlich, dass ich mit Assembler arbeiten wollte und 
“versehentlich” ein Buch zu 
&lt;a href=&quot;/blog/2019/12/assembler/&quot;&gt;Z80&lt;/a&gt; gekauft hatte.&lt;br /&gt;
Hätte mir doch damals bloß jemand gesagt, dass “Assembler” für jeden
Prozessor anders aussieht.&lt;br /&gt;
Na jedenfalls blieb ich dann recht schnell bei dem Spiel mit den 
150/151 Kreaturen kleben, anstatt auf der Hardware wirklich etwas 
sinnvolles zu programmieren.&lt;/p&gt;

&lt;p&gt;Es dauerte dann allerdings weitere 10 Jahre (also so um 2010 herum), bis ich 
mir dann wieder eine echte Nintendo Hardware leistete. Die 2. und 3. Pokemon
Generation hatte ich bis dahin ebenso über Emulatoren nebenbei mal 
durchgenommen.&lt;/p&gt;

&lt;p&gt;Mit einem gebrauchten Nintendo DS vom Gamestop und dann mit dem damals neuen
&lt;a href=&quot;https://de.wikipedia.org/wiki/Nintendo_3DS&quot;&gt;3DS&lt;/a&gt; holte ich die 4. Generation
und das Remake der 2. Generation nach und konnte die 5. Generation dann live
miterleben.&lt;br /&gt;
Nicht ganz unbeteiligt an meiner neu entdeckten Pokemon-Liebe waren auch 
diverse Kontakte in diese Szene.&lt;br /&gt;
… da fühlt man sich wieder jung an “die gute alte Zeit” erinnert, wenn 
gleich ich eine solche Zeit am Gameboy ja nie miterlebt hatte.&lt;/p&gt;

&lt;p&gt;Ein besonderes Highlight war dann die 6. Generation (X und Y) im Jahr 2013.
Denn mit dem neuen Online-Feature, wo man live mit anderen kämpfen und 
tauschen konnte und der Tatsache, dass anfangs noch keine gehackten Pokemon
im Netz waren, machte das “Dabeisein” wirklich viel Spaß.&lt;br /&gt;
Bis heute ist wohl meine Pokemon-X Edition das Spiel mit den meisten 
Spielstunden.&lt;/p&gt;

&lt;p&gt;Als dann 2016/2017 die 7. Generation aufkam, war es zwar auch ganz nett,
aber wirklich beeindruckt war ich davon nicht mehr. Vor allem fehlte mir
ein Remake der 4. Generation, über das spekuliert wurde, denn Nintendo
bringt auf jeder neuen Konsole gerne Remakes von älteren Spielen heraus,
deren Hardware nicht mehr erhältlich ist.&lt;/p&gt;

&lt;h3 id=&quot;schwert-und-schild&quot;&gt;Schwert und Schild&lt;/h3&gt;

&lt;p&gt;Und nun starten wir mit Pokemon Schwert und Pokemon Schild in die 8.
Generation auf der Nintendo Switch. Und das bedeutet auch, dass mein lieber
3DS langsam aber sicher dauerhaft in den Kasten wandern wird.&lt;br /&gt;
Vorbei sind die Zeiten, wo man den 3DS im Rucksack hatte und sich am Abend
über wenigstens einen Street-Pass-Kontakt freuen durfte.&lt;/p&gt;

&lt;p&gt;Das geniale an der Switch ist (und da spricht vielleicht mein nicht mehr
ganz so jugendliches Alter aus mir), dass sie einen schönen großen Screen
hat. Für die Jugend sind 5 cm Displays ja kein Problem, doch ich merke 
langsam doch, dass kleine Anzeigen schwerer zu entziffern werden.&lt;/p&gt;

&lt;p&gt;Die Grafik ist natürlich super und nochmals verbessert im Verhältnis zu
Pokemon Let’s Go Pikachu/Evoli. Einzig in der Naturzone, wo man auch alle
anderen Spieler, die online sind, herumlaufen sieht, gibt es Ruckler und
manchmal grafische Artefakte.&lt;br /&gt;
Im Großen und Ganzen muss man aber schon beeindruckt sein, wie sich 
Pokemon von 160 x 144 auf die heutigen 1280 x 720 Pixel entwickelt hat.&lt;/p&gt;

&lt;p&gt;Besonders die Animation in Kämpfen “passen” jetzt besser zusammen und die
Hintergründe haben eine herausstechende Klarheit und fügen sich gut in den
Ort der Handlung und dessen Wetter ein.&lt;/p&gt;

&lt;p&gt;Dass unser Held im Spiel sich seine Kleidung selbst zusammenstellen kann,
gab es ja schon in der 6. Generation. Doch jetzt können wir auch den 
Aufdruck von Trikot-Nummern am T-Shirt beeinflussen.&lt;/p&gt;

&lt;p&gt;Die Story ist … naja … Pokemon eben. 8 Arenaleiter gilt es zu besiegen
um am Ende den amtierenden Champ zu besiegen und abzulösen. Parallel dazu
darf man wie immer der Legende von besonderen Pokemon hinterherforschen,
die am Ende immer entweder die Welt zerstören oder retten sollen.&lt;/p&gt;

&lt;p&gt;So ist es auch diesmal geschehen und nun, da ich Champ der Galar-Region
bin, startet die After-Story … mal sehen was es noch zu entdecken gibt.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Für einen “alten” Pokemon-Fan sind Schwert/Schild eine schöner Zeitvertreib.
Natürlich darf man bei einem Spiel für Kinder keine komplexen Stories 
oder knifflige Rätsel erwarten.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/pokemon-sword.jpg&quot; alt=&quot;Pokemon Sword&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Ein großer Nachteil sind für mich (wie auch schon seit der 6. Generation)
die Abhängigkeiten zum Internet. Denn was heute toll funktioniert wird
(und das ist “vorprogrammiert”) in ein paar Jahren abgedreht.&lt;br /&gt;
So geschehen beim Trading-System der 4. und 5. Generation.&lt;/p&gt;

&lt;p&gt;Während man von der 3. zur 4. und zur 5. Generation Pokemon auf seinem
Gerät übertragen konnte (ohne Online-Dienst), klappt das seit der&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;Generation nur noch gegen Einzahlung auf einem Internet-Dienst.
Und das ist ärgerlich, man stelle sich vor, man könnte sein Auto
nach 5 Jahren nicht mehr betanken bzw. müsste einen Spezialdienst 
bezahlen um den Tankdeckel zu öffnen.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Aber davon abgesehen mag ich die neue Generation und vor allem ihre
Grafik.&lt;br /&gt;
Den Online-Dienst, über den ich mich gerne auslasse, wird es erst
ab Anfang 2020 geben … also warten wir mal ab, was es da noch
zu kritisieren gibt.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Ein Musiker erdichtete sich vor 10 Jahren einen Text, der heute auch
ebenso noch passt:&lt;/p&gt;

&lt;iframe width=&quot;640&quot; height=&quot;360&quot; src=&quot;/blog/redirect.html?https%3A%2F%2Fwww.youtube-nocookie.com%2Fembed%2FdZpiqfMMtaI&quot; frameborder=&quot;1&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;

&lt;iframe width=&quot;640&quot; height=&quot;360&quot; src=&quot;/blog/redirect.html?https%3A%2F%2Fwww.youtube-nocookie.com%2Fembed%2F17ZjvFliR0Q&quot; frameborder=&quot;1&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
</content>
 </entry>
 
 <entry>
   <title>LiPo Akku Kurzschluss</title>
   <link href="https://www.opengate.at/blog/2019/11/lipo/"/>
   <published>2019-11-23T12:00:00+01:00</published>
   <updated>2019-11-23T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2019/11/lipo</id>
   <category term="hardware" />
   <summary type="text">Es lief wie in Zeitlupe ab.

Ich sah noch, wie sich die beiden losen Polkabel aufeinander zubewegten, 
mein Blick wurde starr, ein kleiner Funke flog …

… und mein 1400mA Lithium Polymer Akku
war tot.
</summary>
   <content type="html">&lt;p&gt;Es lief wie in Zeitlupe ab.&lt;/p&gt;

&lt;p&gt;Ich sah noch, wie sich die beiden losen Polkabel aufeinander zubewegten, 
mein Blick wurde starr, ein kleiner Funke flog …&lt;/p&gt;

&lt;p&gt;… und mein 1400mA &lt;a href=&quot;https://de.wikipedia.org/wiki/Lithium-Polymer-Akkumulator&quot;&gt;Lithium Polymer Akku&lt;/a&gt;
war tot.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Ja, ich weiß, man soll Akkus nicht kurzschließen. Und wenn man sie verkabelt
sollte man aufpassen, dass sich die beiden Polkabel nicht versehentlich
berühren. … Mea Culpa!&lt;/p&gt;

&lt;p&gt;Bei den üblichen Lithium Ionen Akkus der Klasse 18650 wäre durch die beiden
Drähte für die kurze Zeit ein ordentlicher Strom geflossen, der die Kabel
schnell erhitzt hätte und eventuell auch die Isolierung aufgeschmolzen hätte.&lt;/p&gt;

&lt;p&gt;Doch bei solchen unter 1-Sekunden Kontakten, wäre weiter nicht viel passiert.
Und ja, ich weiß das, weil mir das auch schon mal passiert ist. Trotzdem 
sollte man verdammt aufpassen, denn sollte der Akku irgendwo brechen oder 
etwas aufschmelzen, darf sich die Feuerwehr darum kümmern.&lt;/p&gt;

&lt;p&gt;Aber bei meinem flachen LiPo-Pack gab es einen kurzen Funken und danach
führten die ausgehenden Pole keinen Strom mehr.&lt;br /&gt;
Warum eigentlich?&lt;/p&gt;

&lt;p&gt;Tja, kluge Leute bauten eine kleine Schutzschaltungen zwischen den echten 
Polen des Akkus und die hinausgeführten Anschlusskabel ein. Und als ich diese
Drähte durch längere ersetzen wollte und den Kurzschluss verursachte, brannte diese
Schaltung offenbar durch.&lt;br /&gt;
Eigentlich gut, so konnte kein weitere Schaden entstehen.&lt;/p&gt;

&lt;p&gt;Also ab damit in den Sondermüll …&lt;br /&gt;
Nein! Warum? Das muss man doch irgendwie richten können …&lt;/p&gt;

&lt;h3 id=&quot;lipo-schutz-ersetzen&quot;&gt;LiPo Schutz ersetzen&lt;/h3&gt;

&lt;p&gt;Also wird die Plastikverpackung um den Akku vorsichtig weggeschnitten und der
eine oder andere Isolationsstreifen entfernt, und schon kommt der kleine
tote Chip zum Vorschein.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/lipo-protection.jpg&quot; alt=&quot;LiPo-Protection&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Die “echten” Pole des Akkus waren links und rechts einfach mit der Platine
verlötet und so genügten paar Sekunden Kontakt mit meinem Lötkolben um 
den Chip vom Akku zu trennen.&lt;/p&gt;

&lt;p&gt;Mein &lt;a href=&quot;https://de.wikipedia.org/wiki/Multimeter&quot;&gt;Multimeter&lt;/a&gt; zeigte dann brav 
3.9 Volt zwischen den Polen an, was somit bedeutete: Der Akku ist voll und ganz OK.&lt;br /&gt;
Das bedeutet, man könnte sofort ein Gerät an ihn anhängen. Doch ohne den 
Protektor-Chip wäre eine Tiefentladung oder ein Kurzschluss mit übleren
Folgen möglich.&lt;/p&gt;

&lt;p&gt;Zum Glück gibt es für wenige Cent (oder ein paar Euro für 10 Stück) diese
Lithium-Ionen Ladechips im Handel. Und nachdem Lithium-Ionen Batterien
und Lithium-Polymer-Packs quasi gleich aufgebaut sind (bei gleicher 
Ausgangsspannung), dachte ich mir, ich schließe so einen Teil einfach
zwischen Akku und Verbraucher.&lt;/p&gt;

&lt;p&gt;Die neue Platine wurde mit einem Doppelklebestreifen auf das Akku-Pack
geklebt, nachdem + und - Pol des Akkus mit zwei kurzen Drähten mit den
entsprechenden Pins (B+ und B-) verlötet wurden.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/lipo-charger.jpg&quot; alt=&quot;LiPo-Charger&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Und das geile dran: Es ist ein USB Anschluss zum Aufladen integriert,
wie auch die Möglichkeit vorgesehen ist, direkt zwei Ladepole mit dem Chip
zu verbinden.&lt;/p&gt;

&lt;p&gt;Egal ob man nun per USB vom Netzstrom, oder von der Solarzelle aus laden
möchte, beides geht jetzt “direkt” auf dem Akku selbst.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/lipo-enhanced.jpg&quot; alt=&quot;LiPo-Pack-Enhanced&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;wieder-ein-stück-gerettet&quot;&gt;Wieder ein Stück gerettet&lt;/h3&gt;

&lt;p&gt;Yay! Und genau das liebe ich so an unserer Zeit.
In 15-30 Minuten hat man ein defektes Teil mit einfachen Mitteln wieder
einsatztauglich gemacht.&lt;/p&gt;

&lt;p&gt;Ich möchte nicht wissen, wie viele funktionierende Akkus mit defektem Chip 
in den letzten Jahren im Müll gelandet sind und hoffe, dass wir nicht nur
bessere Recycling-Möglichkeiten für solche Fälle bereitstellen, sondern
dass jeder Bürger selbst in die Lage versetzt wird, “sich zu helfen”.&lt;/p&gt;

&lt;p&gt;Das war doch mit den Computern vor 25 Jahren auch so.&lt;br /&gt;
Niemand traute sich ein Betriebssystem zu installieren, weil man keine
Erfahrung hatte und sich fürchtete etwas kaputt zu machen.&lt;br /&gt;
Heute steckt man einen USB Stick an, klickt 5 mal auf “Weiter” und alles 
läuft.&lt;/p&gt;

&lt;p&gt;Und wieder haben wir ein Beispiel dafür, dass nicht früher sondern
heute alles besser ist!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Schuhkarton für Weihnachten</title>
   <link href="https://www.opengate.at/blog/2019/11/shoe-box/"/>
   <published>2019-11-17T12:00:00+01:00</published>
   <updated>2019-11-17T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2019/11/shoe-box</id>
   <category term="general" />
   <summary type="text">Im ersten Harry-Potter Film
beschwerte sich Cousin Dudley lautstark über das Unrecht an seinem Geburtstag 
NUR 36 Geschenke bekommen zu haben. Schließlich waren es im Vorjahr 37.

Nun, die Zahl mag vielleicht übertrieben sein, aber kennen wir nicht alle
mindestens eine Szene, wo sich Beschenkte darüber beschweren, dass sie zu
gering beschenkt wurden?

Und dann gibt es - wie ich erfahren habe - in meinem Heimatbezirk eine stille 
Zahl von Kindern, die gar keine Geschenke bekommen …
</summary>
   <content type="html">&lt;p&gt;Im ersten &lt;a href=&quot;https://de.wikipedia.org/wiki/Harry_Potter_und_der_Stein_der_Weisen_(Film)&quot;&gt;Harry-Potter Film&lt;/a&gt;
beschwerte sich Cousin Dudley lautstark über das Unrecht an seinem Geburtstag 
NUR 36 Geschenke bekommen zu haben. Schließlich waren es im Vorjahr 37.&lt;/p&gt;

&lt;p&gt;Nun, die Zahl mag vielleicht übertrieben sein, aber kennen wir nicht alle
mindestens eine Szene, wo sich Beschenkte darüber beschweren, dass sie zu
gering beschenkt wurden?&lt;/p&gt;

&lt;p&gt;Und dann gibt es - wie ich erfahren habe - in meinem Heimatbezirk eine stille 
Zahl von Kindern, die gar keine Geschenke bekommen …
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Als Sohn einer alleinerziehenden Mutter bekommt man schnell das Attribut 
zugeschrieben “aus sozial schwachen Verhältnissen” zu stammen.&lt;/p&gt;

&lt;p&gt;So habe ich es allerdings nie erlebt. Im Gegenteil. Es gab in meiner Kindheit
jedes Jahr einen Weihnachtsbaum und es lagen IMMER mehr als ein Päckchen mit
meinem Namen darunter.&lt;/p&gt;

&lt;p&gt;Wie anstrengend das damals für Mutter gewesen sein mag, kann ich mir heute
“zum Glück” nicht vorstellen, denn es stimmte schon, viel Geld war nicht da.
Trotzdem reichte es - auch Dank Mutters vorausschauender Handhabung - dass
zu jedem Anlass auch Geschenke dabei waren.&lt;/p&gt;

&lt;p&gt;Und ich habe damals ganz bestimmt nicht die nötige Dankbarkeit an den Tag
gebracht, weil ich gar nicht bemerkte habe, dass mir NICHTS gefehlt hat.
Deshalb sollte ich es heute nochmal tun:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Danke, Mama!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;hr /&gt;

&lt;p&gt;Und deshalb erscheint es mir unvorstellbar, dass in unserer Gesellschaft 
Menschen leben, denen es nicht so gut geht wie mir damals. Wenn Elternteile
versterben oder durch Unfälle arbeitsunfähig werden, wenn sie vor Krieg und
Zerstörung geflohen sind, dann wird der letzte Cent in Socken oder ein
T-Shirt investiert.&lt;br /&gt;
… für den Luxus eines Spielzeugs am Weihnachtsabend bleibt dann leider 
nichts übrig.&lt;/p&gt;

&lt;p&gt;Um so mehr freut es mich daher, dass in Wien einige Hilfsorganisationen dazu
aufrufen, Kindern dennoch ein schönes Fest zu bereiten.&lt;br /&gt;
Schließlich ist es nicht besonders schön, wenn alle im Kindergarten oder der
Schulklasse erzählen, was sie alles bekommen haben, und man selbst leer 
ausgegangen ist und dann beschämt am Gespräch nicht teilnehmen kann.&lt;/p&gt;

&lt;p&gt;Und eine solche schöne Aktion dieser Art heißt ganz banal 
&lt;em&gt;“Schuhkarton-Aktion”&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Sozialarbeiter befragen dabei eben solche Familien, was sich die Kinder 
wünschen würden und daraus erstellte Geschenkelisten werden dann von 
großherzigen Vereinen “abgearbeitet”.&lt;br /&gt;
Aus direkten Spendengeldern oder den Einnahmen von Flohmärkten mit 
gespendeten Artikeln werden die Geschenke dann gekauft und in einfachen 
Schuhkartons verpackt.&lt;br /&gt;
Das besondere an den Schuhkartons ist vor allem deren Verschönerung mit 
Geschenkpapier, woran die Vereinsmitglieder mit Herzensliebe basteln.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Es freut mich ehrlich sehr zu sehen, dass wir auch in der Großstadt solche 
Aktionen haben, wo sich die Menschen gegenseitig helfen.&lt;br /&gt;
Denn selbstverständlich ist so etwas nicht.&lt;/p&gt;

&lt;p&gt;Traurig macht mich daran leider, wenn ich Dinge lese wie:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Junge, 12 Jahre, hätte gerne neue Federmappe&lt;/li&gt;
  &lt;li&gt;Mädchen, 14 Jahre, irgend etwas zum Anziehen, Größe X&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Wow, der wichtigste Wunsch von diesen Kindern sind Schulsachen oder Kleidung,
und nicht das “bloody Action-Pack Delux” für die neue 1000 Euro Konsole.&lt;/p&gt;

&lt;p&gt;Da denke ich mir, dass ich eigentlich wohlstandsverwahrlost bin, wenn ich so
dasitze und überlege, was ich mir denn sonst noch alles kaufen könnte…&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Liebe Freunde und Kollegen.&lt;/p&gt;

  &lt;p&gt;Vielleicht habt ihr das eine oder andere Geldscheinchen in eurer
Börse, dem ihr einen Sinn geben wollt.
Dann nehmt es bitte heraus und gebt es einer solchen Aktion.
Und ihr werdet sehen, das Scheinchen wird euch nicht fehlen,
doch dafür einer anderen Familie eine Freude machen,
die fehlen würde, wäre das Scheinchen nicht auf Wanderschaft gegangen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Und einen ganz besonderen Dank muss ich den Betreibern solcher Aktionen
ausrichten. Jenen Leuten, die in ihrer Freizeit zusammenkommen, 
Geschenke kaufen und dann schön verpacken.&lt;/p&gt;

&lt;p&gt;Diesen guten Seelen, die an “fremde” Kinder denken und ihnen helfen,
gilt mein tiefer Respekt.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Protobuf im Stream</title>
   <link href="https://www.opengate.at/blog/2019/11/protobuf/"/>
   <published>2019-11-16T12:00:00+01:00</published>
   <updated>2019-11-16T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2019/11/protobuf</id>
   <category term="devel" />
   <summary type="text">Wenn man im Zuge der Arbeit schon mit Google’s Protobuf
in Berührung kommt, dann verdient diese Software auch eine etwas genauere 
Betrachtung.

… besonders, wenn es darum geht diverse Problemchen in der 
C++ Implementierung zu kritisieren ;)
</summary>
   <content type="html">&lt;p&gt;Wenn man im Zuge der Arbeit schon mit Google’s &lt;a href=&quot;https://de.wikipedia.org/wiki/Protocol_Buffers&quot;&gt;Protobuf&lt;/a&gt;
in Berührung kommt, dann verdient diese Software auch eine etwas genauere 
Betrachtung.&lt;/p&gt;

&lt;p&gt;… besonders, wenn es darum geht diverse Problemchen in der 
&lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B&quot;&gt;C++&lt;/a&gt; Implementierung zu kritisieren ;)
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Wenn Datenobjekte über das Netz fließen sollen, stellen sich sich folgende
Fragen:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Wie werden Datentypen in Bytestreams übersetzt?&lt;/li&gt;
  &lt;li&gt;Wie werden Zeichen so kodiert, dass sie eindeutig sind&lt;/li&gt;
  &lt;li&gt;Wie wird Speicherplatz gespart?&lt;/li&gt;
  &lt;li&gt;Wie soll der Code dazu aussehen&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Oder vereinfacht gesagt:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Wie &lt;a href=&quot;https://de.wikipedia.org/wiki/Serialisierung&quot;&gt;serialisieren&lt;/a&gt;
und deserialisieren wir unsere Daten?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;protobuf&quot;&gt;Protobuf&lt;/h3&gt;

&lt;p&gt;Google hat hierfür seine Hausmarke “Protobuf” der Öffentlichkeit zugänglich
gemacht, und dieses Framework soll Daten in Objekten zwischen Plattformen
und auch zwischen unterschiedlichen Programmiersprachen über das Netzwerk
(oder andere Datenströme) austauschen können.&lt;/p&gt;

&lt;p&gt;Protobuf ist binär und besonders auf’s Platzsparen optimiert.
Ein “leeres” Objekt (was bedeutet, alle seine Unterelemente entsprechen einem
vorbestimmten Standardwert) wird genau in Null Bytes übersetzt.&lt;/p&gt;

&lt;h3 id=&quot;code-generator&quot;&gt;Code Generator&lt;/h3&gt;

&lt;p&gt;Eine wichtige Eigenschaft der Technologie ist, dass Protobuf Objekte in einer 
Art Interface-Metasprache definiert werden und am Ende durch einen Generator
alle Quellcodes automatisch generiert werden.&lt;/p&gt;

&lt;p&gt;Das hat den großen Vorteil, dass ein Datenobjekt automatisch in allen 
unterstützten Programmiersprachen generiert wird, darunter C++, 
&lt;a href=&quot;https://de.wikipedia.org/wiki/C-Sharp&quot;&gt;C#&lt;/a&gt;, 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Java_(Programmiersprache)&quot;&gt;Java&lt;/a&gt; oder
&lt;a href=&quot;https://de.wikipedia.org/wiki/Python_%28Programmiersprache%29&quot;&gt;Python&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Wir definieren also eine “.proto” Textdatei, z.B. mit dem Inhalt&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;syntax = &amp;quot;proto3&amp;quot;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;message SearchRequest {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  string query = 1;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  int32 page_number = 2;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;  int32 result_per_page = 3;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;und lassen daraus Quellcodes für die Zielsprache generieren, wo wir ein Objekt
&lt;code&gt;SearchRequest&lt;/code&gt; erhalten, das die Felder &lt;code&gt;query&lt;/code&gt;, &lt;code&gt;page_number&lt;/code&gt; und 
&lt;code&gt;result_per_page&lt;/code&gt; enthält … und zusätzlich noch Methoden zu dessen 
Serialisierung und Deserialisierung.&lt;/p&gt;

&lt;h3 id=&quot;serialisierung&quot;&gt;Serialisierung&lt;/h3&gt;

&lt;p&gt;Ein Vorteil und gleichzeitig Nachteil ist das Fehlen von genauen 
Typeninformationen im serialisierten Byteblock. Damit wird nur sehr
wenig Overhead produziert, doch es sind auch Doppeldeutigkeiten möglich.&lt;/p&gt;

&lt;p&gt;Das makanteste Beispiel ist, dass viele Objekte sich als “leerer” Byteblock 
darstellen, wenn ihr Inhalt dem “Default-Zustand” des Objektes gleicht.&lt;br /&gt;
Besteht ein Objekt aus einem String, einem Integer und einem Boolean,
wovon der String leer ist, der Integer auf &lt;code&gt;0&lt;/code&gt; gesetzt und der Boolean &lt;code&gt;false&lt;/code&gt;
lautet, dann wird das Objekt als “0-Byte” Datenblock serialisiert.&lt;/p&gt;

&lt;p&gt;Das bedeutet auch umgekehrt, dass aus einem 0-Byte Datenblock jedes beliebige
Objekt in seinem Default-Zustand deserialisiert werden kann.&lt;/p&gt;

&lt;p&gt;Wenn also mehrere Protobuf Objekte in einem Nachrichtenprotokoll gekapselt 
sind, muss darauf geachtet werden, dass jedes Objekt sauber vom nachfolgenden
getrennt wird.&lt;/p&gt;

&lt;h3 id=&quot;streaming&quot;&gt;Streaming&lt;/h3&gt;

&lt;p&gt;In der Firma hatten wir neulich die Aufgabe, mehrere Protobuf Objekte 
hintereinander in einen Stream zu schreiben und dieser Stream sollte am 
andere Ende wieder in Objekte deserialisiert werden.&lt;/p&gt;

&lt;p&gt;Tja … wie macht man das?&lt;/p&gt;

&lt;p&gt;In C# oder Java Implementierungen gibt es dafür Methoden mit dem Namen
&lt;code&gt;parseDelimitedFrom&lt;/code&gt; und &lt;code&gt;writeDelimitedTo&lt;/code&gt;. Diese schreiben zuerst die 
Länge des nachfolgenden Objektes in einen Puffer, gefolgt vom serialisierten
Datenblock.&lt;br /&gt;
Ein “leeres” Objekt bestünde dann genau aus einer “0” für die Länge und sonst
eben nichts mehr. Größere Objekte hätten dann entsprechend eine serialisierte
Länge als Präfix vor den eigentlichen Daten.&lt;/p&gt;

&lt;p&gt;Doch in der C++ Implementierung von Protobuf fehlen diese Methoden leider.&lt;/p&gt;

&lt;p&gt;Zum Glück schrieb einer der Mitentwickler von Protobuf die simple Lösung in
einem &lt;a href=&quot;http://stackoverflow.com/questions/2340730/are-there-c-equivalents-for-the-protocol-buffers-delimited-i-o-functions-in-ja/22927149#22927149&quot;&gt;Stackoverflow-Posting&lt;/a&gt;,
die in etwa so aussieht:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Serialisierung:
    &lt;ul&gt;
      &lt;li&gt;Man erstellt einen &lt;code&gt;google::protobuf::io::ZeroCopyOutputStream&lt;/code&gt; von 
seinem eigenen IO-Stream (wie. z.B. &lt;code&gt;std::stringstream&lt;/code&gt;)&lt;/li&gt;
      &lt;li&gt;Nun instanziiert man einen &lt;code&gt;google::protobuf::io::CodedOutputStream&lt;/code&gt; als
Wrapper vom &lt;code&gt;ZeroCopyOutputStream&lt;/code&gt;.&lt;/li&gt;
      &lt;li&gt;Jetzt holt man sich die Länge des Objekts in seiner serialisierten Form
mit &lt;code&gt;int msg_size = proto_message.ByteSize();&lt;/code&gt; und schreibt sie mit 
&lt;code&gt;coded_output.WriteVariant32(msg_size);&lt;/code&gt; in den Puffer.&lt;/li&gt;
      &lt;li&gt;Am Ende schreibt man die Objekt-Daten mit 
&lt;code&gt;msg.SerializeToCodedStream(coded_output);&lt;/code&gt; ebenso in den
Stream.&lt;/li&gt;
      &lt;li&gt;Nach der Freigabe der beiden Stream-Wrapper, sollte &lt;code&gt;std::stringstream&lt;/code&gt;
das gleich beinhalten, was &lt;code&gt;writeDelimitedTo&lt;/code&gt; in anderen Sprachen 
schreiben würde.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Deserialisierung:
    &lt;ul&gt;
      &lt;li&gt;Man erstellt z.B. einen &lt;code&gt;google::protobuf::io::ZeroCopyInputStream&lt;/code&gt; als 
Wrapper aus einem &lt;code&gt;std::istream&lt;/code&gt; oder gerne auch einen &lt;code&gt;ArrayInputStream&lt;/code&gt; 
aus einem existierenden C-array bzw. &lt;code&gt;std::vector&lt;/code&gt;.&lt;/li&gt;
      &lt;li&gt;Nun kapselt man den Wrapper in einen 
&lt;code&gt;google::protobuf::io::CodedInputStream&lt;/code&gt;.&lt;/li&gt;
      &lt;li&gt;Jetzt kann man die Größe des folgenden Objektes mit 
&lt;code&gt;coded_input.ReadVariant32(&amp;amp;msg_size);&lt;/code&gt; auslesen.&lt;/li&gt;
      &lt;li&gt;Mit &lt;code&gt;google::protobuf::io::CodedInputStream::Limit limit = coded_input.PushLimit(msg_size);&lt;/code&gt;
verbieten wir, dass die folgende Leseoperation mehr Bytes liest, als 
zu unserem Objekt gehört.&lt;/li&gt;
      &lt;li&gt;&lt;code&gt;msg.ParseFromCodedStream(coded_input);&lt;/code&gt; liest jetzt bis zum Limit und 
befüllt unser Objekt mit den deserialisierten Daten.&lt;/li&gt;
      &lt;li&gt;Die Abfrage &lt;code&gt;msg.ConsumedEntireMessage()&lt;/code&gt; sagt uns, ob das gesamte Objekt
aus dem Stream gezogen werden konnte.&lt;/li&gt;
      &lt;li&gt;Und am Ende kann man mit &lt;code&gt;coded_input.PopLimit(limit);&lt;/code&gt; das alte Leselimit
(was vermutlich bei “unendlich” liegt) wieder zurücksetzen um den 
&lt;code&gt;CodedInputStream&lt;/code&gt; für andere Operationen zu nutzen.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;was-im-internet-nicht-so-genau-beschrieben-wird-&quot;&gt;Was im Internet nicht (so genau) beschrieben wird …&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Vorsicht!&lt;/em&gt;&lt;br /&gt;
Denn bei der Deserialisierung gibt es einige Stolpersteine.
Zum einen gehen wir davon aus, dass der Input-Stream immer ein vollständiges
Objekt beinhaltet. Das muss beim stückweisen Einlesen eines Datenpuffers 
(z.B. bei einer Netzwerkübertragung) nicht der Fall sein.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;coded_input.ConsumedEntireMessage()&lt;/code&gt; gibt nämlich gerne auch mal &lt;code&gt;true&lt;/code&gt;
zurück, wenn im Puffer das Objekt an einer Stelle abgeschnitten wird,
wo danach nur noch “optionale”, also möglicherweise leere Felder folgen.&lt;br /&gt;
In diesem Fall werden die Felder nämlich leer belassen und so getan,
als hätte man schon das gesamte Objekt auslesen können.&lt;/p&gt;

&lt;p&gt;Mein “quick-and-dirty” Workaround sah dann so aus, dass ich nach der
Deserialisierung nochmals &lt;code&gt;msg.ByteSize()&lt;/code&gt; aufgerufen habe, um es mit 
der zuvor gelesenen erwarteten Größe des Objektes zu vergleichen.&lt;/p&gt;

&lt;p&gt;War dem nicht so fehlte etwas, was noch eingelesen werden musste.&lt;br /&gt;
Das hätte man natürlich auch anders erraten können, wenn man nämlich die
Größe des original Raw-Puffers vor der Kapselung mit der erwarteten
Objektgröße verglichen hätte.&lt;br /&gt;
However, &lt;code&gt;msg.ByteSize()&lt;/code&gt; tut das im Nachhinein auch.&lt;/p&gt;

&lt;p&gt;Auch verhält sich der &lt;code&gt;CodedInputStream&lt;/code&gt; recht ungut, in dem er trotz
gesetzter Limitierung am Originalstream weiterliest.&lt;/p&gt;

&lt;p&gt;Man kann also nicht davon ausgehen, dass der Datenzeiger des 
Original-Streams genau auf das nächste Objekt zeigt, wenn ein 
&lt;code&gt;CodedInputStream&lt;/code&gt; benutzt wird.&lt;/p&gt;

&lt;p&gt;Ich musste am Ende dazu übergehen, bei einer stückweisen Datenübertragung
mit einem Memorystream die Daten aufzufangen und dessen Kopie an den
Google Code zu übergeben. Dort wurde dekodiert und am Ende stand fest,
wie viele Bytes für eine Deserialisierung notwendig war.&lt;br /&gt;
Und eben diese Menge wurde dann aus dem Memorystream entfernt, bevor
die Google Streams zurückgesetzt wurden und die nächste Deserialisierung
eingeleitet wurde.&lt;/p&gt;

&lt;p&gt;Es mag aber sein, dass es hierfür eine bessere Lösung gibt.&lt;br /&gt;
Wie auch immer … mein Ansatz scheint zu funktionieren.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Naja, ich weiß nicht, ob ich Protobuf jetzt für “super” halten soll.&lt;br /&gt;
Es tut innerhalb seiner Spezifikation das, was es soll, wenn auch mit ein 
paar offenen Punkten in der C++ Implementierung.&lt;br /&gt;
Doch ich sehe aktuell keinen Grund diese Technologie privat einzusetzen.&lt;/p&gt;

&lt;p&gt;Da schätze ich andere angepasstere Formen der Serialisierung eben mehr.&lt;/p&gt;

&lt;p&gt;Doch die Tatsache, dass es ein Objekt-Austauschformat zwischen allen 
wichtigen Programmiersprachen gibt, ist auf jeden Fall ein großer
Vorteil, der in vielen Projekten die Produktivität ordentlich steigern
kann.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Joker</title>
   <link href="https://www.opengate.at/blog/2019/11/joker/"/>
   <published>2019-11-10T22:45:00+01:00</published>
   <updated>2019-11-10T22:45:00+01:00</updated>
   <id>https://www.opengate.at/blog/2019/11/joker</id>
   <category term="entertainment" />
   <summary type="text">Nachts, am Heimweg vom Kino, wenn man so durch Wiens Straße wandert, 
entscheidet sich, ob der gesehene Film sein Geld wert war.

Und nachdem meine Gedenken kreuz und quere durch vergangene Bekanntschaften,
eigene Befindlichkeiten und Sozialkritik streiften, kann ich nur
sagen, Joaquin Phoenix’s 
Darstellung des “Joker” im 
gleichnamigen Film muss man gesehen haben.
</summary>
   <content type="html">&lt;p&gt;Nachts, am Heimweg vom Kino, wenn man so durch Wiens Straße wandert, 
entscheidet sich, ob der gesehene Film sein Geld wert war.&lt;/p&gt;

&lt;p&gt;Und nachdem meine Gedenken kreuz und quere durch vergangene Bekanntschaften,
eigene Befindlichkeiten und Sozialkritik streiften, kann ich nur
sagen, &lt;a href=&quot;https://de.wikipedia.org/wiki/Joaquin_Phoenix&quot;&gt;Joaquin Phoenix&lt;/a&gt;’s 
Darstellung des &lt;a href=&quot;https://de.wikipedia.org/wiki/Joker_(Film)&quot;&gt;“Joker”&lt;/a&gt; im 
gleichnamigen Film muss man gesehen haben.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Und wie ich auch schon an einigen Stellen im Internet vorher gelesen hatte,
muss ich mich auch der folgenden Meinung anschließen:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Dass dieser Joker Film im Batman (DC) Universum spielt, ist KEIN Vorteil.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Denn die Story, wie aus einem armen teils kranken Menschen ein - nun ja,
sagen wir - geisteskranker Verbrecher wird, ist durchaus bewegend.&lt;/p&gt;

&lt;p&gt;Es ist zwar die gefühlt 100ste Neuverfilmung der Joker-Story, dass aus jedem
unterdrückten, sozial benachteiligtem Kind ein Massenmörder werden kann,
aber nichts desto trotz macht es schon Sinn, dass jene, zu denen das Leben 
ungut war, irgend wann einmal “durchdrehen”.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Marcel_Reich-Ranicki&quot;&gt;Marcel Reich Ranicky&lt;/a&gt; 
meinte in fast jeder Ausgabe der Reihe “Lauter schwierige Patienten”, dass es 
eine wissenschaftliche Arbeit zum Thema Kindheit und soziales Umfeld in Bezug 
auf außergewöhnliche Persönlichkeiten in der Literatur geben sollte.&lt;br /&gt;
Und er meinte außerdem, dass großteils nur Menschen, die viel gelitten haben,
zu starken kritischen Werken befähigt sind, weil sie die Welt ob ihrer
Erlebnisse durch andere Augen sehen.&lt;/p&gt;

&lt;p&gt;Nun mag “Joker” kein Literaturgenie sein, im Gegenteil, doch sein finaler
Auftritt und die scharfe Analyse seiner Umwelt, der erkannten Unfähigkeit 
seiner Mitmenschen lässt mich eher an &lt;a href=&quot;https://de.wikipedia.org/wiki/Thomas_Bernhard&quot;&gt;Thomas Bernhard&lt;/a&gt;
denken, als an die Figur des Widersachers von Batman.&lt;/p&gt;

&lt;p&gt;Deplatziert wirken die Szenen, in den Bruce Wayne als Kind oder sein Vater
an der Handlung teilnehmen. Denn auch wenn vernünftig inszeniert, lenken
diese Figuren meiner Meinung nach vom Schicksal eines kranken und sozial
isolierten Menschen eher ab. Eine jede mögliche Beziehung zu anderen Menschen
hätte die Umstände ebenso gut verkörpern können und der Film wäre
dann von seinen wirklichkeitsnahen Ansätzen nicht ins Fantasy-Genre 
abgeglitten.&lt;/p&gt;

&lt;p&gt;Ein große Leistung hat meines Erachtens Joaquin Phoenix erbracht.
Es ist alles andere als leicht, eine solche Rolle einzustudieren und glaubhaft
zu vermitteln. Das gilt aber - denke ich - für alle Rollen, die mit 
Geisteskrankheit zu tun haben.&lt;/p&gt;

&lt;p&gt;Ich denke da an &lt;a href=&quot;https://de.wikipedia.org/wiki/Leonardo_DiCaprio&quot;&gt;Leonardo DiCaprios&lt;/a&gt;
Rolle in &lt;a href=&quot;https://de.wikipedia.org/wiki/Shutter_Island&quot;&gt;Shutter Island&lt;/a&gt; ebenso,
wie an &lt;a href=&quot;https://de.wikipedia.org/wiki/Dustin_Hoffman&quot;&gt;Dustin Hoffmans&lt;/a&gt; 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Rain_Man&quot;&gt;Rain Man&lt;/a&gt;. Denn die “Ticks”, die man 
sich als Schauspieler bei solchen Rollen aneignet, können durchaus das eigene
Leben negativ beeinflussen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ich war diesmal etwas spät dran, den Film im Kino zu sehen, doch auch trotz
der Spoiler, die man eben so mitbekommt, überraschte mich der Film durch 
seine Bildsprache. “Joker” ist eben doch nicht nur eine weitere Verfilmung
einer interessanten Comic-Figur, es ist ein verzerrtes Porträt eines Menschen, 
dem viel Wahnsinn widerfährt, bis er ihn letztlich als normal ansieht.&lt;/p&gt;

&lt;p&gt;Ein solcher “Joker” könnte auch bei mir um die Ecke in einer kleinen 
Nachbarwohnung heranwachsen und eines Tags ausbrechen.&lt;/p&gt;

&lt;p&gt;… nun, nicht ganz. Denn hier bin ich schon stolz darauf, dass wir 
(noch) nicht alle Sozialämter aus Kostengründen geschlossen haben und 
kranke Menschen ihre Medikamente bekommen und nicht ignorant auf die
Straße gesetzt werden.&lt;/p&gt;

&lt;p&gt;Vielleicht ermahnen uns solche Filme genauer darauf zu achten, wem wir 
durch purem Geiz die Existenzgrundlage entziehen, und dass wir&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;wie Joker trefflich bemerkte - wieder mehr zuhören und auch hinsehen
sollen, wenn uns eine gequälte Seele ihr Schicksal schildert.&lt;/li&gt;
&lt;/ul&gt;
</content>
 </entry>
 
 <entry>
   <title>Der PI-Top</title>
   <link href="https://www.opengate.at/blog/2019/11/pi-top/"/>
   <published>2019-11-09T12:00:00+01:00</published>
   <updated>2019-11-09T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2019/11/pi-top</id>
   <category term="hardware" />
   <summary type="text">Warum gibt es eigentlich keine Laptops, die auf der ARM-Plattform
basieren?

Unzählige ARM-Tablets mit Android
finden wir in jedem Laden heute, doch keinen einzigen Laptop?

Zum Glück gibt es ein Projekt, welches sich in den Kopf gesetzt hat, den
Raspberry-PI “tragbar” zu machen …
</summary>
   <content type="html">&lt;p&gt;Warum gibt es eigentlich keine Laptops, die auf der &lt;a href=&quot;https://de.wikipedia.org/wiki/ARM-Architektur&quot;&gt;ARM-Plattform&lt;/a&gt;
basieren?&lt;/p&gt;

&lt;p&gt;Unzählige ARM-Tablets mit &lt;a href=&quot;https://de.wikipedia.org/wiki/Android_%28Betriebssystem%29&quot;&gt;Android&lt;/a&gt;
finden wir in jedem Laden heute, doch keinen einzigen Laptop?&lt;/p&gt;

&lt;p&gt;Zum Glück gibt es ein Projekt, welches sich in den Kopf gesetzt hat, den
&lt;a href=&quot;https://de.wikipedia.org/wiki/Raspberry_Pi&quot;&gt;Raspberry-PI&lt;/a&gt; “tragbar” zu machen …
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Es ist schon schlimm genug, dass Microsoft seine &lt;a href=&quot;http://docs.microsoft.com/en-us/windows/arm/&quot;&gt;Windows-on-ARM&lt;/a&gt;
Initiative vor Jahren in den Sand gesetzt hat. Vielleicht erleben wir da noch eine 
Renaissance, aber vorerst gibt es fast ausschließlich nur Laptops auf Basis 
der &lt;a href=&quot;https://de.wikipedia.org/wiki/X86-Prozessor&quot;&gt;X86&lt;/a&gt; und X86-64 Plattformen
… also quasi herkömmliche PCs zum Tragen.&lt;/p&gt;

&lt;p&gt;Dabei wären Systeme mit ARM-Prozessoren, die in allen Smartphones und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Tabletcomputer&quot;&gt;Tablets&lt;/a&gt; stecken, ebenso gut 
geeignet um ordentliche Arbeitslaptops daraus zu bauen. Doch Fehlanzeige, 
zumindest in meinem Umfeld ist solche Hardware nicht verfügbar.&lt;/p&gt;

&lt;p&gt;Mit dem &lt;a href=&quot;https://www.pi-top.com/products/pi-top-3&quot;&gt;PI-TOP&lt;/a&gt; haben wir jedoch 
eine Möglichkeit gewonnen, einen ARM-Laptop in die Finger zu bekommen:&lt;/p&gt;

&lt;p&gt;Man nehme einen Handelsüblichen Raspberry-PI (2B oder 3B) und stecke ihn
in ein PI-TOP Laptopgehäuse. Und schon haben wir einen vollständigen
Laptop, der mit einem ARM-Chip betrieben wird und auf dem eine 
ARM-basierte &lt;a href=&quot;https://en.wikipedia.org/wiki/Linux_distribution&quot;&gt;Linux-Distribution&lt;/a&gt;
läuft.&lt;/p&gt;

&lt;p&gt;Ich glaube ja, dass Betriebssystemstandards der Grund dafür sind, warum 
ARM-Laptops nicht angeboten werden.
Denn während reguläre Laptops wie PCs sich an den &lt;a href=&quot;https://de.wikipedia.org/wiki/BIOS&quot;&gt;BIOS&lt;/a&gt;
oder &lt;a href=&quot;https://de.wikipedia.org/wiki/Unified_Extensible_Firmware_Interface&quot;&gt;EFI&lt;/a&gt; 
Standard halten, haben ARM-basierte Chips wenig bis keine Vorgaben, wie ein OS
von ihnen gebootet werden soll. Ähnlich mag es mit den Schnittstellen für
Bildschirme usw. aussehen.&lt;br /&gt;
Bei den Smartphones gilt wohl das gleiche, doch hier ist ein großer hungriger
Markt, der gut bezahlt, während die Laptop-Arbeiter wohl in der Minderheit
stehen.&lt;/p&gt;

&lt;p&gt;However … wichtig ist: Ich habe jetzt einen ARM-Laptop.&lt;/p&gt;

&lt;h3 id=&quot;der-pi-top-3&quot;&gt;Der PI-TOP 3&lt;/h3&gt;

&lt;p&gt;Der PI-TOP ist tatsächlich ein etwas leer wirkendes Laptop-Gehäuse,
also Bildschirm, Tastatur, Touchpad und Akku.&lt;br /&gt;
Wenn man aber die Tastatur herausklappt, und links in seinem
“Hohlraum” einen Raspberry PI 3B als neues Herz verbaut, wird daraus
ein vollständiger und funktionsfähiger Laptop.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/pitop3.jpg&quot; alt=&quot;PI-TOP-3&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Ist der RPI verschraubt, wird ihm eine PIN-Brücke samt Kühlkörper aufgesetzt,
der seine PINs zu einem Adapter weiterleitet, wo ein Breadboard auf einer
Magnetschiene angedockt werden kann. HDMI wird für den Screen “abgegriffen”
und der Audio-Anschluss wird hinten am Gerät hinausgeleitet.
Eingebaute Lautsprecher hat der PI-TOP leider nicht.&lt;/p&gt;

&lt;p&gt;2 der 4 USB-Ports werden abgezwackt, vermutlich für Strom, Tastatur und Maus,
wobei man intern einen USB-Port wieder zurückbekommt.&lt;/p&gt;

&lt;p&gt;Neben dem Breadboard bleibt dann noch etwas Platz um “Zeug” in das Gehäuse
zu legen. Und davon wird auch schon einiges mitgeliefert.
Nämlich ein paar Widerstände, Steckbrücken und ein Ultraschallsensor.&lt;br /&gt;
Natürlich kann man das Breadboard und das “Zeug” auch herausnehmen und so
etwas Gewicht einsparen, oder etwas anderes hineinpacken.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/pitop3-open.jpg&quot; alt=&quot;PI-TOP-3-Open&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Im Lieferumfang ist auch eine 8GB SD-Karte mit der 
&lt;a href=&quot;https://en.wikipedia.org/wiki/Raspbian&quot;&gt;Raspbian&lt;/a&gt; Variante 
“PI-TOP OS” enthalten. Ich muss aber sagen, dass ich damit ein paar 
Problemchen hatte und so habe ich das OS durch das übliche Raspbian
ersetzt, welches weniger RAM verbraucht und auch schnell bootet.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;320 Euro kostet das Laptop Gehäuse und wenn man von seinem grellen
Grünton mal absieht, ist es ein ordentliches Stück Hardware.
Natürlich ist es kein High-End Teil, sondern eben nur Plastik, 
aber dafür gut ausgeführt.&lt;br /&gt;
Und natürlich kann man sowohl das RPI-Board wie auch die SD-Karte
leicht tauschen.&lt;br /&gt;
Die aufklappbare Tastatur macht den Hardwaretausch zu einer Angelegenheit
von wenigen Minuten, während man beim Zerlegen eines normalen Laptops
schon mal bis zu einer Stunde braucht, um z.B. die Festplatte zu tauschen.&lt;/p&gt;

&lt;p&gt;Der größte Nachteil: Der neue Raspberry PI 4 passt nicht hinein.&lt;br /&gt;
Was auch logisch ist, schließlich wurde das Board-Design geändert.
Nur leider wird es wohl in nächster Zeit keinen Laptop als PI-TOP 4
geben, denn unter dem Namen PI-TOP-4 verkauft die Firma ein anderes
Produkt, das den RPI-4 anders einsetzt, aber eben nicht mehr als Laptop.&lt;/p&gt;

&lt;p&gt;Doch auch der RPI-3B+ ist ein gutes Board, mit dem man super programmieren
und auch ein paar Office-Aufgaben erledigen kann.
Mit ein paar Zusatztools für Windows-&lt;a href=&quot;https://en.wikipedia.org/wiki/Remote_Desktop_Protocol&quot;&gt;RDP&lt;/a&gt;
oder &lt;a href=&quot;https://en.wikipedia.org/wiki/Arduino_IDE&quot;&gt;Arduino IDE&lt;/a&gt; wird daraus ein 
guter Wegbegleiter, lediglich Webanwendungen sind mit der CPU heute nicht mehr
möglich. “Gut programmierte Seiten” wie &lt;a href=&quot;http://www.opengate.at/&quot;&gt;OpenGATE.at&lt;/a&gt; 
sind natürlich kein Problem, doch die heutigen mit &lt;a href=&quot;/blog/2018/12/jquery/&quot;&gt;jQuery&lt;/a&gt;
und anderen Werbescripten verseuchten Seiten bereiten dem RPI-3 dann doch 
etwas Kopfweh bzw. Wartezeiten.&lt;/p&gt;

&lt;p&gt;Alles in allem bin ich damit zufrieden und nutze das handliche Teil gerne 
auch im Bett weiter.
… also endlich liege ich auch mal mit einem ARM System in der Kiste.
War doch schon lange überfällig … ;)&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Wenn die Community Sch**** ist</title>
   <link href="https://www.opengate.at/blog/2019/11/oss-pissed/"/>
   <published>2019-11-03T12:00:00+01:00</published>
   <updated>2019-11-03T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2019/11/oss-pissed</id>
   <category term="general" />
   <summary type="text">Mit den Worten:


  Great. Thanks, Dan. As I had limited capacity available at the time, I just
felt that that was that. If I’m going to get emails like that for a little 
project then it’s not worth it anymore.


verabschiedete sich neulich der Entwickler der Bibliothek 
WiringPI und erklärte sein über
Jahre gepflegtes Programmierprojekt für tot.
</summary>
   <content type="html">&lt;p&gt;Mit den Worten:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Great. Thanks, Dan. As I had limited capacity available at the time, I just
felt that that was that. If I’m going to get emails like that for a little 
project then it’s not worth it anymore.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;verabschiedete sich neulich der Entwickler der Bibliothek 
&lt;a href=&quot;http://wiringpi.com/wiringpi-deprecated/&quot;&gt;WiringPI&lt;/a&gt; und erklärte sein über
Jahre gepflegtes Programmierprojekt für tot.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Ich habe mich vor 15 Jahren mal über die “arroganten” C/C++ Entwickler 
geärgert, die gerne mal hochnäsig in Foren die Meinung vertraten:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Wer das nicht versteht, soll es mit der IT bleiben lassen und 
sein Maul halten.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Nun, heute würde ich mich selbst zu jenen “arroganten” Typen zählen.&lt;br /&gt;
Doch ich lege wert darauf, dass die meisten hochnäsigen Aussagen meinerseits
(bzw. unsererseits) leider nur zu oft provoziert werden.&lt;/p&gt;

&lt;p&gt;Nicht jeder am Biologieunterricht interessierte Schüler wird später ein 
weltweit bekannter Hirnchirurg werden. … das ist nun mal Fakt.&lt;br /&gt;
Und gleichsam ist nicht jeder Mensch, der einen PC ein- und ausschalten kann,
qualifiziert sich in komplexe Entscheidungen der Softwareentwicklung
einzumischen.&lt;/p&gt;

&lt;p&gt;Ich selbst kann zwar Autofahren, bin aber absolut unfähig (und auch nicht
interessiert daran) irgend etwas unter der Motorhaube zu verstehen.&lt;/p&gt;

&lt;p&gt;Problematisch wird es aber, wenn “wir” uns einbilden, überall ohne 
Einarbeitung mitreden zu können. Und besonders wenn es um Forderungen
geht.&lt;/p&gt;

&lt;p&gt;Beginnen Sätze mit:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Das ist doch nur …
Das ist das Gleiche wie …
Wieso machst du/macht ihr nicht …&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;erkenne ich mein eigenes jüngeres Ich wieder, das allzu gerne
klugscheißen wollte.&lt;br /&gt;
Man stellt sich die Welt einfach vor und möchte in Sekundenschnelle etwas
“produzieren” um dann möglichst viel Anerkennung dafür abzukassieren.&lt;/p&gt;

&lt;p&gt;Jetzt zeigt aber die Lebenserfahrung, dass unsere Welt in den meisten Fällen
komplex ist und Schnelllösungen den Preis der Ungenauigkeit und 
Unzuverlässigkeit in sich tragen.&lt;/p&gt;

&lt;p&gt;Aus diesem Grund dauert Entwicklung eben und erfordert viel Zeit, Einarbeitung
und vor allem Motivation, aus der dann erst nach und nach verlässliche 
Erkenntnisse abgeleitet werden können.&lt;/p&gt;

&lt;p&gt;Und da ist es eben mehr als nervend, wenn einem unqualifizierte Aussagen und 
überzogene Forderungen ungefiltert vor die Füße geworfen werden.&lt;br /&gt;
Nebenbei sei erwähnt, das sich das gerade im Internet sehr schnell 
potenziert.&lt;/p&gt;

&lt;p&gt;Es ist daher (von mir/uns) nicht arrogant gemeint, wenn dann etwas härtere 
Antworten nach dem Stil&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;Ach setzt dich du auch mal 3 Jahre hin und mach es selbst, dann 
verstehst du schon, warum mich deine Aussagen nerven.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;kommen. Es ist ab einer bestimmten Frequenz an Störungen einfach nur 
natürlich, dass man seiner Umwelt dies mitteilt.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Ich für meinen Teil bedauere es auf allen Ebenen, dass die Entwicklung eines
hervorragenden Projektes wir &lt;code&gt;WiringPI&lt;/code&gt; wegen persönlicher Frustration 
eingestellt wurde.&lt;/p&gt;

&lt;p&gt;Der durch vorlaute Kommentare angerichtete Schaden ist enorm. Nicht nur, dass
ein wichtiges Projekt für &lt;a href=&quot;https://de.wikipedia.org/wiki/Raspberry_Pi&quot;&gt;Raspberry PI&lt;/a&gt;
Fans verschwunden ist, nein auch der Entwickler geht nun zur 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Open_Source&quot;&gt;Open Source&lt;/a&gt; Bewegung auf Distanz.&lt;/p&gt;

&lt;p&gt;Damit schneiden sich die Anwender tief ins eigene Fleisch, wenn sie wie kleine
Kinder die Forderung in Raum stellen, ohne Gegenleistung (Bezahlung) alles und
sofort abschöpfen zu wollen und gleichzeitig nur negative Töne in Richtung der
Entwicklung fließt.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Ich kann daher nur an die Anwender von Software appellieren und versuchen ihnen
klar zu machen, dass Querschüsse in Form von Beschwerden über freie und 
kostenlose Produkte nicht dazu führen, dass plötzlich von selbst alles besser
wird.&lt;br /&gt;
“Wir” brauchen keine Stichler, die selbst weder Zeit noch Liebe in den Aufbau
von Wissen investieren wollen.&lt;/p&gt;

&lt;p&gt;Und ich möchte (aus eigener Erfahrung) betonen, dass es keine verletzend
gemeinte Arroganz ist, wenn “wir” dritte als “dumm” oder “inkompetent”
bezeichnen, sondern eine Art von Hilferuf.&lt;/p&gt;

&lt;p&gt;Denn es gibt nichts Destruktiveres in einem kreativen Beruf, wenn man durch
Kindereien stets an der Ausführung seiner Berufung gehindert wird und einem
die Freude an der Arbeit gezielt vermiest wird.&lt;/p&gt;

&lt;p&gt;Für Gordon von &lt;code&gt;wiringPi&lt;/code&gt; habe ich jedenfalls Verständnis und bedauere zu 
tiefst, dass seine Arbeit für die OpenSource-Community an den Nutzern 
ebendieser gescheitert ist.&lt;/p&gt;

&lt;p&gt;… und leider ist dieses Projekt nicht das einzige, das so endet …&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>M5 Stack</title>
   <link href="https://www.opengate.at/blog/2019/11/m5-stack/"/>
   <published>2019-11-02T12:00:00+01:00</published>
   <updated>2019-11-02T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2019/11/m5-stack</id>
   <category term="hardware" />
   <summary type="text">Der Computer M5 (Multitronik 5) 
wurde bei Sternzeit 4729,4 für die Crew des Raumschiffs Enterprise
zu einer Bedrohung, als er ein destruktives Eigenleben entwickelte.

… Puh, na dann hoffen wir mal, dass mein kleiner M5 Stack
basierend auf dem ESP32 nicht ebenfalls
größenwahnsinnig wird.
</summary>
   <content type="html">&lt;p&gt;Der &lt;a href=&quot;https://memory-alpha.fandom.com/de/wiki/Computer_M5&quot;&gt;Computer M5 (Multitronik 5)&lt;/a&gt; 
wurde bei Sternzeit 4729,4 für die Crew des &lt;a href=&quot;https://de.wikipedia.org/wiki/Raumschiff_Enterprise&quot;&gt;Raumschiffs Enterprise&lt;/a&gt;
zu einer Bedrohung, als er ein destruktives Eigenleben entwickelte.&lt;/p&gt;

&lt;p&gt;… Puh, na dann hoffen wir mal, dass mein kleiner &lt;a href=&quot;http://m5stack.com/&quot;&gt;M5 Stack&lt;/a&gt;
basierend auf dem &lt;a href=&quot;https://de.wikipedia.org/wiki/ESP32&quot;&gt;ESP32&lt;/a&gt; nicht ebenfalls
größenwahnsinnig wird.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Das größte Problem, das ich mit vielen “Nicht-Arduino-UNO” Mikrocontrollern
habe, ist die Tatsache, dass sie alle unterschiedlich aussehen und 
unterschiedliche Pinbelegungen haben.&lt;/p&gt;

&lt;p&gt;Bei einem &lt;a href=&quot;https://en.wikipedia.org/wiki/Arduino_Uno&quot;&gt;UNO Board&lt;/a&gt; kann man ja
Platinen (Shields) bauen, die genau auf die 
Pins passen. Dann ist es egal, ob ein &lt;a href=&quot;https://en.wikipedia.org/wiki/ATmega328&quot;&gt;ATmega328&lt;/a&gt;, 
&lt;a href=&quot;http://www.microchip.com/wwwproducts/en/ATmega32U4&quot;&gt;ATmega32u4&lt;/a&gt; oder ESP32 
den Code ausführt.&lt;br /&gt;
Doch zwischen einem &lt;a href=&quot;http://www.arduino.cc/en/Guide/ArduinoProMini&quot;&gt;Pro Mini&lt;/a&gt;, 
Micro, Nano oder Esplora wird es schwierig. Die sehen alle anders aus.&lt;br /&gt;
Und bei den ESP Boards ist es genau so.&lt;/p&gt;

&lt;p&gt;Will man einen “Sensorstecker” bauen, muss man sich selbst Gedanken machen,
die man die Leiterbahnen nutzt um möglichst effizient die Kommunikation 
zwischen Board und Sensor herzustellen.&lt;/p&gt;

&lt;p&gt;Gibt es da keinen Standard?&lt;/p&gt;

&lt;h3 id=&quot;m5-und-sein-modul-standard&quot;&gt;M5 und sein Modul-Standard&lt;/h3&gt;

&lt;p&gt;Der M5 Stack ist eigentlich auch nur ein ESP32 Board, doch sein Vorteil 
ist ein normiertes Chip- und Gehäusedesign. Ähnlich wie beim Uno, kann man so
Shields entwerfen und auf den Board-Stack draufstecken um so neue Funktionen 
hinzuzufügen.&lt;/p&gt;

&lt;p&gt;Doch das geniale am M5 ist, seine kompakte und handliche Bauform gegenüber 
den UNO Boards.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/m5-stack.jpg&quot; alt=&quot;M5-Stack&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Das &lt;em&gt;Stack&lt;/em&gt; Konzept ermöglicht, dass man mehrere Module übereinander steckt,
oder am Bodenmodul nach allen 4 Seiten Stecker nach außen nutzen kann.&lt;/p&gt;

&lt;p&gt;Das Top-Modul verfügt über ein OLED-Display und 3 Tasten, womit man ohne 
zusätzliche Hardware sofort kleine grafische Programme schreiben kann.&lt;/p&gt;

&lt;p&gt;Besonders toll fand ich daher die fertigen Beispiele für die 
&lt;a href=&quot;https://en.wikipedia.org/wiki/Arduino_IDE&quot;&gt;Arduino IDE&lt;/a&gt;.
Von &lt;a href=&quot;https://de.wikipedia.org/wiki/Tetris&quot;&gt;Tetris&lt;/a&gt; bis hin zur digitalen 
Armbanduhr-Anzeige findet man hier typische Programme, durch die der M5 
glänzen kann.&lt;/p&gt;

&lt;p&gt;Mitgeliefert wird ein 150 mA Akku, der im Bodenmodul verbaut ist.
Doch damit läuft der M5 (wenn er nicht zum Schlafen verdonnert wird)
nur einige Minuten. Deshalb habe ich gleich einen 700 mA Akku nachgerüstet.&lt;/p&gt;

&lt;h3 id=&quot;button-patches&quot;&gt;Button Patches&lt;/h3&gt;

&lt;p&gt;Ein Manko ist mir allerdings schnell aufgefallen:&lt;br /&gt;
Beim Zerlegen des M5 Stacks fielen die 3 Buttons aus dem Gehäuse.
Als ich wieder alles zusammensetzte und die Buttons nutzte, passierte es
recht schnell, dass diese sich schief im Gehäuse verklemmten.&lt;/p&gt;

&lt;p&gt;Durch weitere Module verzog sich das Gehäuse etwas bzw. wurden offenbar die
Tastenräume etwas größer, womit sie “labil” wurden.&lt;/p&gt;

&lt;p&gt;Kein Problem, wenn man einen &lt;a href=&quot;/blog/2019/01/ender-3/&quot;&gt;3D-Drucker&lt;/a&gt;
hat. Und so druckte ich mir einfach neue Buttons, die um einen Millimeter 
höher waren und somit nicht mehr einfach ins Gerät hineinfallen oder sich 
verklemmen konnten.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Gefahr erkannt, Gefahr gebannt!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Also, von der eleganten Ausführung her bekommt man für die 20-30 Euro, die
ein M5 Basisgerät kostet, ein feines Stück Hardware geliefert. Erweiterungen
für &lt;a href=&quot;https://de.wikipedia.org/wiki/RFID&quot;&gt;RFID&lt;/a&gt;, Motoren und viele andere 
Techniklösungen gibt es einige, die mit weiteren 2-10 Euro pro Artikel
verpreist sind.&lt;/p&gt;

&lt;p&gt;Es gibt übrigens parallel zum M5 &lt;strong&gt;Stack&lt;/strong&gt; mit den M5 &lt;strong&gt;Stick&lt;/strong&gt; noch einen 
zweiten Formfaktor. Nun … wenn es um Standards geht, muss man also doch noch
im Vorfeld entscheiden, ob der eine oder der andere Standard besser für ein
Projekt passt.&lt;/p&gt;

&lt;p&gt;Mir gefällt am M5 Konzept, dass es einem erlaubt, ein quasi verkaufsfertiges
Produkt zu bauen, da Gehäuse und Stecker sich an Erweiterbarkeit orientieren
und schön aussehen.&lt;br /&gt;
Bei Arduinos sind lediglich die Boards für ein Modell genormt. Gehäuse gibt es
zahlreiche, die aber alle eher weniger erweiterungsfähig bzw. zusammensteckbar 
sind.&lt;/p&gt;

&lt;p&gt;Ein Lob auf die Erfinder dieses Modells. Es ist einfach &lt;em&gt;cool&lt;/em&gt; designt!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Online und Update Zwangsneurose</title>
   <link href="https://www.opengate.at/blog/2019/10/online-force/"/>
   <published>2019-10-27T12:00:00+01:00</published>
   <updated>2019-10-27T12:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2019/10/online-force</id>
   <category term="software" />
   <summary type="text">Ein großes Problem in Sachen Softwarequalität sehe ich im heutigen Zwang
von Programmen, nur dann zu funktionieren, wenn ein Online-Zugang 
vorhanden ist.

Und damit meine ich gar nicht die Gefahr eines Totalausfalls des 
Internets, sondern spreche eher vom Konsumentenschutz.
</summary>
   <content type="html">&lt;p&gt;Ein großes Problem in Sachen Softwarequalität sehe ich im heutigen Zwang
von Programmen, nur dann zu funktionieren, wenn ein Online-Zugang 
vorhanden ist.&lt;/p&gt;

&lt;p&gt;Und damit meine ich gar nicht die Gefahr eines Totalausfalls des 
Internets, sondern spreche eher vom Konsumentenschutz.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Ein lustiges Beispiel:&lt;/p&gt;

&lt;p&gt;Als ich vor 7 Jahren &lt;a href=&quot;https://pokewiki.de/Pok%C3%A9mon_Schwarze_Edition_und_Wei%C3%9Fe_Edition&quot;&gt;Pokemon Schwarz&lt;/a&gt;
für den &lt;a href=&quot;https://de.wikipedia.org/wiki/Nintendo_DS&quot;&gt;Nintendo DS&lt;/a&gt; gekauft habe, 
war im Spiel die Nutzung eines Online-Modus vorgesehen, die sogenannte 
Traumwelt. Dort erhielt man einige Pokemon, die im regulären Spiel nicht 
verfügbar waren. Doch dieser Dienst wurde 2013 mit der nächsten 
Spielegeneration einfach abgeschaltet.&lt;br /&gt;
Damit wird ein Teil des Produkts unbrauchbar, und die Exemplare, die sogar
heute noch zum Vollpreis in Läden angeboten werden, sind damit Out-of-the-Box
beschädigt.&lt;/p&gt;

&lt;p&gt;Noch viel schlimmer sieht es mit PC Software aus, die einen Aktivierungsserver
voraussetzt, und wo das Unternehmen pleitegegangen ist.
Die eigentlich lauffähige Software verweigert dann den Dienst und ist 
(obwohl einwandfrei erhalten) plötzlich als Ganzes defekt.&lt;/p&gt;

&lt;p&gt;Und so zieht sich eine immer größer werdende Spur an Software-Müll durch
die Kaufportale des Internets.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Da lobe ich mir doch meine alten CDs und Disketten, denn was da drauf ist,
lässt sich auch in 10-20 Jahren (zumindest auf &lt;a href=&quot;https://de.wikipedia.org/wiki/Emulator&quot;&gt;Emulatoren&lt;/a&gt;
) noch ausführen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;… denke ich dann bei mir und tatsächlich habe ich weniger Probleme mit 
Uralt-Programme, als mit welchen von vor 5 Jahren.&lt;/p&gt;

&lt;p&gt;Besonders ärgerlich ist es, dass Microsoft die Server für ältere 
Office-Versionen deaktiviert hat. Das heißt dann, dass mein &lt;a href=&quot;https://en.wikipedia.org/wiki/Microsoft_Office_2003&quot;&gt;Office 2003&lt;/a&gt;
immer noch perfekt funktioniert, aber Office 2007 nun tot ist ???&lt;/p&gt;

&lt;p&gt;Bei allem Respekt, aber gerade die Kosten von Aktivierungsservern sind 
heute derart gering, dass man mit einer Maschine durchaus jene Retro-Fans
für die nächsten Jahre weiter versorgen kann.&lt;/p&gt;

&lt;h3 id=&quot;offline-software-lebt-länger&quot;&gt;Offline-Software lebt länger&lt;/h3&gt;

&lt;p&gt;Für mich bedeutete Softwarequalität eben auch, dass ein Programm nach 10 
Jahren noch problemlos ausführbar sein soll.&lt;br /&gt;
Von alter Software sind bestenfalls technische Gründe bekannt, warum sie 
heute nicht mehr lauffähig ist. Zum Beispiel:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Anzeige und Speicherung von Jahreszahlen vor 2000 
(&lt;a href=&quot;https://de.wikipedia.org/wiki/Jahr-2000-Problem&quot;&gt;Y2K&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Funktionen auf zu neuen CPUs, die Aufgaben zu schnell erledigen
(z.B.: Warte-Schleifen laufen über)&lt;/li&gt;
  &lt;li&gt;Überläufe wegen damaliger Hardwaregrenzen, die heute nicht mehr gelten
(z.B.: Laufwerke mit Größen über 2 GB)&lt;/li&gt;
  &lt;li&gt;Deaktivierung von antiken Schnittstellen oder direkten Hardwarezugriffen
(z.B.: Win16-Programme, die of IO Ports zugreifen)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Vieles davon lässt sich aber durch Emulatoren umgehen.&lt;/p&gt;

&lt;p&gt;Onlineserver, die gerne auch verschlüsselt kommunizieren, können nicht so
einfach nachgebaut werden. Während Updates für Windows NT oder Windows 2000
auch als Service-Packs bis zum Support-Ende bereitgestellt wurden, erhielt
Windows XP sein letztes Service-Pack im Jahr 2007. Doch bis zum Jahr 2014
gab es Updates, die online bezogen werden konnten. Noch läuft dieser
Dienst, doch seine Abschaltung ist nur eine Frage der Zeit.&lt;/p&gt;

&lt;p&gt;Und während Industriesoftware früher mit Hardware-Dongle-Lösungen lizenziert
wurde, die auch recht lange halten, setzen leider auch in diesem Bereich 
immer mehr Produkte auf Online-Aktivierung.&lt;/p&gt;

&lt;p&gt;Ich konnte ja letztes Jahr live mitverfolgen, wie schnell eine Firma eingehen
kann. Da wird dann der Server ein Jahr später einfach abgedreht und damit 
fallen alle Onlinedienste einfach weg.&lt;br /&gt;
Software, die auf solche Server vertraut, fällt dann einfach aus.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Also liebe Programmierer-Kollegen da draußen:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Denkt doch bitte auch mal an eure Kunden. Die wollen von euch Qualität 
kaufen, die eben nicht jährlich durch etwas Neues ersetzt werden muss.&lt;br /&gt;
Gestaltet Updates und Aktivierungsroutinen so, dass sie ohne Internet 
&lt;em&gt;also offline&lt;/em&gt; möglich sind.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Wir erleben heute viele Retro-Tends eben WEIL Software aus den 80er und
90er Jahren heute immer noch lauffähig sind.&lt;br /&gt;
Es wäre doch Schade, wenn die Techniker der 2030ern und 2040ern die Tools 
von heute nicht mehr Aufleben lassen und “cool” finden können!&lt;/p&gt;

&lt;p&gt;… von den wirtschaftlichen Möglichkeiten mal ganz zu schweigen …&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Pulsweitenmodulation für Servos</title>
   <link href="https://www.opengate.at/blog/2019/10/pwm-servo/"/>
   <published>2019-10-26T13:00:00+02:00</published>
   <updated>2019-10-26T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2019/10/pwm-servo</id>
   <category term="hardware" />
   <summary type="text">
  Es muss wieder mehr Bewegung in die Sache kommen.


Also wird ein Servomotor an den 
Mikrokontroller 
angeschlossen.
… aber an welchen?

Ein Servo-Shield oder die 
Bibliothek für den ATmega328 wäre 
zu einfach.

Wie wäre es mit dem ATtiny?

Und die nächste Frage ist quasi “vorprogrammiert”:


  Wie bekommt man jetzt das richtige PWM
Signal hin?


</summary>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;Es muss wieder mehr Bewegung in die Sache kommen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Also wird ein &lt;a href=&quot;https://de.wikipedia.org/wiki/Servo&quot;&gt;Servomotor&lt;/a&gt; an den 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Mikrocontroller&quot;&gt;Mikrokontroller&lt;/a&gt; 
angeschlossen.&lt;br /&gt;
… aber an welchen?&lt;/p&gt;

&lt;p&gt;Ein Servo-&lt;a href=&quot;http://www.arduino.cc/en/Main/ArduinoShields&quot;&gt;Shield&lt;/a&gt; oder die 
Bibliothek für den &lt;a href=&quot;https://en.wikipedia.org/wiki/ATmega328&quot;&gt;ATmega328&lt;/a&gt; wäre 
zu einfach.&lt;/p&gt;

&lt;p&gt;Wie wäre es mit dem &lt;a href=&quot;http://www.microchip.com/wwwproducts/en/ATtiny85&quot;&gt;ATtiny&lt;/a&gt;?&lt;/p&gt;

&lt;p&gt;Und die nächste Frage ist quasi “vorprogrammiert”:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Wie bekommt man jetzt das richtige &lt;a href=&quot;https://de.wikipedia.org/wiki/Pulsdauermodulation&quot;&gt;PWM&lt;/a&gt;
Signal hin?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;blockquote&gt;
  &lt;p&gt;Warum einfach wenn’s auch kompliziert geht?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Mir wird ja gerne vorgeworfen nie den einfachen Weg zu gehen. Das ist kein 
angeborener &lt;a href=&quot;https://de.wikipedia.org/wiki/Masochismus&quot;&gt;Masochismus&lt;/a&gt; sondern 
meist eine eigene Form von Wissensdurst.&lt;/p&gt;

&lt;p&gt;Und Detailwissen ist um so wichtiger, wenn es den einfachen Weg nicht gibt.
Ich zwinge mich also selbst dazu tiefer zu graben, und auch wenn es anfangs 
nutzlos erscheint, aus solcher Sinnlosigkeit konnte ich (oft erst Jahre 
später) unverzichtbares Wissen gewinnen, das sich manchmal auch wirtschaftlich
niederschlägt.&lt;/p&gt;

&lt;p&gt;Unsere Bastel-Servos werden durch digitale Pulse gesteuert. Da geht es darum
wie lange (bzw. wie breit) ein Strompuls andauert im Verhältnis zur Zeit, in
der kein Strom fließt. Deshalb spricht man von Pulslängen- oder 
Pulsweitenmodulation (engl. Pulse Width Modulation, kurz PWM).&lt;/p&gt;

&lt;p&gt;Aus einem solchen binären Signal mit einer bestimmten Länge wird an Hand der 
Dauer des Pulses bestimmt, auf welche Position sich ein Servo hindrehen soll.&lt;/p&gt;

&lt;p&gt;Die genauen Werte und Frequenzen “erlernt” man übrigens am Besten aus dem 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Arduino_(Plattform)&quot;&gt;Arduino&lt;/a&gt; &lt;code&gt;Servo.h&lt;/code&gt; Header:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#define&lt;/span&gt; MIN_PULSE_WIDTH      &lt;span style=&quot;color:#00D&quot;&gt;544&lt;/span&gt; &lt;span style=&quot;color:#777&quot;&gt;// shortest pulse&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#define&lt;/span&gt; MAX_PULSE_WIDTH     &lt;span style=&quot;color:#00D&quot;&gt;2400&lt;/span&gt; &lt;span style=&quot;color:#777&quot;&gt;// longest pulse&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#define&lt;/span&gt; DEFAULT_PULSE_WIDTH &lt;span style=&quot;color:#00D&quot;&gt;1500&lt;/span&gt; &lt;span style=&quot;color:#777&quot;&gt;// default pulse&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#define&lt;/span&gt; REFRESH_INTERVAL   &lt;span style=&quot;color:#00D&quot;&gt;20000&lt;/span&gt; &lt;span style=&quot;color:#777&quot;&gt;// minimum refresh time&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;Die Servos arbeiten mit Pulsen von 50 &lt;a href=&quot;https://de.wikipedia.org/wiki/Hertz_(Einheit)&quot;&gt;Hertz&lt;/a&gt;, 
also jedes Puls-Interval dauert 20 Millisekunden (oder 20000 Mikrosekunden).&lt;/li&gt;
  &lt;li&gt;Ein Puls besteht aus einem kurzen High-Signal und einem ausfüllenden 
Low-Signal.&lt;/li&gt;
  &lt;li&gt;Der kürzeste Puls hat eine Dauer von 544 Mikrosekunden 
(das wäre dann 0 Grad Drehung).&lt;/li&gt;
  &lt;li&gt;Der längste Puls hat eine Dauer von 2400 Mikrosekunden 
(je nach Modell sind das dann ca. 90, 180 oder 360 Grad Drehung).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Die genaue Graddrehung ist aber so spezifisch, dass man den Servo immer 
kalibrieren muss, das heißt, wir müssen herausfinden und speichern, welcher 
Pulswert welchem Winkel entspricht. Einige meiner Servos können sich nämlich
noch ein paar Grad weiter drehen, als es eigentlich spezifiziert ist, und 
andere regieren auf die Minimum and Maximum Werte nicht, und setzen erst 
die Bewegung erst etwas darüber oder darunter um.&lt;/p&gt;

&lt;h3 id=&quot;software-puls-wellen&quot;&gt;Software Puls-Wellen&lt;/h3&gt;

&lt;p&gt;Die meisten MCUs haben eigene PWM-Pins, wo man Pulse per Hardware generieren 
lassen kann. Auf dem &lt;a href=&quot;https://en.wikipedia.org/wiki/Arduino_Uno&quot;&gt;Arduino UNO&lt;/a&gt;
sind sie mit einem Wellensymbol &lt;code&gt;~&lt;/code&gt; markiert.&lt;/p&gt;

&lt;p&gt;Unglücklicherweise ist der Frequenz oft mit dem Takt des Chips verknüpft 
(bzw. mit einer ganzzahligen Teilmenge davon).&lt;br /&gt;
Die Servo Bibliothek der Arduino-IDE nutzt daher Timer und Interrupts, 
über die die Pins dann manuell ein und ausgeschaltet werden.&lt;/p&gt;

&lt;p&gt;Doch für den ATtiny ist die Bibliothek leider nicht implementiert.
Wenn es jetzt aber nicht um hoch präzise Positionierung geht, sondern 
einfach nur eine Demo durchgeführt werden soll, können wir die Pulse
auch mit den Arduino Warte-Routinen “quick-and-dirty” nachbauen.
(Oder anders gesagt, ich bin zu faul mir jetzt die Registercodes 
herauszusuchen um mir eine Timer-Variante nachzubauen.)
Die Funktion &lt;a href=&quot;http://www.arduino.cc/reference/en/language/functions/time/delaymicroseconds/&quot;&gt;&lt;code&gt;delayMicroseconds&lt;/code&gt;&lt;/a&gt;
soll uns hier anfangs dienen.&lt;/p&gt;

&lt;p&gt;Und so wird es gemacht:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Output-Pin auf HIGH setzen mit &lt;a href=&quot;http://www.arduino.cc/reference/en/language/functions/digital-io/digitalwrite/&quot;&gt;&lt;code&gt;digitalWrite()&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Zwischen 544 und 2400 Mikrosekunden per &lt;code&gt;delayMicroseconds()&lt;/code&gt; warten&lt;/li&gt;
  &lt;li&gt;Pin auf LOW setzen mit &lt;code&gt;digitalWrite()&lt;/code&gt;]&lt;/li&gt;
  &lt;li&gt;Nun &lt;code&gt;delayMicroseconds(20000 - vorheriges_delay);&lt;/code&gt; ausführen&lt;/li&gt;
  &lt;li&gt;Und das ganze wieder von Vorne ausführen …&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Und tatsächlich, es funktioniert. Der Servo wackelt zwar wie ein alter 
Alkoholiker, weil das Timing der Pulse recht ungenau ist, doch er
dreht sich ruckelig ungefähr dort hin, wo er hingehört.&lt;/p&gt;

&lt;p&gt;Jetzt kann man die Methode verfeinern. Man kann mit &lt;a href=&quot;http://www.arduino.cc/reference/en/language/functions/time/micros/&quot;&gt;&lt;code&gt;micros()&lt;/code&gt;&lt;/a&gt;
feststellen, wie viel Zeit zwischen den Wartezeiten und anderen ausgeführten 
Codes vergangen ist und das nächste &lt;code&gt;delayMicroseconds()&lt;/code&gt; entsprechend verringern.&lt;br /&gt;
Auch kann man am Richtwert 20000 herumspielen, ihn etwas erhöhen oder 
erniedrigen, denn je nach CPU Frequenz sieht das Timing etwas anders aus.&lt;/p&gt;

&lt;p&gt;Mir ist es so nach etwas Herumprobieren gelungen, einen kleinen 
Servo-Tester umzusetzen, der nur noch wenig zittert und die Position
eines verstellbaren Widerstands (Potentiometers) auf die Servoausrichtung 
überträgt.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/servo-pwm-tester.jpg&quot; alt=&quot;Servo-PWM-Tester&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Mein bester ermittelter &lt;code&gt;delayMicroseconds()&lt;/code&gt; Referenzwert ist übrigens 20260 
(anstatt von 20000) bei einer Taktung meines ATtiny45 von 1 MHz. Da
zittert der Servo dann fast gar nicht mehr.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Und ja, mit einem ATmega328 wäre das in 4 Zeilen Code auch erledigt gewesen,
doch aktuell habe ich ein paar ATtiny45 herumliegen, die ich nicht brauche,
und andererseits hätte ich sonst nie gelernt, dass Servos mit 50 Hertz laufen
und mit 0.5 bis 2.5 Millisekunden Pulsen gesteuert werden.&lt;/p&gt;

&lt;p&gt;Der Servotester ist jedenfalls praktisch, denn wenn man Servos verbaut, sollte
man sie vor dem Einbau auf eine Position stellen, die für die weitere Anwendung
günstig ist.&lt;/p&gt;

&lt;p&gt;Natürlich kann man sich so ein Gerät auch für ein paar Euro kaufen,
aber … &lt;strong&gt;selber machen ist viel cooler&lt;/strong&gt; ;)&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Auf template vergessen?</title>
   <link href="https://www.opengate.at/blog/2019/10/forgotten-template/"/>
   <published>2019-10-20T12:00:00+02:00</published>
   <updated>2019-10-20T12:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2019/10/forgotten-template</id>
   <category term="devel" />
   <summary type="text">Wenn man so etwas sieht wie:


  1error: no match for &apos;operator&amp;lt;&apos; (operand types are 
2&apos;&amp;lt;unresolved overloaded function type&amp;gt;&apos; and &apos;SomeType&apos;)




denkt man zuerst an eine Klasse, für die der Kleiner-Operator &amp;lt; falsch oder 
gar nicht überladen wurde.

Doch … eigentlich handelt es sich um einen Aufruf einer “ge-template-eten” 
Methode.
</summary>
   <content type="html">&lt;p&gt;Wenn man so etwas sieht wie:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;error: no match for &apos;operator&amp;lt;&apos; (operand types are 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;&apos;&amp;lt;unresolved overloaded function type&amp;gt;&apos; and &apos;SomeType&apos;)
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;denkt man zuerst an eine Klasse, für die der Kleiner-Operator &lt;code&gt;&amp;lt;&lt;/code&gt; falsch oder 
gar nicht überladen wurde.&lt;/p&gt;

&lt;p&gt;Doch … eigentlich handelt es sich um einen Aufruf einer “ge-template-eten” 
Methode.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Eigentlich hätte ich den Text auch mit “Neulich in der Firma…” einleiten können.
Doch das erlebte Phänomen kenne ich ja aus vielen Bereichen.&lt;/p&gt;

&lt;p&gt;Man hat C++ Code der unter Windows (MSVC) sowieso kompiliert und unter Linux 
mit Compiler X ebenso. Dann wird auf einen neueren Compiler gewechselt, und
plötzlich kompiliert etwas nicht mehr.&lt;/p&gt;

&lt;p&gt;Doch wenn man glaubt, der neue Compiler hätte einen Bug, so liegt man häufig 
falsch. Die traurige Wahrheit ist am Ende, dass man falschen Code geschrieben
hat, den “nachsichtige” Compiler durchgelassen haben, womit sich die Compiler
selbst nicht an den Standard halten.&lt;/p&gt;

&lt;h3 id=&quot;der-2-phasen-lookup&quot;&gt;Der 2-Phasen Lookup&lt;/h3&gt;

&lt;p&gt;Fast immer wenn Templates unter Windows (MSVC) kompilieren und unter Linux 
(GCC) nicht, liegt es am 2-Phasen Lookup, den Microsoft aus 
Kompatibilitätsgründen nicht oder nur unvollständig durchführt.&lt;/p&gt;

&lt;p&gt;Microsoft nutzt dabei den Ansatz, dass Templates erst an der Stelle 
mitkompiliert werden, wenn sie instanziiert werden. Ein 
&lt;code&gt;template&amp;lt;class T&amp;gt; class X;&lt;/code&gt; bleibt also so lange unberührt, bis das erste Mal
ein &lt;code&gt;X&amp;lt;sometype_t&amp;gt;&lt;/code&gt; instanziiert wird.&lt;br /&gt;
Und dann wird im Rahmen von &lt;code&gt;sometype_t&lt;/code&gt; die Syntax von &lt;code&gt;X&lt;/code&gt; geprüft.&lt;/p&gt;

&lt;p&gt;Der C++ Standard schreibt allerdings vor, dass Templates in 2 Anläufen geprüft
werden. Das erste Mal generisch ohne Instanziierung und das 2 Mal mit den
typen-abhängigen Informationen.&lt;/p&gt;

&lt;p&gt;Und diese “erste Phase” hat ein Problem: Manche Details der Implementierung 
sind zu diesem Zeitpunkt noch nicht bekannt.&lt;br /&gt;
Nehmen wir das Beispiel&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;template&lt;/span&gt;&amp;lt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;T&lt;/span&gt;&amp;gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;struct&lt;/span&gt; Wrapper : &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;public&lt;/span&gt; T
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;public&lt;/span&gt;:
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt; do_something()
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;          do_something_special();
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Unser &lt;code&gt;Wrapper&lt;/code&gt; erbt von &lt;code&gt;T&lt;/code&gt; und geht davon aus, dass es in &lt;code&gt;T&lt;/code&gt;
eine Methode namens &lt;code&gt;do_something_special&lt;/code&gt; gibt.&lt;br /&gt;
Wird &lt;code&gt;Wrapper&lt;/code&gt; zusammen mit einer Klasse instanziiert (Phase 2), 
die ein &lt;code&gt;do_something_special&lt;/code&gt; besitzt, ist alles gut.&lt;/p&gt;

&lt;p&gt;Doch in Phase 1 stellen wir fest, dass es (noch) keine Funktion
namens &lt;code&gt;do_something_special&lt;/code&gt; gibt und hier bricht der GCC dann ab.&lt;/p&gt;

&lt;p&gt;Die Lösung ist, dem Compiler zu sagen, dass die Methode von &lt;code&gt;T&lt;/code&gt; 
abhängt, und dass kann man beim Aufruf z.B.: mit &lt;code&gt;this&lt;/code&gt; oder &lt;code&gt;T::&lt;/code&gt;
tun:&lt;/p&gt;
&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;        T::do_something_special();
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;        &lt;span style=&quot;color:#950&quot;&gt;this&lt;/span&gt;-&amp;gt;do_something_special();
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Und ein ähnliches Problem ergibt sich bei Methoden, die direkt durch
Templates instanziiert werden, oder diese nur “weiterleiten”.
Mein Beispiel sah etwa so aus:&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;enum&lt;/span&gt; StateEnum
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  State_1,
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  ...
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;};
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;struct&lt;/span&gt; Foo
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;template&lt;/span&gt;&amp;lt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; STATE&amp;gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt; interpret()
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;    ...
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;  }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;};
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;template&lt;/span&gt;&amp;lt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; STATE&amp;gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;struct&lt;/span&gt; Bar
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt; do_something(Foo&amp;amp; foo)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;  {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;    foo.interpret&amp;lt;STATE&amp;gt;();        &lt;span style=&quot;color:#777&quot;&gt;// fails&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n21&quot; name=&quot;n21&quot;&gt;21&lt;/a&gt;&lt;/span&gt;};
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n22&quot; name=&quot;n22&quot;&gt;22&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n23&quot; name=&quot;n23&quot;&gt;23&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; main()
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n24&quot; name=&quot;n24&quot;&gt;24&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n25&quot; name=&quot;n25&quot;&gt;25&lt;/a&gt;&lt;/span&gt;  Foo foo;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n26&quot; name=&quot;n26&quot;&gt;26&lt;/a&gt;&lt;/span&gt;  Bar&amp;lt;State_1&amp;gt; bar;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n27&quot; name=&quot;n27&quot;&gt;27&lt;/a&gt;&lt;/span&gt;  bar.do_something(foo)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n28&quot; name=&quot;n28&quot;&gt;28&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n29&quot; name=&quot;n29&quot;&gt;29&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Doch der Code endet mit obiger Fehlermeldung …&lt;br /&gt;
Es liegt am Aufruf von &lt;code&gt;foo.interpret&amp;lt;STATE&amp;gt;&lt;/code&gt;, denn STATE
ist ebenfalls in der ersten Phase unbekannt. Es könnte eine Zahl sein,
die mit dem Kleiner-Operator &lt;code&gt;&amp;lt;&lt;/code&gt; verglichen wird.&lt;/p&gt;

&lt;p&gt;Tja, und wie ruft man jetzt eine ge-template-ete Methode korrekt auf?&lt;/p&gt;

&lt;p&gt;Lösung:&lt;/p&gt;
&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;  instance.&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;template&lt;/span&gt; methodname&amp;lt;template_arguments&amp;gt;(func_arguments);
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Und das Beispiel oben muss dann so aussehen:&lt;/p&gt;
&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;  foo.&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;template&lt;/span&gt; interpret&amp;lt;STATE&amp;gt;();
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Und wieder hat mich so eine Konstellation ein paar Stunden Zeit gekostet.
Problematisch war in erster Linie die tückische Meldung, dass beim 
&lt;code&gt;operator&amp;lt;&lt;/code&gt; etwas nicht passt.&lt;br /&gt;
Denn da sucht man naturgemäß an anderen Stellen und nicht bei 
der Syntax des Methodenaufrufs selbst.&lt;/p&gt;

&lt;p&gt;Doch zum Glück hab ich wieder was gelernt:&lt;br /&gt;
Das Schlüsselwort &lt;code&gt;template&lt;/code&gt; ist nicht nur zum Deklarieren von Templates da, 
sondern auch um Template-Methoden aufzurufen.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Labornetzteil Marke Eigenbau</title>
   <link href="https://www.opengate.at/blog/2019/10/pc-lab-power-supply/"/>
   <published>2019-10-19T13:00:00+02:00</published>
   <updated>2019-10-19T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2019/10/pc-lab-power-supply</id>
   <category term="hardware" />
   <summary type="text">In 20 Jahren sammelt sich ganz von selbst eine Menge an “alten” Computern an,
die man nicht mehr benutzt bzw. benutzen kann.
Entweder ist das Mainboard oder die Festplatte kaputt, oder das Gerät ist
ob seines Alters nicht mehr nutzbar.

Die Netzteile überleben den 
restlichen PC oft, können aber nicht immer in neuen Geräten verbaut werden.

Was macht man also mit einem solchen Netzteil?

Man macht es zu einem Labor-Netzteil…
</summary>
   <content type="html">&lt;p&gt;In 20 Jahren sammelt sich ganz von selbst eine Menge an “alten” Computern an,
die man nicht mehr benutzt bzw. benutzen kann.&lt;br /&gt;
Entweder ist das Mainboard oder die Festplatte kaputt, oder das Gerät ist
ob seines Alters nicht mehr nutzbar.&lt;/p&gt;

&lt;p&gt;Die &lt;a href=&quot;https://de.wikipedia.org/wiki/PC-Netzteil&quot;&gt;Netzteile&lt;/a&gt; überleben den 
restlichen PC oft, können aber nicht immer in neuen Geräten verbaut werden.&lt;/p&gt;

&lt;p&gt;Was macht man also mit einem solchen Netzteil?&lt;/p&gt;

&lt;p&gt;Man macht es zu einem Labor-Netzteil…
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Wenn ich etwas liebe, dann sind das unsere kreativen Bastler, die schon vor 
Jahren Wege und Möglichkeiten entdeckt haben, wie man ein PC-Netzteil zu
einem Labornetzteil umfunktionieren kann.&lt;/p&gt;

&lt;p&gt;Schließlich liefert ein handelsübliches Netzteil mehrere 5 Volt Ausgänge,
und auch einige 3.3 Volt und 12 Volt Leitungen.&lt;/p&gt;

&lt;p&gt;Wenn man weiß, wie man das Netzteil ein bzw. ausschalten kann, dann braucht 
man nur noch seine Geräte mit den richtigen Adern verbinden.&lt;/p&gt;

&lt;h3 id=&quot;pc-power-supply-adapter&quot;&gt;PC-Power-Supply-Adapter&lt;/h3&gt;

&lt;p&gt;Eine sehr einfache “für-Jedermann” Variante gibt es online bereits für wenige
Euros zu erwerben.&lt;/p&gt;

&lt;p&gt;Mit einem PC-Power-Supply-to-Lab-Power-Supply-Adapter braucht man nur den ATX
Mainboard Stecker anschließen und kann vorne seine Geräte wie 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Arduino_(Plattform)&quot;&gt;Arduinos&lt;/a&gt; oder
&lt;a href=&quot;https://de.wikipedia.org/wiki/ESP8266&quot;&gt;ESPs&lt;/a&gt; anklemmen.&lt;br /&gt;
Alle Anschlüsse sind mit leicht auswechselbaren Sicherungen versehen und ein
am Adapter-Board angebrachter Netzschalter hilft beim gezielten bestromen.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/pc-psu-to-lab-psu.jpg&quot; alt=&quot;PC-PSU 2 Lab-PSU&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Wenn man schon eine Bestellung eines solchen Teils absetzt, kann man je nach
Wunsch auch noch etwas hinzufügen, nämlich ein paar Bananenstecker.&lt;/p&gt;

&lt;p&gt;Das Adapterboard kommt nämlich mit Klemmschrauben, die man lockert, ein
Kabel einklemmt und wieder festschraubt. Von oben mag es wie Bananenstecker
aussehen, es sind aber keine.&lt;br /&gt;
Und da bei Labornetzteilen Bananenstecker quasi Standard sind, kann man 
eben diese selbst um ein paar Euro mehr nachrüsten.&lt;/p&gt;

&lt;p&gt;Jene, die ich dran schrauben wollte, waren ein klein bisschen zu dick um durch
die Löcher der Platine zu passen. Doch mit ein ganz klein
wenig Nachbohren mit dem Akkuschrauber, wurden sie groß genug gemacht,
damit die neuen Stecker durchpassten und befestigt werden konnten.&lt;/p&gt;

&lt;p&gt;Jetzt wird noch das alte 200 Watt Netzteil vom Pentium 1 eingeschlossen,
und fertig ist das Labornetzteil.&lt;/p&gt;

&lt;h3 id=&quot;netzteil-marke-eigenbau&quot;&gt;Netzteil Marke Eigenbau&lt;/h3&gt;

&lt;p&gt;Mit einem 3D Drucker kann man das Ganze natürlich auch noch auf die Spitze
treiben. Man findet auf &lt;a href=&quot;http://www.thingiverse.com/&quot;&gt;thingiverse.com&lt;/a&gt; 
Ummantelungen für übliche PC-ATX-Netzteile und kann diese über den Kabelteil stülpen.&lt;br /&gt;
Anstatt des vorhin vorgestellten Adapterboards, schneidet man den ATX
Stecker einfach ab und verbindet die Kabel selbst mit Bananenstecker, die
am gedruckten Gehäuse herausgeführt werden.&lt;/p&gt;

&lt;p&gt;Ein und ausgeschaltet wird das Netzteil durch die Verbindung des
violetten Kabels (Nr. x) mit Ground und schon sollte das Netzteil
anspringen. Es wird generell noch empfohlen, eine Last auf die 
5 Volt Schiene zu hängen, da einige PC Netzteile dies benötigen um
überhaupt Strom zu liefern.&lt;br /&gt;
Dabei wird oft ein Widerstand empfohlen, doch ich würde hier lieber
gleich eine LED-Lampe oder einen Kühlventilator betreiben.&lt;/p&gt;

&lt;p&gt;Vielleicht gehe ich einen solche Bau in Zukunft auch mal an, denn das
wäre ja mal ein “ordentliches” Projekt.&lt;br /&gt;
Vorerst bleibe ich jedoch bei meinem Adapter-Board, das mir für meine
Zwecke voll ausreicht.&lt;/p&gt;

&lt;p&gt;Und wer es ganz besonders schön haben will, schaut sich Simon’s
Beitrag von &lt;a href=&quot;https://www.kondensatorschaden.de/&quot;&gt;kondensatorschaden.de&lt;/a&gt;
dazu an:&lt;/p&gt;

&lt;iframe width=&quot;640&quot; height=&quot;360&quot; src=&quot;/blog/redirect.html?https%3A%2F%2Fwww.youtube-nocookie.com%2Fembed%2F8Lw8OtKINYE&quot; frameborder=&quot;1&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
</content>
 </entry>
 
 <entry>
   <title>BOOST ptime geht die Zeit aus</title>
   <link href="https://www.opengate.at/blog/2019/10/boost-ptime/"/>
   <published>2019-10-13T12:00:00+02:00</published>
   <updated>2019-10-13T12:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2019/10/boost-ptime</id>
   <category term="devel" />
   <summary type="text">Eigentlich dachte ich, dass die Welt etwas aus dem 
Jahr 2000 gelernt hat.
Mit Argusaugen wurde am 1. Januar
des neuen Jahrtausends beobachtet, ob die IT Welt untergeht.

Passiert ist wenig, es war eher nur die grafische Anzeige weniger Tools,
die schlecht implementiert waren und deshalb versagte.
Und Unices wie Linux stellten 
ohnehin den Anspruch, mit Zeit keine Probleme zu haben.

Und dann taucht im Jahr 2019 folgende Erkenntnis auf:
BOOST posix_time hat Probleme mit 32-bit Überlaufen im Jahr 2038 …
W.T.F. ?
</summary>
   <content type="html">&lt;p&gt;Eigentlich dachte ich, dass die Welt etwas aus dem 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Jahr-2000-Problem&quot;&gt;Jahr 2000&lt;/a&gt; gelernt hat.
Mit &lt;a href=&quot;https://de.wikipedia.org/wiki/Argusaugen&quot;&gt;Argusaugen&lt;/a&gt; wurde am 1. Januar
des neuen Jahrtausends beobachtet, ob die IT Welt untergeht.&lt;/p&gt;

&lt;p&gt;Passiert ist wenig, es war eher nur die grafische Anzeige weniger Tools,
die schlecht implementiert waren und deshalb versagte.&lt;br /&gt;
Und Unices wie &lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt; stellten 
ohnehin den Anspruch, mit Zeit keine Probleme zu haben.&lt;/p&gt;

&lt;p&gt;Und dann taucht im Jahr 2019 folgende Erkenntnis auf:
&lt;code&gt;BOOST posix_time&lt;/code&gt; hat Probleme mit 32-bit Überlaufen im Jahr 2038 …&lt;br /&gt;
W.T.F. ?
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;In C und C++ Bibliotheken haben wir eigentlich ein Schlüsselwort, das alle 
solche Probleme löst, und zwar &lt;code&gt;typedef&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Anstatt einer Dateneinheit einen Typen direkt zuzuordnen wie&lt;br /&gt;
&lt;code&gt;int current_time;&lt;/code&gt;&lt;br /&gt;
nutzen wir korrekterweise:&lt;/p&gt;
&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;typedef&lt;/span&gt; [best_fitting_type] time_type_t;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;...
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;time_type_t current_time;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Und während es in den 80er Jahren eher &lt;code&gt;typedef int32_t time_type_t;&lt;/code&gt; hieß,
sollten wir spätestens seit den Jahr 2000 mit &lt;code&gt;typedef int64_t time_type_t;&lt;/code&gt;
arbeiten.&lt;br /&gt;
Die Betriebssysteme haben das meist auch brav getan (Microsoft ließ ein paar
Funktionen aus Kompatibilität bestehen, führte aber entsprechend neue ein um
das Problem anzugehen).&lt;/p&gt;

&lt;p&gt;Dass jetzt aber ausgerechnet unser Heiland 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Boost_(C%2B%2B-Bibliothek)&quot;&gt;BOOST&lt;/a&gt;
über 15 Jahre später noch 32 Bits in seinen Implementierungen hat, verwundete
mich doch sehr.&lt;/p&gt;

&lt;p&gt;Konkret geht es um &lt;code&gt;BOOST&lt;/code&gt;’s 
&lt;a href=&quot;http://www.boost.org/doc/libs/1_71_0/doc/html/date_time/posix_time.html&quot;&gt;&lt;code&gt;posix_time&lt;/code&gt;&lt;/a&gt;, 
welche bis zur Version 1.66 offenbar
mit 32 bit Typen implementiert war. Erst ab Version 
&lt;a href=&quot;http://www.boost.org/users/history/version_1_67_0.html&quot;&gt;1.67&lt;/a&gt;
sind entsprechende Korrekturen eingearbeitet.&lt;/p&gt;

&lt;p&gt;Tja, nur leider hilft uns das gerade bei älteren Projekten wenig, die auf Grund
von Abhängigkeiten zu älteren Compilern an Versionen vor dem Jahr 2018 gebunden
sind.&lt;/p&gt;

&lt;p&gt;Und die Aussage:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Na dann aktualisieren wir einfach auf eine neuere &lt;code&gt;BOOST&lt;/code&gt; Version.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;zeigt leider, dass &lt;code&gt;BOOST&lt;/code&gt; alles andere als abwärts-kompatibel ist. Vieles muss
dann umgeschrieben werden.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Es gibt Möglichkeiten &lt;code&gt;BOOST&lt;/code&gt; zu “hacken”, sprich den internen Datentypen auf 
&lt;code&gt;int64&lt;/code&gt; zu ändern. Aber wer weiß dann schon, ob nicht an anderen Stellen ein 
Überlauf passiert.&lt;/p&gt;

&lt;p&gt;Ich würde daher versuchen nach Möglichkeit auf &lt;code&gt;BOOST&lt;/code&gt; zu verzichten.&lt;br /&gt;
Denn seit &lt;a href=&quot;https://en.wikipedia.org/wiki/C%2B%2B11&quot;&gt;C++11&lt;/a&gt; haben wir mit 
&lt;a href=&quot;http://www.cplusplus.com/reference/chrono/&quot;&gt;std::chrono&lt;/a&gt; ein standardisiertes
Modul, mit dem man ebenso an die POSIX-Zeit kommt:&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color:#B44;font-weight:bold&quot;&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color:#B44;font-weight:bold&quot;&gt;&amp;lt;chrono&amp;gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; main()
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;auto&lt;/span&gt;&amp;amp;&amp;amp; now = std::chrono::system_clock::now();
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;auto&lt;/span&gt;&amp;amp;&amp;amp; count = now.time_since_epoch();
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;auto&lt;/span&gt;&amp;amp;&amp;amp; seconds = std::chrono::duration_cast&amp;lt;std::chrono::seconds&amp;gt;(count);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;  std::cout &amp;lt;&amp;lt; &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Seconds since epoch: &lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &amp;lt;&amp;lt; seconds.count() &amp;lt;&amp;lt; std::endl;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Und hier haben die Schöpfer etwas besser nachgedacht und generell int64 in der
Implementierung von &lt;code&gt;std::chrono::seconds&lt;/code&gt; und seinen Geschwistern vorgesehen.&lt;/p&gt;

&lt;p&gt;Natürlich ist das auch hier ein Implementierungsdetail, das nicht zwangsläufig
garantiert wird. 8-bit Mikrocontroller könnten hier auch weiter mit &lt;code&gt;int32&lt;/code&gt;
ausgestattet sein … doch das ist schon noch ein bisschen was anderes als 
unsere PC- und Internetwelt, wo wir mit 64 Bit Prozessoren arbeiten und 
Gigabytes von [RAM]https://de.wikipedia.org/wiki/Random-Access_Memory) zur 
Verfügung haben.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Meine Meinung ist und bleibt daher:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Letztendlich gibt es KEINEN wie auch immer gearteten Grund, warum 
Zeiteinheiten (im allgemeinen Fall) mit weniger als 64 Bits implementiert
werden sollten.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;… und im GATE Projekt ist das natürlich auch so implementiert!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Fremdschämen im Fernsehen</title>
   <link href="https://www.opengate.at/blog/2019/10/tv/"/>
   <published>2019-10-12T12:00:00+02:00</published>
   <updated>2019-10-12T12:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2019/10/tv</id>
   <category term="general" />
   <summary type="text">In den Jahren 2000 und 2001 wurde ich mit dem damals noch recht neuen
ersten Privatfernsehsender Österreichs konfrontiert.
Nachdem ich mit dem ORF
aufgewachsen bin, aber schon gelegentlich über das Satellitenprogram diverse
deutschen Sender kannte, dachte ich:


  Naja, das wird jetzt ein sanfteres SAT1 oder RTL werden.


Doch leider gilt wie immer: Nur durch Skandale drängt man sich in 
Ellbogenmanier nach vorne.
</summary>
   <content type="html">&lt;p&gt;In den Jahren 2000 und 2001 wurde ich mit dem damals noch recht neuen
ersten Privatfernsehsender Österreichs konfrontiert.&lt;br /&gt;
Nachdem ich mit dem &lt;a href=&quot;https://de.wikipedia.org/wiki/%C3%96sterreichischer_Rundfunk&quot;&gt;ORF&lt;/a&gt;
aufgewachsen bin, aber schon gelegentlich über das Satellitenprogram diverse
deutschen Sender kannte, dachte ich:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Naja, das wird jetzt ein sanfteres SAT1 oder RTL werden.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Doch leider gilt wie immer: Nur durch Skandale drängt man sich in 
Ellbogenmanier nach vorne.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Zwei Formate aus der damaligen Zeit haben sich bei mir derart negativ
ins Gehirn gebrannt, dass ich sie noch heute teilweise vor Augen habe.&lt;/p&gt;

&lt;p&gt;Und das waren die Talkshow &lt;em&gt;“Speed”&lt;/em&gt; und &lt;em&gt;“Tausche Familie”&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Aber zuvor noch eine andere Rückblende…&lt;/p&gt;

&lt;p&gt;Ich weiß nicht mehr wo ich es gehört habe und wer es zuerst ausgesprochen hat,
doch es gab mal eine Diskussion um die Werte in unserer Gesellschaft. Und da 
meinte ein Diskutant in etwa:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Es hat mit der Serie &lt;a href=&quot;https://de.wikipedia.org/wiki/Dallas_(Fernsehserie,_1978)&quot;&gt;Dallas&lt;/a&gt;
begonnen. Das war unter den biederen Sendungen damals eine der ersten, 
wo klar zu erkennen war, dass “der Böse” die nachzueifernde 
Hauptfigur ist. Machtgier, Reichtum und herabwürdigendes Verhalten wurde
“sexy” dargestellt und nie mit Strafe oder Gerechtigkeit aufgewogen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Und die Aussage hat was. Nachdem wir lange mit überkorrekten Familienvätern
und brav hinter’m Herd stehenden Hausfrauen medial bespielt wurden, kam eine
neue Generation von Negativ-Helden auf, in der Betrügereien als straffreier 
Normalfall abgedreht wurden.&lt;/p&gt;

&lt;p&gt;Und wie setzte man im Jahr 2000 hier nochmals eins drauf?&lt;/p&gt;

&lt;h3 id=&quot;speed&quot;&gt;Speed&lt;/h3&gt;

&lt;p&gt;Die von &lt;a href=&quot;https://de.wikipedia.org/wiki/Hademar_Bankhofer_(Moderator)&quot;&gt;Hatschi Bankhofer&lt;/a&gt;
moderierte Talkshow ist so ziemlich das niveauloseste, was ich jemals gesehen
hatte. Und leider galt auch hier:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Es ist so schrecklich, ich kann gar nicht wegsehen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Jugendliche zwischen 13 und 19 Jahren wurde mit skurrilen Vorlieben, schrägen
Meinungen und vor allem mit vielen derben Wortmeldungen vorgeführt und das
gleichaltrige Publikum wurde nach amerikanischen Vorbild angestachelt die 
Wortgefechte immer weiter aufzuheizen.&lt;/p&gt;

&lt;p&gt;Es war wohl eine Zielsetzung im Minutentakt Wörter wir “Titten”, “Schwanz”
und “Ficken” immer wieder einzustreuen, um zu demonstrieren, um wie viel mehr 
man sich gegenüber öffentlich-rechtlichen Sendungen noch herausnehmen konnte.&lt;/p&gt;

&lt;p&gt;Als Österreicher schäme ich mich in Grund und Boden dafür, dass es gelungen 
ist, das ohnehin tiefe Niveau deutscher Talkshows noch um einige Etagen tiefer
zu legen um so einen Negativrekord aufstellen zu können.&lt;/p&gt;

&lt;p&gt;Neulich sind mir auf &lt;a href=&quot;https://www.youtube.com/&quot;&gt;YouTube&lt;/a&gt; wieder einige dieser
alten Folgen “begegnet” und ich kann nur sagen, wie froh ich bin, dass außer
dieser letzten Reste nichts weiteres von dieser Sendung mehr geblieben ist.&lt;/p&gt;

&lt;h3 id=&quot;tausche-familie&quot;&gt;Tausche Familie&lt;/h3&gt;

&lt;p&gt;Eine der ersten Episoden dieser Serie, in der meist zwei Frauen zweier Familien
für eine Woche ausgetauscht wurden, sorgte in meinem Heimatland für eine 
breite Diskussion in den Medien bis hin zum örtlichen Stammtisch.&lt;/p&gt;

&lt;p&gt;Denn hier wurde (wohl absichtlich) eine junge Frau einer türkischen Familie
mit dem proletoiden Gegenstück einer mehr als rassistischen Familie in Wien 
in Szene gesetzt.&lt;/p&gt;

&lt;p&gt;Alleine die Gesichtsausdrücke aber erst recht die beschämende Sprache 
“meiner Landsleute” ist vermutlich die extremste Zurschaustellung von offenem
Fremdenhass in Österreich seit den 40er Jahren gewesen.&lt;/p&gt;

&lt;p&gt;Sogar in Büros und an allen anderen Arbeitsplätzen war die Ausstrahlung der 
Sendung Thema Nummer 1.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Sind wir so?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;War die korrekte Frage damals. Und:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Nein, nein, wir doch nicht!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;die verlogene Antwort darauf.&lt;/p&gt;

&lt;p&gt;Dieser Eklat wurde zwar bewusst “produziert” um damit möglichst
viele Schlagzeilen zu machen, doch jene rassistische Familie hatte kein 
Drehbuch, sondern redete einfach frei heraus.&lt;/p&gt;

&lt;p&gt;Genau diese extremen Darstellungen haben den Effekt, dass wir mehr und 
mehr verrohen. Wir (und vor allem die nächste Generation) nehmen uns dann 
alle kein Blatt mehr vor dem Mund, weil wir ja “im Fernsehen” gesehen haben, 
dass es eh in Ordnung geht, wenn man seine Gehässigkeit einfach auslebt.&lt;/p&gt;

&lt;p&gt;Und was war die Konsequenz?&lt;br /&gt;
ATV hatte traumhafte Zuseherzahlen und eine türkische Frau durfte eine Woche 
lang sprichwörtlich durch die Hölle gehen …&lt;/p&gt;

&lt;iframe width=&quot;640&quot; height=&quot;360&quot; src=&quot;/blog/redirect.html?https%3A%2F%2Fwww.youtube-nocookie.com%2Fembed%2FFlMJq-2TPzM&quot; frameborder=&quot;1&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Das Schlimme ist, dass diese Bilder von den meisten Menschen wieder vergessen 
wurden. Doch der Inhalt hat sich unterbewusst manifestiert und eine Vielzahl 
von Folgeserien mit ähnlich niedrigem Niveau produziert.&lt;/p&gt;

&lt;p&gt;Es ist natürlich Blödsinn zu behaupten, dass deshalb gleich “die Gesellschaft”
ins Wanken gerät, aber eines steht für mich fest: Geholfen haben diese 
Exzesse nicht uns weiterzubringen.&lt;/p&gt;

&lt;p&gt;Und es entsetzt mich in diesen Spiegel blicken zu müssen, der mir aufzeigt,
dass wir nicht die feinen freundlichen liebenswerten Weltretter sind, als die
wir uns gerne aufspielen, sondern dass das perverse Nazischwein tief 
gesellschaftlich in uns verankert ist.&lt;/p&gt;

&lt;p&gt;Und um abschließend ein lustiges abgewandeltes Zitat aus dem Film 
&lt;a href=&quot;https://en.wikipedia.org/wiki/Trainspotting_(film)&quot;&gt;Trainspotting&lt;/a&gt; zu bringen:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Es tut jedem gut, mal die Sau rauszulassen.&lt;/p&gt;

  &lt;p&gt;Nein, dem Typen würde es gut tun die Sau festzubinden.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;… und das sollten einige Medienmacher auch mal beherzigen!
Hoffentlich bleiben der Bevölkerung weitere solche Produktionen erspart.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>CONAN der Erfolg-Zerstörer</title>
   <link href="https://www.opengate.at/blog/2019/10/conan-fail/"/>
   <published>2019-10-06T13:00:00+02:00</published>
   <updated>2019-10-06T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2019/10/conan-fail</id>
   <category term="software" />
   <summary type="text">Wenn man in der CONAN Build Pipeline folgenden 
Fehler sieht:


  ‘NoneType’ object has no attribute ‘token’


so ahnt man noch nicht, dass einem das letztendlich den Tag
versauen wird.
</summary>
   <content type="html">&lt;p&gt;Wenn man in der &lt;a href=&quot;http://conan.io/&quot;&gt;&lt;code&gt;CONAN&lt;/code&gt;&lt;/a&gt; Build Pipeline folgenden 
Fehler sieht:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;‘NoneType’ object has no attribute ‘token’&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;so ahnt man noch nicht, dass einem das letztendlich den Tag
versauen wird.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Meine Firma möchte nun weiter Projekte auf &lt;code&gt;CONAN&lt;/code&gt; migrieren und somit wird 
einiges an Ressourcen in diese ehrgeizige Ziel investiert.&lt;br /&gt;
Und nun, wo die ersten Erfolge hergezeigt werden können, freut man sich
über die angewendete Änderung des Buildsystems.&lt;/p&gt;

&lt;p&gt;Und dann tauchen plötzlich Fehler auf, die sich niemand erklären kann.&lt;/p&gt;

&lt;h3 id=&quot;voraussetzungen&quot;&gt;Voraussetzungen&lt;/h3&gt;

&lt;p&gt;Bibliotheken wie die ZLIB werden angenehmerweise schon im Internet 
fix fertig als &lt;code&gt;CONAN&lt;/code&gt; Paket angeboten. Folglich setzt man eine Abhängigkeit zur
externen Quelle des Softwarepaketes.&lt;/p&gt;

&lt;p&gt;Wenn ein Build-Prozess läuft, lädt &lt;code&gt;CONAN&lt;/code&gt; die neuen Sourcen und Binaries
aus dem Internet und integriert sie als Includes für die Kompilierung
und das Linken des Projektes.&lt;/p&gt;

&lt;p&gt;So die Theorie, die bis vor Kurzem auch gelebte Praxis war.
Doch mit der neuen Fehlermeldung &lt;code&gt;&apos;NoneType&apos; object has no attribute &apos;token&apos;&lt;/code&gt; 
war dies wohl nicht mehr so.&lt;/p&gt;

&lt;h3 id=&quot;das-problem&quot;&gt;Das Problem&lt;/h3&gt;

&lt;p&gt;Nach langem Herumexperimentieren ohne Erfolg, startete ich eine Suche im 
Internet. Und siehe dar, auch andere Menschen (wenn auch wenige) meldeten
Problem mit &lt;code&gt;CONAN&lt;/code&gt; beim Zugriff auf externe Quellen.&lt;/p&gt;

&lt;p&gt;Und nach vielen vielen gelesenen Beiträgen, poppte plötzlich die Meldung auf,
dass dieses Problem an HTTP Umleitungen liegt.&lt;/p&gt;

&lt;p&gt;Ja, ernsthaft … &lt;code&gt;CONAN&lt;/code&gt; kommt mit &lt;a href=&quot;https://en.wikipedia.org/wiki/HTTP_301&quot;&gt;HTTP 301/302&lt;/a&gt;
Statuscodes nicht klar.&lt;br /&gt;
Und offenbar haben die Server-Betreiber unseres &lt;code&gt;CONAN&lt;/code&gt; Paketes neulich eine 
solche Umleitung gesetzt.&lt;/p&gt;

&lt;p&gt;Jetzt wird natürlich stets dazu geraten, sofort die neueste Version von
&lt;code&gt;CONAN&lt;/code&gt; zu installieren, da laufend Fehlerchen dieser Art korrigiert werden,
doch das ist im Firmennetzwerk nicht so einfach.&lt;br /&gt;
Wer kennt nicht die bürokratischen Hürden einer Konzernstruktur, wenn 
man “ganz schnell” ein Softwareupgrade einführen möchte.&lt;/p&gt;

&lt;h3 id=&quot;die-lösung&quot;&gt;Die Lösung&lt;/h3&gt;

&lt;p&gt;Für uns gibt es momentan keine Lösung. Doch wir nutzten einen Workaround.&lt;/p&gt;

&lt;p&gt;Die betroffenen &lt;code&gt;CONAN&lt;/code&gt; Pakete wurden mit dem Browser heruntergeladen und
manuell mit allen Sourcen in unser eigenes &lt;a href=&quot;http://jfrog.com/&quot;&gt;jFrog&lt;/a&gt;
Repository hochgeladen.&lt;/p&gt;

&lt;p&gt;Anstatt die Daten aus dem Netz zu laden, laden wir sie von unseren eigenen
Servern beim Buildprozess herunter. Und da hier keine HTTP Umleitung erzwungen
wird, hat auch &lt;code&gt;CONAN&lt;/code&gt; kein Problem damit.&lt;/p&gt;

&lt;p&gt;Dazu muss am Ende nur die Paket-Abhängigkeit von z.B.:
&lt;code&gt;zlib/1.2.11@conan/stable&lt;/code&gt;&lt;br /&gt;
auf&lt;br /&gt;
&lt;code&gt;zlib/1.2.11@our-server-id/stable&lt;/code&gt;&lt;br /&gt;
gesetzt werden.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Gefahr erkannt, Gefahr gebannt.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Nur besonders zufrieden stimmt mich der Sachverhalt nicht.&lt;/p&gt;

&lt;p&gt;HTTP Umleitungen werden gerne bei der Programmierung vergessen
(ist mir ja auch schon passiert), und dann kommt es zu Abbrüchen,
die schwer nachvollziehbar werden.&lt;/p&gt;

&lt;p&gt;Ich kann daher nur empfehlen, bei der Nutzung von HTTP Bibliotheken
immer nach der Konfiguration zu sehen, ob Redirection automatisch
behandelt werden oder nicht.&lt;/p&gt;

&lt;p&gt;Und die &lt;code&gt;CONAN&lt;/code&gt; Entwickler werden dieses Problem hoffentlich bald
gelöst haben und einen Patch oder ein neues Release ausrollen.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Ein Jahr Blog</title>
   <link href="https://www.opengate.at/blog/2019/10/one-year/"/>
   <published>2019-10-05T12:00:00+02:00</published>
   <updated>2019-10-05T12:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2019/10/one-year</id>
   <category term="general" /><category term="projects" />
   <summary type="text">Vor einem Jahr startete also mein Online-Tagebuch. Und wie bei jedem guten
Vorsatz funktioniert es am Anfang wie geschmiert … und dann … ja dann …
</summary>
   <content type="html">&lt;p&gt;Vor einem Jahr startete also mein Online-Tagebuch. Und wie bei jedem guten
Vorsatz funktioniert es am Anfang wie geschmiert … und dann … ja dann …
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Wenn man bedenkt, dass sich 2019 mein Berufsweg dann doch ganz anders 
entwickelt hat als geplant, freut es mich, dass ich den Blog nicht gleich
wieder aufgeben musste.&lt;/p&gt;

&lt;p&gt;Ich hatte mir mit Beginn des Jahres vorgenommen in jedem Monate ein 
bisschen was zu schreiben und das ist großteils geglückt.
Dass es nicht mehr ein Beitrag pro Tag werden wird, war mir natürlich klar,
denn so viel passiert mir jetzt auch wieder nicht, dass ich jeden Tag damit
Seiten füllen kann.&lt;/p&gt;

&lt;p&gt;Leid tut mir, dass das OpenGATE Projekt nun nur noch auf kleinerer Flamme
vorangetrieben wird, … doch es wird vorangetrieben.
Vor allem fehlt es nun an einem geordneten Zeitplan, und so wird stets
das implementiert, das ich aus aktuellen Gründen gerade brauche.&lt;/p&gt;

&lt;p&gt;Ich bin aber zuversichtlich, dass sich mit der Zeit auch wieder mehr 
Themen für die Entwicklung und Weiterführung des GATE Projektes finden
werden.&lt;br /&gt;
Meine Favoriten wären da natürlich Treiber- und Netzwerkdienste, doch
gerade die benötigen etwas mehr Aufmerksamkeit und sind nicht in 10
Minuten am Abend geschrieben.&lt;/p&gt;

&lt;p&gt;Inzwischen läuft der Build des GATE Frameworks auch regelmäßig auf
&lt;a href=&quot;https://de.wikipedia.org/wiki/Bitbucket&quot;&gt;Bitbucket&lt;/a&gt; und scheitert dort auch 
ständig an der fehlenden &lt;a href=&quot;https://de.wikipedia.org/wiki/GTK_(Programmbibliothek)&quot;&gt;GTK&lt;/a&gt; 
Unterstützung. Womit wir schon beim größten Release-Problem des Projektes 
wären:&lt;br /&gt;
&lt;em&gt;Der GTK Linux Build.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Dieser liegt noch weit hinter der Windows-Entwicklung zurück und sollte
meine höchste Priorität sein. Doch da ich selbst großteils unter Windows
arbeite ist meine private Notwendigkeit des Linux-Builds eben sehr gering.&lt;/p&gt;

&lt;p&gt;Eine andere schwierige Hürde in der GATE Entwicklung stellt für mich die
Festlegung auf &lt;a href=&quot;https://de.wikipedia.org/wiki/Varianten_der_Programmiersprache_C#C89,_C90&quot;&gt;C90&lt;/a&gt; 
dar. Ich habe doch sehr unterschätzt wie mühsam der Aufbau von komplexeren 
Strukturen in reinem C ist, was mit &lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B&quot;&gt;C++&lt;/a&gt; 
in wenigen eleganten Zeilen möglich ist.&lt;br /&gt;
Dennoch bleibe ich bei der Zielvorstellung, dass C die primäre Basis bleibt.
Und der Wunsch in Richtung Treiber Entwicklung zu gehen bestätigt diese 
Entscheidung.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;In diesem Sinne bin ich schon gespannt, ob 2020 einige Ziele des Projektes
abgeschlossen werden können und ein stabiles Release möglich sein wird.&lt;/p&gt;

&lt;p&gt;Und ebenso freue ich mich, dass meine Selbst-Dokumentation im Blog mir auch 
bei der täglichen Arbeit hilft, wo ich dann nachschlagen kann, wie ich 
Problem X oder Y schon einmal gelöst habe.&lt;/p&gt;

&lt;p&gt;Hoffentlich läuft alles weiter so gut, damit ich nächstes Jahr um diese
Zeit wieder eine kurze Zusammenfassung zu allem schreiben kann.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Nationalratswahl 2019</title>
   <link href="https://www.opengate.at/blog/2019/09/voting/"/>
   <published>2019-09-29T22:19:00+02:00</published>
   <updated>2019-09-29T22:19:00+02:00</updated>
   <id>https://www.opengate.at/blog/2019/09/voting</id>
   <category term="general" />
   <summary type="text">Nachdem in Österreich offenbar wöchentlich schwere Verfehlungen von
Spitzenpolitikern erfolgen und keine Regierung mehr ihre Legislaturperiode
zu erfüllen vermag, tun wir das, was man dann eben tut:

Wir gehen eine neue Regierung wählen.
</summary>
   <content type="html">&lt;p&gt;Nachdem in Österreich offenbar wöchentlich schwere Verfehlungen von
Spitzenpolitikern erfolgen und keine Regierung mehr ihre Legislaturperiode
zu erfüllen vermag, tun wir das, was man dann eben tut:&lt;/p&gt;

&lt;p&gt;Wir gehen eine neue Regierung wählen.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Und somit bekomme ich nun 3 Jahre früher als geplant wieder die Chance
den Wahlvorgang in Wien in einem Sprengel zu “beobachten” bzw. diesem
“beizusitzen”.&lt;/p&gt;

&lt;p&gt;Den Wahlbeisitzern und Ersatzbeisitzern wird empfohlen, sich rechtzeitig
eine Wahlkarte zu besorgen, weil sie ja nicht zwingend in dem Wahllokal
sitzen, in welchem sie selbst wählen dürfen.&lt;/p&gt;

&lt;p&gt;Diesmal war es bewusst sehr leicht gestaltet, eine solche Briefwahlkarte
zu bestellen. Das ging wie immer online auf den Seiten der Stadtverwaltung,
doch zusätzlich trudelte in jedem Haushalt ein “Bestellbrief” ein, den man
nur ausfüllen und kostenlos zurückschicken musste um eine Briefwahlkarte 
wenige Tage später zugeschickt zu bekommen.&lt;/p&gt;

&lt;p&gt;Und so kam es, dass eine Million Menschen - so viele wie noch nie zuvor - 
diesmal eine Briefwahlkarte beantragt hatten.&lt;/p&gt;

&lt;p&gt;Der Ablauf im Wahllokal war ganz ähnlich zu dem der &lt;a href=&quot;/blog/2019/05/europe/&quot;&gt;EU-Wahl&lt;/a&gt;.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Ab 6:15 Uhr trafen sich Beisitzer und Wahlleiter im Wahllokal.&lt;/li&gt;
  &lt;li&gt;Die vorbereiteten Stimmzettel wurden durchgezählt und dokumentiert.&lt;/li&gt;
  &lt;li&gt;Die vorbereiteten Wahlkuverts wurden durchgezählt und dokumentiert.&lt;/li&gt;
  &lt;li&gt;Die Wählerlisten wurden zu gleichen Teilen auf die Beisitzer verteilt.&lt;/li&gt;
  &lt;li&gt;Der Wahlleiter gab allgemeine Informationen zu den Abläufen bekannt.&lt;/li&gt;
  &lt;li&gt;Und die Beisitzer wurden vereidigt, ihre Aufgaben korrekt und unparteiisch
zu erfüllen.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Und so öffnete ab 7:00 Uhr für 10 Stunden lang unser Lokal und freute sich 
auf alle eintreffenden Personen, die zu uns kamen um ihre Stimmen abzugeben.&lt;/p&gt;

&lt;p&gt;In 2 Fällen musste diesmal mit der Wahlbehörde telefonisch der Ablauf geklärt
werden.&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;In einem Fall hatte ein Wähler eine Briefwahlkarte beantragt, welche nicht
persönlich zugestellt werden konnte und auch nicht am Postamt abgeholt wurde.
Diese Karte wurde daher wieder zur Wahlbehörde zurückgeschickt.
Nun kann ein solcher Wähler aber nicht einfach in sein Lokal gehen und dort
“normal” wählen, sondern muss zur Behörde fahren und dort die für ihn
bestimmte Briefwahlkarte nutzen.&lt;/li&gt;
  &lt;li&gt;Und in einem anderen Fall hatte sich die Wohnadresse eines Wählers geändert
(und das vermutlich mehrfach), denn für das Wahllokal gilt die Wohnadresse 
eines Stichtages, der Monate vor der Wahl festgelegt wird.
Auch in diesem Fall konnte die Datenänderung mit der Behörde geklärt werden
und die Wahl regulär durchgeführt werden.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ansonsten lief alles genau nach Routine ab.&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Wähler kommt ins Lokal&lt;/li&gt;
  &lt;li&gt;Er zeigt seine Wahl-Einladung mit seiner Wählernummer vor oder nennt seinen 
Namen, anhand dessen seine Nummer nachgeschlagen werden kann.&lt;/li&gt;
  &lt;li&gt;Es erfolgt die Prüfung eines Personalausweises und die Notierung der Daten 
darauf.&lt;/li&gt;
  &lt;li&gt;Nun wird in der Wählerliste eine fortlaufende Nummer eingetragen und 
überprüft, ob für den Wähler nicht schon eine Briefwahlkarte versendet 
wurde.&lt;/li&gt;
  &lt;li&gt;Und wenn alles korrekt war, erhält der Wähler seinen Stimmzettel samt Kuvert.&lt;/li&gt;
  &lt;li&gt;Dieser kann nun in der Wahlkabine seine Kreuzchen machen.&lt;/li&gt;
  &lt;li&gt;Und am Ende wird die abgegebene Stimme in die versiegelte Wahlurne 
eingeworfen.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Also alles nach Vorschrift.&lt;br /&gt;
Und ob diese Vorschriften auch eingehalten werden, prüften ein paar mal 
Mitarbeiter der Wahlbehörde persönlich nach.&lt;/p&gt;

&lt;p&gt;Ab 17:00 Uhr wurde das Lokal geschlossen und die Wahlurne geöffnet.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Zuerst wurden alle geschlossenen Wahlkuverts durchgezählt und festgestellt,
dass exakt so viele vorhanden waren, wie in den Listen Wählerstimmen eingetragen
wurden (also die höchste fortlaufende Nummer).&lt;/li&gt;
  &lt;li&gt;Nun wurden die Kuverts geöffnet und nach Parteien bzw. Ungültigkeit sortiert.
Diese Zählung erfolgte mehrfach durch unterschiedliche Beisitzer um 
sicherzustellen, dass keine Stimme falsch zugeordnet wurde.&lt;/li&gt;
  &lt;li&gt;Der etwas mühsamere Teil lag dann bei der Auszählung der Vorzugsstimmen.
Denn hier kommt ein Kandidat auf Bundesebene, einer auf Landesebene und
einer auf Regionalebene entweder per Namen, per Kandidatennummer oder per
Ankreuzen gewählt werden.&lt;br /&gt;
Und nachdem es recht viele Vorzugsstimmen gab, dauerte es entsprechend
lange, bis diese Infos alle erfasst, in den Kandidatenkatalogen nachgeschlagen
und per Strichliste hochgezählt werden konnte.&lt;/li&gt;
  &lt;li&gt;Am Ende wurde noch sichergestellt, dass die Summen der sortierten Stimmzettel
und die Menge leeren Kuverts mit den Ausgangsdaten übereinstimmten.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Es erinnerte mich etwas an ein “Zeugnis schreiben” in der Schule, als unser
Wahlleiter alle Endergebnisse in amtliche Dokumente eintragen musste, die wir
als Beisitzer final unterschreiben durften.&lt;/p&gt;

&lt;p&gt;Die Stimmzettel wurden letztlich alle in große Kuverts gesteckt und versiegelt.
Und damit ging auch für mich ein langer Wahltag zu Ende.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ich freue mich auch wieder etwas “für die Demokratie” getan zu haben.&lt;br /&gt;
Auch wenn mich der Ausgang der Wahl mit Unsicherheit zurücklässt.
Es mag ein Jammern auf hohem Niveau sein, aber die letztliche politische
Instabilität in meinem Land stimmt mich nachdenklich.&lt;br /&gt;
Anstatt Gemeinsamkeiten zu finden, wird mehr und mehr das Trennende 
hervorgestrichen und es werden noch im Wahlkampf Barrikaden errichtet,
die künftige Koalitionen deutlich erschweren, oder die die sprechenden
Politiker als vorlaute Kinder darstellen, wo es egal ist, was sie 
letztendlich sagen.&lt;/p&gt;

&lt;p&gt;Was ist aus unserer Sozialpartnerschaft geworden, die einst aus 
einem kleinen Land wie Österreich einen wirtschaftlich erfolgreichen 
Staat machte?&lt;/p&gt;

&lt;p&gt;Anstatt dessen treten bröckchenweise Korruptionsfälle und unanständige
Großspenden ans Tageslicht, die WIR Österreicher in anderen Teilen der 
Welt gerne als Anzeichen einer “Bananenrepublik” deuten.&lt;/p&gt;

&lt;p&gt;Trotzdem habe ich den Wahltag mit meinem Kollegen im Lokal jedenfalls 
genossen, musste aber gleichzeitig anmerken:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ich hoffe, wir sehen uns nicht so bald bei der nächsten Wahl wieder.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Es bleibt abzuwarten, ob wir es diesmal schaffen, die von der Verfassung
bezeichneten 5 Jahre einer Legislaturperiode ohne weitere Skandale zu
überstehen …&lt;/p&gt;

&lt;p&gt;… die Hoffnung stirbt zuletzt.&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>dynamic_cast</title>
   <link href="https://www.opengate.at/blog/2019/09/dynamic_cast/"/>
   <published>2019-09-24T12:00:00+02:00</published>
   <updated>2019-09-24T12:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2019/09/dynamic_cast</id>
   <category term="devel" />
   <summary type="text">Liebes Tagebuch.
Heute hat sich folgendes Gespräch ergeben:


  Im letzten Release hat es noch funktioniert, aber seit deiner
Änderung gibt es einen Fehler.



  Kann nicht sein, ich habe den Code nur ein bisschen verbessert, 
sonst wurde nichts verändert.


</summary>
   <content type="html">&lt;p&gt;Liebes Tagebuch.&lt;br /&gt;
Heute hat sich folgendes Gespräch ergeben:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Im letzten Release hat es noch funktioniert, aber seit deiner
Änderung gibt es einen Fehler.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;Kann nicht sein, ich habe den Code nur ein bisschen verbessert, 
sonst wurde nichts verändert.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Ich habe mal eine interessante Aussage zu den &lt;code&gt;*_cast&lt;/code&gt; Routinen in 
&lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B&quot;&gt;C++&lt;/a&gt; gelesen, die beinhaltete:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;code&gt;static_cast&lt;/code&gt;, &lt;code&gt;dynamic_cast&lt;/code&gt;, &lt;code&gt;const_cast&lt;/code&gt; und &lt;code&gt;reinterpret_cast&lt;/code&gt; sind nur 
deshalb so umständlich lange und hässlich ausformuliert worden, damit
C++ Programmierer sie so selten wie möglich nutzen … schließlich
sollten casts in der objektorientierten Programmierung eigentlich 
gar nicht mehr notwendig sein.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Tja … dieser Schuss ist dann aber gehörig nach hinten losgegangen.&lt;/p&gt;

&lt;p&gt;Denn viele C++ Programmierer nutzen nun die kürzeren C-style-Casts.&lt;br /&gt;
Und die sind deshalb so übel, weil der Compiler je nach Fall einen der 
obigen Casts daraus ableitet, wobei deren Bedeutung unterschiedlich
sein kann.&lt;/p&gt;

&lt;p&gt;Bei Zahlen bedeutet ein C-Cast meist einen &lt;code&gt;static_cast&lt;/code&gt;, bei Zeigern
kommt aber oft ein &lt;code&gt;reinterpret_cast&lt;/code&gt; am Ende heraus.&lt;br /&gt;
Das wirklich üble dabei: Es kompiliert immer und erzeugt (meist) keine 
Warnungen, wenn Datentypen “seltsam” interpretiert werden.&lt;/p&gt;

&lt;h3 id=&quot;reinterpret-vs-dynamic&quot;&gt;reinterpret vs. dynamic&lt;/h3&gt;

&lt;p&gt;Neulich hatte ich so einen lustigen Fall, wo obiges Gespräch dabei herauskam.
Tatsächlich hatte ich bei bestehenden Codes die C-Casts durch entsprechende
C++-Casts ersetzt, und in erste Linie auf das Abfangen von NULL-Pointer 
abgezielt.&lt;br /&gt;
Der hinzugefügte &lt;code&gt;dynamic_cast&lt;/code&gt; bei einem &lt;a href=&quot;https://en.cppreference.com/w/cpp/memory/shared_ptr&quot;&gt;Shared-Pointer&lt;/a&gt;
auf ein Basis-Klassen-Interface, wo eine spezielle Methode einer speziellen
Ableitung notwendig war, war einfach als eine “Draufgabe” von mir gedacht, 
so wie es das Lehrbuch verlangt hatte.&lt;/p&gt;

&lt;p&gt;Hmm, und nun läuft produktive Software nicht mehr richtig, weil 
der &lt;code&gt;dynamic_cast&lt;/code&gt; einen Null-Pointer liefert, der erkannt wird und
aus Sicherheit mit einer Fehlermeldung abgebrochen wird.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Warum hat es also früher funktioniert?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In dieser Software gibt es viele unterschiedliche Ableitungen eines
Basis-Interfaces, die alle sehr unterschiedlich sind. Doch zwei bestimmte 
Ableitungen sind im Code (und eigentlich auch binär-) identisch, sie sollen 
aber zwei unterschiedliche Zustände ausdrücken.&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;try&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;switch&lt;/span&gt;(state)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  {
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;case&lt;/span&gt; state_1:
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;    {
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;      ((derived_type1_t*)data)-&amp;gt;do_something();
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;break&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;        }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;case&lt;/span&gt; state_2:
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;    {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;      ((derived_type2_t*)data)-&amp;gt;do_something();
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;break&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;        }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;  }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;}
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;catch&lt;/span&gt;(...)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Mein Änderung sah dann so aus:&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;try&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;switch&lt;/span&gt;(state)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  {
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;case&lt;/span&gt; state_1:
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;    {
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;      derived_type1_t* mydata = &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;dynamic_cast&lt;/span&gt;&amp;lt;derived_type1_t*&amp;gt;(data);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;          &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt;(!mydata) &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;throw&lt;/span&gt; std::runtime_error(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Invalid data&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;      mydata-&amp;gt;do_something();
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;      &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;break&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;        }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;case&lt;/span&gt; state_2:
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;    {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;      derived_type2_t* mydata = &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;dynamic_cast&lt;/span&gt;&amp;lt;derived_type2_t*&amp;gt;(data);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt;(!mydata) &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;throw&lt;/span&gt; std::runtime_error(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Invalid data&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;      mydata-&amp;gt;do_something();
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;break&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;        }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;  }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;}
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n21&quot; name=&quot;n21&quot;&gt;21&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;catch&lt;/span&gt;(...)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n22&quot; name=&quot;n22&quot;&gt;22&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n23&quot; name=&quot;n23&quot;&gt;23&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Kurz zusammengefasst: Der Ersteller der &lt;code&gt;data&lt;/code&gt;-Instanz hat in allen Fällen 
immer nur &lt;code&gt;derived_type1_t&lt;/code&gt; benutzt. Der frühere C-style Cast wurde
zu einem &lt;code&gt;reinterpret_cast&lt;/code&gt;, der nur aus Gottes Gnaden und durch Zufall
funktioniert hat, weil &lt;code&gt;derived_type1_t&lt;/code&gt; and &lt;code&gt;derived_type2_t&lt;/code&gt; gleich 
aufgebaut waren.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Das Schlimme dabei ist, dass schon darüber diskutiert wurde die korrekte 
Änderung (ja, sie war korrekter!) von mir wieder zurückzunehmen, weil 
eine Änderung des Ursprungscodes in einer anderen Abteilung hätte durchgeführt
werden müssen und offenbar “schwer umsetzbar” gewesen wäre.&lt;/p&gt;

&lt;p&gt;Um das zu verhindern erlaubte ich in beiden Fällen einfach beide Datentypen.
Geht der eine nicht, wird der zweite probiert.&lt;/p&gt;

&lt;p&gt;Hoffentlich kommt jetzt morgen nicht die Meldung, dass noch ein dritter
(ebenso unkorrekter) Datentyp zurückkommen kann …&lt;/p&gt;

&lt;p&gt;Tja, und deshalb sehe ich mich gezwungen stets neunmalklug immer und immer
wieder zur wiederholen:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Wenn von einer Basisklasse mit mindestens einer virtuellen Methode auf
eine Ableitung gecastet werden soll, MUSS das immer über einen abgesicherten
&lt;code&gt;dynamic_cast&lt;/code&gt; erfolgen, damit man Typenfehler korrekt erkennen kann.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ach ja, und noch viel wichtiger ist folgender Merksatz.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Bugs sind IMMER an ihrer Wurzel zu fixen und sollen nicht per Workaround 
drei Ebenen weiter zaghaft entschärft werden müssen!&lt;/p&gt;
&lt;/blockquote&gt;

</content>
 </entry>
 
 <entry>
   <title>NanoPi Neo | oeN iPonaN</title>
   <link href="https://www.opengate.at/blog/2019/09/nano-pi-neo/"/>
   <published>2019-09-22T12:00:00+02:00</published>
   <updated>2019-09-22T12:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2019/09/nano-pi-neo</id>
   <category term="hardware" />
   <summary type="text">Es ist schon ein bisschen sehr blöd, wenn zwei Revisionen eines 
System-on-Chip Models die 
PIN-Belegung spiegeln.

Und nachdem ich jetzt ein paar Kurzschlüsse am seriellen Port
produziert habe, fällt mir natürlich auch ein, dass ich schon beim ersten 
Arbeiten mit meinem NanoPI NEO dieses 
Problem hatte …
</summary>
   <content type="html">&lt;p&gt;Es ist schon ein bisschen sehr blöd, wenn zwei Revisionen eines 
&lt;a href=&quot;https://de.wikipedia.org/wiki/System-on-a-Chip&quot;&gt;System-on-Chip&lt;/a&gt; Models die 
PIN-Belegung spiegeln.&lt;/p&gt;

&lt;p&gt;Und nachdem ich jetzt ein paar Kurzschlüsse am &lt;a href=&quot;https://de.wikipedia.org/wiki/Serielle_Schnittstelle&quot;&gt;seriellen Port&lt;/a&gt;
produziert habe, fällt mir natürlich auch ein, dass ich schon beim ersten 
Arbeiten mit meinem &lt;a href=&quot;http://nanopi.io/nanopi-neo.html&quot;&gt;NanoPI NEO&lt;/a&gt; dieses 
Problem hatte …
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Endlich bekommt also mein Nano-PI wieder eine Aufgabe und dafür wird er zuerst
mit einem neuen &lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt; Image ausgestattet.&lt;/p&gt;

&lt;p&gt;Wird das Gerät dann mit der aktualisierten SD-Karte zum ersten mal gestartet, 
sollte ein TTL-Serial-Adapter angeschlossen sein, der die Ausgabe auf den PC
überträgt, damit &lt;a href=&quot;http://putty.org/&quot;&gt;Putty&lt;/a&gt; oder &lt;a href=&quot;https://mobaxterm.mobatek.net/&quot;&gt;MobaXterm&lt;/a&gt;
diesen anzeigen kann.&lt;/p&gt;

&lt;p&gt;Laut Datenblatt des NanoPI Neo sind die Pins des Debug
&lt;a href=&quot;https://de.wikipedia.org/wiki/Universal_Asynchronous_Receiver_Transmitter&quot;&gt;UART&lt;/a&gt;
Ports …&lt;br /&gt;
… ja wo sind sie?&lt;/p&gt;

&lt;p&gt;Das Bild zeigte nicht so ganz meinen Chip, doch er sah recht ähnlich aus.&lt;/p&gt;

&lt;p&gt;Ich vermutete also, dass ich ein älteres Release dieses Modells habe, das
geringfügig anders konfiguriert ist, aber ansonsten mit der gleichen 
(gleichwertigen) Hardware bestückt wurde.&lt;/p&gt;

&lt;p&gt;Die Pins des Debug-Serial-Ports schienen auf meinem Board ein paar Millimeter 
versetzt zu sein, also schloss ich 5V, GND, TX, und RX an jener Stelle mit 
der gleichen Pinbelegung an, wie es im Beispielbild etwas versetzt gezeigt 
wurde.&lt;/p&gt;

&lt;p&gt;Beim Anschließen des USB-UART-Konverters erkannte Windows diesen auf 
COM-Port-7 und ich konnte &lt;code&gt;Putty&lt;/code&gt; starten und entsprechend konfigurieren.&lt;/p&gt;

&lt;p&gt;Doch als ich den NanoPI mit Strom versorgte, ging das virtuelle COM-Port Gerät
plötzlich verloren und Windows meldete einen USB-Fehler.&lt;br /&gt;
Mehrfache Prüfungen führten zu keiner Fehlererkennung, also wurde alles 
wiederholt … und wieder passierte das gleiche.&lt;/p&gt;

&lt;p&gt;Irgendwann dachte ich mir&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ich nehme die Drähte mal ins Maul und “koste”, ob da Strom durchfließt.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Tja, und der Strom zwischen 5V und GND schmeckte nach nichts … weil nämlich
kein Strom und keine Spannung vorhanden war. Also setzte ich mit TX und RX
fort … und siehe da: Ein angenehmes Kribbeln erfüllte meine Zunge.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Kann es sein, dass die Belegung nicht GND, 5V, TX, RX ist sondern genau
umgekehrt, also RX, TX, 5V, GND ?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Also wurden alle Stecker getauscht und nach einem Neustart blieb der 
serielle Adapter stabil und kurze Zeit später zeigte &lt;code&gt;Putty&lt;/code&gt; schon die Boot-
Übertragungen an.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/nano-pi-neo-serial.jpg&quot; alt=&quot;NanoPi-Neo-Serial&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Vertraue keiner Dokumentation, die du nicht selbst geschrieben hast!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Man muss den &lt;a href=&quot;https://de.wikipedia.org/wiki/Raspberry_Pi&quot;&gt;Raspberry-PI&lt;/a&gt; Leuten
schon ein großes Lob aussprechen. Denn sie vergessen ihre alten Produkte nicht
so schnell und wir finden zwischen den Modellen klare Abgrenzungen durch 
Versionsnummern.&lt;/p&gt;

&lt;p&gt;Die “alternativen” &lt;a href=&quot;https://de.wikipedia.org/wiki/ARM-Architektur&quot;&gt;ARM&lt;/a&gt;-Chipschmieden
erfinden fast jedes Jahr eine neue Version ihrer Produkte und nehmen Dokus und 
Software des Vorgängers dann vom Netz.&lt;br /&gt;
So findet man leider unter dem Titel seines Produkts gelegentlich das
Nachfolgemodell und dieses kann leicht verändert aufgebaut sein.&lt;/p&gt;

&lt;p&gt;Wie auch immer … man muss damit rechnen, ein paar Tests auf solchen
Geräten vornehmen zu müssen, wenn nach dem Einschalten etwas nicht 
funktioniert.&lt;/p&gt;

&lt;p&gt;Ich hoffe nur, dass durch die falsche Pinbelegung kein Schaden an den 
Bauteilen entstanden ist. Momentan funktionieren sie, doch ihre Lebenszeit 
wurde durch die Verpolung sicher nicht verlängert.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Toshiba T300</title>
   <link href="https://www.opengate.at/blog/2019/09/toshiba-t300/"/>
   <published>2019-09-21T12:00:00+02:00</published>
   <updated>2019-09-21T12:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2019/09/toshiba-t300</id>
   <category term="retro" /><category term="hardware" />
   <summary type="text">Da mein C64 leider gestorben 
ist, kann sich mein Toshiba T300 mit Hochachtung als mein ältester Computer
bezeichnen.

Der aus dem Jahr 1983 stammende Halb-IBM-Klon
läuft mit einer eigenen Variante von MS-DOS
und bietet eine besondere Diskettenformatierung, die den IBM Floppies damals
voraus war.
</summary>
   <content type="html">&lt;p&gt;Da mein &lt;a href=&quot;/blog/2019/03/c64/&quot;&gt;C64&lt;/a&gt; leider gestorben 
ist, kann sich mein Toshiba T300 mit Hochachtung als mein ältester Computer
bezeichnen.&lt;/p&gt;

&lt;p&gt;Der aus dem Jahr 1983 stammende Halb-&lt;a href=&quot;https://de.wikipedia.org/wiki/IBM-PC-kompatibler_Computer&quot;&gt;IBM-Klon&lt;/a&gt;
läuft mit einer eigenen Variante von &lt;a href=&quot;https://de.wikipedia.org/wiki/MS-DOS&quot;&gt;MS-DOS&lt;/a&gt;
und bietet eine besondere Diskettenformatierung, die den IBM Floppies damals
voraus war.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;blockquote&gt;
  &lt;p&gt;Update: Meine &lt;a href=&quot;/blog/2022/07/t300-again/&quot;&gt;Toshiba T-300 Software Reste&lt;/a&gt;
sind inzwischen auch durchgesehen worden.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Als Schulkind der 90er Jahre musste ich beobachten, wie meine besuchten 
Schulen bis knapp vor dem Jahr 2000 mit antiker Hardware arbeiteten.&lt;/p&gt;

&lt;p&gt;Das waren originale &lt;a href=&quot;https://de.wikipedia.org/wiki/IBM_Personal_Computer&quot;&gt;IBM PCs&lt;/a&gt;, 
aber eben auch ein T300 als quasi Nachbau.
Eben einen solchen konnte ich meiner alten Schule zum Glück abluchsen, und 
konnte das Gerät so vermutlich vor der Zerstörung bewahren.&lt;br /&gt;
&lt;img src=&quot;/blog/assets/img/toshiba-t300.jpg&quot; alt=&quot;Toshiba T300&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Und ich bedauere, dass ich mich nicht auch um ein IBM Modell bemüht habe.&lt;/p&gt;

&lt;p&gt;Jedenfalls habe ich beim jüngsten Besuch am “alten” Zweitwohnsitz dieses
Geräte wieder aus der Ecke geholt und war mehr als erstaunt, dass die
Maschine nach über 20 Jahren sofort einsatzbereit war und problemlos von
Diskette startete. In Summe ist das Gerät schon sicher 30-35 Jahre alt.&lt;/p&gt;

&lt;p&gt;Da kann sich mancher moderne PC eine Scheibe abschneiden, wo 
Elektrolytkondensatoren oder andere Bauteile nach spätestens 10 Jahren 
einfach zerfallen.&lt;/p&gt;

&lt;h3 id=&quot;hardware&quot;&gt;Hardware&lt;/h3&gt;

&lt;p&gt;Leider habe ich aus Zeitmangel gar nicht daran gedacht, die Hardware 
genauer anzusehen, mussten doch einige Disketten am Abend durchprobiert
werden.&lt;/p&gt;

&lt;p&gt;Es sollte ein &lt;a href=&quot;https://de.wikipedia.org/wiki/Intel_8086&quot;&gt;8086&lt;/a&gt; bzw. 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Intel_8088&quot;&gt;8088&lt;/a&gt; Prozessor in der massiven 
Zentraleinheit stecken. Und ich glaube mich zu erinnern, dass ich sogar das 
512 KB &lt;a href=&quot;https://de.wikipedia.org/wiki/Random-Access_Memory&quot;&gt;RAM-Modell&lt;/a&gt; 
ergattert hatte, während viele anderen PCs der Schule nur mit 256 KB 
auskommen mussten.&lt;/p&gt;

&lt;p&gt;Festplatte gab es damals keine (viel zu teuer, wenn doch eh nur Schüler damit
arbeiten sollten), dafür wurde Platz für zwei 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Diskettenlaufwerk&quot;&gt;Diskettenlaufwerke&lt;/a&gt; frei.&lt;/p&gt;

&lt;p&gt;Und die Grafikkarte schaffte es, die üblichen 8 bzw. 16 Farben im Textmodus
auf den fetten &lt;a href=&quot;https://de.wikipedia.org/wiki/Kathodenstrahlr%C3%B6hrenbildschirm&quot;&gt;Röhrenmonitor&lt;/a&gt;
zu übertragen, oder Pixelgrafiken mit bis zu 640 x 350 Pixel zu ermöglichen.&lt;/p&gt;

&lt;h3 id=&quot;dos-20-spezial&quot;&gt;DOS 2.0 Spezial&lt;/h3&gt;

&lt;p&gt;Während die originalen IBM PCs mit IBM’s eigenen &lt;a href=&quot;https://de.wikipedia.org/wiki/PC_DOS&quot;&gt;IBM-DOS&lt;/a&gt;
auf 360 KB &lt;a href=&quot;https://de.wikipedia.org/wiki/Diskette&quot;&gt;Disketten&lt;/a&gt; ausgestattet 
war, hatte Microsoft für Toshiba offenbar einen eigenen MS-DOS-Klon für 
genau diese Hardware geschaffen.&lt;br /&gt;
Konkret sprechen wir von &lt;a href=&quot;https://de.wikipedia.org/wiki/MS-DOS&quot;&gt;MS-DOS&lt;/a&gt; 2.0, 
welches von Laufwerk A: (also das obere) gebootet werden konnte.&lt;/p&gt;

&lt;p&gt;“Normale” MS-DOS oder IBM-DOS Disketten konnte der T300 nicht booten, während
die T300 Disketten wiederum nicht auf üblichen PCs nutzbar waren.&lt;/p&gt;

&lt;p&gt;Das bedeutete leider auch, dass eine Aktualisierung auf eine neuere DOS-Version
unmöglich war, während ich mich erinnere, dass auf dem originalen IBM-PC 
auch noch MS-DOS 5 und MS-DOS 6 problemlos startete.&lt;/p&gt;

&lt;p&gt;DOS 2.0 kam mit den “üblichen” Verdächtigen wie &lt;code&gt;FORMAT&lt;/code&gt;, &lt;code&gt;SYS&lt;/code&gt; oder &lt;code&gt;EDLIN&lt;/code&gt;.
Ein moderner Editor fehlte folglich, doch hier wurde offenbar eine &lt;code&gt;EDIT&lt;/code&gt; 
Software eines Dritterherstellers beigepackt, die man als Vorstufe vom
späteren MS-DOS &lt;code&gt;EDIT&lt;/code&gt; sehen konnte.&lt;/p&gt;

&lt;p&gt;Interessant war, dass ein eigenes Toshiba-Basic als &lt;code&gt;TBASIC&lt;/code&gt; ebenso auf der
Bootdiskette lag, also konnte man sofort mit der 
&lt;a href=&quot;https://de.wikipedia.org/wiki/BASIC&quot;&gt;BASIC&lt;/a&gt; Programmierung starten.&lt;/p&gt;

&lt;h3 id=&quot;diskettenformat&quot;&gt;Diskettenformat&lt;/h3&gt;

&lt;p&gt;Also, keine Ahnung wie oder warum Toshiba es damals so umgesetzt hat, aber
die 5.25 Zoll Disketten wurden mit der doppelten Dichte formatiert.&lt;br /&gt;
Nein, nicht DD (Double-Density mit 360 KB, also das doppelte der ersten
IBM-Formatierung mit 180 KB), sondern ein Non-Standard mit über 
500 KB an nutzbarem Diskettenspeicher.&lt;/p&gt;

&lt;p&gt;Natürlich funktionierten so formatierte Disketten nicht in normalen
(IBM) Laufwerken und auch mein &lt;a href=&quot;https://de.wikipedia.org/wiki/Intel_80386&quot;&gt;386&lt;/a&gt;er 
konnte Mitte der 90er dieses Format mit keinem Tool entziffern.&lt;/p&gt;

&lt;p&gt;Das speziell angepasste DOS-FORMAT Tool konnte aber per Parameter
überredet werden, Disketten mit dem normalen IBM-Standard zu formatieren,
und so war ein Austausch von Daten auch zwischen unterschiedlichen PCs
möglich.&lt;/p&gt;

&lt;p&gt;Ich kann nur vermuten, dass die Lese- Schreibköpfe der Laufwerke um einiges
leistungsfähiger waren als jene der Konkurrenz, denn wenn es gelingt auf 
dem gleichen Medium fast doppelt so viel Kapazität herauszuholen, als es
damals üblich war, und dass diese Daten 20 Jahre nach ihrer Aufzeichnung 
noch vollständig da sind,  … tja, da bin ich echt beeindruckt.&lt;/p&gt;

&lt;h3 id=&quot;software&quot;&gt;Software&lt;/h3&gt;

&lt;p&gt;Hmm … naja, das einzige, was wir damals in der Schule nutzten war &lt;code&gt;TBASIC&lt;/code&gt;
und das mehr als primitive 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Pascal_(Programmiersprache)&quot;&gt;&lt;code&gt;Turbo Pascal 3&lt;/code&gt;&lt;/a&gt;, 
welches per Tastencodes zwischen einem Menü/Compiler Modus und einem 
Texteditor hin und herschalten konnte.&lt;/p&gt;

&lt;p&gt;Meine geliebten Spiele wie &lt;a href=&quot;https://de.wikipedia.org/wiki/Alley_Cat&quot;&gt;Alley Cat&lt;/a&gt;
oder diverse andere Schulprogramme liefen darauf nicht, weil sich die 
Grafikkarte offenbar nicht &lt;a href=&quot;https://de.wikipedia.org/wiki/Enhanced_Graphics_Adapter&quot;&gt;EGA&lt;/a&gt;
/ &lt;a href=&quot;https://de.wikipedia.org/wiki/Video_Graphics_Array&quot;&gt;VGA&lt;/a&gt; konform verhielt.&lt;/p&gt;

&lt;p&gt;Ich erinnere mich auch, dass ich damals mit ein paar 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Assemblersprache&quot;&gt;Assembler&lt;/a&gt;
Zeilen anfangs ebenso an der Grafik gescheitert bin, bis ich feststellte, 
dass einfach andere Adressbereiche gültig waren.&lt;/p&gt;

&lt;p&gt;Die übliche Adresse &lt;code&gt;B000:8000&lt;/code&gt; für farbigen Text lag (glaube ich) auf
&lt;code&gt;B000:0000&lt;/code&gt;, wo eigentlich der Monochrom-Bereich liegen sollte, usw.&lt;/p&gt;

&lt;p&gt;Lediglich ein offenbar selbst-programmiertes &lt;a href=&quot;https://de.wikipedia.org/wiki/Pac-Man&quot;&gt;PacMan&lt;/a&gt;
aus ASCII-Zeichen, war auf den Disketten dabei.&lt;/p&gt;

&lt;p&gt;Ansonsten liegen nur noch ein paar Code-Dateien von Mathematik-Spielereien
wie Quadratwurzel berechnen auf den Disketten.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ach … die gute alte Zeit.&lt;br /&gt;
Ich bin eigentlich froh, dass ich nur an Schulen mit völlig veralteter
Hardware war. Ich meine, wer arbeitete in den späten 90ern noch auf PCs ohne 
Festplatte, damals löste gerade der &lt;a href=&quot;https://de.wikipedia.org/wiki/Intel_Pentium&quot;&gt;Pentium&lt;/a&gt;
den &lt;a href=&quot;https://de.wikipedia.org/wiki/Intel_80486&quot;&gt;486&lt;/a&gt;er ab, und sogar ich hatte
meinen 386 und 486 mit Festplatten bestückt…&lt;/p&gt;

&lt;p&gt;Und genau wegen solcher antiker und langsamer Hardware trieb es mich in
Richtung Assembler, wo ich dann mit einem Grinsen der überforderten
Lehrkraft sagen konnte:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Mein Programm kann das viel schneller.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Die Tatsache, dass ein Gerät mit Baujahr 1983 im Jahr 2019 immer noch 
problemlos startet ist eine wahre Sensation.&lt;/p&gt;

&lt;p&gt;Einziger Nachteil ist und bleibt die nicht vollständige IBM-PC-Kompatibilität.
Denn mit einer solchen könnte sich das Gerät in jedem Museum stolz 
präsentieren. Doch mangels kompatibler Software für diesen Exoten bleibt er
nur ein weiteres Sammlerstück, welches am Zweitwohnsitz wieder in 
Vergessenheit geraten wird.&lt;br /&gt;
Aber trotzdem mag ich ihn … meinen geretteten T-300.&lt;/p&gt;

&lt;h3 id=&quot;nachtrag&quot;&gt;Nachtrag:&lt;/h3&gt;

&lt;p&gt;Und jetzt noch ein paar Fotos vom Innenleben:&lt;/p&gt;

&lt;p&gt;Das Netzteil verläuft über die gesamt Länge des Metallkastens:&lt;br /&gt;
&lt;img src=&quot;/blog/assets/img/toshiba-t300-01.jpg&quot; alt=&quot;Toshiba T300 Top&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Die alten &lt;a href=&quot;https://de.wikipedia.org/wiki/Industry_Standard_Architecture&quot;&gt;ISA&lt;/a&gt; 
Karten verlaufen ebenso über fast ganze Länge und sind damit die größten 
Steckkarten, die ich kenne:&lt;br /&gt;
&lt;img src=&quot;/blog/assets/img/toshiba-t300-02.jpg&quot; alt=&quot;Toshiba T300 Board&quot; /&gt;&lt;br /&gt;
&lt;img src=&quot;/blog/assets/img/toshiba-t300-03.jpg&quot; alt=&quot;Toshiba T300 Board&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Ein &lt;a href=&quot;https://de.wikipedia.org/wiki/Parallele_Schnittstelle&quot;&gt;Drucker&lt;/a&gt; 
und ein &lt;a href=&quot;https://de.wikipedia.org/wiki/RS-232&quot;&gt;COM&lt;/a&gt; Port sind neben der 
Grafikkarte nach außen geleitet. 
Ich erinnere mich dunkel, dass da mal ein Mannesmann 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Nadeldrucker&quot;&gt;Nadeldrucker&lt;/a&gt; dranhing.&lt;br /&gt;
&lt;img src=&quot;/blog/assets/img/toshiba-t300-04.jpg&quot; alt=&quot;Toshiba T300 Back&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Die Tastatur unterscheidet sich in vielen Punkten von heutigen Modellen:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Ein rotes &lt;code&gt;BREAK&lt;/code&gt; sitzt dort, wo wir heute Escape finden&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;ESC&lt;/code&gt;ape liegt unscheinbar neben der “1”&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;CTRL&lt;/code&gt; befindet sich an der heutigen CAPSLOCK Position&lt;/li&gt;
  &lt;li&gt;Und &lt;code&gt;CAPSLOCK&lt;/code&gt; liegt neben Leertaste.&lt;/li&gt;
  &lt;li&gt;Ein &lt;code&gt;EXECUTE&lt;/code&gt; ersetzt &lt;code&gt;HOME&lt;/code&gt; (&lt;code&gt;POS1&lt;/code&gt;) und &lt;code&gt;END&lt;/code&gt; (&lt;code&gt;ENDE&lt;/code&gt;)&lt;/li&gt;
  &lt;li&gt;Dafür ist ein &lt;code&gt;HOME&lt;/code&gt; zwischen den Pfeiltasten.&lt;/li&gt;
  &lt;li&gt;Der Ziffernblock führt &lt;code&gt;+ - * /&lt;/code&gt; auch ganz anders.&lt;/li&gt;
  &lt;li&gt;Und ein paar andere mir unbekannte Tasten findet man ebenso.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/toshiba-t300-05.jpg&quot; alt=&quot;Toshiba T300 Keyboard&quot; /&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>CONAN der Erbauer</title>
   <link href="https://www.opengate.at/blog/2019/09/conan/"/>
   <published>2019-09-14T12:00:00+02:00</published>
   <updated>2019-09-14T12:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2019/09/conan</id>
   <category term="devel" /><category term="software" />
   <summary type="text">Manche denken beim Titel CONAN an den alten 
Kinofilm mit Arnold Schwarzenegger,
andere erinnern sich an den Anime mit dem Detektiv-Jungen.

Und für einen meiner geschätzten Kollegen ist das 
Paket-Tool CONAN die Lösung aller Probleme in der 
C++ Entwicklung.
</summary>
   <content type="html">&lt;p&gt;Manche denken beim Titel CONAN an den alten 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Conan_der_Barbar&quot;&gt;Kinofilm mit Arnold Schwarzenegger&lt;/a&gt;,
andere erinnern sich an den &lt;a href=&quot;https://de.wikipedia.org/wiki/Detektiv_Conan&quot;&gt;Anime mit dem Detektiv-Jungen&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Und für einen meiner geschätzten Kollegen ist das 
&lt;a href=&quot;http://conan.io/&quot;&gt;Paket-Tool CONAN&lt;/a&gt; die Lösung aller Probleme in der 
&lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B&quot;&gt;C++&lt;/a&gt; Entwicklung.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;In der Theorie sieht es so aus:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Wir schreiben einzelne C und C++ Dateien&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/CMake&quot;&gt;CMake&lt;/a&gt; fügt mehrere C/C++ Dateien zu 
einem generischen Projekt zusammen,
das dann auf jeder Build-Umgebung übersetzt werden kann&lt;/li&gt;
  &lt;li&gt;Und &lt;code&gt;CONAN&lt;/code&gt; verwaltet alle Abhängigkeiten von Paketen zwischen
Projekten und erstellt automatisch CMake Files um mehrere Projekte
unter einen Hut zu bekommen.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ob das in der Praxis auch immer so sein wird … das lerne ich gerade im 
Zuge meiner Arbeit.&lt;/p&gt;

&lt;h3 id=&quot;beispiel-szenario&quot;&gt;Beispiel Szenario&lt;/h3&gt;

&lt;p&gt;Angenommen wir schreiben ein Programm, das Kompression einsetzt, z.B. durch
die gute alte &lt;a href=&quot;https://de.wikipedia.org/wiki/Zlib&quot;&gt;ZLIB&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Jetzt können wir die Quellcodes in ein Unterverzeichnis unseres Projektes 
kopieren und einfach mitkompilieren.&lt;br /&gt;
&lt;em&gt;Oder:&lt;/em&gt; wir nutzen &lt;code&gt;CONAN&lt;/code&gt; und setzen eine Abhängigkeit auf ein CONAN-ZLIB-Paket.
Dann brauchen wir nämlich nur noch unsere eigenen Sourcen speichern und 
ausliefern, und &lt;code&gt;CONAN&lt;/code&gt; wird die fehlende ZLIB aus dem Internet (oder einem 
lokalen Build-Artifactory) herunterladen.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;CONAN&lt;/code&gt; stellt unterschiedliche Möglichkeiten seiner Nutzung zur Verfügung,
einige davon sind:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Ein Paket kann alle Sourcen eines Moduls beinhalten und wird dann lokal
bei bzw. vor der Nutzung neu kompiliert&lt;/li&gt;
  &lt;li&gt;Ein Paket enthält Header und vorkompilierte Binärdateien. Damit lädt
&lt;code&gt;CONAN&lt;/code&gt; die fertigen Dateien herunter und stellt sie dem Linker automatisch
zur Verfügung.&lt;/li&gt;
  &lt;li&gt;Oder &lt;code&gt;CONAN&lt;/code&gt; besteht nur noch aus Binärdateien, die für die Auslieferung 
benötigt werden und wird so zu einem Setup/Deployment-Builder.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;CONAN&lt;/code&gt; löst Abhängigkeiten rekursiv auf, dass heißt, wenn wir z.B. eine 
Abhängigkeit zu &lt;code&gt;boost&lt;/code&gt; deklarieren, definiert das &lt;code&gt;boost&lt;/code&gt;-CONAN-Paket, dass 
es von &lt;code&gt;zlib&lt;/code&gt; und &lt;code&gt;bzip2&lt;/code&gt; abhängt. &lt;code&gt;CONAN&lt;/code&gt; lädt oder baut dann alle drei 
Abhängigkeiten und stellt sie uns für das eigene Projekt zur Verfügung:&lt;/p&gt;

&lt;script src=&quot;/blog/assets/mermaid/mermaid.min.js&quot;&gt;&lt;/script&gt;
&lt;div class=&quot;mermaid&quot;&gt;
graph LR
  subgraph &quot;CONAN Build Setup&quot;
    conan[[conanfile.py]]
    cmake[[CMakeLists.txt]]
  end

  boost([boost/1.71.0])
  zlib([zlib/1.2.11])
  bzip([bzip2/1.0.8])
  main[[my_program.cpp&lt;br /&gt;my_component.cpp&lt;br /&gt;my_utilities.cpp]]
  exe[[my_program.exe]]

  cache((CONAN Cache&lt;br /&gt;&lt;br /&gt;boost, zlib, bzip2))

  conan --requires--&amp;gt; boost
  boost --requires--&amp;gt; zlib
  boost --requires--&amp;gt; bzip

  conan --download&lt;br /&gt;install--&amp;gt; cache

  cmake --include_directories&lt;br /&gt;$CONAN_INCLUDE_DIRS--&amp;gt; cache
  cmake --target_link_libraries&lt;br /&gt;$CONAN_LIBS--&amp;gt; cache
  cmake --compile--&amp;gt; main

  cache --link--&amp;gt; exe
  main --link--&amp;gt; exe
&lt;/div&gt;

&lt;h3 id=&quot;implementierung&quot;&gt;Implementierung&lt;/h3&gt;

&lt;p&gt;Ist &lt;code&gt;CONAN&lt;/code&gt; auf dem System installiert, erweitert man &lt;code&gt;CMAKE&lt;/code&gt; um ein paar 
Zeilen und fügt die Datei &lt;code&gt;conanfile.py&lt;/code&gt; hinzu.
Dabei handelt es sich um ein &lt;a href=&quot;https://de.wikipedia.org/wiki/Python_(Programmiersprache)&quot;&gt;Python&lt;/a&gt; 
Script, das eine spezielle Klasse implementiert, deren Methoden in den 
einzelnen Ausführungsschritten das Verhalten von &lt;code&gt;CONAN&lt;/code&gt; beeinflussen.&lt;/p&gt;

&lt;p&gt;Am wichtigsten sind dabei die Abhängigkeiten, wo wir festlegen, welche 
anderen Pakete für den Einsatz unseres Pakets benötigen.
Diese haben das Format:&lt;br /&gt;
&lt;code&gt;name/version@remote/branch&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Im Falle des offiziellen ZLIB-Pakets für &lt;code&gt;CONAN&lt;/code&gt; lautet der Pfad:
&lt;code&gt;zlib/1.2.11@conan/stable&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Der &lt;code&gt;remote&lt;/code&gt; Parameter ist mit der Installation automatisch auf die
Server von &lt;code&gt;conan.io&lt;/code&gt; und &lt;code&gt;bintray.com&lt;/code&gt; gesetzt. Will man Pakete von
anderen bzw. eigenen Servern nutzen, muss ein entsprechender Name
registriert und der CONAN-Konfiguration mitgeteilt werden.&lt;/p&gt;

&lt;p&gt;Wird nun direkt oder indirekt ein Paket installiert, z.B. mit&lt;br /&gt;
&lt;code&gt;conan install zlib/1.2.11@conan/stable&lt;/code&gt;&lt;br /&gt;
dann lädt &lt;code&gt;CONAN&lt;/code&gt; alle benötigten Dateien herunter und speichert
sie in einem (zugegeben etwas merkwürdigen) Pfad im Home-Verzeichnis.&lt;/p&gt;

&lt;p&gt;Wenn wir dann unser leicht modifiziertes &lt;code&gt;CMAKE&lt;/code&gt; nutzen, um Projektdateien 
zu erzeugen, setzt &lt;code&gt;CONAN&lt;/code&gt; automatisch alle Pfade für &lt;code&gt;CMAKE&lt;/code&gt; auf die
richtigen INCLUDE- und LIB- Verzeichnisse, womit wir unser Projekt 
kompilieren können, ohne komplexe Such-Routinen in &lt;code&gt;CMAKE&lt;/code&gt; implementieren
zu müssen.&lt;/p&gt;

&lt;p&gt;Denn dass &lt;code&gt;CMAKE&lt;/code&gt; alle seine Dateien findet, kann bei größeren Projekten
mit mehreren Abhängigkeiten durchaus herausfordernd werden. Und genau
diesen Job soll hier &lt;code&gt;CONAN&lt;/code&gt; erledigen.&lt;/p&gt;

&lt;p&gt;Ein wichtiges Detail ist, dass im Falle von Binärdateien &lt;code&gt;CONAN&lt;/code&gt; für jede
Plattform und Build-Option ein eigenes Paket erstellen kann. 
Für Windows gibt es in der Regel 4 unterschiedliche Pakete für ein Modul, 
nämlich&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Debug Win32&lt;/li&gt;
  &lt;li&gt;Release Win32&lt;/li&gt;
  &lt;li&gt;Debug Win64&lt;/li&gt;
  &lt;li&gt;Release Win64&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Hierfür erstellt man je ein &lt;code&gt;CONAN&lt;/code&gt; Profil pro Build-Konfiguration,
und &lt;code&gt;CONAN&lt;/code&gt; leitet an &lt;code&gt;CMAKE&lt;/code&gt; genau die Pfade weiter, die für die gewünschte
Build-Konfiguration notwendig ist. Und bei unterschiedlichen Compilern
bzw. auf &lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt; ist das ebenso.&lt;/p&gt;

&lt;p&gt;Aus der Build-Konfiguration wird hierfür ein HASH erzeugt und dem
Paket zugeordnet. Die im Beispiel erwähnten 4 Windows Build-Varianten
würden also zu 4 separaten Hashes führen. Eine &lt;code&gt;zlib.dll&lt;/code&gt; wäre also
4 mal gespeichert, doch über den Hash würde man nur genau die &lt;code&gt;dll&lt;/code&gt;
bekommen, die man gerade braucht.&lt;/p&gt;

&lt;p&gt;Leitet man z.B.: den X64-Release-Build des eigenen Programms ein, würde 
über den Hash nur die X64-Release-&lt;code&gt;zlib.dll&lt;/code&gt; ausgewählt und gelinkt werden.&lt;/p&gt;

&lt;h3 id=&quot;beispiel-abläufe&quot;&gt;Beispiel Abläufe&lt;/h3&gt;

&lt;h4 id=&quot;conanfilepy-und-cmakeliststxt&quot;&gt;conanfile.py und CMakeLists.txt&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;conanfile.py&lt;/code&gt; definiert Abhängigkeiten, die von &lt;code&gt;CONAN&lt;/code&gt; in den Cache 
heruntergeladen werden.&lt;br /&gt;
Beim Build mit &lt;code&gt;CMake&lt;/code&gt; verweist das angepasste &lt;code&gt;CMakeLists.txt&lt;/code&gt; automatisch
auf Bibliothekenpfade im Cache. CMake’s &lt;code&gt;find_package&lt;/code&gt; brauchen wir also nicht.&lt;/p&gt;

&lt;script src=&quot;/blog/assets/mermaid/mermaid.min.js&quot;&gt;&lt;/script&gt;
&lt;div class=&quot;mermaid&quot;&gt;
graph LR
  COF[conanfile.py&lt;br /&gt; requires: zlib/1.2.11] --Download--&amp;gt; CC(CONAN Cache)
  CC --Build &amp;amp; Link&lt;br /&gt;Dependencies--&amp;gt; CMF[CMakeLists.txt&lt;br /&gt;target_link_libraries&lt;br /&gt; my_app $CONAN_LIBS]
&lt;/div&gt;

&lt;h4 id=&quot;einzelne-build-schritte&quot;&gt;Einzelne Build-Schritte&lt;/h4&gt;

&lt;p&gt;Liegt den Sourcen ein &lt;code&gt;conanfile.py&lt;/code&gt; bei, kann man in dem Verzeichnis die 
Abhängigkeiten einbetten lassen, danach den Build anstarten und am Ende
die Resultate exportieren lassen. Die Umsetzung der Schritte wird durch 
die Einstellungen und Methoden in &lt;code&gt;conanfile.py&lt;/code&gt; definiert.&lt;/p&gt;

&lt;script src=&quot;/blog/assets/mermaid/mermaid.min.js&quot;&gt;&lt;/script&gt;
&lt;div class=&quot;mermaid&quot;&gt;
graph LR
  COINST[CONAN INSTALL &lt;br /&gt;/source/path] -- Download&lt;br /&gt;dependencies --&amp;gt; COBUILD
  COBUILD[CONAN BUILD &lt;br /&gt;/source/path] -- Run CMake&lt;br /&gt;Build --&amp;gt; COPACK
  COPACK[CONAN PACKAGE &lt;br /&gt;/source/path] -- Extract Headers&lt;br /&gt;and Binaries --&amp;gt; OUT[(Output&lt;br /&gt;Files)]
&lt;/div&gt;

&lt;h4 id=&quot;pakete-erzeugen-und-verteilen&quot;&gt;Pakete erzeugen und verteilen&lt;/h4&gt;

&lt;p&gt;Ein fertiges CONAN Paket kann in einen konfigurierten Store hochgeladen 
werden und von dort auf andere System weiterverteilt werden.
Dafür muss in &lt;code&gt;conanfile.py&lt;/code&gt; eine entsprechende &lt;code&gt;deploy&lt;/code&gt; Routine definiert
sein.&lt;/p&gt;

&lt;script src=&quot;/blog/assets/mermaid/mermaid.min.js&quot;&gt;&lt;/script&gt;
&lt;div class=&quot;mermaid&quot;&gt;
graph LR
  COCREATE[&quot;CONAN CREATE &lt;br /&gt;/source/path &lt;br /&gt;name/version&lt;br /&gt;@user/channel&quot;] --&amp;gt; COCACHE
  COCACHE([CONAN&lt;br /&gt;Cache]) --&amp;gt; COUPLOAD
  COUPLOAD[&quot;CONAN UPLOAD&lt;br /&gt;name/version&lt;br /&gt;@user/channel&quot;] --&amp;gt; ARTIFACTORY[(Package&lt;br /&gt;Artifactory&lt;br /&gt;Server)]
  ARTIFACTORY --&amp;gt; CODOWN[&quot;CONAN INSTALL&lt;br /&gt;name/version&lt;br /&gt;@user/channel&lt;br /&gt;--install-folder &lt;br /&gt;/target/path&quot;] --&amp;gt; CODEP[(Deployment&lt;br /&gt;Output)]
&lt;/div&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Nun, noch ist &lt;code&gt;CONAN&lt;/code&gt; für mich ein Novum und die Umstellung eines größeren 
Projektes (an der ich mitarbeiten darf) ist das teilweise recht aufwendig.
Tatsächlich liegt ein ordentlicher Teil des Migrationsaufwandes an jenen
Stellen, wo &lt;code&gt;CMAKE&lt;/code&gt; Workarounds benutzt wurden um Features zu generieren,
die es ohne &lt;code&gt;CONAN&lt;/code&gt; eben nicht gibt.&lt;br /&gt;
Solche Codes umzuschreiben und durch &lt;code&gt;CONAN&lt;/code&gt;-Standards zu ersetzen erfordert
also dann doch etwas Programmieraufwand in Python und auch 
Verzeichnisstrukturen oder Unit-Tests sind unter &lt;code&gt;CONAN&lt;/code&gt; anders organisiert,
als bei einigen bestehenden Projekten.&lt;/p&gt;

&lt;p&gt;Werde ich &lt;code&gt;CONAN&lt;/code&gt; im GATE Projekt einsetzen?&lt;/p&gt;

&lt;p&gt;Nein, vorerst nicht. Einerseits fehlt mir das Wissen, wie ein “ideales”
&lt;code&gt;CONAN&lt;/code&gt; Projekt aussehen soll und außerdem sind externe Abhängigkeiten genau
das, was das GATE Projekt vermeiden will. Dennoch bleiben stets ein paar 
Abhängigkeiten auch bei mir übrig (z.B. GTK unter Linux) und vielleicht 
werden diese in Zukunft auch durch eine &lt;code&gt;CONAN&lt;/code&gt;-Lösung aus dem Weg 
geräumt werden.&lt;/p&gt;

&lt;p&gt;Bis dahin gibt es aber noch viel für mich zu entdecken …&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Dieses AUTO ist cool (Teil 2)</title>
   <link href="https://www.opengate.at/blog/2019/09/auto-future/"/>
   <published>2019-09-08T12:00:00+02:00</published>
   <updated>2019-09-08T12:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2019/09/auto-future</id>
   <category term="devel" />
   <summary type="text">Wir wissen nun, dass Großvater C
sein auto nie benutzt hat und es in der Garage verrosten ließ.

Doch sein Enkel C++ 11, ein bekennender
auto-Freak, zerlegte die Karosserie, entfernte die Spuren des Zahns der Zeit
und baute sich daraus einen neuen Boliden, der jedoch bald ein Eigenleben 
entwickelte.

Dieser wurde zu einer Rennsau, die bei fast jedem Wettrennen als Nummer 1 
über die Ziellinie sauste
… vorausgesetzt: Es saß der richtige Fahrer hinterm Lenkrad.
</summary>
   <content type="html">&lt;p&gt;Wir wissen nun, dass Großvater &lt;a href=&quot;https://de.wikipedia.org/wiki/C_(Programmiersprache)&quot;&gt;C&lt;/a&gt;
sein &lt;code&gt;auto&lt;/code&gt; nie benutzt hat und es in der Garage verrosten ließ.&lt;/p&gt;

&lt;p&gt;Doch sein Enkel &lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B&quot;&gt;C++&lt;/a&gt; 11, ein bekennender
&lt;code&gt;auto&lt;/code&gt;-Freak, zerlegte die Karosserie, entfernte die Spuren des Zahns der Zeit
und baute sich daraus einen neuen Boliden, der jedoch bald ein Eigenleben 
entwickelte.&lt;/p&gt;

&lt;p&gt;Dieser wurde zu einer Rennsau, die bei fast jedem Wettrennen als Nummer 1 
über die Ziellinie sauste&lt;br /&gt;
… vorausgesetzt: Es saß der richtige Fahrer hinterm Lenkrad.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Wenn man unter C++ weiter “klassisch” programmiert, könnte man denken, dass man 
&lt;code&gt;auto&lt;/code&gt; nicht braucht.&lt;br /&gt;
Es ist sogar übersichtlicher, wenn man Datentypen selbst ausschreibt 
(&lt;code&gt;int x = 42;&lt;/code&gt;) anstatt alles von &lt;code&gt;auto&lt;/code&gt; erledigen zu lassen (&lt;code&gt;auto x = 42;&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Doch spätestens, wenn man mit &lt;a href=&quot;https://de.wikipedia.org/wiki/Template_(C%2B%2B)&quot;&gt;Templates&lt;/a&gt;
und Spezialisierungen arbeitet, sind Typen bei der Deklaration nicht mehr 
zwingend vorhersehbar.&lt;br /&gt;
Doch der Compiler weiß bei der Instanziierung ganz genau, mit welchen Typen
er arbeitet, und genau hier wird &lt;code&gt;auto&lt;/code&gt; zum gefeierten Heilsbringer.&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;template&lt;/span&gt;&amp;lt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;T&lt;/span&gt;&amp;gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;struct&lt;/span&gt; next_greater_type
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;typedef&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;long&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;double&lt;/span&gt; type_t;        &lt;span style=&quot;color:#777&quot;&gt;/* finally the &amp;quot;greatest&amp;quot; type */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;};
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;template&lt;/span&gt;&amp;lt;&amp;gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;struct&lt;/span&gt; next_greater_type&amp;lt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt;&amp;gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;typedef&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;short&lt;/span&gt; type_t;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;};
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;template&lt;/span&gt;&amp;lt;&amp;gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;struct&lt;/span&gt; next_greater_type&amp;lt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;short&lt;/span&gt;&amp;gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;typedef&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;long&lt;/span&gt; type_t;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;};
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;template&lt;/span&gt;&amp;lt;&amp;gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;struct&lt;/span&gt; next_greater_type&amp;lt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;long&lt;/span&gt;&amp;gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;typedef&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;long&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;long&lt;/span&gt; type_t;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;};
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n21&quot; name=&quot;n21&quot;&gt;21&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;template&lt;/span&gt;&amp;lt;&amp;gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;struct&lt;/span&gt; next_greater_type&amp;lt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;long&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;long&lt;/span&gt;&amp;gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n22&quot; name=&quot;n22&quot;&gt;22&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n23&quot; name=&quot;n23&quot;&gt;23&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;typedef&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;double&lt;/span&gt; type_t;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n24&quot; name=&quot;n24&quot;&gt;24&lt;/a&gt;&lt;/span&gt;};
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n25&quot; name=&quot;n25&quot;&gt;25&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n26&quot; name=&quot;n26&quot;&gt;26&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n27&quot; name=&quot;n27&quot;&gt;27&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;template&lt;/span&gt;&amp;lt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;T&lt;/span&gt;&amp;gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n28&quot; name=&quot;n28&quot;&gt;28&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;typename&lt;/span&gt; next_greater_type&amp;lt;T&amp;gt;::type_t multiply(T &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt;&amp;amp; t1, &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; t2)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n29&quot; name=&quot;n29&quot;&gt;29&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n30&quot; name=&quot;n30&quot;&gt;30&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;typedef&lt;/span&gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;typename&lt;/span&gt; next_greater_type&amp;lt;T&amp;gt;::type_t greater_type_t;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n31&quot; name=&quot;n31&quot;&gt;31&lt;/a&gt;&lt;/span&gt;        
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n32&quot; name=&quot;n32&quot;&gt;32&lt;/a&gt;&lt;/span&gt;  greater_type_t a = greater_type_t(t1);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n33&quot; name=&quot;n33&quot;&gt;33&lt;/a&gt;&lt;/span&gt;  greater_type_t b = greater_type_t(t2);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n34&quot; name=&quot;n34&quot;&gt;34&lt;/a&gt;&lt;/span&gt;        
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n35&quot; name=&quot;n35&quot;&gt;35&lt;/a&gt;&lt;/span&gt;  greater_type_t c = a * b;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n36&quot; name=&quot;n36&quot;&gt;36&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; c;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n37&quot; name=&quot;n37&quot;&gt;37&lt;/a&gt;&lt;/span&gt;}
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n38&quot; name=&quot;n38&quot;&gt;38&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n39&quot; name=&quot;n39&quot;&gt;39&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; main()
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n40&quot; name=&quot;n40&quot;&gt;40&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n41&quot; name=&quot;n41&quot;&gt;41&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt; c = &lt;span style=&quot;color:#00D&quot;&gt;127&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n42&quot; name=&quot;n42&quot;&gt;42&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;short&lt;/span&gt; s = &lt;span style=&quot;color:#00D&quot;&gt;32767&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n43&quot; name=&quot;n43&quot;&gt;43&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;long&lt;/span&gt; l = &lt;span style=&quot;color:#00D&quot;&gt;2147483647L&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n44&quot; name=&quot;n44&quot;&gt;44&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;long&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;long&lt;/span&gt; ll = &lt;span style=&quot;color:#00D&quot;&gt;9223372036854775807LL&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n45&quot; name=&quot;n45&quot;&gt;45&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n46&quot; name=&quot;n46&quot;&gt;46&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;auto&lt;/span&gt; result1 = multiply(c, &lt;span style=&quot;color:#00D&quot;&gt;4&lt;/span&gt;);  &lt;span style=&quot;color:#777&quot;&gt;// short result&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n47&quot; name=&quot;n47&quot;&gt;47&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;auto&lt;/span&gt; result2 = multiply(s, &lt;span style=&quot;color:#00D&quot;&gt;4&lt;/span&gt;);  &lt;span style=&quot;color:#777&quot;&gt;// long result&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n48&quot; name=&quot;n48&quot;&gt;48&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;auto&lt;/span&gt; result3 = multiply(l, &lt;span style=&quot;color:#00D&quot;&gt;4&lt;/span&gt;);  &lt;span style=&quot;color:#777&quot;&gt;// long long result&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n49&quot; name=&quot;n49&quot;&gt;49&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;auto&lt;/span&gt; result4 = multiply(ll, &lt;span style=&quot;color:#00D&quot;&gt;4&lt;/span&gt;); &lt;span style=&quot;color:#777&quot;&gt;// double result&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n50&quot; name=&quot;n50&quot;&gt;50&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;        
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n51&quot; name=&quot;n51&quot;&gt;51&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n52&quot; name=&quot;n52&quot;&gt;52&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Im Beispiel wird für jeden Zahlentypen der nächst größere festgelegt.
Die generische “Multiplikation” soll so einen Ausgabetypen festlegen,
der ohne Verlust das Ergebnis enthalten kann.&lt;/p&gt;

&lt;p&gt;Zugegeben, das Beispiel ist wirklich sehr exemplarisch und wenig praxisnah.
Aber es zeigt, dass &lt;code&gt;auto&lt;/code&gt; einem den Aufwand abnimmt, stets über den 
&lt;code&gt;template&lt;/code&gt; &lt;code&gt;typedef&lt;/code&gt; den Ergebnistypen selbst zu bestimmen.&lt;/p&gt;

&lt;h3 id=&quot;auto-und-r-value-referenzen&quot;&gt;&lt;code&gt;auto&lt;/code&gt; und R-Value Referenzen&lt;/h3&gt;

&lt;p&gt;Seine größte Stärke spielt &lt;code&gt;auto&lt;/code&gt; meines Erachtens mit &lt;code&gt;auto&amp;amp;&amp;amp;&lt;/code&gt; aus.&lt;/p&gt;

&lt;p&gt;Denn wir Programmierer machen gerne den Fehler durch ungenaue
und schlecht passende Datentypenangaben Optimierungen zu verhindern.&lt;/p&gt;

&lt;p&gt;Gibt eine Funktion eine const-Referenz zurück, sollte diese auch genau so 
entgegengenommen werden. Nimmt man sie als neue Instanz an, entsteht eine
(oft sinnlose) Kopie, die Speicher und CPU-Zeit frisst.&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;std::&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;string&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt;&amp;amp; get_text();
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;...
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;std::&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;string&lt;/span&gt; x = get_text();        &lt;span style=&quot;color:#777&quot;&gt;// falsch!&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;std::&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;string&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt;&amp;amp; y = get_text(); &lt;span style=&quot;color:#777&quot;&gt;//richtig!&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Genau hier hilft uns &lt;code&gt;auto&amp;amp;&amp;amp;&lt;/code&gt;, denn dieses Konstrukt garantiert, dass die 
Variable den perfekten Typen erhält.&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;std::&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;string&lt;/span&gt; get_copy();
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;std::&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;string&lt;/span&gt;&amp;amp; get_reference();
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;std::&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;string&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt;&amp;amp; get_const_reference();
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;std::&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;string&lt;/span&gt;&amp;amp;&amp;amp; get_rv_reference();
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt; lame_foo()
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;auto&lt;/span&gt; a = get_copy();            &lt;span style=&quot;color:#777&quot;&gt;// std::string / copy&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;auto&lt;/span&gt; b = get_reference();       &lt;span style=&quot;color:#777&quot;&gt;// std::string / copy&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;auto&lt;/span&gt; c = get_const_reference(); &lt;span style=&quot;color:#777&quot;&gt;// std::string / copy&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;auto&lt;/span&gt; d = get_rv_reference();    &lt;span style=&quot;color:#777&quot;&gt;// std::string / move&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;}
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt; smart_foo()
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;auto&lt;/span&gt;&amp;amp;&amp;amp; a = get_copy();            &lt;span style=&quot;color:#777&quot;&gt;// std::string&amp;amp;&amp;amp;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;auto&lt;/span&gt;&amp;amp;&amp;amp; b = get_reference();       &lt;span style=&quot;color:#777&quot;&gt;// std::string&amp;amp;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;auto&lt;/span&gt;&amp;amp;&amp;amp; c = get_const_reference(); &lt;span style=&quot;color:#777&quot;&gt;// std::string const&amp;amp;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;auto&lt;/span&gt;&amp;amp;&amp;amp; d = get_rv_reference();    &lt;span style=&quot;color:#777&quot;&gt;// std::string&amp;amp;&amp;amp;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;In &lt;code&gt;lame_foo&lt;/code&gt; löst &lt;code&gt;auto&lt;/code&gt; stets einen std::string aus, was mit
Ausnahme der letzten Zeile immer ein Kopieren des Strings erfordert.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;smart_foo&lt;/code&gt; hingegen nutzt &lt;code&gt;std::string&amp;amp;&amp;amp;&lt;/code&gt; um Kopien durch 
&lt;a href=&quot;http://en.cppreference.com/w/cpp/language/move_constructor&quot;&gt;Move-Konstruktion&lt;/a&gt;
abzufangen und im Fall von “gewöhnlichen” Referenzen werden diese erkannt und
als eben solche ohne Performanceverlust entgegengenommen.&lt;br /&gt;
Und das ist kurz gesagt: Perfekt.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Scott_Meyers&quot;&gt;Scott Meyers&lt;/a&gt; bezeichnet diese 
Nutzung von Referenzen übrigens gerne als 
&lt;a href=&quot;https://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers&quot;&gt;Universal References&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;auto&lt;/code&gt; zählt im modernen C++ ganz klar zu meinen Favoriten.&lt;br /&gt;
Mehr kann man dazu gar nicht sagen.&lt;/p&gt;

&lt;p&gt;Mein Problem in der Entwicklung ist allerdings, dass ich aus Rücksicht auf 
ältere Compiler (z.B. für &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_CE&quot;&gt;Windows CE&lt;/a&gt; ), 
immer noch oft auf dieses Feature verzichte.&lt;/p&gt;

&lt;p&gt;Doch bei neuen Projekten ist &lt;code&gt;auto&lt;/code&gt; absolut Pflicht!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Dieses AUTO ist cool</title>
   <link href="https://www.opengate.at/blog/2019/09/auto-history/"/>
   <published>2019-09-07T12:00:00+02:00</published>
   <updated>2019-09-07T12:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2019/09/auto-history</id>
   <category term="devel" />
   <summary type="text">
  Die Welt ist im Wandel


hieß schon am Beginn der Herr-der-Ringe Filme
und das trifft auch auf unsere Welt(en) zu.

Während die Worte gleich bleiben ändert sich das, was damit bezeichnet wird,
und schon haben wir ganz neue Möglichkeiten uns auszudrücken.

Das beste Beispiel dafür ist das Schlüsselwort auto, welches seit Urzeiten
ungenutzt im C-Standard 
liegt und welches seit C++ 11 ein 
ganz neue Bedeutung erhalten hat.
</summary>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;Die Welt ist im Wandel&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;hieß schon am Beginn der &lt;a href=&quot;https://de.wikipedia.org/wiki/Der_Herr_der_Ringe_(Filmtrilogie)&quot;&gt;Herr-der-Ringe Filme&lt;/a&gt;
und das trifft auch auf unsere Welt(en) zu.&lt;/p&gt;

&lt;p&gt;Während die Worte gleich bleiben ändert sich das, was damit bezeichnet wird,
und schon haben wir ganz neue Möglichkeiten uns auszudrücken.&lt;/p&gt;

&lt;p&gt;Das beste Beispiel dafür ist das Schlüsselwort &lt;code&gt;auto&lt;/code&gt;, welches seit Urzeiten
ungenutzt im &lt;a href=&quot;https://de.wikipedia.org/wiki/C_(Programmiersprache)&quot;&gt;C-Standard&lt;/a&gt; 
liegt und welches seit &lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B&quot;&gt;C++&lt;/a&gt; 11 ein 
ganz neue Bedeutung erhalten hat.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;In der klassischen C Welt gab bzw. gibt es 3 Formen von Datenelementen:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;statische&lt;/strong&gt;: das sind globale Variablen, die vom Programmbeginn an bis 
zum Ende an der gleichen Adresse verweilen.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;dynamische&lt;/strong&gt;: sie werden von der Speicherverwaltung (
&lt;a href=&quot;http://www.cplusplus.com/reference/cstdlib/malloc/&quot;&gt;&lt;code&gt;malloc()&lt;/code&gt;&lt;/a&gt; ) auf 
Anfrage bereitgestellt und müssen auch manuell wieder freigegeben werden
(&lt;a href=&quot;http://www.cplusplus.com/reference/cstdlib/free/&quot;&gt;free()&lt;/a&gt; )&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;automatische&lt;/strong&gt;: das sind unsere lokalen Variablen und Funktionsparameter
und diese werden automatisch relativ zur aktuell laufenden Funktionsparameter
an einen bestimmten Ort (&lt;a href=&quot;https://de.wikipedia.org/wiki/Aufrufstapel&quot;&gt;Stack&lt;/a&gt;
gepackt.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;globale--statische-variablen&quot;&gt;Globale / statische Variablen&lt;/h3&gt;

&lt;p&gt;Für globale Variablen gibt es den Bezeichner &lt;code&gt;static&lt;/code&gt;, vor allem wenn sie 
innerhalb von Funktionen deklariert werden. Außerhalb (also im globalen
Namensraum) können sie auch den Bezeichner &lt;code&gt;extern&lt;/code&gt; haben, wenn sie über 
Modulgrenzen hinweg (DLL/SO) sichtbar sein sollen.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#777&quot;&gt;/* visible global variable, accessible from everywhere */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;extern&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; global_state = &lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#777&quot;&gt;/* global variable, accessible only in current .c file */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;static&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; internal_state = &lt;span style=&quot;color:#00D&quot;&gt;2&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; my_function(&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; param)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#777&quot;&gt;/* global variable only accessible in this function */&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;static&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; function_state = &lt;span style=&quot;color:#00D&quot;&gt;3&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h3 id=&quot;dynamische-variablen&quot;&gt;Dynamische Variablen&lt;/h3&gt;

&lt;p&gt;Vereinfacht könnte sagen:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Alles, was bei seiner Erzeugung als Pointer entsteht,
fällt in diese Kategorie.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Bei &lt;code&gt;malloc() / free()&lt;/code&gt; angefangen bis hin zu nativen Funktion
eines Betriebssystems bekommen wir stets einen Pointer,
der auf die eigentlichen Daten zeigt.&lt;/p&gt;

&lt;p&gt;Darauf brauchen wir hier nicht näher eingehen.&lt;/p&gt;

&lt;h3 id=&quot;automatische--lokale-variablen&quot;&gt;Automatische / lokale Variablen&lt;/h3&gt;

&lt;p&gt;Tja, aber die meisten Datenelemente liegen in lokalen Variablen
innerhalb von Funktionen, und diese werden automatisch an
einer Speicheradresse angelegt, die am Stack liegt und relativ zum aktuellen
Funktionsrahmen (Stack-Frame) errechnet wird.&lt;/p&gt;

&lt;p&gt;Und genau hier hatte der C Standard ein eigenes Schlüsselwort vorgesehen
und das hieß &lt;code&gt;auto&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;das-c-schlüsselwort-auto&quot;&gt;Das C Schlüsselwort AUTO&lt;/h3&gt;

&lt;p&gt;Es war also vorgesehen, dass wir in Funktionen unseren Code in etwa
so schreiben:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; get_counter()
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;static&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; global_counter = &lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;auto&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; current_count = ++global_counter;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; current_count;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Jede lokale Variable hätte mit &lt;code&gt;auto&lt;/code&gt; als eben solche identifiziert werden
sollen.&lt;br /&gt;
Aber genau das ist überflüssig, denn wenn eine Variable nicht statisch ist,
was sollte sie denn sonst sein?&lt;/p&gt;

&lt;p&gt;Und so konnte man &lt;code&gt;auto&lt;/code&gt; auch weglassen und nur&lt;br /&gt;
&lt;code&gt;int current_count = ...&lt;/code&gt; schreiben um eine automatische Variable zu
erhalten.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;auto&lt;/code&gt; gelang somit in Vergessenheit bevor es noch bekannt wurde.
Und ich kenne keinen verbreiteten C Code, der &lt;code&gt;auto&lt;/code&gt; jemals eingesetzt hätte.&lt;/p&gt;

&lt;h3 id=&quot;auto-als-heilsbringer-in-c&quot;&gt;auto als Heilsbringer in C++&lt;/h3&gt;

&lt;p&gt;Aus genau diesem Grund erhielt &lt;code&gt;auto&lt;/code&gt; im C++ Standard 2011 (C++11) eine 
neue Bedeutung:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Lässt man nach &lt;code&gt;auto&lt;/code&gt; den Datentypen weg und es folgt der Variablennamen,
so legt der Compiler automatisch den Datentypen fest.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Anstatt&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; x = &lt;span style=&quot;color:#00D&quot;&gt;42&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;std::&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;string&lt;/span&gt; y = my_stringstream.str();
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;double&lt;/span&gt;* z = &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;new&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;double&lt;/span&gt;();
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;kann man nun:&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;auto&lt;/span&gt; x = &lt;span style=&quot;color:#00D&quot;&gt;42&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;auto&lt;/span&gt; y = my_stringstream.str();
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;auto&lt;/span&gt; z = &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;new&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;double&lt;/span&gt;();
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;schreiben.&lt;/p&gt;

&lt;p&gt;Und wie geil das für Templates ist … dazu schreib ich morgen was.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>STM8S103F3P6</title>
   <link href="https://www.opengate.at/blog/2019/08/stm8s103f3p6/"/>
   <published>2019-08-31T12:00:00+02:00</published>
   <updated>2019-08-31T12:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2019/08/stm8s103f3p6</id>
   <category term="hardware" />
   <summary type="text">
  … und er ist noch billiger als ein 
ATtiny


Das letzte Argument sollte dann auch den letzten Zweifler überzeugt haben.
Denn ein STM8 Chip kostete mich bei 10 
Stück weniger als 70 Cent pro Stück und das sinkt bei größeren Zahlen noch 
weiter ab.

Was kann man mit dem Teil also machen?
</summary>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;… und er ist noch billiger als ein 
&lt;a href=&quot;/blog/2019/08/attiny84/&quot;&gt;ATtiny&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Das letzte Argument sollte dann auch den letzten Zweifler überzeugt haben.
Denn ein &lt;a href=&quot;https://de.wikipedia.org/wiki/STM8&quot;&gt;STM8&lt;/a&gt; Chip kostete mich bei 10 
Stück weniger als 70 Cent pro Stück und das sinkt bei größeren Zahlen noch 
weiter ab.&lt;/p&gt;

&lt;p&gt;Was kann man mit dem Teil also machen?
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;vergleich-mit-attiny84&quot;&gt;Vergleich mit ATtiny84&lt;/h3&gt;

&lt;p&gt;In Sachen Speicher ist der STM8 dem &lt;a href=&quot;http://www.microchip.com/wwwproducts/en/ATtiny85&quot;&gt;ATtiny&lt;/a&gt;
überlegen, kommt aber mit 1 KB RAM nicht an die 2 KB des ATmega328 heran. Und 
von den PINs her ist ähnlich zur ATtiny84/44/24 Serie, hat zwar weniger 
analoge Eingänge, stellt dafür aber ein paar rein digitale Pins mehr bereit.&lt;br /&gt;
&lt;a href=&quot;https://de.wikipedia.org/wiki/Serial_Peripheral_Interface&quot;&gt;SPI&lt;/a&gt; und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/I%C2%B2C&quot;&gt;I2C&lt;/a&gt; sind hier nicht überlappend 
sondern eigenen Pins zugeordnet.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt; &lt;/th&gt;
      &lt;th style=&quot;text-align: right&quot;&gt;STM8S103F3P6&lt;/th&gt;
      &lt;th style=&quot;text-align: right&quot;&gt;ATtiny84&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;CPU&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;16 MHz&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;1/8/16 MHz&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Programmspeicher&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;8 KB&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;8 KB&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;RAM&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;1 KB&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;512 Byte&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;EEPROM&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;640 Bytes&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;512 Byte&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Spannung&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;2.9 V - 5.5 V&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;2 V - 5.5 V&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Standard-Spannung&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;3.3 V&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;5 V&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Analoge Pins&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;5&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;8&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;PWM Pins&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;8&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;4&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;SPI&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;ja&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;ja&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;I2C&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;ja&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;ja&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;UART&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;ja&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;ja&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Das tolle am Board des &lt;a href=&quot;https://www.st.com/en/microcontrollers-microprocessors/stm8s103f3.html&quot;&gt;STM8S103F3P6&lt;/a&gt; 
ist, dass wir gleich einen &lt;a href=&quot;https://de.wikipedia.org/wiki/Micro-USB-Standard&quot;&gt;Mikro-USB&lt;/a&gt; 
Port verbaut haben um ihn zu bestromen. Das Ladekabel vom Mobiltelefon können
wir hier somit gleich nutzen.&lt;br /&gt;
Aber noch besser ist sein Preis von unter einem Euro pro Stück 
(um die 70 Cent je nach Bestellmenge).&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/STM8S103.jpg&quot; alt=&quot;STM8S103 Chip&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;programmierung&quot;&gt;Programmierung&lt;/h3&gt;

&lt;p&gt;Jetzt könnte man denken: Das ist der perfekte ATmega bzw. Arduino UNO Ersatz.&lt;/p&gt;

&lt;p&gt;Nö, leider nicht ganz.&lt;br /&gt;
Denn der für die Arduino IDE bereitgestellte Compiler schafft nur 
&lt;a href=&quot;https://de.wikipedia.org/wiki/C_(Programmiersprache)&quot;&gt;C&lt;/a&gt; und kein
&lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B&quot;&gt;C++&lt;/a&gt;. Das bedeutet, das so gut wie 
keine Arduino Bibliothek nutzbar ist, weil die fast alle mit C++ Objekten 
arbeiten.&lt;/p&gt;

&lt;p&gt;Zwar sind viele der üblichen C++ Arduino Bibliotheken wie z.B. &lt;code&gt;Serial&lt;/code&gt; durch
ähnliche C-Funktionen ersetzt, dennoch bedeutet das einen 
Produktivitätsverlust.&lt;/p&gt;

&lt;p&gt;Der verbaute USB-Port ist leider nicht für die Programmierung nutzbar, sondern
nur für die Stromzufuhr.&lt;br /&gt;
Will man ein Programm auf den Chip brennen, braucht man ein eigenes 
Programmiergerät, z.B. den &lt;a href=&quot;http://www.st.com/en/development-tools/st-link-v2.html&quot;&gt;ST-Link Programmer&lt;/a&gt;. 
Dieser wird mit 4 speziellen zusätzlichen Programmier-Pins verbunden und per USB am
PC angesteckt.&lt;br /&gt;
&lt;img src=&quot;/blog/assets/img/stlink-v2.jpg&quot; alt=&quot;ST-Link V2&quot; /&gt;&lt;br /&gt;
Programmiergerät-Derivate kann man in Fernost aber schon um 1-2 Euro erhalten.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Bisher ist der Chip quasi “nur Teil meiner Sammlung”. Noch habe ich keine
weiteren Experimente mit dem Chip gemacht, außer die üblichen Pin und LED
Tests.&lt;/p&gt;

&lt;p&gt;Wenn man vom C++ Manko absieht ist der Chip aber super für Projekte geeignet,
die sonst z.B. von einem ATtiny84 erledigt werden.&lt;br /&gt;
Ein besonderer Pluspunkt ist sein Preis, denn dieser Chips ist der günstigste
überhaupt, der so viele analoge Pins und ausreichend RAM bereitstellen kann.&lt;/p&gt;

&lt;p&gt;Ich bin schon gespannt wie die ersten Ergebnisse in Projekten aussehen werden,
wo der STM8 seine Stärken unter Beweis stellen kann.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Datenverlust, die zweite ...</title>
   <link href="https://www.opengate.at/blog/2019/08/data-loss-2/"/>
   <published>2019-08-26T12:00:00+02:00</published>
   <updated>2019-08-26T12:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2019/08/data-loss-2</id>
   <category term="hardware" /><category term="software" />
   <summary type="text">Ja leck mich am A…Arm! Was für ein Wochenende!

Das Schlimmste was einem Datenmenschen passieren kann,
ist Datenverlust. 
Siehe November-2018

Und das Schlimmste hoch zwei was passieren kann ist,
wenn sich das wiederholt.
</summary>
   <content type="html">&lt;p&gt;Ja leck mich am A…Arm! Was für ein Wochenende!&lt;/p&gt;

&lt;p&gt;Das Schlimmste was einem Datenmenschen passieren kann,
ist Datenverlust. 
Siehe &lt;a href=&quot;/blog/2018/11/data-loss/&quot;&gt;November-2018&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Und das Schlimmste hoch zwei was passieren kann ist,
wenn sich das wiederholt.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;wie-backups-daten-vernichten-können&quot;&gt;Wie Backups Daten vernichten können&lt;/h3&gt;

&lt;p&gt;Angefangen hat es eigentlich ein paar Tage zuvor in der Firma. Ich liebe es 
ja, dass ich noch Kollegen haben darf, die voll und ganz IT und Technik 
begeistert sind. Übel ist dann nur, wenn man feststellt:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Boah! Die sind mir weit voraus.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Und so fühlte ich mich beim letzten Thema, namentlich 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Datensicherung&quot;&gt;“Backup”&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Zwar habe ich nun recht viel auf mehreren Computern und Servern bis hin
zur &lt;a href=&quot;https://de.wikipedia.org/wiki/Cloud_Computing&quot;&gt;Cloud&lt;/a&gt; verteilt, 
aber tägliche Echtzeit-Backups, und dann noch mit zusätzlicher Sicherung 
über Nacht zum Zweitwohnsitz … nö, da kann ich nicht mithalten.&lt;/p&gt;

&lt;p&gt;Also startete ich einen Backup Anlauf und wollte dabei auch gleich meinen 
Datenmüll ausmisten, durchsortieren und dann geordnet auf unterschiedliche
Medien duplizieren.&lt;/p&gt;

&lt;p&gt;Mein Fehler war (wieder mal), mit dem Müll anzufangen.&lt;br /&gt;
Der war inzwischen gut sortiert und gesichert, als ich zwischendurch 
auf die Idee kam:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Hey, ich seh’ auch gleich meine alten Floppies durch, ob da noch was
Rettenswertes drauf ist und setze einen meiner Alt-PCs so auf,
dass dort ein Retro-Backup läuft.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Der “Retro-Backup-Rechner” war mein altes Asus A7V600 Board mit einem 
&lt;a href=&quot;https://de.wikipedia.org/wiki/AMD_Athlon_XP&quot;&gt;Athlon XP&lt;/a&gt; aus dem Jahr 
2003/2004, welches als einziges meiner Boards 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Diskette&quot;&gt;Floppy&lt;/a&gt;-, 
&lt;a href=&quot;https://de.wikipedia.org/wiki/ATA/ATAPI&quot;&gt;IDE/P-ATA&lt;/a&gt; und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Serial_ATA&quot;&gt;S-ATA&lt;/a&gt; Ports hatte.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/mainboard-a7v600.jpg&quot; alt=&quot;A7V600&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Natürlich musste ich zuerst nachprüfen, ob es denn ein 
&lt;a href=&quot;https://de.wikipedia.org/wiki/BIOS&quot;&gt;BIOS&lt;/a&gt; Update für diese Maschine im Netz
gab … und Ja, es gab eines.&lt;/p&gt;

&lt;p&gt;Und wie wurde das seinerzeit aufgespielt? Richtig, mit einer 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Disk_Operating_System&quot;&gt;DOS&lt;/a&gt;-Startdiskette.
Und weil ich ohnehin Disketten auf dem Tisch liegen hatte, schnappte ich mir 
eine, schmiss sie ins USB-Diskettenlaufwerk und startete den gut bekannten
&lt;a href=&quot;http://sourceforge.net/projects/win32diskimager/&quot;&gt;Win32 Disk Imager&lt;/a&gt;, 
um ein Boot-Diskettenimage auf den Datenträger zu übertragen.&lt;/p&gt;

&lt;p&gt;Das hatte ich noch nie zuvor ausprobiert (sondern nur bei 
&lt;a href=&quot;https://de.wikipedia.org/wiki/SD-Karte&quot;&gt;SD-Karten&lt;/a&gt;), doch nachdem das Laufwerk
angezeigt wurde, dachte ich, dass es problemlos funktionieren sollte.&lt;br /&gt;
Und dann hieß es:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Image auswählen&lt;/li&gt;
  &lt;li&gt;Laufwerk auswählen&lt;/li&gt;
  &lt;li&gt;Den Schreiben-Button klicken&lt;/li&gt;
  &lt;li&gt;1% fertig&lt;/li&gt;
  &lt;li&gt;Access denied&lt;/li&gt;
  &lt;li&gt;Abbruch&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Seltsam. Alles lief mit Administrator-Rechten, und auch auf anderen Disketten 
trat das gleiche Problem auf.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Nun gut, muss ja nicht heute sein.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;… war mein nächster Gedanke.&lt;/p&gt;

&lt;p&gt;**Und als ich eine Stunde später meinen Rechner neu startete, **
**waren die Hälfte meiner Laufwerke weg. … W.T.F. ?? **&lt;/p&gt;

&lt;p&gt;Genau genommen waren es jene Laufwerke meiner primären Datenplatte, wo 
Partitionen für die Softwareentwicklung, Programm-Archive und die neu
angelegten Backups gespeichert waren.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;An dieser Stelle möchte ich mich über den abgesetzten Aufschrei,&lt;/em&gt; 
&lt;em&gt;der in allen südlichen Wiener Bezirken am Sonntag zu hören war,&lt;/em&gt; 
&lt;em&gt;hiermit entschuldigen.&lt;/em&gt;&lt;/p&gt;

&lt;h3 id=&quot;was-war-geschehen&quot;&gt;Was war geschehen?&lt;/h3&gt;

&lt;p&gt;Nach viel Verzweiflung und einigen fehlgeschlagenen Platten-Restore-Versuchen
gelang mir dann die &lt;strong&gt;Wiederherstellung der Partitionstabelle&lt;/strong&gt; und alle 
Laufwerke waren wieder da. Der Held der Stunde heißt:
&lt;a href=&quot;http://de.minitool.com&quot;&gt;“MiniTool Partition Wizard Pro 11.5”&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/software-minitool-partition-wizard.gif&quot; alt=&quot;MiniTool Partition Wizard&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Meine Vermutung ist, dass der &lt;code&gt;Win32 Disk Imager&lt;/code&gt; anstatt auf 
Floppy Drive “0” das Disketten-Image auf &lt;code&gt;PhysicalDrive0&lt;/code&gt; geschrieben hatte, wo die 
Partitionstabelle ungeschützt, aber die anschließende erste Partition gesperrt 
war … daher das &lt;code&gt;Access Denied&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Das Problem wurde erst beim nächsten Rechnerstart wirksam, als beim Start die 
Partitionen neu eingelesen werden sollten. Und man konnte das Chaos in der
Tabelle auch in der Windows Datenträgerverwaltung wunderbar sehen.&lt;/p&gt;

&lt;p&gt;Diesen vermeintlichen Bug im Win32 Disk Imager werde ich aber noch nachgehen!&lt;/p&gt;

&lt;h3 id=&quot;was-wäre-wenn&quot;&gt;Was wäre wenn?&lt;/h3&gt;

&lt;p&gt;Naja, wäre die Platte einfach so eingegangen, hätte ich das auch überlebt.
Zwar wäre die Arbeit von einer Woche weg gewesen, doch dank GIT und Fileserver
sind sowieso alle wichtigen Daten verteilt gespeichert.&lt;/p&gt;

&lt;p&gt;Doch es hätte mich schon sehr geärgert, wenn ich wieder alles neu 
zusammenstellen hätte müssen.&lt;/p&gt;

&lt;p&gt;Auch lade ich gerne Programme und Dokumente herunter, die für eine 
spätere “Abarbeitung” ungesichert in Ordnern liegen, ganz zu schweigen von
vielen VMs, die zwar entbehrlich, aber dennoch mühsam in der Rekonstruktion
sind, wenn man sie mal braucht.&lt;/p&gt;

&lt;p&gt;Ich denke, ich werden mich also doch an meinen übervorsichtigen Kollegen
orientieren, die täglich ihre Backup-Prozedur laufen lassen und so bei 
Ausfällen nur wenig verlieren.&lt;/p&gt;

&lt;p&gt;Jedenfalls hat sich wieder einmal folgendes bewahrheitet:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Aus Schaden wird man klug!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;nachtrag-ja-win32diskimager-war-schuld&quot;&gt;Nachtrag: Ja, Win32DiskImager war Schuld&lt;/h3&gt;

&lt;p&gt;Meine uralte Version aus dem Jahr 2013, die mir bei SD Karten immer wieder
gute Dienste erwies, hat laut Internet den bekannten Bug mit USB-Floppies 
fehlerhaft zu arbeiten und Festplatten zu korrumpieren.&lt;br /&gt;
Es gibt aber eine neue Version des Tools, wo der Fehler nicht mehr auftreten
soll … ausprobieren werde ich das aber sicher nicht!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>ATtiny84: 85er mit mehr Pins</title>
   <link href="https://www.opengate.at/blog/2019/08/attiny84/"/>
   <published>2019-08-24T12:00:00+02:00</published>
   <updated>2019-08-24T12:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2019/08/attiny84</id>
   <category term="hardware" />
   <summary type="text">Die Chips des ATtiny85/45/25 
sind bei uns inzwischen gut bekannt und werden als Arduino Alternative (genau 
genommen ATmega328 Alternative) gehandelt.
Mit insgesamt 8 PINs bleiben uns allerdings nur 3 digitale und 2 analoge
Ausgänge für Anwendungen übrig.

Doch es gibt da noch den mittleren Bruder in Form des 
ATtiny84/44/24
zwischen der ATtiny und ATmega Serie.
</summary>
   <content type="html">&lt;p&gt;Die Chips des &lt;a href=&quot;http://www.microchip.com/wwwproducts/en/ATtiny85&quot;&gt;ATtiny85/45/25&lt;/a&gt; 
sind bei uns inzwischen gut bekannt und werden als Arduino Alternative (genau 
genommen ATmega328 Alternative) gehandelt.&lt;br /&gt;
Mit insgesamt 8 PINs bleiben uns allerdings nur 3 digitale und 2 analoge
Ausgänge für Anwendungen übrig.&lt;/p&gt;

&lt;p&gt;Doch es gibt da noch den mittleren Bruder in Form des 
&lt;a href=&quot;http://www.microchip.com/wwwproducts/en/ATtiny84&quot;&gt;ATtiny84/44/24&lt;/a&gt;
zwischen der ATtiny und ATmega Serie.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;die-attiny4-serie&quot;&gt;Die ATtiny*4 Serie&lt;/h3&gt;

&lt;p&gt;Die ATtiny*4 Chips passen auf einen 14 Pin Sockel und bieten uns für
Anwendungen gleich 11 &lt;a href=&quot;https://de.wikipedia.org/wiki/Allzweckeingabe/-ausgabe&quot;&gt;GPIO&lt;/a&gt;
Pins an, davon 8 analoge und 3 rein digitale.
(Und natürlich lassen sich die analogen auch wie digitale nutzen.)&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/attiny84-pins.jpg&quot; alt=&quot;ATtiny84 Pins&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Damit sind wir schon viel näher an einem ATmega328 dran, brauchen aber 
immer noch weniger Strom und können den internen Taktgeber auf 
1 Megahertz herunter takten.&lt;/p&gt;

&lt;p&gt;Beim Speicher sieht es aber genau so limitiert aus, wie bei der 85/45/25
Serie, denn hier gilt:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Serie&lt;/th&gt;
      &lt;th style=&quot;text-align: right&quot;&gt;RAM&lt;/th&gt;
      &lt;th style=&quot;text-align: right&quot;&gt;EEPROM&lt;/th&gt;
      &lt;th style=&quot;text-align: right&quot;&gt;Prog. Flash&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;85 oder 84&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;512 Bytes&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;512 Bytes&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;8 KB&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;45 oder 44&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;256 Bytes&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;256 Bytes&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;4 KB&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;25 oder 24&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;128 Bytes&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;128 Bytes&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;2 KB&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Arge Grafiken oder lange Statistiken lassen sich auf Grund des fehlenden
RAMs bzw. des geringen Programm-Speichers nicht auf den kleinen Chip brennen.&lt;br /&gt;
Doch er eignet sich gut, um Daten von mehreren Sensoren weiterzugeben, oder
mehrere Tastenerkennungen oder Strommessungen durchzuführen.&lt;/p&gt;

&lt;p&gt;Wer noch den einen oder anderen &lt;a href=&quot;https://de.wikipedia.org/wiki/ESP8266&quot;&gt;ESP8266-1&lt;/a&gt;
bei sich herumliegen hat, kann dessen serielle Pins mit denen eines ATtiny84 
zusammen schließen und dann vom WLAN des ESP8266 heraus Geräte, die am ATtiny 
hängen, auslesen.&lt;/p&gt;

&lt;p&gt;Nachdem die ATtinys alle mit Spannungen von 2 bis 5.5 Volt betrieben 
werden können, sind sie auch mit den 3.3 Volt der ESP Serie kompatibel.&lt;/p&gt;

&lt;h3 id=&quot;programmierung&quot;&gt;Programmierung&lt;/h3&gt;

&lt;p&gt;Natürlich existiert für die Arduino IDE ein Board Package, das man installieren
kann. Unter http://highlowtech.org/?p=1695 findet man ein Beschreibung,
doch grundsätzlich fügt man die Board-URL
https://raw.githubusercontent.com/damellis/attiny/ide-1.6.x-boards-manager/package_damellis_attiny_index.json
in der Arduino IDE hinzu und sucht im Board-Manager nach ATtiny und sollte
dann auch gleich den ATtiny-Board Eintragen finden.&lt;/p&gt;

&lt;p&gt;Wenn man sich kein eigenes Programmiergerät kaufen will, funktioniert man
am besten einen Arduino UNO zu einem Programmer um, in dem man das
Arduino-as-ISP-Sketch auf ihn hochlädt.&lt;br /&gt;
Dann verbindet man noch die Pins D10, D11, D12 und D13 am UNO mit den Pins
4 (RST), 7 (MOSI/A6), 8 (MISO/A5) und 9 (SCL/A4) des ATtiny84, nebst 
Pluspol auf 1 (VCC) und Minuspol auf 2 (GND).&lt;/p&gt;

&lt;p&gt;Und schon können wir über den UNO ein Sketch kompilieren und auf den ATtiny
übertragen, wenn Arduino-as-ISP als Programmiergerät in der IDE eingestellt 
ist. Also so wie immer, wenn man einen Chip über einen Arduino UNO 
programmieren will.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/attiny84-program.jpg&quot; alt=&quot;ATtiny84 Programming&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;anwendungen-und-problemchen&quot;&gt;Anwendungen und Problemchen&lt;/h3&gt;

&lt;p&gt;Das größte Problem bei Arduino-Bibliotheken ist, dass sie die ATtinys 
generell oft nicht “bedenken” und von der Pin-Belegung des UNOs ausgehen.
Auch kann es sein, dass es abhängig von der eingestellten Prozessortaktung
zu falschen Frequenz- oder Verzögerungswerten kommt.&lt;/p&gt;

&lt;p&gt;Daher muss man nach Bibliotheken suchen, die ATtinys unterstützen oder
eigens für sie geschrieben wurden. Da kann es schon mal etwas dauern
bis man nach ein paar Fehlschlägen die richtige Softwarelösung
gefunden hat.&lt;/p&gt;

&lt;p&gt;Ich selbst stehe hier auch noch am Anfang, freue mich aber mit dieser
MCU ein Mittelding zwischen ATtiny85 und ATmega368 gefunden zu haben.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ein netter IC, nicht perfekt was die Softwareunterstützung anbelangt
aber macht Spaß, mal was “selbst” implementieren zu müssen um das 
Potential des Chips auszunutzen.&lt;/p&gt;

&lt;p&gt;Während man die 85/45/25 beim Elektronikladen um die Ecke findet, 
konnte ich die 84/44/24 Serie in unseren Breiten nicht entdecken.&lt;/p&gt;

&lt;p&gt;In Asien kostet der Chip in der Sockelfassung aktuell mit rund 2 Euro pro 
Stück doppelt so viel wie ein günstiger ATmega328.&lt;br /&gt;
In Summe ist das aber dennoch recht wenig und der Chip spart dafür 
Energiekosten ein, was bei Batterieprojekten wieder als Vergünstigung
wirkt.&lt;/p&gt;

&lt;p&gt;Alles in allem eine Empfehlung und ein Experiment wert.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Arduino am Steckbrett - geht nicht ??</title>
   <link href="https://www.opengate.at/blog/2019/08/breadboard-tutorial/"/>
   <published>2019-08-18T12:00:00+02:00</published>
   <updated>2019-08-18T12:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2019/08/breadboard-tutorial</id>
   <category term="hardware" />
   <summary type="text">Wenn mich etwas nervt, dann sind das Fehlschläge obwohl ich es 
genau so mache wie in einem Tutorial im Netz oder auf Youtube.

Ein Beispiel, über das ich schon öfters gestolpert bin 
(weil ich den richtigen Weg immer wieder vergesse), ist das Setup
eines ATmega328p direkt auf einem 
Breadboard
mit seinem 8MHz internen Quarz.

Folgt man den Anweisungen auf arduino.cc
bekommt man bzw. bekomme ich die Meldung:


  Yikes! Invalid device signature.

</summary>
   <content type="html">&lt;p&gt;Wenn mich etwas nervt, dann sind das Fehlschläge obwohl ich es 
&lt;em&gt;genau so&lt;/em&gt; mache wie in einem Tutorial im Netz oder auf Youtube.&lt;/p&gt;

&lt;p&gt;Ein Beispiel, über das ich schon öfters gestolpert bin 
(weil ich den richtigen Weg immer wieder vergesse), ist das Setup
eines &lt;a href=&quot;https://en.wikipedia.org/wiki/ATmega328&quot;&gt;ATmega328p&lt;/a&gt; direkt auf einem 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Steckplatine&quot;&gt;Breadboard&lt;/a&gt;
mit seinem 8MHz internen Quarz.&lt;/p&gt;

&lt;p&gt;Folgt man den Anweisungen auf &lt;a href=&quot;https://www.arduino.cc/en/Tutorial/ArduinoToBreadboard&quot;&gt;arduino.cc&lt;/a&gt;
bekommt man bzw. bekomme ich die Meldung:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Yikes! Invalid device signature.
&lt;!--more--&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;hr /&gt;

&lt;p&gt;Zuerst mal kurz und prägnant die Lösung:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Der ATmega328 ist mit dem Standard Bootloader und 16 MHz externen 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Oszillator&quot;&gt;Oszillator&lt;/a&gt;
konfiguriert. Ohne diesen Taktgeber läuft er nicht.&lt;br /&gt;
Man muss entweder das Bauteil an die Pins 9 und 10 anschließen oder den Chip
in einem Uno-Board “brennen”.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Und jetzt das ganze nochmals mit etwas &lt;a href=&quot;https://de.wikipedia.org/wiki/Prosa&quot;&gt;Pros&lt;/a&gt;
verfeinert:&lt;/p&gt;

&lt;h3 id=&quot;ziel-atmega328p-ohne-uno-board-direkt-betreiben&quot;&gt;Ziel: ATmega328p ohne UNO Board direkt betreiben&lt;/h3&gt;

&lt;p&gt;Kleine Aufgaben kann der ATmega328 ganz leicht ohne weitere Bauteile erledigen.
Er hat nämlich einen 8 MHz Quarz-Oszillator verbaut, mit dem er autonom 
arbeiten kann, sobald er Strom (so ab 3 Volt) zugeführt bekommt.&lt;/p&gt;

&lt;p&gt;Wegen der anderen Taktfrequenz, kann man aber nicht mehr die “normale” 
Arduino UNO Konfiguration nutzen (die ja auf 16 MHz ausgelegt ist),
sondern man installiert dafür ein eigenes 
&lt;strong&gt;ATmega328 on breadboard (Internal 8 MHz internal clock)&lt;/strong&gt; Board-Package
und kompiliert die Sketches eben dort.&lt;/p&gt;

&lt;p&gt;Das ist auch gut auf &lt;a href=&quot;http://www.arduino.cc/en/Tutorial/ArduinoToBreadboard&quot;&gt;arduino.cc dokumentiert&lt;/a&gt;
und läuft so ab:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.arduino.cc/en/uploads/Tutorial/breadboard-1-6-x.zip&quot;&gt;breadboard-1-6-x.zip&lt;/a&gt; 
herunterladen.&lt;/li&gt;
  &lt;li&gt;Den Inhalt dann nach &lt;code&gt;%USERPROFILE%\Documents\Arduino\hardware&lt;/code&gt; kopieren.
(Falls &lt;code&gt;hardware&lt;/code&gt; noch nicht existiert, den Ordner einfach anlegen).
Am Ende befindet sich dann im &lt;code&gt;hardware&lt;/code&gt; Ordner das Unterverzeichnis 
&lt;code&gt;breadboard&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Arduino_IDE&quot;&gt;Arduino IDE&lt;/a&gt; neustarten, damit 
man den Eintrag &lt;em&gt;ATmega328 on breadboard (Internal 8 MHz internal clock)&lt;/em&gt;
im Board-Menü finden kann.&lt;/li&gt;
  &lt;li&gt;Nun nimmt man ein fertiges Arduino UNO Board, steckt es an und lädt den 
Sketch &lt;code&gt;Examples/ArduinoISP/ArduinoISP&lt;/code&gt; auf dieses Board (und zwar noch mit
den üblichen UNO Einstellungen - also Board &lt;code&gt;Arduino/Genuino UNO&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, und jetzt käme es eigentlich zum Verkabeln der PINs 10, 11, 12, 13 am 
Board mit den Breadboard-PINs 0, 17, 18, 19 und laut Tutorial zum brennen des 
Bootloaders über die &lt;code&gt;Arduino as ISP&lt;/code&gt; Einstellung mit dem neu installierten
Breadboard-Setup.&lt;/p&gt;

&lt;p&gt;Aber Fehlanzeige, die oben erwähnte Meldung&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Yikes! Invalid device signature.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;killt die gute Laune.&lt;/p&gt;

&lt;h3 id=&quot;die-korrekte-lösung&quot;&gt;Die korrekte Lösung:&lt;/h3&gt;

&lt;p&gt;Man braucht also ein zweites UNO Board, wo man den Chip wechseln kann 
(also KEINE &lt;a href=&quot;https://de.wikipedia.org/wiki/Surface-mounted_device&quot;&gt;SMD&lt;/a&gt; 
Variante), oder man baut den Oszillator samt 22pF Kondensatoren gegen Ground
auf ein Steckbrett, und startet den Chip dann im “üblichen” Modus.&lt;/p&gt;

&lt;p&gt;So kann man dann den neuen 8-MHz Bootloader aufspielen.&lt;/p&gt;

&lt;p&gt;Sobald dieser Schritt abgeschlossen ist, kann man den ATmega328 vom UNO
Board entfernen und alles weitere am Breadboard (ohne Osziallator) erledigen. 
Weitere Bootloader oder Sketch-Uploads sollten nun funktionieren.&lt;/p&gt;

&lt;h3 id=&quot;und-noch-ne-info-zum-abschluss&quot;&gt;Und noch ‘ne Info zum Abschluss:&lt;/h3&gt;

&lt;p&gt;Nicht vergessen, dass ein am Breadboard verbauter Oszillator nicht durch
längere Leitungswege oder Schalter zu sehr vom Chip abgeschnürt ist.
&lt;a href=&quot;/blog/2019/05/22-pf-oscillator/&quot;&gt;Wie ich schon lernen musste&lt;/a&gt; 
kann eine solche Konstellation auch eine unnötige Spaßbremse sein.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/arduino-breadboard.jpg&quot; alt=&quot;Arduino Breadboard&quot; /&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Windows Phone / Mobile</title>
   <link href="https://www.opengate.at/blog/2019/08/windows-phone/"/>
   <published>2019-08-16T13:00:00+02:00</published>
   <updated>2019-08-16T13:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2019/08/windows-phone</id>
   <category term="hardware" /><category term="retro" />
   <summary type="text">Seit etwa 8 Jahren steckt ein sogenanntes Smartphone
mit Microsoft Logo in meiner 
Hosentasche.

Anfangs fühlte ich mich noch als “Geek” damit …
heute wird man damit eher verlegen angelächelt, als hätte man eine 
schwere geistige oder körperliche Behinderung.

Wie kam es nur so weit?
</summary>
   <content type="html">&lt;p&gt;Seit etwa 8 Jahren steckt ein sogenanntes &lt;a href=&quot;https://de.wikipedia.org/wiki/Smartphone&quot;&gt;Smartphone&lt;/a&gt;
mit &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft&quot;&gt;Microsoft&lt;/a&gt; Logo in meiner 
Hosentasche.&lt;/p&gt;

&lt;p&gt;Anfangs fühlte ich mich noch als “Geek” damit …
heute wird man damit eher verlegen angelächelt, als hätte man eine 
schwere geistige oder körperliche Behinderung.&lt;/p&gt;

&lt;p&gt;Wie kam es nur so weit?
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Es begann eigentlich so um 2007/2008 als ich in der &lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B&quot;&gt;C++&lt;/a&gt;
Entwicklung mit der Aufgabe konfrontiert war, die Software auch so zu 
schreiben, dass sie am &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_CE&quot;&gt;Windows CE&lt;/a&gt; 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Electronic_Organizer&quot;&gt;Oraganizer&lt;/a&gt; meines Chefs 
laufen kann.&lt;/p&gt;

&lt;p&gt;Diese kleinen Terminplaner und E-Mailreader waren damals noch in kleinem
Rahmen verbreitet.&lt;br /&gt;
Doch mit der Einführung des &lt;a href=&quot;https://de.wikipedia.org/wiki/IPhone&quot;&gt;iPhones&lt;/a&gt; 
verloren diese Geräte mehr und mehr an Bedeutung.&lt;br /&gt;
Ich selbst habe so ein Gerät übrigens nie besessen.&lt;/p&gt;

&lt;p&gt;Doch der Gedanke, ich könnte Windows-Software auch für kleine 
“intelligente Geräte” schreiben gefiel mir sehr und steht ja auch heute noch
auf meiner TODO-Liste.&lt;/p&gt;

&lt;p&gt;Und so kam es, dass ich um 2010/2011 den Schritt wagte, mir ein auslaufendes
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_Mobile&quot;&gt;Windows Mobile 6&lt;/a&gt; 
Teil zu kaufen, das mein altes 0815 Nokia-Mobiltelefon ersetzen sollte.&lt;/p&gt;

&lt;p&gt;Windows Mobile ist nichts anderes als Windows CE mit einer etwas anderen
Oberfläche. Während ein reines Windows CE eine Windows 95/2000 
Desktop Oberfläche mit Taskleiste zeigt, startet Windows Mobile eine
Übersicht über Uhrzeit, Termine und ungelesene E-Mails.&lt;/p&gt;

&lt;p&gt;Windows Mobile 6 basiert auf Windows CE 5, und nicht wie ich damals dachte auf
Windows CE 6. Installiert man also das Windows Mobile 6 SDK für Visual Studio, 
kann man auch Windows CE 5 Applikationen damit schreiben, die dann dank 
Kompatibilität auch auf Windows CE 6 ausführbar sind (… meistens …).&lt;/p&gt;

&lt;p&gt;Dann folgte mit &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_Phone_7&quot;&gt;Windows Phone 7&lt;/a&gt;
Microsofts Abschied von der Marke “Windows Mobile” und Windows CE. Zwar 
basierte “Windows Phone 7” auf einem Windows CE Derivat, begann aber sich von 
der etablierten &lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_Application_Programming_Interface&quot;&gt;Windows API&lt;/a&gt;
zu trennen. Entwickelt werden sollte nur noch in den elends-langsamen 
verwalteten Sprachen wie &lt;a href=&quot;https://en.wikipedia.org/wiki/C_Sharp_(programming_language)&quot;&gt;C#&lt;/a&gt; 
oder &lt;a href=&quot;https://en.wikipedia.org/wiki/Visual_Basic_.NET&quot;&gt;VB.NET&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Meines Erachtens war das der erste Todesstoß für die Plattform. Denn vor 
2010 gab es ja doch noch eine Reihe von Windows-CE/Mobile Apps, die mit
Windows Phone 7 alle funktionsunfähig wurden. Und niemand machte sich 
dann die Mühe seine Apps vollkommen neu zu schreiben.&lt;br /&gt;
Denn gegenüber &lt;a href=&quot;https://en.wikipedia.org/wiki/Objective-C&quot;&gt;Object-C&lt;/a&gt; von 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Apple&quot;&gt;Apple&lt;/a&gt; und dem damals noch jungem 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Android_%28Betriebssystem%29&quot;&gt;Android&lt;/a&gt; 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Java_(Programmiersprache)&quot;&gt;Java&lt;/a&gt;,
sah die “neue” Microsoft API unattraktiv, veraltet und vor allem inkompatibel 
aus.&lt;/p&gt;

&lt;p&gt;Es folgte &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_Phone_8&quot;&gt;Windows Phone 8&lt;/a&gt;, 
welches vom CE Kern auf den Windows-NT Kernel wechselte. Doch auch hier blieb 
man von der Windows-API abgeschnitten, die es gut versteckt im Systemkern gab 
und musste mit einer eigenen Phone-Versionen von &lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_Studio&quot;&gt;Visual Studio&lt;/a&gt;
herumeiern.&lt;/p&gt;

&lt;p&gt;Mit &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_10_Mobile&quot;&gt;Windows 10 Mobile&lt;/a&gt;, 
also dem Windows Phone-Derivat basierend auf dem Windows 10 Kern, wollte 
Microsoft wieder alles in Ordnung bringen. Die 
&lt;a href=&quot;https://en.wikipedia.org/wiki/Universal_Windows_Platform&quot;&gt;Windows Universal Platform&lt;/a&gt; 
hätte die Entwicklung von Desktop-Apps und Phone-Apps vereinheitlichen können 
und machte - aus meiner Sicht - gar kein so schlechtes Bild.&lt;/p&gt;

&lt;p&gt;Doch es war zu spät. Man hatte von 2010 bis 2015 jeden motivierten 
Phone-Entwickler verärgert und in Richtung Android und iPhone verjagt.
Jetzt hatte Microsoft eine Smartphone-Plattform, die den Namen verdient hätte,
die nun aber keiner mehr brauchte und wollte.&lt;/p&gt;

&lt;p&gt;Tja, so kann man eine eigentlich gute Idee, nämlich eine Smartphone Plattform,
die nahtlos mit dem Desktop zusammenarbeitet (so wie es Windows Mobile schon 
seit dem Jahr 2000 angeboten hatte), zerstören.&lt;/p&gt;

&lt;h3 id=&quot;meine-windows-phones&quot;&gt;Meine Windows Phones:&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/winphone-collection.jpg&quot; alt=&quot;My Windows Phones&quot; /&gt;&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Samsung SGH-i200
    &lt;ul&gt;
      &lt;li&gt;Gekauft im Jahr 2010&lt;/li&gt;
      &lt;li&gt;Windows Mobile 6.1&lt;/li&gt;
      &lt;li&gt;CPU 260 MHz&lt;/li&gt;
      &lt;li&gt;Bild: 240 x 320 Pixel&lt;/li&gt;
      &lt;li&gt;Kamera: 2 MPixel&lt;/li&gt;
      &lt;li&gt;Fazit: Ein Witz! Das Gerät nennt sich “Smart-Phone” und ist das Gegenteil.
Ohne WLAN kann man das Internet nur über USB und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/ActiveSync&quot;&gt;Active-Sync&lt;/a&gt; nutzen … 
also gar nicht. Keine Apps, wenig Funktionen&lt;br /&gt;
&lt;img src=&quot;/blog/assets/img/winphone-sghi200.jpg&quot; alt=&quot;SGH-i200&quot; /&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Samsung Omnia Pro B7350
    &lt;ul&gt;
      &lt;li&gt;Gekauft im Jahr 2011&lt;/li&gt;
      &lt;li&gt;Windows Mobile 6.5&lt;/li&gt;
      &lt;li&gt;CPU: 600 MHz&lt;/li&gt;
      &lt;li&gt;Bild: 320 x 320 Pixel&lt;/li&gt;
      &lt;li&gt;Kamera: 3,2 MPixel&lt;/li&gt;
      &lt;li&gt;WLAN (aber nur WPA2-TKIP), Bluetooth&lt;/li&gt;
      &lt;li&gt;Fazit: Ganz OK. Damals mit den alten WLAN Router super, man konnte ins
Netz und sogar ein bisschen browsen und Mails lesen. Es gab YouTube und RSS
Apps, also brauchbar. Mit neueren WLAN Routern und WPA2-AES leider nutzlos 
geworden und die Apps kommen mit HTTPS nicht mehr klar.&lt;br /&gt;
&lt;img src=&quot;/blog/assets/img/winphone-b7350.jpg&quot; alt=&quot;B7350&quot; /&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Samsung Omnia 7
    &lt;ul&gt;
      &lt;li&gt;Gekauft im Jahr 2012&lt;/li&gt;
      &lt;li&gt;Windows Phone 7&lt;/li&gt;
      &lt;li&gt;CPU 1 GHz&lt;/li&gt;
      &lt;li&gt;Bild: 480 x 800 Pixel&lt;/li&gt;
      &lt;li&gt;Kamera: 5 MPixel&lt;/li&gt;
      &lt;li&gt;WLAN, Bluetooth&lt;/li&gt;
      &lt;li&gt;Fazit: Hatte es nur kurz im Einsatz und war eher eine Enttäuschung.
Die wenigen Apps dafür neigten zum Abstürzen und der Web-Browser war
veraltet bzw. nicht voll web-tauglich.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Nokia Lumia 520
    &lt;ul&gt;
      &lt;li&gt;Gekauft im Jahr 2014&lt;/li&gt;
      &lt;li&gt;Windows Phone 8.1&lt;/li&gt;
      &lt;li&gt;CPU: 1 GHz Dualcore&lt;/li&gt;
      &lt;li&gt;Bild: 480 x 800 Pixel&lt;/li&gt;
      &lt;li&gt;Kamera: 5 MPixel&lt;/li&gt;
      &lt;li&gt;WLAN, Bluetooth, GPS&lt;/li&gt;
      &lt;li&gt;Fazit: Mit dem Teil war ich recht zufrieden. Es reagierte recht
schnell und auch die Web-Nutzung war besser als mit dem Vorgänger.
Vor allem die GPS- und Karten-Navigation ersetzte mein altes 
Garmin Navi im Auto.&lt;br /&gt;
&lt;img src=&quot;/blog/assets/img/winphone-lumia520.jpg&quot; alt=&quot;Lumia 520&quot; /&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Microsoft Lumia 550
    &lt;ul&gt;
      &lt;li&gt;Gekauft im Jahr 2016&lt;/li&gt;
      &lt;li&gt;Windows 10 Mobile&lt;/li&gt;
      &lt;li&gt;CPU: 1.1 GHz Quadcore&lt;/li&gt;
      &lt;li&gt;Bild: 720 X 1280 Pixel&lt;/li&gt;
      &lt;li&gt;Kamera: 5 MPixel&lt;/li&gt;
      &lt;li&gt;WLAN, Bluetooth, GPS&lt;/li&gt;
      &lt;li&gt;Fazit: Mein Liebling, mit dem ich lange Zeit viel Freude hatte.
Dank Edge bis heute ein vernünftiges Browsen. Skype voll integriert und
mit einigen Apps nachgerüstet.&lt;br /&gt;
&lt;img src=&quot;/blog/assets/img/winphone-lumia550.jpg&quot; alt=&quot;Lumia 550&quot; /&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Nokia Lumia 720
    &lt;ul&gt;
      &lt;li&gt;Abverkauft im Jahr 2017&lt;/li&gt;
      &lt;li&gt;Windows Phone 8.1 mit Upgrade auf Windows Mobile 10&lt;/li&gt;
      &lt;li&gt;CPU: 1 GHz Dualcore&lt;/li&gt;
      &lt;li&gt;Bild: 480 x 800 Pixel&lt;/li&gt;
      &lt;li&gt;Kamera: 6.7 MPixel&lt;/li&gt;
      &lt;li&gt;WLAN, Bluetooth, GPS, RFID&lt;/li&gt;
      &lt;li&gt;Fazit: Hab es nur für Programmiertests mit &lt;a href=&quot;https://de.wikipedia.org/wiki/Near_Field_Communication&quot;&gt;NFC&lt;/a&gt; 
/ &lt;a href=&quot;http://duckduckgo.com/?q=RFID&amp;amp;atb=v202-3&amp;amp;ia=web&quot;&gt;RFID&lt;/a&gt; angeschafft.
War meinem Lumia 550 unterlegen, außer eben für RFID, dafür 
ist es bis heute gut geeignet, fiel aber mit Win10-1604 
bereits aus dem Supportzyklus.&lt;br /&gt;
&lt;img src=&quot;/blog/assets/img/winphone-lumia720.jpg&quot; alt=&quot;Lumia 720&quot; /&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Microsoft Lumia 950
    &lt;ul&gt;
      &lt;li&gt;Gekauft im Jahr 2018&lt;/li&gt;
      &lt;li&gt;Windows 10 Mobile&lt;/li&gt;
      &lt;li&gt;CPU: 1.8 GHz Hexacore&lt;/li&gt;
      &lt;li&gt;Bild: 1440 x 2560 Pixel&lt;/li&gt;
      &lt;li&gt;Kamera: 20 MPixel&lt;/li&gt;
      &lt;li&gt;WLAN, Bluetooth, GPS&lt;/li&gt;
      &lt;li&gt;Fazit: Bist du deppert, sind das geile Fotos! Obwohl mir das 
bisher recht egal war, stelle ich fest: Mit 20 Megapixel kann ich 
auch meine Hardware abfotografieren und auf dem Bild jede Leiterbahn
nachvollziehen … das war mit den Fotos meiner anderen Telefone
unmöglich.&lt;br /&gt;
&lt;img src=&quot;/blog/assets/img/winphone-lumia950.jpg&quot; alt=&quot;Lumia 950&quot; /&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

</content>
 </entry>
 
 <entry>
   <title>Freie Energie?</title>
   <link href="https://www.opengate.at/blog/2019/08/free-energy/"/>
   <published>2019-08-15T12:00:00+02:00</published>
   <updated>2019-08-15T12:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2019/08/free-energy</id>
   <category term="general" />
   <summary type="text">Vor 15 Jahren hatte ich (mea culpa) eine liebe ältere Kollegin auf den Arm
genommen (nicht physisch!), die sich immer vor “Strahlen” gefürchtet hatte, 
in dem ich ihr eine Schilderung aus meinem Physikunterricht der Unterstufe etwas 
dramatisch nacherzählte:


  Früher konnte man Glühbirnen oder Leuchtstoffröhren ohne Strom
zum Leuchten bringen, wenn man sie (auf korrekte Längen und
Drahtdicken gestutzt) vor Radiosenderanlagen in die Luft hielt.


Wow! Hätte man das Claus Turtur 
erzählt, wäre wohl eine ganze Horde seiner Anhänger samt Aluhüten dort 
hingepilgert um dort die unendliche Energie des Universums anzuzapfen.
</summary>
   <content type="html">&lt;p&gt;Vor 15 Jahren hatte ich (mea culpa) eine liebe ältere Kollegin auf den Arm
genommen (nicht physisch!), die sich immer vor “Strahlen” gefürchtet hatte, 
in dem ich ihr eine Schilderung aus meinem Physikunterricht der Unterstufe etwas 
dramatisch nacherzählte:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Früher konnte man Glühbirnen oder Leuchtstoffröhren ohne Strom
zum Leuchten bringen, wenn man sie (auf korrekte Längen und
Drahtdicken gestutzt) vor Radiosenderanlagen in die Luft hielt.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Wow! Hätte man das &lt;a href=&quot;https://peswiki.com/powerpedia:claus-w-turtur&quot;&gt;Claus Turtur&lt;/a&gt; 
erzählt, wäre wohl eine ganze Horde seiner Anhänger samt Aluhüten dort 
hingepilgert um dort die unendliche Energie des Universums anzuzapfen.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Wie komme ich eigentlich darauf?&lt;/p&gt;

&lt;p&gt;Naja, es war wieder mal Zeit Hardware einzukaufen, und wenn noch Platz im
virtuellen Einkaufswagen ist, wird der eben mit “allerlei” gefüllt.&lt;/p&gt;

&lt;p&gt;Und dieser witzige Dioden-Käfer, der ohne Stromquelle eine LED zum
Leuchten bringt, erinnerte mich an diese obskure “freie Energie” Debatte
und somit hab ich jetzt wieder einen Staubfänger mehr in der Wohnung.&lt;/p&gt;

&lt;p&gt;Ich finde ja alle Arten der “Energiegewinnung”, die einem zum Basteln
motivieren grundsätzlich super … auch wenn sie letztendlich nur wenig
bringen (denke da an meine Piezzo-Stromschuhe).&lt;/p&gt;

&lt;p&gt;Gefährlich wird es aber, wenn aus Interessen und eigenen Beobachtungen
neue Religionen werden, die zu aller erst mal auf die Wissenschaft losgehen
und einfach behaupten, die Wissenschaft würde geheimes Wissen verbergen und
dessen Veröffentlichung absichtlich verhindern um keine Änderungen der
Weltordnung möglich zu machen.&lt;/p&gt;

&lt;p&gt;Es mag ja durchaus stimmen, dass manche Riesenkonzerne bewusst Patente für
Technologieverbesserungen aufkaufen und absichtlich in der Schublade 
verstauben lassen, damit ihr aktuelles Produkt weniger Konkurrenz hat,
doch den Universitäten solche Taktiken vorzuwerfen ist hochgradig unsachlich.&lt;/p&gt;

&lt;p&gt;Nicht, dass dort immer alles perfekt abläuft, doch auf eines kann man sich
verlassen: Wenn eine Entdeckung per Experiment reproduzierbar bewiesen 
werden kann, dann wird das nicht geleugnet.&lt;/p&gt;

&lt;p&gt;Und eben genau diese Experimente wollen bei den “kreativen Erfindungen”
solcher Wissenschaft-Rebellen leider immer nur zu Hause funktionieren und nie 
im Labor (oder anderswo auf der Welt).&lt;/p&gt;

&lt;p&gt;Aber es ist natürlich leichter zu behaupten, man hätte den heiligen Gral ja
schon gefunden und nur unüberwindliche politische Widerstände verhindern es
den Gralsfund anerkennen zu lassen.&lt;/p&gt;

&lt;p&gt;Und das ist für das 21. Jahrhundert einfach nur noch traurig.&lt;br /&gt;
Wir erhalten großteils Schulbildung, die uns dazu befähigen sollte
grundsätzlich Richtiges von Falschem zu unterscheiden und es sollten alle 
auch so “klug” sein, zu einem Thema, das wir nicht verstehen, einfach gar
nichts zu sagen.&lt;/p&gt;

&lt;p&gt;Doch anstatt dessen eröffnen wir sofort neue Gruppenchats auf Facebook,
Whatsapp, Telegramm, Skype oder Discord und verlieren uns in endlosen und
vor allem ziellosen Debatten über Magie, Parallelwelten und eben auch
“freie Energie”.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Aktuelles Beispiel:&lt;br /&gt;
Ich habe nun 2 Minuten meditiert und dann eine bahnbrechende Erfindung gemacht,
womit man auch die Energieprobleme unserer Welt lösen kann:&lt;/p&gt;

&lt;p&gt;10 Dioden werden in Serie auf ein Steckbrett gepinnt und dann zwischen 
den Enden der Kette ein Multimeter angeklemmt.
Mit dieser “Halbleiterwünschelrute” habe ich mein Wohnzimmer durchschritten und
festgestellt, dass auf dem Kästchen, wo mein Handy üblicherweise liegt ein
kosmisches Energiezentrum zu sein scheint.&lt;/p&gt;

&lt;p&gt;Wenn übrigens Mama anruft und ich dann per Bluetooth-Headset mit ihr rede,
strahlt das Zentrum kurzzeitig bis zu 150 Millivolt ab.&lt;br /&gt;
Eine Sensation! Mama’s Geist verstärkt offenbar die kosmische Strahlung aus 
der man Strom gewinnen kann.&lt;/p&gt;

&lt;p&gt;Ich sollte noch mehr Dioden kaufen und weitere Smartphones auf das Kästchen legen.
Vielleicht kann ich dann eine nominelle Spannung von 1.5 Volt (also eine AA Batterie)
messen.&lt;/p&gt;

&lt;p&gt;Hmm … ob die Spannung auch hält, wenn größerer Verbraucher daran hängt?
Sehen wir mal, wie Claus Turtur’s Super-Batterie aus Kalk die Welt retten kann:&lt;/p&gt;

&lt;iframe width=&quot;640&quot; height=&quot;360&quot; src=&quot;/blog/redirect.html?https%3A%2F%2Fwww.youtube-nocookie.com%2Fembed%2FKw2yIrXz8sA&quot; frameborder=&quot;1&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;

&lt;iframe width=&quot;640&quot; height=&quot;360&quot; src=&quot;/blog/redirect.html?https%3A%2F%2Fwww.youtube-nocookie.com%2Fembed%2FyDHfTh-0h3I&quot; frameborder=&quot;1&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;

&lt;iframe width=&quot;640&quot; height=&quot;360&quot; src=&quot;/blog/redirect.html?https%3A%2F%2Fwww.youtube-nocookie.com%2Fembed%2FMC7qMsmWp_k&quot; frameborder=&quot;1&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Das Internet ist leider voller Videos, die uns glauben machen wollen, es gäbe
unendlich viele Ressourcen, die man nur anzapfen müsste. Schlimm ist, wenn 
dann auch noch mathematische Formeln erdacht werden, mit denen man prahlen und
das Publikum beeindrucken kann.&lt;/p&gt;

&lt;p&gt;Leider bleibt am Ende nicht mehr als verpuffende Warme Luft aus Gesprächen 
übrig und auch die Gemeinschaft der Gläubigen nutzen ihre bahnbrechenden 
Erfindungen letztlich doch nicht um sich unabhängig erklären zu können …
und das liegt daran, dass sie allesamt nicht funktionieren und nur unter
speziellen Bedingungen für ganz kurze Zeit “Pulse” absondern.&lt;/p&gt;

&lt;p&gt;Diese sind aber kein politisches Geheimnis sondern den Physikern schon lange
bekannt. Aber wie im mittelalterliche Quacksalber produzieren heute YouTuber 
und andere Selbstdarsteller solche Funkentricks um das “einfache Volk” damit 
zu verzaubern.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Liebe Leute, ich bitte euch: Nehmt zur Kenntnis, dass nur weil die Welt 
komplex geworden ist und wir einfach nicht alles verstehen können, es nicht
bedeutet, dass Geheimwissen vor uns versteckt wird.&lt;br /&gt;
So ergeht es auch mir in Beruf und Hobbies, ich kann nicht alles verstehen.&lt;/p&gt;

  &lt;p&gt;Fallt daher nicht auf Scharlatane herein, die billige Tricks nutzen und 
euch mit frei erfundenen Verschwörungen zur Abwendung von Wissenschaft 
und Technik bekehren wollen.&lt;br /&gt;
Danke!&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>PocketGo vs. X9</title>
   <link href="https://www.opengate.at/blog/2019/08/pocket-go/"/>
   <published>2019-08-11T12:00:00+02:00</published>
   <updated>2019-08-11T12:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2019/08/pocket-go</id>
   <category term="hardware" /><category term="retro" />
   <summary type="text">OpenSource gegen großer Screen…

Wer gewinnt?

Natürlich OpenSource! … daher kurz und bündig:
Der PocketGo (also die Neufassung des BittBoy) ist 
die bessere Retro-Handheld-Konsole im Vergleich zur größeren “X9”.
</summary>
   <content type="html">&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Open_Source&quot;&gt;OpenSource&lt;/a&gt; gegen großer Screen…&lt;/p&gt;

&lt;p&gt;Wer gewinnt?&lt;/p&gt;

&lt;p&gt;Natürlich OpenSource! … daher kurz und bündig:
Der &lt;a href=&quot;https://pocket-go.com/&quot;&gt;PocketGo&lt;/a&gt; (also die Neufassung des BittBoy) ist 
die bessere Retro-Handheld-Konsole im Vergleich zur größeren “X9”. 
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Damals … vor über 25 Jahren … habe ich ja meinen originalen
Nintendo &lt;a href=&quot;https://de.wikipedia.org/wiki/Game_Boy&quot;&gt;Gameboy&lt;/a&gt; verkauft um mir 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_Basic_Classic&quot;&gt;Visual Basic 4.0&lt;/a&gt; für 
die Programmierung leisten zu können.&lt;/p&gt;

&lt;p&gt;Das war natürlich ein Fehler … ich hätte den GB behalten und für das Geld
für VB4 arbeiten gehen sollen. (Auf dem Land war Kinderarbeit damals noch 
gerne gesehen.)&lt;/p&gt;

&lt;p&gt;Seit den 2000ern und dem Internet konnte ich jedoch die “verlorenen” 
Kinderfreuden in &lt;a href=&quot;https://de.wikipedia.org/wiki/Emulator&quot;&gt;Emulatoren&lt;/a&gt; auf dem 
PC wieder nachholen … obwohl, es war nie mehr so wie früher, wenn man bei 
der Autofahrt oder im Bus oder Zug zum hundertsten Mal &lt;a href=&quot;https://de.wikipedia.org/wiki/Super_Mario&quot;&gt;Super Mario&lt;/a&gt;
Land durchgespielt hatte.&lt;/p&gt;

&lt;p&gt;Erst mit dem &lt;a href=&quot;https://de.wikipedia.org/wiki/Nintendo_3DS&quot;&gt;Nintendo 3DS&lt;/a&gt; 
entdeckte ich daher meine Liebe für die tragbaren Spielekonsolen wieder 
und ärgerte mich gleichsam, dass die alten Titel dort nicht verfügbar waren
und deren Neuauflagen zwar bunt aber nicht so “vertraut” und 
pixelig-geschmeidig wie früher waren.&lt;/p&gt;

&lt;p&gt;Die Lösung: Eine Retro-Konsole muss her … nur welche?
&lt;img src=&quot;/blog/assets/img/pocket-go-x9.jpg&quot; alt=&quot;Pocket-GO vs X9&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;x9&quot;&gt;X9&lt;/h3&gt;

&lt;p&gt;Vor einigen Monaten bestellte ich mir daher die sehr preiswerte China-Konsole
&lt;a href=&quot;https://www.banggood.com/X9-S-Rechargeable-5_0-inch-8G-Handheld-Retro-Game-Console-Video-MP3-Player-Camera-p-1131277.html&quot;&gt;X9&lt;/a&gt;, 
die damit warb, hunderte “Retro-Spiele” wiedergeben zu können.&lt;/p&gt;

&lt;p&gt;Mit einem üppigen Screen von 5 Zoll und dem Design der guten alten 
&lt;a href=&quot;https://de.wikipedia.org/wiki/PlayStation_Portable&quot;&gt;PlayStation Portable (PSP)&lt;/a&gt; 
war sie daher super zu bedienen und auch für meine nun etwas älteren Augen 
gut geeignet.&lt;/p&gt;

&lt;p&gt;Doch bei der Software ging der eigentlich gute Eindruck der Hardware dann 
flöten. Und der Grund ist, dass die selbst-fabrizierte Firmware der Konsole
nicht aktualisierbar war, keinem Standard entspricht und außerdem einige
Fehler aufweist.&lt;/p&gt;

&lt;p&gt;Zwar sind eine Menge chinesischer und japanischer Spielchen drauf, die 
mich weniger interessieren und man kann auch GBA ROMs über USB wie auf einen
Stick hochladen und dann spielen, doch bei Klassikern wie Pokemon versagt
der eingebaute Emulator.&lt;/p&gt;

&lt;p&gt;Schlimmer ist die Tatsache, dass das Speichern von Spielständen nicht 
implementiert ist. Wenn man im Spiel selbst abspeichert, scheint es 
funktionieren, doch beim nächsten Start ist alles weg.&lt;br /&gt;
Man muss als Alternative die Save-State-Slots des Emulators nutzen,
wo man das laufende Spiel quasi einfrieren und später wieder laden kann.
Doch mit 6 unbenannten Save-Slots darf man beim nächsten Spielverlangen
erst mal rätseln, welcher der 6 States jetzt der wirklich letzte war.&lt;/p&gt;

&lt;p&gt;Dass die Hersteller dieser Konsole nicht auf Urheberrechte achten, ist bei 
solchen Angeboten sowieso klar, und eigene Betriebssysteme haben sie auch
nicht entwickelt, sondern sich ein Linux “irgendwie” angepasst.&lt;/p&gt;

&lt;p&gt;Dieses dann aber der Öffentlichkeit vorzuenthalten und eine 
Online-Weiterentwicklung damit zu verhindern, ist meines Erachtens ein 
sehr schwerer Fehler.&lt;/p&gt;

&lt;h3 id=&quot;pocket-go&quot;&gt;Pocket-Go&lt;/h3&gt;

&lt;p&gt;Unter dem Namen “Bitt-Boy” kam vor etwas länger als einem Jahr eine ähnliche
Retro-Konsole auf den Markt, die zwar einen relativ kleinen Screen vorwies 
und vom Aufbau her dem Gameboy nachempfunden war, dafür aber eine gute 
Software mitbrachte.&lt;/p&gt;

&lt;p&gt;Der Bruder des Bitt-Boy heißt Pocket-Go und ist quasi die gleiche Hardware
in eine GBA-Form gepresst.&lt;/p&gt;

&lt;p&gt;Hier zeigt sich, dass die wahre Macht in der Software liegt. Denn die dafür
angepasste und frei verfügbare Linux-Ausgabe nutzt eine Vielzahl von 
Open-Source Emulatoren und kann daher nicht nur Konsolen-ROMs sondern auch
&lt;a href=&quot;/blog/2019/04/dos-games/&quot;&gt;DOS-Spiele&lt;/a&gt; wie 
DOOM2 oder Hexen ablaufen lassen.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Wie geil ist das denn!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;dachte ich mir, als ich neben GB, GBA, und SNES, auch das DOS-Box Icon auf
der Oberfläche erblickte.&lt;/p&gt;

&lt;p&gt;Und die Emulatoren funktionieren auch ordentlich, verlieren keine Spielstände
und kommen sogar mit den schwerer emulierbaren Pokemon-Editionen des GBA 
zurecht.&lt;/p&gt;

&lt;p&gt;Und als ich herausfand, dass sogar Playstation-Klassiker wie Final-Fantasy-VII
spielbar sein sollen, stand mein Fazit für diese Retro-Konsole bereits fest:&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ich wünschte, es gäbe eine BittBoy/PocketGo Konsole mit dem Screen der X9.
Denn so kann man für 40 Euro seine Kindheitsfreuden perfekt nochmals aufleben
lassen.&lt;/p&gt;

&lt;p&gt;Doch auch mit dem normalen Pocket-Go bekommt man für wenig Geld viel geboten
und hat ein Gerät, dass mit seiner Steuerung besser als ein Smartphone ist und 
richtigen Spielespaß aufkommen lässt.&lt;/p&gt;

&lt;p&gt;Die neueste Firmware lässt sich als Image herunterladen und einfach auf eine
SD-Karte übertragen, womit ab dem nächsten Boot noch mehr Software geboten
wird, während man alte Spiele und Spielstände per Datei-Kopieren “migrieren” 
kann.&lt;/p&gt;

&lt;p&gt;Mein X9 wird nun wohl in den Hintergrund rücken, obwohl sie “optisch” klar
überlegen ist, sind die Software-Mängel leider überwiegend.&lt;/p&gt;

&lt;p&gt;Vielleicht finden sich ja mal ein paar Hacker-Projekte, die es schaffen 
aus dieser verbugten Konsole doch noch etwas Brauchbares zu machen …&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Body-Check von innen</title>
   <link href="https://www.opengate.at/blog/2019/08/body-check/"/>
   <published>2019-08-04T12:00:00+02:00</published>
   <updated>2019-08-04T12:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2019/08/body-check</id>
   <category term="hardware" />
   <summary type="text">Unlängst plagte mich ein seltsames Rascheln im Ohr, immer wenn ich daran
kratzte. Vermutlich war es ein längeres Haar, dass irgendwie dort
hineinkam und das Trommelfell berührte.
Es tat nicht weh, war aber dennoch seltsam und gelegentlich unangenehm.


  Was geht das drinnen ab?


fragte ich mich … und suchte sogleich nach einem Hilfsmittel um 
es herauszufinden.

</summary>
   <content type="html">&lt;p&gt;Unlängst plagte mich ein seltsames Rascheln im Ohr, immer wenn ich daran
kratzte. Vermutlich war es ein längeres Haar, dass irgendwie dort
hineinkam und das Trommelfell berührte.&lt;br /&gt;
Es tat nicht weh, war aber dennoch seltsam und gelegentlich unangenehm.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Was geht das drinnen ab?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;fragte ich mich … und suchte sogleich nach einem Hilfsmittel um 
es herauszufinden.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;Ein Boroskop (englisch: &lt;a href=&quot;https://en.wikipedia.org/wiki/Borescope&quot;&gt;Borescope&lt;/a&gt;) 
ist ein “starres” &lt;a href=&quot;https://de.wikipedia.org/wiki/Endoskop&quot;&gt;Endoskop&lt;/a&gt;,
also eine Art von Kamera für schwer zugängliche Bereiche und ist vor
allem aus der Medizin bekannt.&lt;/p&gt;

&lt;p&gt;Während man sich mit flexiblen Endoskopen das Körperinnere (wie Magen,
Lunge usw.) ansehen kann, nutzt man das stabförmige Boroskop um sich
z.B. den Gehörgang oder den Rachenraum anzusehen.&lt;br /&gt;
Also Orte, wo man das Gerät nicht verbiegen können muss, um hin zu kommen.&lt;/p&gt;

&lt;p&gt;Und solche “einfachen” Webcams für “Innen” bekommt man schon für knapp
unter 10 Euro aus Fernost … also her mit so einem Ding!&lt;/p&gt;

&lt;h3 id=&quot;bodycheck&quot;&gt;Bodycheck&lt;/h3&gt;

&lt;p&gt;Mein &lt;a href=&quot;https://de.wikipedia.org/wiki/Trommelfell&quot;&gt;Trommelfell&lt;/a&gt; sieht ganz OK
aus, finde ich.
&lt;img src=&quot;/blog/assets/img/borescope-ear.jpg&quot; alt=&quot;Trommelfell&quot; /&gt;
OK, vielleicht nicht auf Hochglanz … aber ein bisschen Ohrschmalz
gehört da schließlich auch rein.&lt;/p&gt;

&lt;p&gt;Mein Auge sieht (wie so oft am Abend) etwas mitgenommen aus.
&lt;img src=&quot;/blog/assets/img/borescope-eye.jpg&quot; alt=&quot;Mein Auge&quot; /&gt;
Tja, das ist typisch, wenn man den ganzen Tag auf einen Bildschirm glotzt.&lt;/p&gt;

&lt;p&gt;(Die Nasenschleimhäute lasse ich hier mal aus.)&lt;/p&gt;

&lt;h3 id=&quot;die-hardware&quot;&gt;Die Hardware&lt;/h3&gt;

&lt;p&gt;Über die Hardware kann ich nicht viel sagen, außer dass das Gerät als 
einfache Webcam namens &lt;code&gt;USB 2.0 PC CAMERA&lt;/code&gt; erkannt wird. Die Hardware-ID
lautet auf &lt;code&gt;USB\VID_1908&amp;amp;PID_2311&amp;amp;MI_00\7&amp;amp;FB0A41A&amp;amp;0&amp;amp;0000&lt;/code&gt; und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows&quot;&gt;Windows&lt;/a&gt; hat bereits einen 
entsprechenden Treiber integriert, folglich ist keine Installation notwendig.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/borescope.jpg&quot; alt=&quot;Boroskop&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Übliche Tools wie die Windows 10 Kamera-App können das Boroskop sofort nutzen,
aber auch andere Tools (wie z.B. &lt;a href=&quot;/blog/2019/02/virtual-dub/&quot;&gt;VirtualDUB&lt;/a&gt;)
können es über &lt;a href=&quot;https://en.wikipedia.org/wiki/DirectShow&quot;&gt;DirectShow&lt;/a&gt;
oder &lt;a href=&quot;https://en.wikipedia.org/wiki/Media_Foundation&quot;&gt;andere Schnittstellen&lt;/a&gt;
ansteuern.&lt;/p&gt;

&lt;p&gt;Unterstützt werden Bilder bis zu maximal &lt;code&gt;640x480&lt;/code&gt; Pixel und trotz der 
möglichen Einstellung von 30 Bildern pro Sekunde, stelle ich “gefühlt”
nur 15 fest. Also ein typischer alter günstiger WebCam Chip in Miniaturform.&lt;/p&gt;

&lt;p&gt;Scharfe Bilder sollten etwa 2 cm for der Linse entfernt sein und die
LEDs an der Front zur Ausleuchtung kann man per Rädchen in ihrer
Strahlkraft anpassen.&lt;/p&gt;

&lt;h3 id=&quot;geheimtipp-ein-super-hardware-tool&quot;&gt;Geheimtipp: Ein super Hardware-Tool&lt;/h3&gt;

&lt;p&gt;Das geilste an der Stabkamera ist aber, dass man sie super dazu einsetzen
kann um mal schnell Platinen zu inspizieren.&lt;/p&gt;

&lt;p&gt;Für Großaufnahmen nutze ich ja gerne mein &lt;a href=&quot;/blog/2019/03/microscope/&quot;&gt;Mikroskop&lt;/a&gt;,
doch wenn man schnell mal eine Lötstelle kontrollieren möchte, braucht man
eine “mobile” Kamera … und dafür ist das Teil gut geeignet.&lt;/p&gt;

&lt;p&gt;Natürlich muss man die 2 cm Abstand halten um halbwegs scharf sehen zu können,
doch das ist schnell eingeübt. Nur die Lichtreflexion auf Bauteilen ist 
gelegentlich etwas lästig.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/borescope-sample1.jpg&quot; alt=&quot;Borescope-1&quot; /&gt;
Und schon sieht man gut lesbar, welche Widerstände und Kondensatoren
verbaut sind.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/borescope-sample2.jpg&quot; alt=&quot;Borescope-2&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/borescope-sample3.jpg&quot; alt=&quot;Borescope-3&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Oh, da ist wohl ein Pin verbogen … aber er hat noch Kontakt:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/borescope-sample4.jpg&quot; alt=&quot;Borescope-4&quot; /&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Win7: SysTray Icon Fehler beheben</title>
   <link href="https://www.opengate.at/blog/2019/08/win7-tray-icons/"/>
   <published>2019-08-02T12:00:00+02:00</published>
   <updated>2019-08-02T12:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2019/08/win7-tray-icons</id>
   <category term="software" />
   <summary type="text">Auf mehreren Laptops konnte ich folgendes Verhalten feststellen:
Der SysTray Icon Space spielt verrückt.

Es gibt seltsame leere Plätze zwischen z.B. One-Drive Icon und Sound 
Lautstärke, und wenn man mit der Maus darüber fährt verschwinden sie, oder
manchmal werden sie auch noch leer.

Oft fehlt auch das Netzwerk/WLAN Symbol.

Doch … Internetsuche sei Dank … es gibt eine Lösung.
</summary>
   <content type="html">&lt;p&gt;Auf mehreren Laptops konnte ich folgendes Verhalten feststellen:&lt;br /&gt;
Der SysTray Icon Space spielt verrückt.&lt;/p&gt;

&lt;p&gt;Es gibt seltsame leere Plätze zwischen z.B. One-Drive Icon und Sound 
Lautstärke, und wenn man mit der Maus darüber fährt verschwinden sie, oder
manchmal werden sie auch noch leer.&lt;/p&gt;

&lt;p&gt;Oft fehlt auch das Netzwerk/WLAN Symbol.&lt;/p&gt;

&lt;p&gt;Doch … Internetsuche sei Dank … es gibt eine Lösung.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Das seltsame Verhalten dürfte mit dem Icon Cache des Systems zu tun haben und
kann durch das Löschen bestimmter Registry Pfade korrigiert werden.&lt;/p&gt;

&lt;p&gt;Folgende Seite diente mir als Vorbild:
&lt;a href=&quot;http://community.spiceworks.com/how_to/36510-how-to-fix-blank-system-tray-icons&quot;&gt;community.spiceworks.com/how_to/36510-how-to-fix-blank-system-tray-icons&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Kurz gefasst sind folgende Schritte nötig:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;RegEdit starten&lt;/li&gt;
  &lt;li&gt;Zum Schlüssel &lt;code&gt;HKEY_CURRENT_USER\Software\Classes\Local Settings\Software\Microsoft\Windows\CurrentVersion\TrayNotify&lt;/code&gt;
wechseln&lt;/li&gt;
  &lt;li&gt;Dort die beiden Einträge &lt;code&gt;IconStreams&lt;/code&gt; und &lt;code&gt;PastIconsStream&lt;/code&gt; löschen&lt;/li&gt;
  &lt;li&gt;Task-Manager starten&lt;/li&gt;
  &lt;li&gt;Alle &lt;code&gt;explorer.exe&lt;/code&gt; Prozesse beenden (abschießen)&lt;/li&gt;
  &lt;li&gt;Eine neue &lt;code&gt;explorer.exe&lt;/code&gt; Instanz mit &lt;code&gt;Datei&lt;/code&gt; &amp;gt; &lt;code&gt;Neuer Task (Ausführen...)&lt;/code&gt; starten.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In meinem Fall hat das die störrischen Tray Icons besänftigt und nun sitzen 
wieder die GUI Vertreter aller wichtigen Programme mit dem richtigen Icon an ihrem Platz.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Für Microsoft sind solche Bugs aber schon ein bisschen peinlich. 
Denn ein Cache sollte Vorgänge beschleunigen und sie nicht durch Fehler 
unnötig in die Länge ziehen.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Datenmigration</title>
   <link href="https://www.opengate.at/blog/2019/07/data-migration/"/>
   <published>2019-07-28T12:00:00+02:00</published>
   <updated>2019-07-28T12:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2019/07/data-migration</id>
   <category term="software" />
   <summary type="text">Es ist mal wieder so weit: 
Neue Festplatte -&amp;gt; Neues Betriebssystem

Dank One-Drive, 
Arbeitsordner 
und Dateiserver sind wichtige 
Dokumente, Fotos und Quellcodes schon “automatisch” gesichert und gleich 
wieder verfügbar.

Doch was ist mit anderen Einstellungen wie Browser
Favoriten und Mail-Archiven?
</summary>
   <content type="html">&lt;p&gt;Es ist mal wieder so weit: &lt;br /&gt;
&lt;code&gt;Neue Festplatte -&amp;gt; Neues Betriebssystem&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Dank &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_OneDrive&quot;&gt;One-Drive&lt;/a&gt;, 
&lt;a href=&quot;http://docs.microsoft.com/en-us/windows-server/storage/work-folders/work-folders-overview&quot;&gt;Arbeitsordner&lt;/a&gt; 
und &lt;a href=&quot;https://de.wikipedia.org/wiki/Dateiserver&quot;&gt;Dateiserver&lt;/a&gt; sind wichtige 
Dokumente, Fotos und Quellcodes schon “automatisch” gesichert und gleich 
wieder verfügbar.&lt;/p&gt;

&lt;p&gt;Doch was ist mit anderen Einstellungen wie &lt;a href=&quot;https://de.wikipedia.org/wiki/Webbrowser&quot;&gt;Browser&lt;/a&gt;
Favoriten und Mail-Archiven?
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Nachdem solche Kleinevieh-Migrationen bei mir fast jährlich anstehen, weil ich
Windows gleich frisch aufsetze anstatt mühsam Windows Installationen zu kopieren
umd sich dann zu ärgern, wenn es nicht korrekt hochfahren will.&lt;/p&gt;

&lt;p&gt;Hier meine “üblichen Verdächtigen”:&lt;/p&gt;

&lt;h3 id=&quot;firefox-und-thunderbird&quot;&gt;Firefox und Thunderbird&lt;/h3&gt;

&lt;p&gt;Nachdem die Mozilla Foundation sowohl den Browser &lt;a href=&quot;https://de.wikipedia.org/wiki/Mozilla_Firefox&quot;&gt;Firefox&lt;/a&gt;
als auch den Mail-Client &lt;a href=&quot;https://de.wikipedia.org/wiki/Mozilla_Thunderbird&quot;&gt;Thunderbird&lt;/a&gt; 
erstellt hat, haben beide Programme einen ähnlichen Aufbau und deren Daten 
können vergleichbar migriert werden.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Kurzlösung:&lt;/strong&gt; Man kopiert sämtliche Dateien ihres Roaming-Profil-Ordners.&lt;/p&gt;

&lt;p&gt;&lt;small&gt;In den folgenden Beispielen ist das ursprüngliche C: Laufwerk der 
älteren Festplatte unter Laufwerk O: eingebunden.&lt;/small&gt;&lt;/p&gt;

&lt;h4 id=&quot;firefox&quot;&gt;Firefox&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;Unter &lt;code&gt;O:\Users\stemei\AppData\Roaming\Mozilla\Firefox&lt;/code&gt; liegen die
Profildaten.&lt;br /&gt;
(Man findet den Profile-Pfad übrigens auch, wenn man im Menü auf
&lt;code&gt;Hilfe -&amp;gt; Informationen zur Fehlerbehebung&lt;/code&gt; klickt und 
beim Punkt &lt;code&gt;Profilordner&lt;/code&gt; den Button &lt;code&gt;Ordner öffnen&lt;/code&gt; drückt,
und dann 2 Ebenen zurück geht.)&lt;/li&gt;
  &lt;li&gt;Der neu installierte Firefox sollte noch nicht gestartet worden sein,
ansonsten müssen beim nachfolgenden Kopieren einfach die bestehenden
Dateien überschrieben werden.&lt;/li&gt;
  &lt;li&gt;Jetzt werden alle Dateien aus dem obigen Verzeichnis nach
&lt;code&gt;C:\Users\stemei\AppData\Roaming\Mozilla\Firefox&lt;/code&gt; kopiert.&lt;/li&gt;
  &lt;li&gt;Startet man im Anschluss Firefox, sollten alle Links und
Favoriten der alten Platte im neuen System vorhanden sein.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;thunderbird&quot;&gt;Thunderbird&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;Unter &lt;code&gt;O:\Users\[username]\AppData\Roaming\Thunderbird&lt;/code&gt; liegen die 
Profildaten.
(Man findet den Profile-Pfad übrigens auch, wenn man im Menü auf
&lt;code&gt;Hilfe -&amp;gt; Informationen zur Fehlerbehebung&lt;/code&gt; klickt und 
beim Punkt &lt;code&gt;Profilordner&lt;/code&gt; den Button &lt;code&gt;Ordner öffnen&lt;/code&gt; drückt,
und dann 2 Ebenen zurück geht.)&lt;/li&gt;
  &lt;li&gt;Der neu installierte Thunderbird sollte noch nicht gestartet worden
sein, bzw. sollten dort keine  Mail-Accounts eingerichtet werden.&lt;/li&gt;
  &lt;li&gt;Nun kopiert man den Inhalt des obigen Pfades nach
&lt;code&gt;C:\Users\[username]\AppData\Roaming\Thunderbird&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Wird nun Thunderbird gestartet, sollten alle Accounts und Daten
der alten Festplatte im neuen Windows verfügbar sein.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;C:\Users\stemei\AppData\Roaming\Thunderbird&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;minecraft-für-windows-10-bedrock-edition&quot;&gt;MineCraft für Windows 10 (Bedrock Edition)&lt;/h3&gt;

&lt;p&gt;Auch &lt;a href=&quot;http://minecraft-de.gamepedia.com/Windows_10_Edition&quot;&gt;MineCraft 10&lt;/a&gt; 
legt seine Daten im Benutzerprofil ab, wo wir die erstellten Welten als 
Verzeichnisse einfach kopieren können.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Zuerst wird sicher gestellt, dass MineCraft nicht läuft.&lt;/li&gt;
  &lt;li&gt;Wir beginnen im Anwendungsverzeichnis 
&lt;code&gt;O:\Users\[username]\AppData\Local\Packages\Microsoft.MinecraftUWP_8wekyb3d8bbwe&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;von dort wechselt man ins Unterverzeichnis 
&lt;code&gt;LocalState\games\com.mojang\minecraftWorlds&lt;/code&gt;, denn die Unterordner dieses
Ordners enthalten die erstellten Spielwelten und werden kopiert.&lt;/li&gt;
  &lt;li&gt;Das Ziel des Kopiervorgangs liegt dann auf der neuen Festplatte 
im gleichen Pfad, also unter
&lt;code&gt;C:\Users\[username]\AppData\Local\Packages\Microsoft.MinecraftUWP_8wekyb3d8bbwe&lt;/code&gt;
&lt;code&gt;\LocalState\games\com.mojang\minecraftWorlds&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Startet man nun das &lt;a href=&quot;https://en.wikipedia.org/wiki/Universal_Windows_Platform&quot;&gt;UWP&lt;/a&gt;
Spiel auf dem neuen System, sollten alle “alten” Welten wieder angezeigt 
werden und spielbar sein.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;arduino-ide&quot;&gt;Arduino IDE&lt;/h3&gt;

&lt;p&gt;Die gute &lt;a href=&quot;https://en.wikipedia.org/wiki/Arduino_IDE&quot;&gt;Arduino IDE&lt;/a&gt; nistet sich 
(interessanterweise) im Dokumenten-Ordner ein.&lt;br /&gt;
Wenn man viele zusätzliche Board-Pakete und Bibliotheken auf seinem alten
System hatte, macht es Sinn auch diese zu kopieren, weil neu herunterladen
mühsam werden kann.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Die Arduino IDE sollte geschlossen sein.&lt;/li&gt;
  &lt;li&gt;Man wechselt ins “alte” Arduino Verzeichnis unter 
&lt;code&gt;O:\Users\[username]\Documents\Arduino&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Dort kopiert man alle enthaltenen Unterordner …&lt;/li&gt;
  &lt;li&gt;und fügt sie unter
&lt;code&gt;C:\Users\[username]\Documents\Arduino&lt;/code&gt; einfach ein.&lt;/li&gt;
  &lt;li&gt;Nach dem Start der IDE sollten die Boards und Libraries zur 
Verfügung stehen.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;-und-noch-mehr-&quot;&gt;… und noch mehr …&lt;/h3&gt;

&lt;p&gt;Die meisten anderen Apps, die ich nutze haben keine wirklichen
“privaten” Daten oder sie sind sehr gering und leichter im neuen
System einzurichten, anstatt sie manuell zu kopieren.&lt;/p&gt;

&lt;p&gt;Doch grundsätzlich kann man viele Programmdaten so übertragen.
Bei den meisten Anwendungen liegen die Daten unter
&lt;code&gt;C:\Users\[username]\AppData\Local&lt;/code&gt; oder 
&lt;code&gt;C:\Users\[username]\AppData\Roaming\&lt;/code&gt;.
Oft findet man den App-Namen direkt als Unterverzeichnis vor,
doch häufig ist der Hersteller-Firmenname oder die Web-Domain
als Verzeichnis noch vorgelagert.&lt;/p&gt;

&lt;p&gt;Es ist natürlich eine Spielerei, die manchmal klappt, manchmal nicht.
Vor allem durch Lizenzen geschützte Software lässt sich nicht so
einfach übertragen und benötigt eine neue Aktivierung oder Ähnliches.&lt;/p&gt;

&lt;h3 id=&quot;zwischen-accounts-kopieren&quot;&gt;Zwischen Accounts kopieren&lt;/h3&gt;

&lt;p&gt;Man kann App-Daten auf diese Weise manchmal auch zwischen lokalen
Accounts kopieren.&lt;br /&gt;
&lt;strong&gt;ABER:&lt;/strong&gt; der Fokus liegt auf “Kopieren”.
Wenn man zwischen zwei Profilverzeichnissen Daten nur “verschiebt”
anstatt sie zu kopieren, können Berechtigungsprobleme auftreten,
vor allem dann, wenn man mit einem separatem Admin-Account verschiebt
und der Ziel-Account  nicht die Rechte hat, die Profildaten des
Quell-Accounts zu lesen.&lt;br /&gt;
Denn beim Verschieben, bleiben (zumeist) die Rechte aus dem 
Originalverzeichnis erhalten. Beim Kopieren werden die Zieldaten
neu angelegt und erhalten die Rechte des Elternverzeichnisses.&lt;/p&gt;

&lt;p&gt;… so viel dazu.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Raspberry PI 4</title>
   <link href="https://www.opengate.at/blog/2019/07/raspberry-pi-4/"/>
   <published>2019-07-20T12:00:00+02:00</published>
   <updated>2019-07-20T12:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2019/07/raspberry-pi-4</id>
   <category term="hardware" />
   <summary type="text">Es gibt so ein paar Dinge, da könnte ich mich doch in den A____ beißen, wenn
ich so verdammt unaufmerksam bin.

Da bestelle ich mir den neuen Raspberry PI
4 (RPI4 abgekürzt) und klicke dann blind auf die Empfehlung 
“Andere Kunden haben auch das gekauft:”, nämlich ein Netzteil.

Und was habe ich geliefert bekommen?
Genau das, was ich bestellt habe, nämlich das falsche Netzteil.

</summary>
   <content type="html">&lt;p&gt;Es gibt so ein paar Dinge, da könnte ich mich doch in den A____ beißen, wenn
ich so verdammt unaufmerksam bin.&lt;/p&gt;

&lt;p&gt;Da bestelle ich mir den neuen &lt;a href=&quot;https://de.wikipedia.org/wiki/Raspberry_Pi&quot;&gt;Raspberry PI&lt;/a&gt;
4 (&lt;em&gt;RPI4&lt;/em&gt; abgekürzt) und klicke dann blind auf die Empfehlung 
&lt;em&gt;“Andere Kunden haben auch das gekauft:”&lt;/em&gt;, nämlich ein Netzteil.&lt;/p&gt;

&lt;p&gt;Und was habe ich geliefert bekommen?&lt;br /&gt;
Genau das, was ich bestellt habe, nämlich das falsche Netzteil.&lt;/p&gt;

&lt;!--more--&gt;
&lt;hr /&gt;

&lt;p&gt;Das neue Raspberry ist ein Leistungsschwein und braucht daher: 
&lt;a href=&quot;https://en.wikipedia.org/wiki/USB_3.0&quot;&gt;USB-3&lt;/a&gt;.&lt;br /&gt;
Und ich Depp habe das “zufällig” empfohlene USB-2 Netzteil für den
RaspPI 3 ausgewählt.&lt;/p&gt;

&lt;p&gt;Die 2.5 bis 3 Ampere würde es zwar liefern, doch der Anschluss passt nicht.&lt;br /&gt;
Und das USB-3 Netzteil meines Smartphones (welches im Kabelkanal meines 
Schreibtisches verbaut war) wollte ich auch nicht missbrauchen.&lt;/p&gt;

&lt;h3 id=&quot;lösung-lötkolben-einschalten&quot;&gt;Lösung: Lötkolben einschalten&lt;/h3&gt;

&lt;p&gt;Alle Raspberry PIs können auch über die &lt;a href=&quot;https://de.wikipedia.org/wiki/Allzweckeingabe/-ausgabe&quot;&gt;GPIO&lt;/a&gt;
Leiste mit Strom versorgt werden. Das wird nicht empfohlen, weil hier kein 
Schutz vor Überspannungen verbaut ist, aber ein “ordentliches” Netzteil 
liefert solche auch nicht.&lt;/p&gt;

&lt;p&gt;Und zum Glück lagen noch ein paar Micro-USB Bauteile in meiner Lade herum.
Dieses wurde mit einer 3-Pin Buchse verschustert und fertig ist der
provisorische Netzteil-Adapter.&lt;/p&gt;

&lt;p&gt;Dann noch anschließen, einstecken … und … Perfekt, der PI startet 
problemlos.&lt;br /&gt;
&lt;img src=&quot;/blog/assets/img/raspberry-pi-diy-power.jpg&quot; alt=&quot;Raspberry PI DIY Power Supply&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;der-neue-raspberry-pi&quot;&gt;Der neue Raspberry PI&lt;/h3&gt;

&lt;p&gt;Vor dem Start wurde natürlich noch das neueste 
&lt;a href=&quot;https://en.wikipedia.org/wiki/Raspbian&quot;&gt;Raspbian Linux&lt;/a&gt; Image 
namens “Buster” herunter geladen und auf eine 
&lt;a href=&quot;https://de.wikipedia.org/wiki/SD-Karte#microSD&quot;&gt;Micro-SD-Karte&lt;/a&gt; kopiert.&lt;/p&gt;

&lt;p&gt;Das OS startet dann wie gewohnt, vergrößerte zuerst seine Root-Partition
und ließ dann auf der GUI noch ein paar Einstellungen für Tastatur und
Zeitzone vornehmen.&lt;/p&gt;

&lt;p&gt;Dann kam der wichtigste Leistungstest, an dem die Vorgängermodelle hart 
zu knabbern hatten: Der &lt;a href=&quot;https://de.wikipedia.org/wiki/Webbrowser&quot;&gt;Webbrowser&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Nachdem ältere Raspberry PIs mit nur 1 GB RAM ausgestattet waren und 
Browser viel Zeug im Hintergrund abarbeiten war “Surfen” mit diesen
Geräten keine Option.&lt;/p&gt;

&lt;p&gt;Doch mein RPI, der mit 4 GB ausgestattet ist, überraschte mich mehr als 
positiv. Die Performance war super und fühlte sich fast wie auf dem Desktop-
Rechner an.&lt;br /&gt;
Ich muss zwar zugeben, nicht all zu viel getestet zu haben, doch das was
ich gesehen habe, war großartig.&lt;/p&gt;

&lt;p&gt;Damit wird der RPI4 nun endlich ein richtiger PC-Ersatz, während seine
Vorgänger eher Mini-Server ihr Dasein fristen mussten.&lt;/p&gt;

&lt;p&gt;Beeindruckend ist natürlich auch, dass wir mit max. 3 Ampere bei 5 Volt
ein Maximallast von 15 Watt erreichen, was ein Bruchteil des Stromverbrauchs
eines PCs darstellt.&lt;/p&gt;

&lt;p&gt;Aus Energiespargründen müsste man dieses Gerät also sofort an jedes Office
stellen, wo nur Text-Dokumente und Tabellen bearbeitet und nebenbei ein
paar Webseiten angesurft werden.&lt;/p&gt;

&lt;p&gt;Denn diese Aufgaben scheint der kleine Rechenknecht mit Bravour zu erledigen.&lt;/p&gt;

&lt;p&gt;Eines muss man allerdings anmerken: 15 Watt bedeuten auch einiges an Abwärme
auf dieser kleinen Fläche und so wurde der Chip recht schnell richtig heiß.&lt;br /&gt;
Ein Kühlkörper und ein kleiner Ventilator sind also leider notwendig für 
einen Dauerbetrieb, was natürlich wieder etwas Krach macht.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Nun, es ist noch etwas früh, das Modell zu bewerten. Aktuell laufen Infos
durch das Netz, dass einige Funktion im neuen OS noch “buggy” sind, die
es erst zu fixen gilt.&lt;/p&gt;

&lt;p&gt;Auch habe ich noch nichts auf dem kleinen Wunderkind zu kompilieren versucht,
doch nachdem auch sein Vorgänger - zwar etwas träge - dafür geeignet waren,
so müsste der neue RPI4 hier ebenfalls glänzen.&lt;/p&gt;

&lt;p&gt;Ich mag das Ding auf jeden Fall.&lt;br /&gt;
Und natürlich erkenne ich mit Demut an, dass wir heute auf einer 
Kreditkarten-großen Platine für 15 Watt&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;4 mal &lt;a href=&quot;https://de.wikipedia.org/wiki/ARM_Cortex-A&quot;&gt;Cortex-A72&lt;/a&gt; 
1.5 GHz Prozessoren&lt;/li&gt;
  &lt;li&gt;4 GB RAM&lt;/li&gt;
  &lt;li&gt;und eine 32 GB SD-Karte&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;betreiben können.&lt;br /&gt;
Wahnsinn!&lt;br /&gt;
Dagegen stinkt mein alter &lt;a href=&quot;https://de.wikipedia.org/wiki/Intel_80486&quot;&gt;80486&lt;/a&gt; 
leider wieder mal ab, der 100 Watt zieht, um&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;einen 66 MHz Prozessor&lt;/li&gt;
  &lt;li&gt;16 MB RAM&lt;/li&gt;
  &lt;li&gt;und eine 512 MB Festplatte&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;am Laufen zu halten.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dieser Punkt geht deutlich an unsere moderne Technik!&lt;/strong&gt;&lt;/p&gt;

&lt;h3 id=&quot;nachtrag&quot;&gt;Nachtrag&lt;/h3&gt;

&lt;p&gt;Natürlich durfte mein 3D Drucker sogleich ein Gehäuse produzieren, damit der
PI (nun mit korrektem USB-3 Stromkabel und 40 mm Fan) ordentlich benutzt 
werden kann.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/raspberry-pi-4.jpg&quot; alt=&quot;Raspberry PI 4&quot; /&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Mein alter Cyrix-Pentium</title>
   <link href="https://www.opengate.at/blog/2019/07/p166/"/>
   <published>2019-07-14T12:00:00+02:00</published>
   <updated>2019-07-14T12:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2019/07/p166</id>
   <category term="hardware" /><category term="retro" />
   <summary type="text">Wir befinden uns etwas vor dem Jahr 2000.

Wer kann sich noch daran erinnern, was Pentium-Rating, 
kurz PR war?

Und bevor auch ich es vergesse, schreib’ ich es mal auf …
</summary>
   <content type="html">&lt;p&gt;Wir befinden uns etwas vor dem Jahr 2000.&lt;/p&gt;

&lt;p&gt;Wer kann sich noch daran erinnern, was &lt;a href=&quot;https://de.wikipedia.org/wiki/P-Rating&quot;&gt;&lt;em&gt;Pentium-Rating&lt;/em&gt;&lt;/a&gt;, 
kurz &lt;em&gt;PR&lt;/em&gt; war?&lt;/p&gt;

&lt;p&gt;Und bevor auch ich es vergesse, schreib’ ich es mal auf …
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Am Wochenende fiel mir am Zweitwohnsitz wieder mein alter Desktop-PC in die 
Hände. Ein typischer Mini-Tower, wie man ihn früher häufig sah.&lt;br /&gt;
Und dann fielen mir auch wieder die Abenteuer mit diesem etwas speziellen
Gerät ein.&lt;br /&gt;
&lt;img src=&quot;/blog/assets/img/pc-p166.jpg&quot; alt=&quot;PC-Front&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Ich war immer schon ein paar Jahre hinterher. Früher war der Grund, dass ich
nie genug Geld für “neue” Hardware hatte, und heute, ja heute ist es mir 
teilweise egal… (Schließlich läuft “meine” Software bereits ideal.)&lt;/p&gt;

&lt;p&gt;Während die Welt den &lt;a href=&quot;https://de.wikipedia.org/wiki/Intel_Pentium_II&quot;&gt;Pentium 2&lt;/a&gt; 
etablierte, bekam ich meinen ersten Pentium 1 im Abverkauf.&lt;br /&gt;
&lt;em&gt;Billig&lt;/em&gt; war eben wichtig.&lt;br /&gt;
Also erstand ich einen Pentium I-200, also einen Pentium der ersten Generation
mit 200 &lt;a href=&quot;https://de.wikipedia.org/wiki/Hertz_(Einheit)&quot;&gt;MHz&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Naja, stimmt nicht ganz, denn ein “Pentium” musste von 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Intel&quot;&gt;Intel&lt;/a&gt; stammen, mein Gerät hatte aber 
einen &lt;a href=&quot;https://de.wikipedia.org/wiki/Cyrix&quot;&gt;Cyrix&lt;/a&gt; Prozessor verbaut.&lt;br /&gt;
Und Cyrix war eine Chip-Schmiede ohne Schmiede, die ihre Produkte von anderen
Herstellern bauen ließ, oder von diesen zeitweise aufgekauft wurde.&lt;/p&gt;

&lt;p&gt;Intel-Nachbauer wie &lt;a href=&quot;https://de.wikipedia.org/wiki/AMD&quot;&gt;AMD&lt;/a&gt; und Cyrix 
führten das sogenannte Pentium-Rating ein um den Markt in folgender Weise 
zu beschummeln:&lt;/p&gt;

&lt;p&gt;Sie behaupteten, dass ihre Chips bei gleicher Taktfrequenz mehr Leistung
boten, als entsprechende Intel-Fabrikate. Und da es marktverzerrend sei,
ihre besseren Produkte “nur” durch die Taktfrequenz mit der Konkurrenz zu
vergleichen, schuf man:&lt;br /&gt;
das &lt;em&gt;Pentium-Rating&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Man behauptete also, dass eine AMD oder Cyrix &lt;a href=&quot;https://de.wikipedia.org/wiki/Prozessor&quot;&gt;CPU&lt;/a&gt;
mit 100 MHz die gleiche Leistung bieten könne, wie ein Intel Pentium mit 133 
MHz. Und so wurde die 100 MHz CPU als &lt;em&gt;PR-133&lt;/em&gt; vermarktet.&lt;/p&gt;

&lt;p&gt;Und ich hatte einen &lt;em&gt;Cyrix PR-200&lt;/em&gt; … doch wie schnell war die CPU wirklich.
Das konnte ich so genau gar nicht herausfinden, denn die wenigen Tools, die 
ich damals von diversen Heft-CDs zur Verfügung hatte, brachten nur 
Vergleichswerte für bestimmte Aufgaben mit bestehenden CPUs.&lt;br /&gt;
Und da kamen sehr konfuse Werte heraus.&lt;/p&gt;

&lt;p&gt;Cyrix Prozessoren waren dafür bekannt, dass sie recht gut bei der 
Integer-Arithmetik waren aber dafür grottenschlecht bei 
Fließkommarechnungen. Also gut für Office-Anwendungen und schlecht für Spiele.&lt;/p&gt;

&lt;p&gt;Das kam dann auch in etwas so raus, also Integer-Rechnungen waren so schnell
wie auf einem Intel Pentium 200, aber bei Fließkomma-Aufgaben war es “gefühlt”
schlechter, als bei einem Freund, der einen Pentium 133 hatte … 
also richtig schlimm.&lt;/p&gt;

&lt;p&gt;Und außerdem konnte ich selbst mit ein paar Programmen feststellen, dass
Grafikoperationen auf dem System “langsamer” wirkten, als sie hätten sein
müssen.&lt;/p&gt;

&lt;p&gt;Wie schnell war die CPU jetzt wirklich? Da musste ich einen Blick ins 
Handbuch werfen und fand dort die &lt;a href=&quot;https://de.wikipedia.org/wiki/Jumper_(Elektrotechnik)&quot;&gt;Jumper&lt;/a&gt;
Konstellationen für die Frequenzmultiplikationen auf dem &lt;a href=&quot;https://de.wikipedia.org/wiki/Hauptplatine&quot;&gt;Mainboard&lt;/a&gt;.&lt;br /&gt;
Ja, richtig, man musste Steckbrücken auf dem Mainboard alles einstellen, ein
bequemes BIOS-Menü wie wir es heute kennen gab es damals leider nicht.&lt;/p&gt;

&lt;p&gt;Und was ich da sehen musste war erschreckend:&lt;br /&gt;
&lt;em&gt;150 MHz CPU bei 75 MHz Busfrequenz&lt;/em&gt;, also 75 MHz am Board multipliziert
mit 2 ergibt die 150 MHz der CPU.&lt;/p&gt;

&lt;p&gt;Und mit dieser Info konnte ich mir dann so einiges erklären …&lt;/p&gt;

&lt;p&gt;Auf so einem klassischen Mainboard arbeitete vieles mit einem bestimmten
Faktor des Bustaktes, auch &lt;a href=&quot;https://de.wikipedia.org/wiki/Front_Side_Bus&quot;&gt;Front-Side-Bus&lt;/a&gt;
(FSB) genannt, und dieser hätte eigentlich 66 MHz sein sollen.
Ein Pentium-133 wäre 66 x 2, ein P-166 dann 66 x 2.5 und ein P-200 ergäbe
sich durch 66 x 3.&lt;/p&gt;

&lt;p&gt;Die Taktik von Cyrix war also, die Daten auf dem Mainboard etwas schneller
zu übertragen (75 MHz und nicht die üblichen 66), dann aber die CPU
schwächer zu takten (150 MHz und eben nicht 200).&lt;/p&gt;

&lt;p&gt;Mit diesem neuen Wissen wurde ich aber neugierig und begann an den Jumpern
herumzuspielen.
Und als ich die Einstellung eines P-166, also 66 x 2.5 MHz ausprobierte,
fand ich heraus, dass die Grafik nun um einiges schneller lief, als vorher.&lt;/p&gt;

&lt;p&gt;Hmm … das könnte am “korrekten” FSB von 66 MHz liegen, denn wenn zwischen
den Komponenten Daten ausgetauscht werden müssen, so müssen diese 
synchronisiert werden. Und da &lt;a href=&quot;https://de.wikipedia.org/wiki/Peripheral_Component_Interconnect&quot;&gt;PCI&lt;/a&gt; 
mit 33 MHz läuft, ergeben sich bei einem 66 MHz FSB bessere Optionen, als 
bei 75 MHz.&lt;br /&gt;
Meine Grafikkarte, die im PCI Slot steckte, war dann “schneller” beim 
Verarbeiten von Operationen.&lt;/p&gt;

&lt;p&gt;Somit habe ich meine CPU um 16 MHz übertaktet, aber den FSB verlangsamt.
Und dieses Verlangsamung brachte wesentlich mehr Vorteile, als wenn man
mit 75 x 2.5 auf 187 MHz gekommen wäre.&lt;br /&gt;
Auch konnte ich keine Instabilitäten oder Hitze beim Betrieb bemerken.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Erkenntnis: Die Feinabstimmung zwischen den Komponenten kann also mehr Leistung
bringen, als stumpfes Übertakten der CPU. Im Gegenteil, manche Übertaktungen 
können sogar zur Leistungsreduktion führen, und zwar ganz ohne 
Signalinstabilitäten.&lt;/p&gt;

&lt;p&gt;Seit mein “P-150 aka PR-200” also ein P-166 geworden ist, hatte ich ein bisschen
mehr Spaß mit ihm, und ich hatte wieder etwas gelernt.&lt;br /&gt;
Die schnellere Grafik war bei meinen alten DOS-Spielen zwar auch nebensächlich,
doch meine eigenen grafischen Programme brachten messbare Verbesserungen ans
Licht,&lt;/p&gt;

&lt;p&gt;Heute sind zum Glück solche Steck-Aktionen auf dem Mainboard verschwunden.
Selbst ein im BIOS falsch getakteter Prozessor ist zumindest bis 
nach der BIOS Phase im System nutzbar. Das war früher nicht zwingend so,
da blieb der Bildschirm gerne auch mal schwarz.&lt;/p&gt;

&lt;p&gt;Ansonsten sieht das Mainboard echt alt aus und die breiten Kabel für 
IDE-Festplatten, CD-ROM und Diskettenlaufwerke machen den Anblick auch leider
nicht übersichtlicher.&lt;/p&gt;

&lt;p&gt;Und trotzdem hat das Teil einen besonderen Platz in meinem Herzen.
Einerseits wegen der seltsamen 150 MHz Taktung und andererseits, weil ich 
darauf meine ersten besseren VB6-Programme und diverse Assembler Tests
schrieb.
&lt;img src=&quot;/blog/assets/img/pc-p166-board.jpg&quot; alt=&quot;PC-Mainboard&quot; /&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Mein Minecraft Grundstück</title>
   <link href="https://www.opengate.at/blog/2019/07/minecraft/"/>
   <published>2019-07-13T12:00:00+02:00</published>
   <updated>2019-07-13T12:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2019/07/minecraft</id>
   <category term="entertainment" />
   <summary type="text">Obwohl ich sie gerne auch mal kritisiere, so passiert es immer wieder,
dass mich unsere “YouTuber”
am Abend unterhalten. Nachdem ich kein klassisches Fernsehempfangsgerät mehr 
besitze und auch kein typisches Streaming-Abo nutze, heißt es also: 
Browser öffnen, etwas auswählen und Play klicken.

Und irgendwie kam ich in den letzten Wochen of diverse 
Minecraft Streamer,
die sich entweder durch das Internet “battlen” oder selbst Server betreiben 
und den Schabernak, den sie dabei erzeugen, als Video hochladen.

Die munteren Videos motivierten mich also, auch mal so einen Minecraft Server
zu besuchen.
</summary>
   <content type="html">&lt;p&gt;Obwohl ich sie gerne auch mal kritisiere, so passiert es immer wieder,
dass mich unsere &lt;a href=&quot;/blog/2019/06/youtuber/&quot;&gt;“YouTuber”&lt;/a&gt;
am Abend unterhalten. Nachdem ich kein klassisches Fernsehempfangsgerät mehr 
besitze und auch kein typisches Streaming-Abo nutze, heißt es also: 
Browser öffnen, etwas auswählen und Play klicken.&lt;/p&gt;

&lt;p&gt;Und irgendwie kam ich in den letzten Wochen of diverse 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Minecraft&quot;&gt;Minecraft&lt;/a&gt; Streamer,
die sich entweder durch das Internet “battlen” oder selbst Server betreiben 
und den Schabernak, den sie dabei erzeugen, als Video hochladen.&lt;/p&gt;

&lt;p&gt;Die munteren Videos motivierten mich also, auch mal so einen Minecraft Server
zu besuchen.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Normalerweise baue ich nur zum Zeitvertreib lokal etwas in meiner
Minecraft Windows 10 Version. Diese ist ja nicht mit dem “normalen” 
Java-Minecraft kompatibel und nennt sich heute “Bedrock Edition”.&lt;/p&gt;

&lt;p&gt;Folglich konnte ich nicht direkt die Server ansprechen, die in diversen
Youtube Videos genannt werden, doch auch die Standard-Server Liste meiner
Windows 10 Edition hatte mit “LifeBoat” einen vorgemerkt, auf dem man auf 
einer Welt ein “Grundstück” erwerben und bebauen kann.&lt;/p&gt;

&lt;p&gt;Also wurden eben ein paar Euro investiert um ein virtuelles kleines Feld
mein Eigen nennen zu dürfen.&lt;/p&gt;

&lt;p&gt;Doch was macht man jetzt da drauf?&lt;/p&gt;

&lt;p&gt;Naja, weil mir nichts besseres einfiel startete ich mal mit einer 
Burgmauer um das Grundstück optisch abzugrenzen und als das erledigt war,
dachte ich mir nach einem kurzen Brainstorming:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Hmm, ich könnte Pixelgrafiken als übergroße Bilder aus Blöcken nachbauen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Doch welche Grafiken?&lt;br /&gt;
Und wenn mir sonst nichts einfällt, greife ich im zu meiner liebsten Standardlösung,
und die heißt bei Spielen: &lt;a href=&quot;https://de.wikipedia.org/wiki/Pok%C3%A9mon&quot;&gt;Pokemon&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Also schnell ein paar Bilder gegoogelt und los ging es.&lt;/p&gt;

&lt;p&gt;Nach der einen oder anderen Stunde war das Meisterwerk fertig und nun ragen
Bisasam, Schiggi, Glumanda und der Trainerjunge “Rot” aus einer Ecke auf Server
cm6.lbsg.net hervor.&lt;br /&gt;
Ein Pikachu-Gesicht und ein kleines Nachtara kamen ebenso hinzu.&lt;/p&gt;

&lt;p&gt;Die Bedrock Server dürften nicht ganz so gut besucht sein, wie jene die in den YouTube
Videos genutzt werden, doch es dauerte nicht lange, bis der eine oder andere Spieler
vorbei kam und sich über die Figuren amüsierte.&lt;/p&gt;

&lt;p&gt;Lustig sind auch jene Typen, die sich bemühen eine “rote Rakete” (siehe 
&lt;a href=&quot;https://de.wikipedia.org/wiki/South_Park&quot;&gt;Southpark&lt;/a&gt;) vor das Grundstück zu 
bauen. Doch nachdem die Rechte jener Rabauken vor meiner Grundstücksgrenze 
enden, bleiben “meine Pokemon” davon unberührt und außerdem kann man die 
Penisskulpturen auf dem Niemandsland leicht wieder ausradieren.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ein netter Zeitvertreib, wenn man parallel Podcasts anhört. Da kann man mit 
einer leichten Aufgabe sein Hirn auf Minimalbetrieb laufen lassen, nebenbei
einen Stream genießen und am Ende hat man … naja … ein paar Pixelbilder
in Minecraft gebaut, die auch andere beäugen können.&lt;/p&gt;

&lt;p&gt;Problematisch finde ich es, wenn Kinder und Jugendliche den ganzen Tag nur 
noch auf ihrem virtuellen Grundstrück verbringen und dort absurde Streitereien
mit ihren virtuellen Nachbarn abhalten.&lt;br /&gt;
Denn solche Aktivitäten sind auf YouTube zu Hauf dokumentiert.&lt;/p&gt;

&lt;p&gt;Wie immer gilt es alles mit Maß und Ziel einzusetzen.&lt;/p&gt;

&lt;p&gt;Mein Minecraft Grundstück gehört mir jetzt für 30 Tage, dann darf ich entweder 
weiter bezahlen, oder es gehört wieder der Allgemeinheit und wird dann vermutlich
von Rabauken wieder eingeebnet.&lt;/p&gt;

&lt;p&gt;Mal sehen, ob ich noch andere Figuren nachbauen werde…&lt;/p&gt;

&lt;h3 id=&quot;nachtrag--ein-paar-wochenend-stunden-später&quot;&gt;Nachtrag … ein paar Wochenend-Stunden später:&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/minecraft-plot-01.jpg&quot; alt=&quot;My Minecraft Plot 01&quot; /&gt;
&lt;img src=&quot;/blog/assets/img/minecraft-plot-02.jpg&quot; alt=&quot;My Minecraft Plot 02&quot; /&gt;
&lt;img src=&quot;/blog/assets/img/minecraft-plot-03.jpg&quot; alt=&quot;My Minecraft Plot 03&quot; /&gt;
&lt;img src=&quot;/blog/assets/img/minecraft-plot-04.jpg&quot; alt=&quot;My Minecraft Plot 04&quot; /&gt;
&lt;img src=&quot;/blog/assets/img/minecraft-plot-05.jpg&quot; alt=&quot;My Minecraft Plot 05&quot; /&gt;
&lt;img src=&quot;/blog/assets/img/minecraft-plot-06.jpg&quot; alt=&quot;My Minecraft Plot 06&quot; /&gt;
&lt;img src=&quot;/blog/assets/img/minecraft-plot-07.jpg&quot; alt=&quot;My Minecraft Plot 07&quot; /&gt;
&lt;img src=&quot;/blog/assets/img/minecraft-plot-12.jpg&quot; alt=&quot;My Minecraft Plot 12&quot; /&gt;
&lt;img src=&quot;/blog/assets/img/minecraft-plot-13.jpg&quot; alt=&quot;My Minecraft Plot 13&quot; /&gt;
&lt;img src=&quot;/blog/assets/img/minecraft-plot-14.jpg&quot; alt=&quot;My Minecraft Plot 14&quot; /&gt;
&lt;img src=&quot;/blog/assets/img/minecraft-plot-15.jpg&quot; alt=&quot;My Minecraft Plot 15&quot; /&gt;
&lt;img src=&quot;/blog/assets/img/minecraft-plot-16.jpg&quot; alt=&quot;My Minecraft Plot 16&quot; /&gt;
&lt;img src=&quot;/blog/assets/img/minecraft-plot-17.jpg&quot; alt=&quot;My Minecraft Plot 17&quot; /&gt;
&lt;img src=&quot;/blog/assets/img/minecraft-plot-18.jpg&quot; alt=&quot;My Minecraft Plot 18&quot; /&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Spider-Man, #Peter-Regung</title>
   <link href="https://www.opengate.at/blog/2019/07/far-from-home/"/>
   <published>2019-07-07T12:00:00+02:00</published>
   <updated>2019-07-07T12:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2019/07/far-from-home</id>
   <category term="entertainment" />
   <summary type="text">Tom Holland hat 
es mir wieder einmal bewiesen:
Er ist einfach ein cooler Typ und die mit Abstand beste Besetzung als 
Spider-Man Darsteller, 
meiner Meinung nach.

Es ist generell ein großes Problem, wenn 25 jährige Schauspieler sich 
lässig eine Schirmkappe aufsetzen und dann Szenen drehen in denen sie
behaupten, sie wären erst 15 Jahre alt.

Doch dem aktuellen Marvel 
Jungspund ist dieser Drahtseilakt recht gut gelungen.
Und mit dem Begriff “Peter-Regung” (Im Original “Peter Tingle”) wird man 
sich vermutlich noch viele Jahre an den Jungen erinnern.
</summary>
   <content type="html">&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Tom_Holland_(Schauspieler)&quot;&gt;Tom Holland&lt;/a&gt; hat 
es mir wieder einmal bewiesen:&lt;br /&gt;
Er ist einfach ein cooler Typ und die mit Abstand beste Besetzung als 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Spider-Man&quot;&gt;Spider-Man&lt;/a&gt; Darsteller, 
meiner Meinung nach.&lt;/p&gt;

&lt;p&gt;Es ist generell ein großes Problem, wenn 25 jährige Schauspieler sich 
lässig eine Schirmkappe aufsetzen und dann Szenen drehen in denen sie
behaupten, sie wären erst 15 Jahre alt.&lt;/p&gt;

&lt;p&gt;Doch dem aktuellen &lt;a href=&quot;https://de.wikipedia.org/wiki/Marvel_Cinematic_Universe&quot;&gt;Marvel&lt;/a&gt; 
Jungspund ist dieser Drahtseilakt recht gut gelungen.
Und mit dem Begriff “Peter-Regung” (Im Original “Peter Tingle”) wird man 
sich vermutlich noch viele Jahre an den Jungen erinnern.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Ich muss wohl nicht mehr zu 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Spider-Man:_Far_From_Home&quot;&gt;“Spider-Man: Far From Home”&lt;/a&gt; 
sagen als:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Yeah! Ein weiterer guter Marvel-Film!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Neben den üblichen Helden-Action-Szenen erlebt man auch ein paar
amüsante Einstellungen aus dem üblichen amerikanischen 
Teenager-Highschool-Genre.
Der Film nimmt sich dabei allerdings nicht allzu ernst und schafft so eine 
gute Mischung aus Comedy und Teeny-Charm.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/movie-far-from-home.jpg&quot; alt=&quot;Spider-Man: Far From Home&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Das Ende (bzw. die zweite Hälfte) des Films empfinde ich jedoch als 
unerwartetes Highlight, denn hier geht es um das Wechselspiel von Vertrauen 
und Betrug und vor allem um die Manipulierbarkeit der Menschen.&lt;/p&gt;

&lt;p&gt;Der Begriff “Fake-News” fällt (glaube ich) kein einziges Mal im Film, und
trotzdem könnte das der geheime Untertitel von Spider-Man - Far From Home
sein.&lt;/p&gt;

&lt;p&gt;Besonders die Marvel-typischen Midcredit und Endcredit Szenen stellen
eigentlich den ganzen Film nochmals auf den Kopf und haben bei mir 
einen Denkprozess angestoßen … was ich bei Superhelden-Filmen nicht
im Vorfeld erwarte.&lt;/p&gt;

&lt;h3 id=&quot;die-wahrheit-und-die-medien&quot;&gt;Die Wahrheit und die Medien&lt;/h3&gt;

&lt;p&gt;Woher wissen wir heute, wer der Gute und wer der Böse ist?&lt;br /&gt;
Die Antwort lautet in unserer Gesellschaft leider immer häufiger:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ich schau mal bei Google oder auf Facebook nach.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Tja, und dann? Dann sehen wir, wer sich selbst am besten zum 
“guten Charakter” stilisiert hat. Es zählt die Story, der Anschein
und das “coolste” Selfie direkt vom Geschehen.&lt;/p&gt;

&lt;p&gt;Täglich wird ein Video hochgeladen, über das man dann medientechnisch
professionell jeden erdenklichen Unsinn als Fakt darstellen kann.&lt;/p&gt;

&lt;p&gt;Wer hinterfragt heute schon ob ein “X” etwas verbrochen hat, wichtig
ist, dass es sofort ein Video und jede Menge Kommentare dazu gibt.
Und wenn man ausreichend beständig die Meinung vertritt, dass die
Erde eine Scheibe sei und “sogenannte” Pseudowissenschaftler nur
deshalb komplizierte Dinge von Planetenkugeln erzählen, damit sie uns
kontrollieren können, dann …&lt;/p&gt;

&lt;p&gt;… ja dann glauben tatsächlich immer mehr Menschen daran.
Ärzte belügen uns gewiss und wollen uns zu Impfungen zwingen, weil sie geheime
Deals mit der Pharmaindustrie haben, Regierungen habe geheime Unterregierungen,
die danach trachten widerspenstige Freigeister einfach so verschwinden zu
lassen, und wieder andere bauen komische Motoren, die angeblich unendlich
Energie aus dem Vakuum absaugen können, doch die Energiekonzerne machen Jagd
auf diese Erfinder und zerstören ihre Modelle, damit sie die Menschheit unter
ihrer Kontrolle behalten können.&lt;/p&gt;

&lt;p&gt;… ja so ein Unsinn verbreitet sich wie die Pest durch die “freien” Netze
und bringen leider immer mehr Bürger dazu 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Quacksalber&quot;&gt;Quacksalber&lt;/a&gt; Weisheiten für
bare Münze zu nehmen.&lt;/p&gt;

&lt;h3 id=&quot;spoiler&quot;&gt;Spoiler:&lt;/h3&gt;

&lt;p&gt;Und genau für diese Bedrohung unserer realen Welt hält 
Spiderman Far from Home - aus meiner Sicht - ein paar geniale
Szenen bereit, die uns darüber nachdenken lassen (sollten!), 
wie oft wir Blender-Videos mehr vertrauen schenken als dem gesunden
Hausverstand.&lt;/p&gt;

&lt;p&gt;Am Ende beweist &lt;a href=&quot;https://de.wikipedia.org/wiki/J._K._Simmons&quot;&gt;J._K._Simmons&lt;/a&gt; 
in seinem Cameo-Auftritt, wie schnell Spidermans Heldentaten durch ein 
gefälschtes Video komplett ins Gegenteil verkehrt werden.&lt;/p&gt;

&lt;p&gt;Die Menschen im Film bekommen eine vermeintlich schockierende Reportage 
geliefert, die beweisen soll, dass die freundliche Spinne aus der
Nachbarschaft der eigentliche “Böse” sein soll, der Monster aus anderen
Dimensionen zu uns geholt hat. Und ganz nebenbei wird die wahre Identität
von Peter Parker weltweit gelüftet.&lt;/p&gt;

&lt;p&gt;… so lässt uns Marvel also auf einen weiteren Film hoffen, der dieses
heiße Eisen anpackt.&lt;/p&gt;

&lt;p&gt;Wie auch immer … genau diese pointierten Szenen, die subtil unsere 
medien-geile und manipulierende Welt charakterisieren, machen den Film für 
mich im doppelten Sinn sehenswert!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Delegate als C Feature</title>
   <link href="https://www.opengate.at/blog/2019/07/c-delegates/"/>
   <published>2019-07-06T12:00:00+02:00</published>
   <updated>2019-07-06T12:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2019/07/c-delegates</id>
   <category term="devel" /><category term="projects" />
   <summary type="text">Ich hatte ja schon mal über Delegetes geschrieben
und meine Lösung angegeben, die ich schon seit über 10 Jahren einsetze.

Doch jetzt kommt alles anders:


  Reiner C Code soll Delegate
tauglich werden!


</summary>
   <content type="html">&lt;p&gt;Ich hatte ja schon mal &lt;a href=&quot;/blog/2018/12/delegates/&quot;&gt;über Delegetes geschrieben&lt;/a&gt;
und meine Lösung angegeben, die ich schon seit über 10 Jahren einsetze.&lt;/p&gt;

&lt;p&gt;Doch jetzt kommt alles anders:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Reiner C Code soll &lt;a href=&quot;https://de.wikipedia.org/wiki/Delegation_(Softwareentwicklung)&quot;&gt;Delegate&lt;/a&gt;
tauglich werden!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;!--more--&gt;
&lt;hr /&gt;

&lt;p&gt;In C++ ist mit &lt;a href=&quot;https://en.wikipedia.org/wiki/Template_(C%2B%2B)&quot;&gt;Templates&lt;/a&gt; 
ja so gut wie alles möglich. Das fing schon vor Jahrzehnten mit 
&lt;a href=&quot;https://en.cppreference.com/w/cpp/utility/functional/bind&quot;&gt;&lt;code&gt;std::bind&lt;/code&gt;&lt;/a&gt; an 
und hat heute mit &lt;a href=&quot;http://en.cppreference.com/w/cpp/language/lambda&quot;&gt;Lambdas&lt;/a&gt; 
einen weiteren Höhepunkt erreicht.&lt;/p&gt;

&lt;p&gt;Auch meine bisherigen Delegate-Implementierung nutzten Templates um mit
“einer” Klasse alle möglichen Konstellationen von Parametertypen abdecken zu
können.&lt;/p&gt;

&lt;p&gt;Doch in &lt;a href=&quot;https://de.wikipedia.org/wiki/C_(Programmiersprache)&quot;&gt;C&lt;/a&gt; haben wir 
dieses Feature nicht und müssten für jede Parameterzusammenstellung eine 
eigene Implementierung von Hand schaffen.&lt;br /&gt;
Auch &lt;a href=&quot;https://gcc.gnu.org/onlinedocs/cpp/Macro-Arguments.html&quot;&gt;Makros&lt;/a&gt; lösen 
dieses Problem meines Erachtens nicht (obgleich sie einige Ansätzen liefern 
könnten).&lt;/p&gt;

&lt;p&gt;Die große Zielsetzung des GATE Projektes ist jedoch die Schaffung einer
binären Schnittstelle für alle Basisoperationen, und das ist bereits in
vielen Teilen gelungen, nur nicht bei &lt;a href=&quot;https://de.wikipedia.org/wiki/Rückruffunktion&quot;&gt;Callbacks&lt;/a&gt;
und Delegates.&lt;/p&gt;

&lt;p&gt;Jetzt gibt es aber tatsächlich eine Möglichkeit, wie man alle Formen
von Parameterkonstellationen durch eine Schnittstelle, genauer gesagt 
einen einzigen Funktionstypen jagen kann, und der heißt:&lt;br /&gt;
&lt;a href=&quot;https://en.cppreference.com/w/c/variadic&quot;&gt;Variadic functions&lt;/a&gt;, 
kurz &lt;code&gt;var_args&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Denn sobald eine Funktion mit einem &lt;code&gt;...&lt;/code&gt; in der Parameterliste endet,
darf der Anwender jeden erdenklichen Parameter an die Funktion übergeben.
Das Knifflige dabei ist, dieses Parameter in der Funktion wieder vom Stack
herunter zu bekommen.&lt;/p&gt;

&lt;h3 id=&quot;wie-sieht-also-das-gate-c-delegate-konzept-aus&quot;&gt;Wie sieht also das GATE C-Delegate Konzept aus?&lt;/h3&gt;

&lt;p&gt;Ein Delegate Objekt besteht aus einem &lt;code&gt;var_arg&lt;/code&gt; Funktionszeiger und 
einem ausreichend großem Speicherplatz für die gewünschte Zielfunktion.&lt;/p&gt;

&lt;p&gt;Will man ein solches Delegate Objekt nun an seine eigene Funktion oder
Objektmethode binden, muss eine Dispatcher Funktion erstellt werden,
die die Parameter aus einem &lt;code&gt;var_arg&lt;/code&gt; Feld herauskitzeln kann und damit
einen Funktionszeiger oder Methodenzeiger aufruft, der in im oben 
erwähnten Speicherplatz geparkt ist.&lt;/p&gt;

&lt;p&gt;Der Aufruf des Delegates ist einfach, denn hier wird die im Delegate 
gelegene Dispatcher-Funktion über den Funktionszeiger direkt aufgerufen
und der erste Parameter ist das Delegate-Objekt selbst, gefolgt von 
jenen “freien” Parameter, die zur “delegierten” Funktion passen.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Aber Achtung!&lt;/em&gt; Eines muss man gleich im Vorfeld sagen:
Typensicherheit seitens des Compilers gibt es dann natürlich keine,
denn die &lt;code&gt;var_args&lt;/code&gt; fressen alles, doch die Dispatcher können nur 
das verdauen, wozu sie berufen sind.&lt;/p&gt;

&lt;p&gt;Auch gibt es keinen Support für Kopien von Objekten (weil C keine
&lt;a href=&quot;http://en.cppreference.com/w/cpp/language/copy_constructor&quot;&gt;Kopierkonstruktoren&lt;/a&gt; 
kennt) oder Referenzen (obwohl sich diese leicht in Pointer umwandeln lassen).&lt;/p&gt;

&lt;p&gt;Wir schaffen somit eine Lösung, wo C Code einen Delegate aufrufen 
kann und dieser den Aufruf in eine C Funktion, eine C++ Objektmethode,
in einen Funktor oder Lambdaausdruck oder auch etwas ganz anderes 
übersetzen kann.&lt;/p&gt;

&lt;p&gt;Besonders spannend wird es, wenn man dieses Feature auf andere Sprachen wie 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Java_(Programmiersprache)&quot;&gt;Java&lt;/a&gt;, 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Python_%28Programmiersprache%29&quot;&gt;Python&lt;/a&gt;
oder &lt;a href=&quot;https://de.wikipedia.org/wiki/Lua&quot;&gt;Lua&lt;/a&gt; anwendet.&lt;/p&gt;

&lt;p&gt;Während wir in C auf Makros setzen müssen um Dispatcher zu generieren,
werden auf der C++ Seite Templates die angesprochenen Dispatcher 
automatisch erzeugen. Sogar der Support von Exceptions ist teilweise gegeben, 
weil die aufgerufene Funktion ge-&lt;code&gt;try&lt;/code&gt;-&lt;code&gt;catch&lt;/code&gt;-t und in einen &lt;code&gt;gate_result_t&lt;/code&gt;
abgebildet wird.&lt;br /&gt;
Gleichzeitig sieht die C++ Kapselung des Aufruf eines Delegates vor, dass 
ein empfangener &lt;code&gt;gate_result_t&lt;/code&gt; wieder auf eine Exception übersetzt wird.&lt;br /&gt;
Dabei gehen (derzeit) zwar einige Informationen verloren, doch der 
logische Ablauf bleibt gleich.&lt;/p&gt;

&lt;p&gt;Auf eines müssen wir ebenso verzichten: Return-values, denn diese müssen
fix &lt;code&gt;gate_result_t&lt;/code&gt; Codes sein und dürfen nur über Erfolg und Misserfolg
des Aufrufs berichten.&lt;/p&gt;

&lt;p&gt;Wenn man aber in Richtung &lt;a href=&quot;http://docs.microsoft.com/en-us/dotnet/api/system.multicastdelegate&quot;&gt;Multicast-Delegates&lt;/a&gt;
denkt, wo ein Aufruf mehrere Zielaufrufe bedeutet, ist das sogar ein Vorteil, 
weil man dann nicht mehrere Return-Values wieder zu einem einzigen 
zusammensetzen muss.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Die GATE &lt;a href=&quot;https://en.wikipedia.org/wiki/User_interface&quot;&gt;UI&lt;/a&gt; Bibliotheken sind 
bereits für weitere Tests auf die neuen “alten” C Delegates umgestellt und 
werden weiter “beobachtet”, ob sie auch wirklich so gut funktionieren wie 
gedacht.&lt;/p&gt;

&lt;p&gt;Offen gesagt freut es mich etwas, dass nun nach 10 Jahren endlich wieder etwas
ganz Neues in meine Codes eingeflossen ist, was die Bandbreite der Anwendung
erhöhen kann und gleichzeitig Kompatibilität bis in die 80er Jahre zurück 
ermöglicht.&lt;/p&gt;

&lt;p&gt;Natürlich sind diese Konstrukte keine Rennpferde und daher werden klassische
Callbacks auch weiterhin intern eingesetzt. Doch gerade bei UI-Events oder
generell “Events”, die nicht zig mal pro Sekunde aufgerufen werden, ist dieser
Layer durchaus mal einen Versuch wert.&lt;/p&gt;

&lt;p&gt;Mal sehen wie sich das weiter entwickeln lässt ;)&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Youtuber</title>
   <link href="https://www.opengate.at/blog/2019/06/youtuber/"/>
   <published>2019-06-30T12:00:00+02:00</published>
   <updated>2019-06-30T12:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2019/06/youtuber</id>
   <category term="general" />
   <summary type="text">So wie wir im Lateinunterricht 
lernten, dass alle römischen Briefe mit dem Intro


  Si tu vales, bene est, ego valeo.
(Wenn du gesund bist, ist es gut, mir geht’s [auch] gut.)


versehen sind, so werden künftige Generationen von “meiner” Zeit glauben,
dass:


  Hey Leute, was geht ab?
Herzlich willkommen zu meinem neuen Video!


die übliche Grußformel am Anfang des 21. Jahrhunderts war.
</summary>
   <content type="html">&lt;p&gt;So wie wir im &lt;a href=&quot;https://de.wikipedia.org/wiki/Latein&quot;&gt;Lateinunterricht&lt;/a&gt; 
lernten, dass alle römischen Briefe mit dem Intro&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Si tu vales, bene est, ego valeo.
(Wenn du gesund bist, ist es gut, mir geht’s [auch] gut.)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;versehen sind, so werden künftige Generationen von “meiner” Zeit glauben,
dass:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Hey Leute, was geht ab?
Herzlich willkommen zu meinem neuen Video!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;die übliche Grußformel am Anfang des 21. Jahrhunderts war.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Ich finde sie ja total lustig, unsere &lt;a href=&quot;https://en.wikipedia.org/wiki/YouTuber&quot;&gt;YouTuber&lt;/a&gt;, 
wie sie mit gestylten Haaren und ihren selbst gebauten Greenscreen-Studios
jeden Tag die restliche Welt davon überzeugen wollen, dass sie die 
“&lt;em&gt;coolsten Typen ever&lt;/em&gt;” sind.&lt;/p&gt;

&lt;p&gt;Unsere Jugend ist es - und das muss man hoch anerkennen - selbstständig 
gelungen eine positive Alternative zur heute eher kritisch anmutenden 
Alltagsgesellschaft zu etablieren.&lt;/p&gt;

&lt;p&gt;Interessant finde ich, dass das in meiner Jugend in den 90er Jahren
(vor allem als Nachtrag der 80er Jahre) eher umgekehrt war.
Damals trug das Fernsehen in erster Linie positive Inhalt fast belehrend vor, 
während die Jugend skeptisch und eigenbrödlerisch die 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Null-Bock-Generation&quot;&gt;Null-Bock-Generation&lt;/a&gt;
formte.&lt;/p&gt;

&lt;p&gt;Und was ist heute? Die Medien zeigen uns primär Katastrophen und Bedrohungen,
dokumentieren, wie Politiker Gladiatorenkämpfe durch immer lauteres
Schreien austragen und … die Jugend?&lt;br /&gt;
Die vernetzt sich, lebt ein von lachenden Selfies dominiertes 
Feel-Good-Leben und macht ihr eigenes Ding.&lt;/p&gt;

&lt;p&gt;So zumindest mein Eindruck.&lt;/p&gt;

&lt;p&gt;Doch ein bisschen mache ich mir Sorgen, was mit den Leitbildern 
(auch &lt;a href=&quot;https://de.wikipedia.org/wiki/Influencer&quot;&gt;Influencer&lt;/a&gt; genannt) 
langfristig geschehen wird.
Denn der größte Nachteil der Jugend ist, dass sie vergänglich ist.
(Natürlich gibt es auch ältere Vertreter in diesem Genre … aber
ihr Zahl ist &lt;em&gt;deutlich&lt;/em&gt; geringer)&lt;/p&gt;

&lt;p&gt;Und wenn der auf YouTube und &lt;a href=&quot;https://de.wikipedia.org/wiki/Instagram&quot;&gt;Instagramm&lt;/a&gt;
zur Schau gestellte “coole Junge” oder das “heiße Mädchen” die Grenze von 
25 Jahren, also nach 10 Jahren im Online-Showgeschäft, hinter sich haben, 
tja was dann?&lt;/p&gt;

&lt;p&gt;Wir wissen es nicht, weil es den Karriereweg des YouTubers bisher nicht gab
und keine Langzeiterfahrung existiert.&lt;/p&gt;

&lt;p&gt;Doch eines habe ich durch eine interessante Begegnung in meinem Leben 
schon gelernt, nämlich aus dem Schicksal der “Kinderstars”.&lt;/p&gt;

&lt;p&gt;Diese gibt es schon seit über 50 Jahren, sie erleben große Erfolge in jungen
Jahren und landen dann … leider auch an sehr dunklen Orten.&lt;/p&gt;

&lt;p&gt;Es verändert einen schon, wenn man heute von einer Million Menschen gefeiert
wird, und morgen nur noch 10 Hardcore-Fans hinter einem stehen, die vielleicht
auch noch &lt;a href=&quot;https://de.wikipedia.org/wiki/Stalking&quot;&gt;Stalkertendenzen&lt;/a&gt; aufweisen.&lt;br /&gt;
Drogen und Alkohol sind leider oft der Wegbegleiter, wenn 30 jährige 
ehemalige Berühmtheiten mit der Rolltreppe nach unten fahren.&lt;/p&gt;

&lt;p&gt;Und eben dieses Schicksal wünsche ich niemandem.&lt;/p&gt;

&lt;p&gt;Ich sehe mir inzwischen auch gerne die Videos der immer freundlichen,
immer motivierten und cool auftretenden Eigenregisseure an, weil es künstlich
ein Gefühl der Leichtigkeit und Problemlosigkeit vermittelt.&lt;br /&gt;
Doch eigentlich sollte hier mehr Selbstkontrolle und Schulung Einzug halten.&lt;/p&gt;

&lt;p&gt;In den von unseren “Stars” gerne gespielten (live-gestreamten) Quizfragen 
zeigt sich dann, dass die Schulbildung den Likezahlen gewichen ist. 
Und so wie &lt;a href=&quot;https://de.wikipedia.org/wiki/Justin_Bieber&quot;&gt;Justin Bieber&lt;/a&gt; einst
nicht wusste, welche Kontinente unser Planet hat und Kanada und USA als zwei 
davon aufzählte, so fallen mir schwere Defizite in Grammatik, Mathematik und
Allgemeinbildung bei vielen Influencern auf.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Doch die Sache hat auch etwas Positives:
Denn vielleicht haben sie nicht ganz so viele Likes wie die 
da oben, doch viele junge Menschen publizieren heute ihre Projekte, die sie
sich fast wissenschaftlich erarbeitet haben.&lt;/p&gt;

&lt;p&gt;Eine junge Studentin stellt z.B. ihren Laborplatz vor und schwärmt von ihrer
Bachelor-Arbeit, ein Schuljunge präsentiert stolz seinen selbst gebautes
Labornetzteil. Ein Jugendgruppe zeigt mindestens wöchentlich, wie sie durch
Flohmärkte Geld für Sozialprojekte eintreiben können.
Und mit dem Umweltschutz setzen sich halbe Städte in Bewegung um für eine 
bessere Welt zu demonstrieren.&lt;br /&gt;
Und das wird eben auch von “Influencern” ausgelöst.&lt;/p&gt;

&lt;p&gt;Also … alles in allem werden die Jungs und Mädels von Morgen das schon 
hinbekommen … wenn gleich auch nicht alles so glänzend bleiben wird, 
wie man es mit Videofiltern auf YouTube hochladen kann.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Variadic arguments heißt aber nicht &apos;alles&apos;</title>
   <link href="https://www.opengate.at/blog/2019/06/va_arg/"/>
   <published>2019-06-23T12:00:00+02:00</published>
   <updated>2019-06-23T12:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2019/06/va_arg</id>
   <category term="devel" />
   <summary type="text">Heute ist mir mal wieder ein lustiger Fehler in Zusammenhang mit
variadic arguments
in C passiert.

Denn da es in C keine Templates und Funktionsüberladungen gibt, sind 
varargs die einzige Möglichkeit mit einer Funktionssignatur beliebige 
Parameter auszuführen.

Tja, und dann hatte ich plötzlich einen Fehler im 
GCC, obwohl der
MSVC alles 
kompilieren konnte.
</summary>
   <content type="html">&lt;p&gt;Heute ist mir mal wieder ein lustiger Fehler in Zusammenhang mit
&lt;a href=&quot;https://en.wikipedia.org/wiki/Variadic_function#In_C&quot;&gt;variadic arguments&lt;/a&gt;
in &lt;a href=&quot;https://de.wikipedia.org/wiki/C_(Programmiersprache)&quot;&gt;C&lt;/a&gt; passiert.&lt;/p&gt;

&lt;p&gt;Denn da es in C keine Templates und Funktionsüberladungen gibt, sind 
&lt;code&gt;varargs&lt;/code&gt; die einzige Möglichkeit mit einer Funktionssignatur beliebige 
Parameter auszuführen.&lt;/p&gt;

&lt;p&gt;Tja, und dann hatte ich plötzlich einen Fehler im 
&lt;a href=&quot;https://en.wikipedia.org/wiki/GNU_Compiler_Collection&quot;&gt;GCC&lt;/a&gt;, obwohl der
&lt;a href=&quot;https://en.wikipedia.org/wiki/Microsoft_Visual_C%2B%2B&quot;&gt;MSVC&lt;/a&gt; alles 
kompilieren konnte.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Um es nicht zu spannend zu machen:&lt;br /&gt;
Der Fehler trat bei einem &lt;code&gt;va_arg(arglist, char);&lt;/code&gt; auf.&lt;/p&gt;

&lt;p&gt;Anfangs war ich verwirrt, las dann aber nach, warum GCC hier bockt … 
und dann fiel es mir auch wieder ein:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Datentypen kleiner als &lt;code&gt;int&lt;/code&gt; müssen bei &lt;code&gt;va_arg&lt;/code&gt;s auf einen &lt;code&gt;int&lt;/code&gt; 
beim Lesen vergrößert werden.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Das macht auch Sinn, denn &lt;code&gt;int&lt;/code&gt; wird in C gerne mit der 
&lt;a href=&quot;https://en.wikipedia.org/wiki/Data_structure_alignment&quot;&gt;Standardausrichtung&lt;/a&gt;
(standard alignment) belegt.&lt;br /&gt;
Und wenn man sich die &lt;code&gt;va_arg&lt;/code&gt; Funktion mal ansieht, ist sie auf X86 als 
Pointeraddition implementiert, wo der Argumentpointer immer um die Größe
des gewünschten Typen verschoben wird.&lt;/p&gt;

&lt;p&gt;Und nachdem auf dem Stack Alignment-Regeln gelten, würde ein
&lt;code&gt;va_arg(arglist, char)&lt;/code&gt; den Pointer nur um ein Byte verschieben, und 
schon hätten wir die Alignmentregeln gebrochen.&lt;/p&gt;

&lt;p&gt;Mit &lt;code&gt;int&lt;/code&gt; verschieben sich Pointer in geordneten Bahnen.&lt;/p&gt;

&lt;p&gt;Das heißt also, dass&lt;/p&gt;
&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt; c = va_arg(arglist, &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt;);
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;falsch ist und durch&lt;/p&gt;
&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt; c = (&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt;)va_arg(arglist, &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt;);
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;ersetzt werden muss.&lt;/p&gt;

&lt;p&gt;Nun gut. Aber warum haben wir unter Windows kein Problem während der GCC
unter Linux bockt?&lt;/p&gt;

&lt;p&gt;Naja, MSVC versucht Programmierfehler abzufangen und korrigiert den 
falschen Datentypen automatisch, was der GCC (völlig korrekt) nicht tut.&lt;/p&gt;

&lt;p&gt;Microsoft’s Versuche hier etwas zu verbessern sind aber eigentlich ein
Schuss ins Knie, wie auch andere Beispiele zeigen.&lt;br /&gt;
Denn wann immer ein Compiler vom Standard abweicht entsteht nicht portierbarer
Code und dann beginnt Jahre später die Debatte, dass man nicht auf einen 
neueren Compiler wechseln darf, weil der dann dem Standard entspricht
aber die Programme darauf nicht mehr funktionieren.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Wie auch immer … ich habe wieder etwas Wissen aufgefrischt und der GATE
Code läuft nun auch auf GCC und Linux wieder so wie er soll.&lt;/p&gt;

&lt;p&gt;Alles in allem war es dann doch noch ein schöner Tag.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Fitness bike power</title>
   <link href="https://www.opengate.at/blog/2019/06/bike-power/"/>
   <published>2019-06-22T12:00:00+02:00</published>
   <updated>2019-06-22T12:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2019/06/bike-power</id>
   <category term="hardware" />
   <summary type="text">Wie war das noch mit diesem 
Fitness Bike ?

Nun ein Weilchen war ich wirklich fleißig und trat fast täglich darauf
herum, doch dann bekam es einen dummen “Bug”.

Es begann furchtbar laut zu quietschen …

</summary>
   <content type="html">&lt;p&gt;Wie war das noch mit diesem 
&lt;a href=&quot;/blog/2019/02/reed-bike/&quot;&gt;Fitness Bike&lt;/a&gt; ?&lt;/p&gt;

&lt;p&gt;Nun ein Weilchen war ich wirklich fleißig und trat fast täglich darauf
herum, doch dann bekam es einen dummen “Bug”.&lt;/p&gt;

&lt;p&gt;Es begann furchtbar laut zu quietschen …&lt;/p&gt;

&lt;!--more--&gt;
&lt;hr /&gt;

&lt;p&gt;… und schon war es mit der Motivation vorbei.&lt;/p&gt;

&lt;p&gt;Unlängst kam mir aber eine interessante Idee, als ich mir folgende Frage
stellte:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Kann man mit dem Ding nicht was sinnvolles machen … 
wie z.B. Strom erzeugen?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Und schon war das Gerät wieder interessant.&lt;/p&gt;

&lt;p&gt;Manche Elektromotoren sind umgekehrte &lt;a href=&quot;https://de.wikipedia.org/wiki/Fahrraddynamo&quot;&gt;Dynamos&lt;/a&gt;, 
sowie Dynamos umgekehrte Motoren sind: Wenn man Strom reinsteckt, 
kommt Bewegung raus und wenn man Bewegung reinsteckt kommt Strom heraus.&lt;/p&gt;

&lt;p&gt;Jetzt sind aber weder meine Test-Motoren von Technikexperimenten und schon 
gar nicht Servos dafür geeignet mit einer Radkurbel betrieben zu werden.&lt;/p&gt;

&lt;p&gt;Doch beim Zerlegen eines defekten alten &lt;a href=&quot;https://de.wikipedia.org/wiki/CD-ROM-Laufwerk&quot;&gt;CD-Laufwerk&lt;/a&gt;
blieb ein Teil übrig, mit dem das was werden konnte: Nämlich der kleine 
Motor, der die Lade auf und zu macht.&lt;/p&gt;

&lt;p&gt;Dieser war (bei meinem Modell) nämlich mit einem Gummiband mit der Auswurf-
Mechanik verbunden und hatte selbst ein entsprechendes Rädchen verbaut.&lt;/p&gt;

&lt;p&gt;Warum also nicht die Bewegung der Radkurbel auf den Motor per Gummiband
übertragen?&lt;/p&gt;

&lt;p&gt;Gesagt, getan.&lt;br /&gt;
In ein paar Minuten hatte ich mit Kabelbindern und den Kartonresten des
Verpackungsmaterials einer Schreibtischschublade eine kleinen Sockel
am Radboden fixiert, wo ich den kleinen Motor festschnallen konnte.&lt;/p&gt;

&lt;p&gt;In der Küche fand ich mit etwas Glück noch ein etwas größeres 
Gummiband und zog es über. … Fertig.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/fitness-bike-power-01.jpg&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Nun kam das &lt;a href=&quot;https://de.wikipedia.org/wiki/Multimeter&quot;&gt;Multimeter&lt;/a&gt; 
zum Handkuss und durfte erste Ergebnisse messen, während ich mit der Hand 
die Pedale bewegte.&lt;br /&gt;
Etwa 2-3 Volt kamen als aus dem kleinen Motor heraus.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/fitness-bike-power-02.jpg&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Hmm, das wäre gerade noch so an der Grenze für den Betrieb eines meiner
kleinen &lt;a href=&quot;https://en.wikipedia.org/wiki/Boost_converter&quot;&gt;Step-Up-Booster&lt;/a&gt; 
Module, dich ich auch bei Solarzellen einsetze um ihren Output auf 5 Volt 
zu erhöhen um andere USB basierte Ladevorgänge durchzuführen.&lt;/p&gt;

&lt;p&gt;Also wurde schnell eines der Module auf eine Prototyp-Platine verpfropft, wo
auch ein kleiner Kondensator untergebracht war, der Spannungsberge und -täler
ausgleichen soll.&lt;/p&gt;

&lt;p&gt;Nun wurde an das USB-Modul noch eine Powerbank angeschlossen und der finale
Test gestartet.&lt;/p&gt;

&lt;p&gt;Na was sagt man dazu … wenn morgen das Stromnetz zusammenbricht, dann könnte
ich rein theoretisch die eine oder andere Batterie mit Muskelkraft wieder
aufladen.&lt;/p&gt;

&lt;p&gt;Wäre eigentlich gut, wenn man gelegentlich dazu gezwungen wird, Strom selbst
zu produzieren. Denn für eine volle Ladung sind vermutlich unzählige Stunden 
Strampeln erforderlich.&lt;br /&gt;
Da würde ich endlich wieder mal zu schätzen wissen, wie toll es ist, dass 
fast unbegrenzt Strom bei uns aus jeder Steckdose kommt.&lt;/p&gt;

&lt;video controls=&quot;&quot; loop=&quot;&quot;&gt;
  &lt;source src=&quot;/blog/assets/video/fitness-bike-power.m4v&quot; type=&quot;video/mp4&quot; /&gt;
  Your browser does not support the HTML5 VIDEO tag.
&lt;/video&gt;
</content>
 </entry>
 
 <entry>
   <title>Code-Review und Code-Kritik?</title>
   <link href="https://www.opengate.at/blog/2019/06/code-criticism/"/>
   <published>2019-06-16T12:00:00+02:00</published>
   <updated>2019-06-16T12:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2019/06/code-criticism</id>
   <category term="devel" /><category term="general" />
   <summary type="text">Wie schön war das noch zu Schulzeiten, als man sich zum Nachbarn rüberbeugte
und frage:


  Kannst du da nochmal drüberlesen?


Denn das Resultat war konkret und ehrlich. Von “interessiert mich nicht” bis
hin zu echt guten Tips nach dem Schema “Ich würde das so und so anders machen”
erhielt man schnell eine entsprechende Antwort.

Und wie sieht das im Beruf aus?
</summary>
   <content type="html">&lt;p&gt;Wie schön war das noch zu Schulzeiten, als man sich zum Nachbarn rüberbeugte
und frage:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Kannst du da nochmal drüberlesen?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Denn das Resultat war konkret und ehrlich. Von “interessiert mich nicht” bis
hin zu echt guten Tips nach dem Schema “Ich würde das so und so anders machen”
erhielt man schnell eine entsprechende Antwort.&lt;/p&gt;

&lt;p&gt;Und wie sieht das im Beruf aus?
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Sollte es so wirken, wir &lt;a href=&quot;https://de.wikipedia.org/wiki/Marcel_Reich-Ranicki&quot;&gt;Marcel Reich-Ranicky&lt;/a&gt;
im &lt;a href=&quot;https://de.wikipedia.org/wiki/Das_Literarische_Quartett&quot;&gt;Literarischen Quartett&lt;/a&gt; ?&lt;/p&gt;

&lt;p&gt;Eigentlich wäre das ja ein schmeichlerischer Gedanke, denn gerne würde ich als
alter Mann hoch geschätzt und deshalb beliebt trotz harter Worte gerne von 
einem Code-Thron auf die armen Kindlein herabreden und ihnen mit belehrender
Stimme klar machen, was gut und was schlecht an ihrem Werk ist.&lt;/p&gt;

&lt;p&gt;… und leider würde das genau so arrogant ausstrahlen, wie ich es eben
beschrieben habe.&lt;/p&gt;

&lt;p&gt;Denn die Gewichtigkeit eines Herrn Reich-Ranicky in der Literatur kann nach
heutigen Maßstäben gerade in der Software-Entwicklung niemand erreichen.&lt;/p&gt;

&lt;p&gt;Obwohl viele Menschen vergessen, dass Quellcode rechtlich zur Literatur 
gezählt wird, ist es doch etwas anderes, wenn man sich in Anekdoten an die
großen Geister der Weltliteratur erinnert, oder ob man die Änderungen an
den Zeilen 23054 - 24860 als sinnvoll oder unpassend deklariert.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Mir jedoch fehlt heute in zunehmenden Maße der … naja, sagen wir mal:
ästhetische Ansatz der Beurteilung von Quellcodes, so wie es in der Schule
noch war.&lt;/p&gt;

&lt;p&gt;In beruflichen Umfeld wird “Codereview” immer wieder als Anwenden von Regeln 
für Zeilenumbrüche und Aufteilung von Blöcken in unterschiedliche Funktionen
betrachtet.&lt;/p&gt;

&lt;p&gt;Sinnvoller wäre es aber meiner Meinung nach eher zu beanstanden, dass z.B. 
unkontrolliert zwischen C und C++ oder einer synchronen und asynchronen
Kommunikationsart hin und hergewechselt wird.&lt;/p&gt;

&lt;p&gt;Würden wir hier von Literatur sprechen, so würde es wohl jedem auffallen,
wenn zwischen Perfekt, Imperfekt und Plusquamperfekt “unprofessionell”
hin und her geschwankt wird, doch gerade dort, wo unsere “Worte” in 
viele digitale Taten übersetzt werden, liegt das Augenmerk leider nur 
zu oft beim “Aussehen” der Noten, aber nicht beim Klang der Musik.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Deshalb freut es mich um so mehr, dass ich aktuell mal wieder an einem
gegenseitigem Code-Review teilnehmen durfte, in welchem wir über die Inhalte
sprechen konnten und hoffe, dass diese Art der Qualitätssicherung sich 
weiter fortsetzt.&lt;/p&gt;

&lt;p&gt;Wenn ich da so an eine wichtige Komponente eines Zulieferers im 
letzten Job zurückdenke, wo wirklich gar nichts funktioniert hat, aber im 
Bericht geschrieben stand, dass “eh alles ‘reviewt’ wurde”, kommen
mir leider Zweifel an den “üblichen” Vorgehensweisen in der 
Softwareentwicklung.&lt;/p&gt;

&lt;p&gt;Gekrönt wird das dann durch “Quell-Kot”, in dem Variablen und Funktionen
in deutscher Sprache benannt sind, genau so als würden wir jetzt in jedem
Land ein anderes Alphabet einführen, nur weil es “einfacher” erscheint.&lt;/p&gt;

&lt;p&gt;Ich bringe dann immer wieder gerne den alten Werbespruch von 
Microsoft aus den Anfängen der 2000er, wo es in etwa hieß:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Mit dotNet ist Programmieren jetzt so einfach, das kann jeder.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Worauf ich immer hinten das Wort “Dummkopf” anfüge und dann frustriert sage:&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;Und deshalb haben wir heute eine Vielzahl (von Dummköpfen), die glauben
programmieren zu können.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ich will es nicht grundsätzlich schlecht reden, aber die Quantität hat die 
Qualität massiv reduziert.
Immer schneller und kürzer müssen die Arbeitszyklen werden und immer weniger
wird das Augenmerk auf langfristig stabile Produkte gerichtet.&lt;/p&gt;

&lt;p&gt;Gerne würde ich ja behaupten, dass das ein Java oder C# Problem sei,
doch leider sieht es in der C++ Welt um kein bisschen besser aus.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Es mag nun anmaßend klingen, aber ich versuche es mal so auszudrücken,
wie der große Literaturpapst es vielleicht hätte ausdrücken können.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ja, das war eine sehr merkwürdig Zeit.
Wenn man bedenkt, wie ein Stroustrup pointiert mit wenigen Vokabel 
einfach alles präzise ausdrücken konnte. Fabelhaft.&lt;br /&gt;
Doch dann kamen die “Direktoren” und versuchten ihre Absichten
mit schnellen Schritten an ihr Ziel zu bringen.
Es war schrecklich ihre eilig hingeworfenen “Werke” anzunehmen und mit
bestehendem zu vergleichen oder zu vereinen.&lt;br /&gt;
Ja, man darf verkürzen, reduzieren und vereinfachen,
aber viele Autoren heute tun das nur all zu oft und viel zu
leichtfertig.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Hier noch ein Beispiel unseres leider verstorbenen Vorbildes:&lt;/p&gt;

&lt;iframe width=&quot;640&quot; height=&quot;360&quot; src=&quot;/blog/redirect.html?https%3A%2F%2Fwww.youtube-nocookie.com%2Fembed%2FxdlEwQF6X_s%3Fstart%3D456&quot; frameborder=&quot;1&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
</content>
 </entry>
 
 <entry>
   <title>Beweisführung: Debug vs Release</title>
   <link href="https://www.opengate.at/blog/2019/06/debug-release/"/>
   <published>2019-06-10T12:00:00+02:00</published>
   <updated>2019-06-10T12:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2019/06/debug-release</id>
   <category term="devel" />
   <summary type="text">Ich könnte mich in den Arsch beißen, dass ausgerechnet mir so etwas passiert,
wo ich doch immer wieder lange darüber rede:


  Man darf Debug und Release Bibliotheken nicht durcheinander bringen.


Tja, und jetzt habe ich viel Zeit mit einem Phantom-Problem vergeudet…
</summary>
   <content type="html">&lt;p&gt;Ich könnte mich in den Arsch beißen, dass ausgerechnet mir so etwas passiert,
wo ich doch immer wieder lange darüber rede:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Man darf Debug und Release Bibliotheken nicht durcheinander bringen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Tja, und jetzt habe ich viel Zeit mit einem Phantom-Problem vergeudet…
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;In der guten alten &lt;a href=&quot;https://de.wikipedia.org/wiki/C_(Programmiersprache)&quot;&gt;C-Welt&lt;/a&gt; 
war noch alles in Ordnung, weil Funktionen nur “flache” Datentypen hin und her 
befördern konnten. Und diese “flachen” Typen waren auch nur einmal in einem 
Header definiert und dadurch (zufällig) in ihrem Aufbau ein binärer Standard.&lt;/p&gt;

&lt;p&gt;Und wenn es um Speicherverwaltung ging, musste nur die von allen geteilte
C-Laufzeit mit &lt;code&gt;malloc()&lt;/code&gt; und &lt;code&gt;free()&lt;/code&gt; herhalten.&lt;/p&gt;

&lt;p&gt;Mit C++ kamen aber (mindestens) zwei Features auf, die den 
“binären C Standard” außer Kraft setzten.&lt;br /&gt;
Nicht grundlos deklariert der C++ Standard das Exportieren von C++ Funktionen
als “undefiniertes” bzw. nicht standardisiertes Verhalten.&lt;/p&gt;

&lt;p&gt;Doch haben alle modernen Compiler für sich selbst ein bestimmtes Verhalten 
“definiert”, womit es üblich ist, dass sowohl C++ Funktionen als auch 
ganze Klassendefinitionen exportiert werden können.&lt;/p&gt;

&lt;p&gt;Die zwei erwähnten Features sind:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Der C++ Heap, Templates und automatisch ausgeführte Konstruktor- und 
Destruktor-Routinen.&lt;/li&gt;
  &lt;li&gt;Spezielle Debugging-Hilfen für die Standard Bibliothek 
&lt;a href=&quot;https://en.wikipedia.org/wiki/Standard_Template_Library&quot;&gt;(STL)&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Punkt 1. hört sich fast wie 3 Punkte an, doch im mir wichtigen Szenario 
spielen diese drei nämlich zusammen:
Wird ein Objekt erzeugt (konstruiert), nutzt der Compiler nämlich 
jene Allokator-Routinen, die im aktuellen Scope “sichtbar” sind.
Und bei Bibliotheken kann das eben pro Bibliothek anders ablaufen, denn:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Zumindest unter Windows können DLLs eigene Heaps nutzen, womit ein 
&lt;code&gt;new&lt;/code&gt; in einer Bibliothek NICHT mit einem &lt;code&gt;delete&lt;/code&gt; im Hauptprogramm
aufgeräumt werden darf. Das gilt auch für Konstruktoren ohne &lt;code&gt;new&lt;/code&gt;,
die z.B. bei einem &lt;code&gt;return&lt;/code&gt; mit dem Bibliotheks-Scope Bytes in den
Callstack einer Funktion schreiben, die dem Hauptprogramm angehört.
Der dortige Destruktor kann diese Daten unter Umständen dann nicht
korrekt freigeben.&lt;/li&gt;
  &lt;li&gt;Die Operatoren &lt;code&gt;new&lt;/code&gt; und &lt;code&gt;delete&lt;/code&gt; können überladen werden und somit
abhängig von &lt;code&gt;include&lt;/code&gt;-Konstellationen andere Ergebnisse liefen, womit
ebenfalls ein &lt;code&gt;delete&lt;/code&gt; mit einem ihm fremden &lt;code&gt;new&lt;/code&gt; in Konflikt gerät.&lt;/li&gt;
  &lt;li&gt;Templates machen die Sache noch komplexer, wenn sie als Header-Only
Includes ebenso in jeder Übersetzungseinheit “anders” interpretiert
werden können. Es existiert nicht “eine” Implementierung die immer
identisch ist, sondern jede Template-Anwendung kann separate 
unterschiedliche Auswirkungen haben.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Doch am “störendsten” manifestiert sich die Eigenschaft der STL 
Implementierung, dass Strukturen je nach Kompiliereinstellung andere
Objekt-Member oder auch Methoden im Angebot haben.&lt;/p&gt;

&lt;p&gt;Eine Release-Variante eines Objektes beinhaltet meist nur
jene Member, die mindestens erforderlich sind, aber eben auch nicht mehr.&lt;/p&gt;

&lt;p&gt;Im Debug-Modus vergrößern sich jedoch viele Objekte und stellen weitere
private Member zur Verfügung um Cookies oder andere States zu speichern.
Benötigt wird das z.B. zum &lt;a href=&quot;https://de.wikipedia.org/wiki/Iterator&quot;&gt;Iterator&lt;/a&gt; 
Debugging.&lt;br /&gt;
Wir wissen ja, dass lesende Iteratoren automatisch ungültig werden,
wenn während ihrer Nutzung das Elternobjekt verändert wird.&lt;br /&gt;
Das ergäbe normalerweise unkontrollierte Abstürze, doch die STL
speichert daher gerne in den Eltern- und Iterator-Objekten Cookies,
die bei jedem Methodenaufruf gegengeprüft werden.&lt;br /&gt;
Kam es also zu einer ungewollten Veränderung, wird “kontrolliert” ein
&lt;code&gt;assert&lt;/code&gt; oder &lt;code&gt;abort()&lt;/code&gt; ausgelöst oder eine 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Ausnahmebehandlung&quot;&gt;Exception&lt;/a&gt; abgefeuert.&lt;/p&gt;

&lt;p&gt;Tja, und daraus ergibt sich eben, dass in einem Gebilde aus einer
Executable und mehreren Bibliotheken bei allen die gleichen 
Compiler-Einstellungen gelten &lt;strong&gt;müssen&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Ist das nicht der Fall, kann z.B. ein Release-Hauptprogramm keine 
&lt;code&gt;std::string&lt;/code&gt; Objekte einer Debug-DLL (oder -SO) entgegennehmen, weil:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Der Zugriff auf Methoden und die verknüpften Daten bei falschen
Speicheradressen landet.&lt;/li&gt;
  &lt;li&gt;Methoden- und Memberpointer nicht mehr auf die richtigen Adressen zeigen, 
wenn&lt;code&gt;#include&lt;/code&gt; Typen je nach Einstellung mit anderen Features ausgestattet 
sind.&lt;/li&gt;
  &lt;li&gt;Weil Allokationen, vor allem die automatischen durch C++, die
“falschen” &lt;code&gt;delete&lt;/code&gt; Codes ausführen.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Man kann in Visual Studio sehr leicht ein DLL und ein EXE Projekt
erstellen, wo die DLL ein Funktion mit einem &lt;code&gt;std::string&lt;/code&gt; return Wert
bereitstellt und ein Konsolenprogramm, welches die Funktion aufruft.&lt;/p&gt;

&lt;p&gt;Erstellt man dann ein Debug und ein Release Build von beiden und kopiert
ganz fies die Debug DLL ins Release-Verzeichnis und umgekehrt, fängt es
schon an zu krachen.&lt;/p&gt;

&lt;p&gt;Natürlich kann auch mal alles gut gehen, beim GCC dürfte das auch öfter so 
sein, doch das heißt nur, dass die Korruption nicht ausreichend war um
gleich aufzufallen oder dass die Korruption optisch nicht sichtbar war.&lt;/p&gt;

&lt;p&gt;In jedem Fall kommt so eine defekt Konstellation zusammen, die dann schwer
zu debuggen ist.&lt;/p&gt;

&lt;p&gt;Daher Notiz an mich selbst (und alle anderen, denen das auch schon mal
passiert ist):&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Immer aufpassen, dass Debug und Release nicht gekreuzt wird.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Das Ergebnis kann schrecklich aussehen …&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Kopfhörer reparieren</title>
   <link href="https://www.opengate.at/blog/2019/06/headset/"/>
   <published>2019-06-02T21:41:00+02:00</published>
   <updated>2019-06-02T21:41:00+02:00</updated>
   <id>https://www.opengate.at/blog/2019/06/headset</id>
   <category term="hardware" />
   <summary type="text">Und alle paar Monate das gleiche Spiel: Mein PC 
Kopfhörer gibt den Geist auf
… im Sinne von: Nur noch eine Seite gibt Klänge von sich.

Normalerweise laufe ich dann panisch in den nächsten Laden um mir einen neuen 
zu kaufen, doch diesmal kam es anders…
</summary>
   <content type="html">&lt;p&gt;Und alle paar Monate das gleiche Spiel: Mein PC 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Kopfh%C3%B6rer&quot;&gt;Kopfhörer&lt;/a&gt; gibt den Geist auf&lt;br /&gt;
… im Sinne von: Nur noch eine Seite gibt Klänge von sich.&lt;/p&gt;

&lt;p&gt;Normalerweise laufe ich dann panisch in den nächsten Laden um mir einen neuen 
zu kaufen, doch diesmal kam es anders…
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Die eigentlichen Kopfhörer sind in der Regel nicht das Problem und leben
(wenn nichts Schlimmeres passiert) bei mir ewig.&lt;br /&gt;
Doch die Kabel stehen immer unter “Zugzwang”. Denn es kommt gelegentlich
mal vor, dass ich mit dem Rollsessel über sie drüberfahre, oder der
Stecker beim wechseln auf andere Geräte abgenutzt wird.&lt;/p&gt;

&lt;p&gt;Nun habe ich seit Ewigkeiten kurze 3.5 mm Klinkensteckerkabel in meiner
Schublade liegen, die noch von einer verschrotteten 
&lt;a href=&quot;https://de.wikipedia.org/wiki/TV-Karte&quot;&gt;TV-Karte&lt;/a&gt; übrig waren.
(Damals musste man den Ton noch per Line-Out der TV-Karte auf Line-In der
Soundkarte übertragen.)&lt;/p&gt;

&lt;p&gt;Also nicht lange überlegt und einfach die Kabel durchgeschnitten.&lt;/p&gt;

&lt;p&gt;Die Idee:&lt;br /&gt;
&lt;code&gt;Defekter Kopfhörer + anderer Klinkenstecker = Funktionierender Kopfhörer&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Etwas lästig waren die Kabel, die für mich nicht ganz schlüssig waren 
(nämlich 5 statt 4 für Links, Rechts und 2x Ground) und beim Test durch manuelles
Zusammendrücken tat sich nichts.&lt;br /&gt;
Doch das lag an der Versiegelung der Drähte. Die sind nämlich mit einem 
nicht-leitenden Lack versehen und sind nicht wie üblich mit Plastik isoliert.&lt;/p&gt;

&lt;p&gt;Doch wenn man den Lötkolben da etwas draufhält schmilzt und verdampft das 
Zeug und dann können die beiden Seiten mit einem Tröpfchen Lötzinn 
zusammengekleistert werden.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Wichtiger Hinweis:&lt;/em&gt; Immer gut Lüften nach so einer Aktion … denn dem
Geruch nach ist der Lack sicher nicht gesundheitsförderlich.&lt;/p&gt;

&lt;p&gt;Am Ende kommt noch ein Schrumpfschlauch drüber und fertig ist der Tonspender.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/repair-headset.jpg&quot; alt=&quot;Repair Headset&quot; /&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Und hat es funktioniert?&lt;/p&gt;

&lt;p&gt;Ja, hat es und ich merke zumindest keinen Qualitätsverlust. Diese Lösung wird
zwar auch nicht ewig halten, doch zumindest kann ich nun den Kauf neuer
Hardware hinauszögern und vorhandenen Müll selbst recyclen.&lt;/p&gt;

&lt;p&gt;Überhaupt werfen &lt;em&gt;wir&lt;/em&gt; (und leider auch ich) viel zu viel gleich weg.&lt;br /&gt;
Mit etwas Mühe kann man aber Kleinigkeiten leicht reparieren und so die
eigene sinnlose Müllproduktion reduzieren.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>LDAP und ADSI</title>
   <link href="https://www.opengate.at/blog/2019/06/ldap-adsi/"/>
   <published>2019-06-01T12:00:00+02:00</published>
   <updated>2019-06-01T12:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2019/06/ldap-adsi</id>
   <category term="software" /><category term="devel" />
   <summary type="text">Seit meiner Schulzeit hatte ich immer wieder kleinere Progrämmchen geschrieben,
sei es um Office-Arbeiten zu erleichtern oder Tools zum Suchen und Verwalten 
von Daten, Links oder Webseiten.
Und auch ein paar Webseiten selbst waren darunter.
Aber alles in allem keine weltbewegenden Sachen.

Das erste wirklich relevante “Programm” aus meinen Händen beschäftigte sich
mit LDAP, 
dem Active Directory und 
ist auch heute noch auf SourceForge 
zu finden.
</summary>
   <content type="html">&lt;p&gt;Seit meiner Schulzeit hatte ich immer wieder kleinere Progrämmchen geschrieben,
sei es um Office-Arbeiten zu erleichtern oder Tools zum Suchen und Verwalten 
von Daten, Links oder Webseiten.&lt;br /&gt;
Und auch ein paar Webseiten selbst waren darunter.&lt;br /&gt;
Aber alles in allem keine weltbewegenden Sachen.&lt;/p&gt;

&lt;p&gt;Das erste wirklich relevante “Programm” aus meinen Händen beschäftigte sich
mit &lt;a href=&quot;https://de.wikipedia.org/wiki/Lightweight_Directory_Access_Protocol&quot;&gt;LDAP&lt;/a&gt;, 
dem &lt;a href=&quot;https://de.wikipedia.org/wiki/Active_Directory&quot;&gt;Active Directory&lt;/a&gt; und 
ist auch heute noch auf &lt;a href=&quot;https://de.wikipedia.org/wiki/SourceForge&quot;&gt;SourceForge&lt;/a&gt; 
zu finden.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Es begann in meiner Tätigkeit als User-Administrator, wo ich großteils nur 
Benutzer auf Anfragen hin in Gruppen verschieben durfte, damit sie Rechte
in anderen Abteilungen, Applikationen oder Projekten erhalten sollten.&lt;/p&gt;

&lt;p&gt;Die Plattform war das Active Directory von 
&lt;a href=&quot;https://en.wikipedia.org/wiki/Windows_Server_2003&quot;&gt;Windows Server 2003&lt;/a&gt;.&lt;br /&gt;
Und damals lief auch die große Umstellung und Auflösung von 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_NT&quot;&gt;Windows NT&lt;/a&gt;,
wo alle User-Accounts ins Active Directory migriert werden mussten und dort
im neuen System wieder alle ihre Rechte erhalten sollten.&lt;br /&gt;
Das waren so um die 8000 Benutzeraccounts.&lt;/p&gt;

&lt;p&gt;Interessant dabei war, dass die Verantwortlichen im Unternehmen hierfür nur 
eine Lösung sahen:&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;Admins sollten die Accounts manuell verschieben, umbenennen und in neue
Gruppen aufnehmen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Anders gesagt: Eine riesige Verschwendung von Arbeitskräften.&lt;/p&gt;

&lt;p&gt;Denn Microsoft hatte schon mit &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_2000&quot;&gt;Windows 2000&lt;/a&gt;
eine neue LDAP Schnittstelle eingeführt, nämlich &lt;code&gt;ADSI&lt;/code&gt;, das 
&lt;a href=&quot;http://docs.microsoft.com/en-us/windows/win32/adsi/active-directory-service-interfaces-adsi&quot;&gt;Active Directory Service Interface&lt;/a&gt;, 
womit alle Objekte in einer Domäne angesprochen und bearbeitet werden konnten.&lt;br /&gt;
Das war über einfachste &lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_Basic_Script&quot;&gt;VB-Scripts&lt;/a&gt; 
möglich und recht gut dokumentiert. Aber auch in VB6 und C++ war es leicht
einsetzbar.&lt;/p&gt;

&lt;p&gt;Zwar hatte ich anfangs weder von ADSI noch von LDAP Ahnung, doch schnell
erkannte ich die Möglichkeit, dieses hirntötende manuelle Verschieben per
Maus automatisch ablaufen zu lassen.&lt;/p&gt;

&lt;p&gt;Eine Woche später konnte ich in meinem guten alten 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_Basic_Classic&quot;&gt;Visual Basic 6&lt;/a&gt; ein 
kleines Formular vorstellen, dass auf Knopfdruck bei allen Accounts in 
einer Suchmaske bestimmte Aktionen auslöste, wie:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Passwort Reset&lt;/li&gt;
  &lt;li&gt;Vorname, Nachname, Displayname, E-Mail-Adresse auf ein neues Format korrigieren&lt;/li&gt;
  &lt;li&gt;Account in andere OUs (Organizational Units) verschieben&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Das Resultat war durchaus beachtlich.&lt;br /&gt;
Während für ein paar tausend Accounts 4 Admins manuell ein Monat herumwerken 
mussten, wurden die restlichen paar tausend in 10 Minuten umgestellt.&lt;/p&gt;

&lt;p&gt;Mission accomplished.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Doch nun hatte ich Blut geleckt und genoss es zunehmend, den LDAP 
Verzeichnisdienst so einfach unter Kontrolle zu haben.&lt;/p&gt;

&lt;p&gt;Aber seien wir mal ehrlich, kompliziert war das ganze in VB nicht.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;Dim obj
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;obj = GetObject(&amp;quot;LDAP://CN=user,OU=org-branch,DC=domain,DC=com&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;obj.Put &amp;quot;attributeName&amp;quot;, &amp;quot;attributeValue&amp;quot;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;obj.SetInfo
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Also startete ich parallel zu Arbeit das Project 
&lt;a href=&quot;http://sourceforge.net/projects/acdir/&quot;&gt;“Active Director”&lt;/a&gt;,
ein Tool mit dem man ADSI Objekte selektieren und Templates
für Änderungen anlegen konnte, die im Anschluss auf die selektierten Objekte
ausgerollt wurden.&lt;br /&gt;
Man nennt das auch gerne mal: &lt;em&gt;Automation&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Denn wenn am Anfang jedes Monats eine Liste mit 30 Personen eintraf,
die es zu Löschen/Deaktivieren galt und eine weitere Liste mit 
Vorname, Nachname und Personalnummer, die als Accounts neu angelegt werden 
sollten, so waren immer X Personen einige Tage beschäftigt, 
das manuell und mit gelangweiltem Blick umzusetzen.&lt;/p&gt;

&lt;p&gt;Doch mit der Möglichkeit, dass diese Liste automatisch eingelesen wird 
und mit einer entsprechenden Vorlage binnen Sekunden ins Directory
übertragen wird, waren die menschlichen Ressourcen freigespielt um 
“echte” Probleme zu lösen oder zu analysieren, die den Betrieb nebenbei
schon lange störten.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Mit jenen Erfahrungen damals fiel mir auch die Nutzung der 
&lt;a href=&quot;https://de.wikipedia.org/wiki/.NET&quot;&gt;dotNet&lt;/a&gt;
&lt;a href=&quot;http://docs.microsoft.com/de-de/dotnet/api/system.directoryservices?view=netframework-2.0&quot;&gt;System.DirectoryServices&lt;/a&gt;
einfacher, denn die wahre Komplexität steckt im Aufbau der Attribute eines
LDAP Verzeichnisdienstes.&lt;/p&gt;

&lt;p&gt;Und auch die Konfiguration von anderen Diensten und Servern fällt einem viel
leichter, wenn man weiß, wo die gesamten LDAP Pfade herkommen.&lt;/p&gt;

&lt;p&gt;ADSI selbst wird zu meinem Bedauern mehr und mehr von .NET verdrängt, obwohl es
neben LDAP einen ganz wichtigen anderen Aspekt hat:&lt;br /&gt;
&lt;em&gt;Es ist eine offene Schnittstelle für unterschiedliche “Directories”.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Denn ADSI kann nicht nur Microsoft Active Directories ansprechen, sondern 
grundsätzlich jeden LDAP Server. Es wird auch standardmäßig mit dem
WinNT Provider ausgeliefert, der lokale Benutzeraccounts und -gruppen
verwalten kann, hier sehen einfach nur die Pfade anders aus:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;Dim obj, flags
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;obj = GetObject(&amp;quot;WinNT://PC-NAME/myaccount,user&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;flags = obj.Get(&amp;quot;UserFlags&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;flags = flags Or ADS_UF_DONT_EXPIRE_PASSWD
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;obj.Put &amp;quot;UserFlags&amp;quot;, flags
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;obj.AccountDisabled = False
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;obj.SetInfo
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Eine ganz besondere Spezialität hat Microsoft leider ab 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_Vista&quot;&gt;Windows Vista&lt;/a&gt; wieder 
entfernt, nämlich der Zugriff auf Novel Netware Directories.&lt;br /&gt;
Hierfür gab es bis Server 2003 und Windows XP den &lt;code&gt;NDS:&lt;/code&gt; und den &lt;code&gt;NWCOMPAT:&lt;/code&gt;
Provider um diese Systeme ebenso zu automatisieren.&lt;br /&gt;
Und ich konnte damals gar nicht anders als so lange im Netz zu suchen, bis
ich eine eigene alte Novell Installation bei mir hatte … 
und … es funktionierte!&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Ich bedauere etwas, dass mich mein Arbeitsweg von ADSI nun weggeführt hat und
mein altes “Active Director” Projekt nun langsam auf SourceForge verwest.&lt;br /&gt;
Zumindest zeitweise konnte ich mit dem Tool mit Größen wie 
&lt;a href=&quot;https://www.systemtools.com/hyena/&quot;&gt;Hyena&lt;/a&gt; mithalten, weil neben ADSI
auch &lt;a href=&quot;https://en.wikipedia.org/wiki/Windows_Management_Instrumentation&quot;&gt;WMI&lt;/a&gt;
integriert wurde und damit fast alles konfigurierbar wird.
Doch am Ende muss man solche Programme entweder kommerzialisieren oder sie 
beenden.&lt;/p&gt;

&lt;p&gt;Doch trotz der alten (und aus heutiger Sicht hässlichen) VB6 Codebase, hat 
mich das Projekt viel über Verwaltung und Codeaufbau gelehrt. Schließlich
waren einige verworfene Ansätze notwendig, bis das ganze schlüssig
und lauffähig war.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Irgendwo in Europa</title>
   <link href="https://www.opengate.at/blog/2019/05/europe/"/>
   <published>2019-05-26T23:00:00+02:00</published>
   <updated>2019-05-26T23:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2019/05/europe</id>
   <category term="general" />
   <summary type="text">Es ist 23:00 Uhr ein damit bin ich von meinem Eid befreit, nicht über die 
heutige EU Wahl zu sprechen.

Das erste mal in meinem Leben durfte ich als sogenannter 
“Ersatzbeisitzer” in einem Wahllokal in meinem Bezirk sitzen.
</summary>
   <content type="html">&lt;p&gt;Es ist 23:00 Uhr ein damit bin ich von meinem Eid befreit, nicht über die 
heutige &lt;a href=&quot;https://de.wikipedia.org/wiki/Europawahl_2019&quot;&gt;EU Wahl&lt;/a&gt; zu sprechen.&lt;/p&gt;

&lt;p&gt;Das erste mal in meinem Leben durfte ich als sogenannter 
“Ersatzbeisitzer” in einem Wahllokal in meinem Bezirk sitzen.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Wir lernen zwar in der Schule, dass wir in einer 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Demokratie&quot;&gt;Demokratie&lt;/a&gt; leben, 
doch bisher beschränkte sich das für mich auf das gelegentliche Ankreuzen
alle paar Jahre … meist nicht mal das.&lt;/p&gt;

&lt;p&gt;Doch in den letzten Jahren ist mir aufgefallen, dass neben jenen, die
gerne Vorne stehen und sich als große Retter, Beschützer und Vertreter
feiern lassen, eigentlich auch andere immer wieder verlässlich zur
Stelle sind, wenn es darum geht sicher zu stellen, dass “das Volk”
seine Stimme einbringen kann.&lt;/p&gt;

&lt;p&gt;Und so habe ich dieses Jahr mal im politisch tätigem Bekanntenkreis
nachgefragt, wer eigentlich die Wahlstimmen auszählt.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Einfache Leute wie du und ich.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;war die Antwort.
Jede zur Wahl zugelassene Partei kann freiwillige Personen als
Wahlbeisitzer vorschlagen. Ziel ist, dass möglichst alle 
politischen Richtungen wie auch Unabhängige dabei sind und nicht 
nur “einschlägige” Parteisoldaten.&lt;/p&gt;

&lt;p&gt;Heute Sonntag früh um 6:15 Uhr war Treffpunkt im schon zwei Wochen 
zuvor bekanntgegebenen Wahllokal, in meinem Fall einer Wiener Schule.
Ebenso wurde mir ein Link zu einer Schulungsseite des Innenministeriums
übermittelt, wo man alles über einen korrekten Wahlablauf lernen kann
und am Ende darüber mit ein paar Fragen abgeprüft wird.&lt;/p&gt;

&lt;p&gt;Bis zur Öffnung des Wahllokals wurde uns vom Wahlleiter und seinem
Stellvertreter noch eine Einführung gegeben, wie wir die Wähler
schriftlich festhalten sollen und am Ende folgte die Ablegung des
Eides, bis 23:00 Uhr (Schließung des letzten Wahllokals in der EU)
nicht über die erlebten Ereignisse der Wahl sprechen zu dürfen.&lt;/p&gt;

&lt;p&gt;Und so kamen tröpfchenweise Wählerinnen und Wähler in den Raum,
und zeigten ihre Wahlinformationskarte mit ihrer Nummer im Wählerverzeichnis
vor. Jeder von uns Beisitzern hatte einen Teil der Liste aller 
registrierten Wähler vor sich und wir lasen dessen Namen hinter der Nummer 
laut vor. Der Wahlleiter bzw. sein Stellvertreter prüfte inzwischen, 
ob auf dem vorgezeigten Lichtbildausweis der gleiche Name vermerkt war.&lt;/p&gt;

&lt;p&gt;Dann wurde die fortlaufende Nummer der Stimmabgabe genannt, die
wir wiederum beim Wähler eintrugen. Also erster Wähler Nr. 1, 
zweiter Wähler Nr. 2, usw.
Darauf hin wurde der Stimmzettel samt Kuvert überreicht und in der Wahlkabine
ausgefüllt, um das befüllte Kuvert am Ende in die versiegelte Urne zu werfen.&lt;/p&gt;

&lt;p&gt;So läuft das also ab. Wähler im Verzeichnis finden, seine Nummer nennen,
und parallel seine “Stimmabgabenummer” erfassen.&lt;/p&gt;

&lt;p&gt;Wenn jemand seine Infokarte mit seiner Nummer nicht dabei hatte, musste
er über seine Wohnadresse gesucht werden, denn die Listen waren nach 
Adressen sortiert.&lt;/p&gt;

&lt;p&gt;Während des Tages gab es einige Kontrollen von Beamten, die feststellten
ob alles ordnungsgemäß ablief und ob Fragen aufgetreten waren.
Aber außer einigen wenigen Fällen, wo Wähler im falschen Wahllokal 
erschienen, lief alles ruhig und geordnet ab.&lt;/p&gt;

&lt;p&gt;Um 17:00 Uhr wurde das Lokal geschlossen und die Wahlurne geöffnet.
Zuerst wurden die Kuverts durchgezählt, ob deren Anzahl gleich der
letzten Stimmabgabenummer war … und das war auch so.&lt;/p&gt;

&lt;p&gt;Dann wurden die Kuverts geöffnet und die Stimmzettel nach Parteien
gemeinsam durchsortiert, wobei immer wieder gegengerechnet wurde, 
ob die Gesamtsumme stimmte.&lt;/p&gt;

&lt;p&gt;Nach der Sortierung nach Parteien wurden noch Vorzugsstimmen und
vorzugslose Stimmzettel aussortiert.&lt;/p&gt;

&lt;p&gt;Bei gegenseitiger Kontrolle trug dann der Wahlleiter alle 
ausgezählten Daten in ein einsprechendes Formular ein,
welches wir alle am Ende mit unserer Unterschrift als 
“korrekt” verifizierten.&lt;/p&gt;

&lt;p&gt;Dann folgte noch eine telefonische Meldung des Ergebnisses an eine 
obere Stelle und damit war der Wahlsonntag für uns erledigt.
Bereits gegen 18:30 Uhr war alles beendet und wir konnten den 
Heimweg antreten.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Für mich war das ein spannender Tag an dem ich Demokratie 
mal “von einer anderen Seite” kennenlernen durfte. Und ich kann 
auch erneut bestätigen, dass in unserem Lokal alles seinen korrekten Ablauf
gefunden hat.&lt;br /&gt;
Verschwundene Wahlzettel oder “kreative” Auszählformen konnte es wegen
der gegenseitigen Kontrolle nicht geben.&lt;/p&gt;

&lt;p&gt;Enttäuscht war ich von der geringen Wahlbeteiligung in meiner Umgebung.
Gerade einmal 40% der registrierten Personen waren zu uns gekommen um von
ihrem Stimmrecht Gebrauch zu machen.&lt;br /&gt;
Eine solche Zahl ist für jede Wahl ein schlechtes Beispiel. Und ich finde es 
Schade, dass wir unsere Verantwortung innerhalb Europas nicht wahrnehmen und 
dann dennoch bei jeder Gelegenheit über EU-Beschlüsse schimpfen.&lt;/p&gt;

&lt;p&gt;Doch da ich gerade erfahren habe, dass die Wahlbeteiligung österreich-weit 
bei über 50% liegt, bin ich dezent beruhigt … denn 50% sind aus meiner
Sicht das absolute Minimum für eine demokratische Legitimation.&lt;/p&gt;

&lt;p&gt;Jedem, der daran Interesse hat, kann ich nur empfehlen dieses Ehrenamt 
ebenso einmal zu bekleiden. Es ist nichts magisch-geheimnisvolles daran, 
nur streckenweise etwas eintönig … doch man kann dann mit Recht behaupten,
zumindest ein bisschen etwas “für die Demokratie” getan zu haben.&lt;/p&gt;

&lt;p&gt;… von ein paar interessanten Gesprächen mit den netten anderen Wahlbeisitzern
mal abgesehen …&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Boost C++</title>
   <link href="https://www.opengate.at/blog/2019/05/boost/"/>
   <published>2019-05-19T12:00:00+02:00</published>
   <updated>2019-05-19T12:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2019/05/boost</id>
   <category term="devel" />
   <summary type="text">In meinen ersten Jahren in der C++
Programmierung hatte ich viel zu lernen, und suchte vor allem auch nach guten
Vorbildern für diese Bildungsreise.

Und wer nach C++ library XYZ googlet, wobei XYZ jedes beliebige Problem sein
kann, der wird sehr häufig auf die Seite boost.org stoßen.

Und obwohl ich es immer strikt ablehne, boost in meinen Projekten einzusetzen, 
so gibt es kaum eine andere Bibliothek aus der ich mehr gelernt hätte.
</summary>
   <content type="html">&lt;p&gt;In meinen ersten Jahren in der &lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B&quot;&gt;C++&lt;/a&gt;
Programmierung hatte ich viel zu lernen, und suchte vor allem auch nach guten
Vorbildern für diese Bildungsreise.&lt;/p&gt;

&lt;p&gt;Und wer nach &lt;code&gt;C++ library XYZ&lt;/code&gt; googlet, wobei &lt;code&gt;XYZ&lt;/code&gt; jedes beliebige Problem sein
kann, der wird sehr häufig auf die Seite &lt;a href=&quot;http://www.boost.org/&quot;&gt;&lt;code&gt;boost.org&lt;/code&gt;&lt;/a&gt; stoßen.&lt;/p&gt;

&lt;p&gt;Und obwohl ich es immer strikt ablehne, boost in meinen Projekten einzusetzen, 
so gibt es kaum eine andere Bibliothek aus der ich mehr gelernt hätte.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Zwischen den Jahren 1998 und 2011 herrschte ein sprichwörtliches Chaos in der C++
Community, welches auch mich ab 2006 traf.&lt;/p&gt;

&lt;p&gt;Der C++ Standard 98 hatte (wie damals üblich) nur mathematische Konstrukte und
generische Container (Arrays, Listen und Dictionaries) in seiner 
Standard-Bibliothek &lt;a href=&quot;https://en.wikipedia.org/wiki/Standard_Template_Library&quot;&gt;(STL)&lt;/a&gt;
abgedeckt.&lt;br /&gt;
Man konnte gerade noch so Dateien öffnen und schließen doch bereits das 
Auflisten eines Verzeichnisses war nicht enthalten.&lt;/p&gt;

&lt;p&gt;Und so begann das Aufblühen von hunderten Bibliotheken, die Systemfunktionen
in C++ einführen sollten.&lt;br /&gt;
Jede war anders, hatte ihre eigenen Macken und war vor allem zu sonst nichts 
kompatibel.&lt;/p&gt;

&lt;p&gt;13 Jahre ließen sich die C++ Architekten Zeit um einen neuen Standard (C++11)
zu entwerfen.&lt;/p&gt;

&lt;p&gt;Doch bis dahin fanden viele Entwickler zusammen und gründeten ein neues 
Projekt, nämlich &lt;code&gt;BOOST&lt;/code&gt; welches als Vorlage für künftige C++ Standards
dienen sollte.&lt;/p&gt;

&lt;p&gt;Es fing mit einfachen Dingen wie atomaren Zugriffen an und arbeitete sich 
über Shared Pointer bis zum Filesystem hoch.&lt;br /&gt;
Interessant wurde es dann aber mit asynchronen Funktionen und jeder 
Menge an Template-Tricks um Daten parsen zu können.&lt;/p&gt;

&lt;p&gt;Und weil &lt;code&gt;BOOST&lt;/code&gt; eben kein spezielles Anwendungsproblem lösen wollte, sondern
ganz allgemein die C++ Plattform erweitern bzw. nutzbar machen wollte, 
wurde diese Bibliothek die Grundlage viele anderen Bibliotheken, die heute 
eine Großteil aller C++ basierten Applikationen berühren.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Wer also mit neuen &lt;code&gt;BOOST&lt;/code&gt; Funktionen arbeitet, hat eine gute Chance, dass
diese “neuen” Routinen in den jeweils nächsten C++ Standard aufgenommen 
werden und damit noch umfassender werden … so die Theorie.&lt;/p&gt;

&lt;p&gt;Und tatsächlich ist &lt;code&gt;BOOST&lt;/code&gt; heute so etwas wie eine bessere &lt;code&gt;STL&lt;/code&gt; geworden
und auch geblieben.&lt;/p&gt;

&lt;p&gt;Wiese arbeite ich also nicht so gerne damit … ?&lt;/p&gt;

&lt;p&gt;Nun, &lt;code&gt;BOOST&lt;/code&gt; wollte seine neuen Features in allen üblichen Compilern 
zugänglich machen. Doch das war 10 bis 15 Jahren fast unmöglich.&lt;br /&gt;
Denn Microsofts weit verbreitetes &lt;code&gt;MSVC&lt;/code&gt; 6.0 erschien kurz vor der
Fertigstellung von C++98 und implementierte dessen Vorgaben teilweise nicht
oder nur dürftig.&lt;br /&gt;
Bestes Beispiel: VC++ 6 warf keine &lt;a href=&quot;http://www.cplusplus.com/reference/new/bad_alloc/&quot;&gt;&lt;code&gt;bad_alloc&lt;/code&gt;&lt;/a&gt;
exception, wenn &lt;code&gt;new&lt;/code&gt; fehlschlug, sondern gab einen NULL-Pointer zurück … 
eigentlich ein Schwerverbrechen.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;BOOST&lt;/code&gt; versuchte daher für jeden Compiler sein Verhalten so umzustellen,
dass es einheitlich wurde. Und dafür muss man die Bibliothek einfach lieben.
Doch gelöst wurden viele Probleme durch Makros, Makros und noch mehr Makros.&lt;/p&gt;

&lt;p&gt;Wollten wir nicht mit C++ die ungeliebten C Makros loswerden?
Ja, doch dann kam &lt;code&gt;BOOST&lt;/code&gt; und führte zehntausende davon ein um Features wie
&lt;code&gt;for_each&lt;/code&gt; oder &lt;a href=&quot;http://en.cppreference.com/w/cpp/language/lambda&quot;&gt;&lt;code&gt;lambda&lt;/code&gt;&lt;/a&gt; 
Funktionen einzuführen.&lt;br /&gt;
Und für diesen &lt;a href=&quot;https://de.wikipedia.org/wiki/Syntaktischer_Zucker&quot;&gt;Syntax-Zucker&lt;/a&gt;
war mir das Treiben einfach zu bunt.&lt;/p&gt;

&lt;p&gt;Außerdem setzt &lt;code&gt;BOOST&lt;/code&gt; großteils auf Header-only Implementierungen, aber 
eben nur großteils und nicht vollständig.
Daher müssen wir weiter noch gegen verschieden &lt;code&gt;BOOST&lt;/code&gt; Libraries linken
anstatt nur ihre Header zu inkludieren.&lt;/p&gt;

&lt;p&gt;Das finde ich ungut, den entweder nutzt man Bibliotheken und lagert alles dort
hin aus, oder man verlässt sich ausschließlich auf Header.&lt;/p&gt;

&lt;p&gt;Die Header-only Bereichen haben dann auch noch den Nachteil, dass sie einen
Großteil aller OS Bibliotheken gleich mitinkludieren.
Um also 10 Zeilen einer &lt;code&gt;BOOST&lt;/code&gt; Funktion nutzen zu können, muss mein 
Compiler zig-tausende Header durchlaufen und deren Inhalt wieder zu 99 %
verwerfen.&lt;/p&gt;

&lt;p&gt;Das waren meine primären Gründe, letztlich doch eigene Wege zu gehen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Wenn man aber von meinen Bedenken absieht hat &lt;code&gt;BOOST&lt;/code&gt; dennoch 
(neben OpenGATE natürlich) die beste Chance als 
“die beste C++ Bibliothek” aller Zeiten durchzugehen.&lt;/p&gt;

&lt;p&gt;Viele Konzepte wie &lt;code&gt;boost::optional&lt;/code&gt; oder &lt;code&gt;boost::asio&lt;/code&gt; sind die Grundlage 
weiterer 3rd Party Bibliotheken, aber auch des GATE Projektes.&lt;/p&gt;

&lt;p&gt;Seit jedoch mit C++11, C++14 und C++17 auch entsprechende neue STL Funktionen 
gibt, die zu BOOST auch ähnlich sind, plädiere ich stets dazu eben diese 
zu nutzen und nicht &lt;code&gt;BOOST&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Denn warum soll man eine ganze &lt;code&gt;BOOST&lt;/code&gt; Runtime mitschleppen wollen, wenn man
nur einen Thread erzeugen will, was dank &lt;a href=&quot;https://en.cppreference.com/w/cpp/thread/thread&quot;&gt;&lt;code&gt;std::thread&lt;/code&gt;&lt;/a&gt;
heute kostenlos aus der C++ Runtime kommt.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Der Arzt und der Zuckerbäcker</title>
   <link href="https://www.opengate.at/blog/2019/05/politics/"/>
   <published>2019-05-18T17:39:00+02:00</published>
   <updated>2019-05-18T17:39:00+02:00</updated>
   <id>https://www.opengate.at/blog/2019/05/politics</id>
   <category term="general" />
   <summary type="text">Die Philosoph Sokrates legte einst folgendes Gleichnis dar:


  Kinder fürchten den Arzt, lieben jedoch den Zuckerbäcker.
Während der erstere für das Wohl des Kindes sorgt, ängstigen sich
viele vor seiner Untersuchung. Den Zuckerbäcker mögen alle, 
weil er süße leckere Speisen herstellt … doch besonders gesund
sind diese nicht.


</summary>
   <content type="html">&lt;p&gt;Die Philosoph Sokrates legte einst folgendes Gleichnis dar:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Kinder fürchten den Arzt, lieben jedoch den Zuckerbäcker.
Während der erstere für das Wohl des Kindes sorgt, ängstigen sich
viele vor seiner Untersuchung. Den Zuckerbäcker mögen alle, 
weil er süße leckere Speisen herstellt … doch besonders gesund
sind diese nicht.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;!--more--&gt;
&lt;hr /&gt;

&lt;p&gt;Dieses Gleichnis überträgt der Ahnherr der Philosophie danach auf 
seinen Gerichtsprozess, wo ihm vorgeworfen wird, die Jugend mit seinen
Ansichten zu verderben, wofür ihm die Todesstrafe droht.&lt;/p&gt;

&lt;p&gt;Er setzt die Ankläger mit den Kindern gleich, die aus Unwissenheit 
und reiner Emotionalität jene lieben, die ihnen (wie die Zuckerbäcker)
schaden und sich vor ihren Beschützern (wie z.B. geschulten Ärzten) 
fürchten.&lt;/p&gt;

&lt;p&gt;Gebracht hatte das Beispiel Sokrates leider nichts. Er wurde zum
Tode verurteilt und starb für seine Überzeugung.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Heute, Wien, 18. Mai 2019.&lt;/p&gt;

&lt;p&gt;Ich wache in einem Land auf, in welchem der 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Heinz-Christian_Strache#Ibiza-Affäre_(2019)&quot;&gt;Vizekanzler der Regierung&lt;/a&gt;
sich selbst als übelster Schurke entlarvt hat, sein Verbrechen
(wenn auch verharmlosend) zugegeben hat, und zurückgetreten ist.&lt;/p&gt;

&lt;p&gt;Unabhängig von der Schwere dieses Verbrechens gegen unsere Demokratie
und gegen das letzte bisschen Anstand, dass ich uns Menschen gerne 
zugeordnet hätte, traue ich meinen Augen nicht, was in den sogenannten
“sozialen” Medien abgeht.&lt;/p&gt;

&lt;p&gt;Massenweise laufen die Anhänger des Zurückgetretenen ihrem nun abwesenden
“Führer” nach, konstruieren Verschwörungen in ihren Köpfen und beschimpfen
die politische Gegenseite dabei aufs Übelste, weil sie die Schuld auf
deren Seite sehen und drohen mit Vergeltung.&lt;/p&gt;

&lt;p&gt;All das passiert, obwohl es ein Eingeständnis des/der Schuldigen gibt
und ein geprüftes Video dazu in allen Medien veröffentlicht ist, 
das einen Politiker bei:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;der Zusage der Manipulation der Bauauftragsvergabe gegen Gelder zeigt&lt;/li&gt;
  &lt;li&gt;der Besprechung der Gründung von Vereinen zur versteckten 
Parteienfinanzierung ertappt&lt;/li&gt;
  &lt;li&gt;der Planung der Einflussnahme auf Medien zwecks für ihn positiver 
Berichterstattung portraitiert.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Und nach solchen Fakten haben wir immer noch eine Vielzahl von Menschen,
die diese Wahrheit nicht akzeptieren wollen und sie deshalb einfach
ignorieren?&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Ich denke dieses Beispiel ließe auch Sokrates erschaudern, denn auch er könnte
dieses Verhalten nicht mehr mit kindlicher Naivität rechtfertigen.&lt;br /&gt;
Hier läuft offenbar noch viel mehr schief.&lt;/p&gt;

&lt;p&gt;Zwar bin ich nach wie vor glücklich in Österreich in Wohlstand leben zu können,
doch die Berichte über &lt;a href=&quot;https://de.wikipedia.org/wiki/Reichsbürgerbewegung&quot;&gt;“Reichsbürger”&lt;/a&gt;, 
“Fake News”-Rufe bei allem, was einem nicht passt, und nun der Anhimmelung
eines solchen geständigen Politikers wird mir langsam etwas bange.&lt;/p&gt;

&lt;p&gt;Ich dachte, dass uns die Technik heute befähigt mehr zu verstehen als frühere
Generationen und dass wir heute objektiver urteilen könnten als unsere 
Vorväter.&lt;/p&gt;

&lt;p&gt;Doch das trifft offenbar nicht bei allen zu. Im Gegenteil,
Ignoranz nimmt an vielen Orten zu und statt beweisbarer 
wissenschaftlicher Erkenntnisse verbreiten sich Hörensagen, Vermutung
und persönlich gefärbter Glaube als wäre es die reine Wahrheit.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Und so muss ich mit Bedauern feststellen, dass nicht nur Kinder
vor dem helfenden Arzt flüchten und dem verführerischen
Zuckerbäcker nachdackeln, sondern dass auch viele ausgewachsene
Mitmenschen lieber den ausgewiesenen Täuschern ihr Ohr leihen
und sich von Faktenberichten irritiert fühlen.&lt;/p&gt;

&lt;p&gt;Wir machen uns über dokumentierte offensichtliche Fehler unserer 
Ahnen lustig, behaupten uns könne kein Irrtum unterlaufen, und
dann laufen wir blind einem jeden trillernden 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Rattenfänger_von_Hameln&quot;&gt;Rattenfänger&lt;/a&gt; 
hinterher?&lt;/p&gt;

&lt;p&gt;Nö … das sind so Tage, wo ich mir denke:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Wärst du doch einfach im Bett geblieben …&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>Geschätzter Busfahrer</title>
   <link href="https://www.opengate.at/blog/2019/05/bus-driver/"/>
   <published>2019-05-17T20:54:00+02:00</published>
   <updated>2019-05-17T20:54:00+02:00</updated>
   <id>https://www.opengate.at/blog/2019/05/bus-driver</id>
   <category term="general" />
   <summary type="text">Wieder mal ein etwas “menschlicheres” Thema:

Heute gegen Abend hatte der Bus 7A der 
Wiener Linien in einer Station
nahe der Triester Straße in Wien eine sogenannte kurze “Betriebsstörung”.
</summary>
   <content type="html">&lt;p&gt;Wieder mal ein etwas “menschlicheres” Thema:&lt;/p&gt;

&lt;p&gt;Heute gegen Abend hatte der Bus 7A der 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Wiener_Linien&quot;&gt;Wiener Linien&lt;/a&gt; in einer Station
nahe der Triester Straße in Wien eine sogenannte kurze “Betriebsstörung”.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Ein Mann lag regungslos quer über die Sitzbänke in der Bushaltestelle und
“unser” Busfahrer stieg unmittelbar aus und versuchte den Mann anzusprechen.&lt;/p&gt;

&lt;p&gt;Dieser reagierte nicht und schaffte es nur kurz die Augen zu öffnen um dann
wieder zusammenzusacken.&lt;/p&gt;

&lt;p&gt;Sofort eilte der Fahrer zum Funkgerät seines Busses und teilte der Zentrale
das Problem mit, und sprach ebenso an, dass er verpflichtet sei bis zum
Eintreffen der ärztlichen Hilfe zu warten.&lt;/p&gt;

&lt;p&gt;Am Ende blieben Fahrgäste in der Haltestelle um bis zum Eintreffen eines
Krankenwagens zu warten, damit der Bus weiterfahren konnte.&lt;/p&gt;

&lt;p&gt;So weit, so gut.&lt;/p&gt;

&lt;p&gt;Überhaupt nicht nachvollziehen konnte ich bei dem Szenario das Verhalten
einiger (zum Glück weniger) anderen Fahrgäste, die wie beleidigt mit zorniger 
Stirn und gerümpfter Nase den Bus verlassen wollten, weil dieser nicht sofort
weiterfuhr.&lt;br /&gt;
Und die Situation nahm beinahe eine dramatische Wendung als eine 
aggressive junge Frau begann den Busfahrer anzuschreien, was 
das hier “für eine Scheiße sei”, wegen so etwas die Fahrt zu unterbrechen, 
wo das nächste Krankenhaus ohnehin nicht weit entfernt war.&lt;/p&gt;

&lt;p&gt;Doch der Busfahrer hielt sich zurück, teilte die Situation den Fahrgästen mit
und als sichergestellt werden konnte, dass jemand auf den halb bewusstlosen
Mann aufpasste, konnte die Fahrt problemlos wieder aufgenommen werden.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Ich denke mir heute, wie glücklich ich mich doch fühlen kann in einer Stadt
zu wohnen, wo das Achten auf die Mitmenschen (zumindest großteils) noch aktiv
gelebt wird.&lt;/p&gt;

&lt;p&gt;Vielleicht war das einer von den Fällen, wo jemand viel zu viel über den Durst
getrunken hat. Doch vielleicht handelte es sich um eine Krankheit, z.B. 
Über- oder Unterzucker und vielleicht hat “unser” Busfahrer einem unbekannten 
Mann mit dem Auslösen der Rettungskette heute das Leben gerettet.&lt;/p&gt;

&lt;p&gt;Den &lt;a href=&quot;https://de.wikipedia.org/wiki/Wiener_Linien&quot;&gt;Wiener Linien&lt;/a&gt;, Ihren 
Mitarbeitern und vor allem “meinem” Busfahrer möchte ich hiermit ein ganz 
besonderes Dankeschön ausrichten und sein Verhalten ausdrücklich loben.&lt;br /&gt;
Es tut gut zu wissen, dass “jemand” auf mich aufpasst, wenn ich selbst oder
mein nächstes Umfeld es nicht tut.&lt;/p&gt;

&lt;p&gt;Und der vorlauten jungen Dame möchte ich anraten ihr Mundwerk etwas zu zügeln … 
denn sie könnte sich z.B. beim Essen ungewollt verschlucken.&lt;br /&gt;
Tut sie das in der Nähe einer Wiener Bushaltestelle ist das aber nicht so
schlimm, denn auch ihr würde der nächste Busfahrer “wieder auf die Beine” helfen.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Apropos Busfahrer: Hier ein lustiges Video mit 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Sebastian_Kr%C3%A4mer&quot;&gt;Sebastian Krämer&lt;/a&gt; aus 
meiner “guten alten” Linksammlung:&lt;/p&gt;

&lt;iframe width=&quot;640&quot; height=&quot;360&quot; src=&quot;/blog/redirect.html?https%3A%2F%2Fwww.youtube-nocookie.com%2Fembed%2FbIS_WI1NLdA&quot; frameborder=&quot;1&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
</content>
 </entry>
 
 <entry>
   <title>Viele Buttons an einem analogen Pin</title>
   <link href="https://www.opengate.at/blog/2019/05/analog-buttons-one-pin/"/>
   <published>2019-05-12T14:06:00+02:00</published>
   <updated>2019-05-12T14:06:00+02:00</updated>
   <id>https://www.opengate.at/blog/2019/05/analog-buttons-one-pin</id>
   <category term="hardware" />
   <summary type="text">Nachdem die ATmega328 
MCUs 13 digitale Pins zur 
Verfügung stellen, könnte man 13 Tasten damit auslesen. Natürlich sind dann 
eben alle 13 digitalen Pins belegt.

Beim ATtiny25/45/85, 
der in Summe nur 5 Pins für Anwendungen bietet (3 digitale und 2 analoge) 
wäre das natürlich ein großes Problem, denn wenn 2 Tasten 2 Pins belegen, 
kann man den restlichen 3 Pins nur mehr wenig anfangen … und jede weitere 
Taste verschlimmert die Angelegenheit.

Die Lösung sind analoge Buttons.
</summary>
   <content type="html">&lt;p&gt;Nachdem die &lt;a href=&quot;https://en.wikipedia.org/wiki/ATmega328&quot;&gt;ATmega328&lt;/a&gt; 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Mikrocontroller&quot;&gt;MCUs&lt;/a&gt; 13 digitale Pins zur 
Verfügung stellen, könnte man 13 Tasten damit auslesen. Natürlich sind dann 
eben alle 13 digitalen Pins belegt.&lt;/p&gt;

&lt;p&gt;Beim &lt;a href=&quot;http://www.microchip.com/wwwproducts/en/ATtiny85&quot;&gt;ATtiny25/45/85&lt;/a&gt;, 
der in Summe nur 5 Pins für Anwendungen bietet (3 digitale und 2 analoge) 
wäre das natürlich ein großes Problem, denn wenn 2 Tasten 2 Pins belegen, 
kann man den restlichen 3 Pins nur mehr wenig anfangen … und jede weitere 
Taste verschlimmert die Angelegenheit.&lt;/p&gt;

&lt;p&gt;Die Lösung sind analoge Buttons.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Vor Jahren erzählte mir ein etwas älterer Herr vom 
“Zeitalter der &lt;a href=&quot;https://de.wikipedia.org/wiki/Analogrechner&quot;&gt;Analog-Computer&lt;/a&gt;”, 
die Rechenaufgaben durch elektrische bzw. physikalische Eigenschaften lösen 
konnten. So richtig verstanden hatte ich das Konzept eigentlich nicht.
Doch es erschien mir logisch, dass sich Spannungen und Stromstärken
durch bestimmte Verschaltungen addieren oder aufteilen lassen.&lt;/p&gt;

&lt;p&gt;Erst in den letzten Monaten, wo ich das Pin-Mangel-Problem vorfand, führte
mich eine Suche zu “analogen Button-Controllern” und den alt bekannt 
Rechenregeln, wonach bei in Serie geschalteten Verbrauchern (Widerständen)
die Spannung proportional abfällt.&lt;/p&gt;

&lt;h3 id=&quot;analoge-widerstand-messung&quot;&gt;Analoge Widerstand-Messung&lt;/h3&gt;

&lt;p&gt;Während digitale Pins nur 2 Zustände unterscheiden, können analoge Pins
als Analog/Digital Wandler genutzt werden und die am Pin anliegende
Spannung messen. Gemessen wird immer gegen die Referenzspannung, die
man auf manchen Controllern auf einen eigenen Pin legen kann (&lt;code&gt;AREF&lt;/code&gt;),
in der Regel aber mit der Betriebsspannung gleichgesetzt ist.&lt;/p&gt;

&lt;p&gt;ATmega/ATtiny MCUs nutzen 10 Bits für die Messung und können so 
Spannungen von 0 Volt bis Betriebsspannung (bzw. AREF) auf die Werte 
0 bis 1023 abbilden.&lt;/p&gt;

&lt;p&gt;Und dann gibt es ja die bekannte Spannungsteiler-Schaltung, wo 
der Strom durch 2 Widerstände fließt und zwischen dem ersten
und zweiten die Spannung entsprechend abgefallen (geteilt) ist.&lt;/p&gt;

&lt;p&gt;Legen wir also eine Leitung zu einem Widerstand und von dort
eine zurück zum analogen Pin, während wir parallel einen Weg zu einem 
zweiten Widerstand und dann zum Ground verlegen:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;+5V&lt;/code&gt; → &lt;code&gt;R1&lt;/code&gt; → &lt;code&gt;R2&lt;/code&gt; → &lt;code&gt;Ground&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;+5V&lt;/code&gt; → &lt;code&gt;R1&lt;/code&gt; → &lt;code&gt;A-Pin&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Der analoge Pin (A-Pin) liefert dann den Wert&lt;br /&gt;
&lt;code&gt;1024 - (R1 / (R1  + R2)) * 1024&lt;/code&gt;&lt;br /&gt;
oder &lt;code&gt;(R2 / (R1 + R2)) * 1024&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Bei zwei 10 Kilo-&lt;a href=&quot;https://de.wikipedia.org/wiki/Ohm&quot;&gt;Ohm&lt;/a&gt; 
Widerständen, wäre das 512, wenn man leichte Schwankungen berücksichtigt oder
leichte Ungleichheiten bei den Widerständen, kann es zu Schwankungen zwischen 
509 und 515 kommen.&lt;/p&gt;

&lt;p&gt;Nehmen wir für den zweiten Widerstand einen fixen Wert, sagen wir 100 KOhm, 
dann können wir mehrere unterschiedliche Widerstände mit Tastern parallel 
zum analogen Pin schalten. Wird ein Taster gedrückt, so misst der Pin eine 
Spannung die für den entsprechenden Widerstand typisch ist.&lt;/p&gt;

&lt;p&gt;Ich hatte einige Widerstände in der Schublade liegen, die ich für einen 
Test so verbauen konnte:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Pulldown: 174 KOhm&lt;/li&gt;
  &lt;li&gt;Button 1: 1.5 KOhm (Messung: 1015)&lt;/li&gt;
  &lt;li&gt;Button 2: 3.9 KOhm (Messung: 1001)&lt;/li&gt;
  &lt;li&gt;Button 3: 7.5 KOhm (Messung: 982)&lt;/li&gt;
  &lt;li&gt;Button 4:  15 KOhm (Messung: 943)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Und schon kann man ein Fadenkreuz (Hinauf, Hinunter, Links, Rechts) 
mit nur einem einzigen analogen Pin bauen.&lt;/p&gt;

&lt;p&gt;Natürlich kann man das so fortsetzen und noch viele weitere Buttons so 
verbauen, doch eine vollständige Tastatur wird das nicht werden, denn:&lt;/p&gt;

&lt;h3 id=&quot;nachteil-man-darf-immer-nur-einen-taster-drücken&quot;&gt;Nachteil: Man darf immer nur einen Taster drücken.&lt;/h3&gt;

&lt;p&gt;Wenn man mehrere Tasten drückt, werden die Widerstände parallel
geschaltet und ergeben einen geringeren Wert nach der Formel:
&lt;code&gt;1/R = 1/R1 + 1/R2 + 1/R3 + ...&lt;/code&gt;.&lt;br /&gt;
Bei zwei Tasten ergibt das verkürzt: &lt;code&gt;R = (R1 * R2) / (R1 + R2)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Da müsste man also für jede Konstellation eigene Soll-Messwerte erfassen
und Kollisionen mit der Wahl von “passenden” Widerständen verhindern.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Wie auch immer, für den kleinen &lt;code&gt;ATtiny&lt;/code&gt; ist diese Methode perfekt, und so
kann man z.B. einen &lt;a href=&quot;https://de.wikipedia.org/wiki/ESP8266&quot;&gt;ESP8266-01&lt;/a&gt;
der keine analogen Pins hat durch einen ATtiny ergänzen, der die Daten ließt 
und per serieller Verbindung zum ESP schickt. … und fertig ist unsere 
kleine WLAN-Fernbedienung (so zumindest die Theorie.)&lt;/p&gt;

&lt;p&gt;Es gibt aber auch fertige Bauteile, die nach diesem Prinzip arbeiten.
Unter der Bezeichnung &lt;code&gt;K845037&lt;/code&gt; ist ein kleiner analoger Controller
zu finden, mit dem man eine einfache Joypad-Funktion erhalten kann.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/analog-buttons-k845037.jpg&quot; alt=&quot;K845037&quot; /&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>SCRUM Teil 2</title>
   <link href="https://www.opengate.at/blog/2019/05/scrum-2/"/>
   <published>2019-05-11T12:00:00+02:00</published>
   <updated>2019-05-11T12:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2019/05/scrum-2</id>
   <category term="devel" /><category term="general" />
   <summary type="text">Vor ein paar Monaten habe ich mich ja schon einmal über 
SCRUM
(nicht gerade positiv) ausgelassen.

Das geschah natürlich auch aus der Frustration heraus, dass mir
die Erinnerung an ein leider gescheitertes Projekt noch frisch
in Kopf dampfte.

Inzwischen habe ich aber die Ehre einem anderem 
SCRUM Team anzugehören …
</summary>
   <content type="html">&lt;p&gt;Vor ein paar Monaten habe ich mich ja schon einmal über 
&lt;a href=&quot;/blog/2019/01/agile-dev/&quot;&gt;SCRUM&lt;/a&gt;
(nicht gerade positiv) ausgelassen.&lt;/p&gt;

&lt;p&gt;Das geschah natürlich auch aus der Frustration heraus, dass mir
die Erinnerung an ein leider gescheitertes Projekt noch frisch
in Kopf dampfte.&lt;/p&gt;

&lt;p&gt;Inzwischen habe ich aber die Ehre einem anderem 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Scrum&quot;&gt;SCRUM&lt;/a&gt; Team anzugehören …
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Kurz zusammengefasst:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Naja, wenn man es besser angeht, ist SCRUM nicht soooo
schlecht, aber große Sprünge macht man damit auch nicht.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Natürlich darf man die individuellen Eigenschaften EINES
Projektes nicht gleich auf ein gesamtes Arbeitsmodell 
verallgemeinern um es zu beurteilen.&lt;/p&gt;

&lt;p&gt;Und so lautet meine konkrete Einstellung:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Letztes Pseudo-SCRUM Projekt: Totalversagen auf allen Ebenen&lt;/li&gt;
  &lt;li&gt;Aktuelles SCRUM Projekt: Hoffnungsvoll neutral&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Doch wenn man wieder in die Vogelperspektive wechselt,
bleibt mein Basiseindruck leider bestehen:&lt;/p&gt;

&lt;p&gt;SCRUM wird leider grundsätzlich nur vom Management dazu eingesetzt,
Zeitabschätzungen für Finanzierungspläne zu machen.
Und dabei bleibt leider stets die Qualität der Softwareentwicklung weit 
zurück.&lt;/p&gt;

&lt;p&gt;Und so stellt sich immer wieder das leidige Problem ein, dass nur um 
schnell einen Sprint abzuschließen “irgendetwas” gemacht wird.
Danach wird dieses “Irgendetwas” lange in der Retrospektive diskutiert,
und für “ganz toll” befunden, um dann im Folgesprint zahlreich eingehende
Defekte und andere Probleme entgegenzunehmen, die natürlich erst im 
übernächsten Sprint erst angegangen werden können.&lt;/p&gt;

&lt;p&gt;Jetzt kann man natürlich positiv argumentieren, dass alle diese Schritte 
formal dokumentiert werden und sich im Laufe der Zeit eben auch ein 
entsprechender Fortschritt einstellt.&lt;/p&gt;

&lt;p&gt;Doch diese zeitlichen Verzögerungen haben auch den unangenehmen Nebeneffekt,
dass Entwickler sich in inzwischen “alte” Themen wieder neu einarbeiten müssen.
Und das kostet Zeit.&lt;/p&gt;

&lt;p&gt;Die Unflexibilität von starren Sprintabläufen, die nicht vom Team, sondern vom
SCRUM Owner vorgegeben werden, führt damit in Summe zu einem größeren 
Zeitablauf um “das Produkt” marktreif zu bekommen, als wenn die Arbeitsschritte
in logisch zusammenhängenden Arbeitspaketen abgearbeitet werden.&lt;/p&gt;

&lt;p&gt;Auch demokratische Beschlüsse sind hier nicht immer gerade ein Optimum, denn
wenn mit Implementierungsdetails nicht-vertraute Kollegen per Abstimmung über
die Priorität von Themen letztendlich entscheiden, geht der Schuss auch mal
nach hinten los und man beobachtet dann zwei Wochen später das interessante
Gespräch, das mit&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ich hab’s euch schon gleich gesagt, dass … so nicht funktionieren wird.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;beginnt. (Und die Aussage kommt dann noch nicht mal von mir …)&lt;/p&gt;

&lt;p&gt;Ebenso interessant ist dann, dass wenn ein Entwickler eine 
&lt;a href=&quot;https://de.wikipedia.org/wiki/User_Story&quot;&gt;User Story&lt;/a&gt; oder
einen Task einbringt und viel Zeit investiert wird, um:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;die Story zu beschreiben&lt;/li&gt;
  &lt;li&gt;die Inhalte zu diskutieren&lt;/li&gt;
  &lt;li&gt;die Aufwände abzuschätzen&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Dann wird (2 Wochen später) jemand anderes mit der Implementierung beauftragt,
der sich darin einarbeitet und 2 Wochen herumdoktort.&lt;/p&gt;

&lt;p&gt;Am Sprint-Ende meldet dann der Story Urheber:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Nein, so war das nicht gemeint, du hättest nur hier X Zeilen anfügen sollen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;W.T.F. ?&lt;/em&gt; denke ich mir dann … denn eigentlich hätte der Urheber das auch
selbst in einer Stunde erledigen können, doch so wurden 3 Wochen vergeudet.&lt;/p&gt;

&lt;p&gt;Am meisten schockiert mich aber die Erfahrung (nun schon aus mehreren Firmen), 
dass solche “Missverständnisse” niemanden stören und als “normal” angesehen 
werden. Schließlich kann man stets lang und breit darüber reden, dass es ja 
eine Erkenntnis und einen Fortschritt gibt … selbst wenn es sich nur um 
wenige Mikrometer handelt.&lt;br /&gt;
Und so wiederholt sich das Spiel jedes Monat.&lt;/p&gt;

&lt;p&gt;Da lobe ich mir die guten alten Tage, wo sich in Startup-Manier ein paar
Leute zusammensetzten, jeder sich seinen Fachbereich suchte und einfach 
unbeirrt drauf losschrieb und wie durch ein Wunder (oder eben durch
fachliche Kompetenz und gute Aufteilung) am Ende ein gutes Produkt daraus
wird.&lt;/p&gt;

&lt;p&gt;Doch wenn ich beginne die Sache von der wirtschaftlichen Seite zu sehen, dann 
stelle ich etwas schadenfroh fest:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Zum Glück werde ich ja nach Arbeitszeit bezahlt.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;hr /&gt;

&lt;p&gt;Doch ich kann auch Positives erkennen, denn mit dem Versuch 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Paarprogrammierung&quot;&gt;Pair-Programming&lt;/a&gt;
in den Prozess mit aufzunehmen ergibt sich nach und nach der positive 
Seiteneffekt, dass Wissen zwischen den Entwicklern verteilt wird.
&lt;a href=&quot;https://de.wikipedia.org/wiki/Extreme_Programming&quot;&gt;Extreme Programming&lt;/a&gt;
lässt grüßen.&lt;/p&gt;

&lt;p&gt;Ist dieses Konzept erst mal Teil eines SCRUM Sprints, so “muss” dieses auch
umgesetzt werden und darf mit Zeitaufwand bedacht werden.
Hier arbeitet dann dieses System endlich auch mal “für” die Entwicklung
und seine Mechanismen stellen den Fortschritt in der Zusammenarbeit sicher.&lt;/p&gt;

&lt;p&gt;Das ist zwar nicht ganz so “romantisch” wie in den alten Hacker-Tagen, wo
sich das von selbst so organisiert hat, aber es ist immerhin ein guter
Anfang.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Es hilft aber auch das eine oder andere Gespräch mit Kollegen zu suchen und 
die Frage zu stellen:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Sag mal, wie war das denn früher, also vor SCRUM.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Und die ebenso interessante Antwort war:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Naja, mal so und mal so, aber in Summe schlimmer.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Der vor mir stets präferierte Ansatz, dass sich Entwickler in ihrer 
Fachrichtung selbst organisieren und nur dann gemeinsame Meetings 
abhalten, wenn sie es für nötig erachten, kann natürlich auch dazu 
führen, dass sich eine Entwicklungsabteilung selbst ausbremst,
oder gegenteilige Arbeitspakete ohne das Wissen der anderen umgesetzt werden.&lt;/p&gt;

&lt;p&gt;Ich bleibe jedoch bei meiner Meinung, dass es in allen Konstellationen,
egal ob mit SCRUM oder ohne immer um die Kommunikation in einem Team geht.&lt;/p&gt;

&lt;p&gt;Oder anders gesagt: Wenn zwei mit einander nicht reden wollen/können, hilft
auch die beste Projektverwaltung oben drüber nichts, denn ob man jetzt
an einander vorbei arbeitet und “nichts” sagt, oder an einander vorbei 
arbeitet und es beim Standup oder Review schön redet kommt am Ende zum 
gleichen Ergebnis.&lt;/p&gt;

&lt;p&gt;Deshalb lobe ich mir vor allem jene Akteure, Owner und Master, die proaktiv
Problemstellungen erkennen und dort schnell einschreiten, dann aber auf 
der anderen Seite die reale Arbeit nicht durch Formalismen und 
Meeting-Bürokratie künstlich erschweren.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>22 Pikofarad vs. 16 Megahertz</title>
   <link href="https://www.opengate.at/blog/2019/05/22-pf-oscillator/"/>
   <published>2019-05-05T12:00:00+02:00</published>
   <updated>2019-05-05T12:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2019/05/22-pf-oscillator</id>
   <category term="hardware" />
   <summary type="text">Ich kam mir vorhin gerade ein bisschen verarscht vor und weiß aber nicht so 
recht, ob die Schuld bei mir oder jemand anderem liegt.

Und alles begann bei der Lehrbuch-Dokumentation vom 
ATmega328, wo doch
klar und deutlich steht, dass man einen 16 MHz 
Oszillator mit 
2 Kondensatoren 
mit je 22 Pikofarad 
gegen Ground verbinden soll …
</summary>
   <content type="html">&lt;p&gt;Ich kam mir vorhin gerade ein bisschen verarscht vor und weiß aber nicht so 
recht, ob die Schuld bei mir oder jemand anderem liegt.&lt;/p&gt;

&lt;p&gt;Und alles begann bei der Lehrbuch-Dokumentation vom 
&lt;a href=&quot;https://en.wikipedia.org/wiki/ATmega328&quot;&gt;ATmega328&lt;/a&gt;, wo doch
klar und deutlich steht, dass man einen 16 MHz 
&lt;a href=&quot;https://en.wikipedia.org/wiki/Electronic_oscillator&quot;&gt;Oszillator&lt;/a&gt; mit 
2 &lt;a href=&quot;https://de.wikipedia.org/wiki/Kondensator_(Elektrotechnik)&quot;&gt;Kondensatoren&lt;/a&gt; 
mit je 22 &lt;a href=&quot;https://de.wikipedia.org/wiki/Farad&quot;&gt;Pikofarad&lt;/a&gt; 
gegen Ground verbinden soll …
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Auch YouTuber behaupten das und zeigen 
&lt;a href=&quot;http://www.youtube.com/watch?v=muP1dp73Mdg&quot;&gt;Videos&lt;/a&gt;, wo es bei ihnen genau 
so funktioniert. Also dachte ich mir schon vor Wochen:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Das bau’ ich mir auch schnell nach.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Und was passierte bei mir dann: Gar nichts. 
Der Chip startete einfach nicht mehr.&lt;br /&gt;
Noch ärgerlicher war die Tatsache, dass ich blind auf diesen Aufbau 
vertraut hatte und auch gleich so auf einer Platine verlötet hatte.&lt;/p&gt;

&lt;p&gt;Bei der Fehlersuche dachte ich nach unzähligen Nachmessungen, ich hätte
ein Bauteil beschädigt, obwohl ich nicht herausfinden konnte, welches 
es war.&lt;/p&gt;

&lt;p&gt;Also wanderte das gescheiterte Projekt in die Schublade.&lt;/p&gt;

&lt;p&gt;Als ich heute mein Steckbrett bemühte und erneut einen ATmega328 mit einem 
externen Oszillator zu betreiben, passierte wieder das gleiche:&lt;br /&gt;
nämlich &lt;em&gt;NICHTS&lt;/em&gt; - der Chip startete einfach nicht.&lt;/p&gt;

&lt;p&gt;Hier konnte ich schnell alle Bauteile auswechseln, und siehe da, 
es geschah wieder nichts.&lt;/p&gt;

&lt;p&gt;Wenn ich jedoch den Chip in ein &lt;a href=&quot;https://en.wikipedia.org/wiki/Arduino_Uno&quot;&gt;UNO Board&lt;/a&gt;
einbaute, funktionierte dieser einwandfrei und das darauf laufende 
Blink-Progrämmchen ließ die &lt;a href=&quot;https://de.wikipedia.org/wiki/Leuchtdiode&quot;&gt;LED&lt;/a&gt; 
an Pin 13 brav zirpen.&lt;/p&gt;

&lt;p&gt;Jetzt wurde ich skeptisch und begann mal spaßhalber am Steckbrett beide 
22-pF-Kondensatoren zu entfernen, wieder hinzuzufügen und dann das ganze 
nochmals mit und ohne Oszillator.&lt;/p&gt;

&lt;p&gt;Und kurzfristig startete der Chip, fror aber nach wenigen Sekunden wieder
ein.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Hmm … nochmals auf das Bild im Beispiel geblickt …&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Dort war der Oszillator ganz knapp beim Chip verbaut. Ich hatte allerdings
sowohl am Breadboard als auch auf der Platine den Oszillator ans andere Ende 
der Struktur verfrachtet und mit Litzen eine Leitung dort hin verlegt.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;OK … kann es vielleicht sein, dass das Signal des Taktgebers vielleicht
gestört wird?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;dachte ich mir, und versetzte am Breadboard sowohl Oszillator als auch die
Kondensatoren zum Chip hin.&lt;/p&gt;

&lt;p&gt;Und siehe dar … alles funktionierte so wie eigentlich erwartet.&lt;/p&gt;

&lt;h3 id=&quot;fazit-wo-gehobelt-wird-fallen-späne&quot;&gt;Fazit: Wo gehobelt wird, fallen Späne&lt;/h3&gt;

&lt;p&gt;Schon etwas ärgerlich, dass man Stunden nach Fehlern in Bauteilen sucht,
bis man merkt, dass die Verkabelung das Problem ist.&lt;/p&gt;

&lt;p&gt;Für meine Platine habe ich mich nun allerdings entschieden, dass der 
ATmega328 nun mit seinem internen 8 MHz Quarz betrieben wird und gar
keinen Oszillator brauchen soll. Grund dafür war, dass ich den 
Chipsockel am Rand eingebaut hatte und den Oszillator nur mit Litzen 
“auf Distanz” verbinden konnte. Also weg damit.&lt;/p&gt;

&lt;p&gt;Mein Glaube an Dokus und Tutorials ist also wiederhergestellt und
nebenbei weiß ich nun, dass Taktfrequenzen offenbar sehr leicht
“zu stören” sind, wenn man sie über längere Leitungen schickt.
(Eigentlich eh logisch, wenn man drüber nachdenkt.)&lt;/p&gt;

&lt;h3 id=&quot;nachtrag-kondensator-messung&quot;&gt;Nachtrag: Kondensator-Messung&lt;/h3&gt;

&lt;p&gt;Ich hatte recht lange meine 22pF Kondensatoren in Verdacht, denn mein liebes
Messgerät, meldete diese bei 3 von 4 Messungen als “unbekanntes Bauteil”.&lt;br /&gt;
Und das wiederholte sich bei allen 10 Stück der Teile, die ich auf Lager
hatte. Der Grund dafür war aber eher, dass das Messgerät diese kleinen 
Kapazitäten einfach nicht mehr richtig messen konnte.&lt;/p&gt;

&lt;p&gt;Im Nachhinein stellte ich fest, dass bei größeren Kapazitäten (30pF - 40pF)
immer mehr Messungen positiv abliefen, und so ab 70pF immer alles gut ging.&lt;/p&gt;

&lt;p&gt;Schlimmer wurde es bei kleinerem Fassungsvermögen, obwohl das Gerät bis
zu 10 pF hätte messen können sollen.&lt;/p&gt;

&lt;p&gt;Tja, man lernt eben jeden Tag was dazu.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/arduino-breadboard.jpg&quot; alt=&quot;Arduino Breadboard&quot; /&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Variant Typen und All-in-one Variablen</title>
   <link href="https://www.opengate.at/blog/2019/05/variant-types/"/>
   <published>2019-05-04T12:00:00+02:00</published>
   <updated>2019-05-04T12:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2019/05/variant-types</id>
   <category term="devel" />
   <summary type="text">Der größte Vorteil von statisch typisierten Sprachen wie 
C oder 
C++ kann auch ein Nachteil werden:

Was ist, wenn der Typ einer Variablen erst zur Laufzeit z.B. durch eine 
Benutzereingabe oder eine Fremdbibliothek festgelegt werden kann?
Oder ein anderes Beispiel: Wie kann man eine Variable bauen, die aus 
unterschiedlichen Datenbankabfragen unterschiedliche Inhalte von Boolean bis 
String beinhalten können soll?

Das alles schaffen “variierende” Typen.
</summary>
   <content type="html">&lt;p&gt;Der größte Vorteil von statisch typisierten Sprachen wie 
&lt;a href=&quot;https://de.wikipedia.org/wiki/C_(Programmiersprache)&quot;&gt;C&lt;/a&gt; oder 
&lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B&quot;&gt;C++&lt;/a&gt; kann auch ein Nachteil werden:&lt;/p&gt;

&lt;p&gt;Was ist, wenn der Typ einer Variablen erst zur Laufzeit z.B. durch eine 
Benutzereingabe oder eine Fremdbibliothek festgelegt werden kann?&lt;br /&gt;
Oder ein anderes Beispiel: Wie kann man eine Variable bauen, die aus 
unterschiedlichen Datenbankabfragen unterschiedliche Inhalte von Boolean bis 
String beinhalten können soll?&lt;/p&gt;

&lt;p&gt;Das alles schaffen “variierende” Typen.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Wenn man sich an Microsoft’s &lt;a href=&quot;https://de.wikipedia.org/wiki/Component_Object_Model&quot;&gt;COM&lt;/a&gt;
orientiert, ist alles ganz einfach:&lt;/p&gt;

&lt;p&gt;Man baut eine &lt;code&gt;struct&lt;/code&gt; und nennt sie &lt;code&gt;VARIANT&lt;/code&gt;, gibt ihr einen Integer
Member namens &lt;code&gt;vt&lt;/code&gt; (für &lt;code&gt;VARTYPE&lt;/code&gt;) und dann einen &lt;code&gt;union&lt;/code&gt; Member, der
alle primitiven Datentypen und auch einige Pointer zu komplexeren Typen
beinhaltet.&lt;/p&gt;

&lt;p&gt;Nun orientiert man sich am Wert von &lt;code&gt;vt&lt;/code&gt;, denn dieser legt fest, welcher
&lt;code&gt;union&lt;/code&gt; Member gerade gültig ist.&lt;/p&gt;

&lt;p&gt;So funktioniert das auch bei anderen Implementierungen: 
Es gibt einen Typen-Identifizierer (Typen-ID) und dann einen mehr oder weniger variablen
Speicherbereich, wo der tatsächliche Typ abgebildet wird.&lt;/p&gt;

&lt;p&gt;Stellt sich bloß noch die Frage, wo die Typen-ID herkommt.&lt;/p&gt;

&lt;p&gt;Nun, COM ist deshalb limitiert, weil es die primitiven Typen 
(bool, int, string) eine endliche Menge sind und alle Objekte mit dem Interface
&lt;code&gt;IUnknown&lt;/code&gt; beginnen müssen. Daher reicht für alle Objekte ein Pointer of
&lt;code&gt;IUnknown&lt;/code&gt; und der Nutzer darf sich per &lt;code&gt;QueryInterface&lt;/code&gt; sein bevorzugtes
Interface vom Objekt abholen.&lt;/p&gt;

&lt;p&gt;In C++ lässt sich dank Templates so ziemlich alles in eine “generische” 
Struktur pressen und die Sprache liefert die ID gleich mit:&lt;/p&gt;
&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;my_type_t my_instance;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;std::type_info my_type_id = &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;typeid&lt;/span&gt;(my_instance);
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Für jeden (und zwar wirklich jeden) möglichen C++ Typ liefert der
&lt;a href=&quot;http://en.cppreference.com/w/cpp/language/typeid&quot;&gt;&lt;code&gt;typeid&lt;/code&gt; Operator&lt;/a&gt; 
eine Instanz von &lt;code&gt;std::type_info&lt;/code&gt; zurück, der mit anderen verglichen 
werden kann.&lt;/p&gt;

&lt;p&gt;Ein einfacher “variierender” Typ ist also schnell selbst gebaut:&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;Variant&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;private&lt;/span&gt;:
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;        std::type_info        info;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;        &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;*                        instance;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;        ...
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;        
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;public&lt;/span&gt;:
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;        &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;template&lt;/span&gt;&amp;lt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;T&lt;/span&gt;&amp;gt; Variant(T &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt;&amp;amp; source)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;        : info(&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;typeid&lt;/span&gt;(source)), instance(&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;new&lt;/span&gt; T(source))
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;        {                
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;        }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;        
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;        &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;template&lt;/span&gt;&amp;lt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;T&lt;/span&gt;&amp;gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;bool&lt;/span&gt; get(T&amp;amp; copy) &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;        {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;                &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt;(&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;typeid&lt;/span&gt;(copy) == &lt;span style=&quot;color:#950&quot;&gt;this&lt;/span&gt;-&amp;gt;info)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;                {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;                        copy = *&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;static_cast&lt;/span&gt;&amp;lt;T*&amp;gt;(&lt;span style=&quot;color:#950&quot;&gt;this&lt;/span&gt;-&amp;gt;instance);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;                        &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color:#069&quot;&gt;true&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;                }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n21&quot; name=&quot;n21&quot;&gt;21&lt;/a&gt;&lt;/span&gt;                &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;else&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n22&quot; name=&quot;n22&quot;&gt;22&lt;/a&gt;&lt;/span&gt;                {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n23&quot; name=&quot;n23&quot;&gt;23&lt;/a&gt;&lt;/span&gt;                        &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color:#069&quot;&gt;false&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n24&quot; name=&quot;n24&quot;&gt;24&lt;/a&gt;&lt;/span&gt;                }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n25&quot; name=&quot;n25&quot;&gt;25&lt;/a&gt;&lt;/span&gt;        }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n26&quot; name=&quot;n26&quot;&gt;26&lt;/a&gt;&lt;/span&gt;        ...
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n27&quot; name=&quot;n27&quot;&gt;27&lt;/a&gt;&lt;/span&gt;};
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Dem Codebeispiel fehlen natürlich noch Vorkehrungen auch das Kopieren und das
Löschen der Instanz vorzunehmen, doch auch das kann man mit Templates auf
Funktionen abbilden, deren Pointer dann ebenfalls in den Variant wandern und 
bei Bedarf aufgerufen werden.&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit:&lt;/h3&gt;

&lt;p&gt;Was ist also besser?&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;Für jeden unterstützen Typen eine ID in Form einer Zahl generieren?&lt;/li&gt;
  &lt;li&gt;Oder einfach &lt;code&gt;typeid&lt;/code&gt; benutzen?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Die Antwort lautet (wie leider so oft): Es hängt davon ab…&lt;/p&gt;

&lt;p&gt;Für reine C++ Projekt ist die zweite Variante ein großer Vorteil.
Auch &lt;a href=&quot;http://www.boost.org/doc/libs/1_62_0/doc/html/variant.html&quot;&gt;&lt;code&gt;boost::variant&lt;/code&gt;&lt;/a&gt; 
baut darauf auf.&lt;/p&gt;

&lt;p&gt;Doch wenn es um den Austausch von Daten mit anderen Bibliotheken geht, wird 
automatisch der erste Ansatz zum besseren. Denn mit einer C-Struktur mit einem
Integer als erstem Member kann wirklich jede andere Sprache umgehen und 
dadurch, dass der “Variant-Type” von Hand spezifiziert wird, liegt es auch
in der Hand des Entwicklers, wie weit die Kompatibilität reichen soll.&lt;/p&gt;

&lt;p&gt;Im Fall von C++ &lt;code&gt;typeid&lt;/code&gt; sind Compiler- und Prozessgrenzen eingezogen.
Es ist nicht garantiert, dass ein typeid aus einer DLL mit dem typeid 
einer EXE kompatibel ist und je nach Version und Header-Stand kann es hier
zu Problemen und Mehrdeutigkeiten kommen.&lt;/p&gt;

&lt;p&gt;In diesem Fall lautet meine Empfehlung: VARIANTen immer von Hand definieren
(und sich natürlich dann auch an die Definitionen halten!).
Ist zwar mehr Aufwand, funktioniert dann aber über viele Jahrzehnte
(wenn es sein muss).&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>DOS Games</title>
   <link href="https://www.opengate.at/blog/2019/04/dos-games/"/>
   <published>2019-04-28T12:00:00+02:00</published>
   <updated>2019-04-28T12:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2019/04/dos-games</id>
   <category term="software" /><category term="retro" />
   <summary type="text">Oder auch: Von AlleyCat und Frogger bis Doom 2 und Duke Nukem 3D

Während andere Schulen schon lange am Umstieg vom 
80486 zum 
Pentium arbeiteten,
war mein erster PC Kontakt in meiner Schule Mitte der 90er Jahre auf
originale IBM 8086 
Kisten beschränkt.

Trotzdem war das Anwerfen von diversen Spielen unter 
DOS 2.0 damals 
ein Vergnügen und eine willkommene Abwechslung im Schul-Alltag.
</summary>
   <content type="html">&lt;h2 id=&quot;oder-auch-von-alleycat-und-frogger-bis-doom-2-und-duke-nukem-3d&quot;&gt;Oder auch: Von AlleyCat und Frogger bis Doom 2 und Duke Nukem 3D&lt;/h2&gt;

&lt;p&gt;Während andere Schulen schon lange am Umstieg vom 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Intel_80486&quot;&gt;80486&lt;/a&gt; zum 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Intel_Pentium&quot;&gt;Pentium&lt;/a&gt; arbeiteten,
war mein erster PC Kontakt in meiner Schule Mitte der 90er Jahre auf
originale &lt;a href=&quot;https://de.wikipedia.org/wiki/IBM_Personal_Computer&quot;&gt;IBM 8086&lt;/a&gt; 
Kisten beschränkt.&lt;/p&gt;

&lt;p&gt;Trotzdem war das Anwerfen von diversen Spielen unter 
&lt;a href=&quot;https://de.wikipedia.org/wiki/MS-DOS#MS-DOS_2.x_und_höher&quot;&gt;DOS 2.0&lt;/a&gt; damals 
ein Vergnügen und eine willkommene Abwechslung im Schul-Alltag.&lt;br /&gt;
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Bis Ende der 90er handelte man am Schulhof mit Disketten und CDs
um die neuesten DOS-Spiele zumindest als “Demo” ansehen zu können.
Alle nachfolgenden Spiele liefen bei mir anfangs auf meinem 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Intel_80486&quot;&gt;486er PC&lt;/a&gt;, erst die
späteren 3D Spiele lernte ich in höherer Auflösung am 
Cyrix-MMX-Pentium zu genießen.&lt;/p&gt;

&lt;h3 id=&quot;alley-cat&quot;&gt;Alley-Cat&lt;/h3&gt;

&lt;p&gt;Ich erinnere mich auch heute noch an einfache Spiele wie
&lt;a href=&quot;https://de.wikipedia.org/wiki/Alleycat&quot;&gt;Alley-Cat&lt;/a&gt;, wo man eine Katze vom 
Gartenzaun aus durch diverse Wohnungsfenster springen lassen musste um dort 
Mäuse zu fangen oder im Goldfischglas Fische zu jagen ohne zu ertrinken.&lt;br /&gt;
Man durfte nie zu lange an einem Fleck stehen bleiben, weil man sonst
von einem vorbeilaufenden Hund oder einem verfolgenden Besen erwischt
wurde.&lt;br /&gt;
&lt;img src=&quot;/blog/assets/img/dos-game-alleycat.png&quot; alt=&quot;Alley-Cat&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;frogger&quot;&gt;Frogger&lt;/h3&gt;

&lt;p&gt;Eines der primitivsten Spiele überhaupt war &lt;a href=&quot;https://de.wikipedia.org/wiki/Frogger&quot;&gt;Frogger&lt;/a&gt;, 
wo man einen Frosch über eine befahrene Straße steuern musste.&lt;br /&gt;
Ich kann mir heute überhaupt nicht mehr vorstellen, dass man Stunden
damit verbringen konnte immer auf dem gleichen Bildschirm immer den
gleichen Frosch an immer den gleichen Autos und Zügen vorbeizunavigieren.&lt;br /&gt;
&lt;img src=&quot;/blog/assets/img/dos-game-frogger.png&quot; alt=&quot;Frogger&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;block-out&quot;&gt;Block Out&lt;/h3&gt;

&lt;p&gt;Interessanter war “Block-Out”, ein 3D-Tetris, das mir damals schon recht
futuristisch vorkam. Man blickte von oben auf einen 3D Raum in dem 3D-Tetris
Elemente geworfen wurden, die man so platzieren sollte, dass sie eine
Fläche vollstände ausfüllen sollten.&lt;br /&gt;
Hatte man sich “verbaut” wuchs ein Turm nach oben und man hatte verloren,
wenn dieser das Ende erreicht hatte.&lt;br /&gt;
&lt;img src=&quot;/blog/assets/img/dos-game-blockout.png&quot; alt=&quot;Block Out&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;pool&quot;&gt;Pool&lt;/h3&gt;

&lt;p&gt;3D mit EGA-Grafik war selten, aber bei Pool-Billard möglich. Ich habe aber 
selten gegen den Computer gewinnen können.&lt;br /&gt;
&lt;img src=&quot;/blog/assets/img/dos-game-pool.gif&quot; alt=&quot;Pool&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;sokoban-und-atomix&quot;&gt;Sokoban und Atomix&lt;/h3&gt;

&lt;p&gt;Trotz primitiver Grafik mit wenigen Farben war das Logik-Spiel
&lt;a href=&quot;https://de.wikipedia.org/wiki/Sokoban&quot;&gt;Sokoban&lt;/a&gt; auch so ein Klassiker, 
den es bis heute in vielen Varianten gibt.
Man musste Kisten herumschieben und alle in ein definiertes Zielgebiet verlegen.
“Nur schieben, kein ziehen.” Und dabei kam man ins Grübeln, weil man sich 
bei einer falschen Bewegung schnell das Ziel “verbaut”.&lt;br /&gt;
&lt;img src=&quot;/blog/assets/img/dos-game-sokoban.gif&quot; alt=&quot;Sokoban&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Chemie und Molekülverbindungen spielerisch erlernen, dass war Atomix.
Eigentlich ist es ein modernerer Sokoban-Klon mit etwas anderen Spielregeln.&lt;br /&gt;
Man wählte ein Atom aus und “stieß” es in eine Richtung, wobei es solange
vorwärts lief, bis es auf eine Wand oder anderes Atom traf und dort 
stoppte. So musste man geschickt ein vorgegebenes Molekül aufbauen.&lt;br /&gt;
&lt;img src=&quot;/blog/assets/img/dos-game-atomix.gif&quot; alt=&quot;Atomix&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;ökolopoly&quot;&gt;Ökolopoly&lt;/h3&gt;

&lt;p&gt;Wer mit Hirn und Verstand eine Gesellschaft aufbauen wollte, startete
Ökolopoly und verteilte pro Runde Punkte an diverse Schlüsselfunktionen, 
die sich gegenseitig beeinflussten. Wer sein Land verbesserte wurde gefeiert, 
wer es herunterwirtschaftete wurde als Staatschef verjagt.&lt;br /&gt;
&lt;img src=&quot;/blog/assets/img/dos-game-oeko.gif&quot; alt=&quot;Oekolopoly&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;pinball&quot;&gt;Pinball&lt;/h3&gt;

&lt;p&gt;In meiner Kindheit gab es sie noch: Flipperautomaten in Wirtshäusern und 
Spielhallen. Doch dank “Pinball” Software Simulationen versenkte ich dann 
kein Geld mehr in diesen Maschinen und ballerte die Kugel mit den Shift-
Tasten über den Bildschirm.&lt;br /&gt;
&lt;img src=&quot;/blog/assets/img/dos-game-flipper.gif&quot; alt=&quot;Tristan Pinball&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;kyrandia&quot;&gt;Kyrandia&lt;/h3&gt;

&lt;p&gt;Mama hatte damals ein besonderes Geburtstagsgeschenk für mich parat:&lt;br /&gt;
&lt;a href=&quot;https://de.wikipedia.org/wiki/The_Legend_of_Kyrandia&quot;&gt;Kyrandia&lt;/a&gt;
auf 4 &lt;a href=&quot;https://de.wikipedia.org/wiki/Diskette&quot;&gt;Disketten&lt;/a&gt;.&lt;br /&gt;
Dieses Spiel war auf dem &lt;a href=&quot;https://de.wikipedia.org/wiki/Intel_80386&quot;&gt;386er&lt;/a&gt; 
mein erstes &lt;a href=&quot;https://de.wikipedia.org/wiki/Rollenspiel_(Spiel)#Computer-Rollenspiel&quot;&gt;RPG&lt;/a&gt; 
und obwohl ich es damals nie geschafft hatte es durchzuspielen, 
bleibt es eines meiner Highlight.&lt;br /&gt;
&lt;img src=&quot;/blog/assets/img/dos-game-kyrandia.jpg&quot; alt=&quot;Kyrandia&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;lemmings-packrat-gold-axe&quot;&gt;Lemmings, Packrat, Gold Axe&lt;/h3&gt;

&lt;p&gt;Dann kamen auch ein paar Raubkopien zu mir ins Haus, die man in der 
Schule schnell ausgetauscht hatte: 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Lemmings&quot;&gt;Lemmings&lt;/a&gt;, 
Packrat und
&lt;a href=&quot;https://de.wikipedia.org/wiki/Golden_Axe&quot;&gt;Golden Axe&lt;/a&gt;&lt;br /&gt;
&lt;img src=&quot;/blog/assets/img/dos-game-packrat.gif&quot; alt=&quot;Packrat&quot; /&gt;&lt;br /&gt;
&lt;img src=&quot;/blog/assets/img/dos-game-goldenaxe.gif&quot; alt=&quot;Golden Axe&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;simcity&quot;&gt;SimCity&lt;/h3&gt;

&lt;p&gt;In &lt;a href=&quot;https://de.wikipedia.org/wiki/SimCity&quot;&gt;SimCity&lt;/a&gt; baute ich viele Stunden
an Städten und hoffte immer, dass mir kein Erdbeben die Arbeit zunichte macht.
Der Cheat-Tastenfolge &lt;code&gt;FUND&lt;/code&gt; ist mir noch in Erinnerung um 10000 $ zu bekommen.&lt;br /&gt;
&lt;img src=&quot;/blog/assets/img/dos-game-simcity.png&quot; alt=&quot;SimCity&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;werbung-für-kellogs&quot;&gt;Werbung für Kellogs&lt;/h3&gt;

&lt;p&gt;Auch Werbefirmen nutzten PC-Spiele um Produkte zu bewerben.
Kellogs’ ließ die Figuren seiner Frühstückspalette im Super-Mario
Stil durch Welten springen und Punkte einsammeln.&lt;br /&gt;
&lt;img src=&quot;/blog/assets/img/dos-game-kellog.gif&quot; alt=&quot;Kellogs&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;abenteuer-im-wald&quot;&gt;Abenteuer im Wald&lt;/h3&gt;

&lt;p&gt;Wenn ein Spiel in Österreich produziert wird, ist es so voller Klischees, dass
es fast weh tut. “Abenteuer im Wald” lässt einen Jungen oder ein Mädchen mit 
einem Waldgeist herumwandern und Aufgaben lösen, um den Wald und die Waldgeister
zu retten.&lt;br /&gt;
Ein typisches “Spiel aus der Schule” um etwas Lehrstoff mit bunten Figuren
zu vermitteln.
&lt;img src=&quot;/blog/assets/img/dos-game-wald.gif&quot; alt=&quot;Abenteuer im Wald&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;knights-of-xentar-dragon-knights&quot;&gt;Knights of Xentar (Dragon Knights)&lt;/h3&gt;

&lt;p&gt;Ein ganz besonderes RPG-Spiel, das ich am PC (und nicht als SNES-Emulation) 
gespielt habe war “Knights of Xentar”, ein absoluter Klassiker mit vielen 
Anime/Manga Bildern und einigen spärlich bekleideten Mädchen, die man als 
Ritter stets retten musste.
&lt;img src=&quot;/blog/assets/img/dos-games-xentar.gif&quot; alt=&quot;Knights of Xentar&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;conquest-of-the-new-world&quot;&gt;Conquest of the New World&lt;/h3&gt;

&lt;p&gt;Ein schönes Strategie- und Aufbauspiel war “Conquest of the New World”.
Man landete an der Küste Amerikas und musste diese besiedeln, Gebäude 
ausbauen und Rohstoffe abbauen um zu Städten heranzuwachsen.&lt;br /&gt;
Gestört wurde man nur von Siedlern anderer Nationen, die es dann in
Kämpfen zu besiegen galt. Über eine serielle Verbindung konnte man es 
sogar mit zwei PCs gegeneinander spielen.
&lt;img src=&quot;/blog/assets/img/dos-game-conquest.jpg&quot; alt=&quot;Conquest of the New World&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;doom2-heretic-und-hexen&quot;&gt;DOOM2, Heretic und Hexen&lt;/h3&gt;

&lt;p&gt;Mit meinem 486 und danach mit meinem &lt;a href=&quot;https://de.wikipedia.org/wiki/Cyrix_6x86&quot;&gt;“Cyrix-Pentium”&lt;/a&gt; 
schaffte ich ein paar Jahre später die Ausführung von Spielen wie 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Doom_2:_Hell_on_Earth&quot;&gt;DOOM 2&lt;/a&gt;, wo man in einer
etwas futuristischen Umgebung Zombies und Dämonen aus der Hölle töten sollte.&lt;/p&gt;

&lt;p&gt;Heute wirkt es schon fast lächerlich, aber damals hielt ich die Pixelmonster
für gruselig und schoss sie immer aus sicherer Entfernung möglichst schnell 
ab.
&lt;img src=&quot;/blog/assets/img/dos-game-doom2.jpg&quot; alt=&quot;DOOM 2&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Ähnlich sahen auch Heretic 1 und Hexen 1 aus, die eigentlich nur wie DOOM in
einer mittelalterlichen Fantasy-Magie-Welt aussahen.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/dos-game-hexen.jpg&quot; alt=&quot;HEXEN&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Auf dem 486 waren solche Spiele mit niedrigsten Auflösung von 320x240 bzw. 
320x200 teilweise auch spielbar … doch für die Augen war dieser 
Pixelklotzhaufen kein Vergnügen.&lt;/p&gt;

&lt;h3 id=&quot;warcraft&quot;&gt;Warcraft&lt;/h3&gt;

&lt;p&gt;Nach &lt;a href=&quot;https://de.wikipedia.org/wiki/Warcraft&quot;&gt;WarCraft&lt;/a&gt; 1 kam Warcraft 2 mit 
einer schöneren verbesserten Grafik und einem ausgereifteren Einheiten und 
Gebäudemodell. Stundenlang konnte man als Mensch gegen Orks oder umgekehrt 
kämpfen um nach vielen Leveln das gegnerische Reich in die Knie zu zwingen.&lt;br /&gt;
&lt;img src=&quot;/blog/assets/img/dos-game-warcraft2.jpg&quot; alt=&quot;Warcraft 2&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;tomb-raider-1&quot;&gt;Tomb Raider 1&lt;/h3&gt;

&lt;p&gt;Mein alter Cyrix mit 200 Megahertz schaffte es dann Games wie
&lt;a href=&quot;https://de.wikipedia.org/wiki/Tomb_Raider&quot;&gt;Tomb Raider&lt;/a&gt; mit unglaublichen 
640x480 Pixel bei gerade mal 25 Frames pro Sekunde flüssig darzustellen.&lt;/p&gt;

&lt;p&gt;Nicht nur Lara Croft war ein &lt;em&gt;Hin(tern)gucker&lt;/em&gt;, sondern auch die großen 
Levels die alte Grabstätten von Griechen, Römern und Ägyptern auf dem
Bildschirm zeigten.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/dos-game-tombraider.jpg&quot; alt=&quot;Tomb Raider 1&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Es zwar in erster Linie ein Herumrennen um Schalter zu finden, die Falltüren
und Tore öffneten, doch gelegentlich durfte man sogar auf richtige Gegner
schießen, bis man im alten Atlantis ein fleischiges Gen-Monster abknallen
musste, bevor es einen mit seinen riesigen Fäusten zertrümmerte.&lt;/p&gt;

&lt;h3 id=&quot;dukenukem-3d&quot;&gt;DukeNukem 3D&lt;/h3&gt;

&lt;p&gt;Am meisten gespielt hatte ich vermutlich &lt;a href=&quot;https://de.wikipedia.org/wiki/Duke_Nukem_3D&quot;&gt;DukeNukem 3D&lt;/a&gt;
denn hier kannte ich am Ende alle Levels und Secrets auswendig.&lt;br /&gt;
Man fühlte sich damals wie ein Pionier in der digitalen Welt, konnte 
unbekannte Orte und Dimensionen erforschen und seine Fingerfertigkeit 
beim Bekämpfen der Gegner trainieren.&lt;br /&gt;
Und außerdem ist es das einzige mir bekannte DOS Spiel, in dem es benutzbare
Toiletten gibt … Wahnsinn!&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/dos-game-duke3d.jpg&quot; alt=&quot;Duke Nukem 3D&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Das Spiel baute unzählige Anspielungen auf Filme und andere
Spiele mit ein, wenn man plötzlich die Brücke der 
&lt;a href=&quot;https://en.wikipedia.org/wiki/USS_Enterprise_(NCC-1701-D)&quot;&gt;Enterprise NCC-1701-D&lt;/a&gt;
betrat, einen zerdrückten &lt;a href=&quot;https://de.wikipedia.org/wiki/Terminator_(Film)&quot;&gt;Terminator&lt;/a&gt; 
in einer Fabrik fand oder eine getöteten “Doomed-Space-Marine” aufspüren 
konnte.&lt;/p&gt;

&lt;h3 id=&quot;quake&quot;&gt;Quake&lt;/h3&gt;

&lt;p&gt;Den Dreidimensionalen Höhepunkt erreichte unter DOS jedoch &lt;a href=&quot;https://de.wikipedia.org/wiki/Quake&quot;&gt;Quake&lt;/a&gt;, 
welches das letzte aufwendige mir bekannte Spiel für diese Plattform war.&lt;/p&gt;

&lt;p&gt;Während DOOM und DukeNukem nur ein “2 dimensionales” 3D Bild errechnen konnte,
war in Tomb Raider bereits die Bild-Kamera “befreit” worden und konnte in alle
Richtungen (auch noch oben oder unten) blicken … zumindest ein Stückchen 
weit.&lt;/p&gt;

&lt;p&gt;In Quake war es dann endlich so weit, dass man wirklich in alle Richtungen 
blicken und auch laufen konnte. Objekte waren frei in ihrer Größe und nicht
mehr wie bei Tomb Raider auf immer die gleiche Würfelform genormt. Und
Projektile wie Handgranaten oder abgetrennte Körperteile flogen “berechnet”
durch die Raum und waren nicht wie früher immer die gleiche Fixbildprojektion.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/dos-game-quake.jpg&quot; alt=&quot;Quake 1&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;das-ende-im-jahr-2000&quot;&gt;Das Ende im Jahr 2000&lt;/h3&gt;

&lt;p&gt;Danach wechselte die Softwareentwicklung vor den 2000ern zügig auf Windows
und sein neues DirectX wie auch auf OpenGL.
Und so kamen Quake 2, Tomb Raider 2 oder StarCraft in noch hervorragenderer 
Grafik aber auch mit höheren CPU und Grafikanforderungen nur noch für Windows 
heraus.&lt;/p&gt;

&lt;p&gt;Gerade was die Egoshooter anbelangt, so muss man sagen, dass diese alle 
zu DOS-Zeiten rein auf der CPU gerechnet wurden. Zwar gab es schon 
Ansätze für 3D Beschleunigung aber nur für sauteure Grafikkarten, die
ich mir damals nie hätte leisten können (und auch Mama hätte dem nie 
zugestimmt).&lt;/p&gt;

&lt;p&gt;Nachdem die DOS Zeit vorbei war, fand ich dann noch Spiele wie 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Transport_Tycoon&quot;&gt;Transport Tycoon&lt;/a&gt;, 
die man auch von Windows 95/98 aus im DOS-Modus starten konnte, 
doch da mit den beginnenden 2000ern schon ganz neue Herausforderungen auf mich
warteten, waren diese Spiele recht schnell wieder weggelegt.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/dos-game-tycoon.jpg&quot; alt=&quot;Transport Tycoon&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;nachtrag-programmierung&quot;&gt;Nachtrag: Programmierung&lt;/h3&gt;

&lt;p&gt;Aus Sicht der Programmierung konnte ich ein Highlight finden, das mich bis
heute beeindruckt, obwohl mir dessen Magie immer noch nicht vollends klar 
ist:&lt;br /&gt;
Auf der CD von &lt;a href=&quot;https://de.wikipedia.org/wiki/Turbo_Assembler&quot;&gt;Turbo Assembler&lt;/a&gt; 
4 waren zahlreiche Programmierbeispiele, die großteils auf DOS ausgelegt 
waren. Darunter befand sich auch der Entwurf eines 3D Egoshooters rein in 
X86 Assembler, der auf meinem 486er echt flüssig lief. Vielleicht war diese
Demo sogar die Grundlage oder einen Abkömmling von Engines für DOOM oder
DukeNukem und ich war einfach nur beeindruckt, dass jemand tausende
Zeilen Assembler Quellcode schreiben konnte, die ein solches Bildspektakel
liefern konnten.&lt;/p&gt;

&lt;p&gt;Doch leider reichte mein Wissen in Sachen Mathematik und Programmierung bei
weitem nicht aus um dieses Werk nachvollziehen zu können. Schade eigentlich,
denn dieser Code war mit dem Ende von DOS auch zum Sterben verurteilt.&lt;/p&gt;

&lt;p&gt;Also wieder ein Beweis dafür, dass man auf Sprachen wie 
&lt;a href=&quot;https://de.wikipedia.org/wiki/C_(Programmiersprache)&quot;&gt;C&lt;/a&gt; und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B&quot;&gt;C++&lt;/a&gt; setzen soll.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Avengers Endgame</title>
   <link href="https://www.opengate.at/blog/2019/04/avengers-endgame/"/>
   <published>2019-04-25T12:00:00+02:00</published>
   <updated>2019-04-25T12:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2019/04/avengers-endgame</id>
   <category term="entertainment" />
   <summary type="text">Was für “ein Hammer” von einem Film. 
Denn neben der langen Wartezeit, die die Sehnsucht ständig größer machte, 
zeigen auch die Fans am Premiere-Abend, wie emotional ein solcher Blockbuster
enden kann.

Und so war der gestrige Abend ein ganz besonderer geworden

</summary>
   <content type="html">&lt;p&gt;Was für “ein Hammer” von einem Film. 
Denn neben der langen Wartezeit, die die Sehnsucht ständig größer machte, 
zeigen auch die Fans am Premiere-Abend, wie emotional ein solcher Blockbuster
enden kann.&lt;/p&gt;

&lt;p&gt;Und so war der gestrige Abend ein ganz besonderer geworden&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/avengers-endgame-logo.jpg&quot; alt=&quot;Avengers Endgame Logo&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Mein größtes Glück ist ja, dass das &lt;a href=&quot;https://de.wikipedia.org/wiki/Wienerberg&quot;&gt;Wienerberg&lt;/a&gt; 
Kino nun auf meinem Heimweg von der Arbeit liegt. Es war also klar, dass nach 
der letzten eingecheckten Codezeile mich mein Weg dorthin führen würde.&lt;/p&gt;

&lt;p&gt;Dort noch schnell einen Happen beim Burgerking verdrückt und dann ging
es zum Kinoeingang.&lt;br /&gt;
Dort machte ich den fatalen Fehler mir noch Popcorn und Cola zu kaufen,
was bei einem 3 Stunden-Film ohne Unterbrechung nach dem Burger-Abendmahl 
einfach nur naiv war.&lt;/p&gt;

&lt;p&gt;Und dann kam die wie immer die elend lange Werbungsphase, die es 
geistig zu unterdrücken galt.&lt;/p&gt;

&lt;p&gt;Endlich wurde dann aber das geliebte Marvel Intro eingeblendet, doch leider 
nicht mit dem heroischen Introsoundtrack, der mir schon etwas abging.&lt;/p&gt;

&lt;p&gt;Was was soll’s, schließlich startete der Film nicht gerade positiv.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Thanos&quot;&gt;Thanos&lt;/a&gt; hatte vor einem Jahr in 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Avengers:_Infinity_War&quot;&gt;Avengers Infinity War&lt;/a&gt; 
die halbe Bevölkerung des Universums ausgelöscht und damit auch auf der Erde 
nur noch leidende und trauernde Menschen zurückgelassen.&lt;/p&gt;

&lt;h3 id=&quot;achtung-spoiler-ab-jetzt&quot;&gt;Achtung, Spoiler ab jetzt:&lt;/h3&gt;

&lt;p&gt;Mit der frischen eingetroffenen &lt;a href=&quot;https://de.wikipedia.org/wiki/Captain_Marvel_(Film)&quot;&gt;Captain Marvel&lt;/a&gt; 
starten die übrigen Avengers sofort einen Gegenschlag gegen Thanos, der sich 
als Gärtner auf seinen Planeten zurückgezogen hat und gewinnen auch prompt.&lt;/p&gt;

&lt;p&gt;Doch leider hat Thanos die Infinity Steine zerstört und somit jede Chance auf 
die Umkehrung seiner Auslöschaktion unmöglich gemacht.&lt;/p&gt;

&lt;p&gt;Seine epischen letzten Worte&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;Ich bin unvermeidbar.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;beenden also schon nach 15 Minuten scheinbar den Film.&lt;/p&gt;

&lt;p&gt;5 Jahre sitzen die Avengers niedergeschlagen da und kümmern sich um 
Alltagsprobleme der “halb leeren” Erde.&lt;/p&gt;

&lt;p&gt;Bis dann der wichtigste Moment kommt und eine dumme Ratte über die
Steuertasten des Kleinbusses mit dem Quantentunnel läuft, diesen
aktiviert und den seit 5 Jahren gefangenen 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Ant-Man_and_the_Wasp&quot;&gt;Antman&lt;/a&gt; wieder 
freilässt, der parallel zu den Ereignissen von Infinity War im Film 
“Antman 2” nicht mehr zurückkehren konnte, weil sich seine Kollegen 
wegen Thanos in Nichts auflösten.&lt;/p&gt;

&lt;p&gt;Hier startet der eigentliche Film, den ich hier aber nicht nacherzählen 
möchte.&lt;/p&gt;

&lt;p&gt;Die Regiseure und Autoren haben sich alle Mühe gegeben einen neuen Weg
zu erzählen, der vielleicht in wenigen Details schon vermutet wurde, doch
von niemandem konkret erraten wurde.&lt;/p&gt;

&lt;p&gt;Und so kam es gegen Ende des Filmes zu einer gigantischen Schlacht, wo
ein “neuer” alter Thanos mit seinen Schergen gegen alle und zwar wirklich 
alle bisher in anderen Filmen gezeigten Helden kämpfen musste.&lt;/p&gt;

&lt;p&gt;Eigentlich war es fast ein Ding der Unmöglichkeit 20 Hauptcharaktere und 
50 Nebencharaktere glaubhaft und “sichtbar” in einem einzigen Film unterzubringen.
Doch dieses Projekt ist gelungen und ich kann (auch wenn es einige kleine
Schönheitsfehler gab) diesen Film nur als sehr gut gelungen und als das
Highlight des Jahres 2019 beschreiben.&lt;/p&gt;

&lt;p&gt;Nun, wie wird es nun weitergehen?&lt;/p&gt;

&lt;p&gt;Denn dieser Film forderte auch Opfer und legte fest, dass wir einige
Charaktere nicht mehr wieder sehen werden, zumindest nicht als Protagonisten.&lt;/p&gt;

&lt;p&gt;Als nächstes steht &lt;a href=&quot;https://de.wikipedia.org/wiki/Spider-Man:_Far_From_Home&quot;&gt;Spider-Man&lt;/a&gt; 
im Sommer auf dem Spielplan, der nun das finale Ende der Marvel-Phase-3 
darstellen soll.&lt;/p&gt;

&lt;p&gt;Doch wie uns dieser Erfolg gezeigt hat, darf Marvel getrost weitere 
“Phasen” planen und uns mit neuen Helden und neuen Avengers zum Staunen 
bringen.&lt;/p&gt;

&lt;p&gt;Ich fürchte nur, dass wir jetzt etwas ähnliches erleben werden, wie es schon
in vielen Serien passiert ist: Es wird immer extremer und damit 
unglaubwürdiger.
Hat man die “gleichrangigen” Bösewichte besiegt, muss man böse Außerirdische
besiegen. Hat man diese besiegt, muss man böse Götter besiegen, … und dann?
Ja dann wird eben ein noch größerer Übergott erfunden usw. usw.&lt;/p&gt;

&lt;p&gt;Aber gehen wir mal davon aus, dass auch bei Marvel eifrige Schreiber sitzen,
die solchen Konstellationen entgegenwirken und uns Fans - so wie bei Endgame -
mit neuen Ideen überraschen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ich liebe Avengers Endgame!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Und wer diesen Film noch nicht gesehen hat und in 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Thor:_Tag_der_Entscheidung&quot;&gt;Thor Ragnarok&lt;/a&gt;
die Zerstörung des Hammers &lt;a href=&quot;https://de.wikipedia.org/wiki/Mjölnir&quot;&gt;Mjölnir&lt;/a&gt; 
betrauern musste, der wir in Endgame ebenfalls eine tolle Überraschung erleben!&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/avengers-endgame-mjolnir.jpg&quot; alt=&quot;Endgame Mjolnir&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Wie &lt;a href=&quot;http://bohnen.wiki/index.php/Daniel_Schröckert&quot;&gt;Daniel Schröckert&lt;/a&gt;
immer gerne zum Abschluss seiner Sendung sagt:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Also geht ins Kino, Leute!&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>Die Bibliothek POCO</title>
   <link href="https://www.opengate.at/blog/2019/04/poco/"/>
   <published>2019-04-21T12:00:00+02:00</published>
   <updated>2019-04-21T12:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2019/04/poco</id>
   <category term="devel" />
   <summary type="text">Es passiert mir leider doch immer wieder, dass ich mich frage:


  Hey, warum erst jetzt?


Und damit meine ich eigentlich:


  Wie konnte es passieren, dass ich bisher nie etwas von was-auch-immer
gehört habe, obwohl ich es schon früher gut hätte gebrauchen können.


Die C++ Bibliothek POCO 
fällt auch in diese Kategorie.
</summary>
   <content type="html">&lt;p&gt;Es passiert mir leider doch immer wieder, dass ich mich frage:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Hey, warum erst jetzt?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Und damit meine ich eigentlich:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Wie konnte es passieren, dass ich bisher nie etwas von &lt;em&gt;was-auch-immer&lt;/em&gt;
gehört habe, obwohl ich es schon früher gut hätte gebrauchen können.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Die C++ Bibliothek &lt;a href=&quot;https://en.wikipedia.org/wiki/POCO_C%2B%2B_Libraries&quot;&gt;POCO&lt;/a&gt; 
fällt auch in diese Kategorie.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Mit einigen C++ Bibliotheken habe ich so meine “philosophischen” Probleme.
&lt;a href=&quot;https://de.wikipedia.org/wiki/Qt_(Bibliothek)&quot;&gt;QT&lt;/a&gt; z.B. braucht ein ganzes 
Zusatzheer an Meta-Compilern und Fremdtools.
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Foundation_Classes&quot;&gt;MFC&lt;/a&gt; gibt’s nur
für Windows, &lt;a href=&quot;https://de.wikipedia.org/wiki/Boost_(C%2B%2B-Bibliothek)&quot;&gt;BOOST&lt;/a&gt; 
hält sich bei einigen Funktionen im Service/Daemon-Bereich zurück und
setzt auf einige STL Antiquitäten auf, die ich gerne vermeiden möchte, 
usw. usw.&lt;/p&gt;

&lt;p&gt;Vor allem fehlt mir bei vielen dieser Bibliotheken die Möglichkeit sie
auf “exotischeren” Plattformen wie 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_CE&quot;&gt;Windows CE&lt;/a&gt; oder 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Android_(Betriebssystem)&quot;&gt;Android&lt;/a&gt; einzusetzen.&lt;/p&gt;

&lt;p&gt;Genau dieses Ziel hat POCO erreicht und das ist ein guter Grund, warum ich 
nun schon einige Unternehmensprojekte kennenlernen durfte, die auf POCO bei 
der Implementierung ihrer Software setzen.&lt;/p&gt;

&lt;p&gt;(Damit erklärt sich für mich allerdings noch weniger, warum ich bis Anfang 
dieses Jahres noch nie darüber gestolpert bin.)&lt;/p&gt;

&lt;p&gt;Neben seiner Kernbibliothek für&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Delegation_(Softwareentwicklung)&quot;&gt;Delegates&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Thread_(Informatik)&quot;&gt;Threads&lt;/a&gt;, Tasks und Synchronisierung&lt;/li&gt;
  &lt;li&gt;Prozesse und &lt;a href=&quot;https://de.wikipedia.org/wiki/Interprozesskommunikation&quot;&gt;IPC&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Streams und Formatierungen&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Regulärer_Ausdruck&quot;&gt;Reguläre Ausdrücke&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Dateien und Verzeichnisse&lt;/li&gt;
  &lt;li&gt;Datum und Uhrzeit&lt;/li&gt;
  &lt;li&gt;Typencontainer&lt;/li&gt;
  &lt;li&gt;Fehlerbehandlung&lt;/li&gt;
  &lt;li&gt;und vieles mehr&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;stehen zahlreiche weitere POCO-Kern basierte Bibliotheken bereit, z.B. für:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Krytographie&lt;/li&gt;
  &lt;li&gt;Datenbanken (&lt;a href=&quot;https://de.wikipedia.org/wiki/Open_Database_Connectivity&quot;&gt;ODBC&lt;/a&gt;, 
&lt;a href=&quot;https://de.wikipedia.org/wiki/SQLite&quot;&gt;SQLite&lt;/a&gt;, Mongo, Redis, …)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Extensible_Markup_Language&quot;&gt;XML&lt;/a&gt; und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/JavaScript_Object_Notation&quot;&gt;JSON&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Typ-Varianten&lt;/li&gt;
  &lt;li&gt;Netzwerkprotokolle
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Socket_(Software)&quot;&gt;Sockets&lt;/a&gt; und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Transport_Layer_Security&quot;&gt;SSL&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;Protokolle wie: HTTP, FTP, Mail&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Was ich an POCO sehr schätze ist die Tatsache, dass eben nicht alles 
(wie bei BOOST) durch Header-Implementierungen und Templates abgebildet wird,
sondern dass viele Implementierungen entweder als statische oder dynamische
Bibliothek zur Verfügung stehen.&lt;/p&gt;

&lt;p&gt;Das ist besonders bei den Individualitäten von Windows, Linux, Windows CE
und Android auch sehr notwendig.&lt;/p&gt;

&lt;p&gt;Ich habe zwar vorerst nur Kleinigkeiten damit gemacht, doch sowohl die
Dokumentation wie auch die Handhabung der Objekte ist vielversprechend.&lt;br /&gt;
Von daher: Daumen hoch für POCO&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Hmm, was wäre wohl passiert, hätte ich POCO schon früher kennen gelernt?&lt;/p&gt;

&lt;p&gt;Zugegeben, es hat viele Übereinstimmungen mit dem GATE Projekt, doch am 
Ende muss ich sagen, dass alleine die Prozessverwaltung mit nicht genügt
hätte.&lt;/p&gt;

&lt;p&gt;… also bleibe ich weiter beim GATE Ansatz und dessen Orientierung auf
Service-nahe APIs.&lt;/p&gt;

&lt;p&gt;Nichts desto trotz ist POCO ein guter Ansatz für eine Vielzahl an 
Softwareszenarien und bleibt auf jeden Fall auf meinem Schirm ;)&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Office: Serienbriefe und Stundenlisten</title>
   <link href="https://www.opengate.at/blog/2019/04/office-apps/"/>
   <published>2019-04-20T12:00:00+02:00</published>
   <updated>2019-04-20T12:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2019/04/office-apps</id>
   <category term="software" /><category term="retro" />
   <summary type="text">Bevor ich erste Schritte in Richtung Programmierung machte, war der PC vor 
allem eines: Ein Druckstudio.

Vor dem Jahr 2000 waren PCs - man kann sich das heute kaum noch vorstellen - 
nur in wenigen Haushalten vertreten …
Und wenn doch jemand so eine Kiste auf dem Schreibtisch in der Ecke hatte, 
war neben Spielen eine Anwendungsgruppe führend: Textverwaltung und 
Tabellenkalkulationen.
</summary>
   <content type="html">&lt;p&gt;Bevor ich erste Schritte in Richtung Programmierung machte, war der PC vor 
allem eines: Ein Druckstudio.&lt;/p&gt;

&lt;p&gt;Vor dem Jahr 2000 waren PCs - man kann sich das heute kaum noch vorstellen - 
nur in wenigen Haushalten vertreten …&lt;br /&gt;
Und wenn doch jemand so eine Kiste auf dem Schreibtisch in der Ecke hatte, 
war neben Spielen eine Anwendungsgruppe führend: Textverwaltung und 
Tabellenkalkulationen.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Microsoft hatte hier schon immer klar die Nase vorne und so sind die beiden 
Produkte “Word” und “Excel” bis heute jedem ein Begriff.&lt;/p&gt;

&lt;p&gt;Auf meinem ersten &lt;a href=&quot;https://de.wikipedia.org/wiki/Intel_80386&quot;&gt;80386&lt;/a&gt; 
PC war neben &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_3.1&quot;&gt;Windows 3.11&lt;/a&gt; 
tatsächlich ein 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Word#Versionen_für_Windows_(16-Bit)&quot;&gt;“Word für Windows 2.0”&lt;/a&gt; 
installiert. Ich habe allerdings nur noch wenig Erinnerung daran, weil ich es 
durch ein paar Dateiverschiebungen versehentlich zerstört hatte. 
Originaldisketten waren nicht dabei und somit war mein PC  “Office-los”.&lt;br /&gt;
(Ein Glück, denn somit konnte ich mich &lt;a href=&quot;https://de.wikipedia.org/wiki/QBasic&quot;&gt;QBASIC&lt;/a&gt; 
und der Programmierung widmen.)&lt;/p&gt;

&lt;p&gt;Als in der Schule auf Windows 3.1 umgestellt wurde, lernte ich dort den damals
härtesten Konkurrenten von Microsoft’s Office kennen: 
&lt;a href=&quot;https://de.wikipedia.org/wiki/WordPerfect&quot;&gt;WordPerfect&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Und nachdem unsere damalige Informatiklehrkraft (eigentlich Leerkraft) die 
Schüler  dazu missbrauchte diverse Papierdokumente des Stadtarchivs abzutippen, 
um ihre politische Karriere anzukurbeln, war WordPerfect das von uns am 
meisten  benutzte Programm (neben jenen, die 
&lt;a href=&quot;/blog/2019/01/dos-school-apps/&quot;&gt;“für die Schule”&lt;/a&gt; 
da waren).&lt;br /&gt;
Ich erinnere mich jedoch daran, dass Word Perfect wirklich wesentlich mehr 
drauf hatte, als mein WinWord 2.0.&lt;/p&gt;

&lt;p&gt;Als dann einige Jahre später (1997/98) im Gymnasium jene Jungs auftauchten, 
die in der Manteltasche selbst gebrannte CDs mit hatten um sie zu verkaufen,
kam ich an den berühmten “Office Sampler”, der von 
&lt;a href=&quot;https://en.wikipedia.org/wiki/Microsoft_Office_95&quot;&gt;Office 95&lt;/a&gt;, 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Publisher&quot;&gt;Publisher 95&lt;/a&gt;
und &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Money&quot;&gt;Money 95&lt;/a&gt; bis hin zu 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Norton_Utilities&quot;&gt;Norton Tools&lt;/a&gt; und 
Antivirus einiges zu bieten hatte.&lt;/p&gt;

&lt;p&gt;Fast parallel dazu gab es das brandneue &lt;a href=&quot;https://en.wikipedia.org/wiki/Microsoft_Office_97&quot;&gt;Office 97&lt;/a&gt; 
ebenfalls an der dunklen Ecke zu kaufen. Und mit diesem “Office” stieg
ich erstmals in diese Welt richtig ein.
&lt;img src=&quot;/blog/assets/img/office-97-word.png&quot; alt=&quot;Word 97&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Wer erinnert sich noch an “Karl Klammer”, die animierte Büroklammer in der 
Bildschirmecke, die während der Arbeit Tipps zu Programmfunktionen gab und
lustige Bewegungen machte, wenn ein Dokument geladen und gespeichert wurde?
&lt;img src=&quot;/blog/assets/img/office-97-assistent.png&quot; alt=&quot;Office 97 Assistent&quot; /&gt;
Ich mochte jedoch den an &lt;a href=&quot;https://de.wikipedia.org/wiki/Albert_Einstein&quot;&gt;Einstein&lt;/a&gt; 
erinnernden “Professor” am liebsten.&lt;/p&gt;

&lt;p&gt;Diese “Kinderei” hat Microsoft auch noch im Nachfolger Office 2000 integriert,
bevor sie mit Version 2003 wieder aus dem Produkt entfernt wurde.&lt;/p&gt;

&lt;p&gt;Jedenfalls, habe ich heute noch einige Dokumente aus jener Zeit auf Disketten
und Backup-CDs, als ich Schulmappen “digitalisierte”.&lt;br /&gt;
Mit einem damaligen Druckern (zuerst ein HP Deskjet, dann ein kleiner Canon)
wurde ich schnell von der Verwandtschaft entdeckt, die sich bei mir das eine 
oder andere Werbeplakat für ihr Familienunternehmen drucken ließ.&lt;/p&gt;

&lt;p&gt;Ich machte dann tatsächlich auch mal bei einem Office-Kurs mit, wo man so 
Sachen wie “Serienbriefe” durchackerte, wo Briefe mit Daten aus kleinen 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Access&quot;&gt;Access-Datenbanken&lt;/a&gt; befüllt 
wurden um sie dann zu drucken und zu versenden.
(Man bedenke, E-Mail gabs zwar schon, aber keiner hatte Internet).&lt;/p&gt;

&lt;p&gt;Wirklich interessant wurde es für mich ab dem Jahr 2000, denn als ich 
entdeckte, dass man &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Excel&quot;&gt;Excel&lt;/a&gt; 
(und auch alle anderen MS Office Apps) mit 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_Basic_for_Applications&quot;&gt;Visual Basic&lt;/a&gt; 
Code erweitern konnte, konnte ich meine ersten inoffiziellen 
“Programmieraufträge” dafür entgegennehmen.
&lt;img src=&quot;/blog/assets/img/office-97-excel.png&quot; alt=&quot;Excel 97&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Und so wurden “automatisch” Excel-Tabellen befüllt und Berichte als 
Word-Dokumente ausgegeben, was an so manchem PC-Arbeitsplatz als magisches
Hexenwerk angesehen wurde.&lt;/p&gt;

&lt;p&gt;Doch nachdem ich mit &lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B&quot;&gt;C++&lt;/a&gt; so ab 2006 
meine heißeste Liebe entdeckt hatte, gingen meine Kontakte mit Office-Apps 
gegen Null. Mit Version 2007 und 2010 hatte ich lediglich als Administrator 
zu tun, wenn es darum ging, diese so auf Fileservern zu platzieren, dass sie 
per Fernwartung oder automatisch installiert werden konnten.&lt;/p&gt;

&lt;p&gt;In jenen Tagen (so ab 2010) war Microsofts Office bei mir zu Hause überhaupt
nicht mehr zu finden und wurde nur in der Firma für die Stundenabrechnung am 
Monatsende genutzt.&lt;/p&gt;

&lt;p&gt;Wenn es notwendig war, Office-Dokumente zu bearbeiten, griff ich zu den 
kostenlosen Open-Source Angeboten wie 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Apache_OpenOffice&quot;&gt;OpenOffice&lt;/a&gt; und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/LibreOffice&quot;&gt;LibreOffice&lt;/a&gt;.&lt;br /&gt;
Leider muss ich weiter sagen, dass beide Produkte bis heute (2019) kein 
adäquater Ersatz für Microsoft Office sind, weil es immer wieder zu Fehlern 
kommt, wenn in &lt;em&gt;XYZ&lt;/em&gt; Office etwas gespeichert wird und dann in Microsoft 
Office  geöffnet wird. (Das mag aber vielleicht auch an Microsoft liegen.)&lt;/p&gt;

&lt;p&gt;Heute lebe ich nahezu Office-frei, weil ich keine “Dokumente” mehr schreibe.
Mit &lt;a href=&quot;https://de.wikipedia.org/wiki/LaTeX&quot;&gt;LaTex&lt;/a&gt;, &lt;a href=&quot;https://de.wikipedia.org/wiki/Markdown&quot;&gt;MarkDown&lt;/a&gt; 
und &lt;a href=&quot;https://de.wikipedia.org/wiki/Doxygen&quot;&gt;Doxygen&lt;/a&gt; habe ich gute Tools, 
die meinen “Output” in ansehnliche &lt;a href=&quot;https://de.wikipedia.org/wiki/Portable_Document_Format&quot;&gt;PDF&lt;/a&gt; 
Dokumente oder &lt;a href=&quot;https://de.wikipedia.org/wiki/Hypertext_Markup_Language&quot;&gt;HTML&lt;/a&gt; 
übersetzen und deren Quellen in jedem beliebigem Texteditor bearbeitet werden 
können.&lt;/p&gt;

&lt;p&gt;Wenn es dennoch notwendig ist, ein Office Formular auszufüllen oder eine 
Tabelle zu bearbeiten, so geschieht das heute online.&lt;br /&gt;
Denn auch die kostenlosen Angebote von Microsoft wie 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_OneDrive&quot;&gt;OneDrive&lt;/a&gt; oder 
Googles &lt;a href=&quot;https://de.wikipedia.org/wiki/Google_Drive&quot;&gt;GoogleDrive&lt;/a&gt;
besitzen Online-Editor für Dokumente, die nahezu perfekte Dokumente erzeugen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Es ist erstaunlich, wie viele Entwicklungen “Office” Produkte in den 
vergangenen 3 Jahrzehnten durchgemacht haben. Noch erstaunlicher ist, dass die 
Anforderungen von 1 MB RAM auf 1 GB gestiegen sind, aber die meisten 
Anwendungen wie Texte  schreiben oder Tabellenzellen addieren sich kaum 
verändert haben.&lt;/p&gt;

&lt;p&gt;Ich glaube in der Tat, dass ein Office 95 heute ebenso noch einen üblichen
Büroalltag abbilden kann, denn seien wir mal ehrlich … wer braucht schon die
vielen Features, die über die Jahre hinzugekommen sind.&lt;/p&gt;

&lt;p&gt;Content wird heute vermehrt online erstellt und als HTML repräsentiert, von
daher denke ich, dass Office Anwendungen im Laufe der Zeit weniger werden.&lt;/p&gt;

&lt;p&gt;Verschwinden werden sie jedoch nie, denn … es ist einfach unglaublich, wie
viel heute auch in großen Unternehmen alles noch in Excel-Tabellen abgebildet
wird.&lt;br /&gt;
Es gäbe zwar für viele Bereiche bessere Tools … aber Excel überlebt sie 
alle! … für immer …&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Pascal</title>
   <link href="https://www.opengate.at/blog/2019/04/pascal/"/>
   <published>2019-04-14T12:00:00+02:00</published>
   <updated>2019-04-14T12:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2019/04/pascal</id>
   <category term="devel" /><category term="retro" />
   <summary type="text">Nachdem ich gegen Ende der Hauptschulzeit QBASIC und Visual Basic 4
erlernt hatte, stellte ich im Gymnasium fest:
Die arbeiten mit was ganz anderem.

Und das war Turbo 
PASCAL, 
genau genommen TP 6.
</summary>
   <content type="html">&lt;p&gt;Nachdem ich gegen Ende der Hauptschulzeit &lt;code&gt;QBASIC&lt;/code&gt; und Visual Basic 4
erlernt hatte, stellte ich im Gymnasium fest:&lt;br /&gt;
Die arbeiten mit was ganz anderem.&lt;/p&gt;

&lt;p&gt;Und das war Turbo 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Pascal_(Programmiersprache)&quot;&gt;PASCAL&lt;/a&gt;, 
genau genommen &lt;a href=&quot;https://de.wikipedia.org/wiki/Turbo_Pascal&quot;&gt;TP 6&lt;/a&gt;.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Es war zwar schon ganz kurz vor dem Jahrtausendwechsel, doch Schulen laufen
bekanntlich immer ein paar Jahrzehnte in der Vergangenheit.
Und so war Windows zwar schon bekannt aber von den Lehrkräften tunlichst
gemieden.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/MS-DOS&quot;&gt;DOS&lt;/a&gt; war ihr Favorit, denn darüber 
hatten sie 15 Jahre vorher in einem Seminar etwas gehört.&lt;/p&gt;

&lt;p&gt;Und so wandte ich mich von der grafischen Programmierung unter 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_Basic_Classic&quot;&gt;Visual Basic&lt;/a&gt; wieder 
zurück zur DOS Konsole und machte meine ersten Gehversuche mit Turbo Pascal.&lt;/p&gt;

&lt;p&gt;… und tatsächlich lernte ich dieses “Produkt” recht schnell lieben.&lt;/p&gt;

&lt;p&gt;Denn es war ähnlich wie &lt;a href=&quot;https://de.wikipedia.org/wiki/QuickBASIC&quot;&gt;QuickBASIC 4.5&lt;/a&gt; 
eine Kombination aus Editor und Compiler, doch im Gegensatz zu QB produzierte 
TP &lt;a href=&quot;https://de.wikipedia.org/wiki/EXE&quot;&gt;EXEn&lt;/a&gt;,
die sauschnell ausgeführt wurden und auch unabhängig von zusätzlichen
Dateien (Laufzeitbibliotheken) waren (zumindest wenn man keine TPUs nutzte).&lt;/p&gt;

&lt;p&gt;Gerade wenn es um den Aufbau von Bildern durch das Zeichnen von 
einzelnen Pixeln und Linien ging, war der Geschwindigkeitsunterschied
zwischen TP und QB extrem und unübersehbar.&lt;/p&gt;

&lt;p&gt;Und außerdem hatte TP eine Eigenschaft, die in QB fehlte:
Die Möglichkeit &lt;a href=&quot;https://de.wikipedia.org/wiki/Assemblersprache&quot;&gt;Assembler Code&lt;/a&gt;
einzustreuen.&lt;/p&gt;

&lt;p&gt;Und an dieser Stelle eröffnete sich mir ein neuer Pfad in der
Softwareentwicklung, den ich auch heute noch beschreite.&lt;br /&gt;
Denn wenn es um Dateien oder “geheime” Systemfunktionen ging,
wie z.B. einen Reboot oder das Formatieren von Disketten,
so suchte man vergeblich nach fertigen Bibliotheken, die
solche Features anboten.&lt;/p&gt;

&lt;p&gt;Doch in Kombination mit der legendären MS-DOS 
&lt;a href=&quot;/blog/2019/02/bios-interrupts/&quot;&gt;Interrupt-Referenz&lt;/a&gt;,
konnte man all das selbst implementieren.&lt;/p&gt;

&lt;p&gt;Und genau das tat ich, zerstörte dabei auch das eine oder andere
Dateisystem, doch war ich glücklich wieder etwas Neues gelernt zu haben.&lt;/p&gt;

&lt;p&gt;Den Höhepunkt dieser Zeit bildete ein Editor für Grafiken um Hintergründe
für ein Final-Fantasy-4-oder-5-artiges Rollenspiel zu erstellen.
Diese schöne Idee wurde leider nie fertig gestellt (wer hätte es gedacht…),
doch sie bereitete mich zusammen mit anderen Assembler-Experimenten auf 
meinen wesentlich später erfolgten Umstieg auf C++ vor, mit dem ich ja
auch noch heute versuche, interessante “geheime” Systemfunktionen für
andere Applikationen und Administrationszwecke nutzbar zu machen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Heute hat PASCAL leider keinen Stellenwert mehr in meinem Programmieralltag.
Auch &lt;a href=&quot;https://de.wikipedia.org/wiki/Object_Pascal&quot;&gt;Delphi und Kylex&lt;/a&gt; 
(auch als Object Pascal bekannt), quasi die GUI-Varianten im Visual Basic Stil
von Pascal, waren beruflich nie gefragt und sind daher schon lange nicht mehr
bei mir installiert.&lt;/p&gt;

&lt;p&gt;Doch das gute alte TP liegt stets Griffbereit in einer 
&lt;a href=&quot;https://de.wikipedia.org/wiki/DOSBox&quot;&gt;DOS-BOX&lt;/a&gt; auf meinem Hauptrechner 
und am Fileserver liegen - als wäre die Zeit stehen geblieben - noch fast 
alle meine alten *.PAS Dateien.&lt;/p&gt;

&lt;p&gt;Vielleicht kommt ja wieder eine Zeit, wo Projekte in Pascal umgesetzt werden.
Mit &lt;a href=&quot;https://de.wikipedia.org/wiki/Free_Pascal&quot;&gt;Free Pascal&lt;/a&gt; gäbe es 
inzwischen auch eine moderne und kostenlose Möglichkeit das anzugehen.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/turbo-pascal.png&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Sortierkästen</title>
   <link href="https://www.opengate.at/blog/2019/04/sorting-boxes/"/>
   <published>2019-04-13T12:00:00+02:00</published>
   <updated>2019-04-13T12:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2019/04/sorting-boxes</id>
   <category term="hardware" />
   <summary type="text">Wie behält man die Übersicht über Bauteile?

Eines kann ich aus Erfahrung sagen: 
Alles über den Schreibtisch zu verstreuen ist keine besonders gute 
Vorgehensweise.
</summary>
   <content type="html">&lt;p&gt;Wie behält man die Übersicht über Bauteile?&lt;/p&gt;

&lt;p&gt;Eines kann ich aus Erfahrung sagen: 
Alles über den Schreibtisch zu verstreuen ist keine besonders gute 
Vorgehensweise.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Heute war Sortiertag … und das war echt anstrengend.&lt;/p&gt;

&lt;p&gt;In den letzten Tagen hatte ich mir auf dem Heimweg mehrere 
billige Sortierschachteln angeschafft. Angefangen hatte es beim großen
blauen Elektronikladen, der alle möglichen Größen von Sortierkästen 
im Angebot hatte.&lt;/p&gt;

&lt;p&gt;Doch nachdem ich einerseits nicht viel Geld für so etwas ausgeben wollte
und auch geplant hatte, alles in meinem kleinen Schreibtischbeikasten
zu verstauen, entschied ich mich für günstige 170x100 mm Plastikboxen, die
in ein paar kleiner Fächer unterteilt waren.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/sorting-box-3.jpg&quot; alt=&quot;Capacitor-Box&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Schnell merkte ich, dass ich inzwischen viel zu viel Hardware und
Bauteile besaß, als das die Kästchen ausreichten.&lt;/p&gt;

&lt;p&gt;Zufällig sah ich beim Billigladen um die Ecke, dass er beim Werkzeug
ebenfalls Sortierkästen im Angebot hatte und somit wurde aufgestockt.
Diese 250x100 mm Boxen waren zwar etwas sperriger, konnten dafür aber
auch größere Teile wie MCU Chips bergen.&lt;br /&gt;
Und außerdem waren sie noch billiger und gleich um die Ecke zu bekommen.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/sorting-box-2.jpg&quot; alt=&quot;Chip-Box&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Am Ende blieben vor allem die Widerstände übrig. Diese haben ja ein etwas
ungutes Format und da ich nicht herumsuchen wollte und auf lange Lieferzeiten
warten wollte, wechselte ich zu &lt;a href=&quot;https://www.thingiverse.com/&quot;&gt;thingiverse.com&lt;/a&gt;
und dort fand ich doch tatsächlich die 3D Modelle für Widerstände.&lt;/p&gt;

&lt;p&gt;Also machte mein 3D Drucker ein paar Überstunden um einige dieser 
“Resistor-Cases” zu drucken.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/sorting-box.jpg&quot; alt=&quot;Resistor-Box&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Das Einsortieren der Widerstände war jedoch ein stundenlanger Alptraum.
Neben dem Beschriften musste ich die Füßchen jedes Bauteils um ein paar
Millimeter kürzen, denn diese waren für die Sortierboxen eine Spur zu lang.&lt;/p&gt;

&lt;p&gt;Aber am Ende ist man dann doch stolz, dass nicht alles wild durcheinander in
mehreren Kartonschachteln herumliegt, sondern nun ordentlich sortiert und
beschriftet stets griffbereit in der Lade liegt.&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>LM317 DIY Stromspender</title>
   <link href="https://www.opengate.at/blog/2019/04/lm317/"/>
   <published>2019-04-06T12:00:00+02:00</published>
   <updated>2019-04-06T12:00:00+02:00</updated>
   <id>https://www.opengate.at/blog/2019/04/lm317</id>
   <category term="hardware" />
   <summary type="text">Sie hätten ja wenigsten auf der Homepage irgend wo schreiben können,
welche Drahtfarbe wo verbunden gehört … diese Händler aus Übersee.

Wie auch immer, die kleine 
LM317 basierte Box zur Versorgung 
kleiner MCU Projekte ist eine
nette und vor allem sinnvolle Do-It-Yourself Aufgabe gewesen.

</summary>
   <content type="html">&lt;p&gt;Sie hätten ja wenigsten auf der Homepage irgend wo schreiben können,
welche Drahtfarbe wo verbunden gehört … diese Händler aus Übersee.&lt;/p&gt;

&lt;p&gt;Wie auch immer, die kleine 
&lt;a href=&quot;https://de.wikipedia.org/wiki/LM317&quot;&gt;LM317&lt;/a&gt; basierte Box zur Versorgung 
kleiner &lt;a href=&quot;https://de.wikipedia.org/wiki/Mikrocontroller&quot;&gt;MCU&lt;/a&gt; Projekte ist eine
nette und vor allem sinnvolle Do-It-Yourself Aufgabe gewesen.&lt;/p&gt;

&lt;!--more--&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/diy_lm317.jpg&quot; alt=&quot;LM317-power-supply&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Der LM317 IC dient der Spannungsregelung. Je nachdem wie viel Spannung
zwischen dem fixen Wert von 1.25 Volt am Adjustment-Pin und seiner
Gegenseite (ein variabler Spannungsteiler) sicher ergibt, um so 
größer oder kleiner ist die Spannung am Output-Pin.&lt;/p&gt;

&lt;p&gt;Das Projekt kommt mit einem kleinen Transformator, der unseren
220 Volt Netzstrom auf 24 Volt reduziert und der LM317 wandelt
diesen in Abhängigkeit zur Einstellung am Adjustment-Pin
auf 0 bis 15 Volt um.&lt;/p&gt;

&lt;p&gt;Die Schaltung lässt Ströme bis zu 200 Milliampere zu und kann
daher zum Betrieb von Arduino oder anderen MCU Projekten genutzt
werden.&lt;/p&gt;

&lt;p&gt;Die Box ist also echt praktisch, wenn man kein Labornetzteil oder
das entsprechende Batterien-Set zur Hand hat.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Der Bausatz beinhaltet auch eine LED Anzeige, die die Spannung misst.&lt;/p&gt;

&lt;p&gt;Was mir sehr gefehlt hat war die Beschreibung, welcher Draht der 
Anzeige wo festgelötet werden soll. Diese Info konnte ich nämlich
nirgends finden.&lt;/p&gt;

&lt;p&gt;Nun ist das Rätsel für mich gelöst, denn wenn man das
&lt;a href=&quot;https://de.wikipedia.org/wiki/Potentiometer&quot;&gt;Potentiometer&lt;/a&gt; von sich selbst 
wegzeigen lässt und die Unterseite der Platine nach oben schaut, dann muss 
von links nach rechts so verdrahtet werden:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Rot&lt;/li&gt;
  &lt;li&gt;Weiß&lt;/li&gt;
  &lt;li&gt;Schwarz&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/diy_lm317_back.jpg&quot; alt=&quot;LM317-power-supply-back&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Jetzt verbaut man noch die Trafospule mit der Platine im mitgelieferten
Acrylgehäuse, montiert die Krokoklemmen und fertig ist unser kleines
Netzteil. Mit dem Drehwiderstand kann man grob die meisten Spannungen in
0.5 Volt Schritten einstellen. Punktgenau geht es nicht, denn dafür ist
der Drehknopf nicht sensibel genug.&lt;/p&gt;

&lt;p&gt;Aber von Batterie-Ladern und Lüftern bis zu 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Arduino_%28Plattform%29&quot;&gt;Arduino&lt;/a&gt; -
oder &lt;a href=&quot;https://de.wikipedia.org/wiki/ESP8266&quot;&gt;ESP&lt;/a&gt; - Projekten kann man damit 
so einiges anstellen.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>180 Tage Blog</title>
   <link href="https://www.opengate.at/blog/2019/04/180-days/"/>
   <published>2019-04-04T22:02:00+02:00</published>
   <updated>2019-04-04T22:02:00+02:00</updated>
   <id>https://www.opengate.at/blog/2019/04/180-days</id>
   <category term="general" /><category term="projects" />
   <summary type="text">Ursprünglich wollte ich ja mit Beginn des Jahres 2019 vom täglichen Blog-
Rhythmus zum wöchentlichen wechseln.

Doch nachdem noch eine Menge “zu sagen” war, ging mein 
Selbst-Dokumentationsprojekt eben weiter.

Jetzt geht mir aber die Zeit aus und somit wird diese Umstellung also
zwingend notwendig.
</summary>
   <content type="html">&lt;p&gt;Ursprünglich wollte ich ja mit Beginn des Jahres 2019 vom täglichen Blog-
Rhythmus zum wöchentlichen wechseln.&lt;/p&gt;

&lt;p&gt;Doch nachdem noch eine Menge “zu sagen” war, ging mein 
Selbst-Dokumentationsprojekt eben weiter.&lt;/p&gt;

&lt;p&gt;Jetzt geht mir aber die Zeit aus und somit wird diese Umstellung also
zwingend notwendig.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Dieser Blog soll mehrere Anforderungen erfüllen:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Er soll die Fortschritte des OpenGATE Projekts grob mitdokumentieren.&lt;/li&gt;
  &lt;li&gt;Die technischen Seiten sollen als “Erinnerung” an die Lösung einzelner 
Entwicklungsprobleme dienen.&lt;/li&gt;
  &lt;li&gt;Und für “die Welt da draußen” darf nebenbei eine Art Tutorial zu 
unterschiedlichen Programmierthemen entstehen.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Der letzte Punkt ist tatsächlich am aufwendigsten, vor allem das manuelle
Zusammensuchen der korrekten Funktionsnamen und der Links zu deren
Dokumentation.&lt;/p&gt;

&lt;p&gt;So vergeht für einen Eintrag gerne mal die eine oder andere Stunde.
Der Grundtext ist immer recht schnell getippt, aber das Umschreiben und
verlinken an den Wochenenden kostet mehrere Stunden.&lt;/p&gt;

&lt;p&gt;Und da ich einerseits meinen Schreibbedarf im letzten halben Jahr 
gestillt habe und nun meine Priorität beim neuen Job liegt, geht es 
sich einfach nicht mehr aus, weiter täglich etwas zu schreiben 
(bzw. am Wochenende die offenen Tage nachzuholen).&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Ich bin daher weiter gespannt, wie ich selbst in 10 Jahren auf dieses
Experiment reagiere, wenn ich mir die dann alten Seiten durchlese.&lt;br /&gt;
Aber im Moment stellt sich für mich selbst ein erster Erfolg ein,
weil ich selbst im Blog zu suchen beginne, wenn es um API-Beschreibungen
geht, die mir gerade nicht einfallen.&lt;/p&gt;

&lt;p&gt;Neben einem Zeitvertreib hat dieses Projekt also auch einen wirtschaftlichen
Aspekt für mich und das ist gut so.&lt;/p&gt;

&lt;hr /&gt;

&lt;blockquote&gt;
  &lt;p&gt;Also lieber Blog! 
Wir werden uns jetzt in der nächsten Zeit etwas seltener “sehen”.&lt;br /&gt;
Pass daher gut auf dich auf und mache nichts, was ich nicht
auch tun würde ;)&lt;/p&gt;

  &lt;p&gt;Bis bald!&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>Interface per Makro aufrufen</title>
   <link href="https://www.opengate.at/blog/2019/04/call-macro/"/>
   <published>2019-04-03T19:47:00+02:00</published>
   <updated>2019-04-03T19:47:00+02:00</updated>
   <id>https://www.opengate.at/blog/2019/04/call-macro</id>
   <category term="devel" />
   <summary type="text">Ich weiß ja:


  Makros sind böse!


AAAAAAber maaaaaanchmal gibt es auch ein paar Nischen, wo sie ganz hilfreich
sind.

Und um eine nicht-objekt-orientierte Sprache wie 
C etwas zu “objektivieren”,
darf man auch die Regeln ein bisschen beugen.
</summary>
   <content type="html">&lt;p&gt;Ich weiß ja:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Makros sind böse!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;AAAAAAber maaaaaanchmal gibt es auch ein paar Nischen, wo sie ganz hilfreich
sind.&lt;/p&gt;

&lt;p&gt;Und um eine nicht-objekt-orientierte Sprache wie 
&lt;a href=&quot;https://de.wikipedia.org/wiki/C_(Programmiersprache)&quot;&gt;C&lt;/a&gt; etwas zu “objektivieren”,
darf man auch die Regeln ein bisschen beugen.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Objekt-Interfaces sind im GATE Projekt ganz ähnlich aufgebaut wie in 
Microsoft’s &lt;a href=&quot;https://de.wikipedia.org/wiki/Component_Object_Model&quot;&gt;COM&lt;/a&gt;. 
Ein Interface ist ein Pointer auf eine Struktur,
von der nur der erste Member bekannt ist, und zwar ein Pointer zur
&lt;a href=&quot;https://de.wikipedia.org/wiki/Tabelle_virtueller_Methoden&quot;&gt;virtuellen Methodentabelle&lt;/a&gt;
(VTBL) und dort befinden sich die
Interfacemethoden.&lt;br /&gt;
Und jede Methode führt als ersten Parameter den Pointer zur Struktur,
also den THIS-Pointer.&lt;/p&gt;

&lt;p&gt;So weit, so gut.&lt;/p&gt;

&lt;p&gt;Aber diese Aufrufe sind in C gelegentlich ziemlich mühsam.
Folgender einfacher C++ Code&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;object-&amp;gt;method(param1, param2);
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;sieht in C so aus:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;object-&amp;gt;vtbl-&amp;gt;method(object, param1, param2);
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;OK, soooo viel mehr an Schreibarbeit ist das hier nicht.
Doch das ändert sich, wenn der Objekt-Pointer von wo anders herkommt,
z.B.: wenn er ein Member einer anderen Struktur ist.&lt;/p&gt;

&lt;p&gt;Das würde dann nämlich so aussehen:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;parent-&amp;gt;child-&amp;gt;method(param1, param2);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;parent-&amp;gt;child-&amp;gt;vtbl-&amp;gt;method(parent-&amp;gt;child, param1, param2);
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Der eigentliche Objekt-Pointer Teil wird immer länger und muss 
zusätzlich im ersten Parameter wiederholt werden. Und diese Wiederholung ist
nebenbei eine beliebte Fehlerquelle beim Kopieren von Code.&lt;/p&gt;

&lt;h3 id=&quot;die-lösung-ein-makro&quot;&gt;Die Lösung: Ein &lt;a href=&quot;https://de.wikipedia.org/wiki/C-Pr%C3%A4prozessor#Definition_und_Ersetzung_von_Makros&quot;&gt;Makro&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;Wie schön wäre die Welt doch, wenn so etwas möglich wäre:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#define&lt;/span&gt; INVOKE(obj, method, params) (obj)-&amp;gt;vtbl-&amp;gt;method((obj), params)
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Damit müssen wir den &lt;code&gt;obj&lt;/code&gt; Token nur einmal schreiben.
Doch das Problem sind die &lt;code&gt;params&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Hier gibt es zwei Möglichkeiten:&lt;/p&gt;

&lt;h3 id=&quot;1-variable-argumentenliste&quot;&gt;(1) Variable Argumentenliste&lt;/h3&gt;

&lt;p&gt;Blöd nur, dass Microsoft und der GCC die Syntax anders “sehen” und deshalb
besteht diese Lösung aus zwei Implementierungen:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#if&lt;/span&gt; defined(GATE_COMPILER_MSVC)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#define&lt;/span&gt; INVOKE(obj, method, ... ) &lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;\&lt;/span&gt;  
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  (obj)-&amp;gt;vtbl-&amp;gt;method((obj), __VA_ARGS__ )
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#else&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#define&lt;/span&gt; INVOKE(obj, method, ... ) &lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;\&lt;/span&gt;  
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;  (obj)-&amp;gt;vtbl-&amp;gt;method((obj), &lt;span style=&quot;color:#579&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#__VA_ARGS__&lt;/span&gt; )
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#endif&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Denn hinter einem Beistrich sind variable Argumente offenbar für den GCC 
etwas Besonderes, daher der doppelte Hashtoken.&lt;/p&gt;

&lt;p&gt;Die Syntax sieht dann so aus:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;INVOKE(object, foobar, param1, param2, param3);
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h3 id=&quot;2-umklammerung-mit-ohne-umklammerung&quot;&gt;(2) Umklammerung mit Ohne-Umklammerung&lt;/h3&gt;

&lt;p&gt;Wenn wir nämlich die Syntax in folgender Form wollen,&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;INVOKE(object, foobar, (param1, param2, param3));
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;so sieht das für mich etwas “natürlicher” aus, weil die Parameter
durch die Klammern quasi von &lt;code&gt;object-&amp;gt;method&lt;/code&gt; optisch getrennt sind.&lt;/p&gt;

&lt;p&gt;Das &lt;code&gt;INVOKE&lt;/code&gt; Makro hat dann genau 3 Parameter, wobei der dritte Parameter
den gesamten Klammerninhalt mit sich führt.&lt;/p&gt;

&lt;p&gt;Wäre das Makro so definiert:&lt;/p&gt;
&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#define&lt;/span&gt; INVOKE(obj, method, params) (obj)-&amp;gt;vtbl-&amp;gt;method((obj), params)
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;käme folgender Blödsinn heraus:`&lt;/p&gt;
&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;object-&amp;gt;vtbl-&amp;gt;foobar(object, (param1, param2, param3));
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Also müssen die Klammern weg. Und wie macht man das?&lt;br /&gt;
Mit einem Trick!&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#define&lt;/span&gt; STRIP_PARENTHESES(...) __VA_ARGS__
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#define&lt;/span&gt; INVOKE(obj, method, params) &lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;\&lt;/span&gt;  
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  (obj)-&amp;gt;vtbl-&amp;gt;method((obj), STRIP_PARENTHESES params)
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Nachdem &lt;code&gt;params&lt;/code&gt; eine durch Klammern begrenzte Liste anderer Parameter 
beinhaltet, wird beim hintereinanderstellen von &lt;code&gt;STRIP_PARENTHESES&lt;/code&gt; und &lt;code&gt;params&lt;/code&gt;
durch die Klammern ein “Aufruf” von STRIP_PARENTHESES generiert und dieser
nutzt “normale” &lt;code&gt;__VA_ARGS__&lt;/code&gt; um die Parameterliste einfach einzufügen,
und zwar ohne die ursprünglichen Klammern.&lt;/p&gt;

&lt;p&gt;Damit wird das Makro so aufgelöst:&lt;/p&gt;
&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;object-&amp;gt;vtbl-&amp;gt;foobar(object, param1, param2, param3);
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Und wir haben einen ganz validen C - Objektaufruf.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Tja, auch wenn es nicht besonders hilfreich im Alltag ist, so gefallen mir
die beiden Lösungen, und die zweite ist als &lt;code&gt;GOCALL&lt;/code&gt; (für Gate-Object-CALL)
im GATE Projekt implementiert ;)&lt;/p&gt;

&lt;p&gt;Microsoft generiert für die C Header aus seinen COM-Klassen pro Methode
ein eigenes Makro, das in etwas so aufgebaut ist:&lt;br /&gt;
&lt;code&gt;[RETTYPE] + &quot; &quot; [INTERFACENAME] + &quot;_&quot; + [METHODNAME] + &quot;(&quot; + [INTERFACENAME] + &quot;* thisptr, &quot; + ... + &quot;)&quot;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Das ist auch nicht unschön, aber ohne Codegenerator etwas mühsam.
Dennoch verfolge ich diesen Weg bei einigen Klassen (z.B. Streams) ebenso und
erzeuge entsprechende Makros manuell.&lt;/p&gt;

&lt;p&gt;Für den allgemeinen Fall ist aber der &lt;code&gt;GOCALL&lt;/code&gt; stets einsatzbereit.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>IncrediBuild</title>
   <link href="https://www.opengate.at/blog/2019/04/incredibuild/"/>
   <published>2019-04-02T22:08:00+02:00</published>
   <updated>2019-04-02T22:08:00+02:00</updated>
   <id>https://www.opengate.at/blog/2019/04/incredibuild</id>
   <category term="devel" /><category term="software" />
   <summary type="text">Privat hatte ich diese seltsame Option 
“IncrediBuild” bei der 
Installation von Visual Studio
schon einmal ausprobiert …
doch da ich keine Performancegewinne sehen konnte, wurde dieses
Experiment schnell und ohne weitere Recherche abgebrochen.

Doch dank des Einsatzes dieser Technologie an meinem Arbeitsplatz, 
sehe ich “IncrediBuild” nun recht häufig.
</summary>
   <content type="html">&lt;p&gt;Privat hatte ich diese seltsame Option 
“&lt;a href=&quot;https://en.wikipedia.org/wiki/IncrediBuild&quot;&gt;IncrediBuild&lt;/a&gt;” bei der 
Installation von &lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_Studio&quot;&gt;Visual Studio&lt;/a&gt;
schon einmal ausprobiert …
doch da ich keine Performancegewinne sehen konnte, wurde dieses
Experiment schnell und ohne weitere Recherche abgebrochen.&lt;/p&gt;

&lt;p&gt;Doch dank des Einsatzes dieser Technologie an meinem Arbeitsplatz, 
sehe ich “IncrediBuild” nun recht häufig.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Große Projekte sind mühsam zu kompilieren. Man wartet wegen Abhängigkeiten
viele Minuten bis der Compiler seine Aufgaben alle abgearbeitet hat.&lt;/p&gt;

&lt;p&gt;Wäre es nicht super, wenn man mehrere Computer an dieser Aufgabe arbeiten
lassen könnte?&lt;/p&gt;

&lt;p&gt;Natürlich wäre es das, und IncrediBuild tut es einfach.&lt;/p&gt;

&lt;p&gt;Incredibuild kann Kompiliervorgänge über das Netzwerk auf andere Rechner
auslagern. Das können separate Systeme oder VMs sein, oder auch die
Rechner von Kollegen, die gerade keine CPU-Intensiven Aufgaben haben.&lt;/p&gt;

&lt;p&gt;Mühsam ist das Thema Versionierung, denn nicht jede Visual Studio Version
mit ihrer eigenen IncrediBuild Version kann mit anderen Versionen 
problemlos kommunizieren. Ein einheitlicher Versionsstand ist hier
sehr hilfreich.&lt;/p&gt;

&lt;p&gt;Wenn man aber alle erforderlichen Einstellungen ermittelt und ausgerollt
hat, ist es ein Vergnügen, wie ein 60 Minuten-Build-Job auf 10 Minuten 
reduziert wird.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/incredibuild.png&quot; alt=&quot;IncrediBuild&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Bisher habe ich noch kein IncrediBuild Setup selbst angelegt sondern nur
bestehende Infrastrukturen genutzt.&lt;br /&gt;
Die Software hat aber Potential und ist auch für andere Plattformen
(und nicht nur Windows) nutzbar.&lt;/p&gt;

&lt;p&gt;Mal sehen, ob ich mal die Zeit finde die Buildvorgänge bei mir zu Hause
auch mit IncrediBuild zu beschleunigen.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Von NMAKE zu CMAKE</title>
   <link href="https://www.opengate.at/blog/2019/04/cmake/"/>
   <published>2019-04-01T22:39:00+02:00</published>
   <updated>2019-04-01T22:39:00+02:00</updated>
   <id>https://www.opengate.at/blog/2019/04/cmake</id>
   <category term="devel" />
   <summary type="text">Als ich zum ersten Male mit 
OpenSSL arbeitete, war ich schwer verärgert,
denn die Bibliothek benötigt Perl-Scripts
um seine eigenen Header und Makefiles an Compiler anzupassen,
um übersetzbar zu werden.

Etwas später kam die libReSSL auf den Markt und 
ich beschloss, ein eigenes Visual Studio
Projekt zu erstellen, in dem ich jede einzelne Quelldatei händisch hinzufügte.

Wie blöd! Denn eigentlich lag eine CMAKE 
Datei bei, und dieser mühsame Prozess wäre automatisch erledigt worden.
</summary>
   <content type="html">&lt;p&gt;Als ich zum ersten Male mit 
&lt;a href=&quot;http://www.openssl.org/&quot;&gt;OpenSSL&lt;/a&gt; arbeitete, war ich schwer verärgert,
denn die Bibliothek benötigt &lt;a href=&quot;https://de.wikipedia.org/wiki/Perl_%28Programmiersprache%29&quot;&gt;Perl-Scripts&lt;/a&gt;
um seine eigenen Header und Makefiles an Compiler anzupassen,
um übersetzbar zu werden.&lt;/p&gt;

&lt;p&gt;Etwas später kam die &lt;a href=&quot;http://www.libressl.org/&quot;&gt;libReSSL&lt;/a&gt; auf den Markt und 
ich beschloss, ein eigenes &lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_Studio&quot;&gt;Visual Studio&lt;/a&gt;
Projekt zu erstellen, in dem ich jede einzelne Quelldatei händisch hinzufügte.&lt;/p&gt;

&lt;p&gt;Wie blöd! Denn eigentlich lag eine &lt;a href=&quot;https://de.wikipedia.org/wiki/CMake&quot;&gt;CMAKE&lt;/a&gt; 
Datei bei, und dieser mühsame Prozess wäre automatisch erledigt worden.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Seit Jahrzehnten bin ich von Visual Studio mit seinen Solutions und
Projekten verwöhnt. Jede neue Quelldatei wird einem Projekt hinzugefügt
und mehrere Projekte (Bibliotheken + Programme) bilden eine Solution.&lt;/p&gt;

&lt;p&gt;Und das beste daran ist, dass mit &lt;code&gt;NMAKE&lt;/code&gt; jede Solution per Kommandozeile
(und damit automatisierbar) in fertige Binäredateien übersetzt werden
kann.&lt;/p&gt;

&lt;p&gt;Als ich nach Windows mit Linux zu arbeiten begann, war ich von den dortigen
MAKE-Files sprichwörtlich angewidert. “Wieso?” fragte ich mich.
“Wieso kann man dort nicht auch ‘einfach’ Dateien einem ‘Projekt’ per
GUI hinzufügen und dieses übersetzen.&lt;/p&gt;

&lt;p&gt;Aus diesem Grund griff ich zur IDE 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Code::Blocks&quot;&gt;Code::Blocks&lt;/a&gt;. Denn diese IDE bot
ähnliche Features wie Visual Studio aber war auch unter Linux einsetzbar.
Zusätzlich kann man mit dem Tool &lt;code&gt;cbp2make&lt;/code&gt; alle Code::Blocks Projekte
oder Workspaces (== Solution) in MAKE Dateien übersetzen.&lt;/p&gt;

&lt;p&gt;Doch hier kommt bereits Sand ins Getriebe, denn wer glaubt MAKE Files sind
gleich MAKE Files, der irrt leider.&lt;br /&gt;
Und so können die mit &lt;code&gt;cbp2make&lt;/code&gt; generierten Anweisungen zwar unter Linux
problemlos verarbeitet werden, doch scheitern sie unter 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Berkeley_Software_Distribution&quot;&gt;BSD&lt;/a&gt; Umgebungen.&lt;/p&gt;

&lt;h3 id=&quot;cmakeliststxt&quot;&gt;CMakeLists.txt&lt;/h3&gt;

&lt;p&gt;Wer jedoch in seinem Quellcode-Verzeichnis eine Datei namens &lt;code&gt;CMakeLists.txt&lt;/code&gt;
anlegt, macht sein Projekt zu einem &lt;code&gt;CMAKE&lt;/code&gt; Projekt.&lt;br /&gt;
Und das Tool &lt;code&gt;CMAKE&lt;/code&gt; erstellt für jede Plattform eigene “native” Projektdateien.
Man kann also aus einer &lt;code&gt;CMakeLists.txt&lt;/code&gt; Datei:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;eine &lt;code&gt;.vcxproj&lt;/code&gt; Projektdatei für Visual Studio&lt;/li&gt;
  &lt;li&gt;eine &lt;code&gt;.cbp&lt;/code&gt; Projektdatei für Code::Blocks&lt;/li&gt;
  &lt;li&gt;oder eine &lt;code&gt;makefile&lt;/code&gt; Datei für Unix Compiler wie &lt;a href=&quot;https://de.wikipedia.org/wiki/GNU_Compiler_Collection&quot;&gt;GCC&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;anlegen und sie dann vom nativen Toolset übersetzen lassen.&lt;/p&gt;

&lt;script src=&quot;/blog/assets/mermaid/mermaid.min.js&quot;&gt;&lt;/script&gt;
&lt;div class=&quot;mermaid&quot;&gt;
graph TD;
  CML[CMakeLists.txt] --&amp;gt; CME((CMake&lt;br /&gt;Executable))
  CME --&amp;gt;|Generator| MSVC[/Visual Studio&lt;br /&gt;project.sln file\]
  CME --&amp;gt;|Generator| GNU[/GNU Linux&lt;br /&gt;MAKE files\]
  CME --&amp;gt;|Generator| BSD[/BSD&lt;br /&gt;MAKE files\]
  CME --&amp;gt;|Generator| NMAKE[/WinSDK BuildTools&lt;br /&gt;NMAKE files\]
  CME --&amp;gt;|Generator| CB[/CodeBlocks&lt;br /&gt;project.cbp file\]
&lt;/div&gt;

&lt;p&gt;Leider gibt es auch für &lt;code&gt;CMakeLists.txt&lt;/code&gt; keinen grafischen Editor,
doch ich komme mit dessen Syntax besser zurecht, als mit anderen.
Und zu meiner Freude gibt es ein Visual Studio-Plugin, welches 
bestehende Solutions in &lt;code&gt;CMAKE&lt;/code&gt; Dateien übersetzen kann.&lt;/p&gt;

&lt;p&gt;Daher möchte ich in Zukunft mehr und mehr zu &lt;code&gt;CMAKE&lt;/code&gt; wechseln und
dessen großartige Portierungshilfen nutzen.&lt;/p&gt;

&lt;p&gt;Wie cool wäre es, wenn das GATE Projekt auf allen
Plattformen wie Windows, Linux, BSD, MacOS und Android automatisch
übersetzt werden kann?&lt;/p&gt;

&lt;p&gt;Und &lt;code&gt;CMAKE&lt;/code&gt; ist dafür - nach meinen bisherigen Erfahrungen - recht gut 
geeignet.&lt;br /&gt;
Natürlich fehlt mir hier noch einiges an Detailwissen, doch sobald wie 
möglich, möchte ich das GATE Projekt von seinen bisherigen Projektdateien
entkoppeln und diese per &lt;code&gt;CMAKE&lt;/code&gt; generieren lassen.&lt;/p&gt;

&lt;h3 id=&quot;der-fall-libressl&quot;&gt;Der Fall libReSSL&lt;/h3&gt;

&lt;p&gt;Meine Dummheit bei der &lt;code&gt;libReSSL&lt;/code&gt; ärgert mich bis heute sehr. Denn
es dauerte einige Stunden, bis ich alle Dateien zusammengesucht
und manuell eingetragen hatte, und am Ende fehlten Makros und 
Variablen, die ich per Debugging schrittweise herausfinden musste.&lt;/p&gt;

&lt;p&gt;Alles stand bereits in der beigelegten &lt;code&gt;CMakeLists.txt&lt;/code&gt; drinnen
und das Erzeugen eines Visual Studio Projektes wäre eine Sache
von Minuten gewesen.&lt;/p&gt;

&lt;p&gt;… aber Nein, ich Depp sitze stundenlang herum und pflege diese
Daten per Hand.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;code&gt;CMAKE&lt;/code&gt; rulez!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Die &lt;code&gt;libReSSL&lt;/code&gt; Integration ins GATE Projekt war dagegen ein Kinderspiel,
denn &lt;code&gt;CMAKE&lt;/code&gt; erstellte mir die Projektdateien, die ich nur noch 
in die richtigen GATE-Verzeichnisse kopieren musste.&lt;/p&gt;

&lt;p&gt;Und so arbeitet das GATE Projekt bereits mit &lt;code&gt;CMAKE&lt;/code&gt; Resultaten, 
obwohl das Tool aktuell noch nicht vollständig ins Projekt integriert ist.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>IDE SSD HDDs: Moderne Festplatte für gestern</title>
   <link href="https://www.opengate.at/blog/2019/03/ide-ssd-hd/"/>
   <published>2019-03-31T19:41:00+02:00</published>
   <updated>2019-03-31T19:41:00+02:00</updated>
   <id>https://www.opengate.at/blog/2019/03/ide-ssd-hd</id>
   <category term="hardware" />
   <summary type="text">Mechanische Festplatten
haben einen Nachteil: Ihre Bauteile nutzen sich mechanisch ab. 
Das passiert natürlich bei allen Medien, aber bei durch Motoren angetriebenen
rotierenden Scheiben, geht gerne mal die Schmierung aus oder Wärme und Abrieb
führen zu Materialrissen.

Aus diesem Grund wird meine Sammlung an Festplatten für den alten 
ATAPI/IDE Bus langsam geringer.

Alle paar Jahre beim “Durchtesten” startet eine Platte weniger und 
neue Modelle werden heute kaum mehr produziert.

Also wie zur Hölle soll ich meinen 80486 
im Jahr 2030 noch betreiben?
</summary>
   <content type="html">&lt;p&gt;Mechanische &lt;a href=&quot;https://de.wikipedia.org/wiki/Festplattenlaufwerk&quot;&gt;Festplatten&lt;/a&gt;
haben einen Nachteil: Ihre Bauteile nutzen sich mechanisch ab. 
Das passiert natürlich bei allen Medien, aber bei durch Motoren angetriebenen
rotierenden Scheiben, geht gerne mal die Schmierung aus oder Wärme und Abrieb
führen zu Materialrissen.&lt;/p&gt;

&lt;p&gt;Aus diesem Grund wird meine Sammlung an Festplatten für den alten 
&lt;a href=&quot;https://de.wikipedia.org/wiki/ATA/ATAPI&quot;&gt;ATAPI/IDE&lt;/a&gt; Bus langsam geringer.&lt;/p&gt;

&lt;p&gt;Alle paar Jahre beim “Durchtesten” startet eine Platte weniger und 
neue Modelle werden heute kaum mehr produziert.&lt;/p&gt;

&lt;p&gt;Also wie zur Hölle soll ich meinen &lt;a href=&quot;https://de.wikipedia.org/wiki/Intel_80486&quot;&gt;80486&lt;/a&gt; 
im Jahr 2030 noch betreiben?
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Eine meiner letzten China-Bestellungen kam nach über einem Monat Wartezeit
endlich bei mir an um mich um Hardware zu bereichern, die in unseren Breiten
einfachen nicht zu kriegen war:&lt;/p&gt;

&lt;p&gt;Kleine &lt;a href=&quot;https://de.wikipedia.org/wiki/Solid-State-Drive&quot;&gt;SSD-Festplatten&lt;/a&gt; 
mit P-ATA IDE Anschluss.
&lt;img src=&quot;/blog/assets/img/ide-ssd-harddisk.jpg&quot; alt=&quot;IDE SSD&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Diese kleinen Teufelchen sehen wie Steckkarten bzw. alte 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Game_Boy_Advance&quot;&gt;Gameboy Advance&lt;/a&gt; 
Module aus und werden direkt in den IDE Port am Mainboard gesteckt 
und nicht wie klassische Festplatten per 40-poligem Kabel verbunden.&lt;/p&gt;

&lt;p&gt;Und damit ich meine alten Computer aus meiner Jugend auch noch weiter 
hin und wieder mal einschalten kann um in schönen Erinnerungen zu 
schwelgen, habe ich 4 Stück davon bestellt.&lt;/p&gt;

&lt;p&gt;256 MB und 512 MB für die 80486 Generation mit 
&lt;a href=&quot;https://de.wikipedia.org/wiki/MS-DOS&quot;&gt;DOS&lt;/a&gt;, 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_3.1&quot;&gt;Windows 3.X&lt;/a&gt;, und
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_95&quot;&gt;Windows 95&lt;/a&gt;.
Sowie einmal 2 GB und 4 GB für die Pentium-Familie (mit AMD und Cyrix).&lt;/p&gt;

&lt;p&gt;Das 2 GB Modul wurde natürlich sofort in den alten 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Cyrix_MediaGX&quot;&gt;Cyrix Media GX&lt;/a&gt; gesteckt,
der nun 10 Jahre regungslos in der Ecke stand … und siehe da, die alte
Socke startete hoch als wäre seit 1997 keine Woche vergangen.&lt;/p&gt;

&lt;p&gt;Wie damals üblich wurden 3 primäre Partitionen erstellt und dann
DOS mit Win 3.11, einmal Windows 95B und einmal NT 4 Workstation installiert.&lt;/p&gt;

&lt;p&gt;Tja … was soll ich sagen. Ich weiß, dass es heute keinen rationalen Sinn
ergibt, diese “Windows-Altlasten” wo zu installieren, doch einmal im Jahr 
erfreue ich mich eben an solchen Nostalgie-Installationen.&lt;/p&gt;

&lt;p&gt;Und mit den IDE-SSDs sollte wieder garantiert sein, dass diese Tradition
noch einige Jahre weiter aufrecht erhalten werden kann.&lt;/p&gt;

&lt;p&gt;Schließlich ist es eben doch was anderes eine “echte Maschine” hochzufahren,
als nur eine VM anzuwerfen.&lt;/p&gt;

&lt;p&gt;Alleine das Test-Geräusch des Disketten-Laufwerks beim Einschalten macht es 
den Aufwand wert.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Fazit: Die Hardware ist - so weit ich das bisher sagen kann - voll in Ordnung.
Das BIOS erkennt die eingesteckten Karten automatisch und auch die alten
Betriebssysteme machen keine Schwierigkeiten.&lt;/p&gt;

&lt;p&gt;Ich gebe aber zu, dass ich mir schnellere Reaktionszeiten erwartet habe und 
weiß nun nicht, ob entweder die IDE-SSDs etwas träge sind, oder ob der IDE Bus
den Flaschenhals darstellt.&lt;/p&gt;

&lt;p&gt;Tatsächlich werden wir heute von modernen SATA SSDs extrem verwöhnt, die 
5 GB große Betriebssysteme in wenigen Sekunden laden können … eine Leistung
die auch moderne Magnetscheiben-Festplatten nicht hinbekommen.&lt;br /&gt;
Da wirkt es etwas mühsam zu beobachten, dass Windows NT 4 mit einer Größe von
200 bis 300 MB trotz SSD länger zum Starten braucht als Windows 10.&lt;/p&gt;

&lt;p&gt;Daher heißt es heute einmal:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Früher war eben doch nicht alles besser .&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>Mein altes 56K Modem</title>
   <link href="https://www.opengate.at/blog/2019/03/56k-modem/"/>
   <published>2019-03-30T16:03:00+01:00</published>
   <updated>2019-03-30T16:03:00+01:00</updated>
   <id>https://www.opengate.at/blog/2019/03/56k-modem</id>
   <category term="hardware" /><category term="retro" />
   <summary type="text">Was fiel mir heute auf den großen Zeh, als ich im alten Zimmer meiner Jugend 
ein Regal umräumte?

Mein erster Weg ins Internet: Ein gebrauchtes 
56K-Modem.

Dieses Teil war über einen langen Zeitraum meine einzige Möglichkeit
gewesen, kleine Datenmengen aus dem Internet zu laden.
</summary>
   <content type="html">&lt;p&gt;Was fiel mir heute auf den großen Zeh, als ich im alten Zimmer meiner Jugend 
ein Regal umräumte?&lt;/p&gt;

&lt;p&gt;Mein erster Weg ins Internet: Ein gebrauchtes 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Modem&quot;&gt;56K-Modem&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Dieses Teil war über einen langen Zeitraum meine einzige Möglichkeit
gewesen, kleine Datenmengen aus dem Internet zu laden.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Ab dem Jahr 2001 bzw. 2002 startete mein “neueres” Leben in Wien mit 
einem Breitbandanschluss, doch was war in den Jahren zuvor?&lt;/p&gt;

&lt;p&gt;Tja, wenig, denn auf dem Land waren Telefonnetz-Modems die einzige
leistbare Methode, ins Internet zu kommen … und trotz ganz anderer
Werbeversprechungen kann ich eines beschwören: Ein “Surfen” gab es
nie, eher ein träges Schleichen.&lt;/p&gt;

&lt;p&gt;Bis vor wenigen Jahren wusste ich nicht, dass das lustige Geräusch,
das Modems beim Einwählen machten, in erster Linie der Störungsfindung
bzw. Entstörung der Sprachleitung dienten. So konnten die beiden 
verbundenen Geräte (also mein lokales Modem und die Gegenstelle des Anbieters)
feststellen, welche Frequenzen und Geschwindigkeiten besser oder schlechter
funktionierten.&lt;/p&gt;

&lt;p&gt;Das theoretische Übertragungsmaximum von 56 Kilobit, also 7 Kilobyte pro 
Sekunde konnte ich nie erreichen. Wenn mal ein Download mit durchschnittlich 
5 KB/s lief, war das schon ein Grund für Freudensprünge.&lt;/p&gt;

&lt;p&gt;Die überwiegende Zeit musste man sich mit 2 bis 3 KB/s “begnügen”, denn ein
“Vergnügen” war das nicht.&lt;/p&gt;

&lt;p&gt;Zwar waren Downloads von &lt;a href=&quot;http://programmersheaven.com/&quot;&gt;programmersheaven.com&lt;/a&gt;
selten größer als 50 bis 100 Kilobytes, doch damals waren Unterbrechungen 
eben auch keine Seltenheit. Und leider war Werbung in Webseiten auch damals 
schon weit verbreitet und deshalb durfte man oft mehrere Minuten waren, bis
eine Webseite überhaupt angezeigt wurde damit man endlich auf die
“Download-Pfeil-Grafik” klicken konnte.&lt;br /&gt;
Dann startete zwar der Download, musste sich aber die Leitung mit weiteren
HTTP-Requests teilen, die immer noch Grafiken der Webseite im Hintergrund
herunterluden.&lt;/p&gt;

&lt;p&gt;Immer wieder wurden Sockets einfach von der Gegenseite wegen zu vieler 
Serververbindungen geschlossen und somit hatte man von 100 KB nur 70 
erhalten und wieder 10 Minuten Lebenszeit verloren.&lt;/p&gt;

&lt;p&gt;Deshalb gehörte zu jedem Modem-Internet auch ein Download-Manager.
Denn die Webbrowser hatten das damals nicht implementiert
und ein abgebrochener Download wurde wie ein erfolgreicher im Cache
gehalten.&lt;br /&gt;
Ein weiterer Klick startete keinen neuen Download sondern lieferte
die zwischengespeicherten abgebrochene defekte Datei zurück&lt;br /&gt;
… echt super so etwas!&lt;/p&gt;

&lt;p&gt;Es dauerte tatsächlich bis ungefähr ins Jahr 2005, bis wir am Land 
in Richtung Breitband erste zaghafte Angebote vorfinden konnten.
Und deshalb war jedes Wochenende bei der Familie für mich 
internet-technisch eine Qual.&lt;/p&gt;

&lt;p&gt;Oft saß ich Freitag Abends lange vor dem PC um Updates, neue Browser
oder Treiber in Wien herunterzuladen um sie am Samstag “zu Mama’s PC”
mitnehmen zu können.&lt;/p&gt;

&lt;p&gt;Dort angekommen wurde eine 10 Meter Telefonkabelverlängerung quer durchs
Haus gespannt und der freie Stecker neben dem alten Post-Telefonapparat
mit dem Modem verbunden, damit man zumindest ein bisschen nachlesen konnte,
was in &lt;a href=&quot;https://de.wikipedia.org/wiki/Internetforum&quot;&gt;Webforen&lt;/a&gt;
tagsüber gepostet wurde.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Programmiertechnisch kam ich mit Modems nur gering in Berührung. 
Zwar weiß ich, dass die guten AT-Kommandos von ihnen abstammen, doch
eben genau diese Geräte habe ich nie damit ferngesteuert.&lt;/p&gt;

&lt;p&gt;Einzig eine Kundenanforderung zum Auslesen der eingerichteten Netzwerke
über &lt;a href=&quot;http://docs.microsoft.com/en-us/windows/desktop/WinInet/about-wininet&quot;&gt;WinINET&lt;/a&gt;
ließ mich unter Windows ein letztes Mal mit der alten Technologie in 
Berührung kommen.&lt;/p&gt;

&lt;p&gt;Und zwar handelte es sich dabei um 
&lt;a href=&quot;https://docs.microsoft.com/de-de/windows/desktop/WinInet/option-flags&quot;&gt;&lt;code&gt;InternetQueryOption&lt;/code&gt;&lt;/a&gt;
mit der Anfrage &lt;code&gt;INTERNET_OPTION_PER_CONNECTION_OPTION&lt;/code&gt; mit
welcher sich Proxy-Einstellungen von VPN- und Modem-Verbindungen auslesen 
lassen.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Heute ist das alles vorbei … und ich bin nicht sonderlich böse darüber.
Eine Zeit lang tarnten sich auch noch UMTS-Sticks mit Modem Interfaces und 
virtuellen seriellen Ports, doch auch diese Geräte werden heute mehr und mehr
als reine Netzwerkschnittstellen - also virtuelle LAN-Adapter - per speziellem
Treiber verkauft.&lt;/p&gt;

&lt;p&gt;Ein hörbares Einwählen wie damals gibt es gar nicht mehr, weil alle 
Übertragungsfrequenzen nicht im hörbaren Bereich angesiedelt sind.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Mein liebes und alt-verhasstes 56K-Modem. Lange hast du meinen Durst nach
Daten zu stillen versucht und mich dennoch nie vollends befriedigen können.
Ich danke dir für deine Geduld und verspreche dir, dich in Ehren zu halten.
Erfreue dich an deinem Rentner-Dasein und genieße auch Du die Stille
am heutigen Abend.&lt;br /&gt;
Tüt-tüt-tüt.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/56k-modem.jpg&quot; alt=&quot;56K Modem&quot; /&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>XML Implementierung</title>
   <link href="https://www.opengate.at/blog/2019/03/xml/"/>
   <published>2019-03-29T19:52:00+01:00</published>
   <updated>2019-03-29T19:52:00+01:00</updated>
   <id>https://www.opengate.at/blog/2019/03/xml</id>
   <category term="devel" />
   <summary type="text">Es ist mal wieder so weit, eine kleine 
XML 
Implementierung muss her.

Und wenn man nicht gerade 
Schemavalidierungen durchführen 
muss, dann ist so ein kleiner Parser
 schnell geschrieben.
</summary>
   <content type="html">&lt;p&gt;Es ist mal wieder so weit, eine kleine 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Extensible_Markup_Language&quot;&gt;XML&lt;/a&gt; 
Implementierung muss her.&lt;/p&gt;

&lt;p&gt;Und wenn man nicht gerade 
&lt;a href=&quot;https://de.wikipedia.org/wiki/XML_Schema&quot;&gt;Schemavalidierungen&lt;/a&gt; durchführen 
muss, dann ist so ein kleiner &lt;a href=&quot;https://de.wikipedia.org/wiki/Parser&quot;&gt;Parser&lt;/a&gt;
 schnell geschrieben.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;XML basiert ja auf Tags, die untergeordnete Tags enthalten können 
(aber nicht müssen).
Ein einfacher XML Parser kann also rekursiv aufgebaut sein, in dem
eine Funktion nur einen einzigen Tag-Knoten parst (von dessen Anfang
bis zu seinem Ende) und wenn darin untergeordnete Knoten enthalten 
sind, ruft sich die Funktion mit dem entsprechenden Sub-String selbst auf.&lt;/p&gt;

&lt;p&gt;Wichtig ist dabei, dass die Parser-Funktion zurückliefert, wie viele
Zeichen aus dem Sub-String sie für ihre Aufgabe bearbeitet hat, damit
die übergeordnete Funktion diese Menge überspringen kann.&lt;/p&gt;

&lt;p&gt;Wie geht man also vor?&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Alles fängt mit einem Kleinerzeichen &lt;code&gt;&amp;lt;&lt;/code&gt; an und dann darf man bis zum 
nächsten Größerzeichen &lt;code&gt;&amp;gt;&lt;/code&gt; wandern.
    &lt;ol&gt;
      &lt;li&gt;Zwischen den Tag-Begrenzern kann man zuerst den Tag-Namen bis zum ersten 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Leerraum&quot;&gt;Whitespace&lt;/a&gt; (oder Ende) auslesen.&lt;/li&gt;
      &lt;li&gt;Danach folgen die Attribute nachdem Schema &lt;code&gt;attribut-name=&quot;wert&quot;&lt;/code&gt;, wobei
die Attribut-Definitionen ebenso wieder durch Whitespaces getrennt sind.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;Endet das Tag mit einem Slash &lt;code&gt;/&amp;gt;&lt;/code&gt; gibt es keine Unterelemente und wir sind fertig.
(&lt;code&gt;return;&lt;/code&gt;)&lt;/li&gt;
  &lt;li&gt;Nun suchen wir das nächste Kleinerzeichen &lt;code&gt;&amp;lt;&lt;/code&gt;.
    &lt;ol&gt;
      &lt;li&gt;Folgt auf das Kleinerzeichen ein Slash &lt;code&gt;/&lt;/code&gt; und danach der Tag-Name, haben wir
das Ende des Tag-Blocks erreicht und sind fertig.
  (&lt;code&gt;return;&lt;/code&gt;)&lt;/li&gt;
      &lt;li&gt;Ist es ein neues Tag (ohne Slash ‘/’), ruft sich die Funktion mit dem Sub-String
ab der Position des neuen Tags auf.&lt;/li&gt;
      &lt;li&gt;Alle Zeichen zwischen dem Ende des Eltern-Tags und dem nächsten Tag sind
Textdaten.&lt;/li&gt;
      &lt;li&gt;Die aufgerufene Funktion übermittelt ihre bearbeiteten Zeichen im Sub-String.
Diese Zeichen werden dann in der laufenden Funktion übersprungen (da schon geparst)
und wir setzen wieder bei Punkt 3 fort.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Eigentlich war es das schon. Tag-Namen und Attribute werden natürlich nebenbei in
den finalen XML Objektbaum eingefügt.&lt;/p&gt;

&lt;p&gt;Ich nutze bei eigenen Implementierungen stets die Token aus dem originalen 
XML Dokument. Andere Bibliotheken machen es teils anders und sie führen sofort
die Konvertierung von XML-Entities durch, also das Umwandeln von 
&lt;code&gt;&amp;amp;amp;gt;&lt;/code&gt; in &lt;code&gt;&amp;gt;&lt;/code&gt; oder von &lt;code&gt;&amp;amp;amp;lt;&lt;/code&gt; in &lt;code&gt;&amp;lt;&lt;/code&gt; usw.&lt;/p&gt;

&lt;p&gt;Diesen Schritt mache ich immer erst, wenn auf das entsprechende Element 
zugegriffen wird. Denn so erreicht man, dass der Baum aus Substrings des 
Originals aufgebaut wird und im Falle von Reference-Counting keinen 
(oder nur wenig) Speicher frisst.&lt;/p&gt;

&lt;p&gt;Wenn man sofort konvertiert, muss man die Daten in neu allokierte Strings
schreiben und hat damit das XML Dokument doppelt im Speicher.&lt;/p&gt;

&lt;p&gt;Ich gebe aber zu, dass bei häufigen Zugriffen auf das gleiche Element meine
Methode zusätzliche Rechenzeit benötigt, da jedes mal aufs Neue ein temporärer
Ergebnis-String erzeugt werden muss.&lt;/p&gt;

&lt;p&gt;Alles läuft also auf die Frage &lt;em&gt;“Speed vs. Size”&lt;/em&gt; hinaus.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Natürlich gibt es dann noch ein paar Sonderfälle wie &lt;code&gt;?xml&lt;/code&gt;, 
&lt;code&gt;!DOCTYPE&lt;/code&gt; und &lt;code&gt;CDATA&lt;/code&gt; Elemente, oder Kommentare nach dem Schema 
&lt;code&gt;&amp;lt;!--&lt;/code&gt; nach &lt;code&gt;--&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Doch im Grunde genommen haben wir so einen primitiven Parser in purem
C bzw. C++, der wenig Speicher braucht und universell portierbar ist.&lt;/p&gt;

&lt;p&gt;Große Bibliotheken schaffen natürlich viel mehr und gehen auf viele
Zusatzdetails von XML ein, wie das dynamische Definieren von 
&lt;a href=&quot;https://en.wikipedia.org/wiki/List_of_XML_and_HTML_character_entity_references&quot;&gt;Entities&lt;/a&gt;, 
die beim Parsen durch andere Inhalte ausgetauscht werden und
vieles mehr.&lt;/p&gt;

&lt;p&gt;Doch die Mehrzahl von Projekten, die XML einsetzen nutzen diese
Features nicht und schreiben ihre Daten nach fixen Vorgaben.
Und dafür reicht dieser minimalistische Ansatz aus.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Wincrypt und libReSSL: Von SSL bis TLS</title>
   <link href="https://www.opengate.at/blog/2019/03/ssl/"/>
   <published>2019-03-28T21:19:00+01:00</published>
   <updated>2019-03-28T21:19:00+01:00</updated>
   <id>https://www.opengate.at/blog/2019/03/ssl</id>
   <category term="devel" />
   <summary type="text">Eigentlich ist es recht einfach einen 
HTTP/1 Client zu 
schreiben. Wenn man auf Features wie Proxies oder Keep-Alive verzichten kann, öffnet man
einfach einen Port, schickt seine GET-Zeile und eine Leerzeile, wartet auf
die Antwort, liest den Header bis zur Leerzeile und dahinter liegen die 
Download-Daten, super, fertig.

Blöd nur, dass heute fast alles über HTTPS, also über einen 
SSL/TLS Tunnel,
verschlüsselt übertragen wird.

… und das implementiert man selbst nicht ganz so einfach.
Dafür braucht man Hilfe.
</summary>
   <content type="html">&lt;p&gt;Eigentlich ist es recht einfach einen 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Hypertext_Transfer_Protocol&quot;&gt;HTTP/1&lt;/a&gt; Client zu 
schreiben. Wenn man auf Features wie Proxies oder Keep-Alive verzichten kann, öffnet man
einfach einen Port, schickt seine GET-Zeile und eine Leerzeile, wartet auf
die Antwort, liest den Header bis zur Leerzeile und dahinter liegen die 
Download-Daten, super, fertig.&lt;/p&gt;

&lt;p&gt;Blöd nur, dass heute fast alles über HTTPS, also über einen 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Transport_Layer_Security&quot;&gt;SSL/TLS&lt;/a&gt; Tunnel,
verschlüsselt übertragen wird.&lt;/p&gt;

&lt;p&gt;… und das implementiert man selbst nicht ganz so einfach.
Dafür braucht man Hilfe.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Jetzt gibt es heute zum Glück einige Bibliotheken die einem das Thema 
Verschlüsselung abnehmen. Doch in kommerziellen Projekte stößt man gerne
auf die Auflage keinen &lt;a href=&quot;https://de.wikipedia.org/wiki/Copyleft&quot;&gt;Copyleft&lt;/a&gt;
&lt;a href=&quot;https://de.wikipedia.org/wiki/Open_Source&quot;&gt;OpenSource&lt;/a&gt; Code einzusetzen.&lt;/p&gt;

&lt;p&gt;Unter &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows&quot;&gt;Windows&lt;/a&gt; 
darf man sich dann mit der 
&lt;a href=&quot;http://docs.microsoft.com/en-us/windows/desktop/api/wincrypt/&quot;&gt;Windows Crypto-API&lt;/a&gt; 
herumschlagen.&lt;br /&gt;
Und wenn ein &lt;a href=&quot;https://de.wikipedia.org/wiki/Portable_Operating_System_Interface&quot;&gt;POSIX&lt;/a&gt; 
OS erlaubt ist, so greife ich stets zu &lt;a href=&quot;http://www.libressl.org/&quot;&gt;libReSSL&lt;/a&gt;, 
dem aufgeräumten Fork des älteren &lt;a href=&quot;http://www.openssl.org/&quot;&gt;OpenSSL&lt;/a&gt; Projektes.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Nur zur Erinnerung:&lt;/em&gt;&lt;br /&gt;
Es begann alles mit dem Titel “Secure Socket Layer”, kurz SSL, wovon es 
eine Version 1 und 2 gab, die schnell wieder fallen gelassen wurden, weil 
Unsicherheiten darin auftraten. SSL 3 hielt sich recht lange und kurz 
danach kam gleich SSL 3.1, was in TLS (Transport Layer Security) 1.0
umbenannt wurde.&lt;br /&gt;
Unter dem Namen TLS wurde die Technologie dann ausgebaut und erweitert und
im Jahr 2018 wurde mit TLS 1.3 der bisher neueste Stand erreicht.&lt;br /&gt;
Sicherheitsprobleme bei SSL 3, die ebenso in den letzten Jahren erkannt
wurden, führten dazu, dass SSL 3 heute auf allen Servern deaktiviert wurde 
und heute praktisch nichts mehr unterhalb von TLS 1.2 genutzt wird.&lt;/p&gt;

&lt;p&gt;… soviel zur Geschichte.&lt;/p&gt;

&lt;h3 id=&quot;wincrypt&quot;&gt;WinCrypt&lt;/h3&gt;

&lt;p&gt;Das ärgerliche an der Crypto-API ist ihr generischer Ansatz, der eigentlich
super wäre, wenn sie nur besser dokumentiert wäre. Daher dauerte es 
bei mir eine Ewigkeit, bis ich endlich herausgefunden hatte, wie man SSL/TLS
Verbindungen darüber implementieren kann.&lt;/p&gt;

&lt;p&gt;Hier mal mein Weg für einfache SSL Clients in Kurzfassung:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;SCHANNEL_CRED&lt;/code&gt; mit &lt;code&gt;SCHANNEL_CRED_VERSION&lt;/code&gt; und den Flags
&lt;code&gt;SCH_CRED_NO_DEFAULT_CREDS | SCH_CRED_NO_SYSTEM_MAPPER | SCH_CRED_REVOCATION_CHECK_CHAIN&lt;/code&gt;
erzeugen.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://docs.microsoft.com/en-us/windows/desktop/api/sspi/nf-sspi-acquirecredentialshandlew&quot;&gt;&lt;code&gt;AcquireCredentialsHandle&lt;/code&gt;(0, SCHANNEL_NAME, SECPKG_CRED_OUTBOUND, 0, &amp;amp;SCHANNEL_CRED, NULL, NULL, &amp;amp;cred_handle, NULL)&lt;/a&gt;
erzeugt uns ein Handle mit dem wir weiterarbeiten können&lt;/li&gt;
  &lt;li&gt;Jetzt müssen so lange Daten ausgetauscht werden bis ein sicherer 
Verbindungskanal ausgehandelt ist
    &lt;ul&gt;
      &lt;li&gt;Zuerst halten wir uns ein paar Flags bereit, nämlich:
&lt;code&gt;ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT | ISC_REQ_CONFIDENTIALITY &lt;/code&gt;
` | ISC_RET_EXTENDED_ERROR | ISC_REQ_ALLOCATE_MEMORY | ISC_REQ_STREAM `
` | ISC_REQ_MANUAL_CRED_VALIDATION`&lt;/li&gt;
      &lt;li&gt;Wir brauchen einen SecBuffer mit Typ &lt;code&gt;SECBUFFER_TOKEN&lt;/code&gt;
und einen SecBufferDesc mit der Version &lt;code&gt;SECBUFFER_VERSION&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;Anfangs wird &lt;a href=&quot;http://docs.microsoft.com/en-us/windows/desktop/api/sspi/nf-sspi-initializesecuritycontextw&quot;&gt;&lt;code&gt;InitializeSecurityContext(NULL, NULL, flags, 0, 0, NULL, 0, &amp;amp;ctx, &amp;amp;sec_buffer_desc, &amp;amp;out_flags, 0)&lt;/code&gt;&lt;/a&gt;
aufgerufen, so lange bis &lt;code&gt;SEC_E_INCOMPLETE_MESSAGE&lt;/code&gt; zurückkommt.&lt;/li&gt;
      &lt;li&gt;Nach jedem Aufruf muss der Inhalt des SecBuffer zur Gegenseite geschickt werden.&lt;/li&gt;
      &lt;li&gt;Bei &lt;code&gt;ERROR_SUCCESS&lt;/code&gt; anstatt von &lt;code&gt;SEC_E_INCOMPLETE_MESSAGE&lt;/code&gt; kommt,&lt;br /&gt;
gilt die Verbindung als hergestellt und nutzbar.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Zum Senden von Daten nutzt man:
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;http://docs.microsoft.com/en-us/windows/desktop/api/sspi/nf-sspi-querycontextattributesw&quot;&gt;&lt;code&gt;QueryContextAttributes(&amp;amp;hctxt, SECPKG_ATTR_STREAM_SIZES, &amp;amp;spc_stream_sizes)&lt;/code&gt;&lt;/a&gt;
zur Feststellung von Puffergrößen&lt;/li&gt;
      &lt;li&gt;Befüllt 4 SecBuffer mit den Typen &lt;code&gt;SECBUFFER_STREAM_HEADER&lt;/code&gt;, &lt;code&gt;SECBUFFER_DATA&lt;/code&gt;,
&lt;code&gt;SECBUFFER_STREAM_TRAILER&lt;/code&gt; und &lt;code&gt;SECBUFFER_EMPTY&lt;/code&gt; und ruft
&lt;a href=&quot;http://docs.microsoft.com/en-us/windows/desktop/api/sspi/nf-sspi-encryptmessage&quot;&gt;&lt;code&gt;EncryptMessage&lt;/code&gt;&lt;/a&gt;
mit einem SecBufferDesc zu den 4 Puffern auf.&lt;/li&gt;
      &lt;li&gt;Am Ende werden die Daten des Header, Data und Trailer Puffers hintereinander
zur Gegenseite gesendet.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Empfangene Daten werden durch die API dekodiert, indem:
    &lt;ul&gt;
      &lt;li&gt;&lt;code&gt;QueryContextAttributes(.., SECPKG_ATTR_STREAM_SIZES, ..)&lt;/code&gt; die Puffergrößen feststellt.&lt;/li&gt;
      &lt;li&gt;4 SecBuffer als &lt;code&gt;SECBUFFER_DATA&lt;/code&gt; und 3 mal &lt;code&gt;SECBUFFER_EMPTY&lt;/code&gt; angelegt&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;http://docs.microsoft.com/en-us/windows/desktop/api/sspi/nf-sspi-decryptmessage&quot;&gt;&lt;code&gt;DecryptMessage&lt;/code&gt;&lt;/a&gt;
den SecBufferDesc mit den 4 Puffern dekodiert.&lt;/li&gt;
      &lt;li&gt;Nach dem Aufruf werden der Puffer mit dem Typ &lt;code&gt;SECBUFFER_DATA&lt;/code&gt; mit den Nutzdaten 
zurückgegeben, während Puffer mit dem Typ &lt;code&gt;SECBUFFER_EXTRA&lt;/code&gt; bei der 
nächsten Sendeaktion vorangestellt werden müssen.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;openssl-und-libressl&quot;&gt;OpenSSL und libReSSL&lt;/h3&gt;

&lt;p&gt;Die OpenSSL API, die auch in der libReSSL verfügbar ist, erlaubt die direkte Nutzung
von Sockets, doch diese Variante gefällt mir nicht, da man die Kommunikationsschicht 
nicht unter Kontrolle hat und sie nicht in bestehende Kommunikationshandler 
integrieren kann.&lt;/p&gt;

&lt;p&gt;Daher gehe ich den Weg über Memorystream-Datenpuffer. Die SSL/TLS Schicht 
liest und schreibt ihre Daten in diese Puffer, und wir können sie dann
an die gewünschte Kommunikationsschicht (z.B.: TCP/IP) weiterreichen.&lt;/p&gt;

&lt;p&gt;Diese Methode hilft vor allem bei der Implementierung von asynchroner
Kommunikation.&lt;br /&gt;
Und sie funktioniert so:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;context =&lt;/code&gt; &lt;a href=&quot;http://www.openssl.org/docs/man1.0.2/man3/SSL_CTX_new.html&quot;&gt;&lt;code&gt;SSL_CTX_new(...)&lt;/code&gt;&lt;/a&gt; 
mit &lt;code&gt;SSLv23_client_method()&lt;/code&gt; oder &lt;code&gt;TLS_client_method()&lt;/code&gt;
aufrufen um ein Kontext Objekt zu erstellen.
    &lt;ul&gt;
      &lt;li&gt;SSLv23 hat einen heute etwas irreführenden Namen, es steht für das 
Aushandeln der bestmöglichen Verbindung. Mit aktuellen Versionen der 
Bibliothek stehen SSL2 und SSL3 gar nicht mehr zur Verfügung, 
sondern wir starten bei TLS 1.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code&gt;session =&lt;/code&gt; &lt;a href=&quot;http://www.openssl.org/docs/manmaster/man3/SSL_new.html&quot;&gt;&lt;code&gt;SSL_new(context)&lt;/code&gt;&lt;/a&gt;
erzeugt mit dem Kontext eine SSL Session.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://linux.die.net/man/3/ssl_set_connect_state&quot;&gt;&lt;code&gt;SSL_set_connect_state(session)&lt;/code&gt;&lt;/a&gt; 
versetzt die Session in den Client-Modus.&lt;/li&gt;
  &lt;li&gt;Nun erzeugen wir zwei Puffer, einen für zu sendende Daten und einen 
wo empfangene Daten angefügt werden, und zwar mit:
&lt;code&gt;send_buffer =&lt;/code&gt; &lt;a href=&quot;http://www.openssl.org/docs/manmaster/man3/BIO_new.html&quot;&gt;&lt;code&gt;BIO_new(BIO_s_mem());&lt;/code&gt;&lt;/a&gt; 
und &lt;code&gt;receive_buffer = BIO_new(BIO_s_mem());&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;SSL_set_bio(session, receive_buffer, send_buffer)&lt;/code&gt; registriert die beiden
Puffer im Session Objekt.&lt;/li&gt;
  &lt;li&gt;Bis &lt;a href=&quot;http://www.openssl.org/docs/man1.0.2/man3/SSL_set_bio.html&quot;&gt;&lt;code&gt;SSL_state(session)&lt;/code&gt;&lt;/a&gt; 
den Wert &lt;code&gt;SSL_ST_OK&lt;/code&gt; erreicht, muss der 
Handshake-Prozess durchgeführt werden.
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;http://www.openssl.org/docs/manmaster/man3/SSL_do_handshake.html&quot;&gt;&lt;code&gt;SSL_do_handshake(session)&lt;/code&gt;&lt;/a&gt; 
wird aufgerufen während parallel die lokal generierten Daten aus dem 
Sende-Puffer abgeholt und verschickt werden und die vom Server empfangenen
Daten in den Empfangspuffer eingepflegt werden.&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;http://www.openssl.org/docs/man1.0.2/man3/BIO_write.html&quot;&gt;&lt;code&gt;BIO_write(receive_buffer, received_data, received_data_length)&lt;/code&gt;&lt;/a&gt;
erledigt das Empfangen&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;http://www.openssl.org/docs/man1.0.2/man3/BIO_read.html&quot;&gt;&lt;code&gt;BIO_read(send_buffer, output_data, ...)&lt;/code&gt;&lt;/a&gt;
ist für das Extrahieren der zu sendenden Daten zuständig.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Ist die Session aufgebaut, können Daten mit 
&lt;a href=&quot;http://www.openssl.org/docs/man1.0.2/man3/SSL_write.html&quot;&gt;&lt;code&gt;SSL_write(session, data_to_encrypt, data_length)&lt;/code&gt;&lt;/a&gt;
verschlüsselt werden und das Resultat mit &lt;code&gt;BIO_read(send_buffer, ...)&lt;/code&gt; 
zum Versenden extrahiert werden.&lt;/li&gt;
  &lt;li&gt;Parallel werden empfangene Daten mit &lt;code&gt;BIO_write(receive_buffer, ...)&lt;/code&gt;
zur Dekodierung weitergereicht und mit 
&lt;a href=&quot;http://www.openssl.org/docs/man1.0.2/man3/SSL_read.html&quot;&gt;&lt;code&gt;SSL_read(session, decrypted_data, data_length)&lt;/code&gt;&lt;/a&gt;
final ausgelesen.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Puh, jetzt wurde fast ein kleines Tutorial aus meinem jüngsten SSL API Ausflug.
Natürlich fehlt noch einiges zum Thema “Zertifikate gezielt einsetzen”.
Aber wer sich nur für die Verschlüsselung und nicht für die Authentifizierung
der Verbindung interessiert, der kann damit schon einen kleinen Client 
schreiben.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>FTP - Der unsterbliche Leiche</title>
   <link href="https://www.opengate.at/blog/2019/03/ftp/"/>
   <published>2019-03-27T20:07:00+01:00</published>
   <updated>2019-03-27T20:07:00+01:00</updated>
   <id>https://www.opengate.at/blog/2019/03/ftp</id>
   <category term="software" />
   <summary type="text">Als mir im Jahr 2000 mein “erster” fester Internetprovider eine Warnung
wegen der Verletzung der Nutzungsbestimmungen zusandte, war der Grund ein
FTP Server.

Denn im Vertrag stand tatsächlich, dass der Zugang nur für TCP Clientdienste
bestimmt war und das Hochfahren eines beliebigen Servers wie HTTP oder FTP
war zwar technisch möglich, doch der Provider überwachte die eingehenden 
Transmissionen und ermahnte seine Kunden daraufhin.

Das war dann eigentlich schon der erste und letzte Moment, wo ich einen
FTP Server zu Hause in Betrieb hatte …
</summary>
   <content type="html">&lt;p&gt;Als mir im Jahr 2000 mein “erster” fester Internetprovider eine Warnung
wegen der Verletzung der Nutzungsbestimmungen zusandte, war der Grund ein
&lt;a href=&quot;https://de.wikipedia.org/wiki/File_Transfer_Protocol&quot;&gt;FTP&lt;/a&gt; Server.&lt;/p&gt;

&lt;p&gt;Denn im Vertrag stand tatsächlich, dass der Zugang nur für TCP Clientdienste
bestimmt war und das Hochfahren eines beliebigen Servers wie HTTP oder FTP
war zwar technisch möglich, doch der Provider überwachte die eingehenden 
Transmissionen und ermahnte seine Kunden daraufhin.&lt;/p&gt;

&lt;p&gt;Das war dann eigentlich schon der erste und letzte Moment, wo ich einen
FTP Server zu Hause in Betrieb hatte …
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Anders sah es allerdings im Internet aus. Denn der Wechsel von
FTP zu &lt;a href=&quot;https://de.wikipedia.org/wiki/Hypertext_Transfer_Protocol&quot;&gt;HTTP&lt;/a&gt; 
und anderen Dateiserver-Diensten wurde erst langsam zwischen 
2000 bis 2010 vollzogen. Und auch heute ist dieses schreckliche Uraltprotokoll
nicht tot zu kriegen.&lt;/p&gt;

&lt;p&gt;Das ursprüngliche FTP ist deshalb so unglaublich umständlich, weil in der
Zeit seiner Entwicklung zwei Kriterien galten:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Jeder vertraut jedem blind&lt;/li&gt;
  &lt;li&gt;Jeder hängt direkt mit einer fixen IP am Internet&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Und deshalb kamen die Macher auf die Idee, dass neue eingehende Verbindungen
des TCP Server-Sockets nur für Kontrollnachrichten zuständig sind. Man kann 
sich also mit Benutzernamen und Passwort anmelden, sich Verzeichnisinhalte 
ansehen und Downloads und Uploads vorbereiten.&lt;/p&gt;

&lt;p&gt;Doch für den eigentlich Download bzw. Upload wird eine weitere Verbindungen
auf einem anderen Port aufgebaut und darüber fließen die Bits des Inhalts.&lt;/p&gt;

&lt;p&gt;Das schlimmste daran ist, dass neben dem Problem des Betriebs von mehreren
Ports auch noch das Server-Client Prinzip umgedreht wird. Denn für den
Verbindungsaufbau ist der “Konsument” der Client und der “Bereitsteller” der
Server, so wie man es erwartet.&lt;br /&gt;
Doch beim Download muss der “Konsument” einen dynamischen TCP-Server hochfahren
und der “Bereitsteller” verbindet sich als Client zu diesem um ihm seine 
Daten zu senden.&lt;/p&gt;

&lt;p&gt;Das ist ein Alptraum für Administratoren, die 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Firewall&quot;&gt;Firewalls&lt;/a&gt; warten müssen, denn statt 
einem einzigen Serverport müssen nun ganze Port-Bereiche freigegeben werden, 
die zufällig mal benutzt werden und dann wieder nicht.&lt;br /&gt;
Und nachdem der Client ebenso als Server funktioniert, muss auch seine Firewall
das Öffnen eines Portbereiches unterstützen.&lt;/p&gt;

&lt;p&gt;Diesem zweiten Punkt wurde mit 
&lt;a href=&quot;https://de.wikipedia.org/wiki/File_Transfer_Protocol#Passives_FTP&quot;&gt;Passiven FTP&lt;/a&gt;
entgegengearbeitet, bei dem nur der FTP-Server mehrere TCP-Server betreibt 
und der Client auch immer nur Client-Verbindungen initiiert anstatt selbst 
zum TCP-Server zu werden.&lt;/p&gt;

&lt;p&gt;Nicht zu vergessen sei, dass der FTP-Server immer seine öffentliche 
Internetadresse kennen muss, denn im Protokoll muss der Gegenseite mitgeteilt
werden, auf welchen anderen Port auf welcher IP sie sich für Up- und Downloads
verbinden soll.&lt;br /&gt;
Und ist die interne IP des Servers nicht gleich der externen, dann muss dies 
von Hand im Server konfiguriert sein. Besonders dumm ist, wenn sich die 
öffentliche IP (z.B. durch Einwahlnetze) ändert.&lt;/p&gt;

&lt;p&gt;Wie auch immer, viele Daten wie Treiber oder Betriebssystem-Images liegen 
auch heute immer noch auf FTP Servern. Und auch bei IT-Lösungen für Kunden,
wo man Daten austauschen muss, wird schnell ein FTP-Server bereitgestellt,
weil dieser “schnell” aufgesetzt ist und Clients weit verbreitet sind.&lt;br /&gt;
Natürlich geht das schnell, denn wegen fehlender Sicherheitsfunktionen reicht
es einfach einen Account anzulegen und ihm ein Verzeichnis zuzuordnen.
Dann schaltet man noch die Firewall für den FTP-Port 21 und die 
Übertragungs-Port-Range ab (z.B.: Ports 13000 bis 14000, tausend gleichzeitige
Verbindungen sind mehr als ausreichend für kleine Projekte), und man ist 
fertig.&lt;/p&gt;

&lt;p&gt;In der Programmierung nutzte ich ganz analog zu HTTP immer 
&lt;a href=&quot;http://docs.microsoft.com/en-us/windows/desktop/wininet/about-wininet&quot;&gt;WinINET&lt;/a&gt; 
unter Windows und die &lt;a href=&quot;http://curl.haxx.se/libcurl/&quot;&gt;libCURL&lt;/a&gt; unter 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt; bzw. 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Portable_Operating_System_Interface&quot;&gt;POSIX&lt;/a&gt; 
Systemen um FTP Clients zu implementieren.&lt;/p&gt;

&lt;h3 id=&quot;wininet&quot;&gt;WinINET&lt;/h3&gt;

&lt;p&gt;WinINET stellt uns neben seinen generischen Funktionen für alle Protokolle
einige FTP-spezifische zur Verfügung, wie z.B.:
&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/desktop/api/Wininet/nf-wininet-ftpfindfirstfilew&quot;&gt;FtpFindFirstFile&lt;/a&gt;
um Dateien aufzulisten oder 
&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/desktop/api/wininet/nf-wininet-ftpcreatedirectoryw&quot;&gt;FtpCreateDirectory&lt;/a&gt;
um Unterverzeichnisse anzulegen.
Ansonsten funktioniert der Nutzung genau so wie für HTTP.&lt;/p&gt;

&lt;h3 id=&quot;libcurl&quot;&gt;libCURL&lt;/h3&gt;

&lt;p&gt;Bei der libCURL ist das leider nicht so, dass es für Verzeichnisoperationen
eigene APIs gibt, womit nur Up- und Downloads von im Vorhinein bekannten 
Pfaden “leicht” zu implementieren sind. Das Lesen eines Verzeichnisses führt 
zu einem Text-Stream, der geparst werden muss und das ist kein Zuckerschlecken, 
da jeder FTP-Server seinen eigenen Ausgabestandard wählt. Sie sind zwar 
ähnlich zueinander, aber eben nicht identisch.&lt;/p&gt;

&lt;p&gt;CURL lässt uns aber native Kommandos für das Protokoll injizieren und so können
wir das Kommando &lt;code&gt;MLST&lt;/code&gt; für standardisierte Verzeichniseinträge nutzen,
oder &lt;code&gt;MKD&lt;/code&gt; um Unterverzeichnisse anzulegen.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Aber Vorsicht!&lt;/strong&gt; Ich musste einst lange mit einer Implementierung kämpfen,
da es FTP-Server gibt, die keine absoluten Pfade verkraften. Die libCURL
wechselt daher immer (im Hintergrund) in das angenommene Zielverzeichnis
und dort muss dann der relative Pfad und nicht der absolute genutzt werden,
weil sich der Server ansonsten den übergebenen absoluten Pfad an seinen
aktuelles “Working-Directory” anhängt und das Ergebnis dann ein ganz anderes
(nicht existierendes= Verzeichnis ist.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;FTP ist wegen seiner Unsicherheit und Server-Client-Port-Murxerei und dann
noch wegen seiner unterschiedlichen Implementierungen ein einziger Graus.
Wer Dateien sicher übertragen will, sollte 
&lt;a href=&quot;https://de.wikipedia.org/wiki/SSH_File_Transfer_Protocol&quot;&gt;SFTP&lt;/a&gt; von 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Secure_Shell&quot;&gt;SSH&lt;/a&gt; benutzen, oder per 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Virtual_Private_Network&quot;&gt;VPN&lt;/a&gt; einen sicheren 
Tunnel nutzen um dann per SMB fortzufahren.&lt;/p&gt;

&lt;p&gt;Eigentlich könnte HTTP das alte FTP vollkommen ablösen, denn mit der 
&lt;a href=&quot;https://de.wikipedia.org/wiki/WebDAV&quot;&gt;WebDAV&lt;/a&gt; Erweiterung existiert für HTTP 
ein Standard um ebenso Verzeichnisse maschinell auszulesen und somit ein 
Dateisystem abzubilden (was im klassischen HTTP leider fehlt).&lt;/p&gt;

&lt;p&gt;Doch … wie wir wissen, bleiben solche Altlasten auf unbestimmte Zeit 
aktiv, und so werde ich wohl noch meine letzten Atemzüge vor Programmen
wie &lt;a href=&quot;https://de.wikipedia.org/wiki/FileZilla&quot;&gt;FileZilla&lt;/a&gt; verbringen, 
über welche ich meinen letzten Blog-Post per FTP zum Webserver übertrage.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Memory leaks: Ein Leck im Speicher</title>
   <link href="https://www.opengate.at/blog/2019/03/leaks/"/>
   <published>2019-03-26T21:50:00+01:00</published>
   <updated>2019-03-26T21:50:00+01:00</updated>
   <id>https://www.opengate.at/blog/2019/03/leaks</id>
   <category term="devel" /><category term="software" />
   <summary type="text">Gerade beim Aufbau von elementaren Datenstrukturen wie 
Arrays, 
Listen, Mappings oder 
Bäumen ist das Thema
Speicherverwaltung vorherrschend.

Denn schnell übersieht man einen Pointer, dessen Ziel nicht freigegeben
und “vergessen” wird. Bis zum Ende des Prozesses ist dieser Speicher verloren.

Gibt es also ein Fundbüro für diese verlorenen Datenblöcke?
</summary>
   <content type="html">&lt;p&gt;Gerade beim Aufbau von elementaren Datenstrukturen wie 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Feld_(Datentyp)&quot;&gt;Arrays&lt;/a&gt;, 
Listen, Mappings oder 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Bin%C3%A4rer_Suchbaum&quot;&gt;Bäumen&lt;/a&gt; ist das Thema
Speicherverwaltung vorherrschend.&lt;/p&gt;

&lt;p&gt;Denn schnell übersieht man einen Pointer, dessen Ziel nicht freigegeben
und “vergessen” wird. Bis zum Ende des Prozesses ist dieser Speicher verloren.&lt;/p&gt;

&lt;p&gt;Gibt es also ein Fundbüro für diese verlorenen Datenblöcke?
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Ja! Und diese heißen &lt;strong&gt;Memory-Leak-Detektoren&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In &lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_Studio&quot;&gt;Microsoft’s Visual Studio&lt;/a&gt; 
ist seit langem ein solcher Detektor im Debug-Modus enthalten. Genutzt werden 
kann er durch den Header &lt;code&gt;&amp;lt;crtdbg.h&amp;gt;&lt;/code&gt; und durch den Aufruf der Funktion 
&lt;a href=&quot;http://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/crtsetdbgflag?view=vs-2019&quot;&gt;&lt;code&gt;_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );&lt;/code&gt;&lt;/a&gt;
am Programmstart wird beim Ende automatisch ein Leak-Report der
C-Runtime im Debug-Output-Fenster ausgegeben.&lt;/p&gt;

&lt;p&gt;Eine wirkliche Hilfe ist das allerdings meist nicht, den die CRT 
kennt nur durch &lt;a href=&quot;http://www.cplusplus.com/reference/cstdlib/malloc/&quot;&gt;&lt;code&gt;malloc()&lt;/code&gt;&lt;/a&gt; 
(und &lt;a href=&quot;http://www.cplusplus.com/reference/new/operator%20new/&quot;&gt;&lt;code&gt;new&lt;/code&gt;&lt;/a&gt;) 
allokierte Bereiche, die noch nicht freigegeben wurden. Und man kann im besten
Fall nur die Codezeile zurückverfolgen, wo der &lt;code&gt;malloc()&lt;/code&gt; (oder der &lt;code&gt;new&lt;/code&gt;) 
Aufruf platziert wurde.&lt;/p&gt;

&lt;p&gt;Bei Bibliotheken hilft das nicht, weil der “Auftraggeber” wo anders
sitzt.&lt;/p&gt;

&lt;h3 id=&quot;visual-leak-detector&quot;&gt;Visual Leak Detector&lt;/h3&gt;

&lt;p&gt;Der &lt;a href=&quot;http://marketplace.visualstudio.com/items?itemName=ArkadyShapkin.VisualLeakDetectorforVisualC&quot;&gt;Visual Leak Detector&lt;/a&gt;
löst dieses Problem kostenlos, indem er zu jeder nicht freigegebenen
Allokation den &lt;a href=&quot;https://de.wikipedia.org/wiki/Aufrufstapel&quot;&gt;Callstack&lt;/a&gt; 
mitspeichert und beim Leak-Report am Ende ausgibt. So kann man 
zurückverfolgen, welche Funktionshierarchie für die Anforderung des 
Speichers verantwortlich war und programmatisch dagegen vorgehen.&lt;/p&gt;

&lt;p&gt;Seit über 10 Jahren ist der &lt;em&gt;VLD&lt;/em&gt; bei mir ein fester Bestandteil in der 
Windows und &lt;code&gt;MSVC&lt;/code&gt; Entwicklung. Er wurde mehrmals weiterentwickelt und klinkt 
sich inzwischen in die meisten anderen Allokationsroutinen ein, die parallel
zur C-Runtime eigene Heaps benutzen und kann somit auch diese Überwachen.&lt;/p&gt;

&lt;h3 id=&quot;address-sanitizer&quot;&gt;Address Sanitizer&lt;/h3&gt;

&lt;p&gt;Für Linux empfahl mir ein guter Kollege einst die Einbindung von 
&lt;a href=&quot;https://en.wikipedia.org/wiki/AddressSanitizer&quot;&gt;libASAN&lt;/a&gt;. Und seit ich diesem
genialen Vorschlag gefolgt bin, kann ich mir das Leben ohne diese Tool
ebenso nicht mehr vorstellen.&lt;/p&gt;

&lt;p&gt;Wenn man nämlich sein Programm mit der Option &lt;code&gt;-fsanitize=address&lt;/code&gt; kompiliert,
wird einiges an Instrumentations-Code eingebaut. Läuft das Programm, wird bei
dessen Beendigung ebenso eine Zusammenfassung auf die Konsole geschrieben,
die von Speicherlecks bis Array-Überläufe vieles meldet.&lt;/p&gt;

&lt;p&gt;Feineinstellen kann man den Sanitizer über 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Umgebungsvariable&quot;&gt;Environment-Variablen&lt;/a&gt;, denn
&lt;code&gt;LSAN_OPTIONS&lt;/code&gt; kann Einstellungen zur Leak-Erkennung beinhalten, wie z.B.:&lt;br /&gt;
&lt;code&gt;ASAN_OPTIONS=verbosity=1:malloc_context_size=20&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;So lassen sich einzelne Features ein- bzw. ausschalten, oder deren Genauigkeit
verändern.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ohne Leak-Detektoren gibt es kein Release!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Leaks können immer auftreten und deren Bekämpfung hat hohe Priorität.
Von daher sollte auf jeder Plattform eine Möglichkeit zur Leak-Erkennung
und -Bekämpfung eingesetzt werden.&lt;/p&gt;

&lt;p&gt;Natürlich gibt es noch einige andere Produkte, die eine solche Fehlersuche
erleichtern. &lt;a href=&quot;https://de.wikipedia.org/wiki/Valgrind&quot;&gt;Valgrind&lt;/a&gt; kennen sicher
viele Linuxianer. Und vor langer Zeit setzte ich beruflich 
&lt;a href=&quot;https://en.wikipedia.org/wiki/BoundsChecker&quot;&gt;BoundsChecker&lt;/a&gt; unter Windows ein.&lt;br /&gt;
Doch inzwischen habe ich festgestellt, dass die beiden genannten 
Gratis-Tools eigentlich den Großteil meiner “Bedürfnisse” in der
Entwicklung abdecken und somit sind weitere Tools einfach uninteressant
geworden.&lt;/p&gt;

&lt;h3 id=&quot;nachtrag-eigenbau&quot;&gt;Nachtrag: Eigenbau&lt;/h3&gt;

&lt;p&gt;Wenn es einem nur um die eigenen &lt;code&gt;malloc()&lt;/code&gt; und &lt;code&gt;new&lt;/code&gt; Aufrufe geht,
kann man sich einen Leak-Detector auch selbst schreiben. Makros
können Aufrufe der beiden Funktionen auf eigenen Code umleiten,
wo in einer globalen Liste alle Allokationspointer gespeichert
werden. Durch die Umleitung von &lt;code&gt;free()&lt;/code&gt; und &lt;code&gt;delete&lt;/code&gt; kann diese
Liste wieder bereinigt werden.&lt;/p&gt;

&lt;p&gt;Am Ende braucht man nur noch den Inhalt dieser globalen Liste anzeigen,
denn sie beinhaltet alle (noch) nicht freigegebenen Speicherblöcke.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Aber Vorsicht!&lt;/em&gt; Fremdbibliotheken, für die solche Makros nicht gelten,
bleiben weiter unsichtbar, wenn man ihre “Strukturen” vergisst
freizugeben, weil sie von der lokalen Umleitung nichts wissen.&lt;br /&gt;
Und auch alle Codeblöcke, die systemspezifische andere 
Allokationsrountinen nutzen, werden von dieser Kleinimplementierung
nicht abgedeckt.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Disketten bzw. floppy disks</title>
   <link href="https://www.opengate.at/blog/2019/03/floppy/"/>
   <published>2019-03-25T00:00:00+01:00</published>
   <updated>2019-03-25T00:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2019/03/floppy</id>
   <category term="hardware" /><category term="retro" />
   <summary type="text">1996 passten alle meine erste Programme noch auf eine oder zwei 
Disketten.
Heute muss ich Quellcodeverzeichnisse immer erst bereinigen, bevor sie
auf den 16 GB USB Stick passen.

Die gesamte Mitschrift eines Schuljahres konnte auf den 1 Megabyte großen
Magnetscheiben gespeichert werden. Doch das in jeder E-Mail mitgeschickte
Logobild meiner Firma geht sich da keinesfalls drauf aus.
</summary>
   <content type="html">&lt;p&gt;1996 passten alle meine erste Programme noch auf eine oder zwei 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Diskette&quot;&gt;Disketten&lt;/a&gt;.
Heute muss ich Quellcodeverzeichnisse immer erst bereinigen, bevor sie
auf den 16 GB USB Stick passen.&lt;/p&gt;

&lt;p&gt;Die gesamte Mitschrift eines Schuljahres konnte auf den 1 Megabyte großen
Magnetscheiben gespeichert werden. Doch das in jeder E-Mail mitgeschickte
Logobild meiner Firma geht sich da keinesfalls drauf aus.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Nachdem ich damals - in den guten alten Tagen - mein Zimmer betrat, 
war die erste Aktion die Power-Taste der Zentraleinheit meines 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Intel_80386&quot;&gt;386ers&lt;/a&gt; zu drücken.&lt;/p&gt;

&lt;p&gt;Ein anfangs kurz tiefer dann immer höher werdender Ton kam aus der grauen 
Blechkiste.&lt;/p&gt;

&lt;p&gt;Dann hörte man: Tick-Tick-Tick-Tick-Tick-Tick-Tick-Tick aus dem 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Systemlautsprecher&quot;&gt;PC-Speaker&lt;/a&gt;.
Das war die Speicherprüfung, die nach jedem 256 Kilobyte Block ein 
Klickgeräusch ausgab, wenn der Speicher zugänglich war.&lt;/p&gt;

&lt;p&gt;Dann kurz Stille, bzw. … das übliche Rauschen von Festplatte und Lüfter.&lt;/p&gt;

&lt;p&gt;Plötzlich ein lautes Krachen &lt;code&gt;DRRRRRROOOO-DRRRRRRRAAAA&lt;/code&gt;.
Das war der Laufwerkstest von Diskettenschacht A:&lt;/p&gt;

&lt;p&gt;Gleich danach ein höheres etwas zirpendes &lt;code&gt;DRRRRRRAAAA&lt;/code&gt;.
Somit war der Laufwerkstest des kleineren Diskettenschachtes B: abgeschlossen.&lt;/p&gt;

&lt;p&gt;Danach ein Piep und dann konnte man den Festplattenkopf leicht knacken hören,
der &lt;a href=&quot;https://de.wikipedia.org/wiki/MS-DOS&quot;&gt;MS-DOS&lt;/a&gt; in den Speicher lud.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Diese einzigartige Geräuschkulisse werde ich wohl nie mehr vergessen.
Auch wenn mein erster PC eine gebrauchte veraltete Klapperkiste war,
ich liebte ihn … hatte ich doch darauf 
&lt;a href=&quot;https://de.wikipedia.org/wiki/QBasic&quot;&gt;QBASIC&lt;/a&gt; erlernen und meine ersten 
kleinen Codes abtippen können.&lt;/p&gt;

&lt;p&gt;Das Gerät ist leider schon lange tot, doch 3 Bauteile daraus funktionieren noch:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;Das Netzteil mit seinem mechanischen Ein/Aus-Schalter&lt;/li&gt;
  &lt;li&gt;Das 5.25 Zoll Diskettenlaufwerk, damals Laufwerk A:&lt;/li&gt;
  &lt;li&gt;Das 3.5 Zoll Diskettenlaufwerk, damals als B: bekannt.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Und seit wenigen Tagen ist das 5.25 Zoll-Teil zu mir nach Wien übersiedelt,
gemeinsam mit einer alten Diskettenschachtel.&lt;/p&gt;

&lt;p&gt;Es macht ja keinen Sinn, wenn die Hardware und Datenträger am Zweitwohnsitz 
langsam verrotten und ich suche ja an manchen Wochenenden Zerstreuung im
Ein- und Ausbau von Teilen auf meinen antiken Pentium-Rechnern.&lt;/p&gt;

&lt;h3 id=&quot;525-zoll-disketten&quot;&gt;5.25 Zoll Disketten&lt;/h3&gt;

&lt;p&gt;Sie zählen zu den ältesten Datenträgern, die ich besitze und sind für mich 
immer optisch ein Augenschmaus: So muss eine “echte” Diskette aussehen.&lt;/p&gt;

&lt;p&gt;An meiner damaligen Schule standen noch alte &lt;a href=&quot;https://de.wikipedia.org/wiki/Intel_8086&quot;&gt;8086&lt;/a&gt;
Kisten mit den ältesten Varianten dieser Disketten mit 180 Kilobyte herum. 
Sie waren teilweise nur einseitig formatiert.&lt;br /&gt;
Dann gab es auch welche, die auf beiden Seiten beschrieben werden konnten
und ganze 360 Kilobytes fassen konnten.&lt;/p&gt;

&lt;p&gt;Für meinen PC haben wir schnell eine 10er Packung der neueren 
DS (double-sided) HD (high-density) Disketten gekauft, die 
stattliche 1.2 Megabytes bereitstellen konnten.&lt;/p&gt;

&lt;p&gt;Und auf eben solchen Disketten startete ich meine Programmierversuche.
Denn die 40 Megabyte Festplatte war mit Windows 3.1 und Word fast
ganz ausgefüllt.&lt;/p&gt;

&lt;h3 id=&quot;35-zoll-disketten&quot;&gt;3.5 Zoll Disketten&lt;/h3&gt;

&lt;p&gt;Tatsächlich hatte ich anfangs nur wenige dieser Exemplare.
Der Grund war: Mein Rechner hatte das 5.25 Zoll Laufwerk als 
A: eingerichtet und konnte nur davon booten.&lt;br /&gt;
Ich wollte daher in erster Linie den Diskettentyp, von dem 
man auch booten konnte.&lt;/p&gt;

&lt;p&gt;Doch als ich eines Tages mutig genug war, den PC aufzuschrauben,
hatte ich schnell erkannt, dass ich die Laufwerke nur anders
herum anstecken muss. Das BIOS hatte ich auch schon entdeckt,
und als danach Laufwerk A: das 3.5 Zoll-Modell war, wurden
die 5.25 Zoll Disketten in den Hintergrund gedrängt.&lt;/p&gt;

&lt;p&gt;Zur Einführung von Windows 95 bekam ich dann den 486er
geschenkt, der nur noch ein 3.5 Zoll Laufwerk hatte.
Doch auch da dauerte es nicht lange, bis ich das alte 
“große” Laufwerk in die neuere Maschine umbaute.&lt;/p&gt;

&lt;p&gt;Und so setzte sich die Reise über den Pentium 1 bis zum Pentium 2 ins Jahr 
2000 fort, obwohl ich nur noch extrem selten zu den alten 5.25 Zöllern griff.&lt;/p&gt;

&lt;p&gt;Meine Übersiedlung nach Wien machte der alte Knacker von Laufwerk nicht
mehr mit … bis eben letzte Woche.&lt;/p&gt;

&lt;p&gt;Nun habe ich, nach fast 20 Jahren wieder ein 5.25 Zoll Laufwerk in meiner 
Nähe. Und es scharrt und knarrt immer noch, wenn es ohne eingelegte 
Diskette einen Zugriffsversuch abarbeitet.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Tja … wie sagt man so schön:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Alte Liebe rostet nicht.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/floppydisk-525.jpg&quot; alt=&quot;Floppy disk 5.25&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Ach ja … da sind ja auch noch meine nun verwaisten C64 Disketten übrig.
Herrje … was soll ich nun mit denen machen?
Denn deren Formatierung lässt sich in PCs nicht mit Boardmitteln lesen.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/floppydisk-c64.jpg&quot; alt=&quot;Floppy disk C64&quot; /&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Mäuse mit und ohne Kugel</title>
   <link href="https://www.opengate.at/blog/2019/03/mice/"/>
   <published>2019-03-24T17:29:00+01:00</published>
   <updated>2019-03-24T17:29:00+01:00</updated>
   <id>https://www.opengate.at/blog/2019/03/mice</id>
   <category term="hardware" /><category term="retro" />
   <summary type="text">Mit der Aussage:


  Der sieht auch weiße Mäuse…


wurde in meiner Kindheit gerne einem Menschen jeden weitere 
Zurechnungsfähigkeit aberkannt. Denn die bei uns verbreiteten Feld- und 
Spitzmäuse haben von grau bis 
braun viele Farben … aber keine ist weiß.

Es wird also mal Zeit etwas zurückzublicken, wie meine Computer zu ihren
“Mäusen” kamen … und ich habe einige Beweise vor mir: Sie waren häufig
weiß.
</summary>
   <content type="html">&lt;p&gt;Mit der Aussage:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Der sieht auch weiße Mäuse…&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;wurde in meiner Kindheit gerne einem Menschen jeden weitere 
Zurechnungsfähigkeit aberkannt. Denn die bei uns verbreiteten Feld- und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Spitzmäuse&quot;&gt;Spitzmäuse&lt;/a&gt; haben von grau bis 
braun viele Farben … aber keine ist weiß.&lt;/p&gt;

&lt;p&gt;Es wird also mal Zeit etwas zurückzublicken, wie meine Computer zu ihren
“Mäusen” kamen … und ich habe einige Beweise vor mir: Sie waren häufig
weiß.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Mein erster gebrauchter Computer kam mit Zentraleinheit, Bildschirm und 
Tastatur aber ohne Maus. &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_3.1&quot;&gt;Windows 3.1&lt;/a&gt;
war zwar enthalten aber musste anfangs ohne “Zeigergerät” betrieben werden.&lt;/p&gt;

&lt;p&gt;Wahrscheinlich ist das der Grund dafür, dass ich für viele Aufgaben auch
heute noch Tastenkombinationen nutze, die keiner mehr kennt.&lt;/p&gt;

&lt;p&gt;Fenster werden mit &lt;code&gt;ALT+F4&lt;/code&gt; geschlossen, MDI-Kindfenster mit &lt;code&gt;STRG+F4&lt;/code&gt;.
&lt;code&gt;F10&lt;/code&gt; oder &lt;code&gt;ALT&lt;/code&gt; alleine wählen den ersten Menüeintrag aus, und mit den
Pfeiltasten kann man die anderen Einträge selektieren. Die Tabulator-Taste
wechselt zwischen den Controls eines Fensters hin und her, während mit
&lt;code&gt;ALT+TAB&lt;/code&gt; zwischen Fenstern gewechselt werden kann.&lt;/p&gt;

&lt;p&gt;All das funktioniert von Windows 3.x bis &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_10&quot;&gt;Windows 10&lt;/a&gt;. 
Und Solitär hat die Sonderstellung, dass mit der Tastatur der Mauszeiger 
zwischen Karten hin und hergeschaltet werden kann um das Spiel auch ohne 
Maus spielen zu können.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Trotzdem: Eine &lt;a href=&quot;https://de.wikipedia.org/wiki/Maus_(Computer)&quot;&gt;Maus&lt;/a&gt; musste her.&lt;br /&gt;
Und somit wurde die erste wichtige Entscheidung fällig: Mit einer Taste
oder mit zweien. Denn Anfang der 90er waren offenbar noch so veraltete
Billigteile erhältlich. Zum Glück überzeugte ich Mama mir die etwas 
bessere mit zwei Tasten zu kaufen, obwohl ich Anfangs keine Verwendung 
dafür hatte.&lt;/p&gt;

&lt;p&gt;Es war eine &lt;a href=&quot;https://de.wikipedia.org/wiki/Serielle_Schnittstelle&quot;&gt;serielle&lt;/a&gt; 
“Kugelmaus”, also eine Maus, in der unten eine Kugel
mitlief und Walzen und Rädchen für die X- und Y-Richtung weiterdrehte.
Die Information wurde über ein einfaches serielles Signal über COM1 oder
COM2 übermittelt.
&lt;img src=&quot;/blog/assets/img/mouse-ball.jpg&quot; alt=&quot;Ball-Mouse&quot; /&gt;
Wichtig war, dass sie “Microsoft-kompatibel” war und automatisch von 
Windows auf den COM-Ports gesucht wurde.&lt;/p&gt;

&lt;p&gt;Die rechte Maustaste hatte tatsächlich früher fast keine Funktion.
Man startete und aktivierte alles per Einfach- oder Doppelklick auf die 
linke (oder bei Ein-Tasten-Modellen auf die einzige) Taste.&lt;br /&gt;
Sogar einige &lt;a href=&quot;https://de.wikipedia.org/wiki/MS-DOS&quot;&gt;DOS&lt;/a&gt; Programme wie 
&lt;code&gt;EDIT&lt;/code&gt;, &lt;code&gt;QBASIC&lt;/code&gt; oder &lt;code&gt;MSAV&lt;/code&gt; nutzten einen Mauszeiger, falls ein 
entsprechender DOS-Treiber installiert war.&lt;/p&gt;

&lt;p&gt;Als ich so gegen 1995 &lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_Basic_Classic&quot;&gt;Visual Basic&lt;/a&gt; 
4.0 erhielt bekam die rechte Maustaste plötzlich eine wichtige Funktion. Denn 
das neue VB setzte viele Eigenschaften vom angekündigten 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_95&quot;&gt;Windows 95&lt;/a&gt; um und zeigte
beim Rechtsklick auf ein Element ein “neuartiges” Kontextmenü an.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/mouse-serial.jpg&quot; alt=&quot;Serial-Mouse&quot; /&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Mit dem Wechsel auf &lt;a href=&quot;https://de.wikipedia.org/wiki/Intel_Pentium&quot;&gt;Pentium&lt;/a&gt; 
und Pentium 2 Systeme tauchte um das Jahr 2000 immer häufiger der 
&lt;a href=&quot;https://en.wikipedia.org/wiki/PS/2_port&quot;&gt;PS/2&lt;/a&gt; Mausport auf, der serielle 
Mäuse schnell ablöste. Doch wie immer kaufte ich damals 
“aus Kompatibilitätsgründen” weiter noch serielle Mäuse, weil diese vorerst
auf alten UND neuen Systemen einsatzfähig wurden.&lt;/p&gt;

&lt;p&gt;Inzwischen waren Windows 98, NT 4 und teilweise schon 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_2000&quot;&gt;Windows 2000&lt;/a&gt; bei mir
aktuell und dort eindeckte ich eine Eigenschaft von PS/2 Mäusen, die 
serielle Geräte nicht hatten: &lt;strong&gt;Die Bewegungen waren wesentlich flüssiger.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Es gab sogar ein eigenes Tool, das die PS/2 Maus-Abtastrate höher stellen
konnte. Und das war dann mein wichtigster Grund endlich umzusteigen.&lt;/p&gt;

&lt;p&gt;Doch schon in dieser Zeit fand bereits die nächste Umstellung statt.
&lt;a href=&quot;https://de.wikipedia.org/wiki/Universal_Serial_Bus&quot;&gt;USB&lt;/a&gt;-Mäuse kamen auf 
den Markt, doch diese brauchten dennoch noch ein paar
Jährchen, bis sie PS/2 Modelle in den Hintergrund drängen konnten.&lt;/p&gt;

&lt;p&gt;Und wieder blieb ich hier bis etwa zum Jahr 2007 konservativ und blieb bei
PS/2. Mit ein Grund war die Tatsache, dass ich inzwischen einige 
&lt;a href=&quot;https://de.wikipedia.org/wiki/KVM-Switch&quot;&gt;KVM-Switches&lt;/a&gt; angeschafft hatte, 
die auf PS/2 festgelegt waren, um mit einer Tastatur und einer Maus mehrere 
PCs zu bedienen.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Ach übrigens: Mein ältestes “Zeigergerät” habe ich erst später geschenkt
bekommen, und zwar eine serielle Trackball-Mouse. Hier bewegt man nicht 
das Geräte auf dem Tisch herum, sondern dreht an der Kugel um den Zeiger
auf dem Bildschirm zu verschieben.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/mouse-trackball.jpg&quot; alt=&quot;Trackball&quot; /&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>AusgeBOOLt</title>
   <link href="https://www.opengate.at/blog/2019/03/bool/"/>
   <published>2019-03-23T14:57:00+01:00</published>
   <updated>2019-03-23T14:57:00+01:00</updated>
   <id>https://www.opengate.at/blog/2019/03/bool</id>
   <category term="devel" />
   <summary type="text">Was für ein Drama! Boolsche Auswertung gab es in C natürlich schon immer.
Doch als C++ den Typen bool als 
elementaren Kernsprachen-Typen einführte, machte C diesen Schritt nicht mit, 
hatte jedoch kurz danach die Idee, dieses Feature als typedef im Header 
stdbool.h nachzuliefern.

Und heute suchte ich verzweifelt einen seltsamen Bug, der den Stack
korrumpierte, der jedoch nur in Visual Studio
2005 und 2008, nicht jedoch im 2017 auftrat.

Und was der Grund? Natürlich der Typ bool.
</summary>
   <content type="html">&lt;p&gt;Was für ein Drama! Boolsche Auswertung gab es in C natürlich schon immer.
Doch als &lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B&quot;&gt;C++&lt;/a&gt; den Typen &lt;code&gt;bool&lt;/code&gt; als 
elementaren Kernsprachen-Typen einführte, machte C diesen Schritt nicht mit, 
hatte jedoch kurz danach die Idee, dieses Feature als &lt;code&gt;typedef&lt;/code&gt; im Header 
&lt;code&gt;stdbool.h&lt;/code&gt; nachzuliefern.&lt;/p&gt;

&lt;p&gt;Und heute suchte ich verzweifelt einen seltsamen Bug, der den Stack
korrumpierte, der jedoch nur in &lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_Studio&quot;&gt;Visual Studio&lt;/a&gt;
2005 und 2008, nicht jedoch im 2017 auftrat.&lt;/p&gt;

&lt;p&gt;Und was der Grund? Natürlich der Typ &lt;code&gt;bool&lt;/code&gt;.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Nun, der &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft&quot;&gt;Microsoft&lt;/a&gt; Teufel hatte aus
Gott weiß welchen Gründen die Compiler-Releases daran gehindert &lt;code&gt;stdbool.h&lt;/code&gt; 
mitauszuliefern und eine “natürliche” Brücke zwischen dem C++ Typen &lt;code&gt;bool&lt;/code&gt; und
dem C-Nachbau &lt;code&gt;_Bool&lt;/code&gt; aufzubauen.&lt;/p&gt;

&lt;p&gt;Aus diesem Grund kompilierten viele moderne Bibliotheken nicht mit etwas
älteren Microsoft Compilern.&lt;/p&gt;

&lt;p&gt;Ein bekannter Workaround dafür ist, den Header &lt;code&gt;stdbool.h&lt;/code&gt; selbst 
bereitzustellen, und eine gängige Variante davon ist:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#if&lt;/span&gt; defined(__cplusplus)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;typedef&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;bool&lt;/span&gt;        _Bool;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#else&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;typedef&lt;/span&gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;enum&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#069&quot;&gt;false&lt;/span&gt; = &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  &lt;span style=&quot;color:#069&quot;&gt;true&lt;/span&gt; = &lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;} _Bool;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;typedef&lt;/span&gt; _Bool &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;bool&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#endif&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;So lange man C nur mit C Code betreibt und C++ Code nur mit C++, gibt es damit
auch keine Probleme.&lt;br /&gt;
Doch wehe, man definiert in C eine Struktur mit &lt;code&gt;bool&lt;/code&gt; Membern, die von einer
C++ Funktion instanziiert wird und dann an eine C Funktion per Pointer 
übergeben wird, dann tanzen Korruptionen und andere Segmentationfaults durch
die Gegend.&lt;/p&gt;

&lt;p&gt;Der Grund ist - wenn er erst erkannt wurde - denkbar einfach.
Weder C noch C++ definieren im Sprachstandard eine feste Größe für &lt;code&gt;bool&lt;/code&gt; 
und &lt;code&gt;enum&lt;/code&gt;, doch die Compiler Hersteller tun dies für ihre Implementierung.&lt;/p&gt;

&lt;p&gt;Und bei Microsoft ist &lt;code&gt;bool&lt;/code&gt; ein Byte groß ohne Alignment, während 
&lt;code&gt;enum&lt;/code&gt; Definitionen einem &lt;code&gt;int&lt;/code&gt; gleicht, also 4 Bytes lang sind.&lt;/p&gt;

&lt;p&gt;Und schon erhält die gleich C-Struktur zwei unterschiedliche Aufbaupläne
und ist in C++ kleiner als in C … somit stimmen die Speicheradressen
nicht mehr und die Welt geht unter.&lt;/p&gt;

&lt;h3 id=&quot;lösung&quot;&gt;Lösung&lt;/h3&gt;

&lt;p&gt;Nun, mit der Änderung der &lt;code&gt;stdbool.h&lt;/code&gt; Implementierung auf:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#if&lt;/span&gt; !defined(__cplusplus)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;typedef&lt;/span&gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;enum&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#069&quot;&gt;false&lt;/span&gt; = &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;,
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#069&quot;&gt;true&lt;/span&gt; = &lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;} _BoolType;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;typedef&lt;/span&gt; unsigend &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;bool&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#579&quot;&gt;#endif&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;typedef&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;bool&lt;/span&gt;        _Bool;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;ist das Problem auf binärer Ebene gelöst.
&lt;code&gt;_Bool&lt;/code&gt; und &lt;code&gt;bool&lt;/code&gt; sind damit in C und C++ genau ein Byte groß
und austauschbar, und die Zuweisung von &lt;code&gt;enum&lt;/code&gt;s auf &lt;code&gt;unsigned char&lt;/code&gt;
wird zumindest vom &lt;code&gt;MSVC&lt;/code&gt; im C-Modus nicht (besonders schlimm) 
angemeckert.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Schon witzig, dass ich jetzt seit Jahren mit dieser alten &lt;code&gt;stdbool&lt;/code&gt;
Implementierung lebe, einige Fremdbibliotheken damit betreibe und noch nie 
Probleme damit hatte.&lt;br /&gt;
Tja, offenbar, habe ich noch nie &lt;code&gt;bool&lt;/code&gt; Werte zwischen C und C++ damit 
ausgetauscht.&lt;br /&gt;
Nun gut, dann wurde das ja auch mal Zeit!&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Bonusfrage: Wie kam überhaupt es zu dem Szenario?&lt;/p&gt;

&lt;p&gt;Antwort: &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_CE&quot;&gt;Windows CE&lt;/a&gt;! 
Für was sonst braucht man denn solche uralten Compiler…&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Augenschmaus: Digitale Mikroskope</title>
   <link href="https://www.opengate.at/blog/2019/03/microscope/"/>
   <published>2019-03-22T17:11:00+01:00</published>
   <updated>2019-03-22T17:11:00+01:00</updated>
   <id>https://www.opengate.at/blog/2019/03/microscope</id>
   <category term="hardware" />
   <summary type="text">
  Mein Augenarzt hat Unrecht. Mit meinen Augen ist alles in Ordnung, 
ich brauchte nur einen größeren Bildschirm!


So rechtfertigte ich damals die Anschaffung eines 
Nintendo 3DS XL, 
weil der normale 3DS immer so ein schwammiges Bild produziert hatte …

Aber schlimmer als alle Videospiele und Konsolen sind die unleserlichen
Aufdrucke auf Bauteilen wie 
Transistoren oder 
Kondensatoren.

… ohne Seh-Hilfe geht es da einfach nicht mehr.
</summary>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;Mein Augenarzt hat Unrecht. Mit meinen Augen ist alles in Ordnung, 
ich brauchte nur einen größeren Bildschirm!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So rechtfertigte ich damals die Anschaffung eines 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Nintendo_3DS#Nintendo_3DS_XL&quot;&gt;Nintendo 3DS XL&lt;/a&gt;, 
weil der normale 3DS immer so ein schwammiges Bild produziert hatte …&lt;/p&gt;

&lt;p&gt;Aber schlimmer als alle Videospiele und Konsolen sind die unleserlichen
Aufdrucke auf Bauteilen wie 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Transistor&quot;&gt;Transistoren&lt;/a&gt; oder 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Kondensator_(Elektrotechnik)&quot;&gt;Kondensatoren&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;… ohne Seh-Hilfe geht es da einfach nicht mehr.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Ärgerlicherweise musste ich nun schon das eine oder andere Bastelexperiment
seit Wochen und Monaten verschieben.&lt;br /&gt;
Neben Zeitgründen liegt aber auch gerne mal der folgende Grund vor:&lt;/p&gt;

&lt;p&gt;Keramikkondensatoren waren in dem Bereich, wo sie hätten beschriftet sein
sollen, abgekratzt oder der Schriftzug war verwischt oder eben gar nicht
vorhanden.&lt;/p&gt;

&lt;p&gt;Während Elektrolytkondensatoren zumeist noch relativ deutlich mit 
Kapazität und Spannung versehen sind, haben ihre kleineren Geschwister
oft nur spärliche Ziffern aufgedruckt, meist die 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Farad&quot;&gt;Pikofarad&lt;/a&gt; Kennzahl, oder noch schlimmer:
Eine kryptische Seriennummer.&lt;/p&gt;

&lt;p&gt;All dass in einem Schriftzug, den ich mit meinen Augen schon lange nicht
mehr erfassen kann. Und so versuchte ich wie ein alter Großvater mit 
einer Lupe und etwas herumraten die Bauteile halbwegs korrekt zuzuordnen.&lt;/p&gt;

&lt;p&gt;Für dieses Problem gibt es zwei Lösungen.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Man besorgt sich ein Messgerät und misst nach.
    &lt;ul&gt;
      &lt;li&gt;Es gibt sogar für &lt;a href=&quot;https://en.wikipedia.org/wiki/ATmega328&quot;&gt;ATMEGA328&lt;/a&gt;
Arduinos Codebeispiele, wie man damit Bauteile prüfen kann, 
doch leider endet deren Genauigkeit recht früh, womit Keramikkondensatoren
nicht mehr erfasst werden konnten.&lt;/li&gt;
      &lt;li&gt;Man kann sich aber solche Messgeräte kaufen, teilweise sogar ebenfalls
wieder als Bausatz. Ein solches besitze ich nun.&lt;/li&gt;
      &lt;li&gt;Für SMD Bauteile helfen Messgeräte nicht, weil man dort nur größere
Teile an ihren Anoden- und Kathoden-füßchen einklemmen kann.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Man investiert in ein günstiges digitales Tischmikroskop, das Platinen und
Bauteile gut ausleuchten und die unleserlichen Bereich lesbar machen kann.
    &lt;ul&gt;
      &lt;li&gt;Und ein solches zählt seit kurzem zu meinem Inventar.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/microscope.jpg&quot; alt=&quot;Microscope&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Ja, ich weiß, wieder so ein Teil, das viel herumsteht, aber man ist dankbar,
wenn man es im Notfall zur Verfügung hat.&lt;/p&gt;

&lt;p&gt;Das Teil ist eigentlich nur eine einfache günstige Webcam mit einer Auflösung
von 800 x 600 Pixel, die aber durch die Linse nur 2 x 2 Zentimeter Bereiche
zur Aufzeichnung durchlässt.&lt;/p&gt;

&lt;p&gt;Und dieser Bereich ist dank LED-Beleuchtung angenehm vergrößert, womit man die
Kennzahlen auf SMD Bauteilen lesen und sogar schwache oder verwischt 
aufgedruckte Kapazitätsgrößen erkennen kann.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ich weiß gar nicht, wie ich bisher ohne das Teil ausgekommen bin, und parallel
dazu sind Chip-Nahaufnahmen eigentlich ganz interessante Hintergrundbilder.&lt;/p&gt;

&lt;p&gt;Mit dem Gerät kann ich nun jedenfalls wesentlich mehr entziffern als bisher
und weiß jetzt endlich, in welcher Richtung ich SMD LEDs einlöten muss.
Denn bisher konnte ich nicht erkennen, auf welcher Seite &lt;code&gt;+&lt;/code&gt; und &lt;code&gt;-&lt;/code&gt; 
Markierungen angebracht waren, nun ist klar erkennbar, wo der Strich und 
wo der Punkt ist.&lt;/p&gt;

&lt;p&gt;Hier ein paar Aufnahmebeispiele:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/microscope-esp.jpg&quot; alt=&quot;Microscope-ESP&quot; /&gt;
&lt;img src=&quot;/blog/assets/img/microscope-serial.jpg&quot; alt=&quot;Microscope-Serial&quot; /&gt;
&lt;img src=&quot;/blog/assets/img/microscope-sensor.jpg&quot; alt=&quot;Microscope-Sensor&quot; /&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Retro-Watch - Uhrenvergleich</title>
   <link href="https://www.opengate.at/blog/2019/03/retro-watch/"/>
   <published>2019-03-21T14:16:00+01:00</published>
   <updated>2019-03-21T14:16:00+01:00</updated>
   <id>https://www.opengate.at/blog/2019/03/retro-watch</id>
   <category term="hardware" />
   <summary type="text">In der Jugend waren mir Armbanduhren zunehmend verhasst. Das lag aber in 
erster Linie an einem Neurodermitis
Leiden, welches aber im Laufe der Zeit mehr und mehr in den Hintergrund
getreten ist.

Und seit ab dem Jahr 2000 die de-facto Handy-Pflicht für alle eingeführt wurde,
trug ich meinen somit neuen computerisierten Chronometer immer in der 
Hosentasche herum.

Erst seit den letzten Monaten prangt nun wieder ein digitalisierter Armreif 
um mein Handgelenk, auf dem man auch die Zeit ablesen kann…
</summary>
   <content type="html">&lt;p&gt;In der Jugend waren mir Armbanduhren zunehmend verhasst. Das lag aber in 
erster Linie an einem &lt;a href=&quot;https://de.wikipedia.org/wiki/Atopisches_Ekzem&quot;&gt;Neurodermitis&lt;/a&gt;
Leiden, welches aber im Laufe der Zeit mehr und mehr in den Hintergrund
getreten ist.&lt;/p&gt;

&lt;p&gt;Und seit ab dem Jahr 2000 die de-facto Handy-Pflicht für alle eingeführt wurde,
trug ich meinen somit neuen computerisierten Chronometer immer in der 
Hosentasche herum.&lt;/p&gt;

&lt;p&gt;Erst seit den letzten Monaten prangt nun wieder ein digitalisierter Armreif 
um mein Handgelenk, auf dem man auch die Zeit ablesen kann…
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Und seit heute darf zu besonderen Anlässen mein Bastelneuzugang ebenso an den
Arm geschnallt werden:&lt;br /&gt;
Eine 
&lt;a href=&quot;http://www.banggood.com/LED-Digital-Watch-Electronic-Clock-Kit-With-Transparent-Cover-p-976634.html&quot;&gt;Do-It-Yourself LED Digital Watch&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/retro-watch.jpg&quot; alt=&quot;Retro-Watch&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Für mich ist es ja immer wieder faszinierend, wie Technik, die vor 30 Jahren
noch ultra-modern war, heute mit ein paar Chips selbst zu Hause 
zusammengelötet werden kann und eigentlich derart gegen aktuelle
Produkte “abstinkt”, dass man Angst bekommt, wie schnell die Technik
fortschreitet.&lt;/p&gt;

&lt;p&gt;Denn heutige Armbanduhren haben schon lange nicht mehr nur die Aufgabe die
Zeit anzuzeigen, genau so wenig wie Mobiltelefone nicht mehr primär zum 
Telefonieren da sind.&lt;/p&gt;

&lt;p&gt;Schrittzähler, Herzschlag-, Blutdruck und Trinkerinnerung sind heute neben
Social-Media Kurzinfo, E-Mail-Abfrage und Terminerinnerung ein 
minimalistisches Funktionsbasispaket, welches dann durch Tauchfunktionen,
GPS- und Kompassanzeige und zahlreiche anderen Erweiterungen bei 
Luxusmodellen ergänzt wird.&lt;/p&gt;

&lt;p&gt;Das “Sprechen” mit der Armbanduhr ist meiner Erfahrung nach heute kein
besonderes Thema, womit &lt;a href=&quot;https://de.wikipedia.org/wiki/David_Hasselhoff&quot;&gt;David Hasselhoff&lt;/a&gt;
in der klassischen Serie &lt;a href=&quot;https://de.wikipedia.org/wiki/Knight_Rider&quot;&gt;Knight Rider&lt;/a&gt;
wohl der einzige Mann bleiben wird, der so mit seinem Auto reden konnte.&lt;/p&gt;

&lt;p&gt;Wozu auch, hat doch heute jeder dritte sein Bluetooth-Headset fix im
Ohr verankert und führt im Supermarkt scheinbar Selbstgespräche bei der
Wahl des besten Joghurts, obwohl er in Wahrheit seinen Beitrag in einem
Online-Firmenmeeting einbringt.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Ich persönlich bin etwas zerrissen zwischen technischer Neugier auf der 
einen Seite und dezenter Anwiderung über unseren modernen Zwang, jeden
Körperteil vernetzen zu wollen.&lt;/p&gt;

&lt;p&gt;Das einzig spannende an meiner Billig-Smartwatch ist, nach dem Aufwachen
meinen Blutdruck zu messen um dann sagen zu können:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ah, eh so niedrig wie immer.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Und inzwischen drücke ich tatsächlich wieder aufs Armgelenk um zu wissen,
wie spät es ist, anstatt in die Hosentasche zu fahren um das Smartphone
nur wegen der Uhrzeit zu zücken.&lt;br /&gt;
Alle anderen Vibrations-Stör-Funktionen sind und bleiben abgeschaltet.&lt;/p&gt;

&lt;p&gt;Doch es nervt mich auch etwas, dass die “coole” Smartwatch mit ihrer
Bluetoothstrahlung ebenso wie die Smartphones alle paar Tage an den
USB-Port zum Aufladen angeschlossen werden müssen.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Herr Gott, wie schön war es früher mit einer einzigen Batterie 
ein halbes Jahr lang Ruhe am Handgelenk zu haben!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Deshalb bin ich jetzt sehr gespannt, wie lange die DIY Watch mit ihrer
3 Volt Lithium Zelle überlebt.&lt;br /&gt;
Die LED-Zeitanzeige verbraucht vermutlich um einiges mehr an Strom,
als das früher auf unbeleuchteten Displays der Fall war.&lt;br /&gt;
Doch zum Glück wird die Zeit nur auf Knopfdruck für ein paar Sekunden
angezeigt, womit im Schlummerzustand hoffentlich nur wenige Mikroampere
zur Sekundenzählung verbraten werden.&lt;/p&gt;

&lt;p&gt;Zumindest in Sachen Stromverbrauch kann ich eines wieder mit gutem
Gewissen sagen:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Früher war alles besser!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Und wie Harald Lesch sagen würde:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Und, hat Sie Ihr digitaler Diktator schon daran erinnert,
dass Sie noch eine Runde um dem Block laufen müssen um Ihren
Schritte-Sollwert zu erreichen?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;hr /&gt;

&lt;p&gt;Nachtrag:&lt;br /&gt;
Naja, nach ein paar Wochen ist die Batterie des DIY-Uhr leer. 
Also auch keine besondere Glanzleistung im Vergleich zu früher.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Internet und Urheberrecht</title>
   <link href="https://www.opengate.at/blog/2019/03/internet-freedom/"/>
   <published>2019-03-20T19:38:00+01:00</published>
   <updated>2019-03-20T19:38:00+01:00</updated>
   <id>https://www.opengate.at/blog/2019/03/internet-freedom</id>
   <category term="general" />
   <summary type="text">Es ist (schon wieder) soweit! Das Internet wird gesperrt, vernichtet,
privatisiert und verstaatlicht.

Leider verliert man als einfacher Bürger den Überblick, was ständig am
Zusammenbrechen ist, weil kontinuierlich Panik von unterschiedlichen 
Strömungen verbreitet wird.

Heute bzw. morgen geht es um den 
Artikel 13,
also der Urheberrechtsrichtlinie der europäischen Union.
</summary>
   <content type="html">&lt;p&gt;Es ist (schon wieder) soweit! Das Internet wird gesperrt, vernichtet,
privatisiert und verstaatlicht.&lt;/p&gt;

&lt;p&gt;Leider verliert man als einfacher Bürger den Überblick, was ständig am
Zusammenbrechen ist, weil kontinuierlich Panik von unterschiedlichen 
Strömungen verbreitet wird.&lt;/p&gt;

&lt;p&gt;Heute bzw. morgen geht es um den 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Urheberrechtsreform_der_Europ%C3%A4ischen_Union&quot;&gt;Artikel 13&lt;/a&gt;,
also der Urheberrechtsrichtlinie der europäischen Union.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Kurz gesagt, ich habe von Recht und Juristerei wenig bis keine Ahnung. 
Das mag eine Schwäche sein, aber ich habe mit ihr leben gelernt.&lt;/p&gt;

&lt;p&gt;Während viele Informatiker hier ohne nachzudenken gleich&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Nein! Widerstand! Zu den Waffen!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;grunzen, bin ich hier bewusst vorsichtiger.
Natürlich bin ich letztendlich absolut für den Verbleib des “freien Internets”,
das nicht durch Zensur und Strafandrohung von Großkonzernen zersetzt wird.
Doch andererseits muss auch der gefährliche rechtsfreie Raum in unseren
virtuellen Netzen begrenzt bzw. aufgelöst werden.&lt;/p&gt;

&lt;p&gt;Und wie so oft passiert vieles immer aus den falschen Gründen…&lt;/p&gt;

&lt;p&gt;Urheberrechte und der Schutz des selbst geschaffenen geistigen Eigentums
ist ein Grundrecht in allen anerkannten Demokratien.&lt;br /&gt;
Zum Glück sind die Zeiten, in denen alles (also wirklich alles) aus
Gottes Gnaden einem König oder Kaiser gehört, ein für alle mal vorbei.&lt;/p&gt;

&lt;p&gt;Von daher kann ich diverse “Piraten”-Bewegungen absolut nicht verstehen
bzw. unterstützen, die stets einem falsch verstandenen Kommunismus nachlaufen,
und notfalls per Gewalt garantieren wollen, dass alles allen gehört.&lt;/p&gt;

&lt;p&gt;Wer etwas “erschafft”, soll auch die primäre Möglichkeit haben, daraus 
wirtschaftlichen Erfolg generieren.&lt;br /&gt;
Und wer solche “Erschaffungen” stiehlt, als eigene Leistung deklariert und
anstatt des tatsächlichen Urhebers Gewinne entwendet, hat wie ein Warendieb
entsprechend geahndet zu werden.&lt;br /&gt;
… so viel zur Theorie.&lt;/p&gt;

&lt;p&gt;ABER: Was ist heute eine echte “Neuerschaffung” und vor allem, 
wer urteilt bzw. bewertet für uns alle Fälle.&lt;/p&gt;

&lt;p&gt;Historiker haben meines Wissens heute festgestellt, dass 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Isaac_Newton&quot;&gt;Isaac Newton&lt;/a&gt; und
&lt;a href=&quot;https://de.wikipedia.org/wiki/Gottfried_Wilhelm_Leibniz&quot;&gt;Gottfried Wilhelm Leibniz&lt;/a&gt; 
beide ziemlich gleichzeitig die 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Differentialrechnung&quot;&gt;Differentialrechnung&lt;/a&gt;
“erfunden” haben. Beide kamen mit unterschiedlichen Ansetzen zum gleichen 
Ergebnis.&lt;br /&gt;
Doch bis über ihren Tod hinaus entbrannte ein Rechtsstreit, wer von wem
abgeschrieben und somit “geistiges Eigentum” geklaut hatte.&lt;/p&gt;

&lt;p&gt;Hier beginnt das Dilemma, dass jeder der beiden als alleiniger Erfinder in 
die Geschichte eingehen wollte. Und auf dieser Ebene wird nicht mehr 
rational debattiert, sondern nur noch Machtge- und Missbrauch eingesetzt um
die eigenen Ziele durchzusetzen.&lt;/p&gt;

&lt;p&gt;Das Internet heute stellt eine Größe menschlicher Einzelerfindungen dar, wie
es sie in der Geschichte noch nie gegeben hat.&lt;br /&gt;
Wer maßt sich also an, hier als gottgleicher Richter zu urteilen, 
wer was wann wie “erfunden”, und wer was wann wie “gestohlen” hat.&lt;/p&gt;

&lt;p&gt;Und solche Schlachten gewinnt in der Regel das stärkere Heer, und nicht die
versprengte Gruppe gerechter und kreativer Idealisten.&lt;/p&gt;

&lt;p&gt;Von daher war das “freie Internet” bisher eine der letzten Inseln der Seeligen,
wo individuelle Gedanken ohne Gift und ohne Dünger wachsen konnten, ohne dass
Konzernvorstellungen sie verderben konnten.&lt;/p&gt;

&lt;p&gt;Wenn es also zu Gesetzeszwängen kommt, die Internetplattformen vorschreiben jede
mögliche “Urheberrechtsverletzung” im Vorfeld zu verhindern, ist jede 
“gerechte” Behandlung des Themas ausgeschlossen.&lt;br /&gt;
Es funktioniert einfach nicht, jede Zeile, jedes Foto und jeden Soundeffekt
im Vorfeld zu prüfen.&lt;/p&gt;

&lt;p&gt;Das Resultat sind halbfertige Content-Filter, die in vielen Fällen einfach nur
“zufällig” entscheiden können, ob ein Inhalt nun eine Teilkopie oder deine
neue Schöpfung ist, und diese Entscheidung wird dann unterwürfig und 
hochtrabend als “künstliche Intelligenz” angepriesen.&lt;/p&gt;

&lt;p&gt;Und genau damit spielt man erst recht wieder den Mächtigen
der Welt die Kontrolle zu, die sich “rechtlich” besser absichern 
können, als andere und “ihr” KI-Produkt besser vermarkten.&lt;/p&gt;

&lt;p&gt;Trotzdem sollten wir nicht vergessen, dass die ganze Debatte nur deshalb 
entstanden ist, weil leider auch viel zu viele Raubvögel im Netz unterwegs
waren und es noch sind.&lt;br /&gt;
Und wenn ich mir manche “Programmierer” ansehe, die kein Bit ihrer 
“eigenen Werke” verstehen weil alles nur zusammenkopiert ist, muss ich schon 
eingestehen, dass ich mir auch so einen Masterknopf wünsche, der bei 
Betätigung die Betrüger auslöscht.&lt;/p&gt;

&lt;p&gt;Doch Tatsache ist: So etwas existiert nicht.&lt;br /&gt;
Und bis weder Technik noch Politik so weit sind hier vernünftige Kriterien
zur “Säuberung” der Netze auf die Beine zu stellen, ist auch jeder
Gesetzesvorschlag, der Anbieter vorverurteilt, als FALSCH abzulehnen.&lt;/p&gt;

&lt;hr /&gt;

&lt;blockquote&gt;
  &lt;p&gt;Zur rechtlichen Sicherheit möchte ich mich von meinem eigenen hier
geschriebenen Blog-Text distanzieren. Ich kann nicht ausschließen,
dass einzelne Worte, Sätze oder Ansichten auch von anderen Menschen
gedacht, geschrieben oder ausgesprochen wurden.&lt;/p&gt;

  &lt;p&gt;Diese Nachricht ist meine persönliche individuelle Meinungsäußerung.
Elektronen und andere dritte, die diese Informationen übermitteln
stehen nicht mit mir in Zusammenhang, noch teile ich automatisch
deren Meinung, nur weil sie meine Meinung transportieren.&lt;/p&gt;

  &lt;p&gt;Bis ich auf Gegenteiliges verklagt werde und den Prozess verliere, 
definiere ich diesen Text als meine persönliche geistige Eigenleistung.
Jeder freie Geist dieser Welt darf diese Gedanken teilen, ist aber 
rechtlich nicht dazu verpflichtet.&lt;/p&gt;

  &lt;p&gt;Wer sich für die Verbreitung meiner Gedanken rechtlich absichern
möchte, kann gerne eine formale Lizenz dafür beantragen.
Ich unterschreibe alles.&lt;/p&gt;

  &lt;p&gt;Und Vorsicht! Manche Nusskuchen KÖNNEN Spuren von Nüssen beinhalten!
Und das Anziehen eines Superman-Kostüms befähigt den Träger
NICHT zum selbstständigen Fliegen.&lt;/p&gt;

  &lt;p&gt;Diese Informationen waren gratis, zumindest derzeit noch.&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>Bluetooth Low Energy (BTH-LE)</title>
   <link href="https://www.opengate.at/blog/2019/03/bluetooth-le/"/>
   <published>2019-03-19T20:42:00+01:00</published>
   <updated>2019-03-19T20:42:00+01:00</updated>
   <id>https://www.opengate.at/blog/2019/03/bluetooth-le</id>
   <category term="hardware" /><category term="devel" />
   <summary type="text">Meine kostengünstige Armbanduhr 
mit Herzschlag und Blutdrucksensor schickt tägliche ihre Daten zur Smartphone
App unter Android.
Harald Lesch nennt solche Geräte
zu Recht “digitale Diktatoren” die nicht gerade ein positives Beispiel 
unserer Gesellschaft sind:


  Weil wir zu faul sind, zu Fuß zur Arbeit zu marschieren und mit Öffis
und Autos durch die Straßen brettern, brauchen wir am Abend die 
“Erinnerungsfunktion” am Handgelenk, dass noch X Schritte zu machen sind,
damit wir uns als “gesund” titulieren können.


However … der spannendere Aspekt des “digitalen Diktators” ist, dass
er über Bluetooth LE 
kommuniziert und so seine gesammelten Daten meldet und neue Konfigurationen 
abholt.
</summary>
   <content type="html">&lt;p&gt;Meine kostengünstige &lt;a href=&quot;https://de.wikipedia.org/wiki/Smartwatch&quot;&gt;Armbanduhr&lt;/a&gt; 
mit Herzschlag und Blutdrucksensor schickt tägliche ihre Daten zur Smartphone
App unter &lt;a href=&quot;https://de.wikipedia.org/wiki/Android_(Betriebssystem)&quot;&gt;Android&lt;/a&gt;.&lt;br /&gt;
&lt;a href=&quot;https://de.wikipedia.org/wiki/Harald_Lesch&quot;&gt;Harald Lesch&lt;/a&gt; nennt solche Geräte
zu Recht “digitale Diktatoren” die nicht gerade ein positives Beispiel 
unserer Gesellschaft sind:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Weil wir zu faul sind, zu Fuß zur Arbeit zu marschieren und mit Öffis
und Autos durch die Straßen brettern, brauchen wir am Abend die 
“Erinnerungsfunktion” am Handgelenk, dass noch X Schritte zu machen sind,
damit wir uns als “gesund” titulieren können.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;However … der spannendere Aspekt des “digitalen Diktators” ist, dass
er über &lt;a href=&quot;https://de.wikipedia.org/wiki/Bluetooth_Low_Energy&quot;&gt;Bluetooth LE&lt;/a&gt; 
kommuniziert und so seine gesammelten Daten meldet und neue Konfigurationen 
abholt.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Das &lt;a href=&quot;http://www.bluetooth.com/specifications/gatt/generic-attributes-overview/&quot;&gt;GATT Profile&lt;/a&gt;
(Generic Attribute Profile) ist in etwas das für Bluetooth, was 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Human_Interface_Device&quot;&gt;HID&lt;/a&gt; 
(Human Interface Device) für 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Universal_Serial_Bus&quot;&gt;USB&lt;/a&gt; 
(Universal Serial Bus) ist.&lt;br /&gt;
Anstatt dass jedes Gerät sein eigenes Datenprotokoll definiert, wird ein
generisches gewählt, das eine variable Sammlung von “Services” bereitstellen
kann, und jedes Service hat eigene “Characteristics” und “Attributes”, die
man entweder nur lesen, nur schreiben oder beides kann.&lt;/p&gt;

&lt;p&gt;So etwas ist für die Programmierung super, weil man mit einer kleinen Anzahl
von APIs jedes mögliche GATT / Bluetooth LE Gerät steuern und auslesen kann.
Die Komplexität steckt dabei aber im Wissen, welches Service welche ID hat,
und welche Eigenschaft (Characteristic) bzw. welche Eigenschaftskombinationen
welche finalen Auswirkungen und Bedeutungen hat.&lt;/p&gt;

&lt;p&gt;Es gibt natürlich das eine oder andere “generische” Service, das jedes
Bluetooth-LE-Gerät bereit stellt um z.B. seinen Namen, Hersteller und die 
Version auszulesen, doch die Details zu vielen weiteren Services stehen nur 
in der Spezifikation des Herstellers oder … nirgends, weil sie nicht 
veröffentlicht sind.&lt;/p&gt;

&lt;p&gt;Um so mehr Spaß macht es dann, diese Details herauszufinden.
Denn es gibt Tools, die alle Byteblöcke eines BTH-LE-Gerätes auslesen und
anzeigen.&lt;br /&gt;
Und daher sah ich mich schon fast gezwungen, diese APIs auch ins GATE
Projekt aufzunehmen um etwas damit “spielen” zu können.&lt;/p&gt;

&lt;p&gt;Seit &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_8&quot;&gt;Windows 8&lt;/a&gt; existieren die 
&lt;a href=&quot;http://docs.microsoft.com/en-us/windows/desktop/api/bluetoothleapis/&quot;&gt;BluetoothGATT*&lt;/a&gt; 
Funktionen um eben genau diese Details auszulesen. Doch wie so oft unter Windows 
fehlt die zusammenhängende Dokumentation, wie man die Pfade für die Geräte kommt.&lt;/p&gt;

&lt;p&gt;Hier die Zusammenfassung:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Man sucht mit der &lt;a href=&quot;http://docs.microsoft.com/en-us/windows-hardware/drivers/install/setupapi&quot;&gt;SetupDI* API&lt;/a&gt; 
nach allen BTH-LE Geräten über die Klasse &lt;code&gt;GUID_BLUETOOTHLE_DEVICE_INTERFACE&lt;/code&gt;
&lt;code&gt;{781aee18-7733-4ce4-add0-91f41c67b592}&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;http://docs.microsoft.com/en-us/windows/desktop/api/setupapi/nf-setupapi-setupdigetclassdevsw&quot;&gt;&lt;code&gt;SetupDiGetClassDevs()&lt;/code&gt;&lt;/a&gt;
öffnet die Liste aller Geräte&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;http://docs.microsoft.com/en-us/windows/desktop/api/setupapi/nf-setupapi-setupdienumdeviceinterfaces&quot;&gt;&lt;code&gt;SetupDiEnumDeviceInterfaces()&lt;/code&gt;&lt;/a&gt;
lädt die Daten eines Geräts (per Index)&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;http://docs.microsoft.com/en-us/windows/desktop/api/setupapi/nf-setupapi-setupdigetdeviceinterfacedetailw&quot;&gt;&lt;code&gt;SetupDiGetDeviceInterfaceDetail()&lt;/code&gt;&lt;/a&gt;
holt uns den Pfad zum Gerät&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-createfilew&quot;&gt;&lt;code&gt;CreateFile()&lt;/code&gt;&lt;/a&gt;
öffnet das Gerät mittels des Geräte-Pfades&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://docs.microsoft.com/en-us/windows/desktop/api/bluetoothleapis/nf-bluetoothleapis-bluetoothgattgetservices&quot;&gt;&lt;code&gt;BluetoothGATTGetServices()&lt;/code&gt;&lt;/a&gt;
holt uns eine Liste der Services und deren 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Globally_Unique_Identifier&quot;&gt;GUIDs&lt;/a&gt; 
eines BTH-LE-Geräts.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Will man die Characteristics eines BTH-LE-Services auf einem Gerät lesen oder
schreiben, wird es etwas “tricky”:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Wir suchen mit der SetupDI* API
nach allen BTH-LE Services über die Klassen-Guid des Services, die wir zuvor 
mit &lt;code&gt;BluetoothGATTGetServices()&lt;/code&gt; erhalten haben.
    &lt;ul&gt;
      &lt;li&gt;Hier gibt es noch den Fall, dass ein Service eine “Short-ID” hat, wo nur 
die ersten Felder der GUID befüllt sind und die restlichen ausgenullt sind.
Bei der Such muss eine solche GUID aber immer auf: 
&lt;code&gt;XXXXXXXX-0000-1000-8000-00805f9b34fb&lt;/code&gt; enden.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Auch hier erhalten wir wieder einen Pfad zum “Service-Gerät”, den wir mit 
&lt;code&gt;CreateFile()&lt;/code&gt; öffnen können.&lt;/li&gt;
  &lt;li&gt;Mit der geöffnet Gerätedatei können wir nun die anderen APIs 
wie &lt;a href=&quot;https://docs.microsoft.com/en-us/windows/desktop/api/bluetoothleapis/nf-bluetoothleapis-bluetoothgattgetcharacteristics&quot;&gt;&lt;code&gt;BluetoothGATTGetCharacteristics&lt;/code&gt;&lt;/a&gt; 
nutzen um jede Einstellung auszulesen oder zu schreiben.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Dieser Schritt war mir nämlich lange nicht klar, und so scheiterte ich stets
daran, dass das &lt;code&gt;HANDLE&lt;/code&gt; zum Bluetooth-Geräte mit den Characteristic-APIs immer
den Code &lt;code&gt;ERROR_INVALID_FUNCTION&lt;/code&gt; zurück gab.
Nur wenn man genau hinsieht, ist bei &lt;code&gt;BluetoothGATTGetServices()&lt;/code&gt; von
&lt;code&gt;HANDLE hDevice&lt;/code&gt; die Rede, während &lt;code&gt;BluetoothGATTGetDescriptorValue()&lt;/code&gt; von
einem “Service HANDLE” spricht.&lt;/p&gt;

&lt;p&gt;Doch niemand sagt einem, dass das Service-HANDLE vom Device-HANDLE zu
unterscheiden ist.&lt;/p&gt;

&lt;p&gt;Daher nochmals:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;&lt;code&gt;BTH-LE-GUID -&amp;gt; Devices -&amp;gt; Device -&amp;gt; Service-Guids&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;Service-&amp;gt;Guid -&amp;gt; Service-Path -&amp;gt; Service-Handle&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;hr /&gt;

&lt;p&gt;So, jetzt kann ich alle Characteristics aller Services meiner Armbanduhr
“sehen” … allein fehlt mir jetzt noch die Info, was die Bytes bedeuten sollen.&lt;/p&gt;

&lt;p&gt;… also wird es Zeit für ein bisschen Herumprobieren.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Bluetooth</title>
   <link href="https://www.opengate.at/blog/2019/03/bluetooth/"/>
   <published>2019-03-18T19:07:00+01:00</published>
   <updated>2019-03-18T19:07:00+01:00</updated>
   <id>https://www.opengate.at/blog/2019/03/bluetooth</id>
   <category term="hardware" />
   <summary type="text">Ich erinnere mich noch an die alten Zeiten, wo wir mit Großmutter nach 
Brombeeren und 
Blaubeeren im Wald suchten und 
danach mit den blau gefärbten Zähnen Grimassen schnitten.

Das ist heute leider eine längst vergangene Geschichte, und obwohl es solche
Beeren auch im Supermarkt zu kaufen gibt, es ist einfach nicht mehr das selbe
wir damals mit Oma.

Doch dafür haben wir ja Bluetooth
… die “andere” 
WLAN -artige 
Technologie, die uns (theoretisch) Freude bereiten sollte.
</summary>
   <content type="html">&lt;p&gt;Ich erinnere mich noch an die alten Zeiten, wo wir mit Großmutter nach 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Brombeeren&quot;&gt;Brombeeren&lt;/a&gt; und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Heidelbeere&quot;&gt;Blaubeeren&lt;/a&gt; im Wald suchten und 
danach mit den blau gefärbten Zähnen Grimassen schnitten.&lt;/p&gt;

&lt;p&gt;Das ist heute leider eine längst vergangene Geschichte, und obwohl es solche
Beeren auch im Supermarkt zu kaufen gibt, es ist einfach nicht mehr das selbe
wir damals mit Oma.&lt;/p&gt;

&lt;p&gt;Doch dafür haben wir ja &lt;a href=&quot;https://de.wikipedia.org/wiki/Bluetooth&quot;&gt;Bluetooth&lt;/a&gt;
… die “andere” 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Wireless_Local_Area_Network&quot;&gt;WLAN&lt;/a&gt; -artige 
Technologie, die uns (theoretisch) Freude bereiten sollte.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;blockquote&gt;
  &lt;p&gt;Bluetooth ist wie 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Universal_Serial_Bus&quot;&gt;USB&lt;/a&gt; ohne Kabel.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So könnte man diesen drahtlosen Funkstandard vereinfachend beschreiben.
Denn es gibt eine Vielzahl von Geräten die “Bluetooth können” obwohl die 
benutzten Datenpakete und Funktionsweisen ganz unterschiedlich sind.&lt;/p&gt;

&lt;p&gt;So ähnlich ist das auch bei USB. Denn das interne USB-Datenaustauschprotokoll
stellt nur sicher, dass mehrere angeschlossene Geräte in einer Sternarchitektur
mit einem Host verbunden werden können und eindeutig adressiert werden.&lt;/p&gt;

&lt;p&gt;Anwendungen gibt es viele, und jede sieht anders aus. Letztendlich kümmern sich
&lt;a href=&quot;https://de.wikipedia.org/wiki/Gerätetreiber&quot;&gt;Gerätetreiber&lt;/a&gt; um die 
eigentliche Funktion und erzeugen im Betriebssystem virtuelle Geräteinstanzen 
wie &lt;a href=&quot;https://en.wikipedia.org/wiki/COM_(hardware_interface)&quot;&gt;COM Ports&lt;/a&gt;, 
Soundkarten, Dateisysteme, Tastaturen, Mäuse und andere Ein- und Ausgabeformen.&lt;/p&gt;

&lt;p&gt;Bluetooth macht das gleiche ohne Kabel, sendet ähnlich wie WLAN im 2.4 GHz 
Bereich und ist auf kurze Distanzen von 1 bis zu 10 Meter ausgelegt.
(Es soll auch stärkere Signalspezifikationen geben, doch die habe ich nie in 
der Praxis zu Gesicht bekommen.) Von daher kann es beim gleichzeitigen WLAN 
Betrieb auch zu Überlagerungen kommen, doch beide Protokolle sind fair zu 
einander und lassen sich gegenseitig “leben”.&lt;/p&gt;

&lt;p&gt;Programmiert wird Bluetooth normalerweise nicht über den Userspace, denn dort 
sind nur die virtuellen Geräte sichtbar. Man schreibt also Treiber für “sein”
Bluetoothgerät und nutzt dann die entsprechenden anderen OS-APIs um das
virtuelle Gerät zu bedienen.&lt;/p&gt;

&lt;p&gt;Es gibt allerdings 2 Ausnahmen:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Einerseits kann man das Scannen nach Bluetooth Geräten und das Verbinden 
mit diesen per Code anstoßen.&lt;br /&gt;
Das Pairing (die Verbindung zwischen Computer und Endgerät) über die
übliche 4-stellige PIN kann so automatisiert werden, weil jedes Geräte 
(ähnlich wie Netzwerk-Adapter) eine eindeutige MAC-Adresse hat und auch
einen Vendor-Code und einen Typen-Identifizierer generisch zur Verfügung 
stellt.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/RFCOMM&quot;&gt;RFCOMM&lt;/a&gt; ist ein Bluetooth-Unterprotokoll, 
welches (ohne spezielle Gerätetreiber) mehrere Datenkanäle zum 
Datenaustausch zwischen 2 Systemen bereitstellen kann. Und unsere 
Betriebssysteme überlassen uns den Zugang dazu über: YAY! 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Socket_(Software)&quot;&gt;Sockets&lt;/a&gt;!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Und somit kann man über RFCOMM bestehenden TCP/UDP Socket Code recyclen 
und über den Wechsel des Family-Flags von INET auf BTH relativ leicht
seine eigenen Protokolle auf Bluetooth portieren.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Unter Windows kann man verbundene Bluetooth-Geräte über 
&lt;a href=&quot;http://docs.microsoft.com/en-us/windows-hardware/drivers/install/setupapi&quot;&gt;Setup-Device-Interface&lt;/a&gt; 
API auflisten, doch seit &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_XP&quot;&gt;Windows XP&lt;/a&gt; 
SP2 liefert Microsoft auch eine eigene Bluetooth-API aus, die ähnlich zur 
FindFirstFile-API eine 
&lt;a href=&quot;http://docs.microsoft.com/en-us/windows/desktop/api/bluetoothapis/nf-bluetoothapis-bluetoothfindfirstdevice&quot;&gt;BluetoothFindFirstDevice&lt;/a&gt;
Funktionsreihe bereitstellt.&lt;/p&gt;

&lt;p&gt;Unter &lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt; habe ich bisher noch keine 
Programmiererfahrung mit Bluetooth sammeln können doch das werde ich 
hoffentlich in Zukunft mal nachholen können.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Im GATE Projekt ist die Windows-Bluetooth API im system Modul jedenfalls
implementiert. Neben Bluetooth existiert auch das moderne 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Bluetooth_Low_Energy&quot;&gt;Bluetooth LE&lt;/a&gt;,
das basierend auf dem BTH Standard 4.x eine erweiterte Spezifikation für
Geräte mit geringer Leistung bereitstellt und mit dem GATT Profile
(Generic Attribute Profile) eine neue Subprotokollspezifikation einführt,
die das generisch Auslesen und Verwaltung von Bluetooth LE Geräten 
und Sensoren ermöglicht.&lt;br /&gt;
Doch dazu kommen wir ein anderes mal.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>LED-Matrix</title>
   <link href="https://www.opengate.at/blog/2019/03/led-matrix/"/>
   <published>2019-03-17T21:33:00+01:00</published>
   <updated>2019-03-17T21:33:00+01:00</updated>
   <id>https://www.opengate.at/blog/2019/03/led-matrix</id>
   <category term="hardware" /><category term="devel" />
   <summary type="text">Na wer kennt sie nicht, diese Laufschrift-Anzeigetafeln, wo aus kleinen
(meist einfärbigen) Lichtpunkten Buchstaben geformt werden, die dann
durchlaufen.

Anfangs gab es das nur im Fernsehen bei diversen Börsen-Szenen zu sehen, 
wo stets irgend welche Kursdaten vorbeiliefen.

Dann hatten es die Geschäfte um auf Niedrigpreise aufmerksam zu machen.

Und heute bauen wir uns das in jedem 
Arduino
Anfängerlernpaket selbst zusammen.
</summary>
   <content type="html">&lt;p&gt;Na wer kennt sie nicht, diese Laufschrift-Anzeigetafeln, wo aus kleinen
(meist einfärbigen) Lichtpunkten Buchstaben geformt werden, die dann
durchlaufen.&lt;/p&gt;

&lt;p&gt;Anfangs gab es das nur im Fernsehen bei diversen Börsen-Szenen zu sehen, 
wo stets irgend welche Kursdaten vorbeiliefen.&lt;/p&gt;

&lt;p&gt;Dann hatten es die Geschäfte um auf Niedrigpreise aufmerksam zu machen.&lt;/p&gt;

&lt;p&gt;Und heute bauen wir uns das in jedem 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Arduino_(Plattform)&quot;&gt;Arduino&lt;/a&gt;
Anfängerlernpaket selbst zusammen.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;In vielen Arduino- und Sensor-Lernkits sind diese 8x8 LED Matrix Elemente
enthalten, mit denen man erste Experimente durchführen kann.
Und auch der &lt;a href=&quot;https://de.wikipedia.org/wiki/BBC_micro:bit&quot;&gt;Micro:bit&lt;/a&gt; hat 
eine 5x5 Matrix für einfache Lichterspiele verbaut.&lt;/p&gt;

&lt;p&gt;Interessanter werden aber etwas längere Ketten dieser Elemente, die man
bequem über &lt;a href=&quot;https://de.wikipedia.org/wiki/Serial_Peripheral_Interface&quot;&gt;SPI&lt;/a&gt; 
ansteuern kann.&lt;br /&gt;
Und so freue ich mich über meine 4 mal 8x8 Anfertigung.&lt;br /&gt;
&lt;img src=&quot;/blog/assets/img/led-matrix.jpg&quot; alt=&quot;LED-Matrix&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Nachdem heute (noch) nicht jeder solche Laufschriftanzeigen besitzt,
kann man dieses einfache Mittel dazu nutzen, Aufmerksamkeit auf sich
zu ziehen.&lt;br /&gt;
Das funktioniert gar nicht so schlecht auf Messen, wenn man ein solches
Teil gut auf seinem Stand platziert hat, oder es wie eine Halskette
mit sich herumträgt.&lt;/p&gt;

&lt;p&gt;Und schon kann man einige weitere Blicke auf “sich” ziehen.&lt;br /&gt;
Deshalb halte ich solche LED-Matrizen wirtschaftlich für die am besten direkt
nutzbaren Arduino-Bauteile. Sie sind leicht zu programmieren und können
für Werbe- und Infozwecke quasi überall eingesetzt werden.&lt;/p&gt;

&lt;p&gt;Andere Elemente wie “Metalldetektoren” oder Beschleunigungssensoren sind
auch ganz nett, aber wer nutzt schon solche Eigenfabrikate für tägliche Belange?&lt;/p&gt;

&lt;p&gt;Von daher ist die LED-Matrix (zumindest für mich) schon etwas besonderes.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Bei meinem Modell handelt es sich um einen MAX7219 LED Display Driver,
der häufiger in dieser Konfiguration zu finden ist. Gesteuert wird dieser
über SPI, doch nachdem es fertige Bibliotheken für die Matrix gibt, 
braucht man nicht selbst die Bytes entsprechend formatieren, sondern
nutzt eine vorhandene Sendefunktion.&lt;/p&gt;

&lt;p&gt;Was man aber oft selbst beisteuern muss, sind die Zeichen.
Und dank der Tatsache, dass wir eine 8x8 Matrix haben, lässt sich das
ganz einfach umsetzen:&lt;/p&gt;

&lt;p&gt;C und &lt;a href=&quot;https://en.wikipedia.org/wiki/C%2B%2B&quot;&gt;C++&lt;/a&gt; erlauben neben Dezimal- und
&lt;a href=&quot;https://de.wikipedia.org/wiki/Hexadezimalsystem&quot;&gt;Hexadezimal&lt;/a&gt; - und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Oktalsystem&quot;&gt;Oktalzahlen&lt;/a&gt;,
auch &lt;a href=&quot;https://de.wikipedia.org/wiki/Dualsystem&quot;&gt;binäre&lt;/a&gt; Zahlenangaben 
und sie haben die Form:&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; x =  B0001000; &lt;span style=&quot;color:#777&quot;&gt;// == 8&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;int&lt;/span&gt; y = &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;b0001010; &lt;span style=&quot;color:#777&quot;&gt;// == 10&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Und somit kann man einen Buchstaben wie ein großes &lt;code&gt;A&lt;/code&gt; wie folgt speichern:&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;unsigned&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt; CHAR_A[] = 
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;b00010000,
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;b00111000,
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;b01101100,
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;b11000110,
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;b11000110,
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;b11111110,
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;b11000110,
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;b11000110
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;};
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Man kann das Ergebnis fast wie als 
&lt;a href=&quot;https://de.wikipedia.org/wiki/ASCII-Art&quot;&gt;ASCII-Kunst&lt;/a&gt; im Quellcode erkennen 
und somit “mit den Bits zeichnen”.
Um ein solches Zeichen dann auf der LED-Matrix anzuzeigen, werden die 8 Bytes
mit ihren 8 Bits per SPI übertragen und schon leuchten die entsprechenden
LEDs auf, wenn ihr zugeordnetes Bit auf 1 gesetzt ist.&lt;/p&gt;

&lt;p&gt;Die verfügbaren Arduino-Bibliotheken erlauben auch mehrere Zeichen an mehrere
8x8 Module zu übertragen und unterstützen auch das Verschieben der Bits um die
Schrift von rechts nach links oder umgekehrt laufen zu lassen.&lt;br /&gt;
Die von mir getestete heißt schlicht und einfach &lt;code&gt;LedControl&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Coole Sache, dieses Teil. In wenigen Minuten hat man eine solche Laufschrift
fertig.&lt;br /&gt;
Jetzt kann man sich noch überlegen, ob man das Modul mit anderen Geräten 
koppeln will.&lt;br /&gt;
Beispiele wären &lt;a href=&quot;https://de.wikipedia.org/wiki/Bluetooth&quot;&gt;Bluetooth&lt;/a&gt; 
oder ein &lt;a href=&quot;https://de.wikipedia.org/wiki/ESP8266&quot;&gt;ESP&lt;/a&gt; um anzuzeigende Texte 
drahtlos zu empfangen.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Setup-Device-Interface API</title>
   <link href="https://www.opengate.at/blog/2019/03/device-setup-api/"/>
   <published>2019-03-16T21:16:00+01:00</published>
   <updated>2019-03-16T21:16:00+01:00</updated>
   <id>https://www.opengate.at/blog/2019/03/device-setup-api</id>
   <category term="devel" />
   <summary type="text">Unter dem Begriff “Hass-Liebe” findet man im guten Lexikon mein Foto 
neben einem Link zur Microsoft 
Windows 
Setup Device-Interface API.

Einerseits ist dieses Konstrukt ein schöner abstrakter Mechanismus um 
praktisches jedes erdenkliche Gerät anzusteuern, auf der anderen Seite 
zählt die genannte API zum schlimmsten Dokumentations-Chaos, das mir 
als Entwickler je untergekommen ist.
</summary>
   <content type="html">&lt;p&gt;Unter dem Begriff “Hass-Liebe” findet man im guten Lexikon mein Foto 
neben einem Link zur Microsoft 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows&quot;&gt;Windows&lt;/a&gt; 
Setup Device-Interface API.&lt;/p&gt;

&lt;p&gt;Einerseits ist dieses Konstrukt ein schöner abstrakter Mechanismus um 
praktisches jedes erdenkliche Gerät anzusteuern, auf der anderen Seite 
zählt die genannte API zum schlimmsten Dokumentations-Chaos, das mir 
als Entwickler je untergekommen ist.&lt;br /&gt;
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Wie so oft hängt alles an der Ablaufdokumentation. Jene der formalen API
ist eigentlich in Ordnung, doch die notwendige komplexe Zusammensetzung von
Aufrufen, die für jede Geräteform anders sein kann, findet man 
… &lt;em&gt;nirgends&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Tatsächlich ist die Device-Interface API gerade für meine Lieblingsbereiche
ein notwendiges Übel um an Pfade von Geräten zu kommen, die man dann 
öffnen und steuern will.
Die Funktion 
&lt;a href=&quot;http://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-createfilew&quot;&gt;&lt;code&gt;CreateFile()&lt;/code&gt;&lt;/a&gt;
öffnet ja bekanntlich nicht nur Dateien, sondern auch Geräte, vorausgesetzt 
der korrekte Pfad wird angegeben.&lt;/p&gt;

&lt;p&gt;Das komplizierte sind am Anfang die 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Globally_Unique_Identifier&quot;&gt;GUIDs&lt;/a&gt;, 
die Geräte und Geräteklassen identifizieren und der undurchsichtige 
Geräte-Baum, bei dem Bussysteme zu Bussystemen leiten, die wiederum Geräte 
beinhalten und dann an ganz anderen Ästen unter Umständen “Dienst-Geräte” 
liegen, die mit einem Gerät verknüpft sind.&lt;/p&gt;

&lt;p&gt;Und so kann es passieren, dass man zur Umsetzung einer Programmlogik
mehrere Geräte öffnen muss, die aber je nachdem, wo sie angebunden sind
(z.B. unterschiedliche USB Ports), dann andere interne Gerätepfade haben.&lt;/p&gt;

&lt;h3 id=&quot;setupdixxxxxx&quot;&gt;SetupDiXXXXXX&lt;/h3&gt;

&lt;p&gt;Wenn etwas mit dem Prefix &lt;code&gt;SetupDi&lt;/code&gt; beginnt, handelt es sich um die 
Setup Device Interface API, mit der Geräte aufgelistet oder deren
Eigenschaften ausgegeben werden können.&lt;/p&gt;

&lt;p&gt;Jedes angeschlossene reale oder virtuell generierte Gerät des Betriebssystems
kann durch diese API aufgelistet werden. Doch dazu brauchen wir stets die
richtigen GUIDs.&lt;/p&gt;

&lt;p&gt;Geräte sind dann zu allem Übel noch unterschiedlich sortiert. Die häufigste
Zuordnung erfolgt über die Geräte-Klassen-GUIDs, und einige davon sind 
auf den &lt;a href=&quot;https://docs.microsoft.com/en-us/windows-hardware/drivers/install/system-defined-device-setup-classes-available-to-vendors&quot;&gt;MSDN Seiten&lt;/a&gt;
dokumentiert.
Doch die dort genannten entspringen der Sortierung des Gerätemanagers, es
gibt aber noch andere, die auf zahlreiche Header je nach Typ verteilt sind:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;Ntddstor.h&lt;/code&gt; für storage drives&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;Bthdef.h&lt;/code&gt; für Bluetooth&lt;/li&gt;
  &lt;li&gt;usw.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Das nervige ist, wenn ein “sichtbares” Gerät unterschiedliche seiner Aspekte 
als Teil von unterschiedlichen Klassen implementiert.
So ist eine Festplatte als Festplattengerät registriert, aber gleichzeitig
auch als “Physisches Laufwerk” und auf sein Bits kann man nur über letztere
GUID zugreifen.&lt;/p&gt;

&lt;p&gt;Hat man aber seine GUID gefunden, geht es zügig weiter.&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://docs.microsoft.com/en-us/windows/desktop/api/setupapi/nf-setupapi-setupdigetclassdevsw&quot;&gt;&lt;code&gt;SetupDiGetClassDevs()&lt;/code&gt;&lt;/a&gt;
holt eine Liste der bekannten Geräteinstanzen einer GUID
    &lt;ul&gt;
      &lt;li&gt;Man erhält hier ein HANDLE, mit dem man alle anderen Daten abholen kann.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://docs.microsoft.com/en-us/windows/desktop/api/setupapi/nf-setupapi-setupdienumdeviceinterfaces&quot;&gt;&lt;code&gt;SetupDiEnumDeviceInterfaces()&lt;/code&gt;&lt;/a&gt;
liefert Infos zu einem Gerät (basierend auf dessen Index in der Liste)
    &lt;ul&gt;
      &lt;li&gt;Diese API ruft man beginnend beim Index 0 so lange hochzählend auf, 
bis man den Fehler &lt;code&gt;ERROR_NO_MORE_ITEMS&lt;/code&gt; zurück bekommt.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://docs.microsoft.com/en-us/windows/desktop/api/setupapi/nf-setupapi-setupdigetdeviceinterfacedetailw&quot;&gt;&lt;code&gt;SetupDiGetDeviceInterfaceDetail&lt;/code&gt;&lt;/a&gt;
holt uns den Pfad zum Gerät, damit wir es öffnen können.
    &lt;ul&gt;
      &lt;li&gt;Mit dem Pfad öffnet man dann einen COM-Port, eine Festplatte zum direkten 
Lesen der Datensektoren oder man verbindet sich so zu einem anderen 
Peripheriegerät um IOCTL Codes zu ihm zu schicken.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Auch interessant können diverse Einstellungen aus dem Registry-Bereich des 
Gerätes sein, und dafür nutzt man 
&lt;a href=&quot;http://docs.microsoft.com/en-us/windows/desktop/api/setupapi/nf-setupapi-setupdigetdeviceregistrypropertyw&quot;&gt;&lt;code&gt;SetupDiGetDeviceRegistryProperty&lt;/code&gt;&lt;/a&gt;.
Ich nutze häufig das Registry-Property &lt;code&gt;SPDRP_FRIENDLYNAME&lt;/code&gt;, mit dem man 
schnell auf die Bezeichnung des Geräts zugreifen kann, die man auch 
im Windows Geräte-Manager findet.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Natürlich kann man mit der Setup-API auch noch einiges mehr machen, 
wie z.B. &lt;a href=&quot;https://de.wikipedia.org/wiki/Gerätetreiber&quot;&gt;Treiber&lt;/a&gt; INF-Dateien 
installieren und weitere Infos auslesen wie auch Einstellungen verändern.&lt;/p&gt;

&lt;p&gt;Doch meiner Erfahrung nach ist es stets am mühsamsten, den richtigen Pfad
und die richtige Klassen-GUID für die gewünschte Anwendung zu finden,
bevor man sich denen Details der eigentlichen Aufgabe widmen kann.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Exceptions: Ausnahmen mit Fußspuren</title>
   <link href="https://www.opengate.at/blog/2019/03/exceptions/"/>
   <published>2019-03-15T20:18:00+01:00</published>
   <updated>2019-03-15T20:18:00+01:00</updated>
   <id>https://www.opengate.at/blog/2019/03/exceptions</id>
   <category term="devel" />
   <summary type="text">Um das Thema der Ausnahmebehandlung
(auch als Exceptions bekannt), sind schon mehrmals große Kriege entbrannt.
Am Ende geht es immer um die Frage:


  Wie viel Overhead wird durch Exceptions erzeugt?


Denn im “guten alten C” 
kommt man schließlich ohne dieses Konstrukt aus.
Meine Meinung dazu ist bekannt:
Exceptions sind eine wichtige Sprachbereicherung, solange man es nicht 
übertreibt.
</summary>
   <content type="html">&lt;p&gt;Um das Thema der &lt;a href=&quot;https://de.wikipedia.org/wiki/Ausnahmebehandlung&quot;&gt;Ausnahmebehandlung&lt;/a&gt;
(auch als Exceptions bekannt), sind schon mehrmals große Kriege entbrannt.
Am Ende geht es immer um die Frage:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Wie viel Overhead wird durch Exceptions erzeugt?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Denn im “guten alten &lt;a href=&quot;https://de.wikipedia.org/wiki/C_(Programmiersprache)&quot;&gt;C&lt;/a&gt;” 
kommt man schließlich ohne dieses Konstrukt aus.
Meine Meinung dazu ist bekannt:&lt;br /&gt;
Exceptions sind eine wichtige Sprachbereicherung, solange man es nicht 
übertreibt.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Das große Problem mit &lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B&quot;&gt;C++&lt;/a&gt; und seinen
Exceptions entstand leider zu einer sehr ungünstigen Zeit, die lange 
vergangen und großteils auch überwunden ist. Trotzdem halten sich Mythen aus
jenen Tagen bis heute und werden durch Wanderprediger immer wieder aufgefrischt.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Schuld sind Windows und X86!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Denn als mit &lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_Application_Programming_Interface&quot;&gt;WIN32&lt;/a&gt;
Structured Exceptions auf der Windows Architektur standardisiert
wurden und Compiler auf dieser Plattform sich an den vorgeschriebenen
Standard halten mussten, war die Welt noch sehr C-orientiert.
Programme und Bibliotheken kennen (bis heute) im Grunde genommen nur
flache Funktionen, die sich gegenseitig aufrufen … also genau das, 
was auch der Prozessor sieht.&lt;/p&gt;

&lt;p&gt;Exceptions wurden daher als Teil einer jeden Funktion implementiert.
Ein &lt;code&gt;try { ... } catch(...) { ... }&lt;/code&gt; führt demnach zu einigen 
Prozessor-Anweisungen, die den Fall einer Exception vorbereiten müssen,
um im Bedarfsfall den Programmfluss entsprechend umzuleiten.&lt;/p&gt;

&lt;p&gt;Schlimmer noch: Auch ohne &lt;code&gt;try/catch&lt;/code&gt; muss bei jedem Funktionsaufruf
die Möglichkeit beachtet werden, dass aus der Funktion “irgendwie” 
eine Exception zurückkommt.&lt;/p&gt;

&lt;p&gt;Hier lehnten sich C Programmierer gegen das neue Konzept auf und fanden
Beispiele, wo mit klassischen Status-Return-Codes nur eine Hand voll,
mit Exception aber ein Vielfaches an Instruktionen beim Übersetzen erzeugt 
wurde.&lt;/p&gt;

&lt;p&gt;Also JA, damals führte die Nutzung von Exception zur Erzeugung von großen
Codeblöcken, die aber nur im Ausnahmefall wirklich notwendig waren.
In Summe ergibt sich also ein messbarer Performanceabfall.&lt;/p&gt;

&lt;p&gt;Auf anderen Plattformen wie &lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt; mit 
dem GCC entwickelte man dieses Konzept weiter und änderte die Art, wie 
Exception-Code generiert wird. Denn bekanntlich schreibt der C++ Standard 
keine besondere Implementierung vor, im Gegenteil, man muss sogar damit 
rechnen, dass jeder Compiler den Code anders übersetzt.&lt;/p&gt;

&lt;p&gt;Und so schaffte es Microsoft erst mit der 
&lt;a href=&quot;https://de.wikipedia.org/wiki/64-Bit-Architektur&quot;&gt;64-bit Architektur&lt;/a&gt;, ein 
besseres Exception-Modell einzuführen, während auf der 32-bit Seite aus Gründen der
Kompatibilität das alte Model (zumindest teilweise) weiter zum Einsatz kommt.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Die Idee:&lt;/em&gt;&lt;br /&gt;
Exception-Code ist von regulärem Code separiert und vieles an “neuer Magie”
steckt im “Werfen” einer Ausnahme. Hier werden dann unterschiedliche 
Code-Tabellen benutzt, die das Zurückwandern durch den Callstack
(auch als Stack-Unwinding bekannt) bis zum nächsten &lt;code&gt;catch&lt;/code&gt; Block ermöglichen.&lt;/p&gt;

&lt;p&gt;Während also früher jede Funktion Exceptions entgegennehmen und selbst wieder
weiterleiten musste, findet dieser Part heute außerhalb der Funktion in jenen
Tabellen und zusätzlichen Hilfscode statt der zwischen den Funktionen
(oder auch ganz wo anders) liegt.&lt;/p&gt;

&lt;p&gt;Damit wird die reguläre Ausführung von Programmcode genau so schnell wie C
Code (teilweise sogar schneller, weil keine Status-Return-Values notwendig sind).
Und wenn es zum &lt;code&gt;throw&lt;/code&gt; kommen sollte, wird der Stack durch externen Code
zurückgerollt.&lt;/p&gt;

&lt;p&gt;Schließlich sind Exceptions ja “Ausnahmen” und nicht die Regel. Sie werden 
also nur im Notfall und damit hoffentlich eher selten ausgeführt, womit diese
Optimierung allen korrekten Ausführungspfaden Geschwindigkeitsvorteile 
verschafft.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Heute kann man daher nicht mehr wie früher argumentieren, Exception würden
die Code-Ausführung verlangsamen.&lt;/p&gt;

&lt;p&gt;Und es freut mich sehr, dass selbst damit die Weiterentwicklung nicht stehen
bleibt. Kürzlich sah ich erst, dass das Exception-Modell ständig weiter
optimiert und verbessert wird.&lt;/p&gt;

&lt;p&gt;So lange also Programmierer nicht den Fehler machen, Exceptions für reguläre
Ausführungszweige zu missbrauchen, so lange sind und bleiben Exceptions die 
heute beste Form der Fehlerbehandlung.&lt;/p&gt;

&lt;p&gt;Und wer sich für die neuesten Entwicklungen in Sachen Exceptions beim
&lt;code&gt;MSVC&lt;/code&gt; interessiert, der kann hier weiterlesen:&lt;br /&gt;
&lt;a href=&quot;https://devblogs.microsoft.com/cppblog/making-cpp-exception-handling-smaller-x64/?utm_source=vs_developer_news&amp;amp;utm_medium=referral&quot;&gt;Making C++ Exception Handling Smaller On x64&lt;/a&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>GPS und NMEA</title>
   <link href="https://www.opengate.at/blog/2019/03/gps-nmea/"/>
   <published>2019-03-14T16:18:00+01:00</published>
   <updated>2019-03-14T16:18:00+01:00</updated>
   <id>https://www.opengate.at/blog/2019/03/gps-nmea</id>
   <category term="hardware" />
   <summary type="text">Pokemon GO und andere Spielchen 
haben offenbart, wie stark wir Menschen heute mit Ortungsdaten konfrontiert 
sind. Es ist quasi zur Pflicht geworden, dass zu jeder Lebensminute auch eine
GPS-Position 
gespeichert wird.

Und niemand weiß, wie viele Ehen schon in die Brüche gingen, weil 
Facebook an die Partnerin 
meldete, dass der Gatte im übernächsten Nachbargarten sitzt und nicht wie 
“gemeldet” ein Meeting im Ausland hat.

Und das ist alles nur deshalb möglich, weil wir solche Empfänger mittragen,
die von ein paar Satelliten Signale auffangen …
</summary>
   <content type="html">&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Pokémon_Go&quot;&gt;Pokemon GO&lt;/a&gt; und andere Spielchen 
haben offenbart, wie stark wir Menschen heute mit Ortungsdaten konfrontiert 
sind. Es ist quasi zur Pflicht geworden, dass zu jeder Lebensminute auch eine
&lt;a href=&quot;https://de.wikipedia.org/wiki/Global_Positioning_System&quot;&gt;GPS-Position&lt;/a&gt; 
gespeichert wird.&lt;/p&gt;

&lt;p&gt;Und niemand weiß, wie viele Ehen schon in die Brüche gingen, weil 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Facebook_Inc.&quot;&gt;Facebook&lt;/a&gt; an die Partnerin 
meldete, dass der Gatte im übernächsten Nachbargarten sitzt und nicht wie 
“gemeldet” ein Meeting im Ausland hat.&lt;/p&gt;

&lt;p&gt;Und das ist alles nur deshalb möglich, weil wir solche Empfänger mittragen,
die von ein paar Satelliten Signale auffangen …
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Heutige Smartphones frustrieren mich als Software-Entwickler. Man hat eine 
Ortungs- und Logging-App in 20 Minuten fertig gestellt.&lt;br /&gt;
Keine Herausforderung, keine Motivation … einfach nur 0815.&lt;/p&gt;

&lt;p&gt;Die Schnittstellen in 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Android_(Betriebssystem)&quot;&gt;Android&lt;/a&gt;, 
&lt;a href=&quot;https://de.wikipedia.org/wiki/.NET_Framework&quot;&gt;dotNet Framework&lt;/a&gt; oder 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_Runtime&quot;&gt;WinRT&lt;/a&gt; laufen nach dem Schema:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;openPositionService()&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;registerEventHandler()&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;receivePositionObjects()&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;ab. … &lt;strong&gt;Langweilig!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Interessanter wird es mit 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Mikrocontroller&quot;&gt;Mikrocontrollern&lt;/a&gt; oder 
&lt;a href=&quot;https://de.wikipedia.org/wiki/NMEA_0183&quot;&gt;NMEA 0183&lt;/a&gt;-basierten GPS-Dongles.&lt;/p&gt;

&lt;h3 id=&quot;nmea&quot;&gt;NMEA&lt;/h3&gt;

&lt;p&gt;Das NMEA Protokoll ist ein uraltes zeilenbasiertes Textprotokoll, das
von einer Vielzahl von GPS-Empfänger-Chips unterstützt wird und seine
Daten über eine 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Serielle_Schnittstelle&quot;&gt;serielle Schnittstelle&lt;/a&gt; 
zur Verfügung stellt.&lt;/p&gt;

&lt;p&gt;Bei DIY Mikrocontroller Projekten ist das häufig ein 5 Volt TTL Signal,
aber alte 12 Volt &lt;a href=&quot;https://de.wikipedia.org/wiki/RS-232&quot;&gt;RS232&lt;/a&gt; COM-Port 
Schnittstellen gibt es sicher auch noch. Für PCs und Laptops haben sich 
USB-Dongles etabliert, die als virtuelle serielle Schnittstelle auftreten.&lt;/p&gt;

&lt;p&gt;Die Chips senden etwa im Sekunden- oder Zweisekundentakt Datenzeilen an den 
Empfänger, der sie parsen und interpretieren darf.&lt;/p&gt;

&lt;p&gt;Alle Zeilen beginnen mit einem Dollarzeichen und Datenfelder sind durch
Kommata getrennt. Der bekannteste Datensatz im GPS Bereich ist der 
&lt;code&gt;GPRMC&lt;/code&gt; Block (Recommended minimum specific GPS data). z.B.:&lt;br /&gt;
&lt;code&gt;$GPRMC,225446,A,4916.45,N,12311.12,W,000.5,054.7,191194,020.3,E*68&lt;/code&gt;&lt;br /&gt;
Er beinhaltet:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Uhrzeit &lt;code&gt;HHMMSS&lt;/code&gt;, also &lt;code&gt;22:54:46&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Status flag, &lt;code&gt;A&lt;/code&gt; = OK, &lt;code&gt;V&lt;/code&gt; = Warning&lt;/li&gt;
  &lt;li&gt;Breitengrad, 2 Stellen vor dem Dezimalpunkt sind Minutenangaben, alles davor sind Grad,
also &lt;code&gt;49 Grad, 16.45 Minuten&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Nord- oder Südhalbkugel der Breitengradangabe, &lt;code&gt;N&lt;/code&gt; = Nord, &lt;code&gt;S&lt;/code&gt; = Süd&lt;/li&gt;
  &lt;li&gt;Längengrad, wieder beginnt 2 Stellen vor dem Dezimalpunkt Minutenangabe und davor
befinden sich die ganzen Grade, also &lt;code&gt;123 Grad, 11.12 Minuten&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Ost- oder Westseite der Längengradangabe, &lt;code&gt;W&lt;/code&gt; = Westen, &lt;code&gt;E&lt;/code&gt; = Osten (East)&lt;/li&gt;
  &lt;li&gt;Geschwindigkeit über dem Boden in “Konten”, hier &lt;code&gt;000.5&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Kurs in Grad, hier &lt;code&gt;054.7&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Aktuelles 6-stelliges Datum, &lt;code&gt;19. November 1994&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Magnetische Variation, hier &lt;code&gt;20.3&lt;/code&gt; Grad&lt;/li&gt;
  &lt;li&gt;Richtung der magnetischen Variation, hier &lt;code&gt;E&lt;/code&gt; für Osten&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Optional können alle Zeilen durch eine Prüfsumme abgesichert werden, die mit einem 
Stern &lt;code&gt;*&lt;/code&gt; eingeleitet wird. Der XOR-basierte Prüfsummenalgorithmus ist sogar 
auf &lt;a href=&quot;https://en.wikipedia.org/wiki/NMEA_0183&quot;&gt;Wikipedia&lt;/a&gt; dokumentiert.&lt;/p&gt;

&lt;p&gt;Ein Line-Feed (&lt;code&gt;LF&lt;/code&gt;) Zeichen terminiert die Zeile.&lt;/p&gt;

&lt;p&gt;Es gibt aber noch zahlreiche andere Zeilenblöcke, die detailliert über die
Satellitenpositionen und mögliche Abweichungen berichten.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;NMEA und GPS sind eine geniale Sache und heute für den Eigenbau relativ günstig
zu erhalten.&lt;/p&gt;

&lt;p&gt;Das tolle an NMEA ist seine Einfachheit und die Tatsache, dass es 
mit einfachsten C-Funktionen implementiert werden kann. Und so kann man sich 
seinen eigen GPS-Empfänger leicht selbst bauen und wesentlich mehr Infos 
aus den Signalen herauslesen, als das unsere Smartphone APIs heute tun, um sich
bei Facebook und Co anzubiedern.&lt;/p&gt;

&lt;p&gt;Viele Elektronik-Läden führen zumindest einen USB-Dongle für den Laptop und 
für den Arduino DIY Bereich lässt sich schnell der eine oder andere Chip 
finden, der mit dem Lieblingsmikrocontroller über serielle TTL Bits redet.&lt;/p&gt;

&lt;p&gt;Anstatt also Pikachus und Taubsis in der Fußgängerzone am Smartphone zu jagen,
könnte man auch versuchen, sich eine Bluetooth und WLAN Karte beim Spaziergang
mitzuspeichern, wenn man empfangene Netze mit Ortungsdaten kombiniert.&lt;/p&gt;

&lt;p&gt;PS: Ich weiß … das gibt’s auch am Smartphone … aber selber bauen macht 
mehr Spaß.&lt;br /&gt;
Hier mein Bastel-Teil als Beispiel, Chip auf der einen Seite, Empfänger-Antenne
auf der anderen:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/gps-ttl-module.jpg&quot; alt=&quot;GPS TTL Module&quot; /&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>GSM und SMS Versand</title>
   <link href="https://www.opengate.at/blog/2019/03/gsm-module/"/>
   <published>2019-03-13T15:46:00+01:00</published>
   <updated>2019-03-13T15:46:00+01:00</updated>
   <id>https://www.opengate.at/blog/2019/03/gsm-module</id>
   <category term="hardware" />
   <summary type="text">Na, wer erinnert sich noch an die Zeiten, als Mobiltelefone mit einer 
Akkuladung eine Woche lang liefen und nicht so wie heute täglich an die 
Steckdose müssen, damit sie nicht elektrisch verdursten?

Damals, als das GSM 
Netz die Leute verband …

Das gibt es heute immer noch. Und während heute leider immer mehr auf 
IP-Dienste wie WhatsApp umgestellt
wird, hat es der SMS 
Dienst dennoch geschafft, diesen Trend (noch) zu überleben.
</summary>
   <content type="html">&lt;p&gt;Na, wer erinnert sich noch an die Zeiten, als Mobiltelefone mit einer 
Akkuladung eine Woche lang liefen und nicht so wie heute täglich an die 
Steckdose müssen, damit sie nicht elektrisch verdursten?&lt;/p&gt;

&lt;p&gt;Damals, als das &lt;a href=&quot;https://de.wikipedia.org/wiki/Global_System_for_Mobile_Communications&quot;&gt;GSM&lt;/a&gt; 
Netz die Leute verband …&lt;/p&gt;

&lt;p&gt;Das gibt es heute immer noch. Und während heute leider immer mehr auf 
IP-Dienste wie &lt;a href=&quot;https://de.wikipedia.org/wiki/WhatsApp&quot;&gt;WhatsApp&lt;/a&gt; umgestellt
wird, hat es der &lt;a href=&quot;https://de.wikipedia.org/wiki/Short_Message_Service&quot;&gt;SMS&lt;/a&gt; 
Dienst dennoch geschafft, diesen Trend (noch) zu überleben.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Tatsächlich war das vor … ähm … 15 Jahren mal so ein 
Bewerbungsgespräch-Test-irgendwas, wo ich gefragt wurde:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Stellen Sie sich vor, Sie müssten eine Plattform zum Versand von 
Mobiletelefon-Nachrichten wie SMS an den Start bringen.
Wie würden Sie vorgehen?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Natürlich hatte ich von der Technik keine Ahnung (der Fragesteller
wohl auch nicht) und so verlief das Gespräch eher auf der Ebene von
Pflichtenheft, Entwicklungsplan, usw.&lt;/p&gt;

&lt;p&gt;Heute weiß ich eigentlich auch nicht mehr darüber … aber wenn man
schon so ein nettes GSM-Bastelset für die 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Arduino_(Plattform)&quot;&gt;Arduino-Plattform&lt;/a&gt; sieht,
dann muss man natürlich zugreifen.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/gsm-module.jpg&quot; alt=&quot;GSM Module&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Die Idee: Ein Chip wird mit einer 
&lt;a href=&quot;https://de.wikipedia.org/wiki/SIM-Karte&quot;&gt;SIM-Karte&lt;/a&gt; verbunden und erhält über
eine &lt;a href=&quot;https://de.wikipedia.org/wiki/Serielle_Schnittstelle&quot;&gt;serielle Schnittstelle&lt;/a&gt; 
Kommandos, um über das Mobilfunknetz Kurznachrichten zu verschicken oder 
einfache &lt;a href=&quot;https://de.wikipedia.org/wiki/General_Packet_Radio_Service&quot;&gt;GPRS&lt;/a&gt;
Internet-Sockets aufzumachen.&lt;/p&gt;

&lt;p&gt;Nun, bei den Breitband-verliebten Social-Media-Selfie-Postern löst das
wahrscheinlich einen Lachkrampf aus, wenn wir von “Datendiensten” des
vergangenen Jahrhunderts sprechen, wo einzelne Kilobyte-Übertragungen
mehrere Sekunden brauchen und dann auch noch so teuer wie ein Gigabyte
im Breitbandbereich sind.&lt;/p&gt;

&lt;p&gt;Doch Tatsache ist, dass das GSM Netz auch im ländlichen Bereich relativ
gut ausgebaut ist, während Breitband durch ungünstige Konstellationen
sogar bei mir in Wien an manchen Ecken einfach versagt.&lt;/p&gt;

&lt;p&gt;An einer Wand in meiner Wohnung passiert es, dass meine UMTS-Sticks am Abend
auf GPRS zurückschalten, womit “das heutige Internet” unbenutzbar wird.&lt;/p&gt;

&lt;p&gt;Und wer &lt;a href=&quot;https://de.wikipedia.org/wiki/Internet_der_Dinge&quot;&gt;IoT&lt;/a&gt; überall 
verbreiten will, bereitet seine Projekte protokoll-technisch eben auch auf 
solche Szenarien vor.&lt;br /&gt;
Angenommen, wir wollen in der Wildnis eine Sensorstation betreiben,
wo wir keinen Netzstrom oder Funkbreitbandanbindung haben. Dort können wir
mit Daten in kleinen Mengen per SMS oder GPRS zu einer Datensammelstelle
schicken.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Als ich daher die NEOWAY-M590-E DIY-Platine sah, war klar, dass ich das
Teil ausprobieren musste.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Ergebnis:&lt;/em&gt; Naja, bisher leider enttäuschend.&lt;/p&gt;

&lt;p&gt;Ich weiß noch nicht, ob es an der mitgelieferten Antenne liegt oder ein
anderes Problem vorliegt, doch Kontakt zum Funknetz erhalte ich bislang
noch keinen dauerhaften.&lt;/p&gt;

&lt;p&gt;Obwohl die Schnellstelle über 
&lt;a href=&quot;/blog/2019/03/at-commands/&quot;&gt;AT-Kommandos&lt;/a&gt; 
natürlich ein Vergnügen ist, denn so lässt sich mit dem 
&lt;a href=&quot;http://www.microchip.com/wwwproducts/en/ATMEGA328&quot;&gt;ATMEGA328&lt;/a&gt; problemlos ein
Datensatz ins Funknetz überspielen … theoretisch.&lt;/p&gt;

&lt;p&gt;“Billig” ist auch der Aufbau der Platine, denn weil das Gerät eigentlich 
für 3 bis 4.5 Volt ausgelegt ist, muss die Spannung vom Arduino-Board
gedrosselt werden.&lt;br /&gt;
Und das wird mit einer simplen Diode umgesetzt, die zwischen 0.5 und 0.7
Volt Spannungsverlust produziert und damit die 5 Volt des Arduinos in den
spezifizierten Spannungsbereich senkt.&lt;/p&gt;

&lt;p&gt;Einige andere Blogger beschreiten daher den Weg anders: Sie entfernen bzw.
überbrücken die Diode und betreiben das Gesamtsystem mit 3.3 Volt.&lt;/p&gt;

&lt;p&gt;Nun, soweit bin ich noch nicht und vielleicht komme ich ja noch dazu die
Platine entsprechend umzubauen.&lt;/p&gt;

&lt;p&gt;Denn lustig wäre es ja schon, wenn man z.B. einen per Solarpanel und Akku
betriebenen Temperatursensor am Baum im Garten hinterm Haus anbringt,
und täglich den “tatsächlichen” Wetterbericht ins Haus geschickt bekommt.&lt;/p&gt;

&lt;p&gt;… mal sehen ob sich da in Zukunft was ergibt.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>AT Kommandos</title>
   <link href="https://www.opengate.at/blog/2019/03/at-commands/"/>
   <published>2019-03-12T15:33:00+01:00</published>
   <updated>2019-03-12T15:33:00+01:00</updated>
   <id>https://www.opengate.at/blog/2019/03/at-commands</id>
   <category term="devel" />
   <summary type="text">Die Meldung “Achtung! Aufgepasst!”, oder englisch “Attention!” leitete in der
guten alten Modem-Zeit eine 
Kommando-Sequenz ein.

Diese ATtention Kommandos 
waren einfache Textzeilen, die immer mit AT eingeleitete wurden um etwas 
abzufragen oder etwas auszulösen.

Die alten Telefonmodems, für welche dieses Protokoll erfunden wurde, stehen
heute nur noch im Museum, doch AT-Kommandos erfreuen sich weiter einer
großen Beliebtheit in ganz anderen Gebieten der Technik.
</summary>
   <content type="html">&lt;p&gt;Die Meldung “Achtung! Aufgepasst!”, oder englisch “Attention!” leitete in der
guten alten &lt;a href=&quot;https://de.wikipedia.org/wiki/Modem&quot;&gt;Modem&lt;/a&gt;-Zeit eine 
Kommando-Sequenz ein.&lt;/p&gt;

&lt;p&gt;Diese &lt;a href=&quot;https://de.wikipedia.org/wiki/AT-Befehlssatz&quot;&gt;&lt;code&gt;AT&lt;/code&gt;tention&lt;/a&gt; Kommandos 
waren einfache Textzeilen, die immer mit &lt;code&gt;AT&lt;/code&gt; eingeleitete wurden um etwas 
abzufragen oder etwas auszulösen.&lt;/p&gt;

&lt;p&gt;Die alten Telefonmodems, für welche dieses Protokoll erfunden wurde, stehen
heute nur noch im Museum, doch AT-Kommandos erfreuen sich weiter einer
großen Beliebtheit in ganz anderen Gebieten der Technik.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Von ihrem Aufbau her, bin ich kein Freund von AT-Kommandos in modernen 
Anwendungen. Sie wurden - ähnlich wie 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Hypertext_Transfer_Protocol&quot;&gt;HTTP&lt;/a&gt; - so 
gewählt, dass Menschen sie zur Not auch manuell in Terminals eintippen konnten
und sind daher der menschlichen Sprache nachempfunden.&lt;/p&gt;

&lt;p&gt;Für jede Abfrage gibt es “einfach so” eine Antwort. Das hört sich leicht
und verständlich an, ist aber - wie bei uns Menschen auch - recht 
fehleranfällig.&lt;/p&gt;

&lt;p&gt;Alles läuft nach folgendem Schema ab:&lt;/p&gt;

&lt;p&gt;Kommando:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;ATmachwas mit X
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Antwort:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;X ist fertig
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;OK
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Oder im Fehlerfall lautet die Antwort einfach:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;ERROR
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Schon bei der Frage, wie der Zeilenwechsel aussieht, wird es zwischen 
Implementierungen schwammig, weil einige &lt;code&gt;CR+LF&lt;/code&gt; als Zeilenende anerkennen,
während anderen nur mit einem alleinigen &lt;code&gt;LF&lt;/code&gt; umgehen können.&lt;/p&gt;

&lt;p&gt;Noch schlimmer wird es, wenn man mehrere Anfragen abschickt.&lt;br /&gt;
Es gibt keine IDs die Antworten mit Anfragen verknüpfen können, und so
ist auch hier fraglich, ob man z.B. auf zwei parallele Anfragen nur die
erste, nur die zweite oder beide beantwortet bekommt.&lt;/p&gt;

&lt;p&gt;Und da AT Kommandos häufig über 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Serielle_Schnittstelle&quot;&gt;serielle Verbindungen&lt;/a&gt; 
geschleust werden, kann auch schnell mal ein Byte verloren gehen. Das ist dann
eben Pech und der Parser auf der Gegenseite darf entweder sehr kreativ 
reagieren oder die Anfrage ignorieren. Eine standardisierte Fehlerkontrolle 
gibt es hierfür leider nicht.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;AT Kommandos haben aber den Vorteil, dass sie besonders in 
&lt;a href=&quot;https://de.wikipedia.org/wiki/C_(Programmiersprache)&quot;&gt;C&lt;/a&gt; leicht implementiert
werden können. Viele Codeumsetzungen kommen mit
&lt;a href=&quot;https://de.wikipedia.org/wiki/Printf&quot;&gt;&lt;code&gt;printf()&lt;/code&gt;&lt;/a&gt;, 
&lt;a href=&quot;http://www.cplusplus.com/reference/cstdio/scanf/&quot;&gt;&lt;code&gt;scanf()&lt;/code&gt;&lt;/a&gt; und
&lt;a href=&quot;http://www.cplusplus.com/reference/cstring/strcmp/&quot;&gt;&lt;code&gt;strcmp()&lt;/code&gt;&lt;/a&gt; aus und das 
erklärt, warum dieses uralte Protokoll-Skelett schon so viele Jahre lebt 
und überlebt hat.&lt;/p&gt;

&lt;p&gt;Doch welche Kommandos verfügbar sind, ist und bleibt Hersteller- und 
anwendungsspezifisch.&lt;br /&gt;
Denn heute finden wir AT-Kommandos in vielen Geräten, die Kommunikationsflüsse
verwalten und steuern sollen. Von LTE und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/UMTS-Modem&quot;&gt;UMTS Sticks&lt;/a&gt;, über WLAN- und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Bluetooth&quot;&gt;Bluetooth Chips&lt;/a&gt; bis hin zu GPS oder 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Global_System_for_Mobile_Communications&quot;&gt;GSM&lt;/a&gt; 
Empfängern.&lt;/p&gt;

&lt;p&gt;Die Kommandos sind dabei entweder die primäre Schnittstelle um mit dem 
Gerät zu interagieren, oder aber eine separate Verwaltungsschnittstelle
um Parameter des eigentlichen primären Protokolls anzupassen.&lt;/p&gt;

&lt;h3 id=&quot;beispiele&quot;&gt;Beispiele&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Mein USB UMTS Stick meldet sich mit 2 COM-Ports. Einer simuliert eine alte
Modem-Schnittstelle, wo über AT-Kommandos eingewählt und aufgelegt werden 
kann. Ein weitere Port erlaubt separate Verwaltungs-AT-Kommandos.&lt;/li&gt;
  &lt;li&gt;Für den &lt;a href=&quot;https://de.wikipedia.org/wiki/ESP8266&quot;&gt;ESP8266&lt;/a&gt; und seine 
Nachfolger gibt es eigente AT-Firmwares, die gerne mit 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Arduino_(Plattform)&quot;&gt;Arduino&lt;/a&gt; Projekten 
genutzt werden. Der Arduino steuert über AT-Kommandos den Aufbau von 
WLAN-Verbindungen und sogar einfache Socket-Verbindungen.&lt;/li&gt;
  &lt;li&gt;Bluetooth Chips für MCU-Projekte nutzen ebenso AT-basierte Befehle um
Daten an verbundene Geräte zu übertragen oder von diesen Daten zu lesen.&lt;/li&gt;
  &lt;li&gt;GSM/GPRS Module werden ebenfalls mit AT-Firmwares geliefert um Funktionen
wie SMS-Versand oder Internetkommunikation zu initiieren.&lt;/li&gt;
  &lt;li&gt;Und auch für diverse Mikrocontroller existieren AT-Subkommandos um 
z.B. ihre PINs zu verwalten.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Das Senden von AT-Kommandos und das Parsen der Antworten gehört also 
weiterhin zu meinen Aufgaben. Einerseits in privaten MCU-Bastelleien, aber 
andererseits auch zur Ansteuerung anderer Geräte über 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Internet_der_Dinge&quot;&gt;IoT&lt;/a&gt; Brücken.&lt;/p&gt;

&lt;p&gt;Lieber wären mir binäre Protokolle, die mit eindeutigen IDs und 
standardisierten Headern arbeiten, anstatt aus Textantworten Zustände
deuten zu müssen.&lt;/p&gt;

&lt;p&gt;Doch andererseits ist dieses Schema lange bewährt und - wie gesagt -
einfach und relativ platz- bzw. codesparend umzusetzen.&lt;/p&gt;

&lt;p&gt;Und dass dabei ein bisschen Retro-Feeling aufkommt, wenn ich die heutige
Highspeed Internetverbindung mit den gleichen Kommandos aufbauen kann,
wie damals mit einem 56K Modem, darf man ja auch nicht gering schätzen …&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>BBC micro:bit</title>
   <link href="https://www.opengate.at/blog/2019/03/microbit/"/>
   <published>2019-03-11T15:46:00+01:00</published>
   <updated>2019-03-11T15:46:00+01:00</updated>
   <id>https://www.opengate.at/blog/2019/03/microbit</id>
   <category term="hardware" />
   <summary type="text">Wenn ich eines emotional überhaupt nicht verkraften kann, dann sind das 
14-jährige Jungs, die mehr über Technik wissen, als ich.

So geschehen letzten Freitag im CoderDojo, das
einige Beispielprogramme für die micro:bit
Platine in seinen Übungsmappen hat.

Also in die Schuhe, auf zum Händler, genommen, bezahlt und zurück nach Hause.
</summary>
   <content type="html">&lt;p&gt;Wenn ich eines emotional überhaupt nicht verkraften kann, dann sind das 
14-jährige Jungs, die mehr über Technik wissen, als ich.&lt;/p&gt;

&lt;p&gt;So geschehen letzten Freitag im &lt;a href=&quot;http://wien.coderdojo.net/&quot;&gt;CoderDojo&lt;/a&gt;, das
einige Beispielprogramme für die &lt;a href=&quot;https://de.wikipedia.org/wiki/BBC_micro:bit&quot;&gt;micro:bit&lt;/a&gt;
Platine in seinen Übungsmappen hat.&lt;/p&gt;

&lt;p&gt;Also in die Schuhe, auf zum Händler, genommen, bezahlt und zurück nach Hause.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Das nette bei &lt;a href=&quot;https://www.semaf.at/&quot;&gt;SEMAF ELECTRONICS&lt;/a&gt; ist, dass immer noch 
Zeit zum Plauschen bleibt. Und so freut es mich sehr nun zu wissen, dass
Dank einiger neuer Projekte endlich mal ein Umdenken in Österreich’s Schulen
stattfindet und Mikrocontroller Programmierung ebenso auf dem Stundenzettel 
steht.&lt;/p&gt;

&lt;p&gt;Schließlich stamme ich ja noch aus einer Zeit, wo einige Lehrer mir 
angewidert entgegneten&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Lass mich mit deinem Blechtrottel in Ruhe.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Für Jungs und Mädels von heute ist der von der 
&lt;a href=&quot;https://de.wikipedia.org/wiki/British_Broadcasting_Corporation&quot;&gt;BBC&lt;/a&gt; 
unterstütze Einplatinencomputer “micro:bit” mit seinem&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/ARM_Cortex-M&quot;&gt;ARM-Cortex-M0&lt;/a&gt; Prozessor&lt;/li&gt;
  &lt;li&gt;256 KB &lt;a href=&quot;https://de.wikipedia.org/wiki/Flash-Speicher&quot;&gt;Flash Speicher&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;16 KB &lt;a href=&quot;https://de.wikipedia.org/wiki/Random-Access_Memory&quot;&gt;RAM&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Bluetooth &lt;a href=&quot;https://de.wikipedia.org/wiki/Bluetooth_Low_Energy&quot;&gt;Low Energy&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;3-Achsen &lt;a href=&quot;https://de.wikipedia.org/wiki/Beschleunigungssensor&quot;&gt;Beschleunigungssensor&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;5x5 &lt;a href=&quot;http://www.mikrocontroller.net/articles/LED-Matrix&quot;&gt;LED Matrix&lt;/a&gt; Display&lt;/li&gt;
  &lt;li&gt;über 20 &lt;a href=&quot;https://de.wikipedia.org/wiki/Allzweckeingabe/-ausgabe&quot;&gt;GPIO Pins&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;und weiteren Features&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;ein gelungenes System für Anfänger und Hobbybastler.&lt;/p&gt;

&lt;p&gt;Während z.B. ein &lt;a href=&quot;https://en.wikipedia.org/wiki/Arduino_Uno&quot;&gt;Arduino UNO&lt;/a&gt; 
ohne Sensoren kommt, hat der micro:bit schon vieles on-board, was zum ersten 
Experimentieren mit Hardware hilfreich ist.&lt;/p&gt;

&lt;p&gt;Das besondere sind aber die für Anfänger hilfreichen 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Integrierte_Entwicklungsumgebung&quot;&gt;IDEs&lt;/a&gt; zum 
grafischen Programmieren.&lt;br /&gt;
Für Windows 10 stellt die &lt;a href=&quot;http://microbit.org/code/&quot;&gt;MakeCode&lt;/a&gt; App eine 
an &lt;a href=&quot;https://de.wikipedia.org/wiki/Scratch_(Programmiersprache)&quot;&gt;Scratch&lt;/a&gt; 
erinnernde Benutzerschnittstelle zur Verfügung, in welcher Anweisungen, 
Verzweigungen und Schleifen als grafische Blöcke per 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Drag_and_Drop&quot;&gt;Drag and Drop&lt;/a&gt; 
platziert werden können.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/micro-bit-ide.png&quot; alt=&quot;micro:bit MakeCode&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Das erlaubt auch das Programmieren auf reinen Touch-Oberflächen und gestattet
so das Coden auf Smartphones und Tablets, die für klassische Textschreiber
wie mich bisher ungenutzt geblieben sind.&lt;/p&gt;

&lt;p&gt;Für unsere Kids ist diese Herangehensweise aber vorteilhaft, da man mit wenigen
Klicks etwas zum Leuchten bringen kann und der in uns allen vorhandene 
Spieltrieb kümmert sich dann um das weitere Erforschen der Möglichkeiten.&lt;/p&gt;

&lt;p&gt;Doch damit nicht genug.&lt;br /&gt;
Natürlich kann man den micro:bit auch per klassischen Programmcode steuern,
auch für die &lt;a href=&quot;http://www.arduino.cc/en/main/software&quot;&gt;Arduino IDE&lt;/a&gt; gibt es 
entsprechende Plugins um die Pins der 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Mikrocontroller&quot;&gt;MCU&lt;/a&gt; zu dirigieren.&lt;/p&gt;

&lt;p&gt;Das integrierte Bluetooth Modul machten die micro:bit Platine zum 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Internet_der_Dinge&quot;&gt;IoT&lt;/a&gt; -
Experimentierkasten, und erlaubt uns die Funktionen des Systems
per Smartphone App oder vom PC aus fern zu steuern.&lt;/p&gt;

&lt;p&gt;Und dann gibt es noch mehrere Upgrades mit 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Servomotor&quot;&gt;Servomotoren&lt;/a&gt; und weiteren 
Sensoren, um daraus kleine Roboter zu bauen.&lt;br /&gt;
Ein solcher ist der 
&lt;a href=&quot;http://www.kitronik.co.uk/5624-move-mini-buggy-kit-excl-microbit.html&quot;&gt;:MOVE mini buggy kit&lt;/a&gt;, 
den ich ebenso einfach gleich mitkaufen musste.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/micro-bit-buggy.jpg&quot; alt=&quot;micro:bit Buggy&quot; /&gt;
(Die LEDs des Buggys sind echt grell!)&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Jetzt werde ich mir den kleinen Alleskönner von micro:bit mal genauer unter
die Lupen nehmen, damit ich beim nächsten Zusammentreffen mit unserer Jugend
auch mitreden kann.&lt;/p&gt;

&lt;p&gt;Und ich kann nur sagen, dass ich mich enorm freue, dass unser Nachwuchs dank
solcher spielerischen Projekte ordentlich auf Zack ist, und dass das Lernen
an unseren Schulen auf diese sinnvolle Weise gefördert wird.&lt;/p&gt;

&lt;p&gt;Allen, die noch nicht die Chance haben, mit solchen Geräten am Bildungsweg
in Berührung zu kommen, denen empfehle ich die 20 Euro selbst zu investieren,
denn das Ergebnis ist eine junge Generation, die auf die Herausforderungen der
nahen Zukunft vorbereitet sein wird.&lt;br /&gt;
… und was wünscht man sich mehr …&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Mein C64 ist tot</title>
   <link href="https://www.opengate.at/blog/2019/03/c64/"/>
   <published>2019-03-10T21:52:00+01:00</published>
   <updated>2019-03-10T21:52:00+01:00</updated>
   <id>https://www.opengate.at/blog/2019/03/c64</id>
   <category term="retro" />
   <summary type="text">Im Jahr 1996 habe ich ihn von einem Lehrer an der Schule geschenkt bekommen,
und ich liebte diese hellgrau-braune Kiste: 
Mein alter Commodore 64.

Die hohen Zeiten der Heimcomputer 
hatte ich natürlich nicht mehr miterlebt, doch schon damals, als gerade mein 
Wechsel von DOS zu 
Windows 95 stattfand,
hatte dieser Großvater der PCs auch meine Aufmerksamkeit.

… vor allem weil Programmierung dort kein Zusatz sondern eine absolute 
Notwendigkeit war. Und so entstand nebenbei eine nette Freundschaft zum
PC-Kollegen aus dem vergangenen Jahrzehnt.
</summary>
   <content type="html">&lt;p&gt;Im Jahr 1996 habe ich ihn von einem Lehrer an der Schule geschenkt bekommen,
und ich liebte diese hellgrau-braune Kiste: 
Mein alter &lt;a href=&quot;https://de.wikipedia.org/wiki/Commodore_64&quot;&gt;Commodore 64&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Die hohen Zeiten der &lt;a href=&quot;https://de.wikipedia.org/wiki/Heimcomputer&quot;&gt;Heimcomputer&lt;/a&gt; 
hatte ich natürlich nicht mehr miterlebt, doch schon damals, als gerade mein 
Wechsel von &lt;a href=&quot;https://de.wikipedia.org/wiki/MS-DOS&quot;&gt;DOS&lt;/a&gt; zu 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_95&quot;&gt;Windows 95&lt;/a&gt; stattfand,
hatte dieser Großvater der PCs auch meine Aufmerksamkeit.&lt;/p&gt;

&lt;p&gt;… vor allem weil Programmierung dort kein Zusatz sondern eine absolute 
Notwendigkeit war. Und so entstand nebenbei eine nette Freundschaft zum
PC-Kollegen aus dem vergangenen Jahrzehnt.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/commodore64.jpg&quot; alt=&quot;C64&quot; /&gt;
(Grafik von &lt;a href=&quot;https://upload.wikimedia.org/wikipedia/commons/9/9d/Commodore-64-Computer-FL.png&quot;&gt;Wikipedia&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;Wir sind heute gewohnt, dass jeder Computer mit einem Betriebssystem 
ausgeliefert wird und dieses automatisch beim Einschalten startet.
Und wir erwarten, dass das Betriebssystem uns eine “einfache” Möglichkeit
bietet Programme zu starten und Dateien zu verwalten.&lt;br /&gt;
Selbst das alte &lt;a href=&quot;https://de.wikipedia.org/wiki/MS-DOS&quot;&gt;DOS&lt;/a&gt; verfolgte schon 
diesem Ansatz.&lt;/p&gt;

&lt;p&gt;Doch das war nicht immer so.&lt;/p&gt;

&lt;p&gt;Wer seinen C64 einschaltete landete vor einem 
&lt;a href=&quot;https://de.wikipedia.org/wiki/BASIC&quot;&gt;BASIC&lt;/a&gt; Interpreter und konnte 
grundsätzlich nichts anderes tun, als Programmier-Kommandos einzutippen.
… und mit BASIC war das alte Zeilennummern-BASIC gemeint und nicht 
die Luxusformen, die wir mit 
&lt;a href=&quot;https://de.wikipedia.org/wiki/QBasic&quot;&gt;QBASIC&lt;/a&gt;,
&lt;a href=&quot;https://de.wikipedia.org/wiki/FreeBASIC&quot;&gt;FreeBASIC&lt;/a&gt; oder 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_Basic_Classic&quot;&gt;Visual Basic&lt;/a&gt; heute kennen.&lt;/p&gt;

&lt;p&gt;Das nenn’ ich mal Programmierer-freundlich: Einschalten, losproggen!&lt;/p&gt;

&lt;p&gt;Wer BASIC Programme schreiben wollte, startete jede Zeile mit einer 
Zeilennummer, meist in Zehnerschritten (10, 20, 30) und anschließend
dem eigentlichen Kommando.&lt;br /&gt;
Diese Kommandos waren zwingend einzeilig und man konnte nicht wie heute
üblich Blöcke einrücken um Verzweigungen auszuführen.&lt;/p&gt;

&lt;p&gt;Dafür gab es &lt;code&gt;GOTO&lt;/code&gt; (Gehe-zu). Was wir heute in der Programmierung als Missgeburt
bezeichnen, war damals Kernfunktion eines jeden Programmes.
Man führte ein Kommando aus und hüpfte dann z.B.: per &lt;code&gt;GOTO 120&lt;/code&gt; zur
Zeile mit der Nummer 120 um dort das nächste Kommando auszuführen.&lt;br /&gt;
z.B.: &lt;code&gt;100 IF A = B THEN GOTO 200 ELSE GOTO 300&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Neben alten Klassikern wie &lt;code&gt;PRINT&lt;/code&gt; um Text und Variablen auszugeben, 
und &lt;code&gt;INPUT&lt;/code&gt; zum Einlesen von Tastatureingaben, waren die beiden 
Hardcore-Vokabel &lt;a href=&quot;https://de.wikipedia.org/wiki/POKE_und_PEEK&quot;&gt;&lt;code&gt;PEEK&lt;/code&gt; und &lt;code&gt;POKE&lt;/code&gt;&lt;/a&gt; 
sehr beliebt.&lt;br /&gt;
Denn die beiden Kommandos lasen direkt von einer Speicheradresse einen Wert,
beziehungsweise schrieben einen neuen in eine Speicherzelle.&lt;/p&gt;

&lt;p&gt;Und nachdem fast alles von Grafik bis Gerätesteuerung auf eine bestimmte 
Speicheradresse abgebildet war, wurden per &lt;code&gt;PEEK&lt;/code&gt; und &lt;code&gt;POKE&lt;/code&gt; kryptische 
Zahlenorgien in Programme gepackt, die Grafikanimationen und Soundeffekte 
produzieren konnten.&lt;/p&gt;

&lt;p&gt;Es war wie eine Mathe-Olympiade für Brillenträger in einer ägyptischen Pyramide,
wenn es darum ging zu verstehen, was mit diesen &lt;code&gt;PEEKs&lt;/code&gt; und &lt;code&gt;POKEs&lt;/code&gt; tatsächlich 
bewirkt werden sollte.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Und die Nicht-Programmierer mussten mindestens die Kommandos&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;LOAD &quot;*&quot;, 8&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;und &lt;code&gt;RUN&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;kennen, womit ein Programm von &lt;a href=&quot;https://de.wikipedia.org/wiki/Diskette&quot;&gt;Diskette&lt;/a&gt;
in den Speicher geladen (&lt;code&gt;LOAD&lt;/code&gt;) und dann ausgeführt werden sollte (&lt;code&gt;RUN&lt;/code&gt;).
Jedes Spiel und jedes Programm lag auf seiner eigenen Disk und wurde auf 
diese Weise per “Programmcode” geladen und ausgeführt.&lt;/p&gt;

&lt;p&gt;Ich erinnere mich noch gut an Klassiker wie 
&lt;a href=&quot;https://de.wikipedia.org/wiki/The_Great_Giana_Sisters&quot;&gt;Great Giana Sisters&lt;/a&gt;,
einem C64-Supermario-Äquivalent mit seinem unverkennbarem Intro, 
oder &lt;a href=&quot;http://www.c64-wiki.com/wiki/Mikie&quot;&gt;Mikie&lt;/a&gt; und ja, genau so einen 
Lehrer wie im Spiel hatte ich auch in meiner Schule.&lt;/p&gt;

&lt;p&gt;Allerdings sah ich diese Spiele nie in Farbe sondern in Schwarz-Grün, weil 
der Monitor nur grüne Bildpunkte auf der Mattscheibe zum Leuchten bringen 
konnte.&lt;/p&gt;

&lt;iframe width=&quot;640&quot; height=&quot;360&quot; src=&quot;/blog/redirect.html?https%3A%2F%2Fwww.youtube-nocookie.com%2Fembed%2FNe-09Bs_bRo&quot; frameborder=&quot;1&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;

&lt;iframe width=&quot;640&quot; height=&quot;360&quot; src=&quot;/blog/redirect.html?https%3A%2F%2Fwww.youtube-nocookie.com%2Fembed%2FeXORrpL7IHI&quot; frameborder=&quot;1&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;

&lt;hr /&gt;

&lt;p&gt;Und genau dieses alte Gerät habe ich am Zweitwohnsitz wieder mal aus der Ecke
geholt und musste feststellen, dass der Bildschirm leider leer blieb, als ich die
fast antike Maschine einschaltete.&lt;/p&gt;

&lt;p&gt;Tja, ich hatte nicht die Zeit die Geräte näher zu begutachten. Es könnte 
entweder am Monitor oder am C64 gelegen haben.&lt;br /&gt;
Aber nach über 30 Jahren kann man es keinem 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Kondensator_(Elektrotechnik)&quot;&gt;Kondensator&lt;/a&gt; 
oder anderem Bauteil übel nehmen, wenn er in den Ruhestand geht.&lt;/p&gt;

&lt;p&gt;Vielleicht traue ich mich ja eines Tages, den alten Brotkasten zu zerlegen
und nach dem Defekt zu suchen, aber vorerst muss ich leider sagen:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Lieber C64! Du warst eine Inspiration für mich und wirst in
meinem Herzen und meinen Emulatoren immer weiter leben.
Danke und alles Gute für deine Seele, wo immer sie nun ist.&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>Links im Dateisystem</title>
   <link href="https://www.opengate.at/blog/2019/03/links/"/>
   <published>2019-03-09T21:43:00+01:00</published>
   <updated>2019-03-09T21:43:00+01:00</updated>
   <id>https://www.opengate.at/blog/2019/03/links</id>
   <category term="devel" />
   <summary type="text">Man kann durchaus behaupten, ich sei “etwas aus der Art” geschlagen.

Denn während viele Programmierer 
“Links” in 
unixoiden Dateisystemen als Segen
betrachten, sehe ich das ganz konträr und behaupte, dass Links eher ein
Feind der Ordnung als dessen Freund sind.

Also … was stimmt nicht mit mir?
</summary>
   <content type="html">&lt;p&gt;Man kann durchaus behaupten, ich sei “etwas aus der Art” geschlagen.&lt;/p&gt;

&lt;p&gt;Denn während viele Programmierer 
“&lt;a href=&quot;https://de.wikipedia.org/wiki/Symbolische_Verkn%C3%BCpfung&quot;&gt;Links&lt;/a&gt;” in 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Unix&quot;&gt;unixoiden&lt;/a&gt; Dateisystemen als Segen
betrachten, sehe ich das ganz konträr und behaupte, dass Links eher ein
Feind der Ordnung als dessen Freund sind.&lt;/p&gt;

&lt;p&gt;Also … was stimmt nicht mit mir?
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Links sind nicht gleich Links, es gibt einige Unterarten davon. Hier soll
es NICHT um die von mir akzeptierten 
“&lt;a href=&quot;https://de.wikipedia.org/wiki/Harter_Link&quot;&gt;Hardlinks&lt;/a&gt;” gehen, sondern um 
“Symbolische Links”, auch als “Sym-Links” oder “Soft-Links” bekannt.&lt;/p&gt;

&lt;p&gt;Denn dabei handelt es sich quasi um eigene Dateien im Dateisystem, die
aber selbst keinen Inhalt haben und auf eine andere Datei verweisen.
Das Betriebssystem führt die Auflösung von Sym-Links zu den Zieldateien
im Hintergrund aus, womit mehrere Einzelschritte notwendig werden.&lt;/p&gt;

&lt;p&gt;Und genau hier liegt mein Problem mit diesem Konstrukt:&lt;br /&gt;
Ein Sym-Link ist ein eigenständiger Dateieintrag mit eigenen Rechten
und die verlinkte Zieldatei ist ein anderer Dateieintrag mit anderen
Rechten.&lt;/p&gt;

&lt;p&gt;Wird also ein Link geöffnet kann es zu folgenden Fehlerfällen kommen:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Die Dateirechte verbieten den Zugriff zum Sym-Link&lt;/li&gt;
  &lt;li&gt;Die Zieldatei ist gar nicht vorhanden&lt;/li&gt;
  &lt;li&gt;Die Dateirechte verbieten den Zugriff zur Zieldatei&lt;/li&gt;
  &lt;li&gt;Die Zieldatei ist selbst ein Link und das Spiel wiederholt sich&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Jetzt könnte man natürlich sagen:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Mir doch egal, warum ich nicht zugreifen kann.&lt;br /&gt;
Fakt ist: Es geht einfach nicht.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Und im Normalfall stimmt das auch.&lt;br /&gt;
Wenn man aber Tools zur Dateiverwaltung gestaltet, wo es um das Kopieren,
Verschieben und Löschen von Dateien geht, wird das Thema jedoch kritisch.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Was bedeutet es, wenn man einen Link kopieren will?&lt;/li&gt;
  &lt;li&gt;Kopiert man den Inhalt der verlinkten Datei?&lt;/li&gt;
  &lt;li&gt;Erstellt man einen weiteren Link zur Originaldatei?
    &lt;ul&gt;
      &lt;li&gt;Ist das ein relativer oder absoluter Pfad?&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Sollen APIs, die prüfen, ob eine Datei existiert, auch prüfen ob das
Ziel eines Links ebenso existiert?&lt;/li&gt;
  &lt;li&gt;Dürfen Links verschoben werden, vor allem wenn sie relative Pfadangaben
beinhalten.&lt;/li&gt;
  &lt;li&gt;Darf man Links kopieren oder verschieben, wenn ihr Ziel nicht existiert?&lt;/li&gt;
  &lt;li&gt;Und welche Rechte sollen Links bekommen?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Tja, die Antwort of diese Fragen ist mehr als komplex und müsste theoretisch
von Anwendung zu Anwendung anders entschieden werden.&lt;/p&gt;

&lt;p&gt;Unter Windows kommt erschwerend hinzu, dass das Erzeugen neuer Links
im Normalfall nur mit Admin-Rechten erlaubt ist.&lt;/p&gt;

&lt;p&gt;Hier liegt also der Knackpunkt: Unabhängiger Bibliothekscode kann nicht alle 
Eventualitäten vorsehen und kann somit nicht universell eingesetzt werden.&lt;/p&gt;

&lt;p&gt;Und dieses selbst geschaffene Problem gibt es in Dateisystemen ohne Links eben
nicht.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Da ich aktuell auch an den Dateiverwaltungsroutinen im GATE Projekt arbeite,
müssen hier entsprechende Workarounds integriert werden, die die oben 
gestellten Fragen beantworten oder zumindest berücksichtigen.&lt;/p&gt;

&lt;p&gt;Eine endgültige Lösung habe ich nicht parat und werde wohl noch einige
Tests abwarten müssen und eventuell auch später das Verhalten abändern
müssen, um auf relevante Szenarien auf Zielsystemen vorbereitet zu sein.&lt;/p&gt;

&lt;p&gt;Naja, und deshalb sind mir Links per Definition eben unsympathisch.&lt;br /&gt;
Mal sehen was die Zukunft bring…&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Weltfrauentag</title>
   <link href="https://www.opengate.at/blog/2019/03/world-women-day/"/>
   <published>2019-03-08T22:48:00+01:00</published>
   <updated>2019-03-08T22:48:00+01:00</updated>
   <id>https://www.opengate.at/blog/2019/03/world-women-day</id>
   <category term="general" />
   <summary type="text">
  Selbst wenn ich als Mann 50 Prozent meiner Privilegien einfach ablege,
bin ich wahrscheinlich immer noch besser gestellt, 
als eine durchschnittliche Frau.


Und deshalb soll uns der heutige 
Weltfrauentag 
daran erinnern, dass wir zwar viel über Gleichberechtigung reden, sie aber 
immer noch lange nicht erreicht haben.
</summary>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;Selbst wenn ich als Mann 50 Prozent meiner Privilegien einfach ablege,
bin ich wahrscheinlich immer noch besser gestellt, 
als eine durchschnittliche Frau.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Und deshalb soll uns der heutige 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Internationaler_Frauentag&quot;&gt;Weltfrauentag&lt;/a&gt; 
daran erinnern, dass wir zwar viel über Gleichberechtigung reden, sie aber 
immer noch lange nicht erreicht haben.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Geschäftsführer haben weltweit häufig folgende Gemeinsamkeiten:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Sie sind männlich.&lt;/li&gt;
  &lt;li&gt;Sie sind weiß.&lt;/li&gt;
  &lt;li&gt;Sie gebärden sich gerne als die einzig wahren Macher.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Und was ist über Frauen bekannt?&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Frauen gehören an den Herd, am besten in aufreizender Kleidung.&lt;br /&gt;
Wissen ist schädlich für sie, und lässt ihre Gebärmutter verkümmern.&lt;br /&gt;
Sie können nicht organisieren, Autofahren schon gar nicht.&lt;br /&gt;
Für politische Mitsprache sind sie ungeeignet.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Jeder lacht über diesen Blödsinn, der vor 50-100 Jahren noch genau so an
Schulen unterrichtet wurde.&lt;br /&gt;
Doch hat die Gesellschaft dazu gelernt?&lt;/p&gt;

&lt;p&gt;Jahrtausende wurden Frauen diskriminiert und bekamen es häufig direkt
zu spüren, wenn dem vermeintlich “starken” Geschlecht etwas nicht passte.&lt;/p&gt;

&lt;p&gt;Ein besonders schändlicher Fall ereignete sich auch in meiner Familie,
wo die Mutter einer entfernten Verwandten ihrer kleine Tochter immer
die Leidenschaft ausredete, der Mutter die Haare zu kämmen.&lt;/p&gt;

&lt;p&gt;Warum? Nun die Kopfhaut der Mutter war mit Narben bedeckt, die sie bei jeder
Berührung schmerzten. Denn immer wenn ihr missmutig gelaunter Mann von der 
Arbeit zurückkam, ließ er seinen Zorn an seiner Frau aus. Und wenn “das Weib” 
dabei mit dem Kopf eine Kleiderkastentür durchschlug, musste sie sich wohl 
auch noch dafür entschuldigen, weil sie so tollpatschig war.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Bitte, sag bloß nichts, sonst wird der Vater wieder böse,
und die Nachbarn schimpfen mich, weil unsere Ehe so schlecht läuft.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Jahre später waren die Kinder des Paars erwachsen geworden. Die Burschen 
hatten weiter Angst etwas gegen den jähzornigen Vater zu sagen.
Bis eines Tages eines der Mädchen ihren Mut zusammennahm, in den
Stall ging, eine Mistgabel holte und sie dem Prügler mit Entschlossenheit
und lauter Stimme an die Gurgel setzte:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Wenn du noch einmal auf die Mutter hinhaust, dann war’s das für dich.
Ich warne dich! Nur noch einmal!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Das war ein Wendepunkt, denn der übermütige Schläger knickte weinerlich ein.
Und die alte Mutter wurde von diesem Tag an nicht mehr getreten und 
geschlagen.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Wie viele fleißige und kreative Frauen wurden wohl in den Jahrtausenden
der Menschheitsgeschichte ihrer Rechte und ihrer Fähigkeiten beraubt, 
weil “alte Sitten” den Mann zum alleinigen Bestimmer über die Familie 
gekürt hatten?&lt;/p&gt;

&lt;p&gt;Wie viele Ehen waren von Gewalt geprägt, worüber keiner sprechen durfte?&lt;/p&gt;

&lt;p&gt;Wie viele Mütter konnten ihre Kinder nur unter schweren Strapazen großziehen,
weil sich die Väter “verschlichen” und sie als billige Arbeitskräfte
künstlich “klein” gehalten wurden?&lt;/p&gt;

&lt;p&gt;Wie oft wurde es von Kollegen und Vorgesetzten geleugnet, wenn eine Frau
sexuelle Belästigung oder Misshandlung gemeldet hatte, und mit 
Kündigungsdrohungen eine Strafverfolgung verhindert wurde?&lt;/p&gt;

&lt;p&gt;Deshalb ist es wichtig, dass wir an solchen Tagen darüber nachdenken,
was in unserer Gesellschaft nicht stimmt, und dass noch ein ordentliches
Stück Weg vor uns liegt, bis Frauen und Männer auch im realen Leben
wirklich gleich gestellt sind, eine adäquates Gehalt beziehen und alles 
erreichen können dürfen, wozu sie begabt sind.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Da gibt es noch verdammt viel zu tun!&lt;/strong&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Noch am selben Tag am Abend erlebte ich im
&lt;a href=&quot;http://wien.coderdojo.net/&quot;&gt;CoderDojo&lt;/a&gt; die herrliche Szene, wie ein 
nicht einmal 10 Jahre altes Mädchen ihre ersten Gehversuche im Webdesign
mit purem &lt;a href=&quot;https://de.wikipedia.org/wiki/Hypertext_Markup_Language&quot;&gt;HTML&lt;/a&gt; 
machte.&lt;br /&gt;
Die junge Hobby-Programmiererin wollte unbedingt auch mal wissen, wie
man eine eigene Webseite erstellt und ihr Vater unterstützte sie bei 
diesem Vorhaben vorbildlich.&lt;/p&gt;

&lt;p&gt;Und dass heute ein Mädchen in so einem typischen “Männerbereich” wie der IT
Seite an Seite mit anderen Jungs und Mädels ihrer neuen Leidenschaft nachgeht,
beweist mir, dass wir vielleicht doch einmal auf dem richtigen Weg sind,
und dass die junge Generation diese sinnlosen Fesseln der Vergangenheit 
sprengen kann.&lt;/p&gt;

&lt;p&gt;Diese Errungenschaften müssen einerseits verteidigt und gleichzeitig ausgebaut 
werden und sie sollten in alle Gegenden und Länder der Welt exportiert werden, 
in denen es leider auch heute noch heißt: “Frauen an den Herd.”&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Captain Marvel: Retro-Cameo hoch 3</title>
   <link href="https://www.opengate.at/blog/2019/03/cameo/"/>
   <published>2019-03-07T22:00:00+01:00</published>
   <updated>2019-03-07T22:00:00+01:00</updated>
   <id>https://www.opengate.at/blog/2019/03/cameo</id>
   <category term="entertainment" /><category term="retro" />
   <summary type="text">Pünktlich am reservierten Platz wurde das Handy auf lautlos geschaltet, noch
schnell ein Zug von der Limoflasche und dann wurde es still. Die ersten
Minuten Vorspiel waren - wie immer - vorüber und dann kam, auf was “wir” 
gespannt wartet hatten:

Die Violinen stimmten an, die ersten rötlichen Bilder klatschten auf die
Leinwand und dann kam …

Ja was? Nicht Iron Man, 
Hulk und 
Black-Widow?

Nein, sondern Stan Lee, 
Stan Lee und noch viele weitere Male Stan Lee.
</summary>
   <content type="html">&lt;p&gt;Pünktlich am reservierten Platz wurde das Handy auf lautlos geschaltet, noch
schnell ein Zug von der Limoflasche und dann wurde es still. Die ersten
Minuten Vorspiel waren - wie immer - vorüber und dann kam, auf was “wir” 
gespannt wartet hatten:&lt;/p&gt;

&lt;p&gt;Die Violinen stimmten an, die ersten rötlichen Bilder klatschten auf die
Leinwand und dann kam …&lt;/p&gt;

&lt;p&gt;Ja was? Nicht &lt;a href=&quot;https://de.wikipedia.org/wiki/Iron_Man&quot;&gt;Iron Man&lt;/a&gt;, 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Hulk_(Comic)&quot;&gt;Hulk&lt;/a&gt; und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Figuren_aus_dem_Marvel-Universum#Black_Widow&quot;&gt;Black-Widow&lt;/a&gt;?&lt;/p&gt;

&lt;p&gt;Nein, sondern &lt;a href=&quot;https://de.wikipedia.org/wiki/Stan_Lee&quot;&gt;Stan Lee&lt;/a&gt;, 
Stan Lee und noch viele weitere Male Stan Lee.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;iframe width=&quot;640&quot; height=&quot;360&quot; src=&quot;/blog/redirect.html?https%3A%2F%2Fwww.youtube-nocookie.com%2Fembed%2FKYZ9obDJJtU&quot; frameborder=&quot;1&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;

&lt;!--
&lt;video controls&gt;
  &lt;source src=&quot;/blog/assets/video/marvel-intro-stan-lee.mp4&quot; type=&quot;video/mp4&quot;&gt;
  Your browser does not support the HTML VIDEO tag.
&lt;/video&gt;
--&gt;

&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Captain_Marvel_(Film)&quot;&gt;Captain Marvel&lt;/a&gt; ist 
heute in den Kinos angelaufen, und obwohl die Preise wie immer zu hoch 
waren … &lt;strong&gt;das muss man einfach gesehen haben&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Vor allem deshalb weil es jetzt nur noch 6 Wochen dauert, bis 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Avengers:_Endgame&quot;&gt;Avengers Endgame&lt;/a&gt;
seinen Kinostart hat und nachdem letztes Jahr in 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Avengers:_Infinity_War&quot;&gt;Avengers Infinity War&lt;/a&gt; 
der böse &lt;a href=&quot;https://de.wikipedia.org/wiki/Figuren_aus_dem_Marvel-Universum#Thanos&quot;&gt;Thanos&lt;/a&gt; 
siegreich war und die halbe Heldenwelt ausgelöscht hat, braucht es nun 
eine neue Superheldin, die noch mal mehr kann als alle anderen.&lt;/p&gt;

&lt;p&gt;Dass das bekannte 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Marvel_Cinematic_Universe&quot;&gt;Marvel Cinematic Universe&lt;/a&gt;
Intro, das ich für eines der gelungensten überhaupt halte, diesmal den leider
verstorbenen Stan Lee, den Schöpfer einer Vielzahl von Comic-Helden, zum 
Hauptthema gemacht hat und am Ende die Worte “Danke, Stan Lee” einblendet, 
finde ich wirklich gelungen.&lt;/p&gt;

&lt;p&gt;Nicht nur, dass man einer der großen Comic-Ikonen des 20. Jahrhunderts 
einen besonderen Ehrenplatz verleiht, nein, es passt sogar zum aktuellen
Zustand der Marvel-Filmwelt, da man ja nicht weiß, welcher Held nach 
&lt;em&gt;Infinity War&lt;/em&gt; doch noch zurückkommen wird und wer nicht.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Der Film selbst ist thematisch für mich etwas schwer einordenbar. Wenn man vom
&lt;a href=&quot;https://de.wikipedia.org/wiki/Captain_America%3A_The_First_Avenger&quot;&gt;1. Captain America Teil&lt;/a&gt; 
absieht, der zwischen 1940 und 1945 spielt, haben alle anderen Filme einen
auf einander aufbauenden Ablauf beginnend bei Hulk und Iron-Man vor 2010 
bis hin zum Jahr 2018 mit 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Ant-Man_and_the_Wasp&quot;&gt;Ant-Man and the Wasp&lt;/a&gt; 
im letzten Sommer.&lt;/p&gt;

&lt;p&gt;Captain Marvel spielt in den 90er Jahren … und solche Prequels
sind immer etwas problematisch.&lt;/p&gt;

&lt;p&gt;Sie wirken auf mich immer besonders “konstruiert”, weil man da möglichst 
nichts tun darf, was die bereits erzählte Zukunft verändern könnte.
(OK, &lt;a href=&quot;https://de.wikipedia.org/wiki/Star_Trek&quot;&gt;StarTrek&lt;/a&gt; und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Pokémon&quot;&gt;Pokemon&lt;/a&gt; mal ausgenommen!)&lt;/p&gt;

&lt;p&gt;Und so kann der neue Film für mich vom Inhalt her nicht mit den letzten 
Highlights wie “AntMan &amp;amp; the Wasp” oder 
“&lt;a href=&quot;https://de.wikipedia.org/wiki/Thor:_Tag_der_Entscheidung&quot;&gt;Thor Ragnarok&lt;/a&gt;” 
mithalten.&lt;br /&gt;
Trotzdem ist die Produktion - wie bei allen Marvel Filmen - auf hohem Niveau
und bot mir einen schönen Kinoabend mit viel Gelächter und ein paar geilen
Action-Szenen.&lt;br /&gt;
&lt;em&gt;Also auf jeden Fall ein Empfehlung zum Anschauen!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Der Film spielt im Jahr 1995 und beinhaltet 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Retro&quot;&gt;Retro&lt;/a&gt;, Retro und noch mehr Retro.
Vom &lt;a href=&quot;https://de.wikipedia.org/wiki/Game_Boy&quot;&gt;Gameboy&lt;/a&gt; über 
&lt;a href=&quot;https://en.wikipedia.org/wiki/Blockbuster_LLC&quot;&gt;Blockbuster-Videotheken&lt;/a&gt; gibt 
es vermutlich keine in Amerika bekannte Marke, die dort nicht einmal plakativ
vorkam.&lt;br /&gt;
Telefonzellen und Spieleautomaten an jeder Ecke und Autos mit quietschenden
Reifen, wenn sie sich Verfolgungsjagden liefern.
Und dann durfte &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_95&quot;&gt;Windows 95&lt;/a&gt; 
auch noch - wie gewohnt - einmal die Internetverbindung unerwartet trennen.&lt;/p&gt;

&lt;p&gt;Für mich, der damals aufwuchs natürlich ein Augenschmaus, aber ich weiß nicht 
ob die moderne Generation nicht entweder mit Fragezeichen auf der Stirn hinaus
geht oder sich bei dieser Zurschaustellung langweilt.&lt;/p&gt;

&lt;p&gt;Denn manchmal bekommt man den Eindruck, dass die Sets einen Museumscharakter
haben, worin sich alle etwas “gekünstelt” verhalten, anstatt so wie 
damals üblich einfach mit seiner Umgebung “zu leben”.&lt;/p&gt;

&lt;p&gt;Mich würde mal interessieren ob ältere Generationen auch solche Retrowellen
erlebt haben, also wo man in Film, Fernsehen oder Literatur auch so viele 
Rückblenden “von vor 20-30 Jahren” umgesetzt hat.&lt;/p&gt;

&lt;p&gt;Denn aktuell habe ich wirklich das Gefühl, dass “Retro” total angesagt ist.
Nicht nur, dass die alten Spielekonsolendesigns wieder neu aufleben, sondern
auch ganz allgemein erinnern mich viele Formen und Farben heute mehr an
“früher”, als dies noch vor 10 Jahren der Fall war.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Die Hoffnung, dass wenn “Retro” cool ist, ich auch wieder “cool” sein werde,
stirbt zuletzt!&lt;/p&gt;

&lt;p&gt;Die Endcredit-Szenen garantieren, dass Captain “Mar-Vell” in &lt;em&gt;Endgame&lt;/em&gt; sein 
wird, und zeigen wie es aussieht, wenn Katzen kotzen müssen ;)&lt;/p&gt;

&lt;p&gt;Und in diesem Sinne freue ich mich, dass Stan Lee auch noch einmal aufleben
durfte und bleibe gespannt, ob er in 6 Wochen in Endgame noch einen Szene 
bekommt, die noch vor seinem Tod gedreht wurde.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Excelsior!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So, und jetzt schau ich mir an, was 
&lt;a href=&quot;http://beans.fandom.com/de/wiki/Daniel_Schröckert&quot;&gt;LeSchroeck&lt;/a&gt; dazu sagt:&lt;/p&gt;

&lt;iframe width=&quot;640&quot; height=&quot;360&quot; src=&quot;/blog/redirect.html?https%3A%2F%2Fwww.youtube-nocookie.com%2Fembed%2Fw3VoCl3nDP4&quot; frameborder=&quot;1&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
</content>
 </entry>
 
 <entry>
   <title>BASE64 Zeichencodes</title>
   <link href="https://www.opengate.at/blog/2019/03/base64/"/>
   <published>2019-03-06T13:28:00+01:00</published>
   <updated>2019-03-06T13:28:00+01:00</updated>
   <id>https://www.opengate.at/blog/2019/03/base64</id>
   <category term="devel" />
   <summary type="text">Zu den ältesten und ersten Kodierungen, die ich lernen durfte,
zählte BASE64.
3 Bytes zu je 8 bits (3 x 8 = 24 bits), werden auf 4 Bytes aufgeteilt, 
wobei nur 6 bit breite Wertebereiche genutzt werden, schließlich ist ja 
4 x 6 auch gleich 24.

Und dieser 6-bit breite Wertebereich wird auf die ASCII-Zeichen 
A-Z, a-z, 0-9 und ‘+’ und ‘/’ aufgeteilt.

Und so können wir jeden erdenklichen binären Block als reine 
Buchstaben- und Zahlenkombinationen darstellen, womit keine Sonderzeichen
oder ASCII
Steuercodes benutzt werden müssen.
</summary>
   <content type="html">&lt;p&gt;Zu den ältesten und ersten Kodierungen, die ich lernen durfte,
zählte &lt;a href=&quot;https://de.wikipedia.org/wiki/Base64&quot;&gt;BASE64&lt;/a&gt;.
3 Bytes zu je 8 bits (3 x 8 = 24 bits), werden auf 4 Bytes aufgeteilt, 
wobei nur 6 bit breite Wertebereiche genutzt werden, schließlich ist ja 
4 x 6 auch gleich 24.&lt;/p&gt;

&lt;p&gt;Und dieser 6-bit breite Wertebereich wird auf die ASCII-Zeichen 
&lt;code&gt;A-Z&lt;/code&gt;, &lt;code&gt;a-z&lt;/code&gt;, &lt;code&gt;0-9&lt;/code&gt; und ‘+’ und ‘/’ aufgeteilt.&lt;/p&gt;

&lt;p&gt;Und so können wir jeden erdenklichen binären Block als reine 
Buchstaben- und Zahlenkombinationen darstellen, womit keine Sonderzeichen
oder &lt;a href=&quot;https://de.wikipedia.org/wiki/American_Standard_Code_for_Information_Interchange&quot;&gt;ASCII&lt;/a&gt;
Steuercodes benutzt werden müssen.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Es geht dabei um das älteste Problem bei Datenformaten:
Wie kann ich zwischen Steuerkommandos (Anfang, Ende, Metadaten) und dem 
eigentlichen Inhalt, der ja genau so 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Steuerzeichen&quot;&gt;Steuerzeichen&lt;/a&gt; enthalten kann, 
möglichst gut unterscheiden?&lt;/p&gt;

&lt;h3 id=&quot;lösung-man-kodiert-um&quot;&gt;Lösung: Man kodiert um.&lt;/h3&gt;

&lt;p&gt;Und parallel gab es früher noch ein zweites Problem, nämlich die Frage,
wie man 8-bit Bytes über eine 7-bit Leitung quetschen kann.&lt;/p&gt;

&lt;p&gt;Diese beiden Probleme löste BASE64 eben mit der Reduktion der benutzten
Bits in einem Byte, womit allerdings die Länge der Datenpuffer um 33 %
anwächst.&lt;/p&gt;

&lt;p&gt;Viele Netzwerkprotokolle und Datenformate nutzen daher BASE64 für 
Contentdaten. In E-Mails können auf diese Weise binäre Attachments 
angefügt werden, weil die Mail-Protokolle 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Simple_Mail_Transfer_Protocol&quot;&gt;SMTP&lt;/a&gt; und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Post_Office_Protocol&quot;&gt;POP3&lt;/a&gt; nur reine
Text-Buchstaben unterstützen. (Man muss allerdings auch hinzufügen,
dass auch andere Kodierungsformen dort gebräuchlich sind.)&lt;br /&gt;
Und uralte &lt;a href=&quot;https://de.wikipedia.org/wiki/Modem&quot;&gt;Modems&lt;/a&gt; bzw. 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Akustikkoppler&quot;&gt;Akkustikkoppler&lt;/a&gt; nutzten 
das 8. Bit zum Teil auch als Prüfsumme und brauchten deshalb ebenso
Kodierungen um binäre Datenströme über 7 Datenbits leiten zu können.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Die GATE Implementierung sieht für so eine Binary-Tripple-to-B64-Quad
Konvertierung wie folgt aus:&lt;/p&gt;
&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;static&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt; * &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt; base64_chars = 
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;ABCDEFGHIJKLMNOPQRSTUVWXYZ&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;abcdefghijklmnopqrstuvwxyz&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;0123456789+/&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;static&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt; base64_nullchar = &lt;span style=&quot;color:#D20&quot;&gt;&apos;=&apos;&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt; gate_base64_enc3(&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt;* inputTriple, &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt;* outputQuad)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;  outputQuad[&lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;] = base64_chars[((gate_uint8_t)inputTriple[&lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;] &amp;gt;&amp;gt; &lt;span style=&quot;color:#00D&quot;&gt;2&lt;/span&gt;) &amp;amp; &lt;span style=&quot;color:#02b&quot;&gt;0x3f&lt;/span&gt;];
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  outputQuad[&lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;] = base64_chars[(((gate_uint8_t)inputTriple[&lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;] &amp;amp; &lt;span style=&quot;color:#02b&quot;&gt;0x03&lt;/span&gt;) &amp;lt;&amp;lt; &lt;span style=&quot;color:#00D&quot;&gt;4&lt;/span&gt;) 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;                | (((gate_uint8_t)inputTriple[&lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;] &amp;gt;&amp;gt; &lt;span style=&quot;color:#00D&quot;&gt;4&lt;/span&gt;) &amp;amp; &lt;span style=&quot;color:#02b&quot;&gt;0x0f&lt;/span&gt;)];
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;  outputQuad[&lt;span style=&quot;color:#00D&quot;&gt;2&lt;/span&gt;] = base64_chars[(((gate_uint8_t)inputTriple[&lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;] &amp;amp; &lt;span style=&quot;color:#02b&quot;&gt;0x0f&lt;/span&gt;) &amp;lt;&amp;lt; &lt;span style=&quot;color:#00D&quot;&gt;2&lt;/span&gt;) 
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;                | (((gate_uint8_t)inputTriple[&lt;span style=&quot;color:#00D&quot;&gt;2&lt;/span&gt;] &amp;gt;&amp;gt; &lt;span style=&quot;color:#00D&quot;&gt;6&lt;/span&gt;) &amp;amp; &lt;span style=&quot;color:#02b&quot;&gt;0x03&lt;/span&gt;)];
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;  outputQuad[&lt;span style=&quot;color:#00D&quot;&gt;3&lt;/span&gt;] = base64_chars[(gate_uint8_t)inputTriple[&lt;span style=&quot;color:#00D&quot;&gt;2&lt;/span&gt;] &amp;amp; &lt;span style=&quot;color:#02b&quot;&gt;0x3f&lt;/span&gt;];
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Hinzu kommen noch zwei ähnliche Funktionen, die das Ende eines binären Blocks 
abschließen, wenn dieser nicht aus 3 sondern aus weniger Bytes besteht.
Dafür ist das Gleichheitszeichen &lt;code&gt;=&lt;/code&gt; reserviert, das eine solche Sequenz 
beendet.&lt;/p&gt;

&lt;p&gt;Bei der Dekodierung muss jedes Element eines Viererblocks in der BASE64
Zeichenliste gefunden werden.
Natürlich können hier auch Kodierungsfehler auftreten, die man finden
und dann Abbrechen muss.
Die aktuelle GATE-Implementierung prüft hier nicht extra auf ein &lt;code&gt;=&lt;/code&gt;, 
sondern sieht alles außerhalb der definierten 64 Zeichen als ein 
Ende bzw einen Abbruch an.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;gate_size_t gate_base64_dec(&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;const&lt;/span&gt;* inputQuad, &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt;* outputTriple)
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  gate_size_t pos1 = gate_str_char_pos(base64_chars, &lt;span style=&quot;color:#00D&quot;&gt;64&lt;/span&gt;, inputQuad[&lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;], &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  gate_size_t pos2 = gate_str_char_pos(base64_chars, &lt;span style=&quot;color:#00D&quot;&gt;64&lt;/span&gt;, inputQuad[&lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;], &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  gate_size_t pos3 = gate_str_char_pos(base64_chars, &lt;span style=&quot;color:#00D&quot;&gt;64&lt;/span&gt;, inputQuad[&lt;span style=&quot;color:#00D&quot;&gt;2&lt;/span&gt;], &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;  gate_size_t pos4 = gate_str_char_pos(base64_chars, &lt;span style=&quot;color:#00D&quot;&gt;64&lt;/span&gt;, inputQuad[&lt;span style=&quot;color:#00D&quot;&gt;3&lt;/span&gt;], &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;  gate_size_t ret = &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n8&quot; name=&quot;n8&quot;&gt;8&lt;/a&gt;&lt;/span&gt;  gate_uint32_t quad = &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt; &lt;a href=&quot;#n9&quot; name=&quot;n9&quot;&gt;9&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n10&quot; name=&quot;n10&quot;&gt;10&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;do&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n11&quot; name=&quot;n11&quot;&gt;11&lt;/a&gt;&lt;/span&gt;  {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n12&quot; name=&quot;n12&quot;&gt;12&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt;(pos1 == GATE_STR_NPOS)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n13&quot; name=&quot;n13&quot;&gt;13&lt;/a&gt;&lt;/span&gt;    {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n14&quot; name=&quot;n14&quot;&gt;14&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;break&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n15&quot; name=&quot;n15&quot;&gt;15&lt;/a&gt;&lt;/span&gt;    }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n16&quot; name=&quot;n16&quot;&gt;16&lt;/a&gt;&lt;/span&gt;    quad |= (gate_uint32_t)pos1 &amp;lt;&amp;lt; &lt;span style=&quot;color:#00D&quot;&gt;18&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n17&quot; name=&quot;n17&quot;&gt;17&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n18&quot; name=&quot;n18&quot;&gt;18&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt;(pos2 == GATE_STR_NPOS)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n19&quot; name=&quot;n19&quot;&gt;19&lt;/a&gt;&lt;/span&gt;    {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n20&quot; name=&quot;n20&quot;&gt;20&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;      &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;break&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n21&quot; name=&quot;n21&quot;&gt;21&lt;/a&gt;&lt;/span&gt;    }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n22&quot; name=&quot;n22&quot;&gt;22&lt;/a&gt;&lt;/span&gt;    quad |= (gate_uint32_t)pos2 &amp;lt;&amp;lt; &lt;span style=&quot;color:#00D&quot;&gt;12&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n23&quot; name=&quot;n23&quot;&gt;23&lt;/a&gt;&lt;/span&gt;    outputTriple[&lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;] = (&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt;)(gate_uint8_t)((quad &amp;gt;&amp;gt; &lt;span style=&quot;color:#00D&quot;&gt;16&lt;/span&gt;) &amp;amp; &lt;span style=&quot;color:#02b&quot;&gt;0xff&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n24&quot; name=&quot;n24&quot;&gt;24&lt;/a&gt;&lt;/span&gt;    ++ret;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n25&quot; name=&quot;n25&quot;&gt;25&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n26&quot; name=&quot;n26&quot;&gt;26&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt;(pos3 == GATE_STR_NPOS)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n27&quot; name=&quot;n27&quot;&gt;27&lt;/a&gt;&lt;/span&gt;    {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n28&quot; name=&quot;n28&quot;&gt;28&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;break&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n29&quot; name=&quot;n29&quot;&gt;29&lt;/a&gt;&lt;/span&gt;    }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n30&quot; name=&quot;n30&quot;&gt;30&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;    quad |= (gate_uint32_t)pos3 &amp;lt;&amp;lt; &lt;span style=&quot;color:#00D&quot;&gt;6&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n31&quot; name=&quot;n31&quot;&gt;31&lt;/a&gt;&lt;/span&gt;    outputTriple[&lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;] = (&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt;)(gate_uint8_t)((quad &amp;gt;&amp;gt; &lt;span style=&quot;color:#00D&quot;&gt;8&lt;/span&gt;) &amp;amp; &lt;span style=&quot;color:#02b&quot;&gt;0xff&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n32&quot; name=&quot;n32&quot;&gt;32&lt;/a&gt;&lt;/span&gt;    ++ret;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n33&quot; name=&quot;n33&quot;&gt;33&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n34&quot; name=&quot;n34&quot;&gt;34&lt;/a&gt;&lt;/span&gt;    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt;(pos4 == GATE_STR_NPOS)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n35&quot; name=&quot;n35&quot;&gt;35&lt;/a&gt;&lt;/span&gt;    {
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n36&quot; name=&quot;n36&quot;&gt;36&lt;/a&gt;&lt;/span&gt;      &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;break&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n37&quot; name=&quot;n37&quot;&gt;37&lt;/a&gt;&lt;/span&gt;    }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n38&quot; name=&quot;n38&quot;&gt;38&lt;/a&gt;&lt;/span&gt;    quad |= (gate_uint32_t)pos4;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n39&quot; name=&quot;n39&quot;&gt;39&lt;/a&gt;&lt;/span&gt;    outputTriple[&lt;span style=&quot;color:#00D&quot;&gt;2&lt;/span&gt;] = (&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;char&lt;/span&gt;)(gate_uint8_t)(quad &amp;amp; &lt;span style=&quot;color:#02b&quot;&gt;0xff&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;strong&gt;&lt;a href=&quot;#n40&quot; name=&quot;n40&quot;&gt;40&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;    ++ret;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n41&quot; name=&quot;n41&quot;&gt;41&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n42&quot; name=&quot;n42&quot;&gt;42&lt;/a&gt;&lt;/span&gt;  } &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;while&lt;/span&gt;(&lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n43&quot; name=&quot;n43&quot;&gt;43&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n44&quot; name=&quot;n44&quot;&gt;44&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; ret;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n45&quot; name=&quot;n45&quot;&gt;45&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Ich habe BASE64 mehrere Male in &lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B&quot;&gt;C++&lt;/a&gt;, 
wie auch in &lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_Basic_Classic&quot;&gt;VB6&lt;/a&gt;, 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_Basic_Script&quot;&gt;VBScript&lt;/a&gt; und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/JavaScript&quot;&gt;JavaScript&lt;/a&gt; implementiert. 
Vielleicht auch mal spaßhalber in C# oder Java, doch daran 
erinnere ich mich dann nicht mehr.&lt;/p&gt;

&lt;p&gt;Der interessantere Punkt ist die Integration der Kodierung in Blockpuffer oder
Streams, denn es wäre ja extrem ineffizient immer nur 3 oder 4 Bytes zu lesen
um dann die jeweils andere Menge sofort in einen Outputstream zu schreiben.&lt;/p&gt;

&lt;p&gt;Sinnvoller ist es, die Daten in vernünftig großen Puffern zu sammeln und dann
in einem Schritt zu konvertieren.&lt;br /&gt;
Das ist zwar nicht besonders schwer, aber immer recht anfällig für 
Pointer-Rechenfehler und diverse Bugs.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Übrigens, korrekterweise muss man anfügen, dass die Implementierung laut 
C-Standard nicht portabel ist und auf unseren CPUs nur “zufällig” funktioniert.&lt;/p&gt;

&lt;p&gt;Warum?&lt;br /&gt;
Na weil hier böse zwischen &lt;code&gt;char&lt;/code&gt; und anderen &lt;code&gt;unsigned&lt;/code&gt; Typen hin und her
gecastet wird. Das wäre laut Standard nur für Werte zwischen 0 und 127 erlaubt,
nicht aber für 128 bis 255 (bzw. -128 bis -1), weil &lt;code&gt;char&lt;/code&gt;
zumeist ein Vorzeichen trägt.&lt;/p&gt;

&lt;p&gt;Doch auf unseren &lt;a href=&quot;https://de.wikipedia.org/wiki/Zweierkomplement&quot;&gt;Zweierkomplement&lt;/a&gt;-
Binärsystemen kommt zum Glück immer das richtige Ergebnis heraus und so lange
es keine nativen Quantenprozessoren gibt, die in Q-Bits statt normalen Bits 
rechnen, ist diese Implementierungen (so wie zahlreiche andere) immer noch 
OK und zwischen (fast) allen CPUs nutzbar.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Die Kraft der Sonne</title>
   <link href="https://www.opengate.at/blog/2019/03/solar-power/"/>
   <published>2019-03-05T14:22:00+01:00</published>
   <updated>2019-03-05T14:22:00+01:00</updated>
   <id>https://www.opengate.at/blog/2019/03/solar-power</id>
   <category term="hardware" />
   <summary type="text">Die stärkste Energieform in unserem Sonnensystem ist und bleibt die 
Sonne.
Sie schuf die Voraussetzungen mit, die unser Leben überhaupt erst ermöglicht 
hat und liefert weit mehr Energie, als wir Menschen überhaupt nutzen können.

Ist es daher nicht pervers, dass wir ausgerechnet Kohle, Öl und Gas verbrennen 
um im Sommer Räume herunter zu kühlen und im Winter unsere Häuser zu beheizen?

Die Lösung: Solarenergie, 
Solarwärme und Photovoltaik. 
Und all das existiert schon seit über 50 Jahren in der Raumfahrt, doch in den
letzten 15 Jahren wurden sie auch für Privathaushalte leistbar.
</summary>
   <content type="html">&lt;p&gt;Die stärkste Energieform in unserem Sonnensystem ist und bleibt die 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Sonne&quot;&gt;Sonne&lt;/a&gt;.
Sie schuf die Voraussetzungen mit, die unser Leben überhaupt erst ermöglicht 
hat und liefert weit mehr Energie, als wir Menschen überhaupt nutzen können.&lt;/p&gt;

&lt;p&gt;Ist es daher nicht pervers, dass wir ausgerechnet Kohle, Öl und Gas verbrennen 
um im Sommer Räume herunter zu kühlen und im Winter unsere Häuser zu beheizen?&lt;/p&gt;

&lt;p&gt;Die Lösung: &lt;a href=&quot;https://de.wikipedia.org/wiki/Sonnenenergie&quot;&gt;Solarenergie&lt;/a&gt;, 
Solarwärme und &lt;a href=&quot;https://de.wikipedia.org/wiki/Photovoltaik&quot;&gt;Photovoltaik&lt;/a&gt;. 
Und all das existiert schon seit über 50 Jahren in der Raumfahrt, doch in den
letzten 15 Jahren wurden sie auch für Privathaushalte leistbar.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Ein für mich spannendes Beispiel sind die kleinen Solarpanele, die man
sich im Elektronikladen für (je nach Stärke) 10 bis 200 Euro kaufen kann,
und ins Fenster stellt.&lt;br /&gt;
Die kleineren Billigmodelle liefern Strom mit ein paar 100 Milliampere um
kleine Schaltkreise zwischen 1 und 12 Volt zu betreiben, während die 
größeren Module das eine oder andere Ampere bereitstellen und somit sogar
kleine Computer wie z.B. den 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Raspberry_Pi&quot;&gt;Raspberry PI&lt;/a&gt; Zero betreiben 
zu können.&lt;/p&gt;

&lt;p&gt;Das nenne ich mal genial!
Wir brauchen keine Steckdosen, Adapter oder USB Buchsen, sondern stellen
einfach ein Panel in die Sonne und können 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Internet_der_Dinge&quot;&gt;IoT&lt;/a&gt; Hardware 
“ohne Kosten” betreiben.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/solar-panels.jpg&quot; alt=&quot;Solar Panels&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Doch einen großen Nachteil hat die Solarenergie!&lt;/p&gt;

&lt;p&gt;Die Sonne ist nicht immer gleich stark präsent. Und wenn man beim Kauf
ein Modul mit 5 Volt und 500 Milliampere gekauft hat 
(was genau der spezifizierten Leistung eines USB 2.0 Ports entspricht), so 
erhält man diesen Strom nur unter idealen Bedingungen:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Direkte Sonneneinstrahlung (ohne Wolken oder andere Wetter-bedingte
Reduktionen)&lt;/li&gt;
  &lt;li&gt;Genaue senkrechte Ausrichtung zur Sonne (das Panel muss also stündlich
zur Sonne neu ausgerichtet werden)&lt;/li&gt;
  &lt;li&gt;Durchschnittliche Temperatur: Zu heiß dürfen die Zellen auch nicht werden&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Und da diese Bedingungen nicht alle erfüllbar sind, schwankt der erzeugte
Solarstrom zwischen (bei mir teils gemessen und teils geschätzt) 20% und 90%
an Sonnentagen und bei Nebel oder Schlechtwetter ist man schon tagsüber
froh, wenn man für kurze Zeit überhaupt 20% der angegebenen Maximalwerte
erreicht.&lt;/p&gt;

&lt;h3 id=&quot;die-lösung&quot;&gt;Die Lösung&lt;/h3&gt;

&lt;p&gt;Entweder man arbeitet überdimensioniert, montiert also mehrere Module und
schaltet diese zusammen um mit 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Aufw%C3%A4rtswandler&quot;&gt;Aufwärts&lt;/a&gt; - oder 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Abw%C3%A4rtswandler&quot;&gt;Abwärts&lt;/a&gt; - Konvertern 
genau die Spannung und Stromstärke zu bekommen, die der Verbraucher benötigt, 
…&lt;/p&gt;

&lt;p&gt;… oder, die bessere Lösung: Man lädt 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Akkumulator&quot;&gt;Akkus&lt;/a&gt; oder andere Speicher damit
auf. Denn die Sonne ist mindestens die Hälfte des Tages nicht zu sehen und 
damit macht es wesentlich mehr Sinn, die Energiespitzen des Tages gut 
wegzuspeichern, und dann aus dem Speicher kontinuierlich Energie zu entnehmen.&lt;/p&gt;

&lt;p&gt;Eine ganz tolle Sache sind Ladestationen für Smartphones, wo wir tagsüber 
unsere Begleiter einklinken können, damit diese von der Sonne aufgeladen
werden.&lt;br /&gt;
Bei viel Sonne sind die Geräte in wenigen Stunden voll, bei wenig Sonne 
dauert es vielleicht den ganzen Tag, bzw. nehmen wir zumindest so viel
Energie auf, dass der Akku sich nicht weiter entlädt.&lt;/p&gt;

&lt;p&gt;Das gilt natürlich auch für &lt;a href=&quot;https://de.wikipedia.org/wiki/Powerbank&quot;&gt;Powerbanks&lt;/a&gt; 
oder andere Akku- und Batterieladegeräte.&lt;/p&gt;

&lt;p&gt;Ein weiterer faszinierender Ansatz ist die Kombination mit einer 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Brennstoffzelle&quot;&gt;Brennstoffzelle&lt;/a&gt;, in der durch
elektrischen Strom Wasser in Sauerstoff und Wasserstoff aufgespalten
wird und bei der Umkehrung des Prozesses die beiden Gase wieder zu reinem
Wasser verbrannt werden und dabei die ursprünglich aufgenommene Energie 
teilweise wieder als Wärme oder Strom abgegeben wird.&lt;br /&gt;
Wer die Brennstoffzelle mit Solarstrom auflädt, hat somit also eine der
saubersten Energiespeicherformen für sich genutzt.&lt;/p&gt;

&lt;h3 id=&quot;nachteile&quot;&gt;Nachteile&lt;/h3&gt;

&lt;p&gt;Nun, auch wenn ich ein totaler Fan der Photovoltaik bin, so sollte man sich
bewusst sein, dass vor allem die Produktion der Akkus für die 
Energiespeicherung wie auch die Produktion der Zellen selbst energieaufwendig
ist und dabei auch sehr umweltschädliche Nebenprodukte entstehen können.&lt;/p&gt;

&lt;p&gt;Der hoch geschätzte &lt;a href=&quot;/blog/2019/02/harald-lesch/&quot;&gt;Physiker Harald Lesch&lt;/a&gt; 
meinte nicht grundlos, dass der heutige Trend zur E-Mobilität bei weitem kein
besonders gesunder ist, weil gerade unsere Energie-hungrigen Autos nach 
Akkus und Batterien verlangen, deren Produktion extreme Umweltschäden 
anrichtet.&lt;/p&gt;

&lt;p&gt;Seine These lautet daher:&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;Fahren Sie autonom, nämlich mit der Bahn und nicht mit Elektroautos.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Doch so wie die ersten Dampfmaschinen auch viel verheizten und nur wenig 
Energie daraus nutzen konnten und wir heute wesentlich höhere Wirkungsgrade
erzielen, so denke ich wird die Weiterentwicklung der Solarenergie 
hoffentlich bald die heutigen Probleme überwinden.&lt;/p&gt;

&lt;p&gt;Außerdem haben nicht Ingenieure sondern die Evolution eine der besten
Solarzellen überhaupt geschaffen, nämlich Pflanzenzellen und die 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Photosynthese&quot;&gt;Photosynthese&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Und so geht auch die Forschung dazu über, das Verhalten von Pflanzen und
natürlichen Farbstoffen zur Energieerzeugung zu nutzen, wie das Beispiel
der &lt;a href=&quot;https://de.wikipedia.org/wiki/Gr%C3%A4tzel-Zelle&quot;&gt;Grätzel-Zelle&lt;/a&gt; zeigt.&lt;/p&gt;

&lt;p&gt;In Versuchen nutzen inzwischen moderne Häuser neues Fensterglas, in welches 
Solarzellen eingearbeitet sind. Diese Streifen dunkeln zu grelles Sonnenlicht
ab und produzieren als Nebenprodukt elektrischen Strom…&lt;/p&gt;

&lt;p&gt;Und genau deshalb liebe ich Technik und Forschung in diesem Bereich.
Solche Ideen helfen uns die Welt weiter zu bringen und vielleicht den
einen oder anderen Schaden, den wir bisher angerichtet haben, wieder
auszugleichen!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>HTTP Clients: WinInet und libCURL</title>
   <link href="https://www.opengate.at/blog/2019/03/inet-http/"/>
   <published>2019-03-04T18:27:00+01:00</published>
   <updated>2019-03-04T18:27:00+01:00</updated>
   <id>https://www.opengate.at/blog/2019/03/inet-http</id>
   <category term="devel" />
   <summary type="text">In Visual Basic 6 war 
auch die nicht-grafische Programmierung “grafisch”.
Es ist logisch, dass man einen Button oder ein Textfeld auf eine Fensterform
zieht, aber dass man eine “Internetverbindung” auch wie einen Button auf einem
Fenster ablegt, finde ich bis heute “merkwürdig”.

Dieses alte VB6 ActiveX 
“Internet Transfer Control” war nichts weiter als ein 
Wrapper um die 
WinInet Komponente, 
also DIE HTTP 
Komponente von Windows, die mit dem 
Internet Explorer 2 und 3 
schon unter Windows NT 4 
und Windows 95 
eingeführt wurde.

Heute ist diese alte C-API 
neben dem modernen WinHTTP 
parallel zur libcURL unter 
Unix Systemen für mich die primäre 
Anlaufstelle, wenn Programme per HTTP(S) Daten aus dem Netzwerk laden möchten.
</summary>
   <content type="html">&lt;p&gt;In &lt;a href=&quot;https://de.wikipedia.org/wiki/Visual_Basic_Classic&quot;&gt;Visual Basic 6&lt;/a&gt; war 
auch die nicht-grafische Programmierung “grafisch”.
Es ist logisch, dass man einen Button oder ein Textfeld auf eine Fensterform
zieht, aber dass man eine “Internetverbindung” auch wie einen Button auf einem
Fenster ablegt, finde ich bis heute “merkwürdig”.&lt;/p&gt;

&lt;p&gt;Dieses alte VB6 &lt;a href=&quot;https://de.wikipedia.org/wiki/ActiveX&quot;&gt;ActiveX&lt;/a&gt; 
“Internet Transfer Control” war nichts weiter als ein 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Wrapper_(Software)&quot;&gt;Wrapper&lt;/a&gt; um die 
&lt;a href=&quot;http://docs.microsoft.com/en-us/windows/desktop/wininet/about-wininet&quot;&gt;WinInet Komponente&lt;/a&gt;, 
also DIE &lt;a href=&quot;https://de.wikipedia.org/wiki/Hypertext_Transfer_Protocol&quot;&gt;HTTP&lt;/a&gt; 
Komponente von Windows, die mit dem 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Internet_Explorer&quot;&gt;Internet Explorer&lt;/a&gt; 2 und 3 
schon unter Windows &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_NT_4.0&quot;&gt;NT 4&lt;/a&gt; 
und &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_95&quot;&gt;Windows 95&lt;/a&gt; 
eingeführt wurde.&lt;/p&gt;

&lt;p&gt;Heute ist diese alte C-&lt;a href=&quot;https://de.wikipedia.org/wiki/Programmierschnittstelle&quot;&gt;API&lt;/a&gt; 
neben dem modernen &lt;a href=&quot;http://docs.microsoft.com/en-us/windows/desktop/winhttp/about-winhttp&quot;&gt;WinHTTP&lt;/a&gt; 
parallel zur &lt;a href=&quot;https://de.wikipedia.org/wiki/CURL&quot;&gt;libcURL&lt;/a&gt; unter 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Unix&quot;&gt;Unix&lt;/a&gt; Systemen für mich die primäre 
Anlaufstelle, wenn Programme per HTTP(S) Daten aus dem Netzwerk laden möchten.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Um ehrlich zu sein bin ich mit überhaupt keiner API wirklich glücklich.
Denn alle haben sie Seiteneffekte und Unschönheiten, die oft in umständlichen
Workarounds münden.&lt;/p&gt;

&lt;p&gt;Also fassen wir mal das Negative zusammen:&lt;/p&gt;

&lt;h3 id=&quot;wininet&quot;&gt;WinINET&lt;/h3&gt;

&lt;p&gt;Diese uralte Schnittstelle ist zwar stabil und bis ins vergangene Jahrtausend
kompatibel, doch sie wurde eben primär für den Internet Explorer entwickelt.
Das Anzeigen von Dialogen, wenn etwas nicht passt, ist hier Standard und muss
oft erst per Code abgeschaltet werden.&lt;/p&gt;

&lt;p&gt;Ein anderer lästiger Punkt sind teilweise Probleme, wenn die Schnittstelle in
Service-Prozessen läuft. Denn als IE Bibliothek werden 
&lt;a href=&quot;https://de.wikipedia.org/wiki/HTTP-Cookie&quot;&gt;Cookies&lt;/a&gt; und temporäre
Dateien im Profil-Verzeichnis des Benutzers abgelegt.&lt;br /&gt;
Doch ein Service läuft in der Regel ohne Benutzer … oder noch schlimmer,
es kann im laufenden Betrieb auf den Anmeldekontext eines Benutzers wechseln.&lt;/p&gt;

&lt;p&gt;Und somit wird es zu einer Grauzone, ob “globale”
&lt;a href=&quot;https://de.wikipedia.org/wiki/Proxy_(Rechnernetz)&quot;&gt;Proxy-Server&lt;/a&gt; Einträge 
oder Verbindungslimits korrekt sind, ob eine Einstellung nun geladen wird
oder nicht. Und wo Dateien angelegt werden lässt sich dann ebenso nicht 
mehr so einfach per Code beeinflussen.&lt;/p&gt;

&lt;h3 id=&quot;winhttp&quot;&gt;WinHTTP&lt;/h3&gt;

&lt;p&gt;WinHTTP wiederum wurde als Alternative für WinINET so um das Jahr 2000
eingeführt und sollte primär für 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Dienst_(Informatik)&quot;&gt;Dienste (Services)&lt;/a&gt; 
zur Verfügung stehen.&lt;/p&gt;

&lt;p&gt;Das ist einerseits toll für reine Dienste, führt aber dazu, dass die 
Bibliothek im normalen Benutzermodus wieder lückenhaft wird.&lt;/p&gt;

&lt;p&gt;Das gilt dann für solche Spezialitäten wie die Anmeldung an 
Windows-Webdiensten über &lt;a href=&quot;https://de.wikipedia.org/wiki/NTLM&quot;&gt;NTLM&lt;/a&gt;, 
wo die nützliche Zwischenspeicherung von Anmeldedaten nicht oder
unvollständig funktioniert.&lt;/p&gt;

&lt;p&gt;Die Unterstützung von älteren Proxy-Servern wie 
&lt;a href=&quot;https://de.wikipedia.org/wiki/SOCKS&quot;&gt;SOCKS4&lt;/a&gt; fehlt auch …
wobei man das heute nicht mehr als Manko anmerken kann.&lt;br /&gt;
Oder kennt diese uralte Protokoll über noch jemand außer mir 😀 ?&lt;/p&gt;

&lt;h3 id=&quot;libcurl&quot;&gt;libcurl&lt;/h3&gt;

&lt;p&gt;Die &lt;a href=&quot;http://curl.haxx.se/libcurl/&quot;&gt;libcurl&lt;/a&gt; wäre als portables 
OpenSource Projekt theoretisch der Heilsbringer unter den Bibliotheken, 
doch leider befriedigt auch sie mich nicht.
Wegen ihrer Abhängigkeit zu zahlreichen anderen Bibliotheken ist das cURL
Projekt so gut wie gar nicht als statische Bibliothek einsetzbar.&lt;/p&gt;

&lt;p&gt;Als dynamisch geteilte Komponente muss sie auf dem Zielsystem korrekt 
integriert sein, so wie auch alle ihre Abhängigkeiten. Und dass sind
nicht nur &lt;a href=&quot;https://de.wikipedia.org/wiki/OpenSSL&quot;&gt;OpenSSL&lt;/a&gt;, 
sondern auch &lt;a href=&quot;http://www.libssh2.org/&quot;&gt;SSH2&lt;/a&gt; und einiges mehr.
Fehlt ein Teil, funktioniert der ganze Rest auch nicht.&lt;/p&gt;

&lt;p&gt;Denn CURL ist nicht nur eine HTTP Bibliothek sondern eine Protokoll-Sammelstelle
für &lt;a href=&quot;https://de.wikipedia.org/wiki/File_Transfer_Protocol&quot;&gt;FTP&lt;/a&gt;, 
&lt;a href=&quot;https://de.wikipedia.org/wiki/SSH_File_Transfer_Protocol&quot;&gt;SFTP&lt;/a&gt;, 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Internet_Message_Access_Protocol&quot;&gt;IMAP&lt;/a&gt; u.s.w.&lt;/p&gt;

&lt;p&gt;Am störendsten empfinde ich aber den API-Aufbau, der auf Callbacks zum 
Empfang der Daten setzt. Damit ist es schwierig die Funktionen durch
einen Stream-Wrapper zu kapseln.&lt;/p&gt;

&lt;h3 id=&quot;und-die-eigene-implementierung&quot;&gt;Und die eigene Implementierung&lt;/h3&gt;

&lt;p&gt;Ja … so schwer ist das HTTP Protokoll ja nicht, das kann man auch
selbst implementieren … glaubt man anfangs.&lt;/p&gt;

&lt;p&gt;Für Server mag das teilweise zutreffend sein, wenn man nur wenige
Features braucht. Doch Clients zu programmieren, die mit allen möglichen 
Server-Spezialitäten konfrontiert werden, ist der größte Alptraum,
und spätestens, wenn es mit Authentifizierung, Verschlüsselung und
&lt;a href=&quot;https://en.wikipedia.org/wiki/HTTP/2&quot;&gt;HTTP/2&lt;/a&gt; losgeht, kann man sich schnell 
von der “coolen” Idee verabschieden, dass man es selber besser machen kann.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Weil HTTP so eine weite und vor allem unterschiedliche Verbreitung hat,
sind HTTP Client Bibliotheken alles andere als leicht zu schreiben und 
keine kann wirklich alles.&lt;br /&gt;
Auch &lt;a href=&quot;https://de.wikipedia.org/wiki/.NET&quot;&gt;dotNet&lt;/a&gt; und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Java_(Programmiersprache)&quot;&gt;JAVA&lt;/a&gt; haben 
hier ihre Limits.&lt;/p&gt;

&lt;p&gt;Folglich muss ich am Ende dennoch sagen, dass die 3 genannten Bibliotheken
Meisterwerke sind, deren “seltsame” Besonderheiten erst bei speziellen
Anforderungen sichtbar werden.&lt;/p&gt;

&lt;p&gt;Natürlich hätte ich mir eine gemeinsame Übermenge gewünscht, die “alles” kann,
Open-Source ist und hoch performant in allen Lebenslagen agiert, doch …&lt;br /&gt;
… man kann eben nicht alles haben.&lt;/p&gt;

&lt;p&gt;Meine Entscheidung bleibt daher: WinINET für Windows, libCURL für Linux.
Und alles wird am Ende dann doch noch gut ausgehen.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Sicherungshaft</title>
   <link href="https://www.opengate.at/blog/2019/03/law-and-order/"/>
   <published>2019-03-03T13:47:00+01:00</published>
   <updated>2019-03-03T13:47:00+01:00</updated>
   <id>https://www.opengate.at/blog/2019/03/law-and-order</id>
   <category term="general" /><category term="retro" />
   <summary type="text">Anfang der 40er Jahre des vergangenen Jahrhunderts verschwand nahe eines
Bauerndorfes in der nördlichen 
Ostmark 
ein junger Mann spurlos.
Er sollte mit zwei Ochsen den Acker pflügen. Die Ochsen fand man verlassen
auf dem Feld und seine Mutter weinte - wie man so sagte - “kübelweise”.

Etwas später langte der Verhaftungsbescheid bei der Familie ein, dass
der 17-Jährige wegen Hetzerei gegen den Staat “zur Sicherheit” in
Gewahrsam genommen wurde, weil Mitbürger sein aufrührerisches Verhalten
gemeldet hatten.

Das “aufrührerische Verhalten” war die trotzige Weigerung die “rechte Hand”
beim Gruß zu heben oder Sprüche zu klopfen wie nachfolgend:


  Gott der Herr schuf Menschen und Tiere,
nur keine Unteroffiziere,
doch in einer schwachen Stunde
schuf der Herr auch diese Hunde.


Dieser damals junge Mann war mein inzwischen lange verstorbener Großvater.
</summary>
   <content type="html">&lt;p&gt;Anfang der 40er Jahre des vergangenen Jahrhunderts verschwand nahe eines
Bauerndorfes in der nördlichen 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Alpen-_und_Donau-Reichsgaue&quot;&gt;Ostmark&lt;/a&gt; 
ein junger Mann spurlos.
Er sollte mit zwei Ochsen den Acker pflügen. Die Ochsen fand man verlassen
auf dem Feld und seine Mutter weinte - wie man so sagte - “kübelweise”.&lt;/p&gt;

&lt;p&gt;Etwas später langte der Verhaftungsbescheid bei der Familie ein, dass
der 17-Jährige wegen Hetzerei gegen den Staat “zur Sicherheit” in
Gewahrsam genommen wurde, weil Mitbürger sein aufrührerisches Verhalten
gemeldet hatten.&lt;/p&gt;

&lt;p&gt;Das “aufrührerische Verhalten” war die trotzige Weigerung die “rechte Hand”
beim Gruß zu heben oder Sprüche zu klopfen wie nachfolgend:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Gott der Herr schuf Menschen und Tiere,&lt;br /&gt;
nur keine Unteroffiziere,&lt;br /&gt;
doch in einer schwachen Stunde&lt;br /&gt;
schuf der Herr auch diese Hunde.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Dieser damals junge Mann war mein inzwischen lange verstorbener Großvater.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Seit Jahrtausenden (zumindest seit &lt;a href=&quot;https://de.wikipedia.org/wiki/Aristoteles&quot;&gt;Aristoteles&lt;/a&gt;)
geht die Welt kontinuierlich unter, weil die Jungen nicht so wollen, 
wie die Alten es vorgesehen haben.&lt;/p&gt;

&lt;p&gt;Aber was passiert, wenn eine Ideologie oder eine Weltanschauung so 
radikal wird, dass sie Jugendliche zur Disziplinierung und Abschreckung
verhaftet?&lt;/p&gt;

&lt;p&gt;Nun, im “glorreichen” &lt;a href=&quot;https://de.wikipedia.org/wiki/Drittes_Reich&quot;&gt;dritten Reich&lt;/a&gt; 
ging das für viele tödlich aus, egal wie viel “arisches” Blut man in sich hatte.
Auch mein Großvater war für die 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Strafdivision_999&quot;&gt;Strafdivision 999&lt;/a&gt; 
(Strafbataillon 999) vorgesehen, wo aufmüpfige Bürger ihre Treue zum Vaterland
wiederfinden sollten. Ob man jetzt von vorne vom Feind oder von hinten wegen 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Fahnenflucht&quot;&gt;Fahnenflucht&lt;/a&gt; von Kugeln zerfetzt
wurde, war letztendlich auch schon egal.&lt;/p&gt;

&lt;p&gt;Ein Arzt, dem der junge Sträfling während seiner “Haft” zur Hilfe zugeteilt wurde,
bewirkte, dass mein Großvater mit wenigen anderen nicht an die Front 
geschickt wurde, und so bekam der inzwischen 18-Jährige eine neue Aufgabe:&lt;/p&gt;

&lt;p&gt;Da in jener Zeit für einige Menschen offenbar Kugeln zu schade waren, erlebte 
das &lt;a href=&quot;https://de.wikipedia.org/wiki/Schafott&quot;&gt;Schafott&lt;/a&gt; eine Renaissance.
So wurden unzählige Menschen per Fallbeil “entsorgt”.&lt;br /&gt;
Und wer war dazu abkommandiert den “Dreck” wegzuräumen?&lt;/p&gt;

&lt;p&gt;So entstand dann dieser Lebenslauf:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;Schule&lt;/li&gt;
  &lt;li&gt;Feldarbeit&lt;/li&gt;
  &lt;li&gt;Abgetrennte Leichenteile verscharren&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Erst als “der Russe” vor den Toren Wiens stand und einige Vertreter der
&lt;a href=&quot;https://de.wikipedia.org/wiki/Herrenvolk_und_Herrenrasse&quot;&gt;Herrenrasse&lt;/a&gt; die 
Flucht ergriffen, gelang es meinem Großvater und einigen seiner Zellengenossen
durch einen zuvor ausgekundschafteten geheimen Weg zu entfliehen.&lt;/p&gt;

&lt;p&gt;Die Flüchtenden durften sich nebenbei damit rühmen, die Sprengung eines Zuges
nahe der Donaubrücken mitansehen zu dürfen und hatten dabei großes Glück von 
den herumfliegenden Eisenbahnrädern nicht getroffen zu werden.&lt;/p&gt;

&lt;p&gt;Ohne viel Nahrung wurde dann halb Niederösterreich zu Fuß durchquert, um dann
die letzten Kriegswochen - bei der Großmutter versteckt - ungesehen zu überleben.&lt;/p&gt;

&lt;p&gt;Ähnliche Erlebnisse haben auch eine Hand voll andere Menschen durchgemacht,
doch niemand kennt die große Zahl derer, die diese Jahre nicht überlebt haben.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Solche Geschichten sind für uns heute reine Fiktion geworden und nur mehr 
als Action-Kino vorstellbar.&lt;br /&gt;
Und in jenen Filmen zeigt man nicht, wie die Betroffenen von Kriegen
auch nach Jahrzehnten noch mit ihrem Schicksal hadern.&lt;br /&gt;
Sie laufen dann scheinbar grundlos beim Mittagessen hinaus, oder man
findet sie alleine sitzend und bemerkt, wie sie sich schnell die Tränen
abwischen, ehe sie sich umdrehen.&lt;/p&gt;

&lt;p&gt;Und eigentlich dachte ich, Europa hätte etwas aus seiner eigenen 
Dummheit gelernt.&lt;/p&gt;

&lt;p&gt;Warum also fangen wir heute wieder mit der Debatte an, dass man 
“vorsorglich” alle Menschen verhaften können soll? War es nicht
allgemeiner Konsens, dass ständige in Gesetze gegossene Brutalität
von 1918 bis 1938 die Zerstörung halb Europas auslöste und dass 
wir es nie wieder so weit kommen lassen werden?&lt;/p&gt;

&lt;p&gt;Ich bin durchaus dafür, dass man zu laxe Strafmaßnahmen anzieht,
aber eben auf rechtsstaatlicher Ebene durch Expertenkommissionen,
und nicht wegen einzelnen Anlassfällen.&lt;br /&gt;
Genau diese Willkür, diese emotional aufgeladenen Schnellschüsse
waren vor 70 Jahren ein Auslöser dafür, was meinem Großvater 
zahlreiche Schmerzen und unzähligen anderen den Tod eingebracht hat.&lt;/p&gt;

&lt;p&gt;Natürlich ist es plump aktuelle politische Entwicklungen immer gleich
mit der Nazizeit in Verbindung zu bringen … aber leider wiederholen sich 
Grausamkeiten in der Menschheitsgeschichte alle 100 Jahre.&lt;br /&gt;
Und ältere Ereignisse sind eben nicht so gut dokumentiert und auf 
Fotos verewigt, wie es vor 70-80 Jahren der Fall war.&lt;br /&gt;
Heute sagen die verschwiegenen dunkelsten Flecken der romantisierten 
Kaiserzeit eben niemandem mehr etwas, doch Nazi-Dokus kennt jeder.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Wehret den Anfängen!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Neulich teilte mir ein erfahrener Mann in einer Diskussion zur
Aktuellen Lage seine Meinung mit:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Wir müssen mit gutem Beispiel voran gehen!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Und damit hatte er recht! Wir müssen wieder Anstand und Rechtschaffenheit 
hochschätzen lernen und diese Werte aktiv fördern, anstatt nur noch 
über Verbote und Bestrafung zu sprechen.&lt;/p&gt;

&lt;p&gt;Anstatt die Jugend als “abtrünnig” unter Generalverdacht zu stellen,
müssen wir Älteren als Vorbilder unserer eigenen Zeit dienen, an denen 
sich die neue Generation reiben wird und das auch ständig aufs Neue tun muss.&lt;/p&gt;

&lt;p&gt;Das wird “uns” Älteren vielleicht viel Zeit kosten und “uns” auch nicht immer
gefallen. Aber keinesfalls dürfen wir unsere schlechten Lebenserfahrungen mit 
einzelnen Personen zu verallgemeinerten Gesetzen und Vorschriften
hochstilisieren, an denen unsere Kinder zu zerbrechen drohen.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Die “andere böse Seite” jener vergangenen Zeit des Nationalsozialismus wird 
übrigens im von mir sehr geschätzten Spielfilm &lt;a href=&quot;https://de.wikipedia.org/wiki/Napola_%E2%80%93_Elite_f%C3%BCr_den_F%C3%BChrer&quot;&gt;Napola&lt;/a&gt;
dargestellt, der in vielen Szenen aufzeigt, was eine militant geprägte 
Gesellschaft anrichten kann und wie man Jugendliche damit zu dressieren 
versuchte.&lt;br /&gt;
… aber auch welchen Mut junge Erwachsene aufbringen können,
wenn sie den ihnen anerzogenen Lebensweg hinterfragen:&lt;/p&gt;

&lt;iframe width=&quot;640&quot; height=&quot;360&quot; src=&quot;/blog/redirect.html?https%3A%2F%2Fwww.youtube-nocookie.com%2Fembed%2FzokixAOB91M&quot; frameborder=&quot;1&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;

&lt;p&gt;Text-Auszug aus “Napola”: 
“Der Aufsatz von Albrecht Stein” (gespielt von 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Tom_Schilling&quot;&gt;Tom Schilling&lt;/a&gt;):&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;… ich jedenfalls war in meiner Vorstellung ein Held,
der Drachen besiegt und Jungfrauen rettet.&lt;br /&gt;
Jemand der die Welt von den Bösen befreit.&lt;br /&gt;
Und als wir gestern loszogen um die Gefangenen zu finden,
da kam ich mir wieder vor wie dieser kleine Junge,
der die Welt vor den Bösen retten will.&lt;/p&gt;

  &lt;p&gt;Doch als wir zurückkamen, da war mir klar geworden,
dass ICH selbst Teil des Bösen bin,
vor dem ich die Welt immer bewahren wollte.&lt;/p&gt;

  &lt;p&gt;Gefangene zu erschießen ist Unrecht!&lt;br /&gt;
Sie waren weder bewaffnet,
wie (mein Vater) Gauleiter Stein angab um uns aufzuhetzen,
noch waren es Männer, sondern Kinder,&lt;br /&gt;
die WIR erschossen haben.&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>Threads: Arbeiter und Schlangen</title>
   <link href="https://www.opengate.at/blog/2019/03/thread-queue/"/>
   <published>2019-03-02T11:07:00+01:00</published>
   <updated>2019-03-02T11:07:00+01:00</updated>
   <id>https://www.opengate.at/blog/2019/03/thread-queue</id>
   <category term="devel" />
   <summary type="text">Viele APIs 
stehen uns nur in synchroner Form zur Verfügung. Dazu zählen
vor allem Funktionen für Kompression und Verschlüsselung.
Will man diese im Hintergrund werken lassen während sich das Hauptprogramm
etwa um die UI kümmert, erzeugt man einen weiteren 
Thread und lässt die
Arbeit dort ausführen (Workerthread).

Und dann gibt es APIs die den Kontext des Threads auf dem sie laufen 
verändern. Es gibt thread-lokale Variablen oder es werden sogar eigene 
Einsprungpunkte in diesem Thread aktiv.

Das kann wiederum mit anderen APIs kollidieren oder dort Seiteneffekte
auslösen.
Auch hier greift man gerne zu separaten Threads, wo Aufgaben in eine
Warteschlange (Queue) 
eingefügt werden und dann hintereinander abgearbeitet werden.
</summary>
   <content type="html">&lt;p&gt;Viele &lt;a href=&quot;https://de.wikipedia.org/wiki/Programmierschnittstelle&quot;&gt;APIs&lt;/a&gt; 
stehen uns nur in synchroner Form zur Verfügung. Dazu zählen
vor allem Funktionen für Kompression und Verschlüsselung.&lt;br /&gt;
Will man diese im Hintergrund werken lassen während sich das Hauptprogramm
etwa um die UI kümmert, erzeugt man einen weiteren 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Thread_(Informatik)&quot;&gt;Thread&lt;/a&gt; und lässt die
Arbeit dort ausführen (Workerthread).&lt;/p&gt;

&lt;p&gt;Und dann gibt es APIs die den Kontext des Threads auf dem sie laufen 
verändern. Es gibt thread-lokale Variablen oder es werden sogar eigene 
Einsprungpunkte in diesem Thread aktiv.&lt;/p&gt;

&lt;p&gt;Das kann wiederum mit anderen APIs kollidieren oder dort Seiteneffekte
auslösen.
Auch hier greift man gerne zu separaten Threads, wo Aufgaben in eine
&lt;a href=&quot;https://de.wikipedia.org/wiki/Warteschlange_(Datenstruktur)&quot;&gt;Warteschlange (Queue)&lt;/a&gt; 
eingefügt werden und dann hintereinander abgearbeitet werden.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Das &lt;a href=&quot;https://de.wikipedia.org/wiki/Component_Object_Model&quot;&gt;Component Object Model&lt;/a&gt; 
ist unter Windows so ein Sonderfall, genau so wie die 
&lt;a href=&quot;https://de.wikipedia.org/wiki/.NET&quot;&gt;dotNet-Runtime&lt;/a&gt; oder die 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Windows_Runtime&quot;&gt;Windows-Runtime (WinRT)&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Hier wird der Thread mit bestimmten Parametern gezielt “initialisiert”
und muss vor dessen Beendigung auch wieder “de-initialisiert” werden.&lt;/p&gt;

&lt;p&gt;Dieser Umstand hat mich schon seit langem dazu bewogen, COM Code immer
in separaten Threads auszuführen.&lt;/p&gt;

&lt;p&gt;So wurde die “Thread-Execution-Queue” geboren, die ich in fast allen
Projekten, an denen ich arbeite, immer einbaue.&lt;/p&gt;

&lt;p&gt;Technisch gesprochen handelt es sich dabei pro Instanz um einen
separaten Thread, und jeglicher Runtime-abhängiger Code wird dabei
gekapselt.
Anstatt eine Funktion direkt auszuführen, wird eine 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Stellvertreter_(Entwurfsmuster)&quot;&gt;Proxy&lt;/a&gt;-Funktion 
bereitgestellt, die ein Thread-Queue-Item anlegt und es der 
Execution-Queue übergibt. Die Proxy-Funktion wartet dann so 
lange (z.B. per Sync-Event), bis der eigentlich Code im 
Execution-Thread fertig ist und kann dann sogar die Ergebnisse oder
abgefangene Exceptions dem eigentlich Aufrufer zurückmelden.&lt;/p&gt;

&lt;p&gt;Diese Prozedur kann übrigens auch dafür genutzt werden, dass
thread-unsicherer Code thread-sicher wird, denn in der
Execution-Queue kann immer nur ein Auftrag nach dem FIFO Prinzip
abgearbeitet werden.&lt;/p&gt;

&lt;p&gt;Aufwändig ist leider das manuelle Schreiben der Proxy-Funktionen. Doch
nachdem innerhalb einer API-Familie oft Funktionen ähnlich gestaltet sind,
kann man mit 
&lt;a href=&quot;https://de.wikipedia.org/wiki/C-Pr%C3%A4prozessor#Definition_und_Ersetzung_von_Makros&quot;&gt;Macros&lt;/a&gt;
und &lt;a href=&quot;https://de.wikipedia.org/wiki/Template_(C%2B%2B)&quot;&gt;Templates&lt;/a&gt;
in C oder C++ viel Arbeitsaufwand reduzieren.&lt;/p&gt;

&lt;p&gt;Kritisch sind vor allem Rückrufprozeduren, die man entweder in den
Aufrufer-Thread zurückleiten muss, oder wo man abwägen muss, ob man direkt
im Execution-Queue Kontext weiteren Code ausführt.&lt;/p&gt;

&lt;p&gt;Daraus ergibt sich nämlich schnell das Problem, dass ein Rückruf zu einem
erneuten Aufruf von Code in der Execution-Queue führt und dieser muss dann
ohne Umleitungen ausgeführt werden, weil die Queue ja bereits arbeitet und
nicht auf sich selbst warten darf.&lt;/p&gt;

&lt;p&gt;Aus diesem Grund befindet sich im GATE Projekt in einigen Modulen Code, 
der anders reagiert, wenn der aktuelle Thread-Context einem zwischengespeicherten 
Kontext entspricht, was auf einen Rückruf aus einem Execution-Queue-Thread 
hindeutet.&lt;/p&gt;

&lt;p&gt;Neuere Programmiersprachen und Frameworks nutzen asynchronen Code häufiger und
nutzen ihre eigenen State-Machines um Code automatisch in anderen Threads
auszuführen.&lt;br /&gt;
Dabei sollte man aber nicht unterschätzen, dass es auch hier zu Seiteneffekten
kommen kann.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Ich empfehle daher mir selbst und jedem anderen Bibliotheksentwickler 
bei solchen Thread-Wechsel-Aktionen wie bei asynchroner Programmierung,
oder kontextabhängiger Ausführung sich Gedanken über alle möglichen
Zustände der eigenen Variablen aber auch der Umgebung zu machen.&lt;/p&gt;

&lt;p&gt;Nichts ist lästiger als ein Modul, dass “normalerweise” immer funktioniert,
und dann ausgerechnet in kritischen Fällen schwer versagt, weil es mit
weiteren Komponenten zu Konflikten kam.&lt;/p&gt;

&lt;p&gt;Oft musste ich schon recht komplizierte Execution-Queues um Fremdbibliotheken
spinnen, weil sie seltsame Dinge mit globalen Variablen oder thread-lokalen
Variablen anstellten, ohne dass dies dokumentiert war.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Wrapper und Abstraktionsschichten</title>
   <link href="https://www.opengate.at/blog/2019/03/abstraction/"/>
   <published>2019-03-01T12:06:00+01:00</published>
   <updated>2019-03-01T12:06:00+01:00</updated>
   <id>https://www.opengate.at/blog/2019/03/abstraction</id>
   <category term="devel" />
   <summary type="text">Wie viele Layer und Abstraktionsschichten “über” einer
konkreten Implementierung sind gut und ab wann ist die
Grenze des guten Geschmacks erreicht?

Diese Frage stelle ich mir bei jedem Projekt aufs Neue und komme stets
zu anderen Ergebnissen.
</summary>
   <content type="html">&lt;p&gt;Wie viele Layer und Abstraktionsschichten “über” einer
konkreten Implementierung sind gut und ab wann ist die
Grenze des guten Geschmacks erreicht?&lt;/p&gt;

&lt;p&gt;Diese Frage stelle ich mir bei jedem Projekt aufs Neue und komme stets
zu anderen Ergebnissen.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Konkret geht es diesmal um die Frage, ob es Sinn macht um 
&lt;code&gt;malloc()&lt;/code&gt; einen Wrapper herum zu legen.&lt;br /&gt;
Jeder vernünftige Entwickler würde sagen:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Nein! Es handelt sich um DIE wichtigste C Funktion, 
die Basis vieler anderen Funktionen. Man braucht 
sie nicht umzuleiten.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Das stimmt grundsätzlich auch, denn eine Umwickelung dieser
Funktion mit einer anderen führt nur zu einem zusätzlichen 
Herumspringen im Codespeicher bei der Ausführung, und wirkt 
sich negativ auf die Cache-Auslastung und Performance aus.&lt;/p&gt;

&lt;p&gt;Doch im GATE Projekt findet dennoch eine solche Umleitung
statt, und zwar zu den Funktion &lt;code&gt;gate_mem_alloc()&lt;/code&gt; und
&lt;code&gt;gate_mem_dealloc()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Und der Grund dafür ist, dass es unter fast jeder Plattform
einen “Spezial-Modus” gibt, in dem &lt;code&gt;malloc()&lt;/code&gt; nicht zur Verfügung steht.
… und das ist die Treiber und Kernel-Modul Entwicklung.&lt;/p&gt;

&lt;p&gt;Nun könnte man mutmaßen, dass die Treiber Entwicklung kein
Primärziel ist (zumindest aktuell noch nicht) und weiter nur die
negativen Aspekte der Umleitung bleiben.&lt;br /&gt;
Doch auch das ist (großteils) nicht zutreffend, da das
GATE Framework für statische Kompilierung und Link-Time
Codegeneration ausgelegt ist.&lt;/p&gt;

&lt;p&gt;Der Optimizer erkennt in der Regel, dass ein Aufruf von
&lt;code&gt;gate_mem_alloc()&lt;/code&gt; direkt auf &lt;code&gt;malloc()&lt;/code&gt; (im Usermode) umleitet und kann
diesen Aufruf daher “inlinen”, also direkt setzen.&lt;/p&gt;

&lt;p&gt;Damit bleibt der Code also weiter bei höchster (bzw. hoher) Effizienz.&lt;/p&gt;

&lt;p&gt;Ich bin daher dazu über gegangen bei Framework-Projekten mehr
Abstraktion einzubauen, als man es durchschnittlich erwarten würde,
im Anbindungen von weiteren mir aktuell noch nicht bekannten
Plattformen zu ermöglichen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Es bleibt natürlich immer im Ermessen des Entwicklers bzw. des Teams,
wir oft man Wrapper oder höherer Abstraktionsschichten über konkrete
Plattform oder Funktions-APIs darüber legt.&lt;/p&gt;

&lt;p&gt;Der größte Nachteil von zu viel Abstraktion ist leider, dass man
damit sehr individuelle und proprietäre Schnittstellen schafft, die 
niemand kennt und erst viel Dokumentation gelesen werden muss.&lt;br /&gt;
Beispiel &lt;code&gt;malloc()&lt;/code&gt; kennt jeder, &lt;code&gt;gate_mem_alloc()&lt;/code&gt; kenne aktuell nur
ich selbst.&lt;/p&gt;

&lt;p&gt;Und so geht es vielen Bibliotheksprojekten.&lt;br /&gt;
Immer herrscht der Kampf zwischen Abstraktion und einfacher bzw. direkter
Native-API-Nutzung.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Hackers &apos;n&apos; Slackers</title>
   <link href="https://www.opengate.at/blog/2019/02/hackers-slackers/"/>
   <published>2019-02-28T21:26:00+01:00</published>
   <updated>2019-02-28T21:26:00+01:00</updated>
   <id>https://www.opengate.at/blog/2019/02/hackers-slackers</id>
   <category term="general" />
   <summary type="text">Oder: Was es so für Typen von IT-Menschen gibt

Die vergangenen Wochen haben mich einige neue Gesichter kennen lernen lassen.
So ist das eben beim Job-Wechsel und den Bewerbungsterminen.

Dabei ist es immer wieder interessant mitzuerleben, wie “andere” Programmierer 
mit ihrem Beruf, ihrer Berufung und ihrem Leben umgehen. 
Bei einigen Stories denkt man sich:


  Oh - mein - Gott, was hast du in der Software-Entwicklung verloren?


Doch dann gibt es wieder diese Highlights, wo man sich denkt:


  Hey! Du bist jetzt mein Freund!

</summary>
   <content type="html">&lt;h2 id=&quot;oder-was-es-so-für-typen-von-it-menschen-gibt&quot;&gt;Oder: Was es so für Typen von IT-Menschen gibt&lt;/h2&gt;

&lt;p&gt;Die vergangenen Wochen haben mich einige neue Gesichter kennen lernen lassen.
So ist das eben beim Job-Wechsel und den Bewerbungsterminen.&lt;/p&gt;

&lt;p&gt;Dabei ist es immer wieder interessant mitzuerleben, wie “andere” Programmierer 
mit ihrem Beruf, ihrer Berufung und ihrem Leben umgehen. 
Bei einigen Stories denkt man sich:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Oh - mein - Gott, was hast du in der Software-Entwicklung verloren?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Doch dann gibt es wieder diese Highlights, wo man sich denkt:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Hey! Du bist jetzt mein Freund!
&lt;!--more--&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;der-is-eh-wurscht-charakter&quot;&gt;Der “Is-Eh-Wurscht” Charakter&lt;/h3&gt;

&lt;p&gt;Das schlimmste, was ich je erlebt habe (vor knapp 13 Jahren), war ein Kollege
Ende 40, der den Standpunkt vertrat:&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;Ich habe genug gearbeitet! Ja, die sollen mich anstellen, damit ich in
ein paar Monaten kündigen und wieder Notstandsgeld beziehen kann.
Das spiele ich jetzt bis zur Pension durch.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Zusätzlich zum angerichteten Schaden bei Kollegen und beim Unternehmen 
frage ich mich, ob solche Typen in ihrem restlichen Leben jemals wieder
Glück empfinden können. Denn eine solche Einstellung wird mit jedem 
Lebensjahr mehr Verbitterung produzieren und die negative Spirale weiter
nach unter drehen.&lt;/p&gt;

&lt;h3 id=&quot;der-schnitzeljäger&quot;&gt;Der Schnitzeljäger&lt;/h3&gt;

&lt;p&gt;Und dann treffe ich immer wieder mal &lt;em&gt;Schnitzeljäger&lt;/em&gt;. Technik und 
Programmierung geht ihnen sprichwörtlich “am Arsch” vorbei, aber sie möchten
Teil einer “coolen” Bewegung sein, oder sie am besten gleich anführen.&lt;/p&gt;

&lt;p&gt;Deshalb lernen sie einzelne Wortgruppen von Wikipedia auswendig um sie
zielgerichtet bei Gesprächen als überirdisches Wissen einzustreuen, damit
jeder sehen bzw. hören kann, wie unendlich klug sie sind.&lt;/p&gt;

&lt;p&gt;Doch dieser Schein verblasst schnell und am Ende bleibt es dann bei 
warmer Luft (CO2-Alarm!).&lt;/p&gt;

&lt;p&gt;Ich muss zugeben, dass ich mit den beiden genannten Menschen-Typen nicht gut
zurecht komme, auch wenn sie oft sozial umgänglicher oder sympathischer 
auftreten.&lt;/p&gt;

&lt;h3 id=&quot;der-techniker&quot;&gt;Der Techniker&lt;/h3&gt;

&lt;p&gt;Ganz anders sieht es aus, wenn man Leuten gegenüber sitzt, die keine 
Floskeln produzieren, sondern anfangs meist etwas vorsichtig aber 
zielgerade zur Sache kommen.&lt;/p&gt;

&lt;p&gt;Nicht-eingeweihte verstehen zwar den einen oder anderen Fachbegriff nicht,
doch ehe man sich versieht ist man mitten in einer spannenden Diskussion,
die quasi von selbst läuft.&lt;/p&gt;

&lt;p&gt;Und dann kommt der Moment wo kein künstliches sondern ein “echtes”
Lächeln über die Wangen huscht, wenn man erzählt:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ja und in der neuen Version, hey, das war echt genial, haben sie 
endlich mal den Bug behoben, na und jetzt rennt alles perfekt.
Mann! Wenn wir jetzt noch …&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Das ist dann der Moment, wo ich mir denke:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Jap! Es ist echt “cool” unter anderen Gleichgesinnten zu sein!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Weil es nämlich nicht das letzte SCRUM-Standup oder das Buch im Regal
mit dem Titel “Der Coding-Experte” ist, das uns Innovationen und vielleicht
eine bessere Zukunft bringt, sondern es sind die Menschen die Freude
an ihrem Schaffen und Tüfteln haben und diese Motivation in all ihr
Handeln einfließen lassen.&lt;/p&gt;

&lt;p&gt;Und in dem Moment sind eben das die “coolen” Jungs.
Und ja, es sind leider fast immer nur “Jungs”. Ich hatte bisher noch nie
das Glück gehabt, mit einer Entwicklerin zusammenzukommen.&lt;br /&gt;
Doch es gibt sie, und mit etwas gutem Willen werden es mehr werden.&lt;br /&gt;
Bei den Gamerinnen hat es begonnen und so hoffe ich, dass es in Zukunft
auch in der Software-Entwicklung mehr Frauen geben wird.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;In jedem Fall freue ich mich, dass ich bei einigen Gesprächen
hoch motivierte Programmierer und IT-Begeisterte kennen lernen durfte und es 
gibt mir ein gutes Gefühl zu wissen, dass es für jeden “Möchtegern-IT-Experten” 
auch ein Gegenstück in Form eines aufgeschlossenen Menschen gibt, der mit
Leidenschaft an die Herausforderungen des Alltags heran geht.&lt;/p&gt;

&lt;p&gt;Und was mich betrifft … ja leider musste ich mich für einen Weg unter
mehreren entscheiden und ich freue mich ihn nun zu gehen. Und so kommt 
man eben nicht mehr mit allen anderen neu kennen gelernten Gesichtern direkt
zusammen.&lt;br /&gt;
Aber gerne hätte ich mir den einen oder anderen potentiellen Kollegen in 
meine neue Arbeit mitgenommen. Schade dass das nicht so einfach geht.&lt;/p&gt;

&lt;p&gt;Aber wie sagt man so schön: 
Man sieht sich im Leben immer zweimal ;)&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Festplattengrößen</title>
   <link href="https://www.opengate.at/blog/2019/02/hdd-sizes/"/>
   <published>2019-02-27T22:31:00+01:00</published>
   <updated>2019-02-27T22:31:00+01:00</updated>
   <id>https://www.opengate.at/blog/2019/02/hdd-sizes</id>
   <category term="hardware" /><category term="retro" />
   <summary type="text">Es ist schon faszinierend, wieviel Daten wir Menschen (und Maschinen) brauchen
und produzieren.
Belegte mein erstes DOS+Windows 
so um die 20 MB, brauchte 
Windows XP bereits 1 GB 
und seit Windows 10 
bekommt man das OS unter 10 GB (fast) nicht mehr installiert.

Doch schlimmer sieht es mit unseren Daten aus, die wir so mit uns 
herumschleppen. Denn während meine Schuldokumente und fast alle Quellcodes
auf ein bis 2 Disketten passten 
(so um die 2 MB), fängt heute jedes einzelne geschäftliche E-Mail mit einer
Logo-Grafik von 5 MB an und viele Einzeldokumente mit ein paar Seiten Text 
belegen den Platz, den früher meine gesamte 
Festplatte bieten konnte.

Und wenn man die Selfies und VOD
Movies mitrechnet, die jeder auf dem Smartphone mitschleppt, 
kommen wir in noch höhere Sphären.
</summary>
   <content type="html">&lt;p&gt;Es ist schon faszinierend, wieviel Daten wir Menschen (und Maschinen) brauchen
und produzieren.
Belegte mein erstes &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_3.1&quot;&gt;DOS+Windows&lt;/a&gt; 
so um die 20 MB, brauchte 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_XP&quot;&gt;Windows XP&lt;/a&gt; bereits 1 GB 
und seit &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_10&quot;&gt;Windows 10&lt;/a&gt; 
bekommt man das OS unter 10 GB (fast) nicht mehr installiert.&lt;/p&gt;

&lt;p&gt;Doch schlimmer sieht es mit unseren Daten aus, die wir so mit uns 
herumschleppen. Denn während meine Schuldokumente und fast alle Quellcodes
auf ein bis 2 &lt;a href=&quot;https://de.wikipedia.org/wiki/Diskette&quot;&gt;Disketten&lt;/a&gt; passten 
(so um die 2 MB), fängt heute jedes einzelne geschäftliche E-Mail mit einer
Logo-Grafik von 5 MB an und viele Einzeldokumente mit ein paar Seiten Text 
belegen den Platz, den früher meine gesamte 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Festplattenlaufwerk&quot;&gt;Festplatte&lt;/a&gt; bieten konnte.&lt;/p&gt;

&lt;p&gt;Und wenn man die Selfies und &lt;a href=&quot;https://de.wikipedia.org/wiki/Video-on-Demand&quot;&gt;VOD&lt;/a&gt;
Movies mitrechnet, die jeder auf dem Smartphone mitschleppt, 
kommen wir in noch höhere Sphären.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Hier mal ein Auszug von PCs und deren Festplattengrößen über die
letzten 20 Jahre:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;1994: &lt;a href=&quot;https://de.wikipedia.org/wiki/Intel_80386&quot;&gt;386SX&lt;/a&gt;: 40 MB&lt;/li&gt;
  &lt;li&gt;1996: &lt;a href=&quot;https://de.wikipedia.org/wiki/Intel_80486&quot;&gt;486DX2&lt;/a&gt;: 512 MB&lt;/li&gt;
  &lt;li&gt;1998: &lt;a href=&quot;https://de.wikipedia.org/wiki/Cyrix_6x86MX&quot;&gt;Cyrix 6x86 MX&lt;/a&gt;: 2.1 GB&lt;/li&gt;
  &lt;li&gt;2001: &lt;a href=&quot;https://de.wikipedia.org/wiki/AMD_Duron&quot;&gt;AMD Duron&lt;/a&gt;: 20 GB&lt;/li&gt;
  &lt;li&gt;2005: &lt;a href=&quot;https://de.wikipedia.org/wiki/Intel_Celeron_D&quot;&gt;Celeron D&lt;/a&gt;: 120 GB&lt;/li&gt;
  &lt;li&gt;2008: &lt;a href=&quot;https://de.wikipedia.org/wiki/AMD_Athlon_64&quot;&gt;Athlon64&lt;/a&gt;: 500 GB&lt;/li&gt;
  &lt;li&gt;2012: &lt;a href=&quot;https://de.wikipedia.org/wiki/Intel-Core-i-Serie#Sandy-Bridge-Generation&quot;&gt;Intel i3 Sandy Bridge&lt;/a&gt;: 500 GB + 1 TB&lt;/li&gt;
  &lt;li&gt;2015: &lt;a href=&quot;https://de.wikipedia.org/wiki/Intel-Core-i-Serie#Ivy-Bridge-Generation&quot;&gt;Intel i3 Ivy Bridge&lt;/a&gt;: 256 GB SSD + 3 TB + 2 TB&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Soll heißen, dass meine heutige Plattenkombination um 131250 mal großer ist, 
als die alte Festplatte meines ersten Computers, bei dem immer 1/4 frei war, 
weil Word-Dokumente immer nur 1 paar Kilobytes groß waren, und wo ich heute 
immer wieder mal an eine Partitionsgrenze stoße und ich ein paar Videodateien
auf eine &lt;a href=&quot;https://de.wikipedia.org/wiki/Blu-ray_Disc&quot;&gt;Blu-Ray&lt;/a&gt; brennen muss.&lt;/p&gt;

&lt;p&gt;Bei Betriebssystemen verstehe ich Zuwachs teilweise ja noch, weil 
wir ja so viel Kompatibilität wie möglich haben wollen und ein OS
somit unzählige Versionen von Bibliotheken aus allen IT-Epochen
mitschleppen muss und täglich werden die Codebases größer.&lt;/p&gt;

&lt;p&gt;Bei Grafiken ist meine Toleranz schon etwas geringer, denn nur weil
ein Foto eine höhere Auflösung hat wird das Bild dadurch nicht besser.&lt;/p&gt;

&lt;p&gt;Und die Datenschützer machen sich auch noch Sorgen, dass man inzwischen
tatsächlich Fingerabdrücke aus Gruppenfotos ableiten kann, weil die
Auflösung derartig hoch geworden ist.&lt;br /&gt;
Doch für den tägliche Gebrauch sind diese Daten oft viel zu viel,
und so herrscht auch hier auf diesem Blog, die Regel, dass eine
Grafik nicht größer als 100 KB sein darf. Und das reicht auch, wenn
man die Auflösung etwas reduziert und Dateiformate wählt, die gut
komprimieren.&lt;/p&gt;

&lt;p&gt;Wer eine Heimkinoanlage hat, nutzt sowieso angepasste Hardware,
daher verstehe ich nicht, warum man auch auf kleinen Laptops immer
nur HD-Videos haben will.&lt;br /&gt;
Ich habe mir schon ein paar mal den Luxus gegönnt am PC sowohl SD
und HD Videos zu kaufen und anzusehen und finde, dass am Monitor 
kein qualitativer Unterschied besteht, der die Verdoppelung bis
Verdreifachung der Videodaten rechtfertigt … nicht mal auf 
größeren Fernsehmonitoren.&lt;/p&gt;

&lt;p&gt;Natürlich kann man argumentieren, dass man in epischen Schlachten
im Standbild theoretisch jeden einzelnen Hintergrundkämpfer in
perfekter Schärfe ansehen könnte … doch im Film ist das 
irrelevant und unsere Gehirne blenden diese vielen Details automatisch
wieder aus.&lt;/p&gt;

&lt;p&gt;Und bei der Programmierung sieht es ähnlich übel aus:
Neben den Quelldateien erzeugen Compiler und IDEs manchmal Gigabyte-
große Objekt- und Hilfsdateien.
Natürlich brauchen Optimierungsroutinen beim Kompilieren möglichst
viele Daten für Statistiken, aber Gigabytes? Echt jetzt?&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/C-Sharp&quot;&gt;C#&lt;/a&gt; und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Java_(Programmiersprache)&quot;&gt;Java&lt;/a&gt; verzichten 
darauf, OK sie optimieren ja auch nichts, aber kommt mir der Output mancher
&lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B&quot;&gt;C++&lt;/a&gt; Compiler etwas übertrieben vor.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit:&lt;/h3&gt;

&lt;p&gt;Aus all diesen Problem hat sich die Tatsache ergeben, dass viele Operationen 
auf klassischen Magnetscheiben-Festplatten nicht mehr lauffähig sind.
Die Mechanik ist einfach nicht schnell genug um so große Datenmenge schnell
ins &lt;a href=&quot;https://de.wikipedia.org/wiki/Random-Access_Memory&quot;&gt;RAM&lt;/a&gt; zu schaufeln.&lt;br /&gt;
Daher retten uns seit bald 10 Jahren 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Solid-State-Drive&quot;&gt;SSDs (Solid State Drives)&lt;/a&gt; den Tag.&lt;/p&gt;

&lt;p&gt;Ich würde daher am Anfang, und zwar bei uns Programmierern anfangen.
Wir müssen uns einfach wieder mal etwas zurück besinnen und unsere Konzepte
platzsparender auslegen.
Sinnloser Ballast sollte entfernt und der notwendige Rest durch bessere
Strukturen und Kompression reduziert werden.&lt;/p&gt;

&lt;p&gt;Das Resultat sind schnellere Programme, weniger Hardwareschrott (weil zu klein)
und am Ende länger zufriedene Nutzer.&lt;/p&gt;

&lt;p&gt;… so ist zumindest meine Meinung.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Luftreiniger</title>
   <link href="https://www.opengate.at/blog/2019/02/air-purifier/"/>
   <published>2019-02-26T19:15:00+01:00</published>
   <updated>2019-02-26T19:15:00+01:00</updated>
   <id>https://www.opengate.at/blog/2019/02/air-purifier</id>
   <category term="hardware" />
   <summary type="text">Was macht man mit den alten CPU Lüftern, die seit Jahren in einer Schachtel
liegen?

Genau, man baut sich daraus einen Luftreiniger.

Und dank einiger Vorlagen auf thingiverse.com
(Suchbegriff “air purifier”) braucht man neben einem 3D-Drucker nur noch eine
Kohlefiltermatte.
</summary>
   <content type="html">&lt;p&gt;Was macht man mit den alten CPU Lüftern, die seit Jahren in einer Schachtel
liegen?&lt;/p&gt;

&lt;p&gt;Genau, man baut sich daraus einen Luftreiniger.&lt;/p&gt;

&lt;p&gt;Und dank einiger Vorlagen auf &lt;a href=&quot;http://www.thingiverse.com&quot;&gt;thingiverse.com&lt;/a&gt;
(Suchbegriff “air purifier”) braucht man neben einem 3D-Drucker nur noch eine
Kohlefiltermatte.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Aktivkohlefilter&quot;&gt;Aktivkohlefilter&lt;/a&gt; findet 
man im Baumarkt oder überall, wo es Zubehör zu  Luftabzügen von Öfen gibt.
Das Material sieht etwas wie Filz aus, und bindet aus der durchströmenden 
Luft chemische und biologische Schadstoffe.&lt;br /&gt;
Damit verringern sich auch die Gerüche die durch biologische 
Umwandlungsprozesse entstehen.&lt;/p&gt;

&lt;p&gt;Die Idee ist nun, dass der Kühlventilator Luft durch einen solchen
Filter bläst.&lt;/p&gt;

&lt;p&gt;Und da es eben einige Formen für solche Lüftergehäuse als 3D-Druck Modell
gibt, sucht man sich einfach eines aus, das einem zusagt.&lt;/p&gt;

&lt;p&gt;Dann müssen wir noch Strom für den Lüfter bereitstellen.&lt;/p&gt;

&lt;p&gt;Leider arbeiten solche CPU Lüfter mit 12 Volt, also bräuchte man ein
Netzteil, das diese Leistung bereit stellt.&lt;/p&gt;

&lt;p&gt;Wenn man den Lüfter aber nicht auf vollen Touren laufen lassen will und
der Lüfter selbst es verträgt, kann man auch versuchen ihn mit nur 5 Volt
zu betreiben.&lt;/p&gt;

&lt;p&gt;Tatsächlich funktionierte das bei meinen alten Modellen nur mit einem
80 mm Teil. Die kleineren begannen erst ab 8 oder 9 Volt zu laufen.
5 Volt werden nämlich via USB bereit gestellt und damit kann man sich
aus alten Kabeln leicht einen Stecker basteln, den man einfach am Stand PC
oder Laptop anschließen kann.&lt;/p&gt;

&lt;p&gt;Ein solcher Luftreiniger reinigt dann eben recht langsam, dafür aber 
kontinuierlich.&lt;/p&gt;

&lt;p&gt;Ich habe mir um ca. 15 Euro eine größere Filtermatte zugelegt, aus der
ich jede Menge solcher kleinen Plättchen ausschneiden kann, um sie in
ausgedruckte Filtergehäuse zu legen.
Und nach ein paar Tagen oder Wochen (je nach Betrieb) kann man die 
Filterstückchen wegwerfen und durch neue ersetzen.&lt;/p&gt;

&lt;p&gt;Die größte Freude bereitete mir die Tatsache, dass meine 5 Volt
Solarzellen für Mikrocontroller zusammengeschaltet ebenso meinen 
80 mm Filter-Lüfter betreiben können.&lt;/p&gt;

&lt;p&gt;Und so kostet mich der Betrieb des Luftreinigers keinen Netzstrom 
während Staub und Schmutzpartikel tagsüber langsam angesaugt und
absorbiert werden.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/img/air-purifier.jpg&quot; alt=&quot;Air Purifier&quot; /&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Übrigens kann man solche Filtermattenstückchen auch über die
PC-Netzteil-Lüfter tackern (zumindest wenn diese nicht zu heiß
werden).
Denn meine PCs ziehen massig Staub an, der sich in den Filtern
fängt und während ich früher im Licht der Tischlampe immer wieder
Staub vorbeifliegen sah, hat diese Reinigung bei mir eine deutliche
Besserung erzielt.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Commanders, von Norton bis Midnight</title>
   <link href="https://www.opengate.at/blog/2019/02/commander/"/>
   <published>2019-02-25T12:18:00+01:00</published>
   <updated>2019-02-25T12:18:00+01:00</updated>
   <id>https://www.opengate.at/blog/2019/02/commander</id>
   <category term="software" /><category term="retro" />
   <summary type="text">Egal ob es sich damals um DOS oder 
heute um Linux Konsolen handelt(e), 
niemand will einzelne Dateien per 
Kommandozeile suchen, bearbeiten
und kopieren.
(Außer es handelt sich um sich wiederholende Muster, die automatisierbar sind.)

Und so fand ich schon Mitte der 90er Jahre schnell zum weitverbreiteten Tool
Norton Commander (NC.EXE), 
mit dem ich auf dem Textbildschirm mit den Pfeiltasten durch das Dateisystem
huschen konnte.
</summary>
   <content type="html">&lt;p&gt;Egal ob es sich damals um &lt;a href=&quot;https://de.wikipedia.org/wiki/MS-DOS&quot;&gt;DOS&lt;/a&gt; oder 
heute um &lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt; Konsolen handelt(e), 
niemand will einzelne Dateien per 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Kommandozeile&quot;&gt;Kommandozeile&lt;/a&gt; suchen, bearbeiten
und kopieren.&lt;br /&gt;
(Außer es handelt sich um sich wiederholende Muster, die automatisierbar sind.)&lt;/p&gt;

&lt;p&gt;Und so fand ich schon Mitte der 90er Jahre schnell zum weitverbreiteten Tool
&lt;a href=&quot;https://de.wikipedia.org/wiki/Norton_Commander&quot;&gt;Norton Commander&lt;/a&gt; (NC.EXE), 
mit dem ich auf dem Textbildschirm mit den Pfeiltasten durch das Dateisystem
huschen konnte.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Das beste am “Commander” war und ist der integrierte Text-Viewer und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Texteditor&quot;&gt;Text-Editor&lt;/a&gt;. 
Jede ausgewählte Datei konnte per F2 im Nur-Lesen Modus
angezeigt werden und per F3 editiert und gespeichert werden.&lt;/p&gt;

&lt;p&gt;Auch ein unverkennbares Markenzeichen sind die beiden Dateifenster.
Man konnte sich links und rechts zwei separate Datei-Browsing-Bereiche
einblenden lassen und mit der TAB-Taste zwischen beiden wechseln.&lt;/p&gt;

&lt;p&gt;Somit konnte man zwei Verzeichnisse fast gleichzeitig bearbeiten.
Man konnte z.B. links Dateien auswählen und per F5 in des ausgewählte
Verzeichnis auf der rechten Seite kopieren.&lt;/p&gt;

&lt;p&gt;Diese Möglichkeit kannte ich anfangs allerdings nicht und nutzt so immer
nur das rechte Fenster zum Verzeichnis-Durchschauen.
Und auf der ungenutzten linken Seite schien dies Ausgabe des zuletzt 
gestarteten Programms durch.&lt;/p&gt;

&lt;p&gt;Eine EXE, COM oder BAT Datei konnte per ENTER sofort gestartet 
werden. Der Commander blendete sich aus, ließ dass Programm
laufen und nach dessen Ende wurde wieder der Commander über den
Schirm geblendet.&lt;/p&gt;

&lt;p&gt;So lernte ich &lt;a href=&quot;https://de.wikipedia.org/wiki/BAT-Datei&quot;&gt;BATCH-Scripting&lt;/a&gt; 
mit großer Leidenschaft, weil man unglaublich schnell zwischen Editierung
und Script-Ausführung mit wenigen Tasten hin- und herschalten konnte.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Gerade unter Linux erlebt dieser Trend bei mir wieder eine Renaissance,
da es dort das OpenSource-Tool 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Midnight_Commander&quot;&gt;Midnight Commander&lt;/a&gt; (MC) 
gibt, welches die Ziele des alten NC auf 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Unix&quot;&gt;Unix&lt;/a&gt; und Linux Systeme überträgt.&lt;/p&gt;

&lt;p&gt;Ob es nun mein &lt;a href=&quot;http://www.orangepi.org/&quot;&gt;Orange PI&lt;/a&gt; oder 
&lt;a href=&quot;http://wiki.friendlyarm.com/wiki/index.php/NanoPi_NEO&quot;&gt;NanoPI Neo&lt;/a&gt; 
über die serielle Schnittstelle sind, oder eine Linux-VM über 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Secure_Shell&quot;&gt;SSH&lt;/a&gt;:&lt;br /&gt;
Überall muss der MC installiert sein, damit ich effizient 
Konfigurationsdateien anpassen und zwischen Verzeichnissen herumkopieren
kann.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Kurz gesagt: &lt;strong&gt;Ich liebe dieses Tool&lt;/strong&gt; und es zählte damals wie heute zu 
meinen meist genutztesten Werkzeugen in der Systemadministration.&lt;/p&gt;

&lt;p&gt;Auch unter Windows haben einige Produkte dieses alte Schema aufgegriffen.
Beispiele sind 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Total_Commander&quot;&gt;TotalCommander&lt;/a&gt; oder 
&lt;a href=&quot;http://freecommander.com/de/ubersicht/&quot;&gt;FreeCommander&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Gelegentlich setze ich auch diese Programme ein, vor allem der FreeCommander
fehlt bei meinen &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_PE&quot;&gt;Windows PE&lt;/a&gt;
Images nie. Doch innerhalb einer Fenster-GUI Umgebung sind sie bei weitem 
nicht so notwendig, wie auf der guten alten Konsole.&lt;/p&gt;

&lt;p&gt;Die Commander Serie bestätigt mir somit, dass alte Konzept quasi ewig leben,
wenn sie gut sind und den Nutzern Arbeit und Zeit ersparen.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Zeitrechnungen</title>
   <link href="https://www.opengate.at/blog/2019/02/times/"/>
   <published>2019-02-24T12:05:00+01:00</published>
   <updated>2019-02-24T12:05:00+01:00</updated>
   <id>https://www.opengate.at/blog/2019/02/times</id>
   <category term="devel" />
   <summary type="text">Da meinte doch tatsächlich mal ein 
Java-Programmierer,
ich solle keinen Code nutzen, der auf den 
Calendar -
Klassen basiert und 
SimpleDateFormat 
einsetzt, denn diese sind nicht Thread-sicher.

Ich kann das ja immer noch nicht glauben, dass Java in seinem Aufbau so defekt
ist, dass es Kalender-Rechnungen in globalen Variablen vermurxt und dann 
Fehler oder Abstürze produziert, wenn unterschiedliche Instanzen in Threads
benutzt werden.

… doch offenbar melden mehrere Seiten solche Probleme.
</summary>
   <content type="html">&lt;p&gt;Da meinte doch tatsächlich mal ein 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Java_(Programmiersprache)&quot;&gt;Java&lt;/a&gt;-Programmierer,
ich solle keinen Code nutzen, der auf den 
&lt;a href=&quot;http://docs.oracle.com/javase/7/docs/api/java/util/Calendar.html&quot;&gt;Calendar&lt;/a&gt; -
Klassen basiert und 
&lt;a href=&quot;http://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html&quot;&gt;SimpleDateFormat&lt;/a&gt; 
einsetzt, denn diese sind nicht Thread-sicher.&lt;/p&gt;

&lt;p&gt;Ich kann das ja immer noch nicht glauben, dass Java in seinem Aufbau so defekt
ist, dass es Kalender-Rechnungen in globalen Variablen vermurxt und dann 
Fehler oder Abstürze produziert, wenn unterschiedliche Instanzen in Threads
benutzt werden.&lt;/p&gt;

&lt;p&gt;… doch offenbar melden mehrere Seiten solche Probleme.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Da mir einige C-&lt;a href=&quot;https://de.wikipedia.org/wiki/Compiler&quot;&gt;Compiler&lt;/a&gt; 
(Stichwort: &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_CE&quot;&gt;Windows CE&lt;/a&gt;) 
ebenso keine Zeitfunktionen anboten, hatte ich mir vor langem mal die Zeit 
genommen, die Zeit selbst zu berechnen.&lt;/p&gt;

&lt;p&gt;… so schwer ist das ja nicht!&lt;/p&gt;

&lt;p&gt;Wir starten brav im 
&lt;a href=&quot;/blog/2018/11/1601/&quot;&gt;Jahr 1601&lt;/a&gt; und können so 
schrittweise Datumsangaben in Sekunden, Millisekunden oder Mikrosekunden 
bis zum heutigen Datum hochrechnen.&lt;/p&gt;

&lt;p&gt;Wichtig sind die Schaltjahr Regeln:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Grundsätzlich ist jedes 4. (bzw. durch 4 teilbare) Jahr  ein Schaltjahr, 
womit der Februar 29 statt 28 Tage hat.&lt;/li&gt;
  &lt;li&gt;Jedes 100ste Jahr ist aber kein Schaltjahr!&lt;/li&gt;
  &lt;li&gt;Doch jedes 400ste Jahr ist dann doch wieder ein Schaltjahr&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Oder wie der C-Programmierer sagen würde:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;gate_bool_t gate_time_is_leap_year(gate_uint16_t year)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;{
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt;(&lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt; == (year % &lt;span style=&quot;color:#00D&quot;&gt;400&lt;/span&gt;)) &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color:#069&quot;&gt;true&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt;(&lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt; == (year % &lt;span style=&quot;color:#00D&quot;&gt;100&lt;/span&gt;)) &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color:#069&quot;&gt;false&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt;(&lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt; == (year % &lt;span style=&quot;color:#00D&quot;&gt;4&lt;/span&gt;)) &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color:#069&quot;&gt;true&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color:#069&quot;&gt;false&lt;/span&gt;;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Es reichen also schon einfachste Zählschleifen, um von Tag 0 am 1.1.1601,
die bis zum gewünschten Tag hoch zu zählen und jeweils die Sekunden eines
Tages (60 x 60 x 24 == 86400) aufzuaddieren.&lt;/p&gt;

&lt;p&gt;Und wenn man Datumsangaben in Ganzzahlen übersetzen kann und umgekehrt, 
sind so “komplexe” Rechnungen wie die Differenz zwischen zwei Zeitpunkten
ein Klacks.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Natürlich kann man das optimieren und Fixpunkte in Tabellen einbauen.
Den einzigen, den ich gerne nutze, ist die Unix-Geburtsstunde, am 
&lt;code&gt;1. 1. 1970&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Doch sobald man weiß, dass dieser Zeitpunkt &lt;code&gt;11644473600&lt;/code&gt; Sekunden vom
&lt;code&gt;1. 1. 1601&lt;/code&gt; entfernt ist, kann man auch schön zwischen Unix- und 1601-Zeit
umrechnen.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Also warum (zur Hölle) braucht Java für so eine Trivialität thread-unsicheren Code?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Daher habe ich mir die 100 Zeilen C Code zur Zeitumrechnung in eine Java Klasse 
kopiert und arbeite nun aus purer Trotzigkeit damit.&lt;br /&gt;
Das soll doch wohl ein Scherz sein, dass erst neue Zeitklassen in Java 8 dieses
Problem im Jahr 2014 zu lösen versuchen und sämtlicher alter Java-Code “buggy”
wird, wenn man ein Datum als lesbaren Text ausgeben will!&lt;/p&gt;

&lt;h3 id=&quot;fazit-hände-weg-von-einigen-java-klassen&quot;&gt;Fazit: Hände weg von (einigen) Java-Klassen&lt;/h3&gt;

&lt;p&gt;Ich will jetzt ja nicht behaupten, dass alles an Java schlecht sei, aber 
solche Konzeptfehler dürfen in einer modernen Sprache nicht auftreten.
Selbst C und C++ haben es im Jahr 2000 geschafft viele historische Funktionen
Thread-safe zu gestalten ohne die Kompatibilität zu brechen.&lt;/p&gt;

&lt;p&gt;Und dass das in Java 20 Jahre lang nicht möglich war halte ich für grob fahrlässig.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>setjmp / longjmp</title>
   <link href="https://www.opengate.at/blog/2019/02/setjmp/"/>
   <published>2019-02-23T10:34:00+01:00</published>
   <updated>2019-02-23T10:34:00+01:00</updated>
   <id>https://www.opengate.at/blog/2019/02/setjmp</id>
   <category term="devel" />
   <summary type="text">
  In einer Zeit, als die alten Götter herrschten,
schrie das Land, das Kriegsherrn in Aufruhr versetzten, nach …


Exceptions, weil weder 
Hercules noch 
Xena 
ein Konzept zur strukturierten Fehlerbehandlung vorweisen konnten.

C++ wurde erst 1998 
vollständig standardisiert und die anderen Sprachen 
… gab es die eigentlich schon?

Doch einer der ältesten Titanen, nämlich 
C, zeigte sich 
unbeeindruckt, da er schon lange über ein Technik verfügte, in “Ausnahmefällen”
quer durch den Code zu springen.
</summary>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;In einer Zeit, als die alten Götter herrschten,
schrie das Land, das Kriegsherrn in Aufruhr versetzten, nach …&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Exceptions&lt;/strong&gt;, weil weder 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Hercules_(Fernsehserie)&quot;&gt;Hercules&lt;/a&gt; noch 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Xena_%E2%80%93_Die_Kriegerprinzessin&quot;&gt;Xena&lt;/a&gt; 
ein Konzept zur strukturierten Fehlerbehandlung vorweisen konnten.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B#Standardisierung&quot;&gt;C++ wurde erst 1998&lt;/a&gt; 
vollständig standardisiert und die anderen Sprachen 
… gab es die eigentlich schon?&lt;/p&gt;

&lt;p&gt;Doch einer der ältesten Titanen, nämlich 
&lt;a href=&quot;https://de.wikipedia.org/wiki/C_(Programmiersprache)&quot;&gt;C&lt;/a&gt;, zeigte sich 
unbeeindruckt, da er schon lange über ein Technik verfügte, in “Ausnahmefällen”
quer durch den Code zu springen.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Die Rede ist von den oft vergessenen Funktionen 
&lt;a href=&quot;https://en.wikipedia.org/wiki/Setjmp.h&quot;&gt;setjmp()/longjmp()&lt;/a&gt; und die 
beiden stellen aus meiner bescheidenen Sicht die Krönung der Hardware-
Abstraktion in einer Hochsprache dar.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;setjmp()&lt;/code&gt; sichert den aktuellen CPU Status in einem Puffer und arbeitet
dann wie jede andere Funktion linear im Code weiter.&lt;br /&gt;
Wird jedoch später &lt;code&gt;longjmp&lt;/code&gt; aktiviert, kommt es zur Wiederherstellung 
des gespeicherten Zustandes und egal wo in welcher Unterfunktion man
gerade Code abarbeitete, man landet wieder dort, wo man zuvor &lt;code&gt;setjmp&lt;/code&gt; 
ausgeführt hatte.&lt;/p&gt;

&lt;p&gt;Syntaktisch Funktionen auch Exceptions so. Man umklammert einen kritischen
Block mit &lt;code&gt;try { ... }&lt;/code&gt; und landet bei einem Fehler (Exception) im 
nachfolgenden &lt;code&gt;catch(...) { ... }&lt;/code&gt; Block.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;setjmp&lt;/code&gt; teilt über seinen Rückgabewert mit, ob es sich um ein “Setzen” des
Sprungpunktes handelte oder eine Rücksprung zu diesem.&lt;br /&gt;
Man könnte also fast glauben, C hätte einen Exception Mechanismus und man 
könnte C++ Exceptions mit &lt;code&gt;setjmp()/longjmp()&lt;/code&gt; umsetzen.&lt;/p&gt;

&lt;p&gt;Ganz so einfach ist es aber nicht, denn es handelt sich eben nur um einen
gezielten Sprung. In anderen Funktion geöffnete Ressourcen bleiben weiter
offen, da sie niemand schließt und folglich ist der Zustand des Programms
nach einem &lt;code&gt;longjmp()&lt;/code&gt; in vielen Fällen korrumpiert.&lt;/p&gt;

&lt;p&gt;Wenn, dann müsste man (am besten automatisiert) um jeden Funktionsaufruf
einen &lt;code&gt;setjmp()/longjmp()&lt;/code&gt; mit einem eigenen Kontextpuffer basteln, der lokale
Spezialitäten freigibt, so wie es in C++ durch Destruktoren erledigt wird.&lt;/p&gt;

&lt;p&gt;Denn C++ Exceptions garantieren, dass im Falle von &lt;code&gt;throw ...&lt;/code&gt; jede laufende
Funktion “rückabgewickelt” wird, bis man den &lt;code&gt;try-catch&lt;/code&gt; Block erreicht hat.
Eine solche Garantie kennen setjmp/longjmp leider nicht.&lt;/p&gt;

&lt;h3 id=&quot;einsatzort&quot;&gt;Einsatzort&lt;/h3&gt;

&lt;p&gt;Tja, wo setzt man also solche Konstrukte heute noch ein?&lt;br /&gt;
Nun es gibt C-Bibliotheken, die in Fehlerfällen 
&lt;a href=&quot;http://en.cppreference.com/w/c/program/abort&quot;&gt;&lt;code&gt;abort()&lt;/code&gt;&lt;/a&gt; oder 
&lt;a href=&quot;http://www.cplusplus.com/reference/cstdlib/exit/&quot;&gt;&lt;code&gt;exit()&lt;/code&gt;&lt;/a&gt;
aufrufen, was einem ziemlich den Tag versauen kann.&lt;/p&gt;

&lt;p&gt;Die &lt;a href=&quot;https://de.wikipedia.org/wiki/Libpng&quot;&gt;libpng&lt;/a&gt; ist so ein Teufelchen. 
Sie lässt einen nur eine Notfall-Funktion registrieren, die aufgerufen wird um nach Hilfe zu rufen, beendet aber nach deren
Rückkehr den Prozess, zumindest war dies in früheren Versionen so.&lt;br /&gt;
Einzige Lösung ist der libpng mit einem longjmp die Kontrolle zu entziehen.&lt;/p&gt;

&lt;p&gt;Man kann &lt;code&gt;longjmp()&lt;/code&gt; aber auch in Signalhandlern einsetzen, um sich vor einem
tödlichen &lt;code&gt;[SEGFAULT](https://de.wikipedia.org/wiki/Schutzverletzung)&lt;/code&gt; zu 
schützen.&lt;br /&gt;
Signale werden ähnlich wie normale Funktionsaufrufe in den laufenden Code
injiziert. Unterbricht der Prozessor die Ausführung wegen eines solchen
schweren Fehlers, findet die Ausführung über (genauer genommen ‘unter’) dem
Context der zuletzt ausgeführten Funktion statt.&lt;br /&gt;
Und von hier aus kann man zum letzten “Fail-Safe” Punkt zurückspringen.
Andernfalls würde ebenfalls nach dem Signalcode der Prozess beendet werden.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Jeder C Programmierer, die noch nie von der Existenz von &lt;code&gt;setjmp()/longjmp()&lt;/code&gt; 
gehört hat, sollte sich wieder mal die Zeit nehmen und im Handbuch 
nachschlagen.&lt;/p&gt;

&lt;p&gt;Diese Funktionen sind besonders in der Systemprogrammierung hilfreich um 
Kollateralschäden durch defekte Komponenten zu bekämpfen.
Null-Pointer und andere tödliche Programmierfehler können so zur Laufzeit
abgefangen werden und das Programm in einen (einigermaßen) stabilen Zustand
überführen.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Umgebungsvariablen und mehr</title>
   <link href="https://www.opengate.at/blog/2019/02/environment/"/>
   <published>2019-02-22T22:01:00+01:00</published>
   <updated>2019-02-22T22:01:00+01:00</updated>
   <id>https://www.opengate.at/blog/2019/02/environment</id>
   <category term="devel" />
   <summary type="text">Ein paar wichtige Informationen bekommt jeder genetisch mitvererbt,
wenn er das Licht der Welt erblickt.
Das ist bei Prozessen ganz ähnlich wie bei Menschen.

Die “Umgebung” 
(“Environment”) beinhaltet einige Datenwerte, die der
Elternprozess seinen Kindern “aufdrücken” kann, und wenn er sich nicht
weiter darum kümmert bekommen die Kinder das gleiche, was er selbst
auf den Weg mitbekommen hat … die Umgebung wird also vererbt.
</summary>
   <content type="html">&lt;p&gt;Ein paar wichtige Informationen bekommt jeder genetisch mitvererbt,
wenn er das Licht der Welt erblickt.&lt;br /&gt;
Das ist bei Prozessen ganz ähnlich wie bei Menschen.&lt;/p&gt;

&lt;p&gt;Die &lt;a href=&quot;https://de.wikipedia.org/wiki/Umgebungsvariable&quot;&gt;“Umgebung”&lt;/a&gt; 
(“Environment”) beinhaltet einige Datenwerte, die der
Elternprozess seinen Kindern “aufdrücken” kann, und wenn er sich nicht
weiter darum kümmert bekommen die Kinder das gleiche, was er selbst
auf den Weg mitbekommen hat … die Umgebung wird also vererbt.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Es wäre schön, wenn es einen ausgeprägten Standard gäbe, was in 
“der Umgebung” alles gespeichert ist, doch bis auf wenige Details 
haben unterschiedliche Anwendungsgruppen auch unterschiedliche
Umgebungsvariablen ausgeprägt.&lt;/p&gt;

&lt;p&gt;Jedenfalls gibt es APIs um auf die eigene Umgebung zuzugreifen, und 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows&quot;&gt;Windows&lt;/a&gt;
vertraut dabei auf 
&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-getenvironmentvariable&quot;&gt;&lt;code&gt;GetEnvironmentVariable()&lt;/code&gt;&lt;/a&gt;, 
während &lt;a href=&quot;https://de.wikipedia.org/wiki/Unix&quot;&gt;Unices&lt;/a&gt; mit 
&lt;a href=&quot;http://pubs.opengroup.org/onlinepubs/009695399/functions/getenv.html&quot;&gt;&lt;code&gt;getenv()&lt;/code&gt;&lt;/a&gt; 
arbeiten.&lt;/p&gt;

&lt;p&gt;Während Unix Systeme auf diese Umgebung “vertrauen”, stellt Windows
für einige Felder eigene APIs bereit:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Das “temporäre” Verzeichnis&lt;br /&gt;
Hier dürfen Programme Dateien ablegen, die nur kurzzeitig zur
Datenauslagernung genutzt und dann gelöscht werden.
    &lt;ul&gt;
      &lt;li&gt;Unter Windows zeigt die Umgebungsvariable &lt;code&gt;TEMP&lt;/code&gt; auf diese Verzeichnis.
Doch zusätzlich gibt die API 
&lt;a href=&quot;http://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-gettemppathw&quot;&gt;&lt;code&gt;GetTempPath()&lt;/code&gt;&lt;/a&gt;
ebenso dieses zurück.&lt;/li&gt;
      &lt;li&gt;Linux benennt diese Variable &lt;code&gt;TMPDIR&lt;/code&gt; und die API 
&lt;a href=&quot;http://pubs.opengroup.org/onlinepubs/009696699/functions/tempnam.html&quot;&gt;&lt;code&gt;tempnam()&lt;/code&gt;&lt;/a&gt; 
kann benutzt werden um darin gleich eine neue Datei anzulegen.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Das Benutzer-Verzeichnis, auch &lt;code&gt;HOME&lt;/code&gt; Directory genannt
Viele Daten des Benutzers und der von ihm gestarteten Programme liegen
hier.
    &lt;ul&gt;
      &lt;li&gt;Unter Windows heißt die Variable &lt;code&gt;USERPROFILE&lt;/code&gt;, doch der Wert kann
auch von der Shell-API 
&lt;a href=&quot;http://docs.microsoft.com/en-us/windows/desktop/api/shlobj_core/nf-shlobj_core-shgetspecialfolderpathw&quot;&gt;&lt;code&gt;SHGetSpecialFolderPath()&lt;/code&gt;&lt;/a&gt; 
mit dem Wert &lt;code&gt;CSIDL_PROFILE&lt;/code&gt; ermittelt werden.&lt;/li&gt;
      &lt;li&gt;Linux bezeichnet sie einfach als &lt;code&gt;HOME&lt;/code&gt;, zusätzlich können Dateien
darin einfach adressiert werden, wenn der Pfad mit &lt;code&gt;~/&lt;/code&gt; beginnt.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Suchorte für nicht-absolute Pfade, auch als &lt;code&gt;PATH&lt;/code&gt; bekannt
Der PATH beinhaltet eine Liste von Verzeichnissen, in denen Dateien
gesucht werden, wenn man sie nicht absolut adressiert und sie nicht
im aktuellen Arbeitsverzeichnis liegen.
Windows und Linux nutzen hier ausnahmsweise mal den gleichen Bezeichner
&lt;code&gt;PATH&lt;/code&gt;, doch während die einzelnen Pfade unter Windows durch 
Strichpunkte &lt;code&gt;;&lt;/code&gt; getrennt sind, nutzt Linux Doppelpunkte &lt;code&gt;:&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Alle anderen mir bekannten Umgebungseinstellungen sind recht spezifisch an 
das jeweilige OS bzw. dessen Programme angepasst, von daher macht es wenig
Sinn noch mehrere zu nennen.&lt;/p&gt;

&lt;p&gt;Ein für meine Anwendungszwecke wichtiger Teil, fehlt allerdings:&lt;/p&gt;

&lt;h3 id=&quot;in-welches-verzeichnis-darf-mein-programm-einstellung-permanent-ablegen&quot;&gt;In welches Verzeichnis, darf mein Programm Einstellung permanent ablegen?&lt;/h3&gt;

&lt;p&gt;Windows kennt hier den Standard, dass im &lt;code&gt;USERPROFILE&lt;/code&gt; einige
Unterverzeichnisse existieren, in welchen Programme wiederum ihre
eigenen Unterverzeichnisse anlegen dürfen um dort Daten abzulegen.&lt;/p&gt;

&lt;p&gt;Damit ist vor allem das &lt;code&gt;\AppData\Local&lt;/code&gt; Verzeichnis gemeint, welches permanent
&lt;code&gt;SHGetSpecialFolderPath()&lt;/code&gt; mit &lt;code&gt;CSIDL_LOCAL_APPDATA&lt;/code&gt; zurückgeliefert wird.&lt;/p&gt;

&lt;p&gt;Unter Linux kenne ich keine formale API, doch dafür den de-facto Standard
alles im HOME-Unterverzeichnis &lt;code&gt;~/.config&lt;/code&gt; abzulegen. Programme erstellen
dort eindeutige Dateien oder Unterverzeichnisse für den Eigenbedarf.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/X_Window_System&quot;&gt;X11&lt;/a&gt; bzw. 
&lt;a href=&quot;http://www.freedesktop.org/wiki/Software/xdg-user-dirs/&quot;&gt;freedesktop.org&lt;/a&gt; 
erweitert dieses Konzept um weitere “sichtbare” Verzeichnisse für
&lt;a href=&quot;http://wiki.archlinux.org/index.php/XDG_user_directories&quot;&gt;Dokumente, Musik, Videos und die Desktopablage&lt;/a&gt;, 
so wie wir es von &lt;code&gt;SHGetSpecialFolderPath()&lt;/code&gt; unter Windows bereits kennen.&lt;br /&gt;
Über die Konfigurationsdatei &lt;code&gt;~/.config/user-dirs.dirs&lt;/code&gt; kann man diese 
Standardwerte abändern.&lt;br /&gt;
Und am Ende landen die Verzeichnisse als Variablen im Environment.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Pipes: Rohrpost zwischen Prozessen</title>
   <link href="https://www.opengate.at/blog/2019/02/pipes/"/>
   <published>2019-02-21T09:17:00+01:00</published>
   <updated>2019-02-21T09:17:00+01:00</updated>
   <id>https://www.opengate.at/blog/2019/02/pipes</id>
   <category term="devel" />
   <summary type="text">Hätte man “Pipes” 
in der Programmierung als “Pipeline” bezeichnet, würden vielleicht mehrere 
Entwickler den Namen kennen und die Technik einsetzen.

Linux bzw. Unix -
Fans wissen mit dem Begriff gut umzugehen, doch auf Seiten
der Windows 
Gemeinde fehlt dieses Wissen leider nur all zu oft.

Dabei sind Pipes eine schöne klassische Form Daten zwischen Eltern- und
Kindprozessen auszutauschen.
</summary>
   <content type="html">&lt;p&gt;Hätte man &lt;a href=&quot;https://de.wikipedia.org/wiki/Pipe_(Informatik)&quot;&gt;“Pipes”&lt;/a&gt; 
in der Programmierung als “Pipeline” bezeichnet, würden vielleicht mehrere 
Entwickler den Namen kennen und die Technik einsetzen.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/Linux&quot;&gt;Linux&lt;/a&gt; bzw. &lt;a href=&quot;https://de.wikipedia.org/wiki/Unix&quot;&gt;Unix&lt;/a&gt; -
Fans wissen mit dem Begriff gut umzugehen, doch auf Seiten
der &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows&quot;&gt;Windows&lt;/a&gt; 
Gemeinde fehlt dieses Wissen leider nur all zu oft.&lt;/p&gt;

&lt;p&gt;Dabei sind Pipes eine schöne klassische Form Daten zwischen Eltern- und
Kindprozessen auszutauschen.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Pipes sind virtuelle Datenschläuche. Was man auf den einen (Schreib-)Seite
hineinfallen lässt, kommt auf der anderen (Lese-)Seite wieder heraus.
Wird eine Pipe erzeugt, erhalten wir in der Regel zwei Handles bzw.
Filedescriptoren, nämlich ein Element zum Hineinschreiben und eines
zum Herauslesen.&lt;/p&gt;

&lt;p&gt;Wenn man von einem kleinen Puffer mal absieht, blockiert ein Schreibvorgang
so lange, bis die Leseseite die Daten gelesen hat. Umgekehrt blockiert ein
Lesevorgang so lange, bis mindestens ein Byte auf der anderen Seite 
geschrieben wurde.&lt;/p&gt;

&lt;h3 id=&quot;anonymous-vs-named-pipes&quot;&gt;Anonymous vs. Named Pipes&lt;/h3&gt;

&lt;p&gt;Zu den ältesten und bekanntesten anonymen Pipe-Formen zählen
&lt;a href=&quot;https://de.wikipedia.org/wiki/Standard-Datenstr%C3%B6me&quot;&gt;STDIN, STDOUT und STDERR&lt;/a&gt;, 
also die Standard-Ein- und -Ausgabe eines Prozesses. Sie werden bei der 
Erzeugung eines Prozesses vom Elternprozess entweder explizit vorgegeben 
oder von diesem einfach geerbt.&lt;/p&gt;

&lt;p&gt;Viele Pipes sind anonym, also namenlos. Bei ihrer Erzeugung entstehen die
beiden erwähnten Lese- und Schreib-Handles/Descriptoren, und die Pipe
existiert so lange, wie die Handles darauf offen sind.&lt;br /&gt;
Ein Prozess kann ein solches Handle zwar klonen, aber von außen kommt man
nicht (bzw. nur sehr schwer) an sie heran.&lt;/p&gt;

&lt;p&gt;Benannte Pipes (Named Pipes) erhalten einen eindeutigen Namen und können
explizit von jedem Prozess geöffnet werden, der die nötigen Rechte hat.
Damit lässt sich quasi eine kleine lokale Server-Client-Architektur
aufsetzen um die Pipe wie einen Server oder Client zu nutzen.&lt;/p&gt;

&lt;h3 id=&quot;windows&quot;&gt;Windows&lt;/h3&gt;

&lt;p&gt;Windows stellt mit den beiden APIs 
&lt;a href=&quot;http://msdn.microsoft.com/en-us/library/windows/desktop/aa365152(v=vs.85).aspx&quot;&gt;&lt;code&gt;CreatePipe()&lt;/code&gt;&lt;/a&gt; 
und &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/windows/desktop/aa365146(v=vs.85).aspx&quot;&gt;&lt;code&gt;CreateNamedPipe()&lt;/code&gt;&lt;/a&gt; 
alles bereit, was man für die Erzeugung beider Formen benötigt. 
Zum Öffnen einer bestehenden Named-Pipe dient 
&lt;a href=&quot;http://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-createfilew&quot;&gt;&lt;code&gt;CreateFile()&lt;/code&gt;&lt;/a&gt; 
und gelesen bzw. geschrieben wird die Pipe ganz klassisch mit 
&lt;a href=&quot;http://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-readfile&quot;&gt;&lt;code&gt;ReadFile()&lt;/code&gt;&lt;/a&gt; und 
&lt;a href=&quot;http://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-writefile&quot;&gt;&lt;code&gt;WriteFile()&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;CreatePipe()&lt;/code&gt; hat leider den Nachteil, dass man damit keine asynchronen 
IO-Funktionen (Stichwort: &lt;a href=&quot;https://en.wikipedia.org/wiki/Overlapped_I/O&quot;&gt;Overlapped&lt;/a&gt;) 
damit nutzen kann.&lt;br /&gt;
Die GATE Implementierung nutzt daher den Umweg, dass eine Named-Pipe mit
einem zufälligen Namen erzeugt wird, denn hier kann man Overlapped-IO
einsetzen.&lt;/p&gt;

&lt;h3 id=&quot;windows-ce&quot;&gt;Windows CE&lt;/h3&gt;

&lt;p&gt;Windows CE kennt - so weit ich weiß und zu meiner Verwunderung - keine Pipes 
außer Konsolen (STDIN, STDOUT) auf einigen Plattformen (aber nicht auf allen).&lt;/p&gt;

&lt;p&gt;Es gibt eine Ersatztechnologie mit dem Namen 
&lt;a href=&quot;http://docs.microsoft.com/en-us/previous-versions/ms834460(v=msdn.10)&quot;&gt;“Message-Queues”&lt;/a&gt;.
Diese können ähnlich wie Pipes genutzt werden, haben aber andere APIs und
sind auch keine echten Pipes.&lt;/p&gt;

&lt;p&gt;In der früheren GATE-Implementierung hatte ich dieses Verfahren mal 
ausprobiert, aber nie einen praktischen Nutzen daraus gezogen. Falls ich 
mal wieder dazu kommen sollte, gibt es sich einen Beitrag dazu.&lt;/p&gt;

&lt;h3 id=&quot;posix-bsd-linux&quot;&gt;POSIX, BSD, Linux&lt;/h3&gt;

&lt;p&gt;Hier wurden Pipes geboren, denn unter Unix Systemen ist es Gang und Gäbe,
dass Programme Pipes erzeugen, sie an ihre Kindprozesse weitervererben und 
so mit ihrem “Nachwuchs” kommunizieren.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://pubs.opengroup.org/onlinepubs/009696899/functions/pipe.html&quot;&gt;&lt;code&gt;pipe()&lt;/code&gt;&lt;/a&gt;
erzeugt ein Filedescriptor-Paar zum anonymen Lesen und Schreiben, 
und die üblichen Verdächtigen 
&lt;a href=&quot;http://pubs.opengroup.org/onlinepubs/009695399/functions/read.html&quot;&gt;&lt;code&gt;read()&lt;/code&gt;&lt;/a&gt;
und &lt;a href=&quot;http://pubs.opengroup.org/onlinepubs/009695399/functions/write.html&quot;&gt;&lt;code&gt;write()&lt;/code&gt;&lt;/a&gt;
sorgen für den Zu- bzw. Abfluss von Bytes.&lt;/p&gt;

&lt;p&gt;Benannte Pipes werden als “besondere” Dateien im Dateisystem abgelegt. Obwohl 
es keine zwingende Vorgabe gibt, wo das sein soll, empfiehlt sich ein 
standardisierter Ort, wie &lt;code&gt;/var&lt;/code&gt; oder &lt;code&gt;/tmp&lt;/code&gt;)&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://pubs.opengroup.org/onlinepubs/009604599/functions/mkfifo.html&quot;&gt;&lt;code&gt;mkfifo()&lt;/code&gt;&lt;/a&gt;
erzeugt diese spezielle FIFO-Pipe-Datei, die mit
&lt;a href=&quot;http://pubs.opengroup.org/onlinepubs/007904975/functions/open.html&quot;&gt;&lt;code&gt;open()&lt;/code&gt;&lt;/a&gt;
entweder zum Lesen oder zum Schreiben separat geöffnet werden kann.&lt;/p&gt;

&lt;p&gt;Im Gegensatz zu Windows bleibt eine solche FIFO-Datei auch erhalten, wenn 
ihr Erstellerprozess und alle anderen Nutzer beendet wurden.
Man kann bzw muss sie dann per 
&lt;a href=&quot;http://pubs.opengroup.org/onlinepubs/009695399/functions/unlink.html&quot;&gt;&lt;code&gt;unlink()&lt;/code&gt;&lt;/a&gt;
manuell löschen.&lt;/p&gt;

&lt;p&gt;Dank der Tatsache, dass alle Deskriptoren per 
&lt;a href=&quot;http://pubs.opengroup.org/onlinepubs/007908799/xsh/select.html&quot;&gt;&lt;code&gt;select()&lt;/code&gt;&lt;/a&gt;
ansteuerbar sind, lassen sich alle Pipes problemlos mit asynchroner Kommunikation
einsetzen.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Nutzt mehr PIPES, liebe Leute.&lt;br /&gt;
Wie oft musste ich schon erleben, dass zum Austausch von 5 Einstellungs-Strings
eine Datenbank zwischen Prozessen einprogrammiert wurde, anstatt diese
Infos einfach per Rohrpost zum Nachbarn zu schicken.&lt;/p&gt;

&lt;p&gt;Man braucht keine separaten Server für solche Aufgaben, die Megabytes an RAM
fressen und sau-langsam sind.&lt;br /&gt;
Pipes schaffen das mit wenigen Kilobytes mit annähernd Lichtgeschwindigkeit!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Windows Management Instrumentation (WMI)</title>
   <link href="https://www.opengate.at/blog/2019/02/wmi/"/>
   <published>2019-02-20T22:01:00+01:00</published>
   <updated>2019-02-20T22:01:00+01:00</updated>
   <id>https://www.opengate.at/blog/2019/02/wmi</id>
   <category term="devel" />
   <summary type="text">WBEM, oder auch 
Web-Based Enterprise Management
ist ein Ansatz um Administration und Fernwartung in großen Netzwerken 
(Unternehmen) zu standardisieren.

Microsoft preschte schon vor den 2000ern mit seiner eigenen 
COM-Implementierung 
davon vor, nannte es WMI und deshalb haben wir heute zu vielen 
Systemkonfigurationen primär nur über die WMI-Schnittstellen Zugang.
</summary>
   <content type="html">&lt;p&gt;&lt;code&gt;WBEM&lt;/code&gt;, oder auch 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Web_Based_Enterprise_Management&quot;&gt;Web-Based Enterprise Management&lt;/a&gt;
ist ein Ansatz um Administration und Fernwartung in großen Netzwerken 
(Unternehmen) zu standardisieren.&lt;/p&gt;

&lt;p&gt;Microsoft preschte schon vor den 2000ern mit seiner eigenen 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Component_Object_Model&quot;&gt;COM&lt;/a&gt;-Implementierung 
davon vor, nannte es WMI und deshalb haben wir heute zu vielen 
Systemkonfigurationen primär nur über die WMI-Schnittstellen Zugang.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Die meisten kennen WMI vom Windows Scripting Host und nehmen es als
“seltsam” wahr.&lt;br /&gt;
Einerseits ist die Menge an Funktionen und Möglichkeiten erschlagend groß,
andererseits läuft vieles über eine SQL-ähnliche Abfragesprache.&lt;/p&gt;

&lt;div class=&quot;language-vb highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;Computer = &amp;quot;.&amp;quot;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;Set objService = GetObject(&amp;quot;WinMgmts:{impersonationLevel=impersonate,(Shutdown)}!\\&amp;quot; &amp;amp; Computer &amp;amp; &amp;quot;\root\cimv2&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;Set objSystems = objService.ExecQuery(&amp;quot;SELECT * FROM Win32_OperatingSystem&amp;quot;)
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;For Each objSystem in objSystems
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;  objSystem.Shutdown()
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;Next
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Das Beispiel zeigt, wie man einen PC herunter fährt.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Man verbindet sich zum WMI-Dienst 
(mit ein paar Angaben, dass z.B. das Shutdown-Privileg gebracht wird)&lt;/li&gt;
  &lt;li&gt;Man empfängt die Liste aller “laufenden” Betriebssystem aus der Klasse 
&lt;code&gt;Win32_OperatingSystems&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;würde mich sehr wundern, wenn da jemals mehr als eine Instanz zurück käme&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Auf allen Instanzen wird die “Shutdown()” Methode ausgeführt.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Theoretisch kann man über die String-Variable &lt;code&gt;Computer&lt;/code&gt; auch den DNS oder 
&lt;code&gt;NETBIOS&lt;/code&gt; Namen eines anderen Systems angeben, oder mit &lt;code&gt;.&lt;/code&gt; auf das lokale 
System verweisen. Das war unter Windows XP noch Gang und Gäbe, doch heute 
lassen Firewall und DCOM-Einstellungen das nicht mehr so ohne weiteres zu und 
man ist auf das lokale System beschränkt.&lt;/p&gt;

&lt;p&gt;WMI hat primär eine COM-Schnittstelle die (wie wir im Beispiel sahen), auch 
Script-fähig ist, also mit dem IDispatch Interface arbeitet.&lt;br /&gt;
Doch seit Einführung von dotNet und etwas später der Powershell, sind die 
alten VBScripts kaum mehr anzutreffen (obwohl sie noch brav funktionieren).&lt;/p&gt;

&lt;p&gt;Außerdem stellt WMI in bestimmten Situationen Zugänge bereit, für die es keine
anderen APIs gibt.&lt;br /&gt;
Das IP-Adressen Setup ist so ein Bereich, wo über die Instanzen der WMI-Klasse
&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/desktop/cimwin32prov/win32-networkadapterconfiguration&quot;&gt;&lt;code&gt;Win32_NetworkAdapterConfiguration&lt;/code&gt;&lt;/a&gt;
über die Methoden &lt;code&gt;EnableStatic&lt;/code&gt;, &lt;code&gt;SetGateways&lt;/code&gt;, &lt;code&gt;EnableDNS&lt;/code&gt;, &lt;code&gt;EnableDHCP&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Doch was für mich gerade hoch spannend ist, ist die Tatsache, dass der 
Hyper-V Service ebenfalls primär über WMI ansteuerbar ist.
Und da Microsoft ja auch den kostenlosen “Nur-Hyper-V” Server zum Download
anbietet, interessiere ich mich sehr für dessen Verwaltung um ein paar
kleine Tools dafür zu schreiben.&lt;/p&gt;

&lt;p&gt;Doch es gibt noch weitere Gebiete, die nur eine WMI Schnittstelle bieten:&lt;br /&gt;
z.B. Die Ansteuerung des Unified Write Filters unter Windows 10 IoT 
Enterprise. Während der alte Enhanced und File-based Write Filter in Windows 7
Embedded noch seine eigene C-API mitbrachte, ist aber Windows 10 WMI
neben der Kommandozeile die einzige Möglichkeit, dieses Feature zu verwalten.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;WMI ist bietet zu extrem vielen Bereichen Zugänge, die nicht im entferntesten
alle auf einer Blog-Seite erwähnt werden können.
Sogar Dateisuchen lassen sich über WQL - die WMI Query Language abbilden.&lt;/p&gt;

&lt;p&gt;Folglich kommt System-Tool Programmierer an dieser essentiellen Technologie
unter Windows vorbei.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Durch den Callstack wandern</title>
   <link href="https://www.opengate.at/blog/2019/02/callstack/"/>
   <published>2019-02-19T17:35:00+01:00</published>
   <updated>2019-02-19T17:35:00+01:00</updated>
   <id>https://www.opengate.at/blog/2019/02/callstack</id>
   <category term="devel" />
   <summary type="text">Verwaltete Sprachen wie 
Java oder jene des 
dotNet Frameworks definieren
einen Standard wie Funktionen ausgestalten sein müssen.
Damit kann das Framework seine eigenen Funktions-Aufrufbäume genau 
zurückverfolgen.

Das merkt man vor allem bei 
Exception, die ganz genau 
wissen woher sie kamen.

C und C++ kennen einen solchen 
Standard für den Aufbau des Callstacks
nicht, weil im Zuge der Optimierung Funktionen eingebettet (Inlining)
werden können oder andere interne Calling-Conventions benutzt werden dürfen.

Will man aber dennoch “seine Herkunft” zur Laufzeit ermitteln muss man selbst
Hand anlegen.
</summary>
   <content type="html">&lt;p&gt;Verwaltete Sprachen wie 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Java_(Programmiersprache)&quot;&gt;Java&lt;/a&gt; oder jene des 
&lt;a href=&quot;https://de.wikipedia.org/wiki/.NET_Framework&quot;&gt;dotNet&lt;/a&gt; Frameworks definieren
einen Standard wie Funktionen ausgestalten sein müssen.&lt;br /&gt;
Damit kann das Framework seine eigenen Funktions-Aufrufbäume genau 
zurückverfolgen.&lt;/p&gt;

&lt;p&gt;Das merkt man vor allem bei 
&lt;a href=&quot;https://de.wikipedia.org/wiki/Ausnahmebehandlung&quot;&gt;Exception&lt;/a&gt;, die ganz genau 
wissen woher sie kamen.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://de.wikipedia.org/wiki/C%2B%2B&quot;&gt;C und C++&lt;/a&gt; kennen einen solchen 
Standard für den Aufbau des &lt;a href=&quot;https://de.wikipedia.org/wiki/Aufrufstapel&quot;&gt;Callstacks&lt;/a&gt;
nicht, weil im Zuge der Optimierung Funktionen eingebettet (Inlining)
werden können oder andere interne Calling-Conventions benutzt werden dürfen.&lt;/p&gt;

&lt;p&gt;Will man aber dennoch “seine Herkunft” zur Laufzeit ermitteln muss man selbst
Hand anlegen.
&lt;!--more--&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Es kann schon mal sinnvoll sein, wenn ein Exception-Konstruktor auch gleich 
den Callstack wegspeichert und in Debugging-Logs mitführt.
Mit diesem Datensatz kann man in einigen Fällen Probleme feststellen, ohne
dass gleich ein Remote-Debugger benutzt werden muss.&lt;/p&gt;

&lt;p&gt;Und es ist auch ein Vorteil, dass Signal-Handler oder 
Structured-Exception-Handler den aktuellen Callstack ausgeben oder 
zwischenspeichern, bevor der Prozess beendet werden muss.&lt;/p&gt;

&lt;h3 id=&quot;linux&quot;&gt;Linux&lt;/h3&gt;

&lt;p&gt;Die Funktion &lt;a href=&quot;http://man7.org/linux/man-pages/man3/backtrace.3.html&quot;&gt;&lt;code&gt;backtrace()&lt;/code&gt;&lt;/a&gt;
ist hier der beste Anlaufplatz, denn sie bildet den Callstack selbst ab.&lt;br /&gt;
Die zurückgegebenen Pointer zeigen auf die Funktionseinsprungpunkte und
mit der Funktion &lt;code&gt;backtrace_symbols()&lt;/code&gt; können die Namen der einzelnen 
Funktionen im Callstack bestimmt werden, falls sie einkompiliert 
wurden. (Sie sind meist nur im Debug-Modus drinnen.)&lt;/p&gt;

&lt;p&gt;Ich würde &lt;code&gt;backtrace()&lt;/code&gt; schon fast als “prefekte” API ansehen, weil keine
Details über CPU-Register oder zusätzlicher Assemblercodes erforderlich
sind.&lt;/p&gt;

&lt;h3 id=&quot;windows-nt&quot;&gt;Windows NT&lt;/h3&gt;

&lt;p&gt;In der 64-bit Variante von &lt;code&gt;Kernel32.dll&lt;/code&gt; befindet sich die Funktion 
&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/desktop/api/winnt/nf-winnt-rtlcapturecontext&quot;&gt;&lt;code&gt;RtlCaptureContext()&lt;/code&gt;&lt;/a&gt;,
die uns alle Register vor Ihrem Aufruf zur Verfügung stellt. Für 32-bit 
Prozesse darf man noch den guten alten Inline-Assembler nutzen
und diese Daten selbst beziehen.&lt;/p&gt;

&lt;div class=&quot;language-asm highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;size_t * ptrFrame = 0;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;size_t ptrStack = 0;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;_asm { mov ptrFrame, ebp }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;_asm { mov ptrStack, esp }
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;ctx.Ebp = (DWORD)reinterpret_cast&amp;lt;size_t&amp;gt;(ptrFrame);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;ctx.Esp = (DWORD)ptrStack;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;ctx.Eip = (DWORD)*(ptrFrame + 1);
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Wer gerne mit dem MinGW GCC (32-bit) arbeitet, sollte mit folgenden Zeilen 
auskommen:&lt;/p&gt;
&lt;div class=&quot;language-asm highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n1&quot; name=&quot;n1&quot;&gt;1&lt;/a&gt;&lt;/span&gt;size_t * ptrFrame = 0;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n2&quot; name=&quot;n2&quot;&gt;2&lt;/a&gt;&lt;/span&gt;size_t ptrStack = 0;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n3&quot; name=&quot;n3&quot;&gt;3&lt;/a&gt;&lt;/span&gt;asm ( &amp;quot;movl %%ebp, %0;&amp;quot; : &amp;quot;=r&amp;quot; ( ptrFrame ) );
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n4&quot; name=&quot;n4&quot;&gt;4&lt;/a&gt;&lt;/span&gt;asm ( &amp;quot;movl %%esp, %0;&amp;quot; : &amp;quot;=r&amp;quot; ( ptrStack ) );
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n5&quot; name=&quot;n5&quot;&gt;5&lt;/a&gt;&lt;/span&gt;ctx.Ebp = (DWORD)reinterpret_cast&amp;lt;size_t&amp;gt;(ptrFrame);
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n6&quot; name=&quot;n6&quot;&gt;6&lt;/a&gt;&lt;/span&gt;ctx.Esp = (DWORD)ptrStack;
&lt;span class=&quot;line-numbers&quot;&gt;&lt;a href=&quot;#n7&quot; name=&quot;n7&quot;&gt;7&lt;/a&gt;&lt;/span&gt;ctx.Eip = (DWORD)*(ptrFrame + 1);
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Für das Durchwandern des Callstacks braucht man im allgemeinen Fall 
zwingend &lt;code&gt;Dbghelp.dll&lt;/code&gt;, denn in ihr ist die Funktion 
&lt;a href=&quot;http://docs.microsoft.com/en-us/windows/desktop/api/dbghelp/nf-dbghelp-stackwalk&quot;&gt;&lt;code&gt;StackWalk64()&lt;/code&gt;&lt;/a&gt;
verborgen, die bei einem Stackframe beginnt und sich weiter zurück arbeiten kann.&lt;/p&gt;

&lt;p&gt;Ab &lt;a href=&quot;https://de.wikipedia.org/wiki/Microsoft_Windows_Vista&quot;&gt;Windows Vista&lt;/a&gt;
zieht die Funktion 
&lt;a href=&quot;http://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/ntifs/nf-ntifs-rtlcapturestackbacktrace&quot;&gt;&lt;code&gt;RtlCaptureStackBackTrace()&lt;/code&gt;&lt;/a&gt;
übergreifend in &lt;code&gt;kernel32.dll&lt;/code&gt; ein, und ist ähnlich komfortabel wie 
&lt;code&gt;backtrace()&lt;/code&gt; in der Linux-Welt.&lt;/p&gt;

&lt;h3 id=&quot;windows-ce&quot;&gt;Windows CE&lt;/h3&gt;

&lt;p&gt;CE hat wieder einen anderen API-Namen gewählt und nutzt
&lt;a href=&quot;https://docs.microsoft.com/en-us/previous-versions/windows/embedded/ms885641%28v%3dmsdn.10%29&quot;&gt;&lt;code&gt;GetThreadCallStack()&lt;/code&gt;&lt;/a&gt;
um analog zu &lt;code&gt;backtrace()&lt;/code&gt; alle Funktionsadressen im Callstack aufzulisten.&lt;/p&gt;

&lt;h3 id=&quot;fazit&quot;&gt;Fazit&lt;/h3&gt;

&lt;p&gt;Die Möglichkeit den Callstack zur Laufzeit zu speichern sollte stets bedacht
und im Framework implementiert sein. Auch wenn in der Praxis C++ Callstacks
nur für Experten aussagekräftig sind, so sind sie immer wieder ein gutes
Hilfsmittel beim Debuggen.&lt;/p&gt;

&lt;p&gt;Selbstverständlich setzt das ein konsequentes Archivieren der Programmsymbole
voraus, denn mit Adressen lässt sich wenig anfangen, wenn man nicht weiß,
welche namentlich bekannte Funktion damit in Verbindung steht.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Eiscreme ohne Zucker</title>
   <lin