<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
>
	<channel>
		<title>Chaotic Experiments</title>
		<description>The semi-interesting bits brought to you from entropy.</description>
		<sy:updatePeriod>daily</sy:updatePeriod>
		<sy:updateFrequency>1</sy:updateFrequency>
		<link>https://chaoticlab.io/</link>
		<atom:link href="https://chaoticlab.io/feed-all.xml" rel="self" type="application/rss+xml" />
		<lastBuildDate>Fri, 29 Mar 2024 00:00:00 +0200</lastBuildDate>
		<xhtml:meta xmlns:xhtml="http://www.w3.org/1999/xhtml" name="robots" content="noindex" />
		
		
			<item>
				<title>Update: MSI Installer for GNU Emacs 29.3 for Windows</title>
				
				
					<description>&lt;p&gt;
Following the GNU Emacs 29.3 release, &lt;a href=&quot;/emacs/wix/update/2019/01/05/emacs_installer.html&quot;&gt;my MSI installer&lt;/a&gt; for GNU Emacs has been updated!
&lt;/p&gt;

&lt;p&gt;
This time there is no 32-bit version of it as no 32-bit executables were provided by the maintainers.
&lt;/p&gt;

&lt;p&gt;
Although this release of Emacs contains a Windows installer, I decided to release my installer as well, because MSI installers might be more convenient in some cases.
&lt;/p&gt;

&lt;p&gt;
You can find all the &lt;a href=&quot;https://github.com/arbv/emacs-msi-installer&quot;&gt;sources&lt;/a&gt; on GitHub as well as the &lt;a href=&quot;https://github.com/arbv/emacs-msi-installer/releases&quot;&gt;pre-built installers&lt;/a&gt; for the latest release of GNU Emacs. The provided installers bundle official, unmodified GNU Emacs binaries for Windows.
&lt;/p&gt;

&lt;p&gt;
If you used an older version of the installer you should be able to perform an in-place upgrade.
&lt;/p&gt;

&lt;p&gt;
&lt;i&gt;I have also uploaded installers for 29.2 because I have completely missed that release.&lt;/i&gt;
&lt;/p&gt;

&lt;p&gt;
Enjoy!
&lt;/p&gt;

&lt;p&gt;
&lt;i&gt;I decided to reuse screenshots from a previous release because the installer&apos;s code was not modified since then, so the screenshots will look the same (except the version number, obviously).&lt;/i&gt;
&lt;/p&gt;

&lt;div class=&quot;org-center&quot;&gt;

&lt;div id=&quot;orge676912&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/01.png&quot; alt=&quot;01.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org092cc3e&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/02.png&quot; alt=&quot;02.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org03a5b25&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/03.png&quot; alt=&quot;03.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;orgc583c97&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/04.png&quot; alt=&quot;04.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org0d6fdd4&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/05.png&quot; alt=&quot;05.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org1d51fac&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/06.png&quot; alt=&quot;06.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
				
				<pubDate>Fri, 29 Mar 2024 00:00:00 +0200</pubDate>
				<link>https://chaoticlab.io/posts/emacs-29-3-msi/</link>
				<guid isPermaLink="true">https://chaoticlab.io/posts/emacs-29-3-msi/</guid>
			</item>
		
			<item>
				<title>Update: MSI Installer for GNU Emacs 29.1 for Windows</title>
				
				
					<description>&lt;p&gt;
Following the GNU Emacs 29.1 release, &lt;a href=&quot;/emacs/wix/update/2019/01/05/emacs_installer.html&quot;&gt;my MSI installer&lt;/a&gt; for GNU Emacs has been updated!
&lt;/p&gt;

&lt;p&gt;
This time there is no 32-bit version of it as no 32-bit executables were provided by the maintainers.
&lt;/p&gt;

&lt;p&gt;
Although this release of Emacs contains a Windows installer, I decided to release my installer as well, because MSI installers might be more convenient in some cases.
&lt;/p&gt;

&lt;p&gt;
You can find all the &lt;a href=&quot;https://github.com/arbv/emacs-msi-installer&quot;&gt;sources&lt;/a&gt; on GitHub as well as the &lt;a href=&quot;https://github.com/arbv/emacs-msi-installer/releases&quot;&gt;pre-built installers&lt;/a&gt; for the latest release of GNU Emacs. The provided installers bundle official, unmodified GNU Emacs binaries for Windows.
&lt;/p&gt;

&lt;p&gt;
If you used an older version of the installer you should be able to perform an in-place upgrade.
&lt;/p&gt;

&lt;p&gt;
Enjoy!
&lt;/p&gt;

&lt;p&gt;
&lt;i&gt;I decided to reuse screenshots from a previous release because the installer&apos;s code was not modified since then, so the screenshots will look the same (except the version number, obviously).&lt;/i&gt;
&lt;/p&gt;

&lt;div class=&quot;org-center&quot;&gt;

&lt;div id=&quot;org3692d80&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/01.png&quot; alt=&quot;01.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org2e1b95e&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/02.png&quot; alt=&quot;02.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;orge7fe294&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/03.png&quot; alt=&quot;03.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org78a17df&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/04.png&quot; alt=&quot;04.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org399e595&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/05.png&quot; alt=&quot;05.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org5bdcf57&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/06.png&quot; alt=&quot;06.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
				
				<pubDate>Tue, 01 Aug 2023 00:00:00 +0300</pubDate>
				<link>https://chaoticlab.io/posts/emacs-29-1-msi/</link>
				<guid isPermaLink="true">https://chaoticlab.io/posts/emacs-29-1-msi/</guid>
			</item>
		
			<item>
				<title>Update: MSI Installer for GNU Emacs 28.2 for Windows</title>
				
				
					<description>&lt;p&gt;
Following the GNU Emacs 28.2 release, &lt;a href=&quot;/emacs/wix/update/2019/01/05/emacs_installer.html&quot;&gt;my MSI installer&lt;/a&gt; for GNU Emacs has been updated!
&lt;/p&gt;

&lt;p&gt;
As usual, it is a belated update.
&lt;/p&gt;

&lt;p&gt;
This time there is no 32-bit version of it as no 32-bit executables were provided by the maintainers.
&lt;/p&gt;

&lt;p&gt;
Although this release of Emacs contains a Windows installer, I decided to release my installer as well, because MSI installers might be more convenient in some cases.
&lt;/p&gt;

&lt;p&gt;
You can find all the &lt;a href=&quot;https://github.com/arbv/emacs-msi-installer&quot;&gt;sources&lt;/a&gt; on GitHub as well as the &lt;a href=&quot;https://github.com/arbv/emacs-msi-installer/releases&quot;&gt;pre-built installers&lt;/a&gt; for the latest release of GNU Emacs. The provided installers bundle official, unmodified GNU Emacs binaries for Windows.
&lt;/p&gt;

&lt;p&gt;
If you used an older version of the installer you should be able to perform an in-place upgrade.
&lt;/p&gt;

&lt;p&gt;
Enjoy!
&lt;/p&gt;

&lt;p&gt;
&lt;i&gt;I decided to reuse screenshots from a previous release because the installer&apos;s code was not modified since then, so the screenshots will look the same (except the version number, obviously).&lt;/i&gt;
&lt;/p&gt;

&lt;div class=&quot;org-center&quot;&gt;

&lt;div id=&quot;orgc125c31&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/01.png&quot; alt=&quot;01.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org9d624a2&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/02.png&quot; alt=&quot;02.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org2463e33&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/03.png&quot; alt=&quot;03.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org85871f2&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/04.png&quot; alt=&quot;04.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org7550c9c&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/05.png&quot; alt=&quot;05.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org0b6f0c3&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/06.png&quot; alt=&quot;06.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
				
				<pubDate>Mon, 26 Sep 2022 00:00:00 +0300</pubDate>
				<link>https://chaoticlab.io/posts/emacs-28-2-msi/</link>
				<guid isPermaLink="true">https://chaoticlab.io/posts/emacs-28-2-msi/</guid>
			</item>
		
			<item>
				<title>Update: MSI Installer for GNU Emacs 28.1 for Windows</title>
				
				
					<description>&lt;p&gt;
Following the GNU Emacs 28.1 release, &lt;a href=&quot;/emacs/wix/update/2019/01/05/emacs_installer.html&quot;&gt;my MSI installer&lt;/a&gt; for GNU Emacs has been updated!
&lt;/p&gt;

&lt;p&gt;
As usual, it is a belated update.
&lt;/p&gt;

&lt;p&gt;
This time there is no 32-bit version of it as no 32-bit executables were provided by the maintainers.
&lt;/p&gt;

&lt;p&gt;
Although this release of Emacs contains a Windows installer, I decided to release my installer as well, because MSI installers might be more convenient in some cases.
&lt;/p&gt;

&lt;p&gt;
You can find all the &lt;a href=&quot;https://github.com/arbv/emacs-msi-installer&quot;&gt;sources&lt;/a&gt; on GitHub as well as the &lt;a href=&quot;https://github.com/arbv/emacs-msi-installer/releases&quot;&gt;pre-built installers&lt;/a&gt; for the latest release of GNU Emacs. The provided installers bundle official, unmodified GNU Emacs binaries for Windows.
&lt;/p&gt;

&lt;p&gt;
If you used an older version of the installer you should be able to perform an in-place upgrade.
&lt;/p&gt;

&lt;p&gt;
Enjoy!
&lt;/p&gt;

&lt;p&gt;
&lt;i&gt;I decided to reuse screenshots from a previous release because the installer&apos;s code was not modified since then, so the screenshots will look the same (except the version number, obviously).&lt;/i&gt;
&lt;/p&gt;

&lt;div class=&quot;org-center&quot;&gt;

&lt;div id=&quot;orgc440404&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/01.png&quot; alt=&quot;01.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;orgaca397d&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/02.png&quot; alt=&quot;02.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org5950f70&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/03.png&quot; alt=&quot;03.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org0ebba41&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/04.png&quot; alt=&quot;04.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;orgd13ff2b&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/05.png&quot; alt=&quot;05.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org1592bb0&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/06.png&quot; alt=&quot;06.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
				
				<pubDate>Wed, 04 May 2022 00:00:00 +0300</pubDate>
				<link>https://chaoticlab.io/posts/emacs-28-1-msi/</link>
				<guid isPermaLink="true">https://chaoticlab.io/posts/emacs-28-1-msi/</guid>
			</item>
		
			<item>
				<title>Update: MSI Installer for GNU Emacs 27.2 for Windows</title>
				
				
					<description>&lt;p&gt;
Following the GNU Emacs 27.2 release, &lt;a href=&quot;/emacs/wix/update/2019/01/05/emacs_installer.html&quot;&gt;my MSI installer&lt;/a&gt; for GNU Emacs has been updated!
&lt;/p&gt;

&lt;p&gt;
As usual, it is a belated update.
&lt;/p&gt;

&lt;p&gt;
Although this release of Emacs contains a Windows installer, I decided to release my installer as well, because MSI installers might be more convenient in some cases.
&lt;/p&gt;

&lt;p&gt;
You can find all the &lt;a href=&quot;https://github.com/arbv/emacs-msi-installer&quot;&gt;sources&lt;/a&gt; on GitHub as well as the &lt;a href=&quot;https://github.com/arbv/emacs-msi-installer/releases&quot;&gt;pre-built installers&lt;/a&gt; for the latest release of GNU Emacs. The provided installers bundle official, unmodified GNU Emacs binaries for Windows.
&lt;/p&gt;

&lt;p&gt;
If you used an older version of the installer you should be able to perform an in-place upgrade.
&lt;/p&gt;

&lt;p&gt;
Enjoy!
&lt;/p&gt;

&lt;p&gt;
&lt;i&gt;I decided to reuse screenshots from a previous release because the installer&apos;s code was not modified since then, so the screenshots will look the same (except the version number, obviously).&lt;/i&gt;
&lt;/p&gt;

&lt;div class=&quot;org-center&quot;&gt;

&lt;div id=&quot;org4ed9868&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/01.png&quot; alt=&quot;01.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;orga9d1d00&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/02.png&quot; alt=&quot;02.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;orgd9bf715&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/03.png&quot; alt=&quot;03.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;orga6003d2&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/04.png&quot; alt=&quot;04.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org6fa4054&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/05.png&quot; alt=&quot;05.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org344f491&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/06.png&quot; alt=&quot;06.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
				
				<pubDate>Tue, 13 Apr 2021 00:00:00 +0300</pubDate>
				<link>https://chaoticlab.io/posts/emacs-27-2-msi/</link>
				<guid isPermaLink="true">https://chaoticlab.io/posts/emacs-27-2-msi/</guid>
			</item>
		
			<item>
				<title>Installing Entware on an Android-powered device: Entware Installer Module for Magisk</title>
				
				
					<description>&lt;p&gt;
You may have an old unused Android-powered phone lying around, or you may have a set-top box which remains unused most of the time, so you want to make it to work also as a home WEB-server. Maybe you are geeky enough for an idea of carrying a Linux-powered server in your pocket. Or you would like to improve the functionality of your Android phone to include a package manager which simplifies installation of &lt;a href=&quot;http://bin.entware.net/armv7sf-k2.6/Packages.html&quot;&gt;a large number of server-side software and development tools&lt;/a&gt;. These are only the reasons for installing &lt;a href=&quot;https://entware.net/&quot;&gt;Entware&lt;/a&gt; on an Android-powered device I can imagine. Everyone can have his or her reasons for doing so.
&lt;/p&gt;

&lt;p&gt;
However, installing Entware on Android might be not straightforward. Initially, I planned to write a guide on how-to get Entware running on a device rooted using Magisk.
&lt;/p&gt;

&lt;p&gt;
To my shame, the guide turned out to be complicated and error-prone. To save you from the hassle, I decided to reuse my findings and code and developed a module for Magisk which you can &lt;a href=&quot;https://github.com/arbv/entware-installer-for-magisk&quot;&gt;find on Github&lt;/a&gt;. Installing Entware using this module is as straightforward as possible, but for now, it supports only devices on which the root file system is a RAM-drive (&lt;code&gt;rootfs&lt;/code&gt;). Unfortunately, this rules out most of the recent devices released with Android 9 and newer (so-called &quot;system-as-root&quot; devices). On these devices, the root file system is a real partition, so you need to manually modify  it before using the module because Magisk does not currently provide a facility to make reversible modifications to directories outside of &quot;/system.&quot;
&lt;/p&gt;

&lt;p&gt;
I do not want to repeat myself in this post because I wrote hopefully &lt;a href=&quot;https://github.com/arbv/entware-installer-for-magisk/blob/master/README.md&quot;&gt;complete documentation for the module&lt;/a&gt;. If you happen to have a newer device where the root file system is not a RAM-drive,
I &lt;a href=&quot;https://github.com/arbv/entware-installer-for-magisk/blob/master/README.md#compatibility&quot;&gt;mentioned&lt;/a&gt; there the modifications which you might want to make before the installation.
&lt;/p&gt;

&lt;p&gt;
Hopefully, I will get this module into the official Magisk modules repository at some point. Now you can install it manually, as &lt;a href=&quot;https://github.com/arbv/entware-installer-for-magisk/blob/master/README.md#installation&quot;&gt;described in the documentation&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;
Happy Entware installation!
&lt;/p&gt;
</description>
				
				<pubDate>Fri, 02 Oct 2020 00:00:00 +0300</pubDate>
				<link>https://chaoticlab.io/posts/entware-installer-for-magisk/</link>
				<guid isPermaLink="true">https://chaoticlab.io/posts/entware-installer-for-magisk/</guid>
			</item>
		
			<item>
				<title>Update to My &apos;daemonize&apos; Library</title>
				
				
					<description>&lt;p&gt;
I have updated &lt;a href=&quot;/c/c++/unix/2018/10/01/daemonize.html&quot;&gt;my tiny C library for writing Unix daemons&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;
In fact, the library&apos;s code itself remained intact.  When the original version was released, I made a somewhat sinful thing: although the library&apos;s code was written with portability in mind, the only example which came with it was Linux specific because of usage of &lt;a href=&quot;https://www.man7.org/linux/man-pages/man2/signalfd.2.html&quot;&gt;&lt;code&gt;signalfd(2)&lt;/code&gt;&lt;/a&gt; to redirect signal handling to the main event processing loop. This issue has been addressed recently: now, additionally to the original Linux specific example there is one which should be portable to the other Unix-like systems. It utilises the somewhat lesser-known &lt;a href=&quot;https://cr.yp.to/docs/selfpipe.html&quot;&gt;self-pipe trick&lt;/a&gt; to redirect signal processing to the loop &lt;sup&gt;&lt;a id=&quot;fnr.example&quot; class=&quot;footref&quot; href=&quot;#fn.example&quot; role=&quot;doc-backlink&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;.
&lt;/p&gt;

&lt;p&gt;
I advise you to use the new example as a template for your daemons, even though there is slightly more code involved in doing the same thing. Even though we seem to live in the world of Linux monoculture, losing portability to other Unixes would be a sad thing.
&lt;/p&gt;
&lt;div id=&quot;footnotes&quot;&gt;
&lt;h2 class=&quot;footnotes&quot;&gt;Footnotes: &lt;/h2&gt;
&lt;div id=&quot;text-footnotes&quot;&gt;

&lt;div class=&quot;footdef&quot;&gt;&lt;sup&gt;&lt;a id=&quot;fn.example&quot; class=&quot;footnum&quot; href=&quot;#fnr.example&quot; role=&quot;doc-backlink&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; &lt;div class=&quot;footpara&quot; role=&quot;doc-footnote&quot;&gt;&lt;p class=&quot;footpara&quot;&gt;
&lt;a href=&quot;https://man7.org/tlpi/code/online/dist/altio/self_pipe.c.html&quot;&gt;Here&lt;/a&gt; you can find another good example of the trick.
&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;


&lt;/div&gt;
&lt;/div&gt;
</description>
				
				<pubDate>Tue, 08 Sep 2020 00:00:00 +0300</pubDate>
				<link>https://chaoticlab.io/posts/daemonize-posix-update/</link>
				<guid isPermaLink="true">https://chaoticlab.io/posts/daemonize-posix-update/</guid>
			</item>
		
			<item>
				<title>Update: MSI Installer for GNU Emacs 27.1 for Windows</title>
				
				
					<description>&lt;p&gt;
Following the GNU Emacs 27.1 release, &lt;a href=&quot;/emacs/wix/update/2019/01/05/emacs_installer.html&quot;&gt;my MSI installer&lt;/a&gt; for GNU Emacs has been updated!
&lt;/p&gt;

&lt;p&gt;
As usual, it is a belated update.
&lt;/p&gt;

&lt;p&gt;
Although this release of Emacs contains a Windows installer, I decided to release my installer as well, because MSI installers might be more convenient in some cases.
&lt;/p&gt;

&lt;p&gt;
You can find all the &lt;a href=&quot;https://github.com/arbv/emacs-msi-installer&quot;&gt;sources&lt;/a&gt; on GitHub as well as the &lt;a href=&quot;https://github.com/arbv/emacs-msi-installer/releases&quot;&gt;pre-built installers&lt;/a&gt; for the latest release of GNU Emacs. The provided installers bundle official, unmodified GNU Emacs binaries for Windows.
&lt;/p&gt;

&lt;p&gt;
If you used an older version of the installer you should be able to perform an in-place upgrade.
&lt;/p&gt;

&lt;p&gt;
Enjoy!
&lt;/p&gt;

&lt;p&gt;
&lt;i&gt;I decided to reuse screenshots from the previous release because the installer&apos;s code was not modified since then.&lt;/i&gt;
&lt;/p&gt;

&lt;div class=&quot;org-center&quot;&gt;

&lt;div id=&quot;org38a89a0&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/01.png&quot; alt=&quot;01.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;orgdcfa594&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/02.png&quot; alt=&quot;02.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org26fa044&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/03.png&quot; alt=&quot;03.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;orge3ea924&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/04.png&quot; alt=&quot;04.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org02f8d30&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/05.png&quot; alt=&quot;05.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org60c9c9d&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/06.png&quot; alt=&quot;06.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
				
				<pubDate>Tue, 25 Aug 2020 00:00:00 +0300</pubDate>
				<link>https://chaoticlab.io/posts/emacs-27-1-msi/</link>
				<guid isPermaLink="true">https://chaoticlab.io/posts/emacs-27-1-msi/</guid>
			</item>
		
			<item>
				<title>Finding the Square Root of a Number Without Using the Standard Library (Newton&apos;s Method)</title>
				
				
					<description>&lt;p&gt;
In this short post, I want to show a way to find the square root of a positive number without relying on the standard library using &lt;a href=&quot;https://en.wikipedia.org/wiki/Newton%27s_method&quot;&gt;Newton&apos;s method&lt;/a&gt;. This is the method which seems to be used in many implementations of the C standard library. The example code is in the C programming language. Before going to the implementation, I provide the mathematical formulae used.
&lt;/p&gt;

&lt;p&gt;
I want to demonstrate how one could solve it with a relatively small amount of code without sacrificing precision much or at all compared to the &lt;code&gt;sqrt()&lt;/code&gt; function from the C standard library.
&lt;/p&gt;
&lt;div id=&quot;outline-container-org0f1ff28&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org0f1ff28&quot;&gt;A Bit of Math&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org0f1ff28&quot;&gt;
&lt;p&gt;
Before going to the code, we need to describe the method which we are going to use. No advanced understanding of math is required.
&lt;/p&gt;

&lt;p&gt;
Finding the square root of a number
&lt;/p&gt;

&lt;p&gt;
\[N = \sqrt{X}\]
&lt;/p&gt;

&lt;p&gt;
using Newton&apos;s method requires multiple steps.
&lt;/p&gt;

&lt;p&gt;
To find the value of the desired accuracy
&lt;/p&gt;

&lt;p&gt;
\[N = A_n\]
&lt;/p&gt;

&lt;p&gt;
we will use the following formula:
&lt;/p&gt;

&lt;p&gt;
\[A_{n} = \frac{A_{n-1} + \frac{X}{A_{n-1}}}{2}\]
&lt;/p&gt;

&lt;p&gt;
where accuracy depends on the value of \(n\). The higher the value of \(n\) the more accurate value of square root we could obtain. We can say that \(n\) is the number of approximations (how many times we want to apply this formula).
&lt;/p&gt;

&lt;p&gt;
When choosing \(n\) one needs to keep in mind that, in general, Newton&apos;s method has quadratic convergence which intuitively means that the number of correct digits roughly doubles in every step. On a computer, the number of approximations is dictated by the hardware.
&lt;/p&gt;

&lt;p&gt;
From the formula above it is obvious that we need to know a way to find a value of \(A_1\) to start.
&lt;/p&gt;

&lt;p&gt;
A good starting value (or, should I say, a good first approximation) would be &lt;i&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Integer_square_root&quot;&gt;integer square root&lt;/a&gt;&lt;/i&gt; of \(X\):
&lt;/p&gt;

&lt;p&gt;
\[I=\lfloor \sqrt{X} \rfloor\]
&lt;/p&gt;

&lt;p&gt;
so
&lt;/p&gt;

&lt;p&gt;
\[A_{1} = I.\]
&lt;/p&gt;

&lt;p&gt;
We will refer to this formulae during the programming process. Now let&apos;s go to the implementation.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgfd256b1&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgfd256b1&quot;&gt;Implementation&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgfd256b1&quot;&gt;
&lt;p&gt;
From the description above it becomes obvious that the first step which we need to do is to calculate the &lt;i&gt;integer square root&lt;/i&gt; \(I\). We can calculate this value iteratively increasing some number \(k\) starting from \(1\) until \(k^2 \gt X\). Reaching this condition means that we have found the &lt;i&gt;integer square root&lt;/i&gt; \(I\) of the number \(X\):
&lt;/p&gt;

&lt;p&gt;
\[I = k - 1.\]
&lt;/p&gt;

&lt;p&gt;
We can achieve this using the following C code:
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-C&quot;&gt;&lt;span class=&quot;org-type&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;org-function-name&quot;&gt;isqrt&lt;/span&gt;(&lt;span class=&quot;org-keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;X&lt;/span&gt;)
{
    &lt;span class=&quot;org-type&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;k&lt;/span&gt; = 1, &lt;span class=&quot;org-variable-name&quot;&gt;result&lt;/span&gt; = 1;
    &lt;span class=&quot;org-keyword&quot;&gt;while&lt;/span&gt; (result &amp;lt;= X)
    {
        k++;
        result = k*k;
    }
    &lt;span class=&quot;org-keyword&quot;&gt;return&lt;/span&gt; k--;
}
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
There are more &lt;a href=&quot;http://www.nuprl.org/MathLibrary/integer_sqrt/&quot;&gt;efficient methods available&lt;/a&gt;, but this one is easier to understand.
&lt;/p&gt;

&lt;p&gt;
Then we need to find \(A_n\)&lt;sup&gt;&lt;a id=&quot;fnr.1&quot; class=&quot;footref&quot; href=&quot;#fn.1&quot; role=&quot;doc-backlink&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; I have to admit that this sentence was added after some &lt;a href=&quot;https://www.reddit.com/r/programming/comments/gmsnog/finding_the_square_root_of_a_number_without_using/&quot;&gt;discussion&lt;/a&gt; at Reddit and it is quite bold. I tried to find some facts which will prove that I am wrong, but so far I have found none. But I am not a floating-point expert, though, so if you have information on this or, even better, the proof - please feel free to contact me. I am interested in improving this code and always ready to admit my mistakes. iteratively. Here the question arises: how should we peek \(n\)? We can paraphrase this question: how many times should we approximate the value?
&lt;/p&gt;

&lt;p&gt;
In C we can use the following trick: considering that the floating-point numbers have finite precision, we may iterate until the value \(A_n\) and \(A_{n-1}\) will not become equal when compared using &lt;code&gt;==&lt;/code&gt; operator in C. That means that we have reached the maximum possible precision on the current hardware (at least for this implementation). That is to say that I expect the method to converge as soon as
&lt;/p&gt;

&lt;p&gt;
\[\left[A_{n-1} - A_n \right] \lt \epsilon\]
&lt;/p&gt;

&lt;p&gt;
where \(\epsilon\) is the &lt;a href=&quot;https://en.wikipedia.org/wiki/Machine_epsilon&quot;&gt;machine epsilon&lt;/a&gt; for double-precision floating-point values (defined as &lt;code&gt;DBL_EPSILON&lt;/code&gt; constant in C).&lt;sup&gt;&lt;a id=&quot;fnr.1.1&quot; class=&quot;footref&quot; href=&quot;#fn.1&quot; role=&quot;doc-backlink&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;
&lt;/p&gt;

&lt;p&gt;
Please keep in mind that this approach may not work in some other programming environments. If it is the case, limit \(n\) with some sane number. Also keep in mind, that we are targeting platforms with &lt;a href=&quot;https://en.wikipedia.org/wiki/IEEE_754&quot;&gt;IEEE 754-compliant&lt;/a&gt; floating-point units.
&lt;/p&gt;

&lt;p&gt;
So, finally, here is the code which implements calculation of the square root using Newton&apos;s method (with some checks omitted for clarity):
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-C&quot;&gt;&lt;span class=&quot;org-type&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;org-function-name&quot;&gt;nsqrt&lt;/span&gt;(&lt;span class=&quot;org-type&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;X&lt;/span&gt;)
{
    &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
    &lt;span class=&quot;org-type&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;I&lt;/span&gt;;
    &lt;span class=&quot;org-type&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;A_prev&lt;/span&gt;, &lt;span class=&quot;org-variable-name&quot;&gt;A&lt;/span&gt;;
    &lt;span class=&quot;org-keyword&quot;&gt;if&lt;/span&gt; (X == 0.0 || X == 1.0 &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;)
    {
        &lt;span class=&quot;org-keyword&quot;&gt;return&lt;/span&gt; X;
    }
    &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
    I = isqrt((&lt;span class=&quot;org-type&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;long&lt;/span&gt;)X); &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;see above&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
    &lt;span class=&quot;org-keyword&quot;&gt;if&lt;/span&gt; (X == (&lt;span class=&quot;org-type&quot;&gt;double&lt;/span&gt;)(I*I)) &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;exact root&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
    {
        &lt;span class=&quot;org-keyword&quot;&gt;return&lt;/span&gt; (&lt;span class=&quot;org-type&quot;&gt;double&lt;/span&gt;)I;
    }
    A = A_prev = I;
    &lt;span class=&quot;org-keyword&quot;&gt;do&lt;/span&gt; {
        A_prev = A;
        A = (A + X/A)/2.0;
    } &lt;span class=&quot;org-keyword&quot;&gt;while&lt;/span&gt; (A_prev != A);

    &lt;span class=&quot;org-keyword&quot;&gt;return&lt;/span&gt; A;
}
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
The reader might be interested in how well the code above performs compared against the &lt;code&gt;sqrt()&lt;/code&gt; function from the C standard library. According to my tests, precision wise, it produces very similar or even the same results, at least on Windows (x86_64) and Linux (x86_64, ARM). I believe that it would be &lt;a href=&quot;https://github.com/brho/plan9/blob/master/sys/src/libc/port/sqrt.c&quot;&gt;the case&lt;/a&gt; for &lt;a href=&quot;https://9p.io/plan9/&quot;&gt;Plan 9&lt;/a&gt; as well. There is one notable exception though: when calculating \(\sqrt{2}\) the results produced by the function above and the built-in one might differ. It seems that the functions in standard C library implementations may return the precomputed value of \(\sqrt{2}\) (the &lt;code&gt;M_SQRT2&lt;/code&gt; constant), which might have been computed using different, possibly more precise, method.
&lt;/p&gt;

&lt;p&gt;
Let&apos;s add the corresponding check to the code (as well as some other checks). Here is the revised version of the function:
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-C&quot;&gt;&lt;span class=&quot;org-type&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;org-function-name&quot;&gt;nsqrt&lt;/span&gt;(&lt;span class=&quot;org-type&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;X&lt;/span&gt;)
{
    &lt;span class=&quot;org-keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;inf&lt;/span&gt; = 1.0l/0.0l; &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;positive infinity&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
    &lt;span class=&quot;org-keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;ninf&lt;/span&gt; = -inf; &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;negative infinity&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
    &lt;span class=&quot;org-keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;nan&lt;/span&gt; = 0.0l/0.0l; &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;not a number&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
    &lt;span class=&quot;org-type&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;I&lt;/span&gt;;
    &lt;span class=&quot;org-type&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;A_prev&lt;/span&gt;, &lt;span class=&quot;org-variable-name&quot;&gt;A&lt;/span&gt;;
    &lt;span class=&quot;org-keyword&quot;&gt;if&lt;/span&gt; (X == 0.0 || X == 1.0 || X == inf)
    {
        &lt;span class=&quot;org-keyword&quot;&gt;return&lt;/span&gt; X;
    }
    &lt;span class=&quot;org-keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;org-keyword&quot;&gt;if&lt;/span&gt; (X == 2.0)
    {
        &lt;span class=&quot;org-keyword&quot;&gt;return&lt;/span&gt; M_SQRT2;
    }
    &lt;span class=&quot;org-keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;org-keyword&quot;&gt;if&lt;/span&gt; (X == ninf || X &amp;lt; -0.0)
    {
        &lt;span class=&quot;org-keyword&quot;&gt;return&lt;/span&gt; nan;
    }
    &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;NaN cannot be compared using == operator&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
    &lt;span class=&quot;org-keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;org-keyword&quot;&gt;if&lt;/span&gt; (memcmp((&lt;span class=&quot;org-type&quot;&gt;void&lt;/span&gt; *)&amp;amp;X, (&lt;span class=&quot;org-type&quot;&gt;void&lt;/span&gt; *)&amp;amp;nan, &lt;span class=&quot;org-keyword&quot;&gt;sizeof&lt;/span&gt;(&lt;span class=&quot;org-type&quot;&gt;double&lt;/span&gt;)) == 0)
    {
        &lt;span class=&quot;org-keyword&quot;&gt;return&lt;/span&gt; nan;
    }
    &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;I =  floor(sqrt(X))&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
    I = isqrt((&lt;span class=&quot;org-type&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;long&lt;/span&gt;)X);
    &lt;span class=&quot;org-keyword&quot;&gt;if&lt;/span&gt; (X == (&lt;span class=&quot;org-type&quot;&gt;double&lt;/span&gt;)(I*I)) &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;exact root&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
    {
        &lt;span class=&quot;org-keyword&quot;&gt;return&lt;/span&gt; (&lt;span class=&quot;org-type&quot;&gt;double&lt;/span&gt;)I;
    }
    &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;Newton&apos;s method: A{n} = (A{n-1} + X/A{n-1})/2&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
    A = A_prev = I; &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;A{1} = I, or A{1} = floor(sqrt(X))&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
    &lt;span class=&quot;org-keyword&quot;&gt;do&lt;/span&gt; {
        A_prev = A;
        A = (A + X/A)/2.0;
    } &lt;span class=&quot;org-keyword&quot;&gt;while&lt;/span&gt; (A_prev != A);
    &lt;span class=&quot;org-keyword&quot;&gt;return&lt;/span&gt; A;
}
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
As far as I can tell, this version should be standard-compliant (at least on my hardware), but I do not want to make such a bold statement, especially considering that developing the standard compliant version of &lt;code&gt;sqrt()&lt;/code&gt; was not the main point of this post.
&lt;/p&gt;

&lt;p&gt;
Moreover, I do not want to claim that this function works in the same way as &lt;code&gt;sqrt()&lt;/code&gt; from the standard C library. For some input values that can be not true. At very least you can expect that the results would be very similar. Please keep it in mind when comparing the implementations.
&lt;/p&gt;

&lt;p&gt;
The main point of this post is to show that one can solve the problem without sacrificing precision with a small amount of code, a bit of math and some knowledge of how the hardware works.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org2493c05&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org2493c05&quot;&gt;The Full Example&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org2493c05&quot;&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-C&quot;&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;to make assert() work in release builds&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
&lt;span class=&quot;org-preprocessor&quot;&gt;#undef&lt;/span&gt; NDEBUG

&lt;span class=&quot;org-preprocessor&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&amp;lt;stdlib.h&amp;gt;&lt;/span&gt;
&lt;span class=&quot;org-preprocessor&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;
&lt;span class=&quot;org-preprocessor&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&amp;lt;string.h&amp;gt;&lt;/span&gt;
&lt;span class=&quot;org-preprocessor&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&amp;lt;assert.h&amp;gt;&lt;/span&gt;

&lt;span class=&quot;org-preprocessor&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&amp;lt;math.h&amp;gt;&lt;/span&gt;

&lt;span class=&quot;org-comment-delimiter&quot;&gt;/*&lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;
Given a number N, the task is to find the square root of N without using sqrt() function.
&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt;*/&lt;/span&gt;
&lt;span class=&quot;org-keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;org-function-name&quot;&gt;isqrt&lt;/span&gt;(&lt;span class=&quot;org-keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;X&lt;/span&gt;)
{
    &lt;span class=&quot;org-type&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;k&lt;/span&gt; = 1, &lt;span class=&quot;org-variable-name&quot;&gt;result&lt;/span&gt; = 1;
    &lt;span class=&quot;org-keyword&quot;&gt;while&lt;/span&gt; (result &amp;lt;= X)
    {
        k++;
        result = k*k;
    }
    &lt;span class=&quot;org-keyword&quot;&gt;return&lt;/span&gt; k--;
}

&lt;span class=&quot;org-keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;org-function-name&quot;&gt;nsqrt&lt;/span&gt;(&lt;span class=&quot;org-type&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;X&lt;/span&gt;)
{
    &lt;span class=&quot;org-keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;inf&lt;/span&gt; = 1.0l/0.0l; &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;positive infinity&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
    &lt;span class=&quot;org-keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;ninf&lt;/span&gt; = -inf; &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;negative infinity&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
    &lt;span class=&quot;org-keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;nan&lt;/span&gt; = 0.0l/0.0l; &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;not a number&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
    &lt;span class=&quot;org-type&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;I&lt;/span&gt;;
    &lt;span class=&quot;org-type&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;A_prev&lt;/span&gt;, &lt;span class=&quot;org-variable-name&quot;&gt;A&lt;/span&gt;;
    &lt;span class=&quot;org-keyword&quot;&gt;if&lt;/span&gt; (X == 0.0 || X == 1.0 || X == inf)
    {
        &lt;span class=&quot;org-keyword&quot;&gt;return&lt;/span&gt; X;
    }
    &lt;span class=&quot;org-keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;org-keyword&quot;&gt;if&lt;/span&gt; (X == 2.0)
    {
        &lt;span class=&quot;org-keyword&quot;&gt;return&lt;/span&gt; M_SQRT2;
    }
    &lt;span class=&quot;org-keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;org-keyword&quot;&gt;if&lt;/span&gt; (X == ninf || X &amp;lt; -0.0)
    {
        &lt;span class=&quot;org-keyword&quot;&gt;return&lt;/span&gt; nan;
    }
    &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;NaN cannot be compared using == operator&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
    &lt;span class=&quot;org-keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;org-keyword&quot;&gt;if&lt;/span&gt; (memcmp((&lt;span class=&quot;org-type&quot;&gt;void&lt;/span&gt; *)&amp;amp;X, (&lt;span class=&quot;org-type&quot;&gt;void&lt;/span&gt; *)&amp;amp;nan, &lt;span class=&quot;org-keyword&quot;&gt;sizeof&lt;/span&gt;(&lt;span class=&quot;org-type&quot;&gt;double&lt;/span&gt;)) == 0)
    {
        &lt;span class=&quot;org-keyword&quot;&gt;return&lt;/span&gt; nan;
    }
    &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;I =  floor(sqrt(X))&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
    I = isqrt((&lt;span class=&quot;org-type&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;long&lt;/span&gt;)X);
    &lt;span class=&quot;org-keyword&quot;&gt;if&lt;/span&gt; (X == (&lt;span class=&quot;org-type&quot;&gt;double&lt;/span&gt;)(I*I)) &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;exact root&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
    {
        &lt;span class=&quot;org-keyword&quot;&gt;return&lt;/span&gt; (&lt;span class=&quot;org-type&quot;&gt;double&lt;/span&gt;)I;
    }
    &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;Newton&apos;s method: A{n} = (A{n-1} + X/A{n-1})/2&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
    A = A_prev = I; &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;A{1} = I, or A{1} = floor(sqrt(X))&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
    &lt;span class=&quot;org-keyword&quot;&gt;do&lt;/span&gt; {
        A_prev = A;
        A = (A + X/A)/2.0;
    } &lt;span class=&quot;org-keyword&quot;&gt;while&lt;/span&gt; (A_prev != A);
    &lt;span class=&quot;org-keyword&quot;&gt;return&lt;/span&gt; A;
}

&lt;span class=&quot;org-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;org-function-name&quot;&gt;main&lt;/span&gt;(&lt;span class=&quot;org-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;argc&lt;/span&gt;, &lt;span class=&quot;org-type&quot;&gt;char&lt;/span&gt; **&lt;span class=&quot;org-variable-name&quot;&gt;argv&lt;/span&gt;)
{
    &lt;span class=&quot;org-keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;inf&lt;/span&gt; = 1.0l/0.0l; &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;positive infinity&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
    &lt;span class=&quot;org-keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;ninf&lt;/span&gt; = -inf; &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;negative infinity&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
    &lt;span class=&quot;org-keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;nan&lt;/span&gt; = 0.0l/0.0l; &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;not a number&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
    &lt;span class=&quot;org-type&quot;&gt;size_t&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;i&lt;/span&gt;;
    &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;some edge cases&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
    assert(isnan(sqrt(nan)));
    assert(isnan(nsqrt(nan)));
    assert(isnan(sqrt(-1.0)));
    assert(isnan(nsqrt(-1.0)));
    assert(sqrt(inf) == nsqrt(inf));
    assert(isnan(sqrt(ninf)));
    assert(isnan(nsqrt(ninf)));
    assert(sqrt(0.0) == nsqrt(0.0));
    assert(sqrt(-0.0) == nsqrt(-0.0));
    assert(sqrt(1.0) == nsqrt(1.0));
    assert(sqrt(2.0) == nsqrt(2.0));

    &lt;span class=&quot;org-keyword&quot;&gt;for&lt;/span&gt; (i = 0; i &amp;lt; 100; i++)
    {
        &lt;span class=&quot;org-keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;r&lt;/span&gt; = sqrt(i), &lt;span class=&quot;org-variable-name&quot;&gt;nr&lt;/span&gt; = nsqrt(i);
        printf(&lt;span class=&quot;org-string&quot;&gt;&quot;%lu - sqrt(): %.50f, nsqrt(): %.50f. same: %s\n&quot;&lt;/span&gt;,
                i, r, nr, (r == nr ? &lt;span class=&quot;org-string&quot;&gt;&quot;true&quot;&lt;/span&gt; : &lt;span class=&quot;org-string&quot;&gt;&quot;false&quot;&lt;/span&gt;));
    }
    &lt;span class=&quot;org-keyword&quot;&gt;return&lt;/span&gt; 0;
}
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;footnotes&quot;&gt;
&lt;h2 class=&quot;footnotes&quot;&gt;Footnotes: &lt;/h2&gt;
&lt;div id=&quot;text-footnotes&quot;&gt;

&lt;div class=&quot;footdef&quot;&gt;&lt;sup&gt;&lt;a id=&quot;fn.1&quot; class=&quot;footnum&quot; href=&quot;#fnr.1&quot; role=&quot;doc-backlink&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; &lt;div class=&quot;footpara&quot; role=&quot;doc-footnote&quot;&gt;&lt;p class=&quot;footpara&quot;&gt;
I have to admit that this sentence was added after some &lt;a href=&quot;https://www.reddit.com/r/programming/comments/gmsnog/finding_the_square_root_of_a_number_without_using/&quot;&gt;discussion&lt;/a&gt; at Reddit and it is quite bold. I tried to find some facts which will prove that I am wrong, but so far I have found none. But I am not a floating-point expert, though, so if you have information on this or, even better, the proof - please feel free to contact me. I am interested in improving this code and always ready to admit my mistakes.
&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;


&lt;/div&gt;
&lt;/div&gt;
</description>
				
				<pubDate>Tue, 19 May 2020 00:00:00 +0300</pubDate>
				<link>https://chaoticlab.io/posts/sqrt-newton/</link>
				<guid isPermaLink="true">https://chaoticlab.io/posts/sqrt-newton/</guid>
			</item>
		
			<item>
				<title>Facilities for Context Switching and Coroutines on AVR microcontrollers (and AVR-based Arduino boards)</title>
				
				
					<description>&lt;p&gt;
In this short post, I want to present a &lt;a href=&quot;https://github.com/arbv/avr-context&quot;&gt;small project&lt;/a&gt; on which I have been working for the last couple of weeks. It is a small library to control an AVR micro-controller execution context. Additionally, it can be used on AVR-based Arduino boards.
&lt;/p&gt;

&lt;p&gt;
&lt;i&gt;I have to note that this is my first serious attempt in micro-controllers programming. Nevertheless, I tried to do my best, but bugs are always possible, so bug reports are welcome. Caveat lector.&lt;/i&gt;
&lt;/p&gt;

&lt;p&gt;
Initially, the project started as a side effect of my attempt to understand how task switching is performed in operating systems. I believe that it is better to use microcontrollers to understand the concepts like this one because the generic computers are meant to run full-featured, multi-user operating systems with virtual memory support. These things, while important on their own, considerably complicate the low-level programming to the point where it is hard to see the forest behind the trees.
&lt;/p&gt;

&lt;p&gt;
The functionality, developed in the process, turned out to be generic enough, so I decided to continue to work on the project, and implemented substitutes for functions &lt;code&gt;getcontext()&lt;/code&gt;, &lt;code&gt;setcontext()&lt;/code&gt;, &lt;code&gt;makecontext()&lt;/code&gt;, &lt;code&gt;swapcontext()&lt;/code&gt;. These functions are commonly available on UNIX-like operating systems because they used to be a part of the POSIX standard (You can read about them &lt;a href=&quot;https://pubs.opengroup.org/onlinepubs/009695399/functions/getcontext.html&quot;&gt;here&lt;/a&gt; and &lt;a href=&quot;https://pubs.opengroup.org/onlinepubs/009695399/functions/makecontext.html&quot;&gt;here&lt;/a&gt;). They can be used to implement many interesting abstractions, but in most cases, this functionality is used to implement coroutines. I decided to go ahead and implemented the &lt;a href=&quot;http://www.inf.puc-rio.br/~roberto/docs/MCC15-04.pdf&quot;&gt;asymmetric stackful coroutines&lt;/a&gt; (as in the &lt;a href=&quot;https://www.lua.org/&quot;&gt;Lua programming language&lt;/a&gt;).
&lt;/p&gt;

&lt;p&gt;
I tried to make the library&apos;s interface as easy to use as possible. There are 8 functions (4 to work with execution context, 4 for to work with coroutines), 4 macros and 2 data types. The interface can be summarised as follows (to give you the high level view):
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-C&quot;&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;Context Switching: avrcontext.h&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;

&lt;span class=&quot;org-keyword&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;org-keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;avr_context_t_&lt;/span&gt; {
    &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
} &lt;span class=&quot;org-type&quot;&gt;avr_context_t&lt;/span&gt;;

&lt;span class=&quot;org-keyword&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;void&lt;/span&gt; (*&lt;span class=&quot;org-type&quot;&gt;avr_context_func_t&lt;/span&gt;)(&lt;span class=&quot;org-type&quot;&gt;void&lt;/span&gt; *);

&lt;span class=&quot;org-preprocessor&quot;&gt;#define&lt;/span&gt; &lt;span class=&quot;org-function-name&quot;&gt;AVR_SAVE_CONTEXT&lt;/span&gt;(&lt;span class=&quot;org-variable-name&quot;&gt;presave_code&lt;/span&gt;, &lt;span class=&quot;org-variable-name&quot;&gt;load_address_to_Z_code&lt;/span&gt;) &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
&lt;span class=&quot;org-preprocessor&quot;&gt;#define&lt;/span&gt; &lt;span class=&quot;org-function-name&quot;&gt;AVR_RESTORE_CONTEXT&lt;/span&gt;(&lt;span class=&quot;org-variable-name&quot;&gt;load_address_to_Z_code&lt;/span&gt;) &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;

&lt;span class=&quot;org-preprocessor&quot;&gt;#define&lt;/span&gt; &lt;span class=&quot;org-function-name&quot;&gt;AVR_SAVE_CONTEXT_GLOBAL_POINTER&lt;/span&gt;(&lt;span class=&quot;org-variable-name&quot;&gt;presave_code&lt;/span&gt;, &lt;span class=&quot;org-variable-name&quot;&gt;global_context_pointer&lt;/span&gt;) &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
&lt;span class=&quot;org-preprocessor&quot;&gt;#define&lt;/span&gt; &lt;span class=&quot;org-function-name&quot;&gt;AVR_RESTORE_CONTEXT_GLOBAL_POINTER&lt;/span&gt;(&lt;span class=&quot;org-variable-name&quot;&gt;global_context_pointer&lt;/span&gt;) &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;

&lt;span class=&quot;org-type&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;org-function-name&quot;&gt;avr_getcontext&lt;/span&gt;(&lt;span class=&quot;org-type&quot;&gt;avr_context_t&lt;/span&gt; *&lt;span class=&quot;org-variable-name&quot;&gt;cp&lt;/span&gt;);
&lt;span class=&quot;org-type&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;org-function-name&quot;&gt;avr_setcontext&lt;/span&gt;(&lt;span class=&quot;org-keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;avr_context_t&lt;/span&gt; *&lt;span class=&quot;org-variable-name&quot;&gt;cp&lt;/span&gt;);

&lt;span class=&quot;org-type&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;org-function-name&quot;&gt;avr_swapcontext&lt;/span&gt;(&lt;span class=&quot;org-type&quot;&gt;avr_context_t&lt;/span&gt; *&lt;span class=&quot;org-variable-name&quot;&gt;oucp&lt;/span&gt;, &lt;span class=&quot;org-keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;avr_context_t&lt;/span&gt; *&lt;span class=&quot;org-variable-name&quot;&gt;cp&lt;/span&gt;);
&lt;span class=&quot;org-type&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;org-function-name&quot;&gt;avr_makecontext&lt;/span&gt;(&lt;span class=&quot;org-type&quot;&gt;avr_context_t&lt;/span&gt; *&lt;span class=&quot;org-variable-name&quot;&gt;cp&lt;/span&gt;,
                     &lt;span class=&quot;org-type&quot;&gt;void&lt;/span&gt; *&lt;span class=&quot;org-variable-name&quot;&gt;stackp&lt;/span&gt;, &lt;span class=&quot;org-keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;size_t&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;stack_size&lt;/span&gt;,
                     &lt;span class=&quot;org-keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;avr_context_t&lt;/span&gt; *&lt;span class=&quot;org-variable-name&quot;&gt;successor_cp&lt;/span&gt;,
                     &lt;span class=&quot;org-type&quot;&gt;avr_context_func_t&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;funcp&lt;/span&gt;, &lt;span class=&quot;org-type&quot;&gt;void&lt;/span&gt; *&lt;span class=&quot;org-variable-name&quot;&gt;funcargp&lt;/span&gt;);

&lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;Asymmetric Stackful Coroutines: avrcoro.h&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;

&lt;span class=&quot;org-keyword&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;org-keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;avr_coro_t_&lt;/span&gt; {
    &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
} &lt;span class=&quot;org-type&quot;&gt;avr_coro_t&lt;/span&gt;;

&lt;span class=&quot;org-keyword&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;org-keyword&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;avr_coro_state_t_&lt;/span&gt; {
    &lt;span class=&quot;org-variable-name&quot;&gt;AVR_CORO_SUSPENDED&lt;/span&gt; = 0,
    &lt;span class=&quot;org-variable-name&quot;&gt;AVR_CORO_RUNNING&lt;/span&gt;,
    &lt;span class=&quot;org-variable-name&quot;&gt;AVR_CORO_DEAD&lt;/span&gt;,
    &lt;span class=&quot;org-variable-name&quot;&gt;AVR_CORO_ILLEGAL&lt;/span&gt;,
} &lt;span class=&quot;org-type&quot;&gt;avr_coro_state_t&lt;/span&gt;;

&lt;span class=&quot;org-keyword&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;void&lt;/span&gt; *(*&lt;span class=&quot;org-type&quot;&gt;avr_coro_func_t&lt;/span&gt;)(&lt;span class=&quot;org-type&quot;&gt;avr_coro_t&lt;/span&gt; *, &lt;span class=&quot;org-type&quot;&gt;void&lt;/span&gt; *);

&lt;span class=&quot;org-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;org-function-name&quot;&gt;avr_coro_init&lt;/span&gt;(&lt;span class=&quot;org-type&quot;&gt;avr_coro_t&lt;/span&gt; *&lt;span class=&quot;org-variable-name&quot;&gt;coro&lt;/span&gt;,
                  &lt;span class=&quot;org-type&quot;&gt;void&lt;/span&gt; *&lt;span class=&quot;org-variable-name&quot;&gt;stackp&lt;/span&gt;, &lt;span class=&quot;org-keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;size_t&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;stack_size&lt;/span&gt;,
                  &lt;span class=&quot;org-type&quot;&gt;avr_coro_func_t&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;func&lt;/span&gt;);
&lt;span class=&quot;org-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;org-function-name&quot;&gt;avr_coro_resume&lt;/span&gt;(&lt;span class=&quot;org-type&quot;&gt;avr_coro_t&lt;/span&gt; *&lt;span class=&quot;org-variable-name&quot;&gt;coro&lt;/span&gt;, &lt;span class=&quot;org-type&quot;&gt;void&lt;/span&gt; **&lt;span class=&quot;org-variable-name&quot;&gt;data&lt;/span&gt;);
&lt;span class=&quot;org-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;org-function-name&quot;&gt;avr_coro_yield&lt;/span&gt;(&lt;span class=&quot;org-type&quot;&gt;avr_coro_t&lt;/span&gt; *&lt;span class=&quot;org-variable-name&quot;&gt;self&lt;/span&gt;, &lt;span class=&quot;org-type&quot;&gt;void&lt;/span&gt; **&lt;span class=&quot;org-variable-name&quot;&gt;data&lt;/span&gt;);
&lt;span class=&quot;org-type&quot;&gt;avr_coro_state_t&lt;/span&gt; &lt;span class=&quot;org-function-name&quot;&gt;avr_coro_state&lt;/span&gt;(&lt;span class=&quot;org-keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;avr_coro_t&lt;/span&gt; *&lt;span class=&quot;org-variable-name&quot;&gt;coro&lt;/span&gt;);

&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
I do not want to repeat myself here, so if you are interested, you can find the full project documentation on &lt;a href=&quot;https://github.com/arbv/avr-context&quot;&gt;the project&apos;s&lt;/a&gt; page on GitHub. There are &lt;a href=&quot;https://github.com/arbv/avr-context/tree/master/examples&quot;&gt;examples&lt;/a&gt; included. I tried to arrange them in such a way that one can use them as a tutorial. They are, I hope, properly documented as well.
&lt;/p&gt;

&lt;p&gt;
The list of available examples:
&lt;/p&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;b&gt;Context Switching:&lt;/b&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/arbv/avr-context/blob/master/examples/Context_Switching/01.GOTO_via_Context_Switching/01.GOTO_via_Context_Switching.ino&quot;&gt;GOTO via Context Switching&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/arbv/avr-context/blob/master/examples/Context_Switching/02.Non-Linear_Program_Execution/02.Non-Linear_Program_Execution.ino&quot;&gt;Non-Linear Program Execution&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/arbv/avr-context/blob/master/examples/Context_Switching/03.Symmetric_Stackful_Coroutines/03.Symmetric_Stackful_Coroutines.ino&quot;&gt;Symmetric Stackful Coroutines&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/arbv/avr-context/blob/master/examples/Context_Switching/04.Preemptive_Task_Switching/04.Preemptive_Task_Switching.ino&quot;&gt;Preemptive Task Switching&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Coroutines:&lt;/b&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/arbv/avr-context/blob/master/examples/Coroutines/01.Basic_Generator/01.Basic_Generator.ino&quot;&gt;Basic Generator&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/arbv/avr-context/blob/master/examples/Coroutines/02.Symmetric_Coroutines_via_Asymmetric_Ones/02.Symmetric_Coroutines_via_Asymmetric_Ones.ino&quot;&gt;Symmetric Coroutines via Asymmetric Ones&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/arbv/avr-context/blob/master/examples/Coroutines/03.Producer-Consumer/03.Producer-Consumer.ino&quot;&gt;Producer-Consumer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/arbv/avr-context/blob/master/examples/Coroutines/04.Producer-Filter-Consumer/04.Producer-Filter-Consumer.ino&quot;&gt;Producer-Filter-Consumer&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
The library can be installed via &quot;Library Manager&quot; in Arduino IDE (search for &lt;b&gt;AVR-context&lt;/b&gt;).
&lt;/p&gt;


&lt;div id=&quot;org44111c5&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/avr-context/libmgr.png&quot; alt=&quot;libmgr.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
The project turned out to be very interesting on itself and involved some research. The references to the specifications, papers and other resources can be found in the project&apos;s documentation. I may do a couple of publications which demonstrate how this library was developed. Although the result is hardware specific, the approach itself can be adapted to almost any hardware platform.
&lt;/p&gt;
</description>
				
				<pubDate>Fri, 15 May 2020 00:00:00 +0300</pubDate>
				<link>https://chaoticlab.io/posts/avr-context/</link>
				<guid isPermaLink="true">https://chaoticlab.io/posts/avr-context/</guid>
			</item>
		
			<item>
				<title>High-Quality Video Playback on Linux</title>
				
				
					<description>&lt;p&gt;
Some programs are so damn good that you start to see them without any relation to the platform on which they run. In this case, you start looking for their substitutes if you are unable to use them on some platforms, often without success. In my opinion, one of the better combinations for video playback is &lt;a href=&quot;https://mpc-hc.org/&quot;&gt;Media Player Classic Home Cinema&lt;/a&gt; in combination with &lt;a href=&quot;http://madvr.com/&quot;&gt;MadVR&lt;/a&gt; video renderer. It is rather hard to beat this combination, but there is a very good, open-source alternative available on Linux: &lt;a href=&quot;https://mpv.io/&quot;&gt;mpv&lt;/a&gt;+&lt;a href=&quot;https://www.smplayer.info/&quot;&gt;SMPlayer&lt;/a&gt;. In this post, I am going to describe how I essentially repeated my configuration for high-quality video playback on Linux.
&lt;/p&gt;

&lt;p&gt;
I believe that there is one thing worth noting: as both &lt;code&gt;SMPlayer&lt;/code&gt; and &lt;code&gt;mpv&lt;/code&gt; are available on Windows the information from this post might be useful if you plan to use these programs on Windows as well. I think that no additional adaptation required for this platform. The same goes for macOS.
&lt;/p&gt;

&lt;p&gt;
I would suggest you keep the &lt;a href=&quot;https://mpv.io/manual/stable/&quot;&gt;man page&lt;/a&gt; of &lt;code&gt;mpv&lt;/code&gt; opened so that you can quickly read about the configuration options referenced in this post.
&lt;/p&gt;
&lt;div id=&quot;outline-container-org97e1b73&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org97e1b73&quot;&gt;Important Options for High-Quality Video Playback&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org97e1b73&quot;&gt;
&lt;p&gt;
To improve video playback quality, we need the following:
&lt;/p&gt;

&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;&lt;b&gt;Good scaling algorithms&lt;/b&gt; - I believe that this part is obvious. I should note that scaling algorithms are computationally intensive in general and require a fairly high-performance video card. I suggest that you use the following algorithms: &lt;a href=&quot;https://en.wikipedia.org/wiki/Lanczos_resampling&quot;&gt;ewa_lanczos&lt;/a&gt; (aka jinc) with an &lt;a href=&quot;https://en.wikipedia.org/wiki/Ringing_artifacts&quot;&gt;anti-ringing filter&lt;/a&gt; for up-scaling and &lt;a href=&quot;https://en.wikipedia.org/wiki/Chrominance&quot;&gt;chroma&lt;/a&gt; scaling, mitchell for down-scaling. A better alternative to ewa_lanczos would be ewa_lanczossharp, but it is very computationally intensive.  If you have decided to use it, I believe that you might not need the anti-ringing filter in that case.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Smooth-motion (with V-Sync)&lt;/b&gt;. Here I should note that this is not converting video to the higher frame-rate as some might think. This technique allows frames from a video to better synchronise with frame-rate of your display. Without this, some judder might appear during motion. This technique is called &lt;a href=&quot;https://github.com/mpv-player/mpv/wiki/Interpolation&quot;&gt;Interpolation&lt;/a&gt; in &lt;code&gt;mpv&apos;s&lt;/code&gt; manual, and there is an in-depth explanation of it on the wiki of the project.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Debanding filter&lt;/b&gt; - prevents &lt;a href=&quot;https://en.wikipedia.org/wiki/Colour_banding&quot;&gt;colour banding&lt;/a&gt; from appearing on the scenes containing some gradients.&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org8cd524b&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org8cd524b&quot;&gt;Configuring mpv&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org8cd524b&quot;&gt;
&lt;p&gt;
Let&apos;s create a configuration file for &lt;code&gt;mpv&lt;/code&gt; which uses the techniques mentioned above. The configuration file of &lt;code&gt;mpv&lt;/code&gt; is located here: &lt;code&gt;~/.config/mpv/mpv.conf&lt;/code&gt;, we are going to add the options described below into it.
&lt;/p&gt;

&lt;p&gt;
In some cases, I am going to mention settings both for &lt;b&gt;middle-end&lt;/b&gt; and &lt;b&gt;high-end&lt;/b&gt; systems. In my opinion, the visual difference between them is so subtle that I would suggest that you go with the configuration for middle-end systems first, especially if you use a laptop. If you use a relatively modern desktop or do not mind extra battery drain and fan noise then go experiment with the configuration for high-end systems.
&lt;/p&gt;

&lt;p&gt;
The first thing which we should set is a video renderer profile. There are many of them but &lt;code&gt;gpu&lt;/code&gt; and &lt;code&gt;gpu-hq&lt;/code&gt; are the ones in which we are interested the most. These, as you might have guessed, allow offloading most of the video post-processing and rendering to a GPU using OpenGL or Vulkan API. &lt;code&gt;gpu-hq&lt;/code&gt; is pre-configured to use higher quality, more computationally intensive filters.
&lt;/p&gt;

&lt;p&gt;
&lt;b&gt;middle-end systems:&lt;/b&gt;
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-nil&quot;&gt;profile=gpu
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
&lt;b&gt;high-end systems:&lt;/b&gt;
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-nil&quot;&gt;profile=gpu-hq
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
We may use Vulkan or OpenGL as a GPU API. Honestly, I have not noticed any difference in performance when playing a video using either, so I would suggest that you stick with OpenGL as the most compatible option. We are going to enable V-Sync as well.
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-nil&quot;&gt;gpu-api=opengl
opengl-swapinterval=1
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
If you want to use Vulkan instead, here is how to do it:
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-nil&quot;&gt;gpu-api=vulkan
vulkan-swap-mode=fifo
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
The next logical step is to configure smooth-motion. Here is how:
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-nil&quot;&gt;video-sync=display-resample
interpolation
tscale=oversample
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
Now let&apos;s configure scaling.
&lt;/p&gt;

&lt;p&gt;
&lt;b&gt;middle-end systems:&lt;/b&gt;
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-nil&quot;&gt;scale=ewa_lanczos:scale-antiring=1
cscale=ewa_lanczos:scale-antiring=1
dscale=mitchell
correct-downscaling
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
&lt;b&gt;high-end systems:&lt;/b&gt;
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-nil&quot;&gt;scale=ewa_lanczossharp
cscale=ewa_lanczossharp
dscale=mitchell
correct-downscaling
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
It is a good idea to enable dithering when it is necessary. &lt;code&gt;mpv&lt;/code&gt; uses a fairly good dithering algorithm by default.
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-nil&quot;&gt;dither-depth=auto
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
The last step is to offload video decoding to GPU when possible. It is especially useful for laptops. We are using &lt;code&gt;auto-copy&lt;/code&gt; instead of &lt;code&gt;auto&lt;/code&gt; to enforce copying back decoding results back to the system RAM. It might be necessary for some filters to work and helps to avoid some decoding issues at the expense of a relatively small performance loss.
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-nil&quot;&gt;hwdec=auto-copy
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgd944762&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgd944762&quot;&gt;Using SMPlayer with a Pre-configured mpv Instance&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgd944762&quot;&gt;
&lt;p&gt;
I prefer to use &lt;code&gt;mpv&lt;/code&gt; as a back-end of &lt;code&gt;SMPlayer&lt;/code&gt;. If you are going to use &lt;code&gt;mpv&lt;/code&gt; as a standalone video player then you can skip reading this section.
&lt;/p&gt;

&lt;p&gt;
Modern versions of &lt;code&gt;SMPlayer&lt;/code&gt; can use &lt;code&gt;mpv&lt;/code&gt; as its back-end without any additional configuration. However, &lt;code&gt;SMPlayer&lt;/code&gt; tries to have &lt;code&gt;mpv&lt;/code&gt; under its full control and starts it with &lt;code&gt;--no-config&lt;/code&gt; option. It forces &lt;code&gt;mpv&lt;/code&gt; to ignore its default configuration file. Fortunately, &lt;code&gt;SMPlayer&lt;/code&gt; can pass user-defined command-line options to &lt;code&gt;mpv&lt;/code&gt;, which allows us to bypass this limitation. To do it we have to use this extra option to force &lt;code&gt;mpv&lt;/code&gt; to load its configuration file:
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-nil&quot;&gt;--include=~/.config/mpv/mpv.conf
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
Here is the screenshot which shows us how to do it:
&lt;/p&gt;

&lt;div class=&quot;org-center&quot;&gt;

&lt;div id=&quot;org2f38d67&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/linux-hq-video-playback/extra-args.png&quot; alt=&quot;extra-args.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;
Please keep in mind that &lt;code&gt;SMPlayer&lt;/code&gt; expects that &lt;code&gt;mpv&lt;/code&gt; does not load its configuration file, so be conscious about what you have in the &lt;code&gt;mpv.conf&lt;/code&gt; file.
&lt;/p&gt;

&lt;p&gt;
Also, it might be a good idea to configure &lt;code&gt;SMPlayer&lt;/code&gt; to use &lt;code&gt;Default&lt;/code&gt; video output engine with disabled post-processing:
&lt;/p&gt;

&lt;div class=&quot;org-center&quot;&gt;

&lt;div id=&quot;orge45945e&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/linux-hq-video-playback/default-video-out.png&quot; alt=&quot;default-video-out.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org566ec93&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org566ec93&quot;&gt;Conclusions&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org566ec93&quot;&gt;
&lt;p&gt;
In this post, we have configured &lt;code&gt;mpv&lt;/code&gt; and &lt;code&gt;SMPlayer&lt;/code&gt; for high-quality video playback. I think that there are some things left which are worth noting.
&lt;/p&gt;

&lt;p&gt;
Firstly, the video output quality depends mostly on the quality of the video files. No amount of configuration will make a miracle here if all you have is a low-quality media material.
&lt;/p&gt;

&lt;p&gt;
Secondly, the quality of the display matters a lot. It does not necessarily mean that you should use these ridiculously expensive professional displays for high precision colour work. Adequately priced display with good IPS matrix will do. I doubt that you will see any difference on a low-end TFT monitor.
&lt;/p&gt;

&lt;p&gt;
I think that these things are rather obvious, but I wanted to have them mentioned anyway.
&lt;/p&gt;

&lt;p&gt;
Hopefully, this post will improve your &lt;del&gt;anime&lt;/del&gt; video playback experience and make your entertainment more joyful.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
				
				<pubDate>Mon, 07 Oct 2019 00:00:00 +0300</pubDate>
				<link>https://chaoticlab.io/posts/linux-hq-video-playback/</link>
				<guid isPermaLink="true">https://chaoticlab.io/posts/linux-hq-video-playback/</guid>
			</item>
		
			<item>
				<title>Update: MSI Installer for GNU Emacs 26.3 for Windows with Per-User Installation Support</title>
				
				
					<description>&lt;p&gt;
I have been working on improving &lt;a href=&quot;/emacs/wix/update/2019/01/05/emacs_installer.html&quot;&gt;Emacs installer for Windows&lt;/a&gt; to add support both per-user and per-machine installations. It was made to address the installation issues of users without administrative privileges. This post is a follow up to a post I have made &lt;a href=&quot;/posts/emacs-26-3-msi/&quot;&gt;recently&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;
This effort resulted in adding support for building &lt;b&gt;per-user&lt;/b&gt; installers. These are available alongside the usual, &lt;b&gt;per-machine&lt;/b&gt; installers. It should be noted, though, that their name might be a little bit deceptive because they support installation in both per-machine &lt;b&gt;and&lt;/b&gt; per-user mode. As you might expect the latter does not require administrative privileges.
&lt;/p&gt;

&lt;p&gt;
Feature-wise both kinds of installers provide similar functionality with one notable exception: &lt;b&gt;the per-user installers unable to set and modify environmental variables conditionally depending on selected scope&lt;/b&gt; and, thus, unable to add installation directory of Emacs to the &lt;b&gt;Path&lt;/b&gt;. This is a limitation of tooling.
&lt;/p&gt;

&lt;p&gt;
Please keep in mind that mixing both per-user and per-machine installations of the same package on the same machine might result in strange behaviour. I would suggest sticking with classical, per-machine only installers if you have enough privileges on your machine.
&lt;/p&gt;

&lt;p&gt;
You can find all the &lt;a href=&quot;https://github.com/arbv/emacs-msi-installer&quot;&gt;sources&lt;/a&gt; on GitHub as well as the &lt;a href=&quot;https://github.com/arbv/emacs-msi-installer/releases&quot;&gt;pre-built installers&lt;/a&gt; for the latest release of GNU Emacs. The provided installers bundle official, unmodified GNU Emacs binaries for Windows.
&lt;/p&gt;

&lt;p&gt;
As usual, If you used an older version of the installer you should be able to perform an in-place upgrade.
&lt;/p&gt;

&lt;p&gt;
The screenshots provided below show the installation of a per-user installer in advanced mode.
&lt;/p&gt;

&lt;p&gt;
Enjoy!
&lt;/p&gt;

&lt;div class=&quot;org-center&quot;&gt;

&lt;div id=&quot;orgf050894&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-per-user-msi/01.png&quot; alt=&quot;01.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org46a7371&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-per-user-msi/02.png&quot; alt=&quot;02.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;orgb51442d&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-per-user-msi/03.png&quot; alt=&quot;03.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;orgdc5c9bf&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-per-user-msi/04.png&quot; alt=&quot;04.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org39fa6e6&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-per-user-msi/05.png&quot; alt=&quot;05.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org9a2284d&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-per-user-msi/06.png&quot; alt=&quot;06.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;orgd46bc0c&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-per-user-msi/07.png&quot; alt=&quot;07.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
				
				<pubDate>Tue, 01 Oct 2019 00:00:00 +0300</pubDate>
				<link>https://chaoticlab.io/posts/emacs-26-3-per-user-msi/</link>
				<guid isPermaLink="true">https://chaoticlab.io/posts/emacs-26-3-per-user-msi/</guid>
			</item>
		
			<item>
				<title>Update: MSI Installer for GNU Emacs 26.3 for Windows</title>
				
				
					<description>&lt;p&gt;
Following the GNU Emacs 26.3 release, &lt;a href=&quot;/emacs/wix/update/2019/01/05/emacs_installer.html&quot;&gt;my MSI installer&lt;/a&gt; for GNU Emacs has been updated!
&lt;/p&gt;

&lt;p&gt;
This time it is rather a belated update.
&lt;/p&gt;

&lt;p&gt;
You can find all the &lt;a href=&quot;https://github.com/arbv/emacs-msi-installer&quot;&gt;sources&lt;/a&gt; on GitHub as well as the &lt;a href=&quot;https://github.com/arbv/emacs-msi-installer/releases&quot;&gt;pre-built installers&lt;/a&gt; for the latest release of GNU Emacs. The provided installers bundle official, unmodified GNU Emacs binaries for Windows.
&lt;/p&gt;

&lt;p&gt;
If you used an older version of the installer you should be able to perform an in-place upgrade.
&lt;/p&gt;

&lt;p&gt;
Enjoy!
&lt;/p&gt;

&lt;div class=&quot;org-center&quot;&gt;

&lt;div id=&quot;org177b0fb&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/01.png&quot; alt=&quot;01.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org8df1398&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/02.png&quot; alt=&quot;02.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;orgaee6541&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/03.png&quot; alt=&quot;03.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;orgd829cbb&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/04.png&quot; alt=&quot;04.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;orga7aefbc&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/05.png&quot; alt=&quot;05.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;orgbdb252f&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/06.png&quot; alt=&quot;06.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
				
				<pubDate>Thu, 12 Sep 2019 00:00:00 +0300</pubDate>
				<link>https://chaoticlab.io/posts/emacs-26-3-msi/</link>
				<guid isPermaLink="true">https://chaoticlab.io/posts/emacs-26-3-msi/</guid>
			</item>
		
			<item>
				<title>Integrating Xfce with LightDM Display Manager</title>
				
				
					<description>&lt;p&gt;
One of the most basic security features of any laptop or workstation is the ability to lock the sscreen. It might be convenient in many other, non-security related, scenarios as well. In most cases, this feature works without user&apos;s intervention on most of the Linux distributions, yet it did not work for me in Xfce4 with LightDM on Arch Linux. As I understand, Xfce does not have its display manager, so it relies on third-party solutions, mostly Gnome Display Manager (GDM). As I prefer Xfce as my desktop environment, I did not want to install GDM as it needs many Gnome libraries to work. Because of this, I decided to use LighDM as my display manager, which is more desktop environment agnostic and lightweight. Unfortunately, Xfce lacks proper integration with it (at least in Arch Linux). In this post, I want to provide a solution to this problem. Moreover, I believe that information in this post might give some ideas to the users of the other desktop environments and window managers on how to integrate them with LightDM.
&lt;/p&gt;

&lt;p&gt;
To some extent, this post is a continuation of the other LightDM related post which I have posted &lt;a href=&quot;/posts/lightdm-extmonitor/&quot;&gt;earlier&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;
If the first two buttons from the image below do not work on your system, you might want to continue reading this post.
&lt;/p&gt;

&lt;div class=&quot;org-center&quot;&gt;

&lt;div id=&quot;org83ca94c&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/xfce-lightdm/session-buttons.png&quot; alt=&quot;session-buttons.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org3b26198&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org3b26198&quot;&gt;How Xfce Initiates Screen Locking and User Switching&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org3b26198&quot;&gt;
&lt;p&gt;
Xfce does not do screen locking or user switching itself, it delegates this functionality to the other programs.
&lt;/p&gt;

&lt;p&gt;
For screen locking Xfce executes &lt;code&gt;xflock4&lt;/code&gt; program which is a shell script. The script locks the session by calling the following programs if they are present on the system (in the following order):
&lt;/p&gt;

&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;&lt;code&gt;xscreensaver-command&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;gnome-screensaver-command&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;xlock&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;slock&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
Similarly, Xfce delegates user switching to the gdmplexiserver which is (or was) a part of the Gnome Display Manager package. As you can see, Xfce is attuned to reuse some of the parts of the GNOME desktop environment.
&lt;/p&gt;

&lt;p&gt;
Considering that LightDM has its utility to control itself, the &lt;code&gt;dm-tool&lt;/code&gt;, we might try to &quot;deceive&quot; Xfce to invoke the &lt;code&gt;dm-tool&lt;/code&gt; instead. We could accomplish that by placing the scripts which call the &lt;code&gt;dm-tool&lt;/code&gt; with a required parameter (&lt;code&gt;lock&lt;/code&gt; or &lt;code&gt;switch-to-greeter&lt;/code&gt;) and are named as above mentioned programs into a directory from the &lt;code&gt;$PATH&lt;/code&gt; environmental variable (&lt;code&gt;/usr/local/bin&lt;/code&gt; seems like the right choice).
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org56787ac&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org56787ac&quot;&gt;The Scripts to Perform Screen Locking and User Switching&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org56787ac&quot;&gt;
&lt;p&gt;
At this point, it is obvious that we need two &lt;b&gt;executable&lt;/b&gt; shell scripts, one for session locking and one for user switching, which we should place into &lt;code&gt;/usr/local/bin&lt;/code&gt; folder. For the first one, I propose to use the name &lt;code&gt;slock&lt;/code&gt; or &lt;code&gt;xlock&lt;/code&gt; &lt;i&gt;(I used to recommend &lt;code&gt;xscreensaver-command&lt;/code&gt;, but I had some problems in SMPlayer in this case)&lt;/i&gt;. Here is the code:
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-shell&quot;&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;!/bin/&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;sh&lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;
&lt;/span&gt;
&lt;span class=&quot;org-comment-delimiter&quot;&gt;# &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;fake slock to make xflock to use lightdm locker
&lt;/span&gt;
&lt;span class=&quot;org-variable-name&quot;&gt;DMTOOL_AVAILABLE&lt;/span&gt;=&lt;span class=&quot;org-string&quot;&gt;&quot;$(&lt;/span&gt;&lt;span class=&quot;org-sh-quoted-exec&quot;&gt;which dm-tool&lt;/span&gt;&lt;span class=&quot;org-string&quot;&gt;)&quot;&lt;/span&gt;

&lt;span class=&quot;org-keyword&quot;&gt;if&lt;/span&gt; [ -n $&lt;span class=&quot;org-variable-name&quot;&gt;DMTOOL_AVAILABLE&lt;/span&gt; ] ; &lt;span class=&quot;org-keyword&quot;&gt;then&lt;/span&gt;
    dm-tool lock
&lt;span class=&quot;org-keyword&quot;&gt;fi&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
For the second case, user switching, we might use a very similar script, named as &lt;code&gt;gdmplexiserver&lt;/code&gt; (the only difference is a parameter to the &lt;code&gt;dm-tool&lt;/code&gt;):
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-shell&quot;&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;!/bin/&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;sh&lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;
&lt;/span&gt;
&lt;span class=&quot;org-comment-delimiter&quot;&gt;# &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;fake gdmplexiserver to make xflock to use lightdm locker
&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt;# &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;for user switching
&lt;/span&gt;
&lt;span class=&quot;org-variable-name&quot;&gt;DMTOOL_AVAILABLE&lt;/span&gt;=&lt;span class=&quot;org-string&quot;&gt;&quot;$(&lt;/span&gt;&lt;span class=&quot;org-sh-quoted-exec&quot;&gt;which dm-tool&lt;/span&gt;&lt;span class=&quot;org-string&quot;&gt;)&quot;&lt;/span&gt;

&lt;span class=&quot;org-keyword&quot;&gt;if&lt;/span&gt; [ -n $&lt;span class=&quot;org-variable-name&quot;&gt;DMTOOL_AVAILABLE&lt;/span&gt; ] ; &lt;span class=&quot;org-keyword&quot;&gt;then&lt;/span&gt;
    dm-tool switch-to-greeter
&lt;span class=&quot;org-keyword&quot;&gt;fi&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
If you are a &lt;code&gt;systemd&lt;/code&gt; user, you might try to use a script which relies on &lt;code&gt;loginctl&lt;/code&gt; for both cases:
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-shell&quot;&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;!/bin/&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;sh&lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;
&lt;/span&gt;
&lt;span class=&quot;org-variable-name&quot;&gt;LOGINCTL_AVAILABLE&lt;/span&gt;=&lt;span class=&quot;org-string&quot;&gt;&quot;$(&lt;/span&gt;&lt;span class=&quot;org-sh-quoted-exec&quot;&gt;which loginctl&lt;/span&gt;&lt;span class=&quot;org-string&quot;&gt;)&quot;&lt;/span&gt;

&lt;span class=&quot;org-keyword&quot;&gt;if&lt;/span&gt; [ -n $&lt;span class=&quot;org-variable-name&quot;&gt;LOGINCTL_AVAILABLE&lt;/span&gt; ] ; &lt;span class=&quot;org-keyword&quot;&gt;then&lt;/span&gt;
    loginctl lock-session
&lt;span class=&quot;org-keyword&quot;&gt;fi&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
After you have done all the steps mentioned above, screen locking and user switching in Xfce should work as expected.
&lt;/p&gt;

&lt;p&gt;
&lt;b&gt;UPD:&lt;/b&gt;
&lt;/p&gt;

&lt;p&gt;
&lt;i&gt;20.07.19 - Note about problems with &lt;code&gt;xscreensaver-command&lt;/code&gt;.&lt;/i&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
				
				<pubDate>Fri, 19 Jul 2019 00:00:00 +0300</pubDate>
				<link>https://chaoticlab.io/posts/xfce-lightdm/</link>
				<guid isPermaLink="true">https://chaoticlab.io/posts/xfce-lightdm/</guid>
			</item>
		
			<item>
				<title>Using LightDM with an External Monitor on a Laptop or with the Multi-monitor Setups</title>
				
				
					<description>&lt;p&gt;
Like many other users, I find it convenient to connect an external monitor to my laptop sometimes. As I often do this, I expect this functionality to work flawlessly but, unfortunately, I experienced some problems when using LightDM on Arch Linux .  By default, LightDM tries to mirror data on multiple displays, and it does not work well when you have monitors with different resolutions. In this post, I want to share my solution to this problem. I expect that this solution might be useful not only for laptop users but for the workstation users with multi-monitor setups as well. Moreover, if LightDM&apos;s user interface sometimes stops responding to your actions, this post might be useful for you.
&lt;/p&gt;

&lt;p&gt;
In general, on a laptop with an external monitor, I expect the login screen to appear on it and have the laptop screen disabled in that case.  If there are multiple external monitors connected to the system, I want only one of them used for a login screen.
&lt;/p&gt;

&lt;p&gt;
Fortunately, these actions can be programmed using a UNIX shell script build around the functionality of the &lt;code&gt;xrandr&lt;/code&gt; utility.
&lt;/p&gt;

&lt;p&gt;
When used without any parameters it prints the list of monitor outputs alongside the information about the connected monitors:
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-nil&quot;&gt;artem@artbox:~$ xrandr
Screen 0: minimum 8 x 8, current 1366 x 768, maximum 32767 x 32767
LVDS1 connected 1366x768+0+0 (normal left inverted right x axis y axis) 340mm x 190mm
   1366x768      60.03*+
   1280x720      59.74
   1024x768      60.00
   1024x576      60.00    59.90    59.82
   960x540       60.00    59.63    59.82
   800x600       60.32    56.25
   864x486       60.00    59.92    59.57
   640x480       59.94
   720x405       59.51    60.00    58.99
   680x384       60.00
   640x360       59.84    59.32    60.00
DP1 disconnected (normal left inverted right x axis y axis)
HDMI1 disconnected (normal left inverted right x axis y axis)
VGA1 disconnected (normal left inverted right x axis y axis)
VIRTUAL1 disconnected (normal left inverted right x axis y axis)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
We could filter out the information about the available outputs using the UNIX tools:
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-nil&quot;&gt;artem@artbox:~$ xrandr | grep connected | cut -d &apos; &apos; -f 1-2
LVDS1 connected
DP1 disconnected
HDMI1 disconnected
VGA1 disconnected
VIRTUAL1 disconnected
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
Keeping in mind that an internal laptop screen is usually connected using the &lt;code&gt;LVDS&lt;/code&gt; interface, we could use the information obtained from the &lt;code&gt;xrandr&lt;/code&gt; tool to achieve what is required.
&lt;/p&gt;

&lt;p&gt;
Let&apos;s outline the logic of the script using pseudo-code:
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-nil&quot;&gt;var primary_out = nil
var to_disable = nil

foreach monitor_out in list_monitor_outputs() do
    if is_connected(monitor_out) then
        if is_connected_via_LVDS(monitor_out) then
            to_disable = monitor_out
        else if primary_out == nil then
            primary_out = monitor_out
        else
            disable_monitor_output(monitor_out)
        endif
    endif
endfor

if primary_out != nil and to_disable != nil then
    set_as_primary_monitor_output(primary_out)
    disable_monitor_output(to_disable)
else if primary_out != nil then
    set_as_primary_monitor_output(primary_out)
endif
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
After translating the pseudo-code above into a shell script, I got the following code:
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-shell&quot;&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;!/bin/&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;sh&lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;
&lt;/span&gt;
&lt;span class=&quot;org-comment-delimiter&quot;&gt;# &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;the script will not work if xrandr is not available
&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;if&lt;/span&gt; [ -z &lt;span class=&quot;org-string&quot;&gt;&quot;$(&lt;/span&gt;&lt;span class=&quot;org-sh-quoted-exec&quot;&gt;which xrandr&lt;/span&gt;&lt;span class=&quot;org-string&quot;&gt;)&quot;&lt;/span&gt; ]; &lt;span class=&quot;org-keyword&quot;&gt;then&lt;/span&gt;
    &lt;span class=&quot;org-keyword&quot;&gt;exit&lt;/span&gt; 1
&lt;span class=&quot;org-keyword&quot;&gt;fi&lt;/span&gt;

&lt;span class=&quot;org-variable-name&quot;&gt;DISABLE_SUBSTRING&lt;/span&gt;=&lt;span class=&quot;org-string&quot;&gt;&quot;LVDS&quot;&lt;/span&gt;

&lt;span class=&quot;org-variable-name&quot;&gt;TO_DISABLE&lt;/span&gt;=&lt;span class=&quot;org-string&quot;&gt;&quot;&quot;&lt;/span&gt;
&lt;span class=&quot;org-variable-name&quot;&gt;PRIMARY_OUT&lt;/span&gt;=&lt;span class=&quot;org-string&quot;&gt;&quot;&quot;&lt;/span&gt;

&lt;span class=&quot;org-variable-name&quot;&gt;old_IFS&lt;/span&gt;=&lt;span class=&quot;org-string&quot;&gt;&quot;${IFS}&quot;&lt;/span&gt;
&lt;span class=&quot;org-variable-name&quot;&gt;IFS&lt;/span&gt;=$&lt;span class=&quot;org-string&quot;&gt;&apos;\n&apos;&lt;/span&gt;
&lt;span class=&quot;org-keyword&quot;&gt;for&lt;/span&gt; out&lt;span class=&quot;org-keyword&quot;&gt; in&lt;/span&gt; &lt;span class=&quot;org-sh-quoted-exec&quot;&gt;`xrandr | grep connected | cut -d &apos; &apos; -f 1-2`&lt;/span&gt;; &lt;span class=&quot;org-keyword&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;org-variable-name&quot;&gt;name&lt;/span&gt;=&lt;span class=&quot;org-sh-quoted-exec&quot;&gt;`echo $out | cut -d &apos; &apos; -f 1`&lt;/span&gt;
    &lt;span class=&quot;org-variable-name&quot;&gt;state&lt;/span&gt;=&lt;span class=&quot;org-sh-quoted-exec&quot;&gt;`echo $out | cut -d &apos; &apos; -f 2`&lt;/span&gt;
    &lt;span class=&quot;org-keyword&quot;&gt;if&lt;/span&gt; [ &lt;span class=&quot;org-string&quot;&gt;&quot;$state&quot;&lt;/span&gt; = &lt;span class=&quot;org-string&quot;&gt;&quot;connected&quot;&lt;/span&gt; ]; &lt;span class=&quot;org-keyword&quot;&gt;then&lt;/span&gt;
        &lt;span class=&quot;org-keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;$name&quot;&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt; in&lt;/span&gt;
            &lt;span class=&quot;org-comment-delimiter&quot;&gt;# &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;disable a monitor connected via LVDS
&lt;/span&gt;            ${&lt;span class=&quot;org-variable-name&quot;&gt;DISABLE_SUBSTRING&lt;/span&gt;}*)
                &lt;span class=&quot;org-keyword&quot;&gt;if&lt;/span&gt; [ -z &lt;span class=&quot;org-string&quot;&gt;&quot;$TO_DISABLE&quot;&lt;/span&gt; ]; &lt;span class=&quot;org-keyword&quot;&gt;then&lt;/span&gt;
                    &lt;span class=&quot;org-variable-name&quot;&gt;TO_DISABLE&lt;/span&gt;=&lt;span class=&quot;org-string&quot;&gt;&quot;$name&quot;&lt;/span&gt;
                &lt;span class=&quot;org-keyword&quot;&gt;fi&lt;/span&gt;
                ;;
            *)
                &lt;span class=&quot;org-comment-delimiter&quot;&gt;# &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;set the &apos;first&apos; external monitor as the
&lt;/span&gt;                &lt;span class=&quot;org-comment-delimiter&quot;&gt;# &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;primary one, disable the other external monitors
&lt;/span&gt;                &lt;span class=&quot;org-keyword&quot;&gt;if&lt;/span&gt; [ -z &lt;span class=&quot;org-string&quot;&gt;&quot;$PRIMARY_OUT&quot;&lt;/span&gt; ]; &lt;span class=&quot;org-keyword&quot;&gt;then&lt;/span&gt;
                    &lt;span class=&quot;org-variable-name&quot;&gt;PRIMARY_OUT&lt;/span&gt;=&lt;span class=&quot;org-string&quot;&gt;&quot;$name&quot;&lt;/span&gt;
                &lt;span class=&quot;org-keyword&quot;&gt;else&lt;/span&gt;
                    xrandr --output &lt;span class=&quot;org-string&quot;&gt;&quot;$name&quot;&lt;/span&gt; --off
                &lt;span class=&quot;org-keyword&quot;&gt;fi&lt;/span&gt;
                ;;
        &lt;span class=&quot;org-keyword&quot;&gt;esac&lt;/span&gt;
    &lt;span class=&quot;org-keyword&quot;&gt;fi&lt;/span&gt;
&lt;span class=&quot;org-keyword&quot;&gt;done&lt;/span&gt;
&lt;span class=&quot;org-variable-name&quot;&gt;IFS&lt;/span&gt;=&lt;span class=&quot;org-string&quot;&gt;&quot;${old_IFS}&quot;&lt;/span&gt;

&lt;span class=&quot;org-comment-delimiter&quot;&gt;# &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;If there is an internal screen, as well as at least one external monitor, then
&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt;# &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;disable the internal monitor and use the external monitor as the primary one.
&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt;# &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;Otherwise, if there are any external monitors, use the &apos;first&apos; detected one
&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt;# &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;as the primary monitor.
&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;if&lt;/span&gt; [ -n &lt;span class=&quot;org-string&quot;&gt;&quot;$TO_DISABLE&quot;&lt;/span&gt; ] &amp;amp;&amp;amp; [ -n &lt;span class=&quot;org-string&quot;&gt;&quot;$PRIMARY_OUT&quot;&lt;/span&gt; ]; &lt;span class=&quot;org-keyword&quot;&gt;then&lt;/span&gt;
    xrandr --output &lt;span class=&quot;org-string&quot;&gt;&quot;$PRIMARY_OUT&quot;&lt;/span&gt; --primary --auto --output &lt;span class=&quot;org-string&quot;&gt;&quot;$TO_DISABLE&quot;&lt;/span&gt; --off
&lt;span class=&quot;org-keyword&quot;&gt;elif&lt;/span&gt; [ -n &lt;span class=&quot;org-string&quot;&gt;&quot;$PRIMARY_OUT&quot;&lt;/span&gt; ]; &lt;span class=&quot;org-keyword&quot;&gt;then&lt;/span&gt;
    xrandr --output &lt;span class=&quot;org-string&quot;&gt;&quot;$PRIMARY_OUT&quot;&lt;/span&gt; --primary --auto
&lt;span class=&quot;org-keyword&quot;&gt;fi&lt;/span&gt;

&lt;span class=&quot;org-keyword&quot;&gt;exit&lt;/span&gt; 0
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
To use the script, one should save it into an &lt;b&gt;executable&lt;/b&gt; file and alter the LightDM&apos;s settings to use it to configure the displays.
&lt;/p&gt;

&lt;p&gt;
In order to accomplish this one should change the &lt;code&gt;display-setup-script&lt;/code&gt; in the &lt;code&gt;[Seat:*]&lt;/code&gt; section of the LightDM configuration file (&lt;code&gt;/etc/lightdm/lightdm.conf&lt;/code&gt;):
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-nil&quot;&gt;[Seat:*]
...
display-setup-script=/path/to/the-script
...

&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
To apply the new settings, please restart the LightDM daemon. The next LightDM session should use the script to configure monitors.
&lt;/p&gt;
</description>
				
				<pubDate>Tue, 16 Jul 2019 00:00:00 +0300</pubDate>
				<link>https://chaoticlab.io/posts/lightdm-extmonitor/</link>
				<guid isPermaLink="true">https://chaoticlab.io/posts/lightdm-extmonitor/</guid>
			</item>
		
			<item>
				<title>Update: MSI Installer for GNU Emacs 26.2 for Windows</title>
				
				
					<description>&lt;p&gt;
Following the GNU Emacs 26.2 release, &lt;a href=&quot;/emacs/wix/update/2019/01/05/emacs_installer.html&quot;&gt;my MSI installer&lt;/a&gt; for GNU Emacs has been updated!
&lt;/p&gt;

&lt;p&gt;
You can find all the &lt;a href=&quot;https://github.com/arbv/emacs-msi-installer&quot;&gt;sources&lt;/a&gt; on GitHub as well as the &lt;a href=&quot;https://github.com/arbv/emacs-msi-installer/releases&quot;&gt;pre-built installers&lt;/a&gt; for the latest release of GNU Emacs. The provided installers bundle official, unmodified GNU Emacs binaries for Windows.
&lt;/p&gt;

&lt;p&gt;
If you used an older version of the installer you should be able to perform an in-place upgrade.
&lt;/p&gt;

&lt;p&gt;
Enjoy!
&lt;/p&gt;

&lt;div class=&quot;org-center&quot;&gt;

&lt;div id=&quot;org0b1e66a&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-2-msi/01.png&quot; alt=&quot;01.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;orgee0f7fc&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-2-msi/02.png&quot; alt=&quot;02.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;orga0ae2f9&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-2-msi/03.png&quot; alt=&quot;03.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org5fa581d&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-2-msi/04.png&quot; alt=&quot;04.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org50e4174&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-2-msi/05.png&quot; alt=&quot;05.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org17de9df&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-2-msi/06.png&quot; alt=&quot;06.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
				
				<pubDate>Thu, 18 Apr 2019 00:00:00 +0300</pubDate>
				<link>https://chaoticlab.io/posts/emacs-26-2-msi/</link>
				<guid isPermaLink="true">https://chaoticlab.io/posts/emacs-26-2-msi/</guid>
			</item>
		
			<item>
				<title>Querying Windows Registry from Emacs Lisp</title>
				
				
					<description>&lt;p&gt;
Recently I needed to query registry values from within Emacs. Emacs, being a cross-platform application mostly tailored to work on UNIX-like operating systems, lacks this functionality. As you can expect, I ended up writing a code which accomplishes the task.
&lt;/p&gt;

&lt;p&gt;
One might need this functionality to configure Emacs to automatically find installation paths of the other tools. For example, I use it to get the git installation path to configure Magit properly.
&lt;/p&gt;

&lt;p&gt;
Although I needed to query only string values (&lt;code&gt;REG_SZ&lt;/code&gt;), there is support for the other registry value types as well. The provided code uses standard &lt;code&gt;reg.exe&lt;/code&gt; command line utility to read values from the registry.
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-elisp&quot;&gt;(&lt;span class=&quot;org-keyword&quot;&gt;defun&lt;/span&gt; &lt;span class=&quot;org-function-name&quot;&gt;win-reg-read&lt;/span&gt; (regkey &lt;span class=&quot;org-type&quot;&gt;&amp;amp;optional&lt;/span&gt; value access-64-bit)
  &lt;span class=&quot;org-doc&quot;&gt;&quot;Read a value in the Windows registry. If the value does not exist, it returns nil. For an empty REG_BINARY value it returns T.&quot;&lt;/span&gt;
  (&lt;span class=&quot;org-keyword&quot;&gt;when&lt;/span&gt; (string-equal system-type &lt;span class=&quot;org-string&quot;&gt;&quot;windows-nt&quot;&lt;/span&gt;)
    (&lt;span class=&quot;org-keyword&quot;&gt;let*&lt;/span&gt; ((regkey (encode-coding-string regkey locale-coding-system))
           (value (&lt;span class=&quot;org-keyword&quot;&gt;and&lt;/span&gt; value (encode-coding-string value locale-coding-system)))
           (reg-exe (concat (getenv &lt;span class=&quot;org-string&quot;&gt;&quot;WinDir&quot;&lt;/span&gt;) &lt;span class=&quot;org-string&quot;&gt;&quot;\\System32\\reg.exe&quot;&lt;/span&gt;))
           (bits-64-param (&lt;span class=&quot;org-keyword&quot;&gt;if&lt;/span&gt; access-64-bit
                              &lt;span class=&quot;org-string&quot;&gt;&quot;/reg:64&quot;&lt;/span&gt;
                            &lt;span class=&quot;org-string&quot;&gt;&quot;/reg:32&quot;&lt;/span&gt;))
           (reg-value (&lt;span class=&quot;org-keyword&quot;&gt;let&lt;/span&gt; ((output (&lt;span class=&quot;org-keyword&quot;&gt;with-output-to-string&lt;/span&gt;
                                      (&lt;span class=&quot;org-keyword&quot;&gt;with-current-buffer&lt;/span&gt;
                                          standard-output
                                        (&lt;span class=&quot;org-keyword&quot;&gt;if&lt;/span&gt; value
                                            (process-file reg-exe nil t nil
                                                          &lt;span class=&quot;org-string&quot;&gt;&quot;query&quot;&lt;/span&gt;
                                                          regkey
                                                          &lt;span class=&quot;org-string&quot;&gt;&quot;/v&quot;&lt;/span&gt;
                                                          value
                                                          bits-64-param)
                                          (process-file reg-exe nil t nil
                                                        &lt;span class=&quot;org-string&quot;&gt;&quot;query&quot;&lt;/span&gt;
                                                        regkey
                                                        &lt;span class=&quot;org-string&quot;&gt;&quot;/ve&quot;&lt;/span&gt;
                                                        bits-64-param))))))
                        (set-text-properties 0 (length output) nil output)
                        output)))
      (&lt;span class=&quot;org-keyword&quot;&gt;let*&lt;/span&gt; ((lines (split-string reg-value &lt;span class=&quot;org-string&quot;&gt;&quot;\n&quot;&lt;/span&gt; nil nil))
             (result-line (nth 2 lines)))
        (&lt;span class=&quot;org-keyword&quot;&gt;when&lt;/span&gt; (&amp;gt; (length lines) 4)
          (&lt;span class=&quot;org-keyword&quot;&gt;let*&lt;/span&gt; ((result-line (&lt;span class=&quot;org-keyword&quot;&gt;if&lt;/span&gt; value &lt;span class=&quot;org-comment-delimiter&quot;&gt;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;skip value name
&lt;/span&gt;                                  (cl-subseq result-line (+ 8 (length value)))
                                (replace-regexp-in-string &lt;span class=&quot;org-string&quot;&gt;&quot;^[ ]+[&lt;/span&gt;&lt;span class=&quot;org-string&quot;&gt;&lt;span class=&quot;org-warning&quot;&gt;\&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;org-string&quot;&gt;(][&lt;/span&gt;&lt;span class=&quot;org-string&quot;&gt;&lt;span class=&quot;org-negation-char&quot;&gt;^&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;org-string&quot;&gt;&lt;span class=&quot;org-warning&quot;&gt;\&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;org-string&quot;&gt;)]+[&lt;/span&gt;&lt;span class=&quot;org-string&quot;&gt;&lt;span class=&quot;org-warning&quot;&gt;\&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;org-string&quot;&gt;)][ ]+&quot;&lt;/span&gt; &lt;span class=&quot;org-comment-delimiter&quot;&gt;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;default value
&lt;/span&gt;                                                          &lt;span class=&quot;org-string&quot;&gt;&quot;&quot;&lt;/span&gt;
                                                          result-line)))
                 (tokens (split-string result-line &lt;span class=&quot;org-string&quot;&gt;&quot;    &quot;&lt;/span&gt; t))
                 (type-string (car tokens)) &lt;span class=&quot;org-comment-delimiter&quot;&gt;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;get registry value type
&lt;/span&gt;                 (result (cl-subseq result-line (+ 4 (length type-string))))) &lt;span class=&quot;org-comment-delimiter&quot;&gt;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;get registry value
&lt;/span&gt;            &lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;decode the registry value string into a lisp object
&lt;/span&gt;            (&lt;span class=&quot;org-keyword&quot;&gt;cond&lt;/span&gt;
             ((&lt;span class=&quot;org-keyword&quot;&gt;or&lt;/span&gt; (string-equal type-string &lt;span class=&quot;org-string&quot;&gt;&quot;REG_DWORD&quot;&lt;/span&gt;)
                  (string-equal type-string &lt;span class=&quot;org-string&quot;&gt;&quot;REG_QWORD&quot;&lt;/span&gt;))
              (string-to-number (cl-subseq result 2) 16))
             ((&lt;span class=&quot;org-keyword&quot;&gt;or&lt;/span&gt; (string-equal type-string &lt;span class=&quot;org-string&quot;&gt;&quot;REG_SZ&quot;&lt;/span&gt;)
                  (string-equal type-string &lt;span class=&quot;org-string&quot;&gt;&quot;REG_EXPAND_SZ&quot;&lt;/span&gt;))
              result)
             ((string-equal type-string &lt;span class=&quot;org-string&quot;&gt;&quot;REG_MULTI_SZ&quot;&lt;/span&gt;)
              (split-string result (regexp-quote &lt;span class=&quot;org-string&quot;&gt;&quot;\\0&quot;&lt;/span&gt;) t)) &lt;span class=&quot;org-comment-delimiter&quot;&gt;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;will not work if there are &apos;&lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;&lt;span class=&quot;org-constant&quot;&gt;\0&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;&apos; sequences in the string
&lt;/span&gt;             ((string-equal type-string &lt;span class=&quot;org-string&quot;&gt;&quot;REG_BINARY&quot;&lt;/span&gt;)
              (&lt;span class=&quot;org-keyword&quot;&gt;let&lt;/span&gt; ((res)
                    (pos 0)
                    (size (/ (length result) 2)))
                (&lt;span class=&quot;org-keyword&quot;&gt;if&lt;/span&gt; (zerop size)
                    t &lt;span class=&quot;org-comment-delimiter&quot;&gt;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;value is present, but empty
&lt;/span&gt;                  (&lt;span class=&quot;org-keyword&quot;&gt;progn&lt;/span&gt;
                    (&lt;span class=&quot;org-keyword&quot;&gt;dotimes&lt;/span&gt; (i size)
                      (&lt;span class=&quot;org-keyword&quot;&gt;push&lt;/span&gt; (string-to-number (cl-subseq result pos (+ pos 2)) 16) res)
                      (&lt;span class=&quot;org-keyword&quot;&gt;incf&lt;/span&gt; pos 2))
                    (reverse res)))))
             (t nil))))))))
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
The function above accepts three arguments:
&lt;/p&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;Registry key name;&lt;/li&gt;
&lt;li&gt;Registry value name (optional). If omitted, the default value of the registry key is queried;&lt;/li&gt;
&lt;li&gt;The last parameter helps to handle registry virtualisation on 64-bit versions of Windows. If true, it queries the 64-bit branch of the registry, 32-bit one otherwise.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
The code returns the value on success, &lt;code&gt;NIL&lt;/code&gt; otherwise. For values, which by their nature hold multiple data items (&lt;code&gt;REG_MULTISTRING_SZ&lt;/code&gt;, &lt;code&gt;REG_BINARY&lt;/code&gt;) the lists of values are returned.
&lt;/p&gt;

&lt;p&gt;
&lt;b&gt;N.B.&lt;/b&gt;
&lt;i&gt;Eli Zaretskii &lt;a href=&quot;https://www.reddit.com/r/emacs/comments/b9wh2n/querying_windows_registry_from_emacs_lisp/ek8ttbq?utm_source=share&amp;amp;utm_medium=web2x&quot;&gt;pointed out&lt;/a&gt; that there were some problems with handling text encodings in the older version of the code. Hopefully, they are fixed now.&lt;/i&gt;
&lt;/p&gt;
&lt;div id=&quot;outline-container-org8c4f2c4&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org8c4f2c4&quot;&gt;Limitations&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org8c4f2c4&quot;&gt;
&lt;p&gt;
I should make a couple of notes about accessing the multi-string (&lt;code&gt;REG_MULTISTRING_SZ&lt;/code&gt;) values and binary values (&lt;code&gt;REG_BINARY&lt;/code&gt;). The &lt;code&gt;reg.exe&lt;/code&gt; utility reports information for multi-string values in such a way that the strings are separated by the &lt;code&gt;&quot;\0&quot;&lt;/code&gt; sequence. If there is this sequence somewhere in the data the code below will return incorrect results.
&lt;/p&gt;

&lt;p&gt;
Empty binary registry values are reported in a somewhat weird way: the code returns T for them.
&lt;/p&gt;

&lt;p&gt;
I doubt that these limitations would bite you in practice.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org2579276&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org2579276&quot;&gt;Dealing with Registry Virtualisation&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org2579276&quot;&gt;
&lt;p&gt;
On 64-bit versions of Windows, the access to some registry keys is &lt;a href=&quot;https://docs.microsoft.com/en-us/windows/desktop/sysinfo/registry-virtualization&quot;&gt;virtualised&lt;/a&gt; for 32-bit applications. As many applications exist in both 32-bit and 64-bit variants often it makes sense to check for both values in the registry.
&lt;/p&gt;

&lt;p&gt;
The code below does just that. On 64-bit versions of Windows, it tries to query value in the 64-bit section of the registry at first and, if it is absent, it tries to query the 32-bit one. I guess that in most cases it is what you want.
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-elisp&quot;&gt;(&lt;span class=&quot;org-keyword&quot;&gt;defun&lt;/span&gt; &lt;span class=&quot;org-function-name&quot;&gt;win-reg-read-64-or-32&lt;/span&gt; (regkey &lt;span class=&quot;org-type&quot;&gt;&amp;amp;optional&lt;/span&gt; value)
  &lt;span class=&quot;org-doc&quot;&gt;&quot;Read a value in the Windows registry.
   If the value does not exist, it returns nil.
   Checks both 32-bit and 64-nit keys,
   considers system bitness when searching for a value.&quot;&lt;/span&gt;
  (&lt;span class=&quot;org-keyword&quot;&gt;let&lt;/span&gt; ((check (getenv &lt;span class=&quot;org-string&quot;&gt;&quot;ProgramW6432&quot;&lt;/span&gt;)))
    (&lt;span class=&quot;org-keyword&quot;&gt;if&lt;/span&gt; (&lt;span class=&quot;org-keyword&quot;&gt;or&lt;/span&gt; (null check) (zerop (length check)))
        (win-reg-read regkey value nil) &lt;span class=&quot;org-comment-delimiter&quot;&gt;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;32-bit Windows
&lt;/span&gt;      (&lt;span class=&quot;org-keyword&quot;&gt;or&lt;/span&gt; (win-reg-read regkey value t) &lt;span class=&quot;org-comment-delimiter&quot;&gt;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;64-bit Windows
&lt;/span&gt;          (win-reg-read regkey value nil)))))
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org70b08f2&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org70b08f2&quot;&gt;A Couple of Examples&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org70b08f2&quot;&gt;
&lt;p&gt;
You might try to get the Git For Windows installation path this way:
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-elisp&quot;&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;Installation Path
&lt;/span&gt;(win-reg-read-64-or-32 &lt;span class=&quot;org-string&quot;&gt;&quot;HKLM\\SOFTWARE\\GitForWindows&quot;&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;InstallPath&quot;&lt;/span&gt;)
&lt;span class=&quot;org-string&quot;&gt;&quot;C:\\Tools\\Git&quot;&lt;/span&gt;
&lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;Git core. Magit Expects it to be in the EXEC-PATH
&lt;/span&gt;(win-reg-read-64-or-32 &lt;span class=&quot;org-string&quot;&gt;&quot;HKLM\\SOFTWARE\\GitForWindows&quot;&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;LibexecPath&quot;&lt;/span&gt;)
&lt;span class=&quot;org-string&quot;&gt;&quot;C:\\Tools\\Git\\mingw64\\libexec\\git-core&quot;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
The same thing for LibreOffice (useful if you want to configure exporting org-mode files to &lt;code&gt;ODT&lt;/code&gt;):
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-elisp&quot;&gt;(win-reg-read-64-or-32 &lt;span class=&quot;org-string&quot;&gt;&quot;HKEY_LOCAL_MACHINE\\SOFTWARE\\LibreOffice\\UNO\\InstallPath&quot;&lt;/span&gt;)
&lt;span class=&quot;org-string&quot;&gt;&quot;C:\\Program Files\\LibreOffice\\program&quot;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
You could obtain the Arduino Integrated Development Environment installation path in a similar way:
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-elisp&quot;&gt;(win-reg-read-64-or-32 &lt;span class=&quot;org-string&quot;&gt;&quot;HKEY_LOCAL_MACHINE\\SOFTWARE\\Arduino&quot;&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;Install_Dir&quot;&lt;/span&gt;)
&lt;span class=&quot;org-string&quot;&gt;&quot;C:\\Tools\\Arduino&quot;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
I hope you got the idea. Not every application keeps its installation path in the registry though, but many do. In any case you should do your research using the Windows Registry Editor.
&lt;/p&gt;

&lt;p&gt;
Off course you could use this code not only for the purpose of querying of the installation paths. I believe that the ability to read registry values from within Emacs makes it possible to configure it in
 such a way that it would barely need any tailoring the configuration for the specific machine.
&lt;/p&gt;

&lt;p&gt;
I hope you will find the code provided above to be useful or, at least, interesting.
&lt;/p&gt;

&lt;p&gt;
&lt;b&gt;P.S.&lt;/b&gt; Future versions of Emacs &lt;a href=&quot;http://git.savannah.gnu.org/cgit/emacs.git/commit/?id=5be83e343f9&quot;&gt;will directly support reading from registry&lt;/a&gt;. There are a couple of limitations though. Thanks to &lt;a href=&quot;https://www.reddit.com/r/emacs/comments/b9wh2n/querying_windows_registry_from_emacs_lisp/ek7ry21?utm_source=share&amp;amp;utm_medium=web2x&quot;&gt;skeeto&lt;/a&gt; for pointing out.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
				
				<pubDate>Fri, 05 Apr 2019 00:00:00 +0300</pubDate>
				<link>https://chaoticlab.io/emacs-win-reg/</link>
				<guid isPermaLink="true">https://chaoticlab.io/emacs-win-reg/</guid>
			</item>
		
			<item>
				<title>Fixing Sleep Mode Issues in Windows 10 (8.1/8) by Disabling InstantGo Mode</title>
				
				
					<description>&lt;p&gt;
Recently I have encountered a problem while using a new laptop - sleep mode did not work reliably. Sleep mode is an important feature for me, so this state of affairs was not acceptable. The fix was rather illogical and it is impossible to accomplish via settings in the graphical user interface tools provided by the Windows operating systems. If you have newer hardware and ever encountered the issues when your Windows-based laptop will not go into sleep mode or will not wake up reliably, or you would put your laptop into sleep mode only to find two hours later that it is active and hot in your backpack - please, continue reading. Probably I have a solution for you worth investigating.
&lt;/p&gt;

&lt;p&gt;
If you haven&apos;t encountered any problems with sleep mode on your hardware - this article is not for you. Otherwise, feel free to continue, but remember that as Windows-powered hardware is diverse and it is impossible to provide a fix which would work reliably for anyone. Moreover, this kind of problems might be a result of failing hardware or buggy drivers. &lt;b&gt;Please, keep it in mind and proceed at your own risk!&lt;/b&gt; Caveat Lector.
&lt;/p&gt;
&lt;div id=&quot;outline-container-org789b3c1&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org789b3c1&quot;&gt;Background Information&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org789b3c1&quot;&gt;
&lt;p&gt;
After some research, I &lt;a href=&quot;https://techjourney.net/how-to-disable-connected-standby-instantgo-in-windows-10-8-1-8/&quot;&gt;found&lt;/a&gt; a solution. On my laptop the problem turned out to be in &lt;b&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/InstantGo&quot;&gt;InstantGo mode&lt;/a&gt;&lt;/b&gt; (formerly named as &lt;b&gt;Connected Standby&lt;/b&gt;). This mode is available on newer hardware and allows to put it in a less power consuming mode while disabling some of the internal devices in a way very similar to how smart-phones and tablets do. It should be noted that network connections remain active so a user still would not miss any notifications in programs like Skype, Facebook Messenger, Steam, mail client, etc. This is why this mode used to be named as Connected Standby.
&lt;/p&gt;

&lt;p&gt;
This mode might look great on paper, but the fact is that laptop hardware significantly differs from the hardware of hand-held devices. A quick search revealed that I am not the only one who have experienced similar problems. There were users, who reported similar problems &lt;a href=&quot;https://forums.windowssecrets.com/showthread.php/180286-quot-Sleep-of-Death-quot-on-Surface-Book-What-the-Problem-Is-and-How-Microsoft-Should-Resolve-It&quot;&gt;even on the hardware which was designed by Microsoft&lt;/a&gt; (aka Sleep of Death). There is no doubt that such a mode might be useful for someone, but I cannot understand two things about it:
&lt;/p&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;Why it is enabled by default?&lt;/li&gt;
&lt;li&gt;Why there is no obvious way to configure it?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
I think that here, by trying to enforce this mode by default instead of &quot;classical&quot; sleep mode, Microsoft made a poor decision. When you sleep, you are not expected to react to any external events, right? So should your laptop, otherwise, this mode cannot be named as &quot;sleep mode&quot; any more as it makes no sense.
&lt;/p&gt;

&lt;p&gt;
So, if InstantGo mode is not reliable for you, you might want to try to disable it. Doing so will bring the &quot;classical&quot; sleep mode back. At least on my hardware, it works reliably and it never failed. The fact that there is no method to easily disable InstantGo mode further complicates the matter.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgfe91d2a&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgfe91d2a&quot;&gt;The Possible Fix&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgfe91d2a&quot;&gt;
&lt;p&gt;
If you are tech-savvy please go ahead and read &lt;a href=&quot;https://techjourney.net/how-to-disable-connected-standby-instantgo-in-windows-10-8-1-8/&quot;&gt;this article&lt;/a&gt; (by the way, I have registry files to &lt;a href=&quot;/data/win-sleepmode-fix/instantgo-disable.reg&quot;&gt;disable&lt;/a&gt; and &lt;a href=&quot;/data/win-sleepmode-fix/instantgo-enable.reg&quot;&gt;enable&lt;/a&gt; InstantGo). If you are not, please continue reading because I have detailed instruction for you:
&lt;/p&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;Open the Start Menu (press the &lt;code&gt;Win&lt;/code&gt; button on your keyboard) and start typing &lt;code&gt;regedit.exe&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;org-center&quot;&gt;

&lt;div id=&quot;org46027a6&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/win-sleepmode-fix/01.png&quot; alt=&quot;01.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;Find the &lt;code&gt;regedit.exe&lt;/code&gt; in the search results, click on it with the right mouse button, choose &lt;b&gt;&quot;Run as Administrator&quot;&lt;/b&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;org-center&quot;&gt;

&lt;div id=&quot;org88ff1c4&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/win-sleepmode-fix/02.png&quot; alt=&quot;02.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;A confirmation window might appear (it depends on your system&apos;s configuration). It might be required to enter the administrator&apos;s account password here. Enter it, if it is required, and answer affirmatively.&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;org-center&quot;&gt;

&lt;div id=&quot;org6ad3e8a&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/win-sleepmode-fix/03.png&quot; alt=&quot;03.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;The &lt;b&gt;&quot;Registry Editor&quot;&lt;/b&gt; window should appear.&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;org-center&quot;&gt;

&lt;div id=&quot;org5295e32&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/win-sleepmode-fix/04.png&quot; alt=&quot;04.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;Navigate to the following registry key:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
&lt;code&gt;HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Power&lt;/code&gt;.
&lt;/p&gt;

&lt;p&gt;
Find the &lt;code&gt;CsEnabled&lt;/code&gt; registry value. Please remember to what it is set (usually it is set to &lt;code&gt;1&lt;/code&gt;).
&lt;/p&gt;

&lt;div class=&quot;org-center&quot;&gt;

&lt;div id=&quot;org0a9b266&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/win-sleepmode-fix/05.png&quot; alt=&quot;05.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;Double-click on the &lt;code&gt;CsEnabled&lt;/code&gt; registry value. Small windows with the title &lt;b&gt;&quot;Edit DWORD (32-bit) value&quot;&lt;/b&gt; should appear. Set the value to &lt;code&gt;0&lt;/code&gt; and click &lt;b&gt;&quot;OK&quot;&lt;/b&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;org-center&quot;&gt;

&lt;div id=&quot;orgd9a0c00&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/win-sleepmode-fix/06.png&quot; alt=&quot;06.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;


&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;b&gt;Reboot the computer.&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
Hopefully, after performing the steps written above, sleep mode on your laptop should be more reliable than it was before. If it isn&apos;t, please repeat the steps but set the &lt;code&gt;CsEnabled&lt;/code&gt; back to its original value - probably InstantGo was not the cause of your problems with the sleep mode.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgdafc623&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgdafc623&quot;&gt;Conclusion&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgdafc623&quot;&gt;
&lt;p&gt;
In general, I orient my blog towards programmers, IT personnel and, to a lesser extent, tech-savvy users. Arguably, tracking down this problem was difficult and I realised that probably there are less advanced users who might encounter the same issue but lack the necessary knowledge and research skills to figure out what is going on. This article is my humble attempt to improve the situation.
&lt;/p&gt;

&lt;p&gt;
I believe that it is a major issue because under some circumstances it might lead to damaged hardware (e.g. when you often carry your laptop in a bag or a backpack).
&lt;/p&gt;

&lt;p&gt;
I think that Microsoft targeted the InstantGo (Connected Standby) mostly towards less tech-savvy users who expect their computer to perform some tasks even when it is in the sleep mode (as smart-phones and tablets do), but, I believe, it is safe to say that in this particular case the cure was worse than the illness.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
				
				<pubDate>Thu, 14 Mar 2019 00:00:00 +0200</pubDate>
				<link>https://chaoticlab.io/posts/win-sleepmode-fix/</link>
				<guid isPermaLink="true">https://chaoticlab.io/posts/win-sleepmode-fix/</guid>
			</item>
		
			<item>
				<title>MSI Installer for GNU Emacs</title>
				
				
					<description>&lt;p&gt;
If you use GNU Emacs on Windows you might have noticed that on &lt;a href=&quot;https://www.gnu.org/software/emacs/&quot;&gt;the official site&lt;/a&gt; the only download option for this platform is a ZIP-archive, no installer is provided. It is, of course, a very compatible option and, probably, most of the GNU Emacs users can integrate it with the operating system manually. Nevertheless, I think that there is no need to make it harder than it should be. It would be great if there was an installer.
&lt;/p&gt;

&lt;p&gt;
Considering that I &lt;i&gt;managed&lt;/i&gt; to built an installer using open source &lt;a href=&quot;http://wixtoolset.org&quot;&gt;WiX Toolset&lt;/a&gt; for the other project which I help to maintain (&lt;a href=&quot;https://github.com/sharplispers/cormanlisp&quot;&gt;Corman Lisp&lt;/a&gt;), I decided to build an MSI installer for GNU Emacs as well. It was rather easy to adapt existing code for the new project.
&lt;/p&gt;

&lt;p&gt;
This project is my humble contribution to the GNU Emacs community.
&lt;/p&gt;

&lt;p&gt;
You can find all the &lt;a href=&quot;https://github.com/arbv/emacs-msi-installer&quot;&gt;sources&lt;/a&gt; on GitHub as well as the &lt;a href=&quot;https://github.com/arbv/emacs-msi-installer/releases&quot;&gt;pre-built installers&lt;/a&gt; for the latest release of GNU Emacs. The sources are in the public domain (&lt;a href=&quot;https://creativecommons.org/share-your-work/public-domain/cc0/&quot;&gt;CC0&lt;/a&gt;). The repository also includes the build instructions. The provided installers bundle official, unmodified GNU Emacs binaries for Windows.
&lt;/p&gt;

&lt;p&gt;
The availability of an MSI installer for an application makes it easier to deploy in some environments.
&lt;/p&gt;

&lt;p&gt;
This project addresses not only the GNU Emacs&apos;s installation experience. It might be interesting to the developers which are facing the task of building an MSI installer. It seems that it is not easy to stumble upon a complete Windows Installer XML project. If it is the case, you might want to have a look at the &lt;a href=&quot;https://github.com/sharplispers/cormanlisp/tree/master/installer&quot;&gt;Corman Lisp installer&lt;/a&gt; project which is very similar yet somewhat more complex.
&lt;/p&gt;

&lt;p&gt;
Please note that I am not a Windows Installer guru, but I do eat my own dog food, so this installer was tested at least by one person before the release.
&lt;/p&gt;

&lt;p&gt;
Enjoy!
&lt;/p&gt;

&lt;div class=&quot;org-center&quot;&gt;

&lt;div id=&quot;orgf36b118&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-msi/01.png&quot; alt=&quot;01.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org311ba66&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-msi/02.png&quot; alt=&quot;02.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;orga2cee2b&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-msi/03.png&quot; alt=&quot;03.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;orgd872cdf&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-msi/04.png&quot; alt=&quot;04.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;orgc1616dc&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-msi/05.png&quot; alt=&quot;05.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;orgf76ea0a&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-msi/06.png&quot; alt=&quot;06.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
				
				<pubDate>Sat, 05 Jan 2019 00:00:00 +0200</pubDate>
				<link>https://chaoticlab.io/emacs/wix/update/2019/01/05/emacs_installer.html</link>
				<guid isPermaLink="true">https://chaoticlab.io/emacs/wix/update/2019/01/05/emacs_installer.html</guid>
			</item>
		
			<item>
				<title>Personal Notes on Corman Lisp 3.1 Release</title>
				
				
					<description>&lt;p&gt;
Today, as I &lt;a href=&quot;https://github.com/sharplispers/cormanlisp/issues/40&quot;&gt;announced&lt;/a&gt; earlier, the Corman Lisp 3.1 &lt;a href=&quot;https://github.com/sharplispers/cormanlisp/issues/41&quot;&gt;has been released&lt;/a&gt; after more than a decade-long break. Somehow it happened that I am one of the active maintainers of the Corman Lisp, so, I think, it might be appropriate to make a post on this site about how I became a maintainer, what motivated me to work on it and why I believe it is important. You will not find the &lt;a href=&quot;https://github.com/sharplispers/cormanlisp/blob/corman-3_1/documentation/CormanLisp_3_1_Release_notes.txt&quot;&gt;release notes&lt;/a&gt; here because I think it is not the right place to post them. If you have at least mild interest in this implementation, I would suggest you to continue reading.
&lt;/p&gt;
&lt;div id=&quot;outline-container-org12533bc&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org12533bc&quot;&gt;How I became a maintainer&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org12533bc&quot;&gt;
&lt;p&gt;
Some time ago I stumbled upon a non-supported Common Lisp implementation on Github, Corman Lisp. It was in a bad shape - it did not work well on the modern, 64-bit versions of Windows and the project&apos;s solution needed a bit of cleaning. I should note that I am genuinely interested in Lisp, compilers, programming languages and their runtime environments. Additionally to that, I possess some knowledge of Windows application programming interface, a skill which not every system programmer, interested in open source development, seems to have. The project seemed to fit my interests well, so I decided to look at it more closely.
&lt;/p&gt;

&lt;p&gt;
Three days later I fixed a very annoying bug which made it possible to use the software on the 64-bit versions of Windows and things started to look even more interesting: it turned out I can work on such a complex system and make important changes to it. I should note that this was kind of an act of insight, to this very day I do not understand how I managed to fix it. Later Roger Corman, the original author, contacted me via Github, &lt;a href=&quot;https://github.com/sharplispers/cormanlisp/commit/21569836c8cb5c6cde6cdc342867c7f4cb7d02c7#commitcomment-20257863&quot;&gt;thanked for fixing this&lt;/a&gt; and returned to the project.
&lt;/p&gt;

&lt;p&gt;
Additionally to that, I understood that this project is very important from the educational perspective. This is a fairly complete Common Lisp implementation which is easy to study and might give one interesting inside on how to build a working, high-performance environment for a dynamic programming language which includes, among other things, a native code compiler and a garbage collector. I realised that if I am able to understand how it works, then someone else can do that too. For me, it was a major turning point. Then I contacted &lt;a href=&quot;https://www.xach.com/&quot;&gt;Zachary P. Beane&lt;/a&gt; (a.k.a. Xach) who gave me the write permissions to the repository and I became a co-maintainer of the Corman Lisp.
&lt;/p&gt;

&lt;p&gt;
Later Luis Cervantes joined the project and made &lt;a href=&quot;https://github.com/sharplispers/cormanlisp/commits?author=Luis-Cervantes&quot;&gt;a lot of valuable contributions&lt;/a&gt;.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org6b407b2&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org6b407b2&quot;&gt;Why I think that maintaining Corman Lisp is important&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org6b407b2&quot;&gt;
&lt;p&gt;
There are multiple reasons why I believe that maintaining Corman Lisp is important. I am going to describe the main ones in more detail.
&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org98c0c36&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org98c0c36&quot;&gt;It is a good implementation for newbies&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org98c0c36&quot;&gt;
&lt;p&gt;
In my opinion, Common Lisp is not a hard programming language to learn, especially comparing it to such a language as C++. What is hard is getting the proper environment at the beginning. Here a potential newbie typically has the two general recommendations from the community.
&lt;/p&gt;

&lt;p&gt;
The first one is to use Emacs+SLIME+SBCL (or Clozure CL, &amp;#x2026;). I should say that this is what I, and most of the other Common Lisp programmers, use most of the time and for a reason: it is an incredibly powerful development environment, probably the best one among environments for the dynamic programming languages. On the other hand, it might be difficult to set up and Emacs might seem weird for a beginner. It takes some time to tame it. In fact, to manually configure Emacs as a Common Lisp development environment one should be familiar with another Lisp (Emacs Lisp).
&lt;/p&gt;

&lt;p&gt;
To overcome this issues a newbie must not lose the spark of interest from the very beginning. For someone, this experience might be overwhelmingly frustrating. It should be noted that such a user might be potentially a good programmer, but he or she just happens to have a somewhat different background. The fact that there are &lt;a href=&quot;https://portacle.github.io/&quot;&gt;some projects&lt;/a&gt; which bundle Emacs preconfigured as a development environment for Common Lisp lowers the entry bar somewhat, but it is not always enough.
&lt;/p&gt;

&lt;p&gt;
The second option is to use a freely available, proprietary, limited version of a commercial Common Lisp programming environment, be it &lt;a href=&quot;https://franz.com/downloads/clp/survey&quot;&gt;Allegro&lt;/a&gt; or &lt;a href=&quot;http://www.lispworks.com/downloads/&quot;&gt;LispWorks&lt;/a&gt;. Despite the limitations, this option is viable for a beginner who wants to try some Common Lisp if he or she does not mind the limitations. There is always an option to move to another development environment after the initial learning phase.
&lt;/p&gt;

&lt;p&gt;
From analysing the options above it becomes clear that there is a niche for an easy to install, open source Common Lisp implementation which provides a familiar environment for the most commonly used operating systems - Windows. The fact that Corman Lisp is one of the few implementations which have its own integrated development environment makes it a good candidate to fill the niche. Lowering the bar of entry is important, as it might help to attract more users to the Common Lisp. In my opinion, it is something which it desperately needs.
&lt;/p&gt;

&lt;p&gt;
I should say that lowering the entry bar for a beginner is one of my main motivations behind contributing to the project.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org398c54f&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org398c54f&quot;&gt;It has a lot of educational value&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org398c54f&quot;&gt;
&lt;p&gt;
One of the more interesting characteristics of the Corman Lisp is that it is incredibly compact, while it still provides all the major features of a Common Lisp. Its runtime, the Lisp kernel, is one of the most compact ones, yet it contains all the important parts of an efficient implementation of a dynamic programming language.
&lt;/p&gt;

&lt;p&gt;
The fact that I was able to start making important changes to it in a relatively short time says a lot.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org020993e&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org020993e&quot;&gt;It has unique features&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org020993e&quot;&gt;
&lt;p&gt;
Although there are few very good Common Lisp implementations available, both open source and proprietary, Corman Lisp has some features which are not always available elsewhere:
&lt;/p&gt;

&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;It can be used to create dynamic link libraries (DLLs). It is possible to develop the plug-ins to the existing applications on par with C.&lt;/li&gt;
&lt;li&gt;Corman Lisp kernel has the interfaces for integration into the other C++ applications as a scripting engine. It does not force you to write the whole application in Common Lisp.&lt;/li&gt;
&lt;li&gt;A Corman Lisp&apos;s heap image can be dumped and restored without restarting the process. There are not many implementations which allow this.&lt;/li&gt;
&lt;li&gt;It is possible to reuse C definitions directly from header files. It is very handy when building Lisp bindings to the C libraries.&lt;/li&gt;
&lt;li&gt;Corman Lisp is one of the few implementations which feature its own integrated development environment.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
The fact that Corman Lisp is 32-bit only limits its use cases. Nevertheless, it has a lot of interesting features which make it convenient in some cases where using other implementations is hard or even not possible.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org039c4c2&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org039c4c2&quot;&gt;It is a major achievement&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-org039c4c2&quot;&gt;
&lt;p&gt;
Probably Common Lisp has the highest number of implementations to the number of users ratio. It contrasts to most of the other dynamic programming languages which typically have one reference implementation. I think that it is a result of being defined through a standard which thoroughly describes the programming language rather than a sign of the simplicity of the language itself.
&lt;/p&gt;

&lt;p&gt;
Most of the implementations started as commercial products or their development was initially supported by a government because such a project typically requires a lot of effort and needs good financial support. This is a result of Lisp being a programming language which requires non-trivial programming techniques to be implemented efficiently. This fact alone makes any available Common Lisp implementation a valuable technical achievement.
&lt;/p&gt;

&lt;p&gt;
Corman Lisp is not an exception here. It is a bit different though, as it was mostly developed by one person. Taking into consideration how much effort it takes to develop a usable Common Lisp implementation, it is a very valuable achievement as doing it this way surely needed the different approaches. A curious individual might learn a lot from studying it, doing so reveals a lot about how to individually develop a non-trivial project.
&lt;/p&gt;

&lt;p&gt;
You might like a &lt;a href=&quot;https://www.youtube.com/watch?v=Jdf89uLcLNk&quot;&gt;video&lt;/a&gt; in which Roger Corman reveals his motivation behind starting the project as well as provides some technical details about it.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org07395ef&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org07395ef&quot;&gt;Conclusion&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org07395ef&quot;&gt;
&lt;p&gt;
After reading the information above you should understand why I think that maintaining Corman Lisp is important. I believe it is a good implementation which, as it was mentioned earlier, very compact and, thus, open for innovation and contributions. It surely has its downsides but it can be iteratively improved to a more usable state. It is also extremely easy to start working on.
&lt;/p&gt;

&lt;p&gt;
While working on it I gained interesting experience as doing so required some knowledge which I had no chance to gain anywhere else. As it turns out, there is no need to be a programming rock star to do meaningful work on a non-trivial project. When I started working on the project I did not know Lisp very well and now I am only moderately better.
&lt;/p&gt;

&lt;p&gt;
The fun continues and I am looking forward to what goes next!
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
				
				<pubDate>Sun, 30 Dec 2018 00:00:00 +0200</pubDate>
				<link>https://chaoticlab.io/lisp/update/2018/12/30/corman-3-1-release.html</link>
				<guid isPermaLink="true">https://chaoticlab.io/lisp/update/2018/12/30/corman-3-1-release.html</guid>
			</item>
		
			<item>
				<title>A Handmade External Antenna For a Mobile Modem or Router</title>
				
				
					<description>&lt;p&gt;
Recently I have completed my tiny DIY-project: an external antenna for a 3G modem/router so I decided to make a post to provide some additional details as well as to publish some photographs. You can find them at the end of the post.
&lt;/p&gt;

&lt;p&gt;
According to my measurements, the antenna gives the gain around 8-9 Db. I believe it is a good result: maximal theoretical gain of such an antenna is 10.5 Db. I wanted to make a portable variant that I can take with me in a case of travelling.
&lt;/p&gt;

&lt;p&gt;
The design of the antenna is well known here in Ukraine as well as in other ex-USSR countries. Its name is &apos;Kharchenko&apos;s antenna&apos; (&quot;антенна Харченко&quot; in Russian, &quot;антена Харченка&quot; in Ukrainian), named after a Soviet engineer who invented it. The article with the original design was published in edition #11 of a magazine &apos;Radio&apos; (&quot;Радио&quot; in Russian) in 1964. You can find the article on &lt;a href=&quot;http://radiowiki.ru/images/7/70/%D0%A0%D0%B0%D0%B4%D0%B8%D0%BE_1962_%D0%B3._%E2%84%9611.djvu&quot;&gt;page 50&lt;/a&gt;. By design, it is an (omni)&lt;a href=&quot;https://en.wikipedia.org/wiki/Directional_antenna&quot;&gt;directional antenna&lt;/a&gt;. An almost the same design, with minor differences, was &lt;a href=&quot;http://trevormarshall.com/biquad.htm&quot;&gt;popularised&lt;/a&gt; in the English-speaking part of the Internet by Trevor Marshall, so it is often named after him there (&apos;Trevor Marshall&apos;s antenna&apos;). Another very common name for it is &apos;Bi-Quad antenna.&apos;
&lt;/p&gt;

&lt;p&gt;
Originally, it was designed for receiving TV-signal, but with the development of the technologies, the base design was adapted for the new standards, e.g. Wi-Fi, CDMA, 3G (WCDMA) and so on. Indeed, I can remember this antenna being used for receiving TV-signal when I was a child. To this very day, it is one of the most practical designs for many applications. Here, in ex-USSR, its variant is often used for boosting Wi-Fi signal (&lt;a href=&quot;http://www.qrz.ru/schemes/contribute/antenns/wifi/bi-quad2.shtml&quot;&gt;an example&lt;/a&gt;). I believe it is one of the best designs for a portable antenna, as it is possible to fit all the parts in a compact case.
&lt;/p&gt;

&lt;p&gt;
One might wonder why I made an antenna for 3G in the times when the 4G is widely deployed? Well, here, in Ukraine, 4G has appeared only this year (yes, in 2018). 3G was introduced a couple of years earlier so it is more widely available: in the case, when you might need an external antenna, there are more chances to receive the 3G signal rather than 4G.
&lt;/p&gt;

&lt;p&gt;
Here I shall quote &lt;a href=&quot;https://en.wikipedia.org/wiki/William_Gibson&quot;&gt;William Gibson&lt;/a&gt;:
&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;
The future is already here — it&apos;s just not very evenly distributed.
&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
I am not complaining though, as it is better to have something later than never.
&lt;/p&gt;

&lt;p&gt;
If you are intrigued enough and want to make one for your own use, you have to do all the necessary calculations to make the antenna that is well tuned for a targeted radio frequency. Fortunately, there is an &lt;a href=&quot;https://play.google.com/store/apps/details?id=com.radioacoustick.cantennator&quot;&gt;Android application&lt;/a&gt;, named &apos;Cantennator&apos;, which can do all the necessary calculations for you. By the way, the application does support other antenna designs too. A real gem for an antenna geek!
&lt;/p&gt;

&lt;p&gt;
The author of the program has a &lt;a href=&quot;http://3g-aerial.biz/&quot;&gt;site&lt;/a&gt; (in Russian) which is dedicated to different antenna designs for numerous applications. The information on this site was invaluable.
&lt;/p&gt;

&lt;p&gt;
If you want to make an antenna for 4G, then you should know that 4G uses &lt;a href=&quot;https://en.wikipedia.org/wiki/MIMO&quot;&gt;MIMO&lt;/a&gt; so you will need two similar antennas or one, which naturally supports MIMO. In this case, &lt;a href=&quot;https://whirlpool.net.au/wiki/homemade_yagi&quot;&gt;&apos;Patch-Yagi&apos;&lt;/a&gt; antenna seems to be a better alternative, as you can connect two cables to them. Unfortunately, it is harder to make this one portable.
&lt;/p&gt;

&lt;p&gt;
I did not plan to publish a detailed guide on making the antenna. I believe it is rather easy to understand by looking at the provided photographs. Moreover, I think this approach would stimulate your creativity. For your convenience, I provided the list of the main parts and materials, which I used, as well as some recommendations. &lt;i&gt;Please keep in mind that I am not an expert on this topic though.&lt;/i&gt;
&lt;/p&gt;

&lt;p&gt;
You will need:
&lt;/p&gt;

&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;Around 1 meter of thick &lt;b&gt;copper wire&lt;/b&gt; (with the diameter of 2.5mm) for the vibrator. The aluminium one will do, but it is harder to solder.&lt;/li&gt;
&lt;li&gt;A &lt;b&gt;sheet of copper or aluminium&lt;/b&gt; for the reflector. I reused one from an empty aluminium can (from cider). In fact, any copper plated or aluminium plated material will do. If you have decided to follow my route, you might find &lt;a href=&quot;https://www.youtube.com/watch?v=38PWUyKqk9Q&quot;&gt;this video&lt;/a&gt; very useful. I should note that reflector is &lt;b&gt;not&lt;/b&gt; connected to the coaxial cable in any manner for this antenna. I have seen many similar antennas where it is, but, I believe, it is an error.&lt;/li&gt;
&lt;li&gt;A &lt;b&gt;set of connectors&lt;/b&gt;. I used the &lt;a href=&quot;https://en.wikipedia.org/wiki/BNC_connector&quot;&gt;BNC-connectors&lt;/a&gt;, but I would advise you to get &lt;a href=&quot;https://en.wikipedia.org/wiki/N_connector&quot;&gt;N-connectors&lt;/a&gt; instead because they are better suited for the task. &lt;i&gt;Try to avoid cheap connectors. Good connectors are vital for an antenna.&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;Around one meter of &lt;b&gt;5Ohm &lt;a href=&quot;https://en.wikipedia.org/wiki/Coaxial_cable&quot;&gt;coaxial cable&lt;/a&gt;&lt;/b&gt;. I used the thin RG-58 cable as I wanted the portable design, but ideally, you should use much thicker wire with the diameter at least 1cm, e.g. LMR-400 or RG-8. It especially makes sense if you want to make non-portable outdoors antenna. If you decided to use a thin cable for a portable variant, LMR-195 is better than RG-58. &lt;i&gt;If you need a cable, which is much lengthier than one meter, use a thick cable due to huge signal loss.&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;A &lt;b&gt;[[&lt;a href=&quot;https://en.wikipedia.org/wiki/Patch_cable&quot;&gt;https://en.wikipedia.org/wiki/Patch_cable&lt;/a&gt;]pigtail]]&lt;/b&gt; to connect the cable to a receiving device, e.g., 3G/4G modem or router. For example, the one I got is BNC to TS-9, but it depends on the device and, obviously, your choice of connectors. You might end-up with making the pigtail too. Avoid long pigtails due to signal loss. Ideally, it should be around 15cm, no more.&lt;/li&gt;
&lt;li&gt;A &lt;b&gt;case&lt;/b&gt;, which suits your design. I adapted a &lt;i&gt;thoroughly cleaned&lt;/i&gt; plastic can from the pickled herring.&lt;/li&gt;
&lt;li&gt;Optionally, a &lt;b&gt;stand&lt;/b&gt;. I adapted a small tripod for a camera or phone.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
As about the cost, I am not sure that buying a manufactured one costs significantly more, especially if you are going to buy the high-quality components. I do not care, because I made one for fun and buying something like an antenna is, basically, a hit-and-miss process. Moreover, I would always prefer a handmade thing to the one manufactured in China. Even if the last one looks better, the handmade one is less &lt;i&gt;deceitful&lt;/i&gt;.
&lt;/p&gt;

&lt;p&gt;
&lt;i&gt;(The images are clickable.)&lt;/i&gt;
&lt;/p&gt;
&lt;div class=&quot;org-center&quot;&gt;

&lt;div id=&quot;orgf41b77e&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/3g-ant/01.jpg&quot; alt=&quot;01.jpg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;orgc2f037a&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/3g-ant/02.jpg&quot; alt=&quot;02.jpg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;orgb95f48e&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/3g-ant/03.jpg&quot; alt=&quot;03.jpg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org5220966&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/3g-ant/04.jpg&quot; alt=&quot;04.jpg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org560c2d1&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/3g-ant/05.jpg&quot; alt=&quot;05.jpg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org194c357&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/3g-ant/06.jpg&quot; alt=&quot;06.jpg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org8925598&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/3g-ant/07.jpg&quot; alt=&quot;07.jpg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;orga266a83&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/3g-ant/08.jpg&quot; alt=&quot;08.jpg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org31f471d&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/3g-ant/09.jpg&quot; alt=&quot;09.jpg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org7759d51&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/3g-ant/10.jpg&quot; alt=&quot;10.jpg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
				
				<pubDate>Wed, 03 Oct 2018 00:00:00 +0300</pubDate>
				<link>https://chaoticlab.io/electronics/diy/update/2018/10/03/3g-antenna.html</link>
				<guid isPermaLink="true">https://chaoticlab.io/electronics/diy/update/2018/10/03/3g-antenna.html</guid>
			</item>
		
			<item>
				<title>Daemonize - a Tiny C Library for Programming the UNIX Daemons</title>
				
				
					<description>&lt;p&gt;
Whatever they say, writing System-V style UNIX daemons &lt;i&gt;is&lt;/i&gt; hard. One has to follow &lt;a href=&quot;http://man7.org/linux/man-pages/man7/daemon.7.html&quot;&gt;many rules&lt;/a&gt; to make a daemon process behave correctly on diverse UNIX flavours. Moreover, debugging such a code might be somewhat tricky. On the other hand, the process of daemon initialisation is rigid and well defined so the corresponding code has to be written and debugged once and later can be reused countless number of times.
&lt;/p&gt;

&lt;p&gt;
Developers of BSD UNIX were very aware of this, as there a C library function &lt;a href=&quot;https://www.freebsd.org/cgi/man.cgi?query=daemon&amp;amp;sektion=3&amp;amp;apropos=0&amp;amp;manpath=FreeBSD+11.2-RELEASE+and+Ports&quot;&gt;&lt;code&gt;daemon()&lt;/code&gt;&lt;/a&gt; was available starting from version 4.4. The function, although non-standard, is present on many UNIXes. Unfortunately, it does not follow all the required steps to reliably run a process in the background on systems which follow System-V semantics (e.g. Linux). The details are available at the corresponding &lt;a href=&quot;http://man7.org/linux/man-pages/man3/daemon.3.html&quot;&gt;Linux man page&lt;/a&gt;. The main problem here, as I understand it, is that &lt;code&gt;daemon()&lt;/code&gt; does not use the &lt;a href=&quot;http://thinkiii.blogspot.com/2009/12/double-fork-to-avoid-zombie-process.html&quot;&gt;double-forking technique&lt;/a&gt; to avoid the situation when &lt;a href=&quot;https://en.wikipedia.org/wiki/Zombie_process&quot;&gt;zombie processes&lt;/a&gt; appear.
&lt;/p&gt;

&lt;p&gt;
Whenever I encounter a problem like this one, I know it is time to write a tiny C library which solves it. This is exactly how &lt;a href=&quot;https://bitbucket.org/arbv/daemonize&quot;&gt;&apos;daemonize&apos;&lt;/a&gt; was born (&lt;a href=&quot;https://github.com/arbv/daemonize&quot;&gt;GitHub mirror&lt;/a&gt;). The library consists of only two files which are meant to be integrated into the source tree of your project. Recently I have updated the library and realised that it would be good to describe how to use it on this site.
&lt;/p&gt;

&lt;p&gt;
If for some reason you want to make a Windows service, I have a battle tested &lt;a href=&quot;https://bitbucket.org/arbv/foobar_service&quot;&gt;template code&lt;/a&gt; for you as well.
&lt;/p&gt;
&lt;div id=&quot;outline-container-org9b7a124&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org9b7a124&quot;&gt;System-V Daemon Initialisation Procedure&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org9b7a124&quot;&gt;
&lt;p&gt;
To make discussion clear we shall quote the steps which have to be performed during a daemon initialisation (according to &lt;a href=&quot;http://man7.org/linux/man-pages/man7/daemon.7.html&quot;&gt;daemon(7)&lt;/a&gt; manual page on Linux). I do it to demonstrate that this task is more tricky than one might expect.
&lt;/p&gt;

&lt;p&gt;
So, here we go:
&lt;/p&gt;

&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;Close all open file descriptors except standard input, output, and error (i.e. the first three file descriptors 0, 1, 2). This ensures that no accidentally passed file descriptor stays around in the daemon process. On Linux, this is best implemented by iterating through &lt;code&gt;/proc/self/fd&lt;/code&gt;, with a fallback of iterating from file descriptor 3 to the value returned by &lt;code&gt;getrlimit()&lt;/code&gt; for &lt;code&gt;RLIMIT_NOFILE&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Reset all signal handlers to their default. This is best done by iterating through the available signals up to the limit of &lt;code&gt;_NSIG&lt;/code&gt; and resetting them to &lt;code&gt;SIG_DFL&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Reset the signal mask using &lt;code&gt;sigprocmask()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Sanitize the environment block, removing or resetting environment variables that might negatively impact daemon runtime.&lt;/li&gt;
&lt;li&gt;Call &lt;code&gt;fork()&lt;/code&gt;, to create a background process.&lt;/li&gt;
&lt;li&gt;In the child, call &lt;code&gt;setsid()&lt;/code&gt; to detach from any terminal and create an independent session.&lt;/li&gt;
&lt;li&gt;In the child, call &lt;code&gt;fork()&lt;/code&gt; again, to ensure that the daemon can never re-acquire a terminal again.&lt;/li&gt;
&lt;li&gt;Call &lt;code&gt;exit()&lt;/code&gt; in the first child, so that only the second child (the actual daemon process) stays around. This ensures that the daemon process is re-parented to init/PID 1, as all daemons should be.&lt;/li&gt;
&lt;li&gt;In the daemon process, connect &lt;code&gt;/dev/null&lt;/code&gt; to standard input, output, and error.&lt;/li&gt;
&lt;li&gt;In the daemon process, reset the &lt;code&gt;umask&lt;/code&gt; to 0, so that the file modes passed to &lt;code&gt;open()&lt;/code&gt;, &lt;code&gt;mkdir()&lt;/code&gt; and suchlike directly control the access mode of the created files and directories.&lt;/li&gt;
&lt;li&gt;In the daemon process, change the current directory to the root directory (&lt;code&gt;/&lt;/code&gt;), in order to avoid that the daemon involuntarily blocks mount points from being unmounted.&lt;/li&gt;
&lt;li&gt;In the daemon process, write the daemon PID (as returned by &lt;code&gt;getpid()&lt;/code&gt;) to a PID file, for example &lt;code&gt;/run/foobar.pid&lt;/code&gt; (for a hypothetical daemon &quot;foobar&quot;) to ensure that the daemon cannot be started more than once. This must be implemented in race-free fashion so that the PID file is only updated when it is verified at the same time that the PID previously stored in the PID file no longer exists or belongs to a foreign process.&lt;/li&gt;
&lt;li&gt;In the daemon process, drop privileges, if possible and applicable.&lt;/li&gt;
&lt;li&gt;From the daemon process, notify the original process started that initialization is complete. This can be implemented via an unnamed pipe or similar communication channel that is created before the first &lt;code&gt;fork()&lt;/code&gt; and hence available in both the original and the daemon process.&lt;/li&gt;
&lt;li&gt;Call &lt;code&gt;exit()&lt;/code&gt; in the original process. The process that invoked the daemon must be able to rely on that this &lt;code&gt;exit()&lt;/code&gt; happens after initialization is complete and all external communication channels are established and accessible.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
The discussed library does most of the above-mentioned initialisation steps as it becomes immediately evident that implementation details for some of them heavily dependent on the internal logic of an application itself, so it is not possible to implement them in a universal library. I believe it is not a flaw, though, as the missed parts are safe to implement in an application code.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orga15a788&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orga15a788&quot;&gt;The Library&apos;s Application Programming Interface&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orga15a788&quot;&gt;
&lt;p&gt;
The generic programming interface was loosely modelled after above-mentioned BSD&apos;s &lt;a href=&quot;https://www.freebsd.org/cgi/man.cgi?query=daemon&amp;amp;sektion=3&amp;amp;apropos=0&amp;amp;manpath=FreeBSD+11.2-RELEASE+and+Ports&quot;&gt;daemon()&lt;/a&gt; function. The library provides two user available functions (one is, in fact, implemented on top of the other) as well as a set of flags to control a daemon creation behaviour.
&lt;/p&gt;

&lt;p&gt;
The first one is:
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-C&quot;&gt;&lt;span class=&quot;org-type&quot;&gt;pid_t&lt;/span&gt; &lt;span class=&quot;org-function-name&quot;&gt;daemonize&lt;/span&gt;(&lt;span class=&quot;org-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;flags&lt;/span&gt;);
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
The function might be considered the portable substitution to the BSD&apos;s &lt;code&gt;daemon()&lt;/code&gt; function.
&lt;/p&gt;

&lt;p&gt;
Its only argument is the bit-mask &lt;code&gt;flags&lt;/code&gt; which control different aspects of the daemon creation.
&lt;/p&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;code&gt;DMN_DEFAULT&lt;/code&gt; - Create daemon with default daemonization parameters (close existing file descriptors, reset signal handlers, change the current directory to /, set umask to 0).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;DMN_NO_CLOSE&lt;/code&gt; - Do not close existing file descriptors and do not redirect standard file descriptors to /dev/null.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;DMN_KEEP_SIGNAL_HANDLERS&lt;/code&gt; - Do not reset signal handlers to their defaults.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;DMN_NO_CHDIR&lt;/code&gt; - Do not change the current directory of the daemon to /.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;DMN_NO_UMASK&lt;/code&gt; - Do not set umask to 0.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
One can use bit-or operator &lt;code&gt;|&lt;/code&gt; to pass multiple flags at once, as it is often the case in C programming language.
&lt;/p&gt;

&lt;p&gt;
This function, generally, follows &lt;code&gt;fork()&lt;/code&gt; semantics.  By default, the function returns PID of the daemon process to the parent process (which starts a daemon) or 0 to the daemon process. On error it returns -1 - this value might be returned to both parent and daemon process. In this case, the &lt;b&gt;errno&lt;/b&gt; value is set accordingly. In the case, if during the daemonization an error has occurred, the &lt;b&gt;errno&lt;/b&gt; value is transparently transferred to the parent process.
&lt;/p&gt;

&lt;p&gt;
The second function is:
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-C&quot;&gt;&lt;span class=&quot;org-type&quot;&gt;pid_t&lt;/span&gt; &lt;span class=&quot;org-function-name&quot;&gt;rundaemon&lt;/span&gt;(&lt;span class=&quot;org-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;flags&lt;/span&gt;,
                &lt;span class=&quot;org-type&quot;&gt;int&lt;/span&gt; (*&lt;span class=&quot;org-function-name&quot;&gt;daemon_func&lt;/span&gt;)(&lt;span class=&quot;org-type&quot;&gt;void&lt;/span&gt; *&lt;span class=&quot;org-variable-name&quot;&gt;udata&lt;/span&gt;),
                &lt;span class=&quot;org-type&quot;&gt;void&lt;/span&gt; *&lt;span class=&quot;org-variable-name&quot;&gt;udata&lt;/span&gt;,
                &lt;span class=&quot;org-type&quot;&gt;int&lt;/span&gt; *&lt;span class=&quot;org-variable-name&quot;&gt;exit_code&lt;/span&gt;,
                &lt;span class=&quot;org-keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;char&lt;/span&gt; *&lt;span class=&quot;org-variable-name&quot;&gt;pid_file_path&lt;/span&gt;);
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
This function is a mere wrapper on top of &lt;code&gt;daemonize()&lt;/code&gt; which might check and create PID-file  if desired. It is recommended to use this function instead of &lt;code&gt;daemonize()&lt;/code&gt; whenever applicable.
&lt;/p&gt;

&lt;p&gt;
As you can see, this function has more arguments than the previous one. These arguments are:
&lt;/p&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;code&gt;int flags&lt;/code&gt; - daemon creation flags, see above;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;int (*daemon_func)(void *udata)&lt;/code&gt; - pointer to the function to be called after successful daemonization (the actual daemon body);&lt;/li&gt;
&lt;li&gt;&lt;code&gt;void *udata&lt;/code&gt; - pointer to be passed as the value in a call to &lt;code&gt;daemon_func&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;int exit_code&lt;/code&gt; - pointer to a variable which receives value returned by &lt;code&gt;daemon_func&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;const char *pid_file_path&lt;/code&gt; - full pathname to the PID-file. It is used for checking if the daemon is not already running (by checking if the file exists and locked) and is created if it does not exist. When daemon exits, this file is removed under normal conditions. This value might be &lt;code&gt;NULL&lt;/code&gt;, in this case no checks performed and no file is created.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
&lt;code&gt;rundaemon()&lt;/code&gt; shares return values with &lt;code&gt;daemonize()&lt;/code&gt; with one notable exception: it returns -2 if daemon is running.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org9b27b8d&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org9b27b8d&quot;&gt;A Complete Example&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org9b27b8d&quot;&gt;
&lt;p&gt;
I believe that the discussion would be incomplete without a full example. It shows how to write a basic daemon using the above discussed library. The following example might be used as a template for your own daemon.
&lt;/p&gt;

&lt;p&gt;
The daemon performs the following actions:
&lt;/p&gt;

&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;Runs in background and creates PID-file;&lt;/li&gt;
&lt;li&gt;Sets up logging via &lt;a href=&quot;http://man7.org/linux/man-pages/man3/syslog.3.html&quot;&gt;syslog&lt;/a&gt; facility;&lt;/li&gt;
&lt;li&gt;Handles &lt;code&gt;SIGTERM&lt;/code&gt; and &lt;code&gt;SIGHUP&lt;/code&gt; signals (using &lt;a href=&quot;http://man7.org/linux/man-pages/man2/signalfd.2.html&quot;&gt;&lt;code&gt;signalfd()&lt;/code&gt;&lt;/a&gt; and &lt;code&gt;select()&lt;/code&gt;);&lt;/li&gt;
&lt;li&gt;Exits on &lt;code&gt;SIGTERM&lt;/code&gt; signal.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
It is implemented on top of the above-discussed &lt;code&gt;rundaemon()&lt;/code&gt; in an event-driven manner and distributed alongside the library as &lt;code&gt;example.c&lt;/code&gt; file.
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-C&quot;&gt;&lt;span class=&quot;org-preprocessor&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&amp;lt;unistd.h&amp;gt;&lt;/span&gt;

&lt;span class=&quot;org-preprocessor&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;
&lt;span class=&quot;org-preprocessor&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&amp;lt;stdlib.h&amp;gt;&lt;/span&gt;
&lt;span class=&quot;org-preprocessor&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&amp;lt;signal.h&amp;gt;&lt;/span&gt;
&lt;span class=&quot;org-preprocessor&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&amp;lt;errno.h&amp;gt;&lt;/span&gt;

&lt;span class=&quot;org-preprocessor&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&amp;lt;sys/types.h&amp;gt;&lt;/span&gt;
&lt;span class=&quot;org-preprocessor&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&amp;lt;sys/select.h&amp;gt;&lt;/span&gt;
&lt;span class=&quot;org-preprocessor&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&amp;lt;sys/time.h&amp;gt;&lt;/span&gt;
&lt;span class=&quot;org-preprocessor&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&amp;lt;sys/stat.h&amp;gt;&lt;/span&gt;
&lt;span class=&quot;org-preprocessor&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&amp;lt;sys/signalfd.h&amp;gt;&lt;/span&gt;
&lt;span class=&quot;org-preprocessor&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&amp;lt;fcntl.h&amp;gt;&lt;/span&gt;
&lt;span class=&quot;org-preprocessor&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&amp;lt;syslog.h&amp;gt;&lt;/span&gt;

&lt;span class=&quot;org-preprocessor&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;daemonize.h&quot;&lt;/span&gt;

&lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;The daemon process body&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
&lt;span class=&quot;org-keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;org-function-name&quot;&gt;example_daemon&lt;/span&gt;(&lt;span class=&quot;org-type&quot;&gt;void&lt;/span&gt; *&lt;span class=&quot;org-variable-name&quot;&gt;udata&lt;/span&gt;)
{
    &lt;span class=&quot;org-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;exit&lt;/span&gt; = 0;
    &lt;span class=&quot;org-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;exit_code&lt;/span&gt; = EXIT_SUCCESS;

    &lt;span class=&quot;org-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;sfd&lt;/span&gt; = -1;
    &lt;span class=&quot;org-type&quot;&gt;sigset_t&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;mask&lt;/span&gt;;
    &lt;span class=&quot;org-keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;signalfd_siginfo&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;si&lt;/span&gt;;

    &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;open the system log&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
    openlog(&lt;span class=&quot;org-string&quot;&gt;&quot;EXAMPLE&quot;&lt;/span&gt;, LOG_NDELAY, LOG_DAEMON);

    &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;greeting&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
    syslog(LOG_INFO, &lt;span class=&quot;org-string&quot;&gt;&quot;EXAMPLE daemon started. PID: %ld&quot;&lt;/span&gt;, (&lt;span class=&quot;org-type&quot;&gt;long&lt;/span&gt;)getpid());

    &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;create a file descriptor for signal handling&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
    sigemptyset(&amp;amp;mask);
    &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;handle the following signals&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
    sigaddset(&amp;amp;mask, SIGTERM);
    sigaddset(&amp;amp;mask, SIGHUP);

    &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;Block the signals so that they aren&apos;t handled
       according to their default dispositions&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
    &lt;span class=&quot;org-keyword&quot;&gt;if&lt;/span&gt; (sigprocmask(SIG_BLOCK, &amp;amp;mask, &lt;span class=&quot;org-constant&quot;&gt;NULL&lt;/span&gt;) == -1)
    {
        closelog();
        &lt;span class=&quot;org-keyword&quot;&gt;return&lt;/span&gt; EXIT_FAILURE;
    }

    sfd = signalfd(-1, &amp;amp;mask, 0);
    &lt;span class=&quot;org-keyword&quot;&gt;if&lt;/span&gt; (sfd == -1)
    {
        perror(&lt;span class=&quot;org-string&quot;&gt;&quot;signalfd failed&quot;&lt;/span&gt;);
        sigprocmask(SIG_UNBLOCK, &amp;amp;mask, &lt;span class=&quot;org-constant&quot;&gt;NULL&lt;/span&gt;);
        closelog();
        &lt;span class=&quot;org-keyword&quot;&gt;return&lt;/span&gt; EXIT_FAILURE;
    }

    &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;the daemon loop&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
    &lt;span class=&quot;org-keyword&quot;&gt;while&lt;/span&gt; (&lt;span class=&quot;org-negation-char&quot;&gt;!&lt;/span&gt;exit)
    {
        &lt;span class=&quot;org-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;result&lt;/span&gt;;
        &lt;span class=&quot;org-type&quot;&gt;fd_set&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;readset&lt;/span&gt;;

        &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;add the signal file descriptor to set&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
        FD_ZERO(&amp;amp;readset);
        FD_SET(sfd, &amp;amp;readset);
        &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;One could add more file descriptors here
           and handle them accordingly if one wants to build a server using
           event-driven approach.&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;

        &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;wait for the data in the signal file descriptor&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
        result = select(FD_SETSIZE, &amp;amp;readset, &lt;span class=&quot;org-constant&quot;&gt;NULL&lt;/span&gt;, &lt;span class=&quot;org-constant&quot;&gt;NULL&lt;/span&gt;, &lt;span class=&quot;org-constant&quot;&gt;NULL&lt;/span&gt;);
        &lt;span class=&quot;org-keyword&quot;&gt;if&lt;/span&gt; (result == -1)
        {
            syslog(LOG_ERR, &lt;span class=&quot;org-string&quot;&gt;&quot;Fatal error during select() call.&quot;&lt;/span&gt;);
            &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;a low level error&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
            exit_code = EXIT_FAILURE;
            &lt;span class=&quot;org-keyword&quot;&gt;break&lt;/span&gt;;
        }

        &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;read the data from the signal handler file descriptor&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
        &lt;span class=&quot;org-keyword&quot;&gt;if&lt;/span&gt; (FD_ISSET(sfd, &amp;amp;readset) &amp;amp;&amp;amp; read(sfd, &amp;amp;si, &lt;span class=&quot;org-keyword&quot;&gt;sizeof&lt;/span&gt;(si)) &amp;gt; 0)
        {
            &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;handle the signals&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
            &lt;span class=&quot;org-keyword&quot;&gt;switch&lt;/span&gt; (si.ssi_signo)
            {
                &lt;span class=&quot;org-keyword&quot;&gt;case&lt;/span&gt; SIGTERM: &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;stop the daemon&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
                    syslog(LOG_INFO, &lt;span class=&quot;org-string&quot;&gt;&quot;Got SIGTERM signal. Stopping daemon...&quot;&lt;/span&gt;);
                    exit = 1;
                    &lt;span class=&quot;org-keyword&quot;&gt;break&lt;/span&gt;;
                &lt;span class=&quot;org-keyword&quot;&gt;case&lt;/span&gt; SIGHUP: &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;reload the configuration&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
                    syslog(LOG_INFO, &lt;span class=&quot;org-string&quot;&gt;&quot;Got SIGHUP signal.&quot;&lt;/span&gt;);
                    &lt;span class=&quot;org-keyword&quot;&gt;break&lt;/span&gt;;
                &lt;span class=&quot;org-keyword&quot;&gt;default&lt;/span&gt;:
                    syslog(LOG_WARNING, &lt;span class=&quot;org-string&quot;&gt;&quot;Got unexpected signal (number: %d).&quot;&lt;/span&gt;, si.ssi_signo);
                    &lt;span class=&quot;org-keyword&quot;&gt;break&lt;/span&gt;;
            }
        }
    }

    &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;close the signal file descriptor&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
    close(sfd);
    &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;remove the signal handlers&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
    sigprocmask(SIG_UNBLOCK, &amp;amp;mask, &lt;span class=&quot;org-constant&quot;&gt;NULL&lt;/span&gt;);
    &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;write an exit code to the system log&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
    syslog(LOG_INFO, &lt;span class=&quot;org-string&quot;&gt;&quot;Daemon stopped with status code %d.&quot;&lt;/span&gt;, exit_code);
    &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;close the system log&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
    closelog();

    &lt;span class=&quot;org-keyword&quot;&gt;return&lt;/span&gt; exit_code;
}


&lt;span class=&quot;org-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;org-function-name&quot;&gt;main&lt;/span&gt;(&lt;span class=&quot;org-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;argc&lt;/span&gt;, &lt;span class=&quot;org-type&quot;&gt;char&lt;/span&gt; **&lt;span class=&quot;org-variable-name&quot;&gt;argv&lt;/span&gt;)
{
    &lt;span class=&quot;org-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;exit_code&lt;/span&gt; = 0;

    &lt;span class=&quot;org-type&quot;&gt;pid_t&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;pid&lt;/span&gt; = rundaemon(0, &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;Daemon creation flags.&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
                          example_daemon, &lt;span class=&quot;org-constant&quot;&gt;NULL&lt;/span&gt;, &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;Daemon body function and its argument.&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
                          &amp;amp;exit_code, &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;Pointer to a variable to receive daemon exit code&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
                          &lt;span class=&quot;org-string&quot;&gt;&quot;/tmp/example.pid&quot;&lt;/span&gt;); &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;Full path to the PID-file (lock).&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
    &lt;span class=&quot;org-keyword&quot;&gt;switch&lt;/span&gt; (pid)
    {
        &lt;span class=&quot;org-keyword&quot;&gt;case&lt;/span&gt; -1: &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;Low level error. See errno for details.&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
        {
            perror(&lt;span class=&quot;org-string&quot;&gt;&quot;Cannot start daemon.&quot;&lt;/span&gt;);
            &lt;span class=&quot;org-keyword&quot;&gt;return&lt;/span&gt; EXIT_FAILURE;
        }
        &lt;span class=&quot;org-keyword&quot;&gt;break&lt;/span&gt;;
        &lt;span class=&quot;org-keyword&quot;&gt;case&lt;/span&gt; -2: &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;Daemon is already running&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
        {
            fprintf(stderr,&lt;span class=&quot;org-string&quot;&gt;&quot;Daemon already running.\n&quot;&lt;/span&gt;);
        }
        &lt;span class=&quot;org-keyword&quot;&gt;break&lt;/span&gt;;
        &lt;span class=&quot;org-keyword&quot;&gt;case&lt;/span&gt; 0: &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;Daemon process.&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
        {
            &lt;span class=&quot;org-keyword&quot;&gt;return&lt;/span&gt; exit_code; &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;Return daemon exit code.&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
        }
        &lt;span class=&quot;org-keyword&quot;&gt;default&lt;/span&gt;: &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;Parent process&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
        {
            printf(&lt;span class=&quot;org-string&quot;&gt;&quot;Parent: %ld, Daemon: %ld\n&quot;&lt;/span&gt;, (&lt;span class=&quot;org-type&quot;&gt;long&lt;/span&gt;)getpid(), (&lt;span class=&quot;org-type&quot;&gt;long&lt;/span&gt;)pid);
        }
        &lt;span class=&quot;org-keyword&quot;&gt;break&lt;/span&gt;;
    }

    &lt;span class=&quot;org-keyword&quot;&gt;return&lt;/span&gt; EXIT_SUCCESS;
}
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org90a4539&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org90a4539&quot;&gt;Conclusion&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org90a4539&quot;&gt;
&lt;p&gt;
The objective of the library is to hide all the trickery of programming a daemon so you could concentrate on the more creative parts of your application. I hope it does this well.
&lt;/p&gt;

&lt;p&gt;
If you are not only interested in &lt;i&gt;writing&lt;/i&gt; a daemon, but also want to &lt;i&gt;make yourself familiar&lt;/i&gt; with the techniques which are used to accomplish that, the &lt;a href=&quot;https://bitbucket.org/arbv/daemonize&quot;&gt;source code&lt;/a&gt; is available. Moreover, I would advise anyone, who starts developing for a UNIX environment to do that, as it shows many intricacies of programming for these platforms.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
				
				<pubDate>Mon, 01 Oct 2018 00:00:00 +0300</pubDate>
				<link>https://chaoticlab.io/c/c++/unix/2018/10/01/daemonize.html</link>
				<guid isPermaLink="true">https://chaoticlab.io/c/c++/unix/2018/10/01/daemonize.html</guid>
			</item>
		
			<item>
				<title>Fixing Emacs&apos;s FlySpell Mode for Texts with Multiple Alphabets</title>
				
				
					<description>&lt;p&gt;
Recently I have encountered a problem in Emacs when using &lt;b&gt;flyspell-buffer&lt;/b&gt; command to spell-check a text in Emacs. I tracked down the problem and decided to &lt;a href=&quot;http://debbugs.gnu.org/cgi/bugreport.cgi?bug=32280&quot;&gt;report the bug&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;
The problem was complicated and it was possible to reproduce it only for texts which use more than one writing system (e. g. Latin and Cyrillic) and only under some circumstances.
&lt;/p&gt;

&lt;div class=&quot;org-center&quot;&gt;

&lt;div id=&quot;org188f609&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/flyspell-bug-sample2.png&quot; alt=&quot;flyspell-bug-sample2.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;
Emacs developers were very responsive and after few days Eli Zaretskii tracked down the root of the problem and provided a better fix which is going to be incorporated into Emacs 26.2.
&lt;/p&gt;

&lt;p&gt;
If you happen to use an older version of Emacs and have to spell-check some multilingual texts often, you might want to consider redefining &lt;b&gt;flyspell-external-point-words&lt;/b&gt; in your configuration file with the version, provided below.
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-elisp&quot;&gt;
(&lt;span class=&quot;org-keyword&quot;&gt;defun&lt;/span&gt; &lt;span class=&quot;org-function-name&quot;&gt;flyspell-external-point-words&lt;/span&gt; ()
  &lt;span class=&quot;org-doc&quot;&gt;&quot;Mark words from a buffer listing incorrect words in order of appearance.
The list of incorrect words should be in `&lt;/span&gt;&lt;span class=&quot;org-doc&quot;&gt;&lt;span class=&quot;org-constant&quot;&gt;flyspell-external-ispell-buffer&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;org-doc&quot;&gt;&apos;.
\(We finish by killing that buffer and setting the variable to nil.)
The buffer to mark them in is `&lt;/span&gt;&lt;span class=&quot;org-doc&quot;&gt;&lt;span class=&quot;org-constant&quot;&gt;flyspell-large-region-buffer&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;org-doc&quot;&gt;&apos;.&quot;&lt;/span&gt;
  (&lt;span class=&quot;org-keyword&quot;&gt;let*&lt;/span&gt; (words-not-found
         (flyspell-casechars (flyspell-get-casechars))
         (ispell-otherchars (ispell-get-otherchars))
         (ispell-many-otherchars-p (ispell-get-many-otherchars-p))
         (word-chars (concat flyspell-casechars
                             &lt;span class=&quot;org-string&quot;&gt;&quot;+&lt;/span&gt;&lt;span class=&quot;org-string&quot;&gt;&lt;span class=&quot;org-regexp-grouping-backslash&quot;&gt;\\&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;org-string&quot;&gt;&lt;span class=&quot;org-regexp-grouping-construct&quot;&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;org-string&quot;&gt;&quot;&lt;/span&gt;
                             (&lt;span class=&quot;org-keyword&quot;&gt;if&lt;/span&gt; (not (string= &lt;span class=&quot;org-string&quot;&gt;&quot;&quot;&lt;/span&gt; ispell-otherchars))
                                 (concat ispell-otherchars &lt;span class=&quot;org-string&quot;&gt;&quot;?&quot;&lt;/span&gt;))
                             flyspell-casechars
                             &lt;span class=&quot;org-string&quot;&gt;&quot;+&lt;/span&gt;&lt;span class=&quot;org-string&quot;&gt;&lt;span class=&quot;org-regexp-grouping-backslash&quot;&gt;\\&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;org-string&quot;&gt;&lt;span class=&quot;org-regexp-grouping-construct&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;org-string&quot;&gt;&quot;&lt;/span&gt;
                             (&lt;span class=&quot;org-keyword&quot;&gt;if&lt;/span&gt; ispell-many-otherchars-p
                                 &lt;span class=&quot;org-string&quot;&gt;&quot;*&quot;&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;?&quot;&lt;/span&gt;)))
         (buffer-scan-pos flyspell-large-region-beg)
         case-fold-search)
    (&lt;span class=&quot;org-keyword&quot;&gt;with-current-buffer&lt;/span&gt; flyspell-external-ispell-buffer
      (goto-char (point-min))
      &lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;Loop over incorrect words, in the order they were reported,
&lt;/span&gt;      &lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;which is also the order they appear in the buffer being checked.
&lt;/span&gt;      (&lt;span class=&quot;org-keyword&quot;&gt;while&lt;/span&gt; (re-search-forward &lt;span class=&quot;org-string&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;org-string&quot;&gt;&lt;span class=&quot;org-regexp-grouping-backslash&quot;&gt;\\&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;org-string&quot;&gt;&lt;span class=&quot;org-regexp-grouping-construct&quot;&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;org-string&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;org-string&quot;&gt;&lt;span class=&quot;org-negation-char&quot;&gt;^&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;org-string&quot;&gt;\n]+&lt;/span&gt;&lt;span class=&quot;org-string&quot;&gt;&lt;span class=&quot;org-regexp-grouping-backslash&quot;&gt;\\&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;org-string&quot;&gt;&lt;span class=&quot;org-regexp-grouping-construct&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;org-string&quot;&gt;\n&quot;&lt;/span&gt; nil t)
    &lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;Bind WORD to the next one.
&lt;/span&gt;    (&lt;span class=&quot;org-keyword&quot;&gt;let&lt;/span&gt; ((word (match-string 1)) (wordpos (point)))
      &lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;Here there used to be code to see if WORD is the same
&lt;/span&gt;      &lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;as the previous iteration, and count the number of consecutive
&lt;/span&gt;      &lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;identical words, and the loop below would search for that many.
&lt;/span&gt;      &lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;That code seemed to be incorrect, and on principle, should
&lt;/span&gt;      &lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;be unnecessary too. -- rms.
&lt;/span&gt;      (&lt;span class=&quot;org-keyword&quot;&gt;if&lt;/span&gt; flyspell-issue-message-flag
          (message &lt;span class=&quot;org-string&quot;&gt;&quot;Spell Checking...%d%% [%s]&quot;&lt;/span&gt;
               (floor (* 100.0 (point)) (point-max))
               word))
      (&lt;span class=&quot;org-keyword&quot;&gt;with-current-buffer&lt;/span&gt; flyspell-large-region-buffer
        (goto-char buffer-scan-pos)
        (&lt;span class=&quot;org-keyword&quot;&gt;let&lt;/span&gt; ((keep t))
          &lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;Iterate on string search until string is found as word,
&lt;/span&gt;          &lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;not as substring.
&lt;/span&gt;          (&lt;span class=&quot;org-keyword&quot;&gt;while&lt;/span&gt; keep
        (&lt;span class=&quot;org-keyword&quot;&gt;if&lt;/span&gt; (search-forward word
                    flyspell-large-region-end t)
            (&lt;span class=&quot;org-keyword&quot;&gt;let*&lt;/span&gt; ((found-list
                (&lt;span class=&quot;org-keyword&quot;&gt;save-excursion&lt;/span&gt;
                  &lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;Move back into the match
&lt;/span&gt;                  &lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;so flyspell-get-word will find it.
&lt;/span&gt;                  (forward-char -1)
                              &lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;Is this a word that matches the
&lt;/span&gt;                              &lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;current dictionary?
&lt;/span&gt;                              (&lt;span class=&quot;org-keyword&quot;&gt;if&lt;/span&gt; (looking-at word-chars)
                      (flyspell-get-word))))
               (found (car found-list))
               (found-length (length found))
               (misspell-length (length word)))
              (&lt;span class=&quot;org-keyword&quot;&gt;when&lt;/span&gt; (&lt;span class=&quot;org-keyword&quot;&gt;or&lt;/span&gt;
                             &lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;Misspelled word is not from the
&lt;/span&gt;                             &lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;language supported by the current
&lt;/span&gt;                             &lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;dictionary.
&lt;/span&gt;                             (null found)
                 &lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;Size matches, we really found it.
&lt;/span&gt;                 (= found-length misspell-length)
                 &lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;Matches as part of a boundary-char separated
&lt;/span&gt;                 &lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;word.
&lt;/span&gt;                 (member word
                     (split-string found ispell-otherchars))
                 &lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;Misspelling has higher length than
&lt;/span&gt;                 &lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;what flyspell considers the word.
&lt;/span&gt;                             &lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;Caused by boundary-chars mismatch.
&lt;/span&gt;                             &lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;Validating seems safe.
&lt;/span&gt;                 (&amp;lt; found-length misspell-length)
                 &lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;ispell treats beginning of some TeX
&lt;/span&gt;                 &lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;commands as nroff control sequences
&lt;/span&gt;                 &lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;and strips them in the list of
&lt;/span&gt;                 &lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;misspelled words thus giving a
&lt;/span&gt;                 &lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;non-existent word.  Skip if ispell
&lt;/span&gt;                 &lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;is used, string is a TeX command
&lt;/span&gt;                 &lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;(char before beginning of word is
&lt;/span&gt;                 &lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;backslash) and none of the previous
&lt;/span&gt;                 &lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;conditions match.
&lt;/span&gt;                 (&lt;span class=&quot;org-keyword&quot;&gt;and&lt;/span&gt; (not ispell-really-aspell)
                                  (not ispell-really-hunspell)
                                  (not ispell-really-enchant)
                  (&lt;span class=&quot;org-keyword&quot;&gt;save-excursion&lt;/span&gt;
                    (goto-char (- (nth 1 found-list) 1))
                    (&lt;span class=&quot;org-keyword&quot;&gt;if&lt;/span&gt; (looking-at &lt;span class=&quot;org-string&quot;&gt;&quot;[\\]&quot;&lt;/span&gt; )
                    t
                      nil))))
            (&lt;span class=&quot;org-keyword&quot;&gt;setq&lt;/span&gt; keep nil)
                        &lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;Don&apos;t try spell-checking words whose
&lt;/span&gt;                        &lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;characters don&apos;t match CASECHARS, because
&lt;/span&gt;                        &lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;flyspell-word will then consider as
&lt;/span&gt;                        &lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;misspelling the preceding word that matches
&lt;/span&gt;                        &lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;CASECHARS.
&lt;/span&gt;                        (&lt;span class=&quot;org-keyword&quot;&gt;or&lt;/span&gt; (null found)
                (flyspell-word nil t))
            &lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;Search for next misspelled word will begin from
&lt;/span&gt;            &lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;end of last validated match.
&lt;/span&gt;            (&lt;span class=&quot;org-keyword&quot;&gt;setq&lt;/span&gt; buffer-scan-pos (point))))
          &lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;Record if misspelling is not found and try new one
&lt;/span&gt;          (&lt;span class=&quot;org-keyword&quot;&gt;cl-pushnew&lt;/span&gt; (concat &lt;span class=&quot;org-string&quot;&gt;&quot; -&amp;gt; &quot;&lt;/span&gt; word &lt;span class=&quot;org-string&quot;&gt;&quot; - &quot;&lt;/span&gt;
                       (int-to-string wordpos))
                              words-not-found &lt;span class=&quot;org-builtin&quot;&gt;:test&lt;/span&gt; #&apos;equal)
          (&lt;span class=&quot;org-keyword&quot;&gt;setq&lt;/span&gt; keep nil)))))))
      &lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;we are done
&lt;/span&gt;      (&lt;span class=&quot;org-keyword&quot;&gt;if&lt;/span&gt; flyspell-issue-message-flag (message &lt;span class=&quot;org-string&quot;&gt;&quot;Spell Checking completed.&quot;&lt;/span&gt;)))
    &lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;Warn about not found misspellings
&lt;/span&gt;    (&lt;span class=&quot;org-keyword&quot;&gt;dolist&lt;/span&gt; (word words-not-found)
      (message &lt;span class=&quot;org-string&quot;&gt;&quot;%s: word not found&quot;&lt;/span&gt; word))
    &lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;Kill and forget the buffer with the list of incorrect words.
&lt;/span&gt;    (kill-buffer flyspell-external-ispell-buffer)
    (&lt;span class=&quot;org-keyword&quot;&gt;setq&lt;/span&gt; flyspell-external-ispell-buffer nil)))

&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
Alternatively, you can put the function definition into separate file (&lt;b&gt;flyspell-fix.el&lt;/b&gt;) inside your Emacs configuration directory (&lt;b&gt;~/.emacs.d&lt;/b&gt;) and load it only for Emacs versions which are older than 26.2.
&lt;/p&gt;

&lt;p&gt;
After creating &lt;b&gt;flyspell-fix.el&lt;/b&gt; file, as mentioned above, add the following lines into your Emacs&apos;s configuration file:
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-elisp&quot;&gt;
&lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;fix flyspell for older versions of Emacs.
&lt;/span&gt;(&lt;span class=&quot;org-keyword&quot;&gt;when&lt;/span&gt; (&lt;span class=&quot;org-keyword&quot;&gt;or&lt;/span&gt; (&amp;lt; emacs-major-version 26)
          (&lt;span class=&quot;org-keyword&quot;&gt;and&lt;/span&gt; (= emacs-major-version 26)
               (&amp;lt; emacs-minor-version 2)))
  (load (concat user-emacs-directory &lt;span class=&quot;org-string&quot;&gt;&quot;flyspell-fix.el&quot;&lt;/span&gt;)))

&lt;/pre&gt;
&lt;/div&gt;
</description>
				
				<pubDate>Thu, 09 Aug 2018 00:00:00 +0300</pubDate>
				<link>https://chaoticlab.io/hacks/emacs/2018/08/09/fix-flyspell.html</link>
				<guid isPermaLink="true">https://chaoticlab.io/hacks/emacs/2018/08/09/fix-flyspell.html</guid>
			</item>
		
			<item>
				<title>dumpmem() - a Function to Dump an Area in RAM in Hexadecimal Format</title>
				
				
					<description>&lt;p&gt;
Today I want to share with you some code which helped me to track down a problem in a rather complex networking VoIP application. I believe it might be useful in other scenarios as well.
&lt;/p&gt;

&lt;p&gt;
Some time ago I debugged a networked application. The problem seemed to be in the handling of one type of network packets and two versions of the application behaved differently under similar circumstances. There is one known issue with debugging networked applications - timing might be very important and, in some cases, there is no much time to diagnose raw data which was received via networking socket in a debugger. More than that, the format of the data was binary and, thus, not human readable. Using network sniffing software (like &lt;a href=&quot;https://www.wireshark.org/&quot;&gt;Wireshark&lt;/a&gt;) was not an option, as parts of the message contained encrypted information.
&lt;/p&gt;

&lt;p&gt;
To verify my hypothesis without interfering much with the application during runtime, I decided to dump contents of the parts of the message to a log file in hexadecimal format and analyse the data later. The format closely resembles one, used by HEX-editors, as you will see. In fact, I adopted most of the source code from a HEX-viewing utility which I wrote as a university assignment a long time ago.
&lt;/p&gt;

&lt;p&gt;
Here is the source code of a function, which dumps contents of a part of random access memory in hexadecimal format:
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-C&quot;&gt;
&lt;span class=&quot;org-type&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;org-function-name&quot;&gt;dumpmem&lt;/span&gt;(&lt;span class=&quot;org-type&quot;&gt;FILE&lt;/span&gt; *&lt;span class=&quot;org-variable-name&quot;&gt;out&lt;/span&gt;, &lt;span class=&quot;org-keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;void&lt;/span&gt; *&lt;span class=&quot;org-variable-name&quot;&gt;ptr&lt;/span&gt;, &lt;span class=&quot;org-keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;size_t&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;size&lt;/span&gt;)
{
    &lt;span class=&quot;org-keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;size_t&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;BYTES_PER_LINE&lt;/span&gt; = 16;
    &lt;span class=&quot;org-type&quot;&gt;size_t&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;offset&lt;/span&gt;, &lt;span class=&quot;org-variable-name&quot;&gt;read&lt;/span&gt;;

    &lt;span class=&quot;org-type&quot;&gt;uint8_t&lt;/span&gt; *&lt;span class=&quot;org-variable-name&quot;&gt;p&lt;/span&gt; = (&lt;span class=&quot;org-type&quot;&gt;uint8_t&lt;/span&gt; *)ptr;
    &lt;span class=&quot;org-keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;uint8_t&lt;/span&gt; *&lt;span class=&quot;org-variable-name&quot;&gt;maxp&lt;/span&gt; = (p + size);

    &lt;span class=&quot;org-keyword&quot;&gt;if&lt;/span&gt; (out == &lt;span class=&quot;org-constant&quot;&gt;NULL&lt;/span&gt; || ptr == &lt;span class=&quot;org-constant&quot;&gt;NULL&lt;/span&gt; || size == 0)
    {
        &lt;span class=&quot;org-keyword&quot;&gt;return&lt;/span&gt;;
    }

    &lt;span class=&quot;org-keyword&quot;&gt;for&lt;/span&gt; (offset = read = 0; offset != size; offset += read)
    {
        &lt;span class=&quot;org-type&quot;&gt;uint8_t&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;buf&lt;/span&gt;[BYTES_PER_LINE];

        &lt;span class=&quot;org-keyword&quot;&gt;for&lt;/span&gt; (read = 0; read != BYTES_PER_LINE &amp;amp;&amp;amp; (&amp;amp;p[offset + read]) &amp;lt; maxp; read++)
        {
            buf[read] = p[offset + read];
        }

        &lt;span class=&quot;org-keyword&quot;&gt;if&lt;/span&gt; (read == 0)
            &lt;span class=&quot;org-keyword&quot;&gt;return&lt;/span&gt;;

        fprintf(out, &lt;span class=&quot;org-string&quot;&gt;&quot;%.8x: &quot;&lt;/span&gt;, (&lt;span class=&quot;org-type&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;int&lt;/span&gt;)offset);

        &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;raw data&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
        &lt;span class=&quot;org-keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;org-type&quot;&gt;size_t&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;i&lt;/span&gt; = 0; i &amp;lt; read; i++)
        {
            fprintf(out, &lt;span class=&quot;org-string&quot;&gt;&quot; %.2x&quot;&lt;/span&gt;, buf[i]);
            &lt;span class=&quot;org-keyword&quot;&gt;if&lt;/span&gt; (BYTES_PER_LINE &amp;gt; 8 &amp;amp;&amp;amp; BYTES_PER_LINE % 2 == 0 &amp;amp;&amp;amp; i == (BYTES_PER_LINE / 2 - 1))
                fprintf(out, &lt;span class=&quot;org-string&quot;&gt;&quot; &quot;&lt;/span&gt;);
        }

        &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;ASCII&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
        &lt;span class=&quot;org-keyword&quot;&gt;if&lt;/span&gt; (read &amp;lt; BYTES_PER_LINE)
        {
            &lt;span class=&quot;org-keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;org-type&quot;&gt;size_t&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;i&lt;/span&gt; = read; i &amp;lt; BYTES_PER_LINE; i++)
            {
                fprintf(out, &lt;span class=&quot;org-string&quot;&gt;&quot;  &quot;&lt;/span&gt;);
                fprintf(out, &lt;span class=&quot;org-string&quot;&gt;&quot; &quot;&lt;/span&gt;);
                &lt;span class=&quot;org-keyword&quot;&gt;if&lt;/span&gt; (BYTES_PER_LINE &amp;gt; 8 &amp;amp;&amp;amp; BYTES_PER_LINE % 2 == 0 &amp;amp;&amp;amp; i == (BYTES_PER_LINE / 2 - 1))
                    fprintf(out, &lt;span class=&quot;org-string&quot;&gt;&quot; &quot;&lt;/span&gt;);
            }
        }
        fprintf(out, &lt;span class=&quot;org-string&quot;&gt;&quot; &quot;&lt;/span&gt;);
        &lt;span class=&quot;org-keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;org-type&quot;&gt;size_t&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;i&lt;/span&gt; = 0; i &amp;lt; read; i++)
        {
            &lt;span class=&quot;org-keyword&quot;&gt;if&lt;/span&gt; (buf[i] &amp;lt;= 31 || buf[i] &amp;gt;= 127) &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;ignore control and non-ASCII characters&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
                fprintf(out, &lt;span class=&quot;org-string&quot;&gt;&quot;.&quot;&lt;/span&gt;);
            &lt;span class=&quot;org-keyword&quot;&gt;else&lt;/span&gt;
                fprintf(out, &lt;span class=&quot;org-string&quot;&gt;&quot;%c&quot;&lt;/span&gt;, buf[i]);
        }

        fprintf(out, &lt;span class=&quot;org-string&quot;&gt;&quot;\n&quot;&lt;/span&gt;);
    }
}

&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
As one could see, it accepts three parameters:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;&lt;b&gt;out&lt;/b&gt; - output file stream;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;ptr&lt;/b&gt; - pointer to data;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;size&lt;/b&gt; - data size.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
There is some room for optimisation, but I think that it is not worth it.
&lt;/p&gt;

&lt;p&gt;
If you wonder how the output of this function looks like, here is a short example of an H.225 RAS message:
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-nil&quot;&gt;00000000:  03 00 00 ab 08 02 18 af  05 04 04 88 18 a0 a5 28 ...............(
00000010:  06 76 63 34 30 30 00 6c  04 81 36 30 31 7e 00 8b .vc400.l..601~..
00000020:  05 20 b8 06 00 08 91 4a  00 06 02 01 00 93 44 04 . .....J......D.
00000030:  00 76 00 63 00 34 00 30  00 30 22 c0 26 00 00 02 .v.c.4.0.0&quot;.&amp;amp;...
00000040:  0e 59 65 61 6c 69 6e 6b  20 56 43 34 30 30 00 00 .Yealink VC400..
00000050:  0b 33 30 2e 31 30 2e 30  2e 32 37 00 00 00 01 40 .30.10.0.27....@
00000060:  03 00 61 00 73 00 72 00  76 00 c0 a8 29 9c 06 b8 ..a.s.r.v...)...
00000070:  00 dc 27 ec f9 6b ef e5  11 94 0e 00 15 65 86 fc ..&apos;..k.......e..
00000080:  9f 00 5d 0d 80 07 00 c0  a8 5a 0e 06 b8 11 00 82 ..]......Z......
00000090:  27 ec f9 6b ef e5 11 94  0e 00 15 65 86 fc 9f 01 &apos;..k.......e....
000000a0:  00 01 00 01 00 01 00 02  80 01 00                ...........
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
Off course, the discussed debugging technique is not the panacea and should be used only in very specific cases, as, I believe, one could obtain similar results using modern debugging tools. But anyway it helped me to solve a problem in short time, so I decided to share this information here. It is not a tool for everyday use, but still, I think, it is a trick worth to know about.
&lt;/p&gt;
</description>
				
				<pubDate>Wed, 08 Aug 2018 00:00:00 +0300</pubDate>
				<link>https://chaoticlab.io/c/c++/hacks/2018/08/08/dumpmem.html</link>
				<guid isPermaLink="true">https://chaoticlab.io/c/c++/hacks/2018/08/08/dumpmem.html</guid>
			</item>
		
			<item>
				<title>Persistent Remote Terminal Session With TMUX</title>
				
				
					<description>&lt;p&gt;
The first thing I install on every UNIX machine on which I have enough administrative rights is &lt;a href=&quot;https://github.com/tmux/tmux/wiki&quot;&gt;tmux&lt;/a&gt; (terminal multiplexor) - I feel uncomfortable to connect to it via SSH otherwise. For example, you could encounter some problems with your Internet connection - any sudden disconnect might disrupt a lengthy operation like backup which might have been initiated from within the remote terminal session. I want my remote session to be persistent.
&lt;/p&gt;

&lt;p&gt;
I used to have a habit to start a tmux session right after I have connected to a remote server via SSH. Recently I realised that this action can be automatised. I ended up with the following code-snippet which might be placed into your shell initialisation file (e.g. &lt;b&gt;.bashrc&lt;/b&gt; for &lt;b&gt;bash&lt;/b&gt;):
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-shell&quot;&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt;# &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;Attach to the tmux session on login via SSH.
&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;if&lt;/span&gt; [ &lt;span class=&quot;org-negation-char&quot;&gt;!&lt;/span&gt; -z &lt;span class=&quot;org-string&quot;&gt;&quot;$SSH_CLIENT&quot;&lt;/span&gt; ] &amp;amp;&amp;amp; [ -z &lt;span class=&quot;org-string&quot;&gt;&quot;$DESKTOP_SESSION&quot;&lt;/span&gt; -a -z &lt;span class=&quot;org-string&quot;&gt;&quot;$TMUX&quot;&lt;/span&gt; ] ; &lt;span class=&quot;org-keyword&quot;&gt;then&lt;/span&gt;
    tmux attach -t remote || tmux new -s remote
&lt;span class=&quot;org-keyword&quot;&gt;fi&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
The above-mentioned snippet automatically tries to connect to an existing tmux session named &lt;b&gt;remote&lt;/b&gt; or start a new one when logged-in via SSH. It contains some additional checks, which should be discussed:
&lt;/p&gt;

&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;There is a check for empty &lt;b&gt;DESKTOP_SESSION&lt;/b&gt; environmental variable to avoid connecting to the tmux session from within remote X Session initiated over SSH;&lt;/li&gt;
&lt;li&gt;There is a check for empty &lt;b&gt;TMUX&lt;/b&gt; environmental variable to avoid connecting to the tmux session recursively.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
I believe that being able to automatically reconnect to an existing terminal session is very convenient. I hope you will find it useful too.
&lt;/p&gt;
</description>
				
				<pubDate>Thu, 05 Apr 2018 00:00:00 +0300</pubDate>
				<link>https://chaoticlab.io/unix/hacks/2018/04/05/persistent-remote-session.html</link>
				<guid isPermaLink="true">https://chaoticlab.io/unix/hacks/2018/04/05/persistent-remote-session.html</guid>
			</item>
		
			<item>
				<title>Launch!</title>
				
				
					<description>&lt;p&gt;
So, here goes yet another technical blog. The need to make one emerged after the realisation that I miss technical writing a lot since I left a university. Moreover, I hope that it will help me to improve my written English.
&lt;/p&gt;

&lt;p&gt;
Although I have no particular agenda, you might expect from me writing about computer science, technology, and programming. I am not limiting myself to these topics though. In general, I am going to keep writing about whatever seems interesting to me at the moment or revisit some of my older stuff if there is nothing more entertaining that catches my attention.
&lt;/p&gt;

&lt;p&gt;
Hope to see you soon!
&lt;/p&gt;
</description>
				
				<pubDate>Fri, 30 Mar 2018 00:00:00 +0300</pubDate>
				<link>https://chaoticlab.io/update/2018/03/30/launch.html</link>
				<guid isPermaLink="true">https://chaoticlab.io/update/2018/03/30/launch.html</guid>
			</item>
		
	</channel>
</rss>


