<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
    <channel>
        <title></title>
        <link>https://worrbase.com</link>
        <description></description>
        <generator>Zola</generator>
        <language>en</language>
        <atom:link href="https://worrbase.com/rss.xml" rel="self" type="application/rss+xml"/>
        <lastBuildDate>Fri, 18 Dec 2020 00:00:00 +0000</lastBuildDate>
        
            <item>
                <title>Setting up an OpenBSD Gitlab runner</title>
                <pubDate>Fri, 18 Dec 2020 00:00:00 +0000</pubDate>
                <link>https://worrbase.com/blog/gitlab-openbsd/</link>
                <guid>https://worrbase.com/blog/gitlab-openbsd/</guid>
                <description>&lt;p&gt;I think one of the larger problems I&#x27;ve had when writing software has been doing
proper testing CI on OpenBSD, which for me, obviously is a problem. Much of the
time, I end up either just doing CI on Linux or not setting up CI at all.&lt;&#x2F;p&gt;
&lt;p&gt;There are a few popular CI options available:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;travis-ci.com&quot;&gt;Travis CI&lt;&#x2F;a&gt; (supports linux and macos)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.appveyor.com&quot;&gt;Appveyor&lt;&#x2F;a&gt; (supports Windows, linux and macos)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&quot;&gt;GitHub Actions&lt;&#x2F;a&gt; (supports Windows, linux and macos)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&quot;&gt;GitLab&lt;&#x2F;a&gt; (officially supports Windows, linux, macos and FreeBSD)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Finally, I should mention that there is one platform that does absolutely solve
my problem, definitely better than I will in this blog post. That&#x27;s
&lt;a href=&quot;https:&#x2F;&#x2F;sr.ht&quot;&gt;Sourcehut&lt;&#x2F;a&gt;! They officially have machines for a variety of Linux
platforms, FreeBSD, OpenBSD and &lt;a href=&quot;https:&#x2F;&#x2F;9front.org&quot;&gt;9front&lt;&#x2F;a&gt;, and on a few
different architectures as well!&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m on the fence about sr.ht at the moment, and in general I&#x27;m pretty fond of
GitLab, so I wanted to tackle the issue of having some degree of OpenBSD testing
through GitLab.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;NB&lt;&#x2F;em&gt;: It&#x27;s worth noting that the setup that I&#x27;m going to describe isn&#x27;t
particularly secure, and doesn&#x27;t provide build isolation. CI is quite literally
remote code execution as a service, so the setup I&#x27;m going to describe is not
suitable for colocation with anything else.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;getting-an-openbsd-vm&quot;&gt;Getting an OpenBSD VM&lt;&#x2F;h2&gt;
&lt;p&gt;This isn&#x27;t particularly related to the guide, but if you&#x27;re looking for a
hosting platform that supports OpenBSD, I&#x27;ve enjoyed &lt;a href=&quot;https:&#x2F;&#x2F;vultr.com&quot;&gt;Vultr&lt;&#x2F;a&gt;
quite a bit. I&#x27;ve had fairly good experiences with their support and had p good
uptime with my VMs. They also offer cheap $2.50&#x2F;mo, IPv6-only VMs (yes, GitLab
and the GitLab runner have full IPv6 support, so this is an option).&lt;&#x2F;p&gt;
&lt;p&gt;I should also mention &lt;a href=&quot;https:&#x2F;&#x2F;openbsd.amsterdam&quot;&gt;OpenBSD Amsterdam&lt;&#x2F;a&gt;, which is
run by OpenBSD fans and makes monthly donations to the OpenBSD project with the
proceeds.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;building-the-runner&quot;&gt;Building the runner&lt;&#x2F;h2&gt;
&lt;p&gt;Building is simple. We&#x27;re gonna deviate from the official instructions a bit,
because we don&#x27;t need the helper images or anything.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#2b303b;&quot;&gt;
&lt;span style=&quot;color:#bf616a;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; doas pkg_add bash gmake
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; git clone https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-runner
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; cd gitlab-runner
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; BUILD_PLATFORMS=&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;-osarch openbsd&#x2F;$(arch -s) gmake runner-bin
&lt;&#x2F;span&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The runner binary will be in &lt;code&gt;out&#x2F;binaries&#x2F;gitlab-runner-openbsd-$(arch -s)&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;machine-setup&quot;&gt;Machine setup&lt;&#x2F;h2&gt;
&lt;p&gt;I&#x27;m assuming you&#x27;re starting with a completely fresh install.&lt;&#x2F;p&gt;
&lt;p&gt;First, install the following packages:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#2b303b;&quot;&gt;
&lt;span style=&quot;color:#bf616a;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; doas pkg_add bash git git-lfs curl jq
&lt;&#x2F;span&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Despite GitLab&#x27;s docs saying they support &lt;code&gt;sh&lt;&#x2F;code&gt;, they only support an &lt;code&gt;sh&lt;&#x2F;code&gt; that
supports long options (&lt;code&gt;--login&lt;&#x2F;code&gt;), so we have to use &lt;code&gt;bash&lt;&#x2F;code&gt; here.&lt;&#x2F;p&gt;
&lt;p&gt;We&#x27;re going to run the runner (and our builds) as a separate user, not as root.
There&#x27;s no great way to do proper isolation of arbitrary
binaries on OpenBSD outside of &lt;code&gt;vmd&lt;&#x2F;code&gt;, which I don&#x27;t believe supports nested
virtualization. We could run this in a &lt;code&gt;chroot&lt;&#x2F;code&gt;, but unfortunately it&#x27;d be a
pretty loaded &lt;code&gt;chroot&lt;&#x2F;code&gt;, since the deps for all of our builds would also live in
the &lt;code&gt;chroot&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#2b303b;&quot;&gt;
&lt;span style=&quot;color:#bf616a;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; doas useradd&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt; -s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; &#x2F;sbin&#x2F;nologin&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt; -m&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; gitlab
&lt;&#x2F;span&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If you have other users, I&#x27;d recommend making their home directories unreadable
to others.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#2b303b;&quot;&gt;
&lt;span style=&quot;color:#bf616a;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; doas chmod&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt; -R&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; o-rx &#x2F;home&#x2F;*
&lt;&#x2F;span&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;resources&quot;&gt;Resources&lt;&#x2F;h3&gt;
&lt;p&gt;To reduce the impact of abuse, we&#x27;re gonna try and restrict the usable resources
a bit. We&#x27;re going to modify &lt;code&gt;&#x2F;etc&#x2F;login.conf&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The following values are specific for my use-case, and won&#x27;t necessarily be
applicable for your system.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#2b303b;&quot;&gt;
&lt;span style=&quot;color:#c0c5ce;&quot;&gt;gitlab:\
	:coredumpsize=0:\  # prevent coredumps
	:filesize=30M:\    # largest file can be 30M
	:maxproc=50:\      # max 50 processes
	:datasize=1G:\     # 1G heap per proc
	:stacksize=4M:\    # 4M stack per proc
	:openfiles=512:\   # 512 open files per process
	:tc=default:       # inherit other values from `default` class
&lt;&#x2F;span&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Since I&#x27;m on Vultr, and they have a weird partition scheme where &lt;code&gt;&#x2F;home&lt;&#x2F;code&gt; isn&#x27;t
its own partition, I&#x27;m going to set up filesystem quotas for &lt;code&gt;gitlab&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#2b303b;&quot;&gt;
&lt;span style=&quot;color:#c0c5ce;&quot;&gt;# edit `fstab` to add the `quota` option to `&#x2F;`
$ doas mount -o update,quota &#x2F;
$ doas edquota
$ doas quotaon
$ doas -u gitlab quota
&lt;&#x2F;span&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;network&quot;&gt;Network&lt;&#x2F;h3&gt;
&lt;p&gt;We&#x27;re also going to restrict network access for the &lt;code&gt;gitlab&lt;&#x2F;code&gt; user. We&#x27;ll do this
through adding the following lines to our &lt;code&gt;&#x2F;etc&#x2F;pf.conf&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#2b303b;&quot;&gt;
&lt;span style=&quot;color:#c0c5ce;&quot;&gt;table &amp;lt;github&amp;gt; file &amp;quot;&#x2F;etc&#x2F;pf&#x2F;github&amp;quot;
table &amp;lt;allowed_hosts&amp;gt; const { gitlab.com crates.io static.crates.io }

block out log proto {tcp udp} user gitlab                     # by default block outgoing traffic and log to pflog0
block in proto {tcp udp} user gitlab                          # block any incoming traffic
pass out proto {tcp udp} to 127.0.0.1 port 53 user gitlab     # pass dns traffic
pass out proto tcp to &amp;lt;allowed_hosts&amp;gt; port 443 user gitlab
pass out proto tcp to &amp;lt;github&amp;gt; port 443 user gitlab
&lt;&#x2F;span&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I&#x27;m primarily writing rust, so I just need the three hosts in the
&lt;code&gt;&amp;lt;allowed_hosts&amp;gt;&lt;&#x2F;code&gt; table, as well as whatever IPs github is using that day.
Part of the reason I log blocked outgoing calls, is
that if a build fails due to a network issue, it makes it a lot easier to figure
out what new rules you may have to add to your &lt;code&gt;pf.conf&lt;&#x2F;code&gt; to get builds flowing
again.&lt;&#x2F;p&gt;
&lt;p&gt;To build the github table, I run the following script in an hourly cronjob:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#2b303b;&quot;&gt;
&lt;span style=&quot;color:#65737e;&quot;&gt;#!&#x2F;bin&#x2F;sh

&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;&#x2F;usr&#x2F;local&#x2F;bin&#x2F;curl -sSH &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Accept: application&#x2F;vnd.github.v3+json&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot; https:&#x2F;&#x2F;api.github.com&#x2F;meta |
	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;&#x2F;usr&#x2F;local&#x2F;bin&#x2F;jq --raw-output &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;.api+.git+.web|sort|join(&amp;quot;\n&amp;quot;)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;#39; &amp;gt; &#x2F;etc&#x2F;pf&#x2F;github
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;&#x2F;sbin&#x2F;pfctl -T&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; replace&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt; -t&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; github&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt; -f&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; &#x2F;etc&#x2F;pf&#x2F;github
&lt;&#x2F;span&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Finally, I also add the following to &lt;code&gt;&#x2F;etc&#x2F;ssh&#x2F;sshd_config&lt;&#x2F;code&gt; to prevent this user
from logging in via ssh.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#2b303b;&quot;&gt;
&lt;span style=&quot;color:#c0c5ce;&quot;&gt;DenyUsers gitlab
&lt;&#x2F;span&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;installing-the-runner&quot;&gt;Installing the runner&lt;&#x2F;h2&gt;
&lt;p&gt;To install, copy the binary into &lt;code&gt;&#x2F;usr&#x2F;local&#x2F;bin&lt;&#x2F;code&gt;. I&#x27;d recommend keeping it out of the home directory,
so it&#x27;s harder for a rogue job to overwrite.&lt;&#x2F;p&gt;
&lt;p&gt;I drop the following config file in &lt;code&gt;&#x2F;etc&#x2F;gitlab&#x2F;config.toml&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#2b303b;&quot;&gt;
&lt;span style=&quot;color:#bf616a;&quot;&gt;concurrent &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;check_interval &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;log_level &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;= &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;info&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;

[session_server]
  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;session_timeout &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1800

&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;[[runners]]
  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;name &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;= &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;openbsd-6.8&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;
  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;url &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;= &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;https:&#x2F;&#x2F;gitlab.com&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;
  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;token &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;= &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;&amp;lt;secret&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;
  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;executor &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;= &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;shell&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;
  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;shell &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;= &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;bash&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;
  [runners.custom_build_dir]
  [runners.cache]
    [runners.cache.s3]
    [runners.cache.gcs]
&lt;&#x2F;span&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I also have an rc script to start it&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#2b303b;&quot;&gt;
&lt;span style=&quot;color:#65737e;&quot;&gt;#!&#x2F;bin&#x2F;ksh

&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;daemon&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;=&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;&#x2F;usr&#x2F;local&#x2F;bin&#x2F;gitlab-runner-openbsd-amd64&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;daemon_class&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;=&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;gitlab&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;daemon_user&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;=&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;gitlab&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;daemon_flags&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;=&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;run -c &#x2F;etc&#x2F;gitlab&#x2F;config.toml&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;daemon_timeout&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;60

&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; &#x2F;etc&#x2F;rc.d&#x2F;rc.subr

&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;pexp&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;=&amp;quot;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;daemon&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;} &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;daemon_flags&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;

&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;rc_bg&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;=&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;YES&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;rc_reload&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;NO

&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;rc_pre&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;() {
	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;# There are some interesting network timeouts
	# if I don&amp;#39;t refresh the pf rules
	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;&#x2F;sbin&#x2F;pfctl -f&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; &#x2F;etc&#x2F;pf.conf
}

&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;rc_start&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;() {
	$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;{rcexec} &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;daemon&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;} &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;daemon_flags&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot; &amp;gt;&amp;gt; &#x2F;var&#x2F;log&#x2F;gitlab-runner.log &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;amp;
}

&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;rc_cmd &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;1
&lt;&#x2F;span&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Following all of this, you can &lt;a href=&quot;https:&#x2F;&#x2F;docs.gitlab.com&#x2F;runner&#x2F;register&#x2F;&quot;&gt;just follow the normal gitlab
instructions&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;Does this work?&lt;&#x2F;p&gt;
&lt;p&gt;Well, yeah.&lt;&#x2F;p&gt;
&lt;p&gt;The big problem is that I wouldn&#x27;t necessarily call this secure by any means. At the end of the
day, users submitting PRs to my project that use this runner are still able to run arbitrary code
on my gitlab runner. All CI&#x2F;CD is remote code execution as a service. Even with the steps taken
above, there are still ripe opportunities for abuse.&lt;&#x2F;p&gt;
&lt;p&gt;I definitely don&#x27;t feel comfortable integrating this machine with my personal infrastructure. I&#x27;m
certainly not setting it up to forward mail to my mail servers, since that&#x27;d require a key on the
box. For now, this is roughly the best I think I&#x27;ll do.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;what-would-be-better&quot;&gt;What would be better?&lt;&#x2F;h3&gt;
&lt;p&gt;Ephemeral VMs (also with similar settings) would be the ideal here. If vmd supported nested VMs,
it&#x27;d be awesome to add vmd support to the gitlab runner and launch all of my jobs in individual VMs.
Alas, as far as I&#x27;m aware, this would only be possible if I had a bare metal machine handy.
VirtualBox on a non-OpenBSD platform could also be a fair option worth exploring.&lt;&#x2F;p&gt;
&lt;p&gt;For right now, this works for my case, is cheap enough, and this VM is essentially ephemeral to
me and easily trashed if I need to replace it for any reason.&lt;&#x2F;p&gt;
&lt;p&gt;Feel free to reach out if you think that there are ways to improve on this setup, or if I got
something super wrong.&lt;&#x2F;p&gt;
</description>
            </item>
        
            <item>
                <title>Final Fantasy VI</title>
                <pubDate>Tue, 06 Oct 2020 00:00:00 +0000</pubDate>
                <link>https://worrbase.com/games/ffvi/</link>
                <guid>https://worrbase.com/games/ffvi/</guid>
                <description>&lt;p&gt;For the longest time, I always considered this game one of my favorites,
despite never finishing. I started it for the very first time on emulator
somewhere around 2002 or 2003? I started it a number of times since then, but
never finished it nor usually ever made it to the World of Ruin.&lt;&#x2F;p&gt;
&lt;p&gt;But the other day, I finally finished it! Now I feel like I can say with certainty
that it&#x27;s one of my favorite games, if not my favorite game of all time.&lt;&#x2F;p&gt;
&lt;p&gt;There will be &lt;strong&gt;FULL SPOILERS&lt;&#x2F;strong&gt; for &lt;strong&gt;EVERYTHING&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;it-ain-t-perfect&quot;&gt;It ain&#x27;t perfect&lt;&#x2F;h3&gt;
&lt;p&gt;So before I start heaping praise upon praise on this game, I really want to make
sure I account for the problems with this game.&lt;&#x2F;p&gt;
&lt;p&gt;The SNES version of this game launched with some horrible, game-breaking bugs.
The most infamous, is the Sketch Bug, where using Relm&#x27;s &lt;code&gt;Sketch&lt;&#x2F;code&gt; ability
could cause the game to crash at best or corrupt your save at worst.&lt;&#x2F;p&gt;
&lt;p&gt;A smaller bug that still heavily impacts gameplay, is that the &lt;code&gt;Evade%&lt;&#x2F;code&gt; stat
just doesn&#x27;t mean anything. Instead, &lt;code&gt;MBlock%&lt;&#x2F;code&gt; (your chance of evading magic
attacks) controls both magic evasion and normal evasion. It&#x27;s also very easy
to max out &lt;code&gt;MBlock%&lt;&#x2F;code&gt;, which on an unpatched version makes you virtually
invincible in many cases.&lt;&#x2F;p&gt;
&lt;p&gt;The English translation is &lt;a href=&quot;https:&#x2F;&#x2F;legendsoflocalization.com&#x2F;final-fantasy-vi&#x2F;&quot;&gt;notoriously
bad&lt;&#x2F;a&gt;. It&#x27;s not just bad
in the sense that there are outdated references, or that perhaps some
characterization doesn&#x27;t match the original dialog, but in some cases the
dialog is outright incorrect. It does have some unique characterization
though, a lot of which has been brought into other games (more on that later).&lt;&#x2F;p&gt;
&lt;p&gt;One of the other big problems with this game is how unbalanced the characters
are. Each character has different base stats, and one unique ability that
they&#x27;re able to use in addition to &lt;code&gt;Attack&lt;&#x2F;code&gt; and &lt;code&gt;Magic&lt;&#x2F;code&gt;. The problem here
though, is that &lt;code&gt;Magic&lt;&#x2F;code&gt; is far, far better than pretty much any ability late
game, and many of the abilities suck. Some of the worst offenders:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Relm - &lt;code&gt;Sketch&lt;&#x2F;code&gt; uses an enemy&#x27;s ability against it...although oftentimes
enemies are resistant to their own abilities. It also tends to be pretty weak.
Relm is honestly only saved by her monster magic stat.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Celes - &lt;code&gt;Runic&lt;&#x2F;code&gt; prevents any magic from being cast, and converts it into MP
for Celes. While it&#x27;s good early game, late-game you should be casting too
much magic for it to be useful anymore. Celes is saved by having some of the
best equipment and being one of the best magic casters.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Strago - &lt;code&gt;Lore&lt;&#x2F;code&gt; is essentially blue magic. I love blue magic in FF games,
but unfortunately Strago&#x27;s stats suck, and also &lt;code&gt;Lore&lt;&#x2F;code&gt;s have wildly marked
up MP costs compared to basic spells. It ends up not being worthwhile to use
most &lt;code&gt;Lore&lt;&#x2F;code&gt;s late-game, at least in my experience (the exception here being
Mighty Guard).&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Cyan - &lt;code&gt;Bushido&#x2F;SwdTech&lt;&#x2F;code&gt; is a skill where you wait while a bar slowly fills
up, and then it performs an attack based on how long you let it fill up. The
abilities are never anything too special, and it takes &lt;em&gt;way too long&lt;&#x2F;em&gt; to
actually charge the bar up meaningfully.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Setzer - &lt;code&gt;Slots&lt;&#x2F;code&gt; is a slot game. The attack depends on what the slots land
on, and if you don&#x27;t make a match, you get an incredibly weak MT heal on the
party.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Mog - &lt;code&gt;Dance&lt;&#x2F;code&gt; performs random attacks based on the dance you select. Most of
these aren&#x27;t great for much of the game? I honestly just found the most
utility just equipping Mog with spears and the two &lt;code&gt;Jump&lt;&#x2F;code&gt;-related relics.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The others are mostly passable, but ideally I&#x27;d love to see a theoretical
version of this game with much better balanced versions of these special
abilities, and perhaps slightly nerfed magic to make sure that specials keep
being relevant late-game.&lt;&#x2F;p&gt;
&lt;p&gt;So onto all the ways that this game is great!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;characters&quot;&gt;Characters&lt;&#x2F;h3&gt;
&lt;p&gt;I think one of the things that folks tend to remember about this game are all
14 (ok well you know the 12 important ones) characters. Despite them not
having enough time for full arcs, they mostly have mini-arcs but also clear
characterization, even in the English version.&lt;&#x2F;p&gt;
&lt;p&gt;One of the more interesting decisions is that FFVI is not intended to
have one main character? I know growing up, I always considered Locke the main
character, since he was the first man that joined the party, and young me
hadn&#x27;t yet understood the idea that women can be protags too. Now after
completing it, I definitely feel like Celes is closer to being something like
a main protag, since she&#x27;s one of the three required characters at the end,
and she undergoes the most character growth.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;celes&quot;&gt;Celes&lt;&#x2F;h4&gt;
&lt;p&gt;Celes starts her story as a general of the evil empire that serves as the Big
Bad for the World of Balance. Locke rescues her, but when they rejoin the party,
there&#x27;s this great scene where, as the party meets her, they all interrogate her
as to her true motives. Once they begin to trust her more, they end up finding
out that her dad is a researcher for the Empire, and the Big Bad lies to the group
that Celes has been working for them the whole time.&lt;&#x2F;p&gt;
&lt;p&gt;After the World of Ruin, Celes ends up on an island taking care of her father,
Cid, and he most likely dies (more on that in a bit). Celes ends up trying to commit
suicide, before going on an adventure to round up all of her friends. And it&#x27;s
wonderful to see them all reunite in a ruined world, and the slow reunion kind of
highlights how they&#x27;ve grown to respect and care about Celes throughout the
story.&lt;&#x2F;p&gt;
&lt;p&gt;Celes was definitely the main character I was most invested in, especially
throughout the World of Ruin. The whole of the island scenes really makes the
despair of the World of Ruin feel truly palpable. You see someone who starts off
as a fairly strong character get understandably broken by the end of the world
and the death of her father, and that really moved me. That really made me feel
like things in the World of Ruin were truly hopeless.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;terra&quot;&gt;Terra&lt;&#x2F;h4&gt;
&lt;p&gt;Terra is another one of the main-ish characters that&#x27;s worth a mention. You start
off as her, enslaved by Kefka and torching people in a neutral city to retrieve
an Esper. Terra ends up being able to speak with the Esper, and her resonance
with the Esper is what ends up kicking off the whole tale.&lt;&#x2F;p&gt;
&lt;p&gt;She reluctantly joins the Returners, a group fighting against the Gestahlian
Empire. As the game progresses, she discovers that she ends up being the child
of an Esper and a human, stolen by the Empire to be turned into a weapon. She
feels a kinship with the Espers who are being kidnapped and murdered by the
Empire, and that kinship is what ends up driving her to fight against them.&lt;&#x2F;p&gt;
&lt;p&gt;One of the things that I really thought the game did a good job of conveying is
Terra&#x27;s sense of empathy and her role as a caretaker. One of the first ways that
we see this, is the first time she morphs into her Esper form. She flies away
out of control, and ends up confronting a child, before flying away again. When
your party encounters and talks to the child, he makes it clear that Terra had
kind eyes, and it was clear to him that she wasn&#x27;t going to hurt him, despite
how his parents had feared for his life.&lt;&#x2F;p&gt;
&lt;p&gt;Later, we see this in how she seems to feel so deeply for the Espers in
captivity in the Magitek Research Facility. Seeing them trapped in tubes is
clearly heartbreaking for her, moreso because she knows that she&#x27;s essentially
one of them.&lt;&#x2F;p&gt;
&lt;p&gt;Finally, in the World of Ruin, Celes discovers that Terra saved all of the
children of Mobliz before it was destroyed, and is now raising...all of them.
The kids adore her, calling her Mama Terra, and are greatly saddened when you
eventually take her away to help save the world.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;kefka&quot;&gt;Kefka&lt;&#x2F;h4&gt;
&lt;p&gt;Kefka is the most memorable character though. He&#x27;s this
sadistically evil clown that&#x27;s mad with power, and he &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=PqtOWpNAs48&quot;&gt;has an absolutely dope
theme song&lt;&#x2F;a&gt;.
Kefka&#x27;s rise to power and his worsening sadism is one of the stand-out points of
this game. Kefka transforms from a character that wanted to ascend the ranks of
the Gestahl Empire to a being whose thirst for power was unquenchable.&lt;&#x2F;p&gt;
&lt;p&gt;At the start of the game, Kefka is a high-ranking general in Gestahl&#x27;s army,
leading a batallion of troops to Figaro Castle to interrogate the king about
hiding Terra, who had escaped from the Empire&#x27;s clutches earlier.  However, the
king is less than helpful, Kefka throws a bit of a tantrum and light&#x27;s Figaro
castle, ostensibly an ally of the empire until that point, on fire. When Figaro
Castle submerges itself into the dessert, Kefka utters one of his most famous,
incorrectly translated, lines: &lt;a href=&quot;https:&#x2F;&#x2F;legendsoflocalization.com&#x2F;son-of-a-submariner-kefkas-famous-line-in-detail&#x2F;&quot;&gt;&amp;quot;Son of a
submariner!&amp;quot;&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Some time later, Sabin and Shadow happen upon Kefka at a Gestahlian camp laying
siege to Doma Castle. He shows up to the camp telling General Leo that the
Emperor is calling him away on other business (an outright lie). Leo leaves,
warning Kefka not to do anything evil, and Kefka promptly orders that the moat
surrounding the castle be poisoned. Wildly, I guess that Doma&#x27;s moat is their
primary water supply, since shortly after, everyone but Cyan drops dead from
poison, leading to a quick end to the siege of Doma.&lt;&#x2F;p&gt;
&lt;p&gt;Towards the midpoint of the game, Gestahl tricks your party and General Leo in getting Espers to
meet the Empire in a neutral town for a ceasefire. Kefka shows up, purportedly
on Gestahl&#x27;s orders, murders General Leo, murders all of the Espers and burns
the town, killing most of the folks living there.&lt;&#x2F;p&gt;
&lt;p&gt;In the transition from the WoB to the WoR, Kefka takes a turn in that he stops
working for the Emperor, and instead betrays the Emperor in pursuit of becoming
a God and destroying the world. Once a God, Kefka destroys towns seemingly at
random, out of what appears to be hatred for humankind.&lt;&#x2F;p&gt;
&lt;p&gt;These scenes, as well as  a few others that I&#x27;ve left out, really had an effect
of me. They cemented Kefka in my mind as unabashedly evil, and his
lightheartedness in perpetrating these acts always made all of these things far
more disquieting. His horrifying actions always felt like they gave the main
quest urgency and real consequences. They also served as the most memorable
moments in the game for me, stuff that stuck with me throughout childhood and
well into adulthood.&lt;&#x2F;p&gt;
&lt;p&gt;One of the weaker parts of his character is that there doesn&#x27;t
appear to be any motivation for his ascent to power. The best we get comes from
some optional dialog in a random town, where someone in a tavern mentions that
Kefka was the first Magitek knight and had suffered severe brain damage as a
result. Honestly, I don&#x27;t love that justification and wish that Kefka&#x27;s
backstory had been expanded on in a meaningful way.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;characterization-in-general&quot;&gt;Characterization in general&lt;&#x2F;h4&gt;
&lt;p&gt;I think one of the more interesting things that this game does is the general
case of how you learn about characters&#x27; backstories. The game almost never forces you
to learn about most of the characters. There are a few cases, like with Celes
and her dad, where through playing the main game, they do character development.
In the character sections above, there are even clear examples. Without talking
to a random NPC in a tavern, you&#x27;d never find out how Kefka became unhinged.
Without talking to that random child, you&#x27;d never discover that Terra had that
moment as an Esper with a child. Without discovering the hidden orphanage in the
wreckage of Mobliz, you&#x27;d never realize that Terra had adopted a horde of small
children.&lt;&#x2F;p&gt;
&lt;p&gt;There are more extreme examples of this type of storytelling, one of them being
Gau. Gau is a child that you discover on the Veldt, that joins your party when
you toss him some meat. If you avoid talking to random NPCs, that&#x27;s quite
literally all you know about him. He undergoes no character development; at most
you&#x27;re treated to some &lt;a href=&quot;https:&#x2F;&#x2F;legendsoflocalization.com&#x2F;final-fantasy-vi&#x2F;part-05&#x2F;#the-name-is-mr-thou&quot;&gt;fun
scenes&lt;&#x2F;a&gt;
where Gau calls Cyan &amp;quot;Mr. Thou&amp;quot; because of his speech patterns.&lt;&#x2F;p&gt;
&lt;p&gt;However, if you talk to some NPCs in Mobliz, you find out that a neglectful old
man had a mental break, confused his child for a monster and threw him out into
the Veldt. Later in the game, when you get an airship, you can even find this
old man, and lead Gau to him. If you do so, you get a cutscene where your party
tries its best to dress Gau up in a fancy suit and reintroduce him to his
father. It starts off touching, but when it becomes clear that his father is
never going to remember him, Gau backs off saddened, but at least secure in the
knowledge that his father is safe.&lt;&#x2F;p&gt;
&lt;p&gt;That&#x27;s a really cool scene! But it&#x27;s trivially missable! I have very mixed
feelings about this approach, but I think one of the strongest arguments for it
is that these scenes feel more earned, in a way. When you think to bring Gau to
see that random old man speaking nonsense in a hut, it feels like you&#x27;re getting
rewarded with backstory for making that connection. It feels much less like the
game is forcing its narrative upon you, and instead that it&#x27;s letting you
discover its narrative.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s also one of the things that I think makes different people&#x27;s playthroughs
of this game unique. Not everyone is going to uncover the same parts of the
characers&#x27; backstories, and that breeds discussion and commentary, which I think
is pretty cool.&lt;&#x2F;p&gt;
&lt;p&gt;At the same time, if any of my friends play this game, I wonder how much of
these sidestories they&#x27;ll actually discover. It&#x27;s almost sad that they may not
get the same experience with the characters of FFVI that I did. I love these
characters, I enjoyed their stories and I want my friends to be able to enjoy
them as well.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;ambitious&quot;&gt;Ambitious&lt;&#x2F;h3&gt;
&lt;p&gt;This game is one of the most ambitious games that I&#x27;ve played on the
Super Nintendo, and honestly I think that that is both positive and negative.
Really the only negative is that they crafted characters and a world that I
wanted to see &lt;em&gt;more&lt;&#x2F;em&gt; of. There are 14 characters in this game, and 12 of them
have some degree of backstory...and unfortunately there&#x27;s not enough time or
space on the cartridge to flesh all 12 of these characters out enough as well
as handle the story.&lt;&#x2F;p&gt;
&lt;p&gt;The story feels a lot more high stakes than a lot of Final Fantasy games that
I&#x27;ve played. The world &lt;em&gt;ends&lt;&#x2F;em&gt; in this game. Whole towns are destroyed.
Arguably the whole merged world situation from FFV seems like it should be
more destructive, but it doesn&#x27;t seem to have the impact that Kefka creating
the world of ruin does. Compared to the merging of worlds in FFV, so many more
people clearly die from Kefka creating the world of ruin.&lt;&#x2F;p&gt;
&lt;p&gt;FFVII seems to have similarly high stakes, since the end of the world is also
on the table in that game, but Sephiroth &lt;em&gt;isn&#x27;t successful&lt;&#x2F;em&gt; with his plan. In
FFVI you&#x27;re cleaning up a world destroyed, whereas in many other FF&#x27;s you&#x27;re
trying to prevent it.&lt;&#x2F;p&gt;
&lt;p&gt;Once you&#x27;re in the World of Ruin, everything seems incredibly bleak. Like I
said, Celes tries to commit suicide. The overworld music has gone from
&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=a6t_uyg_pF8&quot;&gt;traditional jrpg fare&lt;&#x2F;a&gt; to a &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=06LGnRvN6E8&quot;&gt;sad,
almost dirge-like tune&lt;&#x2F;a&gt;. When you
get to towns, you see people living in absolute ruin. People talk about the
deaths of their families and friends. Characters that you did quests for in the
WoB are now dead, ultimately because you &lt;em&gt;failed&lt;&#x2F;em&gt; to save them and their world.
You failed, and you are feeling the full effects of it. Now, instead of you and
your friends working together to save the world, you&#x27;re alone. You&#x27;re alone and
you feel it. And when you start off, you&#x27;re just hoping your friends have
&lt;em&gt;survived&lt;&#x2F;em&gt; and you&#x27;re trying to find them.&lt;&#x2F;p&gt;
&lt;p&gt;This tonal shift is also accompanied by a change in the gameplay. The first half
of the game was a typical, linear jrpg. However, once we switch to the World of
Ruin, the rails are gone. You can go anywhere as you try to find out if your
friends even survived. Before, you had not just a goal, but you were told where
to go and how to achieve it, by either the folks in your party or NPCs. Once the
world ends, you&#x27;re not just alone in the sense that your party members are gone,
you&#x27;re also alone in the sense that nobody is telling you what to do anymore.
You just have to figure it out on your own.&lt;&#x2F;p&gt;
&lt;p&gt;From here, the game turns into much more of an open-world affair. You can go
anywhere, you can get your party members in any order and there&#x27;s actually very
little that the game forces you to do in terms of progression. One popular FFVI
run that I learned about during this playthrough is called a CES run, where you
only get Celes, Edgar and Setzer (the required characters) and complete the game.&lt;&#x2F;p&gt;
&lt;p&gt;One of the wildest parts of all this is that the World of Ruin only happened
because FFVI was &lt;em&gt;ahead of schedule&lt;&#x2F;em&gt;, and the &lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;christinelove&#x2F;status&#x2F;1290497444040437762&quot;&gt;devs decided on a whim to add it&lt;&#x2F;a&gt;.
I cannot even imagine this game without the World of Ruin; it wouldn&#x27;t have had
nearly the emotional impact without it.&lt;&#x2F;p&gt;
&lt;p&gt;Honestly, for the time, opening up a jrpg like this was quite a departure from
the rest of the gaming landscape. Sidequests were of course pretty common, but
making whole swathes of what&#x27;s conceivably the story was markedly different from
other popular jrpgs of the time. Even in other FF games of the time, when you
got your airship, there&#x27;d still be a clear quest-line you would have to follow
that was still very linear.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;choice&quot;&gt;Choice&lt;&#x2F;h3&gt;
&lt;p&gt;One thing that struck me as particularly unique about FFVI was the types of
choice that the game presented you with, and how it can directly impact the
gameplay experience you have.&lt;&#x2F;p&gt;
&lt;p&gt;When we talk about choice in video games, it&#x27;s oftentimes the bs Mass Effect
Paragon&#x2F;Renegade dialog-tree-based system: NPC says thing, you can reply in a
certain way that adds or removes points on some kind of purity meter.&lt;&#x2F;p&gt;
&lt;p&gt;FFVI goes about presenting options to the player in an incredibly different way.
Honestly, it doesn&#x27;t really present them at all.&lt;&#x2F;p&gt;
&lt;p&gt;There are very few major choices that you can make that affect the story. I
think there are only two? There are only two that I&#x27;m going to discuss here
anyway.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;killing-shadow&quot;&gt;Killing Shadow&lt;&#x2F;h4&gt;
&lt;p&gt;Shadow is a merc that, in the WoB, will join your party for a fee and will leave
when the mood suits him. We also see him work for the Empire in parts of the
WoB, reinforcing that he&#x27;s the type that&#x27;d &lt;a href=&quot;https:&#x2F;&#x2F;legendsoflocalization.com&#x2F;final-fantasy-vi&#x2F;part-02&#x2F;#slittin-throats-and-takin-money&quot;&gt;slit his mama&#x27;s throat for a
nickel&lt;&#x2F;a&gt;.
However, we see him change throughout the story, and develop affection for some
of the characters in your party, particularly relating to both Terra and Relm.&lt;&#x2F;p&gt;
&lt;p&gt;Once we get to the Floating Continent, we see that Shadow has been tossed aside
by the Empire and that they even tried to have him killed. Shadow rejoins your
party throughout the Floating Continent, and fights on your side for the
remainder of the game, or his life.&lt;&#x2F;p&gt;
&lt;p&gt;Right as the world begins to end, Shadow says that he&#x27;s going to distract Kefka
while the others escape, and to wait up before jumping on the airship and fleeing.
However, when he says, &amp;quot;wait up,&amp;quot; he means it. As you race against the clock
towards the airship, if you don&#x27;t wait until quite literally the last second
before jumping on the airship, Shadow dies as the world ends.&lt;&#x2F;p&gt;
&lt;p&gt;What I like about this, is that the signal to the player is subtle. It&#x27;s a real
thing that Shadow asks, and the game doesn&#x27;t break the 4th wall in any way to
let you know that not waiting will result in Shadow dying. It&#x27;s even makes
sense to think that if you get into the airship early, you&#x27;ll just see Shadow
run and jump aboard regardless of what you do.&lt;&#x2F;p&gt;
&lt;p&gt;If you do end up killing Shadow,
the game doesn&#x27;t even really tell you that you could&#x27;ve prevented his death.
Imagine killing Shadow, not realizing you could save him, and then chatting with
a friend that &lt;em&gt;did&lt;&#x2F;em&gt; save him. I like that the subtlety of this choice very
likely prompted these types of conversations, as well as wonder as to what else
could&#x27;ve been a choice.&lt;&#x2F;p&gt;
&lt;p&gt;Another big consequence of this choice is that you end up missing out on the
majority of Shadow&#x27;s backstory. You get some bits of it in the World of Balance,
but a lot of it is discovered in the WoR. Killing him cuts out that whole
storyline.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;killing-cid&quot;&gt;Killing Cid&lt;&#x2F;h4&gt;
&lt;p&gt;When we start in the World of Ruin, we play as Celes sharing a cottage with a
sick Cid. To stop him from dying, you need to go down to the beach, catch
some fish and feed them to Cid. The catch though, is that not all fish help
equally, and it&#x27;s timed. There&#x27;s no timer on-screen, his condition just quietly
gets worse.&lt;&#x2F;p&gt;
&lt;p&gt;If you don&#x27;t have the running shoes equipped, and you don&#x27;t already know which
fish are better for Cid, it&#x27;s very likely that he&#x27;ll die. Any of the times I
played without a guide, I never was able to save him. On this playthrough, I
could&#x27;ve saved him, but I decided to let him die on purpose, because I think
Celes&#x27; arc is so much more powerful with the death of her father.&lt;&#x2F;p&gt;
&lt;p&gt;While this
choice doesn&#x27;t have gameplay implications like letting Shadow die, it does
heavily change the tone of Celes&#x27; story.
If you don&#x27;t save Cid, Celes tries to commit suicide and only regains the will
to live by finding Locke&#x27;s headband - a sign that he might still be out there
and alive. You find a note from Cid about a raft he&#x27;s been working on, and you
set out to find your friends.&lt;&#x2F;p&gt;
&lt;p&gt;If you do save him, well, Cid just tells you about the raft he built and sends
you on your way. I don&#x27;t really like this route, since it&#x27;s much more satisfying
to see Celes pull herself together from the edge of utter despair.&lt;&#x2F;p&gt;
&lt;p&gt;Both of these choices profoundly change the tone of the story, and the game
never hits you over the head with them. There&#x27;s no little ding, there&#x27;s no meter
tracking your morality and most importantly, it&#x27;s very possible to play through
the game not recognizing that either scenario could&#x27;ve played out any
differently.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;blue-magic&quot;&gt;Blue Magic&lt;&#x2F;h3&gt;
&lt;p&gt;One of the more unique types of magic that frequently recurs in FF games is
blue magic. Blue magic allows you to learn some of the attacks of your enemies,
although the mechanics vary significantly from game to game. However, where
this game differs from previous (and as far as I&#x27;m aware, subsequent) entries,
is that there are essentially 3 different types of blue magic: Lores, Sketch and
Rages.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;lores&quot;&gt;Lores&lt;&#x2F;h4&gt;
&lt;p&gt;Lores are Strago&#x27;s special skill, and function like blue magic does in previous
entries in the series. To learn a new spell, Strago has to witness an enemy
casting it while not being impaired by certain status elements. After he&#x27;s seen
an enemy use a magic attack, he can use it from then on.&lt;&#x2F;p&gt;
&lt;p&gt;Like I mentioned earlier though, these kind of suck unfortunately. The big problem
isn&#x27;t that any of the actual skills suck, in fact many of the spells are
traditional FF blue magic spells, but it&#x27;s that they cost tons of MP compared to
the traditional white, black and grey magic and tend to have worse damage output
or effects as well. Since late-game FFVI is all about maximizing damage output
through magic casting, blue magic just doesn&#x27;t make sense in the magic economy.
If Strago had a better magic stat and&#x2F;or if the MP cost of blue magic was
reduced, it could&#x27;ve had a much larger role in the game.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;sketch&quot;&gt;Sketch&lt;&#x2F;h4&gt;
&lt;p&gt;Sketch is Relm&#x27;s special skill, and it just executes one of the enemy&#x27;s specific
skills against it. As I mentioned before, this does unfortunately have the
massive drawback of the enemy often resisting its Sketch move. Relm also has the
opposite problem of Strago, in that her magic stat is super high, so using
Sketch instead of casting high-powered magic almost never makes sense.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;rages&quot;&gt;Rages&lt;&#x2F;h4&gt;
&lt;p&gt;Rages are Gau&#x27;s skill, and they&#x27;re one of the best in the game. So far, of the
FF games that I&#x27;ve played (FF4-8, FF10 and FF15), there hasn&#x27;t been any other
ability like it. I guess there are technically skills with the word &amp;quot;Rage&amp;quot; in
them, but they have always functioned like traditional blue magic, rather than
Gau&#x27;s Rage.&lt;&#x2F;p&gt;
&lt;p&gt;With Rage, you pick an enemy and cede control of Gau completely. Gau then adopts
a limited version of that enemy&#x27;s moveset, as well as their resistances and
weaknesses for the rest of the battle. To
actually acquire these Rages, you have to go to the Veldt, an area where every
enemy you&#x27;ve ever encountered will spawn, and use another Gau skill called
&amp;quot;Leap&amp;quot; on the enemy party. Gau will leave your party for a couple of battles,
and will come back with the Rage of all of the enemies in that encounter.&lt;&#x2F;p&gt;
&lt;p&gt;For background, blue magic in all FF games is generally limited to roughly 10-30
spells, depending on the game. But remember, I said that every enemy appears on
the Veldt. That&#x27;s right...pretty much every enemy, and even some bosses, are
available to you as Rages. That ends up being roughly 250 different Rages that
you can learn. There are (incredibly necessary) guides that &lt;a href=&quot;https:&#x2F;&#x2F;gamefaqs.gamespot.com&#x2F;ps&#x2F;562865-final-fantasy-vi&#x2F;faqs&#x2F;35118&quot;&gt;cover this topic in
great
detail&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;This provides an incredible amount of flexibility, and the payoffs of learning
the system well actually turn out to be worth it, making Gau one of the better
characters throughout the game. Really the only downside is that it&#x27;s difficult
to organically understand all of the Rages and their trade-offs, since there are
so many, and their various trade-offs aren&#x27;t always clear without a guide.
Learning how to milk the Rage system ended up being one of the more fun parts of
my most recent play-through.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;limit-breaks&quot;&gt;Limit breaks&lt;&#x2F;h3&gt;
&lt;p&gt;Notably, FFVI is the first game that featured the mechanic that turned into
Limit Breaks! It&#x27;s hinted at in the Beginner&#x27;s house, which serves as kind of
the in-game manual for new players. One of the people there says to &amp;quot;try using
the Fight command when you&#x27;re low on health.&amp;quot; What that practically means, is that
there&#x27;s a chance that if you attack at low health, you&#x27;ll execute a unique,
powerful move that sometimes will also yield instant death to an enemy.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=cnYdopVjOj8&quot;&gt;Here&#x27;s a quick video exhibition&lt;&#x2F;a&gt;,
since it&#x27;s kinda cool to see. I didn&#x27;t encounter any of these in
my playthrough, unfortunately.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;setting&quot;&gt;Setting&lt;&#x2F;h3&gt;
&lt;p&gt;In terms of setting, FFVI was the first game that really pushed the fusion of
the industrial and more traditionally magical settings that are familiar in more
modern entries of Final Fantasy.&lt;&#x2F;p&gt;
&lt;p&gt;FFVI has a number of towns all in different stages of development. There&#x27;s the
highly-industrialized Vector, which serves as the location of the high tech
Magitek Research Facility as well as the seat of the Empire. In this area, homes
are made of brick and steel, and the brutalist fortress housing the Emperor
towers over the populace. Vector seems very much like a scaled down version of
Midgar in FFVII, in a way. It&#x27;s the center of not just power, but also technology.&lt;&#x2F;p&gt;
&lt;p&gt;Contrast this to a town like Mobliz or Thamasa. These towns are very similar to
towns you&#x27;d encounter in FFV or earlier, where there are a few simple homes and
shops, but no real industry.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h3&gt;
&lt;p&gt;FFVI slaps. I&#x27;m not sure that these posts will ever have a real conclusion. I
also didn&#x27;t really plan this out, so there&#x27;s not really a point to this post,
other than expressing some of the aspects of this game that really caught my attention.&lt;&#x2F;p&gt;
&lt;p&gt;My hottest take on this game is that FFVI walked so that FFVII could run.
Honestly, this game feels in many ways like a spiritual predecessor (and I guess
it&#x27;s also the literal predecessor) to FFVII. Many ideas, like the hybridization
of magic and tech, the technology capitol being the seat of authoritarian power,
the unhinged, sadistic general disobeying orders to become the Big Bad after
spend their early life as a science experiment. It seems like FFVII fleshed out
and refined a lot of the ideas that FFVI had developed.&lt;&#x2F;p&gt;
&lt;p&gt;Despite this, my biggest dream would be for FFVI to get the FFVII:Remake
treatment. I&#x27;d love an opportunity to revisit this world and to see how the
developers would expand upon the environment and the characters with more time.
I&#x27;d love to see Vector, Narshe and Figaro get the HD treatment. I&#x27;d love to see
an update to the battle system that gave some of the worse characters more
opportunity. The biggest problem that FFVI has in my eyes, is that I&#x27;m left
wanting more, and I&#x27;m left wanting to see what developers today could do with
the framework that it built on the SNES. Hopefully someday, I&#x27;ll get my wish.&lt;&#x2F;p&gt;
</description>
            </item>
        
            <item>
                <title>What is this?</title>
                <pubDate>Fri, 03 Jul 2020 00:00:00 +0000</pubDate>
                <link>https://worrbase.com/games/intro/</link>
                <guid>https://worrbase.com/games/intro/</guid>
                <description>&lt;p&gt;I play &lt;em&gt;a lot&lt;&#x2F;em&gt; of jrpg&#x27;s, and I wanted a place to just write about my thoughts.
I figured rather than create a new tumblr or create a new site, I&#x27;d add them
onto my personal blog.&lt;&#x2F;p&gt;
&lt;p&gt;I mostly want to have this space as a place to ramble about jrpgs, so that when
I&#x27;m trying to remember my favorite parts, or the story, or talk to someone about
what I liked or disliked, I have a reference of my thoughts while playing it to
refer to.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m not writing formal reviews, I&#x27;m not trying be a games journalist or
whatever, I&#x27;m writing first and foremost for myself. In light of that,
everything I write will have &lt;strong&gt;full spoilers&lt;&#x2F;strong&gt; for whatever game I&#x27;m talking
about. Honestly, I like sharing my thoughts on games&#x27; endings with my friends,
so avoiding writing about them out of fear that I might spoil something for some
rando reading this defeats the purpose.&lt;&#x2F;p&gt;
</description>
            </item>
        
            <item>
                <title>Extended Attributes</title>
                <pubDate>Wed, 30 Dec 2015 00:00:00 +0000</pubDate>
                <link>https://worrbase.com/blog/extended-attributes/</link>
                <guid>https://worrbase.com/blog/extended-attributes/</guid>
                <description>&lt;p&gt;While working on &lt;a href=&quot;http:&#x2F;&#x2F;onwednesdayswewear.pink&#x2F;post&#x2F;132589889688&#x2F;pythons-osgetxattr&quot;&gt;support for FreeBSD&#x27;s extended attributes in
python&lt;&#x2F;a&gt;,
I tried to be conscious of other implementations of extended attributes in
different operating systems, that way I wouldn&#x27;t be inadvertently causing the
sane problem that I was trying to fix: reliance on a particular API&#x27;s
semantics.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-are-extended-attributes&quot;&gt;What are extended attributes?&lt;&#x2F;h2&gt;
&lt;p&gt;To put it very simply, extended attributes are metadata that are attached to
files. Typically, they&#x27;re key&#x2F;value pairs that the filesystem associates with
a particular file on the filesystem, though that doesn&#x27;t always have to be the
case.&lt;&#x2F;p&gt;
&lt;p&gt;How they&#x27;re implemented depends on both the filesystem, as well as the
operating system. This means that implementations on the same filesystem (UFS,
for example) can be complete incompatible across operating systems (Solaris
and FreeBSD).&lt;&#x2F;p&gt;
&lt;p&gt;Extended attributes are not mandated by &lt;em&gt;any&lt;&#x2F;em&gt; standard. The tooling and APIs
are quite different across operating systems and some operating systems (OpenBSD, HP-UX)
don&#x27;t implement them at all. Because support is non-standard and spotty,
it&#x27;s rare to see them used in cross-platform software. I&#x27;d be super-interested
in seeing some counter-examples to this.&lt;&#x2F;p&gt;
&lt;p&gt;Extended attributes are &lt;em&gt;sometimes&lt;&#x2F;em&gt; namespaced. That is to say, there exists
some top-level grouping of attributes. Other than the top-level namespace,
there usually isn&#x27;t hierarchy to attributes, other than any arbitrary
user-defined hierarchy. Namespaces are usually &lt;code&gt;system&lt;&#x2F;code&gt; and &lt;code&gt;user&lt;&#x2F;code&gt;, although
this isn&#x27;t necessarily consistent, as we&#x27;ll see. Extended attributes under the
&lt;code&gt;system&lt;&#x2F;code&gt; namespace are only modifiable by root (and sometimes only queriable
by root).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;linux&quot;&gt;Linux&lt;&#x2F;h2&gt;
&lt;pre style=&quot;background-color:#2b303b;&quot;&gt;
&lt;span style=&quot;color:#c0c5ce;&quot;&gt;ssize_t &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;getxattr&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const char &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;path&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const char &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;,
                 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, size_t &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;size&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;);
ssize_t &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;lgetxattr&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const char &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;path&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const char &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;,
                 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, size_t &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;size&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;);
ssize_t &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;fgetxattr&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;fd&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const char &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;,
                 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, size_t &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;size&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;);

ssize_t &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;listxattr&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const char &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;path&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;char &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;list&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, size_t &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;size&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;);
ssize_t &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;llistxattr&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const char &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;path&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;char &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;list&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, size_t &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;size&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;);
ssize_t &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;flistxattr&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;fd&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;char &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;list&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, size_t &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;size&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;);

&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;removexattr&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const char &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;path&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const char &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;lremovexattr&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const char &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;path&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const char &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;fremovexattr&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;fd&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const char &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;);

&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;setxattr&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const char &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;path&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const char &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;,
              &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const void &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, size_t &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;size&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;flags&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;lsetxattr&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const char &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;path&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const char &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;,
              &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const void &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, size_t &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;size&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;flags&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;fsetxattr&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;fd&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const char &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;,
              &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const void &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, size_t &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;size&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;flags&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;);
&lt;&#x2F;span&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The linux API is actually a fairly nice one, and for the rest of this post I&#x27;m
going to use it as my point of comparison. The return values of the &lt;code&gt;getxattr&lt;&#x2F;code&gt; and
&lt;code&gt;listxattr&lt;&#x2F;code&gt; functions are the &lt;em&gt;total&lt;&#x2F;em&gt; size of the attribute, &lt;em&gt;not&lt;&#x2F;em&gt; the size of
the data returned. This lends itself to a nice idiom for checking whether or
not truncation occurred:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#2b303b;&quot;&gt;
&lt;span style=&quot;color:#b48ead;&quot;&gt;char&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; buf[BUFSIZ];
ssize_t res;

res = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;getxattr&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;&#x2F;home&#x2F;worr&#x2F;foo&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;, &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;user.foo&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;, buf, sizeof(buf)) &amp;gt; sizeof(buf);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(res &amp;gt; sizeof(buf))
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;* truncation occured *&#x2F;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;else if &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(res == -&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;)
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;* error occurred *&#x2F;
&lt;&#x2F;span&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If &lt;code&gt;value&lt;&#x2F;code&gt; is &lt;code&gt;NULL&lt;&#x2F;code&gt; in a call to &lt;code&gt;getxattr&lt;&#x2F;code&gt; or &lt;code&gt;listxattr&lt;&#x2F;code&gt;, the size of
the buffer required to hold the contents of the EA will be returned. This
allows you to query the amount of space required to hold the return value,
allocate it, and then call the function again to populate that. That&#x27;s
unfortunately racey, so it&#x27;s preferable to call and then &lt;code&gt;realloc&lt;&#x2F;code&gt; if
truncation.&lt;&#x2F;p&gt;
&lt;p&gt;Linux extended attributes are namespaced, and the namespace is specified as
part of the attribute name. Namespaces are separated from attribute names by a
&lt;code&gt;.&lt;&#x2F;code&gt;. Currently, they support the common &lt;code&gt;system&lt;&#x2F;code&gt; and &lt;code&gt;user&lt;&#x2F;code&gt; namespaces, as
well as &lt;code&gt;security&lt;&#x2F;code&gt; and &lt;code&gt;trusted&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s important to note that &lt;code&gt;listxattr&lt;&#x2F;code&gt; will never retrun &lt;code&gt;EPERM&lt;&#x2F;code&gt;. If there
are EAs that the current user cannot access, they just won&#x27;t be returned.&lt;&#x2F;p&gt;
&lt;p&gt;The attribute list returned by &lt;code&gt;listxattr&lt;&#x2F;code&gt; is &lt;code&gt;NULL&lt;&#x2F;code&gt;-delimited, and all of the
attribute names returned by &lt;code&gt;listxattr&lt;&#x2F;code&gt; &lt;em&gt;are&lt;&#x2F;em&gt; fully-qualified.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;aix&quot;&gt;AIX&lt;&#x2F;h2&gt;
&lt;p&gt;It seems funny that I&#x27;m going to talk about AIX&#x27;s interface right after
linux&#x27;s, but that&#x27;s largely because it&#x27;s...almost exactly the same.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#2b303b;&quot;&gt;
&lt;span style=&quot;color:#c0c5ce;&quot;&gt;ssize_t &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;getea&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const char &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;path&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const char &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;,
        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, size_t &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;size&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;);
ssize_t &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;fgetea&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;filedes&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const char &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, size_t &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;size&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;);
ssize_t &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;lgetea&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const char &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;path&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const char &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;,
        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, size_t &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;size&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;);

ssize_t &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;listea&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const char &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;path&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;char &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;list&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, size_t &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;size&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;);
ssize_t &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;flistea &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;filedes&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;char &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;list&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, size_t &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;size&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;);
ssize_t &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;llistea &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const char &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;path&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;char &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;list&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, size_t &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;size&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;);

&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;removeea&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const char &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;path&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const char &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;fremoveea&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;filedes&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const char &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;lremoveea&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const char &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;path&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const char &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;);

&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;setea&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const char &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;path&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const char &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;,
        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, size_t &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;size&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;flags&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;fsetea&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;filedes&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const char &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;,
        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, size_t &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;size&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;flags&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;lsetea&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const char &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;path&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const char &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;,
        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, size_t &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;size&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;flags&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;);
&lt;&#x2F;span&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Just like linux, &lt;code&gt;getea&lt;&#x2F;code&gt; and &lt;code&gt;listea&lt;&#x2F;code&gt; return the size of the actual attribute
value, which makes checking for truncation super easy. They also support
getting called with a zero size, which will just return the size of the list or
attribute value without writing any data to &lt;code&gt;value&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The only key difference is that is that they use the character &lt;code&gt;0xF8&lt;&#x2F;code&gt; to
separate the namespace from the attribute name. So querying for system
attributes involves querying the name &lt;code&gt;0xF8SYSTEM0xF8attr&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;There&#x27;s also the &lt;code&gt;statea&lt;&#x2F;code&gt; family of functions, which will fill in a
&lt;code&gt;struct stat64x&lt;&#x2F;code&gt;, but that&#x27;s of little consequence to us here.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;freebsd-netbsd&quot;&gt;FreeBSD &#x2F; NetBSD&lt;&#x2F;h2&gt;
&lt;pre style=&quot;background-color:#2b303b;&quot;&gt;
&lt;span style=&quot;color:#c0c5ce;&quot;&gt;ssize_t
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;extattr_get_fd&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;fd&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;attrnamespace&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const char &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;attrname&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, size_t &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;nbytes&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;);
ssize_t
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;extattr_get_file&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const char &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;path&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;attrnamespace&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const char &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;attrname&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, size_t &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;nbytes&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;);
ssize_t
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;extattr_get_link&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const char &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;path&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;attrnamespace&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const char &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;attrname&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, size_t &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;nbytes&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;);

&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;int
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;extattr_set_fd&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;fd&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;attrnamespace&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const char &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;attrname&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const void &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, size_t &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;nbytes&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;int
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;extattr_set_file&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const char &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;path&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;attrnamespace&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const char &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;attrname&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const void &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, size_t &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;nbytes&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;int
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;extattr_set_link&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const char &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;path&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;attrnamespace&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const char &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;attrname&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const void &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, size_t &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;nbytes&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;);

&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;int
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;extattr_delete_fd&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;fd&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;attrnamespace&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const char &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;attrname&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;int
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;extattr_delete_file&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const char &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;path&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;attrnamespace&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const char &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;attrname&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;int
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;extattr_delete_link&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const char &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;path&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;attrnamespace&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const char &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;attrname&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;);

ssize_t
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;extattr_list_fd&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;fd&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;attrnamespace&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, size_t &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;nbytes&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;);
ssize_t
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;extattr_list_file&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const char &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;path&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;attrnamespace&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, size_t &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;nbytes&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;);
ssize_t
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;extattr_list_link&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const char &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;path&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;attrnamespace&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, size_t &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;nbytes&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;);
&lt;&#x2F;span&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;FreeBSD and NetBSD both use the same functions for the extended attribute
calls. The most obvious difference is that the attribute namespace is no
longer part of the attribute name. Each namespace is defined as an constant,
and must be passed separately.&lt;&#x2F;p&gt;
&lt;p&gt;Almost seemingly as a result of this difference, &lt;code&gt;extattr_list&lt;&#x2F;code&gt; can now error with
&lt;code&gt;EPERM&lt;&#x2F;code&gt;, rather than hiding the attribute names that the caller doesn&#x27;t have
access to.&lt;&#x2F;p&gt;
&lt;p&gt;The other, more annoying difference, is the return value of the &lt;code&gt;extattr_get&lt;&#x2F;code&gt;
and &lt;code&gt;extattr_list&lt;&#x2F;code&gt; functions. Rather than behaving like linux, AIX or OS X,
they instead return the number of bytes written, making truncation detection
harder. This basically requires that you make two calls if you want to ensure
that no truncation will occur.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;os-x&quot;&gt;OS X&lt;&#x2F;h2&gt;
&lt;pre style=&quot;background-color:#2b303b;&quot;&gt;
&lt;span style=&quot;color:#c0c5ce;&quot;&gt;ssize_t
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;getxattr&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const char &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;path&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const char &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, size_t &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;size&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, u_int32_t &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;position&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;options&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;);
ssize_t
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;fgetxattr&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;fd&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const char &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, size_t &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;size&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, u_int32_t &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;position&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;options&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;);

ssize_t
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;listxattr&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const char &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;path&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;char &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;namebuf&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, size_t &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;size&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;options&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;);
ssize_t
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;flistxattr&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;fd&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;char &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;namebuf&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, size_t &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;size&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;options&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;);

&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;int
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;removexattr&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const char &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;path&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const char &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;options&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;int
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;fremovexattr&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;fd&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const char &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;options&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;);

ssize_t
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;listxattr&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const char &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;path&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;char &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;namebuf&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, size_t &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;size&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;options&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;);
ssize_t
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;flistxattr&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;fd&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;char &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;namebuf&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, size_t &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;size&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;options&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;);
&lt;&#x2F;span&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;OS X differs in a few ways. Notably, their functions all take an options arg.
Rather than calling an entirely different function to prevent following
symlinks, you can pass the &lt;code&gt;XATTR_NOFOLLOW&lt;&#x2F;code&gt; to prevent traversing symlinks.&lt;&#x2F;p&gt;
&lt;p&gt;Another, fairly curious difference is the &lt;code&gt;position&lt;&#x2F;code&gt; argument that&#x27;s part of
the prototype for &lt;code&gt;getxattr&lt;&#x2F;code&gt;. To really get a handle on this, we&#x27;re going to
dive into the wonderful world of forks.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;forks&quot;&gt;Forks&lt;&#x2F;h3&gt;
&lt;p&gt;Forks are kind of like having multiple datastreams for the same file. The data
that we typically think of being stored in a file is dumped into one fork (in
the case of Mac OS, the data fork) and metadata, resources or any other type
of data could exist in other forks, wholly independent.&lt;&#x2F;p&gt;
&lt;p&gt;On Mac OS filesystems (MFS, HFS, HFS+), each file could have at least a
resource fork for the purpose of storing resources about a given file. This
was used for things like splitting up icons that Finder would use to represent
a file, or for separating presentation and content of text documents.&lt;&#x2F;p&gt;
&lt;p&gt;HFS+ (maybe HFS too? I&#x27;m not sure) allowed for any number of named forks.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;back-to-os-x&quot;&gt;Back to OS X&lt;&#x2F;h3&gt;
&lt;p&gt;Extended attributes on OS X are &lt;em&gt;actually&lt;&#x2F;em&gt; just named forks. The extended
attribute API wholly supplanted the old resource manager API.
To ensure that applications could seek to arbitrary points in a
fork, OS X&#x27;s extended attribute API includes a position argument.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;getxattr&lt;&#x2F;code&gt; is similar to Linux, in that it returns the size of the attribute&#x27;s
data, not just the number of bytes read. This makes truncation detection
pretty easy.&lt;&#x2F;p&gt;
&lt;p&gt;It is worth noting that extended attribute names in OS X are &lt;em&gt;not&lt;&#x2F;em&gt; namespaced
in any special way.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;solaris&quot;&gt;Solaris&lt;&#x2F;h2&gt;
&lt;p&gt;Solaris gets weird. Solaris is probably closest to OS X in its implementation
of extended attributes, in that extended attributes are just named forks.
However, Solaris includes &lt;em&gt;only one&lt;&#x2F;em&gt; specialized function call to deal with
extended attributes.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#2b303b;&quot;&gt;
&lt;span style=&quot;color:#b48ead;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;attropen &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const char &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;path&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const char &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;attrpath&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;oflag&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, ...);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;* the varargs can include a mode argument of type mode_t *&#x2F;
&lt;&#x2F;span&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;But &lt;em&gt;even this&lt;&#x2F;em&gt; isn&#x27;t required, since you can get the same results from using
a combination of &lt;code&gt;open&lt;&#x2F;code&gt; and &lt;code&gt;openat&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#2b303b;&quot;&gt;
&lt;span style=&quot;color:#b48ead;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; fd = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;open&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(path, O_RDONLY);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; attrfd = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;openat&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(fd, attrpath, oflag|O_XATTR, mode);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;close&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(fd);
&lt;&#x2F;span&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;From there, all of the *at functions can be used to operate on extended
attributes with some restrictions:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;no links between attribute space and non-attribute space&lt;&#x2F;li&gt;
&lt;li&gt;no renames between attribute space and non-attribute space&lt;&#x2F;li&gt;
&lt;li&gt;only regular files are allowed - no dirs, symlinks or devices&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Otherwise, extended attributes are treated like regular files.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;this-sucks&quot;&gt;This sucks&lt;&#x2F;h2&gt;
&lt;p&gt;This is awful when trying to expose a generic, cross-platform API for extended
attributes; the only one that I&#x27;ve found is &lt;a href=&quot;https:&#x2F;&#x2F;metacpan.org&#x2F;pod&#x2F;File::ExtAttr&quot;&gt;written for
perl&lt;&#x2F;a&gt;. I had
to add support for FreeBSD in Go, Python and Rust - and none of these deal with
Solaris or AIX! Adding FreeBSD support
was pretty rough, largely since implementors assume that every OS has a
Linux-compatible API.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;No OS has a Linux-compatible extended attribute API&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Are attributes namespaced? Are namespaces strings? Are they &lt;code&gt;int&lt;&#x2F;code&gt; constants?&lt;&#x2F;li&gt;
&lt;li&gt;Are they named forks? What happens if I need to seek?&lt;&#x2F;li&gt;
&lt;li&gt;How big can the data be? How do we check for truncation?&lt;&#x2F;li&gt;
&lt;li&gt;Error conditions differ radically&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Honestly, I wonder if this contributes to the lack of cross-platform apps that
use extended attributes. They&#x27;re super useful in any case where it&#x27;s necessary
to track metadata about files without having to keep track of it in a separate
database. That&#x27;s honestly fraught with peril anyway, since you&#x27;re dependent on
the name of the file (or whatever identifier you use in your db) staying
constant across renames, deletes, etc.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;where-to-go-from-here&quot;&gt;Where to go from here?&lt;&#x2F;h2&gt;
&lt;p&gt;A C wrapper lib around all of these implementations would be nice, but there are
some obvious trade-offs that need to be made.&lt;&#x2F;p&gt;
&lt;p&gt;The way that I&#x27;ve done this in Python and Rust has been to:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Assume linux-like namespaces, and translate accordingly. If there aren&#x27;t namespaces in your OS&#x27;s implementation, then just make the namespace part of the attribute name.&lt;&#x2F;li&gt;
&lt;li&gt;Make two calls to get the size of the extended attribute. This works across AIX, Linux and OS X. Solaris will have to use &lt;code&gt;statat&lt;&#x2F;code&gt; to get the size. Unfortunately, race conditions abound.&lt;&#x2F;li&gt;
&lt;li&gt;When listing extended attributes, ignore &lt;code&gt;EPERM&lt;&#x2F;code&gt; for system-level attributes&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Maybe when I get some time, I&#x27;ll start working on one.&lt;&#x2F;p&gt;
&lt;p&gt;Finally: please, please stop assuming that the whole world is Linux.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;sources&quot;&gt;Sources&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Extended_file_attributes&quot;&gt;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Extended_file_attributes&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man2&#x2F;listxattr.2.html&quot;&gt;http:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man2&#x2F;listxattr.2.html&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man2&#x2F;getxattr.2.html&quot;&gt;http:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man2&#x2F;getxattr.2.html&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man2&#x2F;setxattr.2.html&quot;&gt;http:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man2&#x2F;setxattr.2.html&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man2&#x2F;removexattr.2.html&quot;&gt;http:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man2&#x2F;removexattr.2.html&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man7&#x2F;xattr.7.html&quot;&gt;http:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man7&#x2F;xattr.7.html&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www-01.ibm.com&#x2F;support&#x2F;knowledgecenter&#x2F;api&#x2F;content&#x2F;nl&#x2F;en-us&#x2F;ssw_aix_71&#x2F;com.ibm.aix.basetrf2&#x2F;removeea.htm&quot;&gt;https:&#x2F;&#x2F;www-01.ibm.com&#x2F;support&#x2F;knowledgecenter&#x2F;api&#x2F;content&#x2F;nl&#x2F;en-us&#x2F;ssw_aix_71&#x2F;com.ibm.aix.basetrf2&#x2F;removeea.htm&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www-01.ibm.com&#x2F;support&#x2F;knowledgecenter&#x2F;api&#x2F;content&#x2F;nl&#x2F;en-us&#x2F;ssw_aix_71&#x2F;com.ibm.aix.basetrf2&#x2F;setea.htm#setea&quot;&gt;https:&#x2F;&#x2F;www-01.ibm.com&#x2F;support&#x2F;knowledgecenter&#x2F;api&#x2F;content&#x2F;nl&#x2F;en-us&#x2F;ssw_aix_71&#x2F;com.ibm.aix.basetrf2&#x2F;setea.htm#setea&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www-01.ibm.com&#x2F;support&#x2F;knowledgecenter&#x2F;api&#x2F;content&#x2F;nl&#x2F;en-us&#x2F;ssw_aix_71&#x2F;com.ibm.aix.basetrf1&#x2F;listea.htm&quot;&gt;https:&#x2F;&#x2F;www-01.ibm.com&#x2F;support&#x2F;knowledgecenter&#x2F;api&#x2F;content&#x2F;nl&#x2F;en-us&#x2F;ssw_aix_71&#x2F;com.ibm.aix.basetrf1&#x2F;listea.htm&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www-01.ibm.com&#x2F;support&#x2F;knowledgecenter&#x2F;api&#x2F;content&#x2F;nl&#x2F;en-us&#x2F;ssw_aix_71&#x2F;com.ibm.aix.basetrf1&#x2F;getea.htm&quot;&gt;https:&#x2F;&#x2F;www-01.ibm.com&#x2F;support&#x2F;knowledgecenter&#x2F;api&#x2F;content&#x2F;nl&#x2F;en-us&#x2F;ssw_aix_71&#x2F;com.ibm.aix.basetrf1&#x2F;getea.htm&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;man.netbsd.org&#x2F;6.0&#x2F;usr&#x2F;share&#x2F;man&#x2F;html2&#x2F;extattr_get_file.html&quot;&gt;http:&#x2F;&#x2F;man.netbsd.org&#x2F;6.0&#x2F;usr&#x2F;share&#x2F;man&#x2F;html2&#x2F;extattr_get_file.html&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;developer.apple.com&#x2F;library&#x2F;mac&#x2F;documentation&#x2F;Darwin&#x2F;Reference&#x2F;ManPages&#x2F;man2&#x2F;getxattr.2.html&quot;&gt;https:&#x2F;&#x2F;developer.apple.com&#x2F;library&#x2F;mac&#x2F;documentation&#x2F;Darwin&#x2F;Reference&#x2F;ManPages&#x2F;man2&#x2F;getxattr.2.html&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Resource_fork&quot;&gt;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Resource_fork&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.oracle.com&#x2F;cd&#x2F;E18752_01&#x2F;html&#x2F;816-5175&#x2F;fsattr-5.html#REFMAN5fsattr-5&quot;&gt;https:&#x2F;&#x2F;docs.oracle.com&#x2F;cd&#x2F;E18752_01&#x2F;html&#x2F;816-5175&#x2F;fsattr-5.html#REFMAN5fsattr-5&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</description>
            </item>
        
            <item>
                <title>Starting a dev blog</title>
                <pubDate>Sun, 01 Nov 2015 00:00:00 +0000</pubDate>
                <link>https://worrbase.com/blog/devblog/</link>
                <guid>https://worrbase.com/blog/devblog/</guid>
                <description>&lt;p&gt;I haven&#x27;t really written anything here in, well, over a year. I&#x27;ve thought a
lot about how I really need to start writing again, and what kind of stuff I&#x27;d
like to write about.  Over the last
few weeks, I&#x27;ve realized that I&#x27;m much more enthusiastic about the stuff that
I&#x27;m working on when I spend a little time writing or tweeting about it. That
said, I think I&#x27;m going to move updates about the FOSS projects I&#x27;m working on
from Twitter to my &lt;a href=&quot;http:&#x2F;&#x2F;onwednesdayswewear.pink&quot;&gt;dev blog&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Every day that I work on something, I&#x27;ll post a bite-sized update on my dev
blog. If I come across something interesting to write about outside of just
posting commits, then I&#x27;ll circle back here and write a bit about it in
detail. I&#x27;d like to keep this low-volume and long-form (except for this post,
obviously), if possible.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m going to try this out for at least the next few days, since I have a lot
of FOSS work in my pipeline.&lt;&#x2F;p&gt;
</description>
            </item>
        
            <item>
                <title>An Obfuscated String Implementation for Go</title>
                <pubDate>Tue, 25 Feb 2014 00:00:00 +0000</pubDate>
                <link>https://worrbase.com/blog/secstring/</link>
                <guid>https://worrbase.com/blog/secstring/</guid>
                <description>&lt;p&gt;Recently, I purchased the domain rit.singles, and I was possessed with the
urge of making an actual dating website. I thought it would be cool to write
it in Go, since that&#x27;s one of the hip new languages of the now, and also
because it does a lot of things that I really like.&lt;&#x2F;p&gt;
&lt;p&gt;I started by writing the account management and registration code. This is
surprisingly tricky, because handling sensitive data with any semblance of
security is a pain. Luckily, Go exposes a number of very useful syscalls for
us to work with.&lt;&#x2F;p&gt;
&lt;p&gt;Since I&#x27;m not offering enough click-bait on my block, I feel like it&#x27;s only
appropriate to turn the rest of this post into a listicle.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;4-weird-tricks-one-florida-man-used-to-protect-sensitive-data-in-memory-hackers-hate-him&quot;&gt;4 Weird Tricks One Florida Man Used to Protect Sensitive Data in Memory!!! (Hackers &lt;em&gt;hate&lt;&#x2F;em&gt; him!)&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;1-mlock-your-pages&quot;&gt;1. &lt;code&gt;mlock&lt;&#x2F;code&gt; your pages&lt;&#x2F;h3&gt;
&lt;p&gt;Allocate as many pages of memory as you need to hold your string. Then
&lt;code&gt;mlock&lt;&#x2F;code&gt; them immediately.
&lt;a href=&quot;http:&#x2F;&#x2F;pubs.opengroup.org&#x2F;onlinepubs&#x2F;7990989775&#x2F;xsh&#x2F;mlock.html&quot;&gt;mlock&lt;&#x2F;a&gt;
is a portable function that strongly
encourages your kernel not to swap out a page of memory.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;why-is-this-useful&quot;&gt;Why is this useful?&lt;&#x2F;h4&gt;
&lt;p&gt;Swap doesn&#x27;t get zeroed out, and there&#x27;s no way to guarantee when it will get
overwritten, so you don&#x27;t know how long any persisted data will last. While
encrypting your swap is a good idea, you can&#x27;t expect everyone to encrypt
their swap paritions.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;any-caveats&quot;&gt;Any caveats?&lt;&#x2F;h4&gt;
&lt;p&gt;Hibernating will still persist passwords to swap. Sorry.&lt;&#x2F;p&gt;
&lt;p&gt;Solaris and Solaris-based operating systems require that you grant the
proc_lock_memory privilege before a user can run anything that calls
&lt;code&gt;mlock&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Memory that you &lt;code&gt;mlock&lt;&#x2F;code&gt; must be page-aligned. I &lt;code&gt;mmap&lt;&#x2F;code&gt; my sensitive memory to
ensure this.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;2-mprotect-your-pages&quot;&gt;2. &lt;code&gt;mprotect&lt;&#x2F;code&gt; your pages&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a href=&quot;http:&#x2F;&#x2F;pubs.opengroup.org&#x2F;onlinepubs&#x2F;009696799&#x2F;functions&#x2F;mprotect.html&quot;&gt;mprotect&lt;&#x2F;a&gt;
assigns permissions to your pages. I typically write my sensitive
data, and then immediately &lt;code&gt;mprotect&lt;&#x2F;code&gt; the page such that it&#x27;s read-only. If
any process tries to write or execute that memory, that triggers a segfault,
which is much better than tampering with sensitive memory.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;why-is-this-useful-1&quot;&gt;Why is this useful?&lt;&#x2F;h4&gt;
&lt;p&gt;Instead of a rogue buffer overrun wiping your sensitive data, you instead
trigger a segfault. This helps prevent tampering, either malicious or
accidental, of your sensitive data.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;any-caveats-1&quot;&gt;Any caveats?&lt;&#x2F;h4&gt;
&lt;p&gt;Again, the memory that you pass into &lt;code&gt;mprotect&lt;&#x2F;code&gt; must be page-aligned.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;3-encrypt-your-sensitive-strings&quot;&gt;3. Encrypt your sensitive strings&lt;&#x2F;h3&gt;
&lt;p&gt;It&#x27;s really just obfuscation rather than offering &lt;strong&gt;real&lt;&#x2F;strong&gt; security, but it&#x27;s
a worthwhile tactic. Passwords become less trivially identifiable if they&#x27;re
encrypted in memory.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;why-is-this-important&quot;&gt;Why is this important?&lt;&#x2F;h4&gt;
&lt;p&gt;If an attacker gets a memory dump, or if a machine hibernated and an attacker
has your swap device, it makes it far harder to identify a password.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;any-caveats-2&quot;&gt;Any caveats?&lt;&#x2F;h4&gt;
&lt;p&gt;Hell yes.&lt;&#x2F;p&gt;
&lt;p&gt;The key needs to be stored in memory. If the attacker knows where in memory
your key is, then it&#x27;s trivial to decrypt your sensitive string. It really
just ends up being obfuscation more than anything.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;4-memset-s-your-pages-before-you-munmap-them&quot;&gt;4. &lt;code&gt;memset_s&lt;&#x2F;code&gt; your pages before you &lt;code&gt;munmap&lt;&#x2F;code&gt; them&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a href=&quot;http:&#x2F;&#x2F;www.open-std.org&#x2F;jtc1&#x2F;sc22&#x2F;wg14&#x2F;www&#x2F;docs&#x2F;n1381.pdf&quot;&gt;memset_s&lt;&#x2F;a&gt; is a
new C11 function that will &lt;code&gt;memset&lt;&#x2F;code&gt; with the guarantee that it won&#x27;t be
optimized out.&lt;&#x2F;p&gt;
&lt;p&gt;If the value that you &lt;code&gt;memset&lt;&#x2F;code&gt; isn&#x27;t used after the &lt;code&gt;memset&lt;&#x2F;code&gt;, smart compilers
will optimize it away. If you&#x27;re clearing sensitive memory after you&#x27;re done
using it, this is &lt;em&gt;definitely not&lt;&#x2F;em&gt; what you want.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;why-is-this-important-1&quot;&gt;Why is this important?&lt;&#x2F;h4&gt;
&lt;p&gt;When you &lt;code&gt;free&lt;&#x2F;code&gt; or &lt;code&gt;munmap&lt;&#x2F;code&gt; memory, it isn&#x27;t wiped before being given back to
the OS. If an attacker gets a memory dump &lt;em&gt;after&lt;&#x2F;em&gt; you have freed a sensitive
block of information, it&#x27;s very possible that the value is still in memory.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;memset&lt;&#x2F;code&gt; isn&#x27;t sufficient for the reason I outlined above.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;any-caveats-3&quot;&gt;Any caveats?&lt;&#x2F;h4&gt;
&lt;p&gt;&lt;code&gt;memset_s&lt;&#x2F;code&gt; isn&#x27;t implemented in many libc&#x27;s. If this is a case for your
targets, then check out &lt;a href=&quot;https:&#x2F;&#x2F;www.securecoding.cert.org&#x2F;confluence&#x2F;display&#x2F;seccode&#x2F;MSC06-C.+Beware+of+compiler+optimizations&quot;&gt;this implementation from
CERT&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;now-where-the-hell-does-go-come-into-all-of-this&quot;&gt;Now where the hell does Go come into all of this?&lt;&#x2F;h2&gt;
&lt;p&gt;Since I&#x27;m working with passwords for rit.singles in Go, I felt the need to
write a secure password implementation in Go. In it, I did all of these
things, save for clearing my data with &lt;code&gt;memset_s&lt;&#x2F;code&gt;. As far as I&#x27;m aware, Go&#x27;s
compiler won&#x27;t optimize away a normal &lt;code&gt;memset&lt;&#x2F;code&gt;, so I&#x27;m safe there.&lt;&#x2F;p&gt;
&lt;p&gt;The code for the &lt;code&gt;secstring&lt;&#x2F;code&gt; package is on
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;worr&#x2F;secstring&quot;&gt;GitHub&lt;&#x2F;a&gt;. The documentation is on
&lt;a href=&quot;http:&#x2F;&#x2F;godoc.org&#x2F;github.com&#x2F;worr&#x2F;secstring&quot;&gt;GoDoc&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;I welcome any bugs&#x2F;criticisms&#x2F;questions&#x2F;audits.&lt;&#x2F;p&gt;
</description>
            </item>
        
            <item>
                <title>Setting up RetroPie</title>
                <pubDate>Thu, 17 Oct 2013 00:00:00 +0000</pubDate>
                <link>https://worrbase.com/blog/retropie/</link>
                <guid>https://worrbase.com/blog/retropie/</guid>
                <description>&lt;p&gt;Today, after a few days of work, I finally got
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;petrockblog&#x2F;RetroPie-Setup&quot;&gt;RetroPie&lt;&#x2F;a&gt; up and running at an
acceptable speed. It was a little longer and a little more difficult than
anticipated, so it makes sense to blog about it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;sd-card-selection&quot;&gt;SD Card Selection&lt;&#x2F;h2&gt;
&lt;p&gt;Surprisingly, your SD Card makes a significant difference in the time it takes
to load games and write out game state. The other, non-obvious, impact of the SD
card is contention for IO when other tasks on your pi are reading&#x2F;writing
from&#x2F;to the SD card.&lt;&#x2F;p&gt;
&lt;p&gt;I had initially chosen a slow, older class 4 card. Whenever some other process
wrote out to disk, my games would noticeably lag a bit. I haven&#x27;t had that
problem since switching to a Class 10 though.&lt;&#x2F;p&gt;
&lt;p&gt;Don&#x27;t just rely on the class number to give you information about the
performance characteristics of the SD card. Checkout &lt;a href=&quot;http:&#x2F;&#x2F;elinux.org&#x2F;RPi_SD_cards&quot;&gt;this handy
list&lt;&#x2F;a&gt; before buying.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;os-selection&quot;&gt;OS Selection&lt;&#x2F;h2&gt;
&lt;p&gt;Go with vanilla Raspbian.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;ve played with &lt;a href=&quot;http:&#x2F;&#x2F;www.linuxsystems.it&#x2F;2012&#x2F;06&#x2F;raspbian-wheezy-armhf-raspberry-pi-minimal-image&#x2F;&quot;&gt;Darkbasic&#x27;s
Raspbian&lt;&#x2F;a&gt;, 
&lt;a href=&quot;http:&#x2F;&#x2F;pibanglinux.org&#x2F;&quot;&gt;PiBang&lt;&#x2F;a&gt;, and vanilla Raspbian for the host image.
Raspbian was the fastest by far (&lt;em&gt;after&lt;&#x2F;em&gt; you disable all of the crap, of
course). It&#x27;s also convenient to have raspi-config and raspi-update installed
from the getgo. RetroPie expects that you&#x27;re running Raspbian, and you can hit
some interesting behaviour if you aren&#x27;t.&lt;&#x2F;p&gt;
&lt;p&gt;While I initially liked PiBang, systemd is a poor choice for the pi if you want
to emulate. I noticed
as I was playing games, systemd was eating a large portion of my CPU, and would
occasionally cause lag when there was a sudden burst of activity. Moving to a
non-systemd distro (Darkbasic&#x27;s Raspbian) helped significantly.&lt;&#x2F;p&gt;
&lt;p&gt;Darkbasic&#x27;s Raspbian was slow enough by itself. I never worked out the reason,
since it uses the same repos as vanilla raspbian, with all of the same
optimizations, however performance just on the terminal was noticeably slower.
I&#x27;ll post benchmarks later (possibly never).&lt;&#x2F;p&gt;
&lt;p&gt;Darkbasic&#x27;s Raspbian image is also very minimal, and not configured the same way
as vanilla Raspbian. This can lead to some interesting issues when trying to
build and run RetroArch (more later).&lt;&#x2F;p&gt;
&lt;p&gt;If you choose not to install Raspbian, and use some minimal RPi distro, I&#x27;ll
include some helpful hints throughout (I set this up several times on the above
distros).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;let-s-get-started&quot;&gt;Let&#x27;s get started&lt;&#x2F;h2&gt;
&lt;p&gt;Install your favorite image normally. Don&#x27;t stop any services just yet or do any
configuring just yet. Stick to a vanilla install, since that&#x27;s what RetroPie
expects (and it doesn&#x27;t like any deviation).&lt;&#x2F;p&gt;
&lt;h3 id=&quot;non-raspbian-notes&quot;&gt;Non-raspbian notes&lt;&#x2F;h3&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Add an input group.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#2b303b;&quot;&gt;
&lt;span style=&quot;color:#c0c5ce;&quot;&gt;addgroup --system input
&lt;&#x2F;span&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Make sure that &lt;code&gt;&#x2F;opt&#x2F;vc&#x2F;lib&lt;&#x2F;code&gt; is early in your linker path&lt;&#x2F;p&gt;
&lt;p&gt;Check out &lt;code&gt;&#x2F;etc&#x2F;ld.so.conf.d&lt;&#x2F;code&gt;. Some distros will install versions of
libEGL and related graphics libraries earlier in your library path. &lt;strong&gt;These
generally do not work&lt;&#x2F;strong&gt; and will throw weird, un-Googleable errors.&lt;&#x2F;p&gt;
&lt;p&gt;If you see &lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#2b303b;&quot;&gt;
&lt;span style=&quot;color:#c0c5ce;&quot;&gt;libEGL warning: DRI2: xcb_connect failed
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;libEGL warning: GLX: XOpenDisplay failed
&lt;&#x2F;span&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;when starting emulationstation that&#x27;s symptomatic of this problem. The libraries
in &lt;code&gt;&#x2F;opt&#x2F;vc&#x2F;lib&lt;&#x2F;code&gt; are built to use the Raspberry Pi&#x27;s VideoCore chip.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h2 id=&quot;pull-down-the-source&quot;&gt;Pull down the source&lt;&#x2F;h2&gt;
&lt;p&gt;After you&#x27;ve logged in and gone through the initial setup for your pi, pull down
the RetroPie-Setup source.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#2b303b;&quot;&gt;
&lt;span style=&quot;color:#c0c5ce;&quot;&gt;git clone git:&#x2F;&#x2F;github.com&#x2F;petrockblog&#x2F;RetroPie-Setup.git
cd RetroPie-Setup
&lt;&#x2F;span&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Before we compile, I&#x27;d recommend setting your CFLAGS. Thanks to a patch I
submitted, RetroPie-Setup now has some sane defaults (
&lt;code&gt;-O2 -pipe -mfpu=vfp -march=armv6j -mfloat-abi=hard&lt;&#x2F;code&gt;), but those aren&#x27;t
fast. I&#x27;d recommend
&lt;code&gt;-Ofast -fno-fast-math -pipe -mfpu=vfp -march=armv6j -mfloat-abi=hard&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;-Ofast&lt;&#x2F;code&gt; turns on the fastest optimization level, while potentially building
unsafe code. It works quite well for me, but YMMV.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;-fno-fast-math&lt;&#x2F;code&gt; turns off a GCC optimization that -Ofast enables.
fast-math uses some &amp;quot;faster&amp;quot; math that doesn&#x27;t give you the guarantees of some
of the standard math functions. In some cases, it&#x27;s also
&lt;a href=&quot;http:&#x2F;&#x2F;programerror.com&#x2F;2009&#x2F;09&#x2F;when-gccs-ffast-math-isnt&#x2F;&quot;&gt;slower&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;-mfpu=vfp&lt;&#x2F;code&gt;, &lt;code&gt;-march=arm6j&lt;&#x2F;code&gt; both tell &lt;code&gt;gcc&lt;&#x2F;code&gt; to generate code
specific to the raspi architecture, as well as what kind of fpu-specific machien
code to generate. These two flags are both used by the raspbian project to build
their packages&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;-mfloat-abi=hard&lt;&#x2F;code&gt; tells the compiler to generate fpu-specific
instructions. Without this flag, &lt;code&gt;gcc&lt;&#x2F;code&gt; will generate floating point code
that will not run on the fpu, but will link to library functions that emulate
floating-point code. This is slow. All raspbian packages are built with this
flag (that&#x27;s what puts the &#x27;hf&#x27; in &#x27;armhf&#x27;).&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;If you&#x27;re worried about the problems the new flags &lt;em&gt;could&lt;&#x2F;em&gt; introduce, then stick
to the defaults. If you&#x27;re just reading this and you already have RetroPie
installed, you should probably rebuild to get the new compiler options ;).&lt;&#x2F;p&gt;
&lt;p&gt;Set the CFLAGS with&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#2b303b;&quot;&gt;
&lt;span style=&quot;color:#b48ead;&quot;&gt;export &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;CFLAGS&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;-Ofast &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;-fno-fast-math -pipe -mfpu&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;vfp &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;-march&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;armv6j &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;-mfloat-abi&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;hard
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;export &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;CXXFLAGS&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;=&amp;quot;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;CFLAGS&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;export &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;ASFLAGS&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;=&amp;quot;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;CFLAGS&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;After all of this, it&#x27;s just a quick &lt;code&gt;sudo .&#x2F;retropie_setup.sh&lt;&#x2F;code&gt;. Pick and
choose what you want; it&#x27;s really none of my business, and it&#x27;s quite easy.&lt;&#x2F;p&gt;
&lt;p&gt;Make sure you pick the source-based builds (I guarantee that the binary ones
weren&#x27;t built with any good options) and that you tell the installer to start
&lt;code&gt;emulationstation&lt;&#x2F;code&gt; on boot.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;post-installation&quot;&gt;Post installation&lt;&#x2F;h2&gt;
&lt;p&gt;Disable &lt;em&gt;everything&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#2b303b;&quot;&gt;
&lt;span style=&quot;color:#c0c5ce;&quot;&gt;update-rc.d avahi-daemon remove
update-rc.d bluetooth remove
update-rc.d cron remove
update-rc.d cups remove
update-rc.d dbus remove
update-rc.d ifplugd remove
update-rc.d lightdm remove
update-rc.d nfs-common remove
update-rc.d rpcbind remove
update-rc.d rsync remove
update-rc.d rsyslog remove
update-rc.d saned remove
update-rc.d triggerhappy remove
update-rc.d ntp remove
ls &#x2F;etc&#x2F;rc3.d
K06rpcbind  README  S02dphys-swapfile  S02ssh  S05plymouth  S05rmnologin
&lt;&#x2F;span&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I use ssh to manage the system, so I leave that. Everything else must go.&lt;&#x2F;p&gt;
&lt;p&gt;Don&#x27;t get me wrong, usually I like logging, &lt;code&gt;ntp&lt;&#x2F;code&gt; and &lt;code&gt;cron&lt;&#x2F;code&gt;, but it&#x27;s just not
necessary on a pi that&#x27;s dedicated to playing games.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;pibang-systemd-notes&quot;&gt;PiBang&#x2F;systemd notes&lt;&#x2F;h3&gt;
&lt;p&gt;PiBang uses this half-assed systemd with sysvinit compatibility. It&#x27;s a pain in
the ass. Almost all of the packages that need to start at boot that you get on
PiBang need to be disabled with &lt;code&gt;update-rc.d&lt;&#x2F;code&gt;. Some others though need to be
disabled with &lt;code&gt;systemctl disable &amp;lt;service&amp;gt;&lt;&#x2F;code&gt;. I&#x27;ll leave it as an exercise to the
reader to figure out how to tell.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;minimal-image-notes&quot;&gt;Minimal image notes&lt;&#x2F;h3&gt;
&lt;p&gt;You&#x27;re probably sitting there laughing at how much bloat Raspbian comes with.
While that&#x27;s fair, keep in mind that the RetroPie script installs a ton of shit,
cups and sane included. Make sure you audit your startup as well.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;configuring-a-joystick&quot;&gt;Configuring a joystick&lt;&#x2F;h2&gt;
&lt;p&gt;Your joystick needs to be configured before you can start playing games.
Emulation Station will configure it for you when you first start it up, however
that configuration only applies to Emulation Station. You need to configure your
emulators on their own.&lt;&#x2F;p&gt;
&lt;p&gt;For RetroArch:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#2b303b;&quot;&gt;
&lt;span style=&quot;color:#c0c5ce;&quot;&gt;cd ~&#x2F;RetroPie&#x2F;emulators&#x2F;RetroArch&#x2F;tools&#x2F;
.&#x2F;retroarch-joyconfig -o p&amp;lt;playernumber&amp;gt;.cfg -p &amp;lt;playernumber&amp;gt; -j &amp;lt;joysticknumber&amp;gt;
# joysticks are 0 indexed (they map to &#x2F;dev&#x2F;input&#x2F;jsn
# players are 1 indexed
cat p*.cfg &amp;gt;&amp;gt; ~&#x2F;RetroPie&#x2F;configs&#x2F;all&#x2F;retroarch.cfg
&lt;&#x2F;span&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;non-raspbian-notes-1&quot;&gt;Non-raspbian notes&lt;&#x2F;h3&gt;
&lt;p&gt;You&#x27;ll need a &lt;code&gt;udev&lt;&#x2F;code&gt; rule to automatically give the &lt;code&gt;input&lt;&#x2F;code&gt; group permissions to
access the joystick devices. Drop the following into
&lt;code&gt;&#x2F;etc&#x2F;udev&#x2F;rules.d&#x2F;99-input.rules&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#2b303b;&quot;&gt;
&lt;span style=&quot;color:#c0c5ce;&quot;&gt;SUBSYSTEM==&amp;quot;input&amp;quot;, GROUP=&amp;quot;input&amp;quot;, MODE=&amp;quot;0660&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This ensures that the &lt;code&gt;input&lt;&#x2F;code&gt; group owns any new input devices, and that they
are group-readable.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;but-moooom-i-want-to-use-an-xbox-controller&quot;&gt;But moooom, I want to use an XBox controller&lt;&#x2F;h3&gt;
&lt;p&gt;No. You don&#x27;t.&lt;&#x2F;p&gt;
&lt;p&gt;You can use &lt;code&gt;xboxdrv&lt;&#x2F;code&gt; to hook up your XBox controller. It&#x27;s a userspace driver
that talks to the raw joystick device and interprets the XBox controllers&#x27;s
raw output into something meaningful.&lt;&#x2F;p&gt;
&lt;p&gt;Since the driver lives in userspace, anytime you twiddle a joystick or press a
button, you&#x27;re hopping like mad between userspace and kernelspace. This is slow.
I could actually emulate the slow-mo feature provided by RetroArch just by
twiddle both joysticks.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;no-i-m-a-special-snowflake-and-i-demand-to-know-how-to-use-an-xbox-controller&quot;&gt;No. I&#x27;m a special snowflake and I demand to know how to use an XBox controller&lt;&#x2F;h3&gt;
&lt;pre style=&quot;background-color:#2b303b;&quot;&gt;
&lt;span style=&quot;color:#c0c5ce;&quot;&gt;apt-get install xboxdrv
sudo -s
echo xboxdrv --silent &amp;gt; &#x2F;etc&#x2F;rc.local
&lt;&#x2F;span&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If you don&#x27;t want to reboot, just execute&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#2b303b;&quot;&gt;
&lt;span style=&quot;color:#c0c5ce;&quot;&gt;xboxdrv --silent &amp;amp;
&lt;&#x2F;span&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;as root.&lt;&#x2F;p&gt;
&lt;p&gt;You&#x27;ve been warned.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;starting-emulationstation-on-boot&quot;&gt;Starting emulationstation on boot&lt;&#x2F;h2&gt;
&lt;p&gt;Luckily, RetroPie did half of the work for you! If you selected the option
(either in setup or install) to start &lt;code&gt;emulationstation&lt;&#x2F;code&gt; on boot, it&#x27;ll drop a
handy snippet into &#x2F;etc&#x2F;profile which will do that on login.&lt;&#x2F;p&gt;
&lt;p&gt;However, you still need to login.&lt;&#x2F;p&gt;
&lt;p&gt;To alleviate that, edit your inittab.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#2b303b;&quot;&gt;
&lt;span style=&quot;color:#c0c5ce;&quot;&gt;1:2345:respawn:&#x2F;sbin&#x2F;getty --autologin pi --noclear 38400 tty1 
#1:2345:respawn:&#x2F;sbin&#x2F;getty --noclear 38400 tty1 
#2:23:respawn:&#x2F;sbin&#x2F;getty 38400 tty2
#3:23:respawn:&#x2F;sbin&#x2F;getty 38400 tty3
#4:23:respawn:&#x2F;sbin&#x2F;getty 38400 tty4
#5:23:respawn:&#x2F;sbin&#x2F;getty 38400 tty5
#6:23:respawn:&#x2F;sbin&#x2F;getty 38400 tty6
&lt;&#x2F;span&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Go to line 45 (on raspbian, or where the gettys are started), and enable
autologin for whatever user is going to run RetroArch.&lt;&#x2F;p&gt;
&lt;p&gt;In the spirit of disabling everything, I also stopped all of the other gettys
from spawning.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;should-i-overclock&quot;&gt;Should I overclock?&lt;&#x2F;h2&gt;
&lt;p&gt;Well, it depends. Want to run SNES games that have Mode-7 graphics? Or any of
the SNES games that packaged an extra processor on the cartridge? Yes.
Overclock.&lt;&#x2F;p&gt;
&lt;p&gt;In most other situations, you&#x27;re fine if you follow this guide. The one thing I
would recommend doing, however, is changing the memory&#x2F;gpu mem split. I gave my
GPU 384MB of memory. I&#x27;m barely breaking 20MB of memory usage running my pi, so
I don&#x27;t need very much system memory.&lt;&#x2F;p&gt;
&lt;p&gt;Your game will start slowing down as the proc
overheats, so make sure you have a heatsink and a case with some kind of airflow
if you plan on overclocking.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;notes-for-non-raspbian-users&quot;&gt;Notes for non-raspbian users&lt;&#x2F;h3&gt;
&lt;p&gt;Yeah, you probably do want to overclock. If your distro is compiled with dumb
options, it&#x27;ll help a bit.&lt;&#x2F;p&gt;
&lt;p&gt;On both Darkbasic&#x27;s raspbian and PiBang, I had to overclock to get decent
performance.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;That&#x27;s about as perfect a setup as you can get for RetroPie. If you have any
other suggestions, leave them in the comments. I didn&#x27;t configure RetroArch
anymore than shown above, because well, I didn&#x27;t need to. For all of my ROMs
built by the homebrew community that are totally free and legal to play, I ran
into no slowdown with this setup on Raspbian.&lt;&#x2F;p&gt;
&lt;p&gt;However, YMMV, as always.&lt;&#x2F;p&gt;
</description>
            </item>
        
            <item>
                <title>OpenSMTPD</title>
                <pubDate>Sun, 18 Aug 2013 00:00:00 +0000</pubDate>
                <link>https://worrbase.com/blog/opensmtpd/</link>
                <guid>https://worrbase.com/blog/opensmtpd/</guid>
                <description>&lt;p&gt;I love &lt;a href=&quot;http:&#x2F;&#x2F;opensmtpd.org&#x2F;&quot;&gt;OpenSMTPD&lt;&#x2F;a&gt;. After years of running a postfix 
installation, OpenSMTPD is such a joy to configure and use. The configuration
is dead simple, and it&#x27;s pretty damn stable. I wrote a
&lt;a href=&quot;https:&#x2F;&#x2F;coderwall.com&#x2F;p&#x2F;eejzja&quot;&gt;protip&lt;&#x2F;a&gt; about it over on Coderwall. I plan on
following up with more protips about more advanced configurations, with lmtp,
SSL&#x2F;TLS and greylisting.&lt;&#x2F;p&gt;
&lt;p&gt;Obviously, it&#x27;s now the mail server running mail on
&lt;a href=&quot;http:&#x2F;&#x2F;worrbase.com&quot;&gt;worrbase.com&lt;&#x2F;a&gt;, as well as the mail servers for my spamd
test cluster (remember to email
&lt;a href=&quot;mailto:ubuntu@spamd.worrbase.com&quot;&gt;ubuntu@spamd.worrbase.com&lt;&#x2F;a&gt;!).&lt;&#x2F;p&gt;
&lt;p&gt;Oh, and my friend &lt;a href=&quot;http:&#x2F;&#x2F;yasonik.com&#x2F;&quot;&gt;Michail Yasonik&lt;&#x2F;a&gt; redesigned my blog.
It looks significantly better than what I had up before.&lt;&#x2F;p&gt;
</description>
            </item>
        
            <item>
                <title>Update: spamd on Linux</title>
                <pubDate>Sun, 28 Jul 2013 00:00:00 +0000</pubDate>
                <link>https://worrbase.com/blog/spamd-deployed/</link>
                <guid>https://worrbase.com/blog/spamd-deployed/</guid>
                <description>&lt;p&gt;I finally took some time this weekend to deploy spamd on some ec2 instances. I
have 2 mail servers on ubuntu 13.04 running the latest copy of spamd on linux,
with synchronized greylisting tables.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;ve run into a few bugs with deployment, which I&#x27;ve added to the github
issues. Hopefully I can get them resolved soon.&lt;&#x2F;p&gt;
&lt;p&gt;I did run spamd through a small gamut of tests with postal, a SMTP stress
tester. They handled the excess load beautifully, keeping the synchronization
tables up to date even at 1000 mails&#x2F;min (well, it was less than that, due to
spamd&#x27;s resource draining feature) for 8 hours.&lt;&#x2F;p&gt;
&lt;p&gt;If you want to help test spamd, it&#x27;d be super great if you can sign up
&lt;a href=&quot;mailto:ubuntu@spamd.worrbase.com&quot;&gt;ubuntu@spamd.worrbase.com&lt;&#x2F;a&gt;
for all kinds of sketchy services. Maybe even forge
the email address and reply to some spam messages (that&#x27;s what I&#x27;m doing). I&#x27;d
like to continue testing it for the next week or so with some real-world spam
load.&lt;&#x2F;p&gt;
&lt;p&gt;The only bit left to port is spamlogd. I haven&#x27;t figured out the most logical
way to translate it to iptables, since iptables lacks a logging device akin to
pflogd.&lt;&#x2F;p&gt;
&lt;p&gt;Again, please direct spam to &lt;a href=&quot;mailto:ubuntu@spamd.worrbase.com&quot;&gt;ubuntu@spamd.worrbase.com&lt;&#x2F;a&gt;
(or even &lt;a href=&quot;mailto:hostmaster@spamd.worrbase.com&quot;&gt;hostmaster@spamd.worrbase.com&lt;&#x2F;a&gt; to test greytrapping).&lt;&#x2F;p&gt;
</description>
            </item>
        
            <item>
                <title>spamd on Linux</title>
                <pubDate>Sun, 23 Jun 2013 00:00:00 +0000</pubDate>
                <link>https://worrbase.com/blog/spamd/</link>
                <guid>https://worrbase.com/blog/spamd/</guid>
                <description>&lt;p&gt;Somehow, I became a mail administrator for CSH several years ago. I don&#x27;t know
why I did that to myself.&lt;&#x2F;p&gt;
&lt;p&gt;Regardless, I started deploying a secondary MX earlier this week and I ran
into a problem - greylisting.&lt;&#x2F;p&gt;
&lt;p&gt;We use greylisting to greatly reduce the amount of spam amavis needs to
process. We used gld on Debian, quite successfully might I add, for the last
few years.&lt;&#x2F;p&gt;
&lt;p&gt;Greylisting, in case you don&#x27;t know, is a simple technique to reduce the
amount of spam you receive. Your mail server responds to any connection from
an unknown mail server with a temporary failure, and makes a note of the ip,
mail from and rcpt to that the mail server sent.&lt;&#x2F;p&gt;
&lt;p&gt;Now legitimate mail servers, upon seeing a temporary failure, will try again.
Many spam mail servers, on the other hand, won&#x27;t (why? I don&#x27;t fucking know).
This is surprisingly successful. There are graphs all over the internet
showing the spam reduction, and I&#x27;ll leave finding them as an exercise to the
reader.&lt;&#x2F;p&gt;
&lt;p&gt;Anyway, back to gld. gld is a simple greylisting daemon (hey, I wonder where
the name gld came from...) that&#x27;s backed by a postgresql db. That&#x27;s fine, but
the only solution for managing greylists across multiple MX&#x27;s is postgresql
replication. That feels a little hacky to me...not to mention that gld seems
pretty unmaintained.&lt;&#x2F;p&gt;
&lt;p&gt;So I looked at postgrey, which is a postfix milter that does greylisting.
Well, that&#x27;s not a great solution because we have even fewer options for
greylist replication across MX&#x27;s.&lt;&#x2F;p&gt;
&lt;p&gt;Now, I run my own mail server (surprise! @worrbase.com) on OpenBSD using
OpenSMTPD and spamd. spamd is the OpenBSD greylisting solution, and it&#x27;s by
far the best I&#x27;ve used.&lt;&#x2F;p&gt;
&lt;p&gt;Features include:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;all the normal greylisting features (blacklists! whitelists! greylists!)&lt;&#x2F;li&gt;
&lt;li&gt;replication&lt;&#x2F;li&gt;
&lt;li&gt;it saps spammer&#x27;s resources&lt;&#x2F;li&gt;
&lt;li&gt;there&#x27;s basically no configuration&lt;&#x2F;li&gt;
&lt;li&gt;greytrapping&lt;&#x2F;li&gt;
&lt;li&gt;the SMTP conversations are hilarious&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Well, armed with this knowledge, I ported spamd to Linux. I can&#x27;t promise that
it&#x27;s terribly stable yet, but you&#x27;re welcome to test it and file bug reports.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;worr&#x2F;spamd&quot;&gt;Here&#x27;s&lt;&#x2F;a&gt; the github page.&lt;&#x2F;p&gt;
</description>
            </item>
        
            <item>
                <title>Leaving sugar behind...or am I?</title>
                <pubDate>Thu, 09 May 2013 00:00:00 +0000</pubDate>
                <link>https://worrbase.com/blog/leaving-sugar/</link>
                <guid>https://worrbase.com/blog/leaving-sugar/</guid>
                <description>&lt;p&gt;Well, my H&#x2F;FOSS class is coming to an end. In a few short hours, I&#x27;ll finish 
my last H&#x2F;FOSS class with a presentation on our work on Sugar (coincidentally
it&#x27;s also my last college class).&lt;&#x2F;p&gt;
&lt;p&gt;At this point, I&#x27;ve realized that Sugar is a fairly disorganized project. It
seems like it&#x27;s constantly in flux, with multiple wikis, bugtrackers, git repos,
etc. It&#x27;s very confusing to get started deving on - probably the most
difficult project to enter in my experience in FOSS.&lt;&#x2F;p&gt;
&lt;p&gt;That being said, walking away will be hard...well, not that hard since I don&#x27;t
plan on walking away just yet.&lt;&#x2F;p&gt;
&lt;p&gt;I was assigned some tasks by the team after my initial set of patches, so I&#x27;ll
make sure to finish those up. Then what? I&#x27;ll probably run away and never look
back.&lt;&#x2F;p&gt;
&lt;p&gt;While I can appreciate the work the Sugar devs do, it&#x27;s not a project that I
find particularly compelling, so I plan on leaving it once I&#x27;ve submitted my
last set of patches. &lt;&#x2F;p&gt;
</description>
            </item>
        
            <item>
                <title>Fixing Sugar bugs</title>
                <pubDate>Fri, 03 May 2013 00:00:00 +0000</pubDate>
                <link>https://worrbase.com/blog/sugar-fixes/</link>
                <guid>https://worrbase.com/blog/sugar-fixes/</guid>
                <description>&lt;p&gt;After a late start, Matt and I have been blazing ahead on development of
Sugar. As of this writing, we have 6 (almost 7) patches merged into Sugar
upstream.&lt;&#x2F;p&gt;
&lt;p&gt;The biggest hurdle in getting Sugar installed was that I wasn&#x27;t running it on
a supported OS. I was building and testing on Fedora 19, where it only
supports Fedora 18 and Ubuntu whateverthefuck.&lt;&#x2F;p&gt;
&lt;p&gt;As a result, my first 5 patches fixed various problems with the build system,
including adding support for Fedora 19. After some vigorous testing and
discussion, all 5 patches were merged in.&lt;&#x2F;p&gt;
&lt;p&gt;Afterwards, I found a crash in the journal caused by mousing over the Pippy
activity icon. The crash was caused by a call to a deprecated function...a
function prevalent across the entirety of Sugar. My 6th and 7th patches are
fixing this sweeping problem.&lt;&#x2F;p&gt;
&lt;p&gt;While we haven&#x27;t quite fixed the kinds of usability bugs we first set out to
fix, we are making a significant impact on Sugar and are helping fix the
contribution process.&lt;&#x2F;p&gt;
</description>
            </item>
        
            <item>
                <title>Week 2 in Sugarland</title>
                <pubDate>Thu, 11 Apr 2013 00:00:00 +0000</pubDate>
                <link>https://worrbase.com/blog/sugar-progress2/</link>
                <guid>https://worrbase.com/blog/sugar-progress2/</guid>
                <description>&lt;p&gt;Hey all,&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s Thursday during H&#x2F;FOSS class, which means that it&#x27;s time for an update on
my progress with Sugar.&lt;&#x2F;p&gt;
&lt;p&gt;We&#x27;ve made very little progress - we&#x27;ve uncovered some more network-related
usability bugs, but haven&#x27;t produced any working code yet.&lt;&#x2F;p&gt;
&lt;p&gt;Our environments have been set up, however Matt&#x27;s got blown away in an OS
reinstall.&lt;&#x2F;p&gt;
</description>
            </item>
        
            <item>
                <title>Sugar Progress</title>
                <pubDate>Thu, 04 Apr 2013 00:00:00 +0000</pubDate>
                <link>https://worrbase.com/blog/sugar-progress/</link>
                <guid>https://worrbase.com/blog/sugar-progress/</guid>
                <description>&lt;p&gt;Sugar progress has been slow so far - Matt and I have mostly been working on administrative stuff.&lt;&#x2F;p&gt;
&lt;p&gt;I specifically set up the project page, and communicated with the sugar community about the validity of some of our bugs.&lt;&#x2F;p&gt;
&lt;p&gt;Not much more to report than that.&lt;&#x2F;p&gt;
</description>
            </item>
        
            <item>
                <title>Introduction to Perl</title>
                <pubDate>Thu, 28 Mar 2013 00:00:00 +0000</pubDate>
                <link>https://worrbase.com/blog/intro-to-perl/</link>
                <guid>https://worrbase.com/blog/intro-to-perl/</guid>
                <description>&lt;p&gt;Hey everyone! I made a Perl seminar for &lt;a href=&quot;http:&#x2F;&#x2F;www.csh.rit.edu&#x2F;&quot;&gt;CSH&lt;&#x2F;a&gt;!&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.google.com&#x2F;presentation&#x2F;d&#x2F;1XXIpO0MYS70NHcdBvvLoXwsBMM_4IPnas9Vmd6h892s&#x2F;edit?usp=sharing&quot;&gt;Here it is!&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.google.com&#x2F;folder&#x2F;d&#x2F;0B2CJPQY-C9ItQVE4TVNEckc4N3c&#x2F;edit?usp=sharing&quot;&gt;And here is the code!&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;This isn&#x27;t even close to conclusive, but it does give you a basic introduction.&lt;&#x2F;p&gt;
&lt;p&gt;I cover certain topics that are important, and omit ones that are actually bad (default variable, 2 argument open).&lt;&#x2F;p&gt;
</description>
            </item>
        
            <item>
                <title>My thoughts on Open Source</title>
                <pubDate>Mon, 11 Mar 2013 00:00:00 +0000</pubDate>
                <link>https://worrbase.com/blog/my-thoughts-on-foss/</link>
                <guid>https://worrbase.com/blog/my-thoughts-on-foss/</guid>
                <description>&lt;p&gt;Surprisingly enough, this post &lt;em&gt;is not&lt;&#x2F;em&gt; for my FOSS class.&lt;&#x2F;p&gt;
&lt;p&gt;Anyway, &lt;a href=&quot;http:&#x2F;&#x2F;www.wired.com&#x2F;opinion&#x2F;2013&#x2F;03&#x2F;github&#x2F;&quot;&gt;this&lt;&#x2F;a&gt; article has been
circulating around my network lately, and it led me to think about my stance on
open source.&lt;&#x2F;p&gt;
&lt;p&gt;I love open source software, both writing it and using it.&lt;&#x2F;p&gt;
&lt;p&gt;Why?&lt;&#x2F;p&gt;
&lt;p&gt;First and foremost, I&#x27;m a student. Learning is quite literally my profession.
And hopefully after I graduate in May, I&#x27;ll continue to learn. I love technology
because to be truly successful, you need to continue to learn throughout your
career. &lt;&#x2F;p&gt;
&lt;p&gt;Open source allows me to learn by working with other people&#x27;s code. Whenever I
jump into a large codebase, I tend to pick up techniques and design strategies
employed by the original programmer. By doing this, I&#x27;ve also gotten
progressively better at jumping into large projects quickly and figuring out
exactly what I need to do to add whatever feature or fix whatever bug.&lt;&#x2F;p&gt;
&lt;p&gt;I also tend to get frustrated by poor software. There are a lot of open source
projects that I like that lack features, or are bug-ridden. Whenever I get
pissed off by something that doesn&#x27;t work, I can fix it. And then I can push my
changes upstream and fix it for everyone. Not only is it empowering, but I don&#x27;t
have to change my workflow&#x2F;program to account for other people&#x27;s broken code.&lt;&#x2F;p&gt;
&lt;p&gt;A benefit of pushing your code upstream is the feedback you get on it. Most open
source developers will analyze your code before they merge it in, give you
feedback and allow you to fix your change. It&#x27;s a great way to get some
constructive criticism on your code.&lt;&#x2F;p&gt;
&lt;p&gt;But the best benefit to working on open source is how it enhances my résumé. As
I mentioned before, I&#x27;m a student. There was a point where I was struggling to
get my first post-college job in the field. Having a github filled with open
source projects that I&#x27;ve pushed to as well as open source projects of my own
was a huge advantage over the competition - it helped me really stand out.&lt;&#x2F;p&gt;
&lt;p&gt;Never will I parrot the fucking notion that all software should be Free - it
shouldn&#x27;t be. I&#x27;ll never support viral open source licensing - that&#x27;s not
freedom and that hurts businesses, both small and large.&lt;&#x2F;p&gt;
&lt;p&gt;But I will say that open source is invaluable to students looking to get out
into industry, and that it allows people already in industry to train old
skills as well as learn new ones.&lt;&#x2F;p&gt;
</description>
            </item>
        
            <item>
                <title>FOSS Class Introduction</title>
                <pubDate>Thu, 07 Mar 2013 00:00:00 +0000</pubDate>
                <link>https://worrbase.com/blog/foss-intro/</link>
                <guid>https://worrbase.com/blog/foss-intro/</guid>
                <description>&lt;p&gt;So, first, I royally messed this up when I first committed this blog entry, and
wrote about 3 things I enjoyed doing, rather than writing about 3 Sugar
activities. That post has been removed - largely out of embarrassment&lt;&#x2F;p&gt;
&lt;p&gt;That being said, here are my three favorite Sugar activities.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;wine&quot;&gt;Wine&lt;&#x2F;h2&gt;
&lt;p&gt;The first activity I find interesting is Wine. This isn&#x27;t because I think the
Wine project is particularly interesting by itself, but because I find it
surprising that Wine has been &amp;quot;ported&amp;quot; to the OLPC as well as its reception.&lt;&#x2F;p&gt;
&lt;p&gt;One reviewer basically says that it&#x27;s how he does normal computing on his OLPC,
which is curious to me, as there really ought to be Activities to handle his
needs (in this case, playing games and listening to music).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;etoys&quot;&gt;Etoys&lt;&#x2F;h2&gt;
&lt;p&gt;Etoys was pretty much guaranteed to make this list, as I&#x27;m (obviously) a
programmer. It seems like a smart way to make programming more appealing to
children, so that they can get hooked at a young age.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;getbooks&quot;&gt;GetBooks&lt;&#x2F;h2&gt;
&lt;p&gt;GetBooks looks great, as it makes book acquisition trivial for people who want
to read. I&#x27;m not sure what kinds of books you can find using OPDS, but the idea
by itself is laudable. I honestly can&#x27;t wait to see what kinds of texts are
available to me.&lt;&#x2F;p&gt;
</description>
            </item>
        
            <item>
                <title>Managing ports in FreeBSD with CFEngine3</title>
                <pubDate>Mon, 06 Aug 2012 00:00:00 +0000</pubDate>
                <link>https://worrbase.com/blog/freebsd-cfengine/</link>
                <guid>https://worrbase.com/blog/freebsd-cfengine/</guid>
                <description>&lt;p&gt;CFEngine is a fantastic tool for managing configuration files and packages 
across heterogeneous environments. I figured I could use it to maintain a
basic set of installed packages across my Debian, OpenBSD and FreeBSD systems.&lt;&#x2F;p&gt;
&lt;p&gt;Except that the FreeBSD package_method promises in the cfengine standard 
library suck.&lt;&#x2F;p&gt;
&lt;p&gt;They use FreeBSD packages, and unless you have a box building your own sets of
FreeBSD packages...packages suck. They are built with all of the bells and
whistles, ergo they pull in a ton of shit you probably don&#x27;t need on your
system.&lt;&#x2F;p&gt;
&lt;p&gt;So I wrote a package_method promise that instead uses portmaster to install
and remove packages. Here&#x27;s the code:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#2b303b;&quot;&gt;
&lt;span style=&quot;color:#c0c5ce;&quot;&gt;body package_method freebsd_portmaster
{
    package_changes =&amp;gt; &amp;quot;individual&amp;quot;;

    package_list_command =&amp;gt; &amp;quot;&#x2F;usr&#x2F;sbin&#x2F;pkg_info&amp;quot;;

    package_list_name_regex    =&amp;gt; &amp;quot;([^\s]+)-.*&amp;quot;;
    package_list_version_regex =&amp;gt; &amp;quot;[^\s]+-([^\s]+).*&amp;quot;;

    package_installed_regex =&amp;gt; &amp;quot;.*&amp;quot;;

    package_name_convention =&amp;gt; &amp;quot;$(name)&amp;quot;;
    package_delete_convention =&amp;gt; &amp;quot;$(name)-$(version)&amp;quot;;

    package_file_repositories =&amp;gt; {
        &amp;quot;&#x2F;usr&#x2F;ports&#x2F;accessibility&#x2F;&amp;quot;,
        &amp;quot;&#x2F;usr&#x2F;port&#x2F;arabic&#x2F;&amp;quot;
        &amp;quot;&#x2F;usr&#x2F;ports&#x2F;archivers&#x2F;&amp;quot;,
        &amp;quot;&#x2F;usr&#x2F;ports&#x2F;astro&#x2F;&amp;quot;,
        &amp;quot;&#x2F;usr&#x2F;ports&#x2F;audio&#x2F;&amp;quot;,
        &amp;quot;&#x2F;usr&#x2F;ports&#x2F;benchmarks&#x2F;&amp;quot;,
        &amp;quot;&#x2F;usr&#x2F;ports&#x2F;biology&#x2F;&amp;quot;,
        &amp;quot;&#x2F;usr&#x2F;ports&#x2F;cad&#x2F;&amp;quot;,
        &amp;quot;&#x2F;usr&#x2F;ports&#x2F;chinese&#x2F;&amp;quot;,
        &amp;quot;&#x2F;usr&#x2F;ports&#x2F;comms&#x2F;&amp;quot;,
        &amp;quot;&#x2F;usr&#x2F;ports&#x2F;converters&#x2F;&amp;quot;,
        &amp;quot;&#x2F;usr&#x2F;ports&#x2F;databases&#x2F;&amp;quot;,
        &amp;quot;&#x2F;usr&#x2F;ports&#x2F;deskutils&#x2F;&amp;quot;,
        &amp;quot;&#x2F;usr&#x2F;ports&#x2F;devel&#x2F;&amp;quot;,
        &amp;quot;&#x2F;usr&#x2F;ports&#x2F;dns&#x2F;&amp;quot;,
        &amp;quot;&#x2F;usr&#x2F;ports&#x2F;editors&#x2F;&amp;quot;,
        &amp;quot;&#x2F;usr&#x2F;ports&#x2F;emulators&#x2F;&amp;quot;,
        &amp;quot;&#x2F;usr&#x2F;ports&#x2F;finance&#x2F;&amp;quot;,
        &amp;quot;&#x2F;usr&#x2F;ports&#x2F;french&#x2F;&amp;quot;,
        &amp;quot;&#x2F;usr&#x2F;ports&#x2F;ftp&#x2F;&amp;quot;,
        &amp;quot;&#x2F;usr&#x2F;ports&#x2F;games&#x2F;&amp;quot;,
        &amp;quot;&#x2F;usr&#x2F;ports&#x2F;german&#x2F;&amp;quot;,
        &amp;quot;&#x2F;usr&#x2F;ports&#x2F;graphics&#x2F;&amp;quot;,
        &amp;quot;&#x2F;usr&#x2F;ports&#x2F;hebrew&#x2F;&amp;quot;,
        &amp;quot;&#x2F;usr&#x2F;ports&#x2F;hungarian&#x2F;&amp;quot;,
        &amp;quot;&#x2F;usr&#x2F;ports&#x2F;irc&#x2F;&amp;quot;,
        &amp;quot;&#x2F;usr&#x2F;ports&#x2F;japanese&#x2F;&amp;quot;,
        &amp;quot;&#x2F;usr&#x2F;ports&#x2F;java&#x2F;&amp;quot;,
        &amp;quot;&#x2F;usr&#x2F;ports&#x2F;korean&#x2F;&amp;quot;,
        &amp;quot;&#x2F;usr&#x2F;ports&#x2F;lang&#x2F;&amp;quot;,
        &amp;quot;&#x2F;usr&#x2F;ports&#x2F;mail&#x2F;&amp;quot;,
        &amp;quot;&#x2F;usr&#x2F;ports&#x2F;math&#x2F;&amp;quot;,
        &amp;quot;&#x2F;usr&#x2F;ports&#x2F;mbone&#x2F;&amp;quot;,
        &amp;quot;&#x2F;usr&#x2F;ports&#x2F;misc&#x2F;&amp;quot;,
        &amp;quot;&#x2F;usr&#x2F;ports&#x2F;multimedia&#x2F;&amp;quot;,
        &amp;quot;&#x2F;usr&#x2F;ports&#x2F;net&#x2F;&amp;quot;,
        &amp;quot;&#x2F;usr&#x2F;ports&#x2F;net-im&#x2F;&amp;quot;,
        &amp;quot;&#x2F;usr&#x2F;ports&#x2F;net-mgmt&#x2F;&amp;quot;,
        &amp;quot;&#x2F;usr&#x2F;ports&#x2F;net-p2p&#x2F;&amp;quot;,
        &amp;quot;&#x2F;usr&#x2F;ports&#x2F;news&#x2F;&amp;quot;,
        &amp;quot;&#x2F;usr&#x2F;ports&#x2F;packages&#x2F;&amp;quot;,
        &amp;quot;&#x2F;usr&#x2F;ports&#x2F;palm&#x2F;&amp;quot;,
        &amp;quot;&#x2F;usr&#x2F;ports&#x2F;polish&#x2F;&amp;quot;,
        &amp;quot;&#x2F;usr&#x2F;ports&#x2F;ports-mgmt&#x2F;&amp;quot;,
        &amp;quot;&#x2F;usr&#x2F;ports&#x2F;portuguese&#x2F;&amp;quot;,
        &amp;quot;&#x2F;usr&#x2F;ports&#x2F;print&#x2F;&amp;quot;,
        &amp;quot;&#x2F;usr&#x2F;ports&#x2F;russian&#x2F;&amp;quot;,
        &amp;quot;&#x2F;usr&#x2F;ports&#x2F;science&#x2F;&amp;quot;,
        &amp;quot;&#x2F;usr&#x2F;ports&#x2F;security&#x2F;&amp;quot;,
        &amp;quot;&#x2F;usr&#x2F;ports&#x2F;shells&#x2F;&amp;quot;,
        &amp;quot;&#x2F;usr&#x2F;ports&#x2F;sysutils&#x2F;&amp;quot;,
        &amp;quot;&#x2F;usr&#x2F;ports&#x2F;textproc&#x2F;&amp;quot;,
        &amp;quot;&#x2F;usr&#x2F;ports&#x2F;ukrainian&#x2F;&amp;quot;,
        &amp;quot;&#x2F;usr&#x2F;ports&#x2F;vietnamese&#x2F;&amp;quot;,
        &amp;quot;&#x2F;usr&#x2F;ports&#x2F;www&#x2F;&amp;quot;,
        &amp;quot;&#x2F;usr&#x2F;ports&#x2F;x11&#x2F;&amp;quot;,
        &amp;quot;&#x2F;usr&#x2F;ports&#x2F;x11-clocks&#x2F;&amp;quot;,
        &amp;quot;&#x2F;usr&#x2F;ports&#x2F;x11-drivers&#x2F;&amp;quot;,
        &amp;quot;&#x2F;usr&#x2F;ports&#x2F;x11-fm&#x2F;&amp;quot;,
        &amp;quot;&#x2F;usr&#x2F;ports&#x2F;x11-fonts&#x2F;&amp;quot;,
        &amp;quot;&#x2F;usr&#x2F;ports&#x2F;x11-servers&#x2F;&amp;quot;,
        &amp;quot;&#x2F;usr&#x2F;ports&#x2F;x11-themes&#x2F;&amp;quot;,
        &amp;quot;&#x2F;usr&#x2F;ports&#x2F;x11-toolkits&#x2F;&amp;quot;,
        &amp;quot;&#x2F;usr&#x2F;ports&#x2F;x11-wm&#x2F;&amp;quot;,
    };

    package_add_command =&amp;gt; &amp;quot;&#x2F;usr&#x2F;local&#x2F;sbin&#x2F;portmaster -D -G --no-confirm&amp;quot;;
    package_update_command =&amp;gt; &amp;quot;&#x2F;usr&#x2F;local&#x2F;sbin&#x2F;portmaster -D -G --no-confirm&amp;quot;;
    package_delete_command =&amp;gt; &amp;quot;&#x2F;usr&#x2F;local&#x2F;sbin&#x2F;portmaster --no-confirm -e&amp;quot;;

    expireafter =&amp;gt; 240;
}
&lt;&#x2F;span&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The only interesting thing about the body of the promise is that I&#x27;m using
package_file_repositories in a way that it was never intended to be used.
Since the port names needed to be provided to portmaster in a
&lt;category&gt;&#x2F;&lt;name&gt; format, I&#x27;m leveraging a cfengine trick to kind of fake
that. If you provide a package_file_repositories clause, cfengine will
prepend a variable called $(firstrepo) to the name of every package that it
adds to the package_add_command line. &lt;&#x2F;p&gt;
&lt;p&gt;Armed with this knowledge, we just add a package_file_repositories entry for
each port category directory, and the problem&#x27;s been solved.&lt;&#x2F;p&gt;
</description>
            </item>
        
            <item>
                <title>CFEngine SVN pre-commit hook</title>
                <pubDate>Wed, 11 Jul 2012 00:00:00 +0000</pubDate>
                <link>https://worrbase.com/blog/cfengine-svn-pre-commit/</link>
                <guid>https://worrbase.com/blog/cfengine-svn-pre-commit/</guid>
                <description>&lt;p&gt;I use CFEngine on my personal site to manage my configuration. I have an SVN repo on one box that I can push
configuration changes to, and then from there, the changes get pushed out to all of my boxes.&lt;&#x2F;p&gt;
&lt;p&gt;One problem that I encountered is that changes to my CFEngine configurations that had syntax errors would be
pushed out to all of my machines, and cause them to fallback to the failsafe configuration, which is less than
ideal.&lt;&#x2F;p&gt;
&lt;p&gt;My solution was to write a pre-commit hook for my SVN repo that would prevent me from checking anything in that
would break my configuration.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#2b303b;&quot;&gt;
&lt;span style=&quot;color:#65737e;&quot;&gt;#!&#x2F;bin&#x2F;bash

&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;REPOS&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;=$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;1
TXN&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;=$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;2
LOG&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;=&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;&#x2F;home&#x2F;svn&#x2F;commit.log&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;CHANGES&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;0

&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;[[ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot; = &amp;quot;&amp;quot; &amp;amp;&amp;amp; &amp;quot;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot; = &amp;quot;&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;]]&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;then
  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;echo &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Most be called as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt; REPOS TXN&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot; &amp;gt;&amp;gt; &amp;quot;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;LOG&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;
  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;exit&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; 1
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fi

&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;AWK&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;=&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;&#x2F;bin&#x2F;awk&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;GREP&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;=&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;&#x2F;bin&#x2F;grep&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;RM&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;=&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;&#x2F;bin&#x2F;rm&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;ECHO&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;=&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;&#x2F;bin&#x2F;echo&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;SED&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;=&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;&#x2F;bin&#x2F;sed&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;SVN&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;=&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;&#x2F;usr&#x2F;bin&#x2F;svn&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;SVNLOOK&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;=&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;&#x2F;usr&#x2F;bin&#x2F;svnlook&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;SVN_URL&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;=&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;file:&#x2F;&#x2F;&#x2F;home&#x2F;svn&#x2F;cfengine&#x2F;trunk&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;CF_PROMISES&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;=&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;&#x2F;usr&#x2F;sbin&#x2F;cf-promises&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;

&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;PROMISEDIR&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;=&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;&#x2F;home&#x2F;svn&#x2F;.cfagent&#x2F;inputs&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;MODULESIDR&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;=&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;&#x2F;home&#x2F;svn&#x2F;.cfagent&#x2F;modules&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;

&amp;quot;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;ECHO&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;REPOS &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;REPOS&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot; &amp;gt;&amp;gt; &amp;quot;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;LOG&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;
&amp;quot;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;ECHO&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;TXN &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;TXN&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot; &amp;gt;&amp;gt; &amp;quot;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;LOG&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;

&amp;quot;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;ECHO&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Checking out working copy from &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;REPOS&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt; ....&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot; &amp;gt;&amp;gt; &amp;quot;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;LOG&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;
&amp;quot;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;SVN&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot; co&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt; --depth&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; immediates &amp;quot;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;SVN_URL&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;}&#x2F;cf-agent_policies&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot; &amp;quot;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;PROMISEDIR&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot; &amp;gt; &#x2F;dev&#x2F;null
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;[[ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;? -ne&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; 0 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;]]&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;then
  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;ECHO&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Failed to get fresh working copy&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot; &amp;gt;&amp;gt; &amp;quot;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;LOG&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;
  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;exit&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; 1
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fi

&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;SVN&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot; co&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt; --depth&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; immediates &amp;quot;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;SVN_URL&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;}&#x2F;cf-agent_modules&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot; &amp;quot;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;MODULESIDR&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot; &amp;gt; &#x2F;dev&#x2F;null
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;[[ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;? -ne&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; 0 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;]]&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;then
  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;ECHO&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Failed to get fresh working copy&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot; &amp;gt;&amp;gt; &amp;quot;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;LOG&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;
  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;exit&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; 1
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fi

&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;# Figure out what directories have changed using svnlook.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;FILES=`$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;{SVNLOOK}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; changed ${&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;REPOS&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt; -t &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;${&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;TXN&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;} | $&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;{AWK} &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;{ print $2 }&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;#39;` &amp;gt; &#x2F;dev&#x2F;null

&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; FILE &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;FILES&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;do
  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;ECHO&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;file changed &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;FILE&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot; &amp;gt;&amp;gt; &amp;quot;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;LOG&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;
  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;[[ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;$(&amp;quot;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;ECHO&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot; &amp;quot;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;FILE&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot; | $&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;{GREP}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; cfengine&#x2F;trunk) != &amp;quot;&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;]]&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;then
    if &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;[[ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;$(&amp;quot;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;ECHO&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot; &amp;quot;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;FILE&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot; | $&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;{GREP}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; generic_cf-agent_policies) != &amp;quot;&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;]]&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;then
      if &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;[[ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;$(&amp;quot;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;ECHO&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot; &amp;quot;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;FILE&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot; | &amp;quot;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;SED&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt; -e &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;s&#x2F;home\&#x2F;svn\&#x2F;cfengine\&#x2F;trunk\&#x2F;cf-agent_policies\&#x2F;&#x2F;&#x2F;g&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;#39;) != &amp;quot;&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;]]&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;then
        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;CHANGES&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;1
        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;SVNLOOK&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot; cat &amp;quot;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;REPOS&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot; &amp;quot;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;FILE&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt; -t &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;TXN&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot; &amp;gt; ${&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;PROMISEDIR&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;}&#x2F;$(&amp;quot;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;ECHO&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot; &amp;quot;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;FILE&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot; | &amp;quot;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;SED&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt; -e &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;s&#x2F;home\&#x2F;cfengine\&#x2F;trunk\&#x2F;cf-agent_policies\&#x2F;&#x2F;&#x2F;g&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;#39;)
      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fi
    fi
  fi
done

if &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;[[ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;${&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;CHANGES&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;} &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;-eq&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; 0 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;]]&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;then
  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;exit&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; 0
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fi

&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;CF_PROMISES&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt; --dry-run &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;gt; &#x2F;dev&#x2F;null
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;[[ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;? -ne&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; 0 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;]]&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;then
  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;ECHO&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Syntax error! Aborting commit!&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot; &amp;gt;&amp;gt; &amp;quot;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;LOG&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;

  &amp;quot;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;RM&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt; -rf &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;PROMISEDIR&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;
  &amp;quot;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;RM&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt; -rf &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;MODULESIDR&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;

  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;exit&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; 1
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fi

&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;RM&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt; -rf &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;PROMISEDIR&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;
&amp;quot;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;RM&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt; -rf &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;MODULESIDR&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This should be the pre-commit file in the hooks directory of your SVN repo. If that file exits with a non-zero code, the commit will fail.
The file &lt;em&gt;must&lt;&#x2F;em&gt; be executable by the svn user.&lt;&#x2F;p&gt;
</description>
            </item>
        
            <item>
                <title>Book Review: Programming Perl</title>
                <pubDate>Tue, 10 Jul 2012 00:00:00 +0000</pubDate>
                <link>https://worrbase.com/blog/programming-perl/</link>
                <guid>https://worrbase.com/blog/programming-perl/</guid>
                <description>&lt;p&gt;&lt;strong&gt;NOTE:&lt;&#x2F;strong&gt;
&lt;em&gt;Hey! This is a book review I wrote some time ago that was published &lt;a href=&quot;http:&#x2F;&#x2F;www.csh.rit.edu&#x2F;reviews?page=1&quot;&gt;here&lt;&#x2F;a&gt;. This review is outdated, mostly because there IS a new edition about the last major release of perl, perl 5.14. Because of the release of the new edition, I thought it might be good to reproduce the review on my blog.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The camel book is a book that needs no introduction. The Perl community considers it the ultimate Perl book, and rightfully so, as it is written by Larry Wall himself (also Christiansen and Jon Orwant)!&lt;&#x2F;p&gt;
&lt;p&gt;The camel book is an in-depth look at the Perl programming language. The book does a fantastic job explaining how to use the language, the more powerful aspects of the language, as well as some of the implementation details of the compiler. As you progress through the book, it constantly builds upon itself. Different quirks&#x2F;features of the language which are first introduced as black magic are explained in exhaustive detail later on. For example, you first learn about what the autoload pragma is, followed by advanced usage of goto, and then they tie that together by detailing how autoload is implemented with gotos. As a side note, I know this sounds gross, but gotos aren&#x27;t what you think they are in Perl... at least not always.&lt;&#x2F;p&gt;
&lt;p&gt;The writing is, for the most part, very clear and understandable, and contains a heavy dose of humor. The humor is definitely welcome, as the text would be horribly dry without it. The humor also tends to be representative of the Perl community at large, which is fabulous for the new Perl programmer. The only problem I had with the writing style was the chapter on regular expressions. In this chapter, the wording is murky at times, and more examples would be a welcome addition. Like I said though, this is only one chapter.&lt;&#x2F;p&gt;
&lt;p&gt;The biggest problem with this book is that it&#x27;s old. The latest edition (3rd at the time of this writing) only covers up to Perl 5.6. We&#x27;re at Perl 5.12 now, with 5.14 on the horizon, and a significant amount has changed. However, that doesn&#x27;t make this book irrelevant. I think it makes a wonderful companion to Modern Perl by chromatic. Once someone has a handle on how to write modern Perl (&amp;gt;=5.10), this book is definitely a great look at the rest of Perl as well as an interesting peek into the internals of the language. Regardless of recent developments in the language, this book still has a significant amount of relevant content.&lt;&#x2F;p&gt;
&lt;p&gt;If you want to truly become a Perl master, you need a copy of this book, but keep in mind you&#x27;ll also probably want a book that covers more modern Perl.&lt;&#x2F;p&gt;
</description>
            </item>
        
            <item>
                <title>CrashPlan on FreeBSD 9.0, A HOWTO</title>
                <pubDate>Sat, 31 Mar 2012 00:00:00 +0000</pubDate>
                <link>https://worrbase.com/blog/crashplan/</link>
                <guid>https://worrbase.com/blog/crashplan/</guid>
                <description>&lt;p&gt;This was an incredibly productive week for me. I got a lot done, including
setting up Nagios for my servers, starting a CSH Photohunt Android app, working
a bit on a game that I&#x27;ve been writing, and most importantly, rolling out
network backups.&lt;&#x2F;p&gt;
&lt;p&gt;And that&#x27;s what this post is about.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;http:&#x2F;&#x2F;www.crashplan.com&#x2F;&quot;&gt;CrashPlan&lt;&#x2F;a&gt; is a cloud backup service that allows
users to backup &lt;em&gt;unlimited data&lt;&#x2F;em&gt; for a small monthly fee. For people with large
amounts of data, this is a significantly cheaper solution than Amazon S3 or
Carbonite or similar. I quickly purchased the unlimited backup service, and
decided to start backing up all of my computers using their service.&lt;&#x2F;p&gt;
&lt;p&gt;While I really hate the GUI tool, I think the service itself is fantastic.
&lt;a href=&quot;http:&#x2F;&#x2F;www.onlinebackupsreview.com&#x2F;crashplan.php&quot;&gt;Here&#x27;s a fantastic review&lt;&#x2F;a&gt; of
the backup service, as well as a coupon.&lt;&#x2F;p&gt;
&lt;p&gt;Let me first start out by saying that I already do backups. I do Time Machine
and rsync backups to my FreeBSD NAS. What I was looking for initially was a
cloud backup service that allowed me to backup my entire NAS to the internet (if
I say &amp;quot;cloud&amp;quot; one more time...). CrashPlan doesn&#x27;t &amp;quot;support&amp;quot; FreeBSD. That is to
say, they don&#x27;t officially provide a client to allow you to backup from
FreeBSD...but it&#x27;s more than possible.&lt;&#x2F;p&gt;
&lt;p&gt;So without further ado...&lt;&#x2F;p&gt;
&lt;h2 id=&quot;how-to-backup-your-freebsd-9-0-machine-with-crashplan&quot;&gt;How to backup your FreeBSD 9.0 machine with CrashPlan&lt;&#x2F;h2&gt;
&lt;p&gt;First, set up and install the linux compatibility environment. Open up your
make.conf and add these two lines:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#2b303b;&quot;&gt;
OVERRIDE_LINUX_BASE_PORT=f10
OVERRIDE_LINUX_NONBASE_PORTS=f10
&lt;&#x2F;pre&gt;
&lt;p&gt;We want to install the Fedora 10-based environment, since it&#x27;s the newest and
best supported one at the time of this writing. Then, load the linux.ko kernel
module, and add the option startup option to your rc.conf.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#2b303b;&quot;&gt;
# kldload linux.ko
# echo &amp;quot;linux_enable=\&amp;quot;YES\&amp;quot;&amp;quot; &amp;gt;&amp;gt; &#x2F;etc&#x2F;rc.conf
# echo &amp;quot;crashplan_enable=\&amp;quot;YES\&amp;quot;&amp;quot; &amp;gt;&amp;gt; &#x2F;etc&#x2F;rc.conf
&lt;&#x2F;pre&gt;
&lt;p&gt;Now, install the compat environment, java and linproc&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#2b303b;&quot;&gt;
# portmaster emulators&#x2F;linux_base-f10
# portmaster sysutils&#x2F;linux-procps
# portmaster java&#x2F;linux-sun-jre16
&lt;&#x2F;pre&gt;
&lt;p&gt;Add linproc to your &#x2F;etc&#x2F;fstab, as well as some other mounts while we&#x27;re here&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#2b303b;&quot;&gt;
# echo &amp;quot;linproc &#x2F;compat&#x2F;linux&#x2F;proc linprocfs rw 0 0&amp;quot; &amp;gt;&amp;gt; &#x2F;etc&#x2F;fstab
# echo &amp;quot;&#x2F;usr &#x2F;backup&#x2F;usr nullfs rw 0 0&amp;quot; &amp;gt;&amp;gt; &#x2F;etc&#x2F;fstab
# echo &amp;quot;&#x2F;var &#x2F;backup&#x2F;var nullfs rw 0 0&amp;quot; &amp;gt;&amp;gt; &#x2F;etc&#x2F;fstab
&lt;&#x2F;pre&gt;
&lt;p&gt;When you&#x27;re in the linux compat environment, &#x2F;usr and &#x2F;var are resolved to
&#x2F;compat&#x2F;linux&#x2F;usr and &#x2F;compat&#x2F;linux&#x2F;var transparently. We need those nullfs
mounts so that we can actually back up &#x2F;usr and &#x2F;var. Those are a bit important.&lt;&#x2F;p&gt;
&lt;p&gt;Now mount the shit out of everything.&lt;&#x2F;p&gt;
&lt;p&gt;Download crashplan somewhere under &#x2F;compat&#x2F;linux, and then chroot into your
linux environment. Run the install script, and back out.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#2b303b;&quot;&gt;
# chroot &#x2F;compat&#x2F;linux&#x2F; &#x2F;bin&#x2F;bash
# cd CrashPlan-install &amp;amp;&amp;amp; .&#x2F;install.sh
&lt;&#x2F;pre&gt;
&lt;p&gt;chrooting is not absolutely necessary, but whatever. Moving on! We have some
stuff to configure with CrashPlan before it&#x27;ll run well, and we&#x27;re going to need
to find&#x2F;write ourselves an init script as well!&lt;&#x2F;p&gt;
&lt;p&gt;First, in &#x2F;compat&#x2F;linux&#x2F;usr&#x2F;local&#x2F;crashplan&#x2F;bin&#x2F;run.conf, modify the two lines
to end with this:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#2b303b;&quot;&gt;
SRV_JAVA_OPTS=&amp;quot;... -Djava.nio.channels.spi.SelectorProvider=sun.nio.ch.PollSelectorProvider&amp;quot;
GUI_JAVA_OPTS=&amp;quot;... -Djava.nio.channels.spi.SelectorProvider=sun.nio.ch.PollSelectorProvider&amp;quot;
&lt;&#x2F;pre&gt;
&lt;p&gt;The important part is the last define on both lines. CrashPlan uses epoll, which
isn&#x27;t available to us on FreeBSD. That line essentially tells CrashPlan to
behave itself on our platform.&lt;&#x2F;p&gt;
&lt;p&gt;Another thing we ought to do is to tell CrashPlan where Java is. Add a line to
&#x2F;compat&#x2F;linux&#x2F;usr&#x2F;local&#x2F;crashplan&#x2F;install.vars that does that&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#2b303b;&quot;&gt;
JAVACOMMON=&amp;lt;YOUR PATH TO LINUX JAVA&amp;gt;
&lt;&#x2F;pre&gt;
&lt;p&gt;Neat! Now we just need an init script...and we can get that from &lt;a href=&quot;http:&#x2F;&#x2F;blog.oddbit.com&#x2F;2011&#x2F;05&#x2F;installing-crashplan-under-freebsd-8.html&quot;&gt;one of the two
sources I got some of this information
from!&lt;&#x2F;a&gt;
All we care about is the init script at the bottom. We&#x27;ve already done all of
the other steps listed (and more!), so don&#x27;t worry about those. We&#x27;ve done some
things differently, but IMO this is a better setup.&lt;&#x2F;p&gt;
&lt;p&gt;Copy the contents of that initscript to &#x2F;usr&#x2F;local&#x2F;etc&#x2F;rc.d&#x2F;crashplan, and
you&#x27;re good to go. You can start it with&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#2b303b;&quot;&gt;
# service crashplan start
&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;a href=&quot;http:&#x2F;&#x2F;kim.scarborough.chicago.il.us&#x2F;do&#x2F;nerd&#x2F;tips&#x2F;crashplan&quot;&gt;Here&lt;&#x2F;a&gt; is the other
source of my information regarding CrashPlan installation on FreeBSD.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;http:&#x2F;&#x2F;stgsupport.crashplan.com&#x2F;doku.php&#x2F;how_to&#x2F;configure_a_headless_client&quot;&gt;Here&lt;&#x2F;a&gt;
is the official documentation for running CrashPlan headless.&lt;&#x2F;p&gt;
&lt;p&gt;Happy backups!&lt;&#x2F;p&gt;
</description>
            </item>
        
            <item>
                <title>OSS and App::GitHub</title>
                <pubDate>Tue, 27 Mar 2012 00:00:00 +0000</pubDate>
                <link>https://worrbase.com/blog/oss/</link>
                <guid>https://worrbase.com/blog/oss/</guid>
                <description>&lt;p&gt;I have a love hate relationship with open source software.&lt;&#x2F;p&gt;
&lt;p&gt;On the one had, I get incredibly frustrated by the lack of support, the lack of
documentation and the spotty code quality.&lt;&#x2F;p&gt;
&lt;p&gt;On the other, I love having the ability to fix other people&#x27;s code. It&#x27;s been an
incredibly important tool in my education. I definitely would not have nearly
the knowledge that I do now if it weren&#x27;t for the ability to quickly and easily
involve myself in open source projects.&lt;&#x2F;p&gt;
&lt;p&gt;Not only that, it&#x27;s also convenient to have the ability to fix broken software
that I&#x27;d like to use.&lt;&#x2F;p&gt;
&lt;p&gt;Honestly, while I find that closed-source software has significantly fewer bugs,
better documentation and better support - I have to say that that last point is
a very compelling case for the use of open source software...&lt;em&gt;by developers&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;I don&#x27;t understand why non-developers get so evangelical about open source
software. I just can&#x27;t understand what the appeal is for them. Sure, if the
software is stable and fulfills a need, by all means use it - but why the hell
are there so many non-developer Linux users that constantly and mindlessly
praise open source?&lt;&#x2F;p&gt;
&lt;p&gt;But I digress.&lt;&#x2F;p&gt;
&lt;p&gt;Regardless, for me, as a part-time developer, open source software is tits,
simply for the ability to fix bugs that piss me off.&lt;&#x2F;p&gt;
&lt;p&gt;I ran into a great example of this this past weekend, actually. I found a
fantastic Perl module, &lt;a href=&quot;https:&#x2F;&#x2F;metacpan.org&#x2F;module&#x2F;App::GitHub&quot;&gt;App::GitHub&lt;&#x2F;a&gt;.
While the idea is fantastic, the version I tried to use was horribly broken.&lt;&#x2F;p&gt;
&lt;p&gt;A beer and 4 patches later, I fixed it and was offered co-maintainership.&lt;&#x2F;p&gt;
&lt;p&gt;So this is also half of an announcement of a new release of App::GitHub that
doesn&#x27;t break when you try and use it.&lt;&#x2F;p&gt;
</description>
            </item>
        
            <item>
                <title>AdiumQQ</title>
                <pubDate>Tue, 17 Jan 2012 00:00:00 +0000</pubDate>
                <link>https://worrbase.com/blog/adiumqq/</link>
                <guid>https://worrbase.com/blog/adiumqq/</guid>
                <description>&lt;p&gt;Sometimes, the best projects come out of the dumbest disputes.&lt;&#x2F;p&gt;
&lt;p&gt;I was in my room, and my former roommate &lt;a href=&quot;http:&#x2F;&#x2F;clockfort.com&quot;&gt;Clockfort&lt;&#x2F;a&gt; and
&lt;a href=&quot;http:&#x2F;&#x2F;rus.har.mn&#x2F;&quot;&gt;Russ&lt;&#x2F;a&gt; got talking about old chat protocols that we used to
use. Clockfort suddenly remembered his old ICQ number, and we went around adding
each other on all of our old chat networks.&lt;&#x2F;p&gt;
&lt;p&gt;I took this joke a little far, however. I started making all kinds of new
accounts. I went through every protocol supported by pidgin, and signed up for
accounts. At the time, pidgin listed &lt;a href=&quot;http:&#x2F;&#x2F;www.imqq.com&quot;&gt;QQ&lt;&#x2F;a&gt; as a supported
protocol.&lt;&#x2F;p&gt;
&lt;p&gt;I signed up for a QQ account, and tried to connect with pidgin. Unfortunately,
it just didn&#x27;t work. I found out that the builtin QQ plugin didn&#x27;t support the
latest QQ protocol. I fount a plugin called
&lt;a href=&quot;http:&#x2F;&#x2F;code.google.com&#x2F;p&#x2F;libqq-pidgin&#x2F;&quot;&gt;libqq-pidgin&lt;&#x2F;a&gt; that did exactly what I
needed. So I installed it, and added my one Chinese friend to my buddy list.&lt;&#x2F;p&gt;
&lt;p&gt;Later that night, I wanted to talk to her at work. I booted up Adium, and added
my QQ account. Unfortunately, it didn&#x27;t work, because like pidgin, Adium is
built on top of libpurple, and libpurple dropped official support for QQ. My
solution was to write my own QQ plugin for Adium.&lt;&#x2F;p&gt;
&lt;p&gt;The end result is &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;worr&#x2F;AdiumQQ&#x2F;&quot;&gt;AdiumQQ&lt;&#x2F;a&gt;. It supports
basic features right now, like chat and such. It does not support file transfers
or captchas just yet. Those features are coming.&lt;&#x2F;p&gt;
&lt;p&gt;Today, I&#x27;m posting about it in my blog because it just got accepted in &lt;a href=&quot;http:&#x2F;&#x2F;adiumxtras.com&#x2F;&quot;&gt;Adium
Xtras&lt;&#x2F;a&gt;. I&#x27;m really proud, since this is my first open
source program I&#x27;ve written that people are finding useful.&lt;&#x2F;p&gt;
&lt;p&gt;Thanks to the libqq-pidgin team for making a nice base for me to build my plugin
off of!&lt;&#x2F;p&gt;
&lt;p&gt;I will of course announce any new release information on my blog.&lt;&#x2F;p&gt;
</description>
            </item>
        
            <item>
                <title>rvm and perlbrew</title>
                <pubDate>Tue, 27 Dec 2011 00:00:00 +0000</pubDate>
                <link>https://worrbase.com/blog/rvm-and-perlbrew/</link>
                <guid>https://worrbase.com/blog/rvm-and-perlbrew/</guid>
                <description>&lt;p&gt;I was kind of an idiot in my last post. I wrote a ruby script to 
symlink my gems&#x27; executables to &#x2F;usr&#x2F;local&#x2F;bin. Well that&#x27;s dumb.  There&#x27;s a
much better way to accomplish the same goal, with some healthier side effects!
It&#x27;s called &lt;a href=&quot;http:&#x2F;&#x2F;beginrescueend.com&#x2F;rvm&#x2F;install&#x2F;&quot;&gt;rvm&lt;&#x2F;a&gt; (or Ruby Version 
Manager)!&lt;&#x2F;p&gt;
&lt;p&gt;rvm allows you to manage multiple versions of ruby that are installed to a
location in your home directory. You can select a version of ruby to use for
current session with 
rvm use 1.9.2
That command will use ruby-1.9.2, provided you installed it with rvm. To
install:
rvm install 1.9.2
When you have a version of ruby selected, gems will install into the
directory that houses that version of ruby, and won&#x27;t pollute your
system install of ruby.&lt;&#x2F;p&gt;
&lt;p&gt;App::perlbrew (installable through cpan) does exactly the same thing, albeit
with Perl! I heartily recommend both if you do development with either ruby
or Perl.&lt;&#x2F;p&gt;
</description>
            </item>
        
            <item>
                <title>Ruby and Gems from Homebrew on Mac OSX</title>
                <pubDate>Wed, 15 Jun 2011 00:00:00 +0000</pubDate>
                <link>https://worrbase.com/blog/homebrew-rubygems/</link>
                <guid>https://worrbase.com/blog/homebrew-rubygems/</guid>
                <description>&lt;p&gt;Hey, so I bought a Macbook Air a month ago, and I&#x27;ve grown to absolutely adore
it. It basically comes down to that I have an OS that I don&#x27;t need to fix
constantly, while also having access to all of the utilities I&#x27;m used to using
on my Linux&#x2F;UNIX environments.&lt;&#x2F;p&gt;
&lt;p&gt;I use &lt;a href=&quot;http:&#x2F;&#x2F;mxcl.github.com&#x2F;homebrew&#x2F;&quot;&gt;Homebrew&lt;&#x2F;a&gt; to manage my software,
because it seems to be the best package management solution for OS X. I
haven&#x27;t really tried any others, but I have no inclination to after using
Homebrew for the past few months.&lt;&#x2F;p&gt;
&lt;p&gt;Oh and I also learned Ruby. And I kind of like it so far.&lt;&#x2F;p&gt;
&lt;p&gt;Regardless, this post isn&#x27;t about my Ruby experience thus far. It&#x27;s just
documenting a minor annoyance. When I install gems using ruby1.9 from
Homebrew, the gems don&#x27;t make a symlink in &#x2F;usr&#x2F;local, and the internet tells
me the right thing to do is to make it myself.&lt;&#x2F;p&gt;
&lt;p&gt;Well fuck that.&lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s a brief ruby program that will insert these links for you! I&#x27;m not
claiming to be a Ruby expert, or even competent, so run this at your own risk.
It can get a little destructive, and makes some assumptions.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#2b303b;&quot;&gt;
&lt;span style=&quot;color:#65737e;&quot;&gt;#!&#x2F;usr&#x2F;bin&#x2F;env ruby

&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;require &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;RubyGems&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;#39;

&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;installed_gems &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;= []
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;prefix &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;= &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;&#x2F;usr&#x2F;local&#x2F;bin&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;#39;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;ruby &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;= &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;&#x2F;usr&#x2F;local&#x2F;Cellar&#x2F;ruby&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;#39;

&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;Gem&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;Specification&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;all_names&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;reverse&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;each &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;do &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;gem&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;|
  (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;version&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;) = [&amp;#39;&amp;#39;, &amp;#39;&amp;#39;]
  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;gem&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;match&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;([\w&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;\-&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;\-&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;([\w&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;\.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&#x2F;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;do &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;m&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;|
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;name = m&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;captures&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;]
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;version = m&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;captures&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;]
  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;end

  Gem::Specification&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;new do &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;|
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;name = name
    s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;version = version

    installed_gems&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;push&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;)

  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;end

  installed_gems&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;delete_if do &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;i&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;|
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;name == i&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;name and Gem::Version&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;version&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;) &amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;Gem&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;Version&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;i&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;version&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;)
  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;end
end


installed_gems&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;each &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;do &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;gem&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;|
  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; File.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;directory&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;? &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;gem&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;bin_dir  then&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
    Dir.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;entries&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;gem&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;bin_dir&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;each &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;do &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;file&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;|
     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;fullpath &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;gem&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;bin_dir &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;+ &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;#39; + &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;file
     newpath &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;prefix &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;+ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;file

     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;not File.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;directory&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;? &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;fullpath  then
       &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; File.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;symlink&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;? &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;newpath then
         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; File.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;readlink&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;newpath&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;match &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;%&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;{&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;usr&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;local&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;Cellar&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;ruby&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;} &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;then
           puts &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Linking #{fullpath} to #{newpath}...&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;
           File.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unlink &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;newpath&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
           File.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;symlink &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;fullpath&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;newpath
         end
       end
     end
    end
  end
end
&lt;&#x2F;span&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Hope that helps.&lt;&#x2F;p&gt;
</description>
            </item>
        
            <item>
                <title>Hotel Internet</title>
                <pubDate>Tue, 14 Jun 2011 00:00:00 +0000</pubDate>
                <link>https://worrbase.com/blog/hotel-internet/</link>
                <guid>https://worrbase.com/blog/hotel-internet/</guid>
                <description>&lt;p&gt;Have you ever been to a hotel, or an airport, that served wireless? And the
after you connected, you get redirected to a page where you pay money, or
make an account? Those are called captive portals. Setting up your own is
really easy!&lt;&#x2F;p&gt;
&lt;p&gt;The old de facto FOSS software for captive portals was
&lt;a href=&quot;https:&#x2F;&#x2F;worrbase.com&#x2F;blog&#x2F;hotel-internet&#x2F;www.chillispot.info&quot;&gt;Chillispot&lt;&#x2F;a&gt;. However, this software is old, and broken,
and doesn&#x27;t really work anymore. So, I used its drop in replacement,
&lt;a href=&quot;coova.org&#x2F;CoovaChilli&quot;&gt;CoovaChilli&lt;&#x2F;a&gt;. CoovaChilli is totally compatible with
Chillispot, so if you&#x27;ve used Chillispot before, you can use your old
configuration with CoovaChilli without any modification.&lt;&#x2F;p&gt;
&lt;p&gt;CoovaChilli handles serving DHCP to your clients, as well as setting up
routing for you. Your server acts as a router for traffic for auth&#x27;d clients.
CoovaChilli creates a tun device that it tunnels traffic through, kind of like
a VPN. 
Since it serves DHCP, you can configure it to give your clients DNS servers,
proxy information, etc. CoovaChilli will also load up a whole bunch of
firewall rules that will restrict what resources clients can access on your
network.&lt;&#x2F;p&gt;
&lt;p&gt;First step, set up a simple FreeRadius configuration. I left mine pretty with the
Debian defaults, and just created some accounts for testing. This system isn&#x27;t
in production, so I don&#x27;t care about tuning my radius setup. And FreeRadius
isn&#x27;t the point of this entry.&lt;&#x2F;p&gt;
&lt;p&gt;Once, you have FreeRadius going, download, compile and install CoovaChilli.
CoovaChilli doesn&#x27;t have Debian or Ubuntu packages that work very well...and
building packages from the source doesn&#x27;t work perfectly either, so just
.&#x2F;configure, make and make install. Don&#x27;t worry, there&#x27;s a make deinstall in
case you want to remove it cleanly.&lt;&#x2F;p&gt;
&lt;p&gt;After building it, copy &#x2F;etc&#x2F;chilli&#x2F;defaults to &#x2F;etc&#x2F;chilli&#x2F;config and start
editing. Some things you&#x27;ll want to change:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;HS_DNS1 and HS_DNS2: the DNS servers given to your hosts&lt;&#x2F;li&gt;
&lt;li&gt;HS_RADSECRET: the secret required to talk to your Radius server&lt;&#x2F;li&gt;
&lt;li&gt;HS_UAMSECRET: the secret required to talk to your hotspot&lt;&#x2F;li&gt;
&lt;li&gt;HS_UAMSERVER: URL to the login page&lt;&#x2F;li&gt;
&lt;li&gt;HS_POSTAUTH_PROXY: we&#x27;ll talk about this later&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;You&#x27;ll also probably want to set your interfaces. Your WAN interface needs to
be set through your OS, but your LAN interface requires absolutely no
configuration through your OS - CoovaChilli will do it when it comes up.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s also important to run this:
sysctl net.ipv4.ip_forward=yes&lt;&#x2F;p&gt;
&lt;p&gt;That will enable IP forwarding on your system.&lt;&#x2F;p&gt;
&lt;p&gt;The other values can be left with their default values. We&#x27;re not going to set
up a custom login page because we really don&#x27;t care. The default is fine for
us. You&#x27;re going to need to install &lt;a href=&quot;https:&#x2F;&#x2F;worrbase.com&#x2F;blog&#x2F;hotel-internet&#x2F;haserl.sourceforge.net&quot;&gt;haserl&lt;&#x2F;a&gt; to use
it.&lt;&#x2F;p&gt;
&lt;p&gt;Well cool, we now have a captive portal! Run the init script, and bam. You now
have a captive portal.&lt;&#x2F;p&gt;
&lt;p&gt;Tomorrow, we&#x27;ll talk about going beyond basic configuration, and content
modification using Squid3 and GreasySpoon.&lt;&#x2F;p&gt;
</description>
            </item>
        
            <item>
                <title>Faking STDIN in Perl unit tests</title>
                <pubDate>Wed, 11 May 2011 00:00:00 +0000</pubDate>
                <link>https://worrbase.com/blog/stdin-testing/</link>
                <guid>https://worrbase.com/blog/stdin-testing/</guid>
                <description>&lt;p&gt;I had this question the other day when I was writing my Exherbo packager the
other day. I never found a good, conclusive answer through Google or
Identi.ca&#x2F;Twitter, so I tried something fairly obvious, and it worked!&lt;&#x2F;p&gt;
&lt;p&gt;When doing unit tests for an interactive program, oftentimes the need comes up
to fake STDIN, and provide some test interactions. In Perl, this is actually
rather trivial.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;a-note-on-filehandles-in-perl&quot;&gt;A note on filehandles in Perl&lt;&#x2F;h2&gt;
&lt;p&gt;In Perl, we often see this syntax for opening files:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#2b303b;&quot;&gt;
&lt;span style=&quot;color:#96b5b4;&quot;&gt;open&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;HANDLE&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;path&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;#39;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;print &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;while &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;close&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;HANDLE&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;);
&lt;&#x2F;span&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is bad style for a number of reasons (not checking to see if open was
successful, not using lexical filehandles, not using 3 param open()...), but
regardless, there is a thing or two worth noting here that&#x27;s relevant to the
rest of the discussion.&lt;&#x2F;p&gt;
&lt;p&gt;When you open a filehandle in this manner, you aren&#x27;t getting a scalar, an
array, or even a hash back. You&#x27;re getting a global typeglob. What the hell does
that even mean?&lt;&#x2F;p&gt;
&lt;p&gt;Perl has three separate symbol tables for storing variables, one for each type.
Typeglobs are a way to access all three, and are denoted by the asterisk sigil.
Hopefully that&#x27;ll clear up possible questions about the syntax below.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;another-note-about-perl-but-this-time-about-scope&quot;&gt;Another note about Perl, but this time about scope&lt;&#x2F;h2&gt;
&lt;p&gt;Most newcomers to Perl understand lexical scope and global scope, but get
confused about &#x27;local&#x27; or dynamic scope. &lt;&#x2F;p&gt;
&lt;p&gt;Dynamic scope is pretty hackish, but also very useful. Dynamic variables
(declared with the &#x27;local&#x27; keyword) are lexical, however their scope also
includes the bodies of any functions that get called within the lexical scope.&lt;&#x2F;p&gt;
&lt;p&gt;This simple example code should highlight what I mean.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#2b303b;&quot;&gt;
&lt;span style=&quot;color:#65737e;&quot;&gt;#!&#x2F;usr&#x2F;bin&#x2F;env perl

&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use strict&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use warnings&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;5.010&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;;

&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;our &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;foo &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;= &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;foo!&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;;

&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;sub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foofunc &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;{
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;say &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;;
}

&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;foofunc&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;();

{
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;local &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;foo &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;= &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;bar!&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;;
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;foofunc&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;();
}

&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;foofunc&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;();
&lt;&#x2F;span&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;foofunc is expecting global $foo, however localizing (giving it dynamic scope)
in that block allow us to change the value of the global the function sees.
Dynamic scope ends in the same place lexical scope would end.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;enough-build-up&quot;&gt;Enough build-up&lt;&#x2F;h2&gt;
&lt;p&gt;Now that you understand these two key concepts, it should be fairly easy to see
how we&#x27;re going to fake STDIN. Here&#x27;s the code:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#2b303b;&quot;&gt;
&lt;span style=&quot;color:#c0c5ce;&quot;&gt;{
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;open&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;FH&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;#39;, &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;t&#x2F;input.1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;#39;) or &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;die &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;!&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;;
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;local &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;STDIN&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;;
    *&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;STDIN &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;= *&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;FH&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;;
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;Exherbo&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;Packager&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;init_config&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;t&#x2F;config.yml&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;#39;);
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;close&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;FH&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;);
}
&lt;&#x2F;span&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here, we open a new filehandle (lexical filehandles &lt;em&gt;will not&lt;&#x2F;em&gt; work here), and
then give STDIN dynamic scope and set its value to our filehandle. It&#x27;s a simple
enough hack, but it works satisfactorily.&lt;&#x2F;p&gt;
&lt;p&gt;If this is the absolute wrong way to go about it, I&#x27;d love to know. This is just
what I came up with when I couldn&#x27;t find what I thought to be a reasonable
solution with Google.&lt;&#x2F;p&gt;
</description>
            </item>
        
            <item>
                <title>PSGI</title>
                <pubDate>Mon, 25 Apr 2011 00:00:00 +0000</pubDate>
                <link>https://worrbase.com/blog/psgi/</link>
                <guid>https://worrbase.com/blog/psgi/</guid>
                <description>&lt;p&gt;&lt;a href=&quot;http:&#x2F;&#x2F;perldancer.org&quot;&gt;Dancer&lt;&#x2F;a&gt; is the hottest new Perl PSGI-compatible web 
framework. You might be thinking, Perl web development? Doesn&#x27;t that use CGI?
Isn&#x27;t CGI balls slow? Well...you&#x27;re wrong. Most things you think you know about
Perl are probably wrong.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s start out with debunking the myth of CGI. CGI is slow, but there are a
number of Perl-compatible alternatives. &lt;&#x2F;p&gt;
&lt;p&gt;The most well-know, and best supported
alternative is FastCGI. Don&#x27;t hate on FastCGI because it has CGI in the name,
it avoids the big pitfall of CGI (loading a new interpreter every time a new 
page is called) by having a FastCGI server load your interpreter, and then
responding to requests sent to the FastCGI server from the web server.&lt;&#x2F;p&gt;
&lt;p&gt;This is gives us a clear performance improvement (not having to load a new
interpreter every time you load up a web page), as well as a security benefit
(total isolation from the web server user&#x2F;process).&lt;&#x2F;p&gt;
&lt;p&gt;The other well-known alternative to CGI is mod_perl. mod_perl is Apache,
specific, and it&#x27;s also pretty old and janky. I&#x27;m not going to talk about it,
mainly because I have never used it. It&#x27;s poorly documented, and there exist
better alternatives anyway. Let&#x27;s move on.&lt;&#x2F;p&gt;
&lt;p&gt;Ahh, PSGI. We love PSGI. PSGI is fast, and is under ridiculously rigorous
development. PSGI applications get a hashref that provides all of the necessary
information about the environment: request method, uri, variables, protocol
info, etc. It then returns an arrayref of a status code, HTTP headers and the
document body.&lt;&#x2F;p&gt;
&lt;p&gt;Most of the time, you&#x27;ll be using a framework, so you&#x27;ll never have to care
about interacting with the internals of PSGI directly. &lt;&#x2F;p&gt;
&lt;p&gt;Astute readers are probably thinking, &amp;quot;Hey, if PSGI is perl, then what does that
run on, and how does it interact with my web server?&amp;quot; Well, good reader, it runs
on any of the above-mentioned frameworks and more! There&#x27;s an Apache mod for it,
it works with CGI, FastCGI, and mod_perl, and you have have to deal with any of
that shit!&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;http:&#x2F;&#x2F;plackperl.org&#x2F;&quot;&gt;Plack&lt;&#x2F;a&gt; is the reference implementation of the PSGI
middleware. It sits between your webserver and Perl application serving up the
PSGI environment for you, while translating the arrayref you return into
meaningful data for the web server.&lt;&#x2F;p&gt;
&lt;p&gt;Hopefully, this clears up some confusion about Perl and web dev, along with PSGI
and its role in Perl web dev. This post also goes out to
&lt;a href=&quot;http:&#x2F;&#x2F;twitter.com&#x2F;seanmcgary&quot;&gt;@seanmcgary&lt;&#x2F;a&gt;, the ignorant shit who inspired
this post (and by ignorant shit I mean pretty cool guy who is very knowledgeable
about PHP and Javascript, but knows nothing of the Perl world).&lt;&#x2F;p&gt;
</description>
            </item>
        
            <item>
                <title>Virtual Filesystems in Perl</title>
                <pubDate>Fri, 15 Apr 2011 00:00:00 +0000</pubDate>
                <link>https://worrbase.com/blog/perl-virtual-filesystem/</link>
                <guid>https://worrbase.com/blog/perl-virtual-filesystem/</guid>
                <description>&lt;p&gt;So I mentioned in a previous post that I was writing a scoring engine
for CRTs, the hacking competition I&#x27;m holding for CSH. Well obviously I&#x27;m
writing it in Perl, because I know Perl best, and it seems like the perfect
sort of language for this task.&lt;&#x2F;p&gt;
&lt;p&gt;Actually, what drew me to writing the scoring engine in Perl is the sheer power
of &lt;a href=&quot;http:&#x2F;&#x2F;poe.perl.org&quot;&gt;POE&lt;&#x2F;a&gt;. But that&#x27;s totally a topic for another post.&lt;&#x2F;p&gt;
&lt;p&gt;When I started work on the scoring engine, for some reason I got the notion into
my head of making it cross platform. I don&#x27;t know why the hell I&#x27;d ever do that,
since all I tend to use are UNIX-based machines, but whatever, fuckit, that&#x27;s
what I decided to do.&lt;&#x2F;p&gt;
&lt;p&gt;The first (and so far only) real hurdle I hit when writing cross-platform code
is dealing with configuration file paths appropriately across different OSes.
However, I found an &lt;a href=&quot;http:&#x2F;&#x2F;www.willmcgugan.com&#x2F;blog&#x2F;tech&#x2F;2011&#x2F;3&#x2F;20&#x2F;creating-a-virtual-filesystem-with-python-and-why-you-need-one&#x2F;&quot;&gt;interesting
article&lt;&#x2F;a&gt; on reddit that solved this addressed this exact problem...in Python.&lt;&#x2F;p&gt;
&lt;p&gt;I figured there would be a Perl tool because why the hell not, and guess what? I
was so blessed to find
&lt;a href=&quot;http:&#x2F;&#x2F;search.cpan.org&#x2F;%7Ehanenkamp&#x2F;File-System-1.16&#x2F;lib&#x2F;File&#x2F;System.pm&quot;&gt;File::System&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;File::System is a fabulous perl module that allows programmers to abstract the
real filesystem away behind a virtual filesystem. You can arbitrarily set the
root to whatever directory you want, or with File::System::Layered, merge
bunches of directories into your root.&lt;&#x2F;p&gt;
&lt;p&gt;Thanks to this perl module, it&#x27;s trivial to set up OS-specific configuration
locations without dealing with tons of bullshit in your code. Let me share some
of my scoring engine code with you to show you how it&#x27;s done.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#2b303b;&quot;&gt;
&lt;span style=&quot;color:#b48ead;&quot;&gt;package &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;Scoring&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;Engine&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;Backend&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;;

&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use strict&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use warnings&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;5.012&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;;

&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;require &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;Exporter&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;our &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;@&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;ISA &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;qw&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Exporter&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&#x2F;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;our &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;@&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;EXPORT_OK &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;qw&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;fs&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&#x2F;;

&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;sub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;fs &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;{
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;state &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;fs&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;;

    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;($&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;Test&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;Scoring&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;Engine&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;::test&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;) {
        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;require &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;Scoring&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;Engine&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;Backend&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;Test&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;;

        $&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;fs &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;= $&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;Scoring&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;Engine&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;Backend&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;Test&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;::fs&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;;
        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;fs&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;;
    }

    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;given &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;($&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;^O&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;) {
        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;when &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;MSWin32&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;) {
            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;require &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;Scoring&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;Engine&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;Backend&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;Windows&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;;

            $&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;fs &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;= $&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;Scoring&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;Engine&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;Backend&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;Windows&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;::fs&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;;
        }

        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;when &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;linux&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;) {
            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;require &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;Scoring&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;Engine&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;Backend&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;Linux&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;;

            $&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;fs &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;= $&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;Scoring&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;Engine&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;Backend&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;Linux&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;::fs&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;;
        }

        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;when &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;darwin&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;) {
            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;require &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;Scoring&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;Engine&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;Backend&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;Mac&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;;

            $&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;fs &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;= $&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;Scoring&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;Engine&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;Backend&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;Mac&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;::fs&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;;
        }
    }

    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;fs&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;;
}
&lt;&#x2F;span&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This right here is the bulk of the code. This uses some modern Perl constructs,
so if any of this looks unfamiliar or even scary to you, I suggest you go pick
up chromatic&#x27;s excellent Modern Perl book. You have some catching up to do. :)&lt;&#x2F;p&gt;
&lt;p&gt;Moving right along here, it&#x27;s fairly obvious what this code does. We export a
simple function called fs, which pulls your OS from the $^O variable and
switches over it. Based on that, I load whatever OS specific module I need, and
that gives me a File::System::Object to work with.&lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s what the OS specific modules look like:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#2b303b;&quot;&gt;
&lt;span style=&quot;color:#b48ead;&quot;&gt;package &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;Scoring&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;Engine&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;Backend&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;Mac&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;;

&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use strict&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use warnings&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;5.012&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;;

&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;File&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;System&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;;

&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;our &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;fs &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;File&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;System&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Real&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;#39;,
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;root &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;=&amp;gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;$ENV{&amp;#39;HOME&amp;#39;}&#x2F;.scoringengine&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;;
&lt;&#x2F;span&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The first argument I pass into the File::System constructor denotes what type of
File::System::Object I get back. In this case, I want the simple
File::System::Real, since I only need to map one real directory to my virtual
filesystem root.&lt;&#x2F;p&gt;
&lt;p&gt;After doing that, use is simple:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#2b303b;&quot;&gt;
&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;Scoring&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;Engine&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;Backend &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;qw&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;fs&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&#x2F;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;YAML&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;Any &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;qw&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Load&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&#x2F;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use constant &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;DNS_CONFIG &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;= &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;&#x2F;dns.yml&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;#39;;

&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;my &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;fs &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;fs&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;my &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;fh &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;= $&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;fs&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;lookup&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;DNS_CONFIG&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;)-&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;open&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;local &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;my &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;teams &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;= Load(&amp;lt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;fh&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;close&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;($&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;fh&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;);
&lt;&#x2F;span&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Calling File::System::Obect::lookup finds me the actual file that I want, and
gives me a File::System::Object back that I can call the open function on. open
works just the way it normally does, giving me a plain old filehandle to
manipulate.&lt;&#x2F;p&gt;
&lt;p&gt;After that, everything is peaches.&lt;&#x2F;p&gt;
&lt;p&gt;Now, in all of my code that needs to access the filesystem, I have absolutely no
need to worry about translating paths or anything like that. It&#x27;s as easy as
getting my File::System::Object and accessing files with that.&lt;&#x2F;p&gt;
&lt;p&gt;Another benefit is unit testing. If you scroll back up to my first code post,
you&#x27;ll totally notice that there&#x27;s a check to see if a test module is loaded.&lt;&#x2F;p&gt;
&lt;p&gt;This is for ease of testing. In my unit test code (you are writing unit tests,
right?), I can easily just load that module before I load Scoring::Engine, and I
don&#x27;t have to do any other trickery to have my code look for my cooked test
configuration files in my unit test directory.&lt;&#x2F;p&gt;
&lt;p&gt;File::System is pretty hot, and I really hope people have embraced it as the
de-facto way to deal with filesystem access.&lt;&#x2F;p&gt;
</description>
            </item>
        
            <item>
                <title>New blog</title>
                <pubDate>Mon, 11 Apr 2011 00:00:00 +0000</pubDate>
                <link>https://worrbase.com/blog/new-blog/</link>
                <guid>https://worrbase.com/blog/new-blog/</guid>
                <description>&lt;p&gt;I&#x27;ve reworked my blog quite a bit. I transferred my some of my old
Wordpress posts to a new blogging engine -- jekyll.&lt;&#x2F;p&gt;
&lt;p&gt;Jekyll is pretty fantastic, in that it generates static sites from
posts done in markdown, and templates made with the Liquid templating
engine. It&#x27;s gaining popularity thanks to being the technology that runs
github pages.&lt;&#x2F;p&gt;
&lt;p&gt;I heard about it from &lt;a href=&quot;http:&#x2F;&#x2F;becomingaweso.me&#x2F;&quot;&gt;Ryan Clough&lt;&#x2F;a&gt; a few years
ago (before it was cool), and then my friend 
&lt;a href=&quot;http:&#x2F;&#x2F;russell.harmon.name&#x2F;&quot;&gt;Russel Harmon&lt;&#x2F;a&gt; encouraged me to start using
it for my own blog. Since I accidentally took down my wordpress site
sometime ago, I decided to give it a go. I also decided to roll out nginx
instead of Apache since my servers are too old to really handle Apache 
effectively.&lt;&#x2F;p&gt;
&lt;p&gt;So far, I definitely like it. I love writing my blog in vim (the best
text editor) and doing version control with git. I still need to set up 
git hooks to auto-publish when I commit.&lt;&#x2F;p&gt;
&lt;p&gt;I write all of the entries on my OpenBSD dev server, charmeleon, and then
push the generated HTML to my web server, so I don&#x27;t need to bother setting
up the jekyll tools on my web server or anything like that.&lt;&#x2F;p&gt;
&lt;p&gt;nginx is fast. It&#x27;s really fast, and it&#x27;s trivial to configure (for static
sites, anyway). I&#x27;m going to keep using it, and possibly try and use it
when I set up my personal Diaspora node.&lt;&#x2F;p&gt;
</description>
            </item>
        
            <item>
                <title>CRTS</title>
                <pubDate>Sat, 09 Apr 2011 00:00:00 +0000</pubDate>
                <link>https://worrbase.com/blog/crts/</link>
                <guid>https://worrbase.com/blog/crts/</guid>
                <description>&lt;p&gt;A week ago, I participated in a competition at RIT called ISTS, the Internet Security Talent Search. This competition challenges students
in the area to form teams to defend and maintain a small network, while attacking other teams&#x27; network. And lemme tell you, this was a fucking
blast. I did it last year, but now that I&#x27;m significantly more competent, I had so much more fun.&lt;&#x2F;p&gt;
&lt;p&gt;The competition works something like this: there are 14 teams that all have identical setups of mixed Windows, Linux and FreeBSD machines. Three 
of the five machines host network services that need to have maximum uptime, and the other two machines are clients that can be used for attacking.
Teams get points for every minute of uptime each service has, as well as for attacking machines of other teams.&lt;&#x2F;p&gt;
&lt;p&gt;During the competition, teams are given challenges to complete called business injects, which can range from adding services, to adding features
to existing services, to attacking other teams. It really runs the gamut.&lt;&#x2F;p&gt;
&lt;p&gt;However, while we&#x27;re busy doing our thing, the red team, made up of graduates, security consultants, etc. are indiscriminately attacking everyone.
Since every team has identical machines with identical configurations, we all know the security vulns that other teams have as soon as we discover
them ourselves, so really the red team is kind of at a disadvantage.&lt;&#x2F;p&gt;
&lt;p&gt;For the CSH team (Team OPCOMM), I was mail bitch (because apparently no one wants to deal with postfix), and FreeBSD wizard. I maintained the 
postfix and dovecot installation on a teammates machine, while also maintaining FTP and DNS on my own. Unsurprisingly, my box was the only one
box on the team that didn&#x27;t get pwned during the competition. And I&#x27;m not saying that it&#x27;s unsurprising because I&#x27;m pompous or anything, I&#x27;m saying
it because I was maintaining the FreeBSD box. I mean really, next to all that Windows and Linux-y shit, FreeBSD is a fucking tank.&lt;&#x2F;p&gt;
&lt;p&gt;Now, since I&#x27;m talking about ISTS, you&#x27;re probably wondering why this post is titled CRTS. Well, through talking to people on CSH after the competition,
I found that many people were interested in the idea of the competition, but they didn&#x27;t think they had enough skill to compete.&lt;&#x2F;p&gt;
&lt;p&gt;So I decided to hold an event just like ISTS for CSH.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m calling it the Computer Science House Root Type Person Talent Search, or CSH RTP Talent Search, or CRTS. It&#x27;s definitely focused at people who
have little to no systems administration experience, but still challenging enough such that people who know what they&#x27;re doingwill still have fun.&lt;&#x2F;p&gt;
&lt;p&gt;Prior, there will be a fuckton of seminars given about topics people will need to be familiar with, starting with basic UNIX skills ranging all
the way up to intermediate hacking techniques.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s going to be a great weekend, and I&#x27;ve already gotten a lot of interest from people on CSH. I&#x27;ve planned some fun vulns for teams to discover, and
I&#x27;m writing a bitchin&#x27; Perl scoring engine using POE and Dancer. All of the code is on github, and I&#x27;ll make sure to list the different setups in detail
after the competition.&lt;&#x2F;p&gt;
</description>
            </item>
        
            <item>
                <title>Formspring API Issues</title>
                <pubDate>Tue, 06 Jul 2010 00:00:00 +0000</pubDate>
                <link>https://worrbase.com/blog/formspring-api-issues/</link>
                <guid>https://worrbase.com/blog/formspring-api-issues/</guid>
                <description>&lt;p&gt;I&#x27;ve been working on my Perl library for Formspring.me, and I&#x27;ve run into a pretty egregious issue. Apparently they aren&#x27;t following the OAuth spec correctly, and aren&#x27;t returning  a oauth_callback_confirmed parameter. The problem for me lies in that the wonderful Perl OAuth library, Net::OAuth requires that the OAuth response return this parameter, and errors if it&#x27;s not present. I&#x27;ve emailed api@formspring.me about it, but they have yet to answer my email.&lt;&#x2F;p&gt;
&lt;p&gt;[1] http:&#x2F;&#x2F;tools.ietf.org&#x2F;html&#x2F;rfc5849#section-2.1&lt;&#x2F;p&gt;
</description>
            </item>
        
            <item>
                <title>Formspring.me API beta</title>
                <pubDate>Thu, 03 Jun 2010 00:00:00 +0000</pubDate>
                <link>https://worrbase.com/blog/formspring-me-api-beta/</link>
                <guid>https://worrbase.com/blog/formspring-me-api-beta/</guid>
                <description>&lt;p&gt;formspring.me released a beta version of their API today. For those of you who don&#x27;t know, formspring.me is the popular social networking site that allows people to ask and answer anonymous questions. It uses Facebook Connect for user auth, as well as letting users sign up on the site if they don&#x27;t have a Facebook account.&lt;&#x2F;p&gt;
&lt;p&gt;Apparently, as a joke some time ago, I signed up for the beta API. So I decided to develop a Perl module allowing easy use of the Formspring.me API. You can follow the development of it on my &lt;a href=&quot;http:&#x2F;&#x2F;github.com&#x2F;worr&#x2F;WWW--Formspring&quot;&gt;github&lt;&#x2F;a&gt;. I plan to release this code to CPAN when I&#x27;m done so that other people can use it.&lt;&#x2F;p&gt;
&lt;p&gt;Since I&#x27;m new to the CPAN world, if one of you astute readers notices something blatantly wrong about my code, I&#x27;d appreciate it if you&#x27;d point it out.&lt;&#x2F;p&gt;
</description>
            </item>
        
            <item>
                <title>My first COBOL program on z&#x2F;OS</title>
                <pubDate>Sun, 25 Apr 2010 00:00:00 +0000</pubDate>
                <link>https://worrbase.com/blog/my-first-cobol-program-on-zos/</link>
                <guid>https://worrbase.com/blog/my-first-cobol-program-on-zos/</guid>
                <description>&lt;p&gt;Today, I got Hello World working in COBOL on an IBM Z9. This is actually surprisingly more difficult than it would seem. But I&#x27;m gonna document it here so I remember how to do it, and also in case some random z&#x2F;OS n00b stumbles upon this entry.&lt;&#x2F;p&gt;
&lt;p&gt;Here is the Hello World file I wrote:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#2b303b;&quot;&gt;
&lt;span style=&quot;color:#c0c5ce;&quot;&gt;IDENTIFICATION DIVISION.
PROGRAM-ID. HELLO.
PROCEDURE DIVISION.
    DISPLAY &amp;#39;Hello, World&amp;#39;.
    STOP RUN.
&lt;&#x2F;span&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Seems pretty easy, right? Well, yeah, no shit. It&#x27;s Hello World. I grabbed it from a Wikipedia article. It&#x27;s not exactly innovative genius. However, compiling it and linking it is a different story.&lt;&#x2F;p&gt;
&lt;p&gt;I tried at first using the ISPF foreground COBOL compiler. However, this was very non-obvious, and the documentation was lacking. All the documentation I found consisted mostly of how to do it through TSO, where it made mention that an ISPF interface did exist.&lt;&#x2F;p&gt;
&lt;p&gt;So then I went the JCL route.&lt;&#x2F;p&gt;
&lt;p&gt;IBM has some great documentation on how to do this. However, it is definitely not in the 900+ page Enterprise COBOL for z&#x2F;OS Programming Guide. That was really just confusing. &lt;a href=&quot;http:&#x2F;&#x2F;publib.boulder.ibm.com&#x2F;infocenter&#x2F;zos&#x2F;basics&#x2F;index.jsp?topic=&#x2F;com.ibm.zos.zappldev&#x2F;toc.htm&quot;&gt;Here is the great documentation.&lt;&#x2F;a&gt; This is what got me off the ground.&lt;&#x2F;p&gt;
&lt;p&gt;My JCL ended up looking like this:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#2b303b;&quot;&gt;
&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&#x2F;&#x2F;CLGP JOB
&#x2F;&#x2F;CLG EXEC IGYWCLG
&#x2F;&#x2F;COBOL.SYSIN DD DSN=HLQ.EXPERIME.COBOL(HELLO),DISP=SHR
&lt;&#x2F;span&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It&#x27;s really pretty simple. The first line just declares the name of the job (CLGP), the next line executes the terribly named COBOL compile, link-editor, and run JCL procedure. IBM wrote it so you don&#x27;t have to. The last line just loads the dataset member that contains all of the COBOL code.&lt;&#x2F;p&gt;
&lt;p&gt;See? Mainframes and COBOL are THAT easy!&lt;&#x2F;p&gt;
</description>
            </item>
        
            <item>
                <title>LTSP</title>
                <pubDate>Thu, 22 Apr 2010 00:00:00 +0000</pubDate>
                <link>https://worrbase.com/blog/ltsp/</link>
                <guid>https://worrbase.com/blog/ltsp/</guid>
                <description>&lt;p&gt;I finally finished rolling out the new changes to CSH&#x27;s usercenter. I decided to move away from Fully Automatic Installation and move towards the thin client solution provided by &lt;a href=&quot;http:&#x2F;&#x2F;ltsp.org&quot;&gt;LTSP&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;FAI was really painful to test, as well as significantly more painful to manage. LTSP allows us to only update one machine, and install upgrades without having to reboot the machines to receive the softupdates (the FAI way).&lt;&#x2F;p&gt;
&lt;p&gt;One machine, in this case a virtual machine on CSH&#x27;s Xen cluster, runs all of the software for the clients. The terminal client connects to the terminal server&#x27;s login prompt until the user logs in. Then the client automatically ssh&#x27;s (with X forwarding of course) to the server and subsequently runs all of their software off of that.&lt;&#x2F;p&gt;
&lt;p&gt;It is bandwidth heavy (on that segment of our network anyway), but it works very well. The clients are just as fast with the X forwarding as they would be with a locally installed OS (these machines are ultra slow).&lt;&#x2F;p&gt;
&lt;p&gt;Really, there isn&#x27;t much to say other than FAI is terrible. Related: I plan on setting up &lt;a href=&quot;http:&#x2F;&#x2F;www.puppetlabs.com&#x2F;&quot;&gt;puppet&lt;&#x2F;a&gt; at some point for myself.&lt;&#x2F;p&gt;
</description>
            </item>
        
            <item>
                <title>COBOL</title>
                <pubDate>Sat, 13 Mar 2010 00:00:00 +0000</pubDate>
                <link>https://worrbase.com/blog/cobol/</link>
                <guid>https://worrbase.com/blog/cobol/</guid>
                <description>&lt;p&gt;So I haven&#x27;t really posted in the last month, mainly because I haven&#x27;t done anything interesting. I&#x27;ve been writing some Perl code using Catalyst and Mason. But that&#x27;s not terribly exciting.&lt;&#x2F;p&gt;
&lt;p&gt;I am however, taking a Mainframes course at RIT this quarter. It promises to be relatively exciting. In it, we get to learn the intricacies of z&#x2F;OS, and how to manage one of those beasts. That&#x27;ll be fun. Surprisingly, there&#x27;s a programming project towards the end of it (it&#x27;s surprising because it&#x27;s a Networking and Sysadmin course, we don&#x27;t program much). And since I&#x27;m learning how to administer and use mainframes, I thought to myself, &amp;quot;Hell, let&#x27;s do this project in COBOL.&amp;quot; So here I sit, trying to find a decent COBOL tutorial on the internet.&lt;&#x2F;p&gt;
&lt;p&gt;If anyone finds one, please send it to me. It&#x27;d be nice.&lt;&#x2F;p&gt;
</description>
            </item>
        
            <item>
                <title>Google App Engine, Twitter4J and OAuth</title>
                <pubDate>Sat, 13 Mar 2010 00:00:00 +0000</pubDate>
                <link>https://worrbase.com/blog/google-app-engine-twitter4j-and-oauth/</link>
                <guid>https://worrbase.com/blog/google-app-engine-twitter4j-and-oauth/</guid>
                <description>&lt;p&gt;So I&#x27;m writing a Twitter app in Java on Google App Engine right now with my friend, Dave Bright. We&#x27;re using Google Web Toolkit for our frontend, and App Engine for hosting and database and such. &lt;a href=&quot;http:&#x2F;&#x2F;twitter4j.org&quot;&gt;Twitter4J&lt;&#x2F;a&gt; is our Twitter library of choice.&lt;&#x2F;p&gt;
&lt;p&gt;Since we ran into a spot of trouble using OAuth with the Twitter4J library, I decided to give a bit of a brief tutorial on how to get it working on App Engine. There is actually very different than the code in my as I do some more error checking, and need to do some other stuff with my datastore.&lt;&#x2F;p&gt;
&lt;h2&gt;Twitter4J OAuth Overview&lt;&#x2F;h2&gt;
&lt;ol&gt;
	&lt;li&gt;Set the consumer key and secret for your twitter object with setOAuthConsumer(key, secret)&lt;&#x2F;li&gt;
	&lt;li&gt;Get a request token with getRequestToken(callback_uri)&lt;&#x2F;li&gt;
	&lt;li&gt;Persist the request token somewhere, we&#x27;ll need the original later when we need to get the access token.&lt;&#x2F;li&gt;
	&lt;li&gt;Redirect the user to the URL returned by getAuthorizationURL()&lt;&#x2F;li&gt;
	&lt;li&gt;Get the persisted request token, setOAuthConsumer again.&lt;&#x2F;li&gt;
	&lt;li&gt;Call getOAuthAccessToken(request_token, oauth_verifier) to get an access token&lt;&#x2F;li&gt;
	&lt;li&gt;Persist that token with the user data, you&#x27;ll need this everytime you want to authenticate.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h2&gt;Some incomplete example code&lt;&#x2F;h2&gt;
Please note, this is not code I actually have in production anywhere. It&#x27;s original code just for the blog.
&lt;pre style=&quot;background-color:#2b303b;&quot;&gt;
&lt;span style=&quot;color:#b48ead;&quot;&gt;public &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;String &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;authenticate&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;() {
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;TwitterFactory&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; tf = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;new &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;TwitterFactory&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;();
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;Twitter&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; twitter = tf.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;getInstance&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;();

    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; This is actually really important, as Twitter WILL NOT send you back the oauth_verifier if
    &#x2F;&#x2F; you don&amp;#39;t provide the callback URI, even if you provide a callback on their site
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    twitter.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;setOAuthConsumer&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;CONSUMER_KEY&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;CONSUMER_SECRET&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;);
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;RequestToken&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; rtoken = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;new &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;RequestToken&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;CALLBACK_URI&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;);

    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; This is a special class that just relates the token to the RequestToken object in the app engine
    &#x2F;&#x2F; datastore. The token string itself is the key.
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;OAuthTemp&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; temp = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;new &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;OAuthTemp&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(rtoken.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;getToken&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(), rtoken);

    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Our persistence manager is named pm
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    pm.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;makePersistent&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(temp);

    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; rtoken.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;getAuthorizationURL&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;();
}
&lt;&#x2F;span&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The second bit of the code gets called when the user is returned to the page. You need to get the oauth_token and the oauth_verifier GET variables and pass them to this function.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#2b303b;&quot;&gt;
&lt;span style=&quot;color:#b48ead;&quot;&gt;public&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; void &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;authenticatePartII&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;String&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; oauth_token, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;String&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; oauth_verifier) {
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;TwitterFactory&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; tf = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;new &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;TwitterFactory&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;();
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;Twitter&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; twitter = tf.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;getInstance&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;();

    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Get the temp object out of the datastore, and get the old RequestToken
    &#x2F;&#x2F; Yes, it MUST be the old RequestToken. Or at least, have all the same parameters
    &#x2F;&#x2F; as the old RequestToken.
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;Key&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; k = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;KeyFactory&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;createKey&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;OAuthTemp&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;class&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;getSimpleName&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(), oauth_token);
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;OAuthTemp&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; temp = pm.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;getObjectById&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;OAuthTemp&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;class&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, k);
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;RequestToken&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; rtoken = temp.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;getrtoken&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;();

    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; You MUST provide the original RequestToken and the oauth_verifier passed to you by Twitter
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    twitter.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;setOAuthConsumer&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;CONSUMER_KEY&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;CONSUMER_SECRET&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;);
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;AccessToken&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; ac  = twitter.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;getOAuthAccessToken&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(rtoken, oauth_verifier);

    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; You really don&amp;#39;t need the RequestToken information after you got your AccessToken, so
    &#x2F;&#x2F; delete it.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    twitter.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;setOAuthAccessToken&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(ac);
    pm.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;deletePersistent&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(temp);

    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; However you store user data, you ought to associate the AcessToken object you
    &#x2F;&#x2F; just got with your twitter user, and pop it in the datastore. I&amp;#39;ll leave that bit up to you.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That&#x27;s all there really is to it. The Twitter4J library isn&#x27;t the best documented library, and just looking at the Javadocs and the Desktop-centric code examples isn&#x27;t really that helpful. I hope this clears up some confusion on how to get Twitter4J working with OAuth.&lt;&#x2F;p&gt;
</description>
            </item>
        
            <item>
                <title>My major is too easy...</title>
                <pubDate>Mon, 18 Jan 2010 00:00:00 +0000</pubDate>
                <link>https://worrbase.com/blog/my-major-is-too-easy/</link>
                <guid>https://worrbase.com/blog/my-major-is-too-easy/</guid>
                <description>&lt;p&gt;This weekend, I had absolutely nothing to do. I didn&#x27;t have any homework, studying, projects or the like because my major is far too easy. So I got bored and wrote a complete &lt;a href=&quot;http:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Brainfuck&quot;&gt;Brainfuck&lt;&#x2F;a&gt; interpreter in Perl.&lt;&#x2F;p&gt;
&lt;p&gt;The interpreter was the easiest; it took me a morning to get that working albeit without support for nested parens. After that, I decided to write a text to Brainfuck converter, which (not surprisingly) turns text into executable Brainfuck code. Maybe if I get bored again, I could write a module to output the equivalent Perl or C code given some Brainfuck code.&lt;&#x2F;p&gt;
&lt;p&gt;This was my first real project using object oriented Perl. In all honesty, I like that Perl&#x27;s object system allows for many different types of objects (objects can be scalars, arrays, or hashes) and how flexible that is. Unfortunately, I didn&#x27;t get to exploit that flexibility in my code. It&#x27;s still cool though.&lt;&#x2F;p&gt;
&lt;p&gt;What I wrote is 2 Perl modules that make up the linked list that store data generated by Brainfuck code, a Perl module that interprets and runs the code, and a Perl module that translates text to executable Brainfuck code. I know I could have used a pre-built linked list, but I thought it was more fun to write my own.&lt;&#x2F;p&gt;
&lt;p&gt;The biggest challenge was definitely writing the translation code. I could&#x27;ve done it the easy way, and just output x amount of pluses for the character code of each letter, but I decided that was the lamest way to write Brainfuck. Instead, I looped through each character in the phrase, and added some nodes in my Brainfuck code that corresponded to the tens place of each character code. Then, when outputting a character, my Brainfuck code would change the data pointer to the node that was set to the tens place of the character code of the desired character, and increment or decrement it to the proper value.&lt;&#x2F;p&gt;
&lt;p&gt;A more ideal way to do it (to generate cleaner Brainfuck, at least) is to set each of those prep nodes to the nearest multiple of 20 for each character code, and then use whichever node is closest to the desired value. Maybe if I feel like doing more with this, then I&#x27;ll add that feature (probably not).&lt;&#x2F;p&gt;
&lt;p&gt;In addition to writing all this, I also made a &lt;a href=&quot;http:&#x2F;&#x2F;github.com&#x2F;worr&quot;&gt;GitHub&lt;&#x2F;a&gt; account. My GitHub has all the above code, so you can clone the repo if you want to see what the code looks like (it&#x27;s actually really easy to read Perl).&lt;&#x2F;p&gt;
&lt;p&gt;This whole idea came from an idea on CSH. A guy here decided to publish a &amp;quot;Hello World of the Week&amp;quot; article in our newsletter, and to combat him I wrote a Brainfuck version of Hello World. This contest grew, and other people joined (albeit humorously) with such contributions as a boot loader that printed out Hello World, Hello World in White Space, and Hello World in Microsoft Word. My contribution (also in my git repo) generated valid Brainfuck code for the phrase Hello World, and then ran it through my interpreter (aka Hello World in 425ish lines).&lt;&#x2F;p&gt;
</description>
            </item>
        
            <item>
                <title>omirssi: An Omegle irssi plugin</title>
                <pubDate>Fri, 25 Dec 2009 00:00:00 +0000</pubDate>
                <link>https://worrbase.com/blog/omirssi-an-omegle-irssi-plugin/</link>
                <guid>https://worrbase.com/blog/omirssi-an-omegle-irssi-plugin/</guid>
                <description>&lt;p&gt;Sometimes I really hate going home. I&#x27;m on Christmas break, and I&#x27;ve spent the majority of my time just watching movies in my basement. I got really bored, so yesterday morning while I was watching &amp;quot;Juno&amp;quot; (love that movie), I wrote an &lt;a href=&quot;http:&#x2F;&#x2F;omegle.com&quot; target=&quot;_self&quot;&gt;Omegle&lt;&#x2F;a&gt; script for irssi. I just made up a &lt;a href=&quot;http:&#x2F;&#x2F;code.google.com&#x2F;p&#x2F;omirssi&quot; target=&quot;_self&quot;&gt;google code&lt;&#x2F;a&gt; page for download, so have at it irssi users. Maybe I&#x27;ll get around to adding it to the big list of irssi scripts sometime soon.&lt;&#x2F;p&gt;
</description>
            </item>
        
            <item>
                <title>Perl, Apache2::Request, and uploading files</title>
                <pubDate>Mon, 07 Dec 2009 00:00:00 +0000</pubDate>
                <link>https://worrbase.com/blog/perl-apache2request-and-uploading-files/</link>
                <guid>https://worrbase.com/blog/perl-apache2request-and-uploading-files/</guid>
                <description>&lt;p&gt;So I started writing a netboot server for floor. I decided to start writing the web interface first, and learn myself some mason, web perl, and database-y things. Also found some things out about the process that were a little undocumented&#x2F;misdocumented (now a word).&lt;&#x2F;p&gt;
&lt;p&gt;The biggest issue (so far) was file uploads. So here&#x27;s a quick tutorial on how to do file uploads with perl, with mason.&lt;&#x2F;p&gt;
&lt;p&gt;In index.html (or wherever your form HTML code lives):&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#2b303b;&quot;&gt;
&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;form &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;method&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;=&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;post&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;action&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;=&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;upload.mas&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;enctype&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;=&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;multipart&#x2F;form-data&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;&amp;gt;
  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;input &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;type&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;=&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;file&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;=&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;file_name&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot; &#x2F;&amp;gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;br&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; &#x2F;&amp;gt;
  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;input &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;type&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;=&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;submit&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;=&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Submit&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot; &#x2F;&amp;gt;
&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;form&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In upload.mas:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#2b303b;&quot;&gt;
&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;lt;%&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;init&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;gt;
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;Apache2&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;Upload&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;;

    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;# $r is an Apache2::RequestRec, not an Apache2::Request like some places say it is
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;my &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;req &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;Apache2&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;Request&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;($&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;);

    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;# file_name refers to the form name you had in your HTML
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;my &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;upload &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;= $&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;req&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;upload&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;file_name&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;#39;);

    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;my &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;fh &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;= $&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;upload&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;fh&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;;
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;open &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;OUTFILE&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;&amp;gt;$where_ever_you_wanna_save_the)file&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;;

    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;binmode &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;fh&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;;
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;binmode &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;OUTFILE&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;;

    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;print &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;OUTFILE &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;line &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;foreach my &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;line &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;lt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;fh&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;gt;);
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;close &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;OUTFILE&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;;
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;close &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;fh&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;;
&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;%init&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In your httpd.conf:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#2b303b;&quot;&gt;
&lt;span style=&quot;color:#c0c5ce;&quot;&gt;APREQ2_READLIMIT 2G # Sets the max size of your user&amp;#39;s uploads to 2GB
&lt;&#x2F;span&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I intentionally skipped over error handling code and all of the httpd.conf config for the sake of brevity (I did say brief tutorial). Since I need to allow for larger file sizes than Apache does by default (64MB), I spent quite some time looking for that Apache directive.&lt;&#x2F;p&gt;
&lt;p&gt;Hopefully this saves someone some time.&lt;&#x2F;p&gt;
</description>
            </item>
        
            <item>
                <title>OpenBSD pf vs Linux iptables: A Comparison</title>
                <pubDate>Sat, 14 Nov 2009 00:00:00 +0000</pubDate>
                <link>https://worrbase.com/blog/openbsd-pf-vs-linux-iptables-a-comparison/</link>
                <guid>https://worrbase.com/blog/openbsd-pf-vs-linux-iptables-a-comparison/</guid>
                <description>&lt;p&gt;This weekend, I decided it would be a good idea to turn my Linux router&#x2F;firewall into an OpenBSD router&#x2F;firewall. &lt;a href=&quot;http:&#x2F;&#x2F;www.csh.rit.edu&#x2F;~devnull&#x2F;blog&#x2F;&quot;&gt;Clockfort&lt;&#x2F;a&gt; recommended it, so I decided to grab backups of my iptables rules, install OpenBSD, and learn pf.&lt;&#x2F;p&gt;
&lt;p&gt;I learned iptables about a year ago, when I first built this router&#x2F;firewall. It acts like those little home gateways that you get; it does NAT, DHCP, DNS, etc. I&#x27;ve also used iptables to firewall my desktop and laptop (though those rule sets were significantly simpler than the firewall).&lt;&#x2F;p&gt;
&lt;h3&gt;Configuration&lt;&#x2F;h3&gt;
The firstÂ notableÂ difference between pf and iptables: pf has a config file! It also has variables, lists and tables that you can manually populate which ease configuration. You can even include other config files in case you need to split your config for whatever reason. When you&#x27;re done modifying the config file, just call pfctl -f &#x2F;etc&#x2F;pf.conf and it&#x27;ll load that rule set and start filtering.
&lt;p&gt;iptables doesn&#x27;t have any of that. iptables are primarily populated through the iptables command. You can use iptables-save and iptables-restore to save and load iptables rules from a file. The file is basically a bunch of iptables commands with the iptables bit omitted. Another alternative is to write a bash script that loads your iptables rules one by one. That option gives you the benefit of using variables so that it&#x27;s trivial to change IPs or similar.&lt;&#x2F;p&gt;
&lt;p&gt;I used iptables-save and restore to configure my iptables rules, and just wrote rules to that file in a similar syntax when I wanted to reconfigure parts of my firewall.&lt;&#x2F;p&gt;
&lt;h3&gt;Rule Processing&lt;&#x2F;h3&gt;
The next most obvious way they differ is how they process rules. iptables has various tables, each with different chains that packets traverse, whereas pf just processes packets straight down the config file.
&lt;p&gt;With pf, packets traverse the flat pf.conf file. Even if a packet matches a rule, it continues to process the packet all the way down the configuration file. Only if a rule contains the &amp;quot;quick&amp;quot; option does pf stop processing and take action before hitting the end of the rule set. If a packet makes it all the way to the end of the config file, the last action specified from a rule that matched that packet is taken.&lt;&#x2F;p&gt;
&lt;p&gt;With iptables, packets are processed by various chains in different order, depending on the source and destination in the packet. For example, normal outgoing packets are processed by the OUPUT chain on the filter table. Various rules within that chain may cause processing to hop over to a different set of rules on a user-defined chain, or might take action on a packet. When a packet matches a rule description, processing on that chain stops immediately, and the action is taken.&lt;&#x2F;p&gt;
&lt;h3&gt;Dynamic Modification&lt;&#x2F;h3&gt;
pf really just owns iptables here. To dynamically update your rules with iptables, you just write new rules on the fly. If you want to do a bunch, you would write a bash script to delete some rules, and write new ones.
&lt;p&gt;pf, you can change tables, variables, lists and anchors on the fly. Anchors are a really cool feature of pf. They are basically sub-rulesets that have names. So if you define an anchor somewhere in your ruleset, you can call pfctl and totally redefine the rules within that anchor. You can even write anchors to files, and load them from different files.&lt;&#x2F;p&gt;
&lt;h3&gt;Packet Filtering&lt;&#x2F;h3&gt;
pf is pretty simple concerning what it can filter for. It can filter based on protocol, TCP flags, source IP, destination IP, interface, and port. There is also some slightly more advanced filtering, like antispoof, unicast reversing, and passive operating system finger printing. For the majority of situations, this kind of firewall control is fine.
&lt;p&gt;iptables can do all of the same stuff. However with iptables, you can load all sorts of modules that do far more intensive filtering than pf. You can filter based on state (no, you can&#x27;tÂ filterÂ based on state in pf), where they are (geoip), time, statistics, ToS, and much more. There are so many target extensions for iptables, it is ridiculous. And if that isn&#x27;t enough, you can pass the packet into userspace and write a script to filter it further there.&lt;&#x2F;p&gt;
&lt;h3&gt;Performance&lt;&#x2F;h3&gt;
pf is fast. I said before that you can&#x27;t filter packets in pf based on state. That doesn&#x27;t mean that pf isn&#x27;t a stateful firewall. It definitely recognizes state, as it passes packets that are part of an established connection without even processing them with pf. This means the majority of your packets skip your firewall rules entirely. This isn&#x27;t nearly as insecure as it sounds, since most iptables rulesets pass packets that are part of an established state anyway. It definitely has the distinct advantage of making it faster though.
&lt;p&gt;With iptables, all of your packets pass through all of your rules. This can really slow things down, especially if you have complicated rulesets. If you use all sorts of crazy iptables modules, that will slow it down pretty heavily too. And if you pass the packet into userspace for further processing, it will slow it down even more.&lt;&#x2F;p&gt;
&lt;h3&gt;Conclusion&lt;&#x2F;h3&gt;
pf and iptables are both great firewalling solutions, but cater to people of different needs. pf is ridiculously fast, but lacks some of the more avanced features of iptables. Since my router&#x2F;firewall box doesn&#x27;t really need those advanced iptables features, and since it needs to be fast, I&#x27;m gonna stick with pf for now.
</description>
            </item>
        
            <item>
                <title>Google Wave</title>
                <pubDate>Mon, 26 Oct 2009 00:00:00 +0000</pubDate>
                <link>https://worrbase.com/blog/google-wave/</link>
                <guid>https://worrbase.com/blog/google-wave/</guid>
                <description>&lt;p&gt;Yeah, that&#x27;s right. Just got an account. Well, by just, I mean I got one on Friday. Don&#x27;t even ask for invites, because they were gone by Saturday morning. Also, if you don&#x27;t know what Wave is, you should really go to &lt;a href=&quot;http:&#x2F;&#x2F;wave.google.com&quot;&gt;this&lt;&#x2F;a&gt; site and watch the video. I know it&#x27;s long, but it&#x27;s well worth it.&lt;&#x2F;p&gt;
&lt;p&gt;So Google Wave is pretty awesome. It&#x27;s ridiculously buggy, but it works well enough if you aren&#x27;t using it in a production environment. I have yet to try out any of the multimedia stuff beyond embedding YouTube videos in Wave, but I imagine it works just as well as everything else does. I&#x27;ll probably talk more about that when I&#x27;ve played with it.&lt;&#x2F;p&gt;
&lt;p&gt;What I&#x27;ve really been playing with is the Wave API, in Python of course. The jist of what I&#x27;ve been reading is that the Java API isn&#x27;t as up to par as the Python API. Also, I hate Java, and I hate writing code in Java.&lt;&#x2F;p&gt;
&lt;p&gt;The Wave API is built off of &lt;a href=&quot;http:&#x2F;&#x2F;appspot.com&quot;&gt;Google App Engine&lt;&#x2F;a&gt;, and has all the same limitations as App Engine. My roommate and I kinda half started working on an NNTP gateway to Wave. Unfortunately, the limitations App Engine sets makes this a little more difficult than we&#x27;d like (no sockets or anything of the sort).&lt;&#x2F;p&gt;
&lt;p&gt;The one thing I&#x27;ve come across in the API that I don&#x27;t like, is that you &lt;em&gt;must&lt;&#x2F;em&gt; include the entire Python Wave module in the app directory that you upload to App Engine. Not a huge issue, but definitely a bit of an annoyance. The only real problems I see are the possibility for people to modify the version of the Wave API they upload, and that the version of the Wave API they upload is outdated.&lt;&#x2F;p&gt;
&lt;p&gt;Another issue with using App Engine as the platform for all of the Wave code and such, is that you &lt;em&gt;must&lt;&#x2F;em&gt; use Python 2.5. App Engine doesn&#x27;t work with anything higher than that. So even though the Wave development site says you can use Python 2.5 or above, the above part is really a lie.&lt;&#x2F;p&gt;
&lt;p&gt;The good news: Google Wave won&#x27;t forever be reliant on App Engine. Sometime in the future, they will be allowing Apps from anywhere. This is will be awesome, and I can&#x27;t wait.&lt;&#x2F;p&gt;
&lt;p&gt;Oh, and I had other productive things I was gonna do this weekend, but they all got shot to hell when I got my Wave account.&lt;&#x2F;p&gt;
&lt;p&gt;Now you can wave me at ay1244@googlewave.com&lt;&#x2F;p&gt;
</description>
            </item>
        
            <item>
                <title>Project Work Weekend Part II</title>
                <pubDate>Mon, 19 Oct 2009 00:00:00 +0000</pubDate>
                <link>https://worrbase.com/blog/project-work-weekend-part-ii/</link>
                <guid>https://worrbase.com/blog/project-work-weekend-part-ii/</guid>
                <description>&lt;p&gt;Yesterday ended up being extraordinarily productive for me. I learned GTK+ in perl, and wrote the GUI for my Omegle app. It&#x27;s looking decent, although there is this annoying issue with the menu bar that&#x27;s bothering me a bit. It&#x27;s very simple, but I can&#x27;t really think of any other features to put in the GUI.&lt;&#x2F;p&gt;
&lt;p&gt;I also got a bunch of the abstraction for my CS project done today. But that wasn&#x27;t that much code. Oh well.&lt;&#x2F;p&gt;
&lt;p&gt;Also, in the middle of this post, got roped into helping fix our Xen management interface. And by help, I meant I installed Ubuntu server (ugh) on a machine and installed openssh. Woo.&lt;&#x2F;p&gt;
</description>
            </item>
        
            <item>
                <title>Project Work Weekend Part I</title>
                <pubDate>Sat, 17 Oct 2009 00:00:00 +0000</pubDate>
                <link>https://worrbase.com/blog/project-work-weekend-part-i/</link>
                <guid>https://worrbase.com/blog/project-work-weekend-part-i/</guid>
                <description>&lt;p&gt;So CSH is holding its first &amp;quot;Project Work Weekend&amp;quot; of the year, and so far, it&#x27;s kinda been productive. Personally, I got a lot of work done. I&#x27;ve been kinda productive. I worked a little bit on my Omegle application that I&#x27;ve been playing with in my head, and I definitely got some of my CS project done.&lt;&#x2F;p&gt;
&lt;p&gt;For my CS project, me and a partner have to write a game playing framework, and then a bunch of pluggable games for the framework. It&#x27;s a lot easier than it sounds, as they&#x27;re all little command line games like take away, kayles, or connect 3. It&#x27;s still pretty cool though. It&#x27;s weird to be working with objects again after mostly programming in C this summer. But yeah, so the project is coming along. It&#x27;s nice, because right now I only really have to write the abstract framework while my partner writes the game parts that inherit from my framework. Also I have to fix the old game. But whatever, that should be easy.&lt;&#x2F;p&gt;
&lt;p&gt;My Omegle app is coming along slowly. Trying to figure out perl GTK+ while figuring out perl OO while figuring out the ill-documented WWW::Omegle perl module. Fun times. Actually, typing this made me realize I should OO it up a little more. Gonna go back to work after this post.&lt;&#x2F;p&gt;
&lt;p&gt;I definitely need to finish up the slides for the presentations I&#x27;m gonna give CSH. I&#x27;m gonna publish them on here too, under a new &amp;quot;Presentations&amp;quot; section. It should look pretty hot.&lt;&#x2F;p&gt;
&lt;p&gt;Anyway, I should go back to being productive, cause I haven&#x27;t done as much as I wanted.&lt;&#x2F;p&gt;
</description>
            </item>
        
            <item>
                <title>About Me</title>
                <pubDate>Thu, 29 Mar 1990 00:00:00 +0000</pubDate>
                <link>https://worrbase.com/about/</link>
                <guid>https://worrbase.com/about/</guid>
                <description>&lt;section class=&quot;h-card vcard&quot;&gt;
&lt;img src=&quot;&#x2F;img&#x2F;self.jpg&quot; alt=&quot;Selfie Shot&quot; class=&quot;smallImg selfie u-photo photo&quot;&gt;
&lt;p class=&quot;p-note note&quot;&gt;Hey, I&#x27;m &lt;span class=&quot;p-name fn&quot;&gt;&lt;span class=&quot;p-given-name given-name&quot;&gt;William&lt;&#x2F;span&gt; &lt;span class=&quot;p-family-name family-name&quot;&gt;Orr&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; or &lt;span class=&quot;p-nickname nickname&quot;&gt;worr&lt;&#x2F;span&gt;. I&#x27;m currently a &lt;span class=&quot;p-job-title job-title&quot;&gt;Devops Engineer&lt;&#x2F;span&gt; at Adevinta. Currently, I work with Kubernetes and Golang in the cloud, like the rest of the dang ops world these days. I also have an interest in systems programming, and focus on OS&#x2F;systems programming projects in my limited spare time. Currently, I&#x27;m located in &lt;span class=&quot;p-adr h-adr adr&quot;&gt;&lt;span class=&quot;p-locality locality&quot;&gt;Barcelona&lt;&#x2F;span&gt;, &lt;span class=&quot;p-country-name country-name&quot;&gt;Spain&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;.&lt;&#x2F;p&gt;
&lt;p&gt; I&#x27;m a staunch &lt;a href=&quot;https:&#x2F;&#x2F;openbsd.org&quot;&gt;OpenBSD&lt;&#x2F;a&gt; user at home, with almost all of my systems running OpenBSD where possible (I have one system that has to run FreeBSD). Currently, I&#x27;m spending time getting more proficient in Go and Rust, and trying to make the experience of both on OpenBSD more palatable where I can.&lt;&#x2F;p&gt;
&lt;h2&gt;Contact Me&lt;&#x2F;h2&gt;
&lt;dl&gt;
    &lt;span class=&quot;group&quot;&gt;
        &lt;dt&gt;PGP Key:&lt;dt&gt;
        &lt;dd class=&quot;contactItem&quot;&gt;&lt;a class=&quot;modalLink u-key key&quot; href=&quot;https:&#x2F;&#x2F;pgp.worr.pub&quot;&gt;95D8 225C 2EFE 2DA8 954F 41A1 E588 5A8A 4D91 B964&lt;&#x2F;a&gt;&lt;&#x2F;dd&gt;
    &lt;&#x2F;span&gt;
    &lt;span class=&quot;group&quot;&gt;
        &lt;dt&gt;Gitlab:&lt;&#x2F;dt&gt;
        &lt;dd class=&quot;contactItem&quot;&gt;&lt;a class=&quot;modalLink u-url url&quot; href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;worr&quot;&gt;gitlab.com&#x2F;u&#x2F;worr&lt;&#x2F;a&gt;&lt;&#x2F;dd&gt;
    &lt;&#x2F;span&gt;
    &lt;span class=&quot;group&quot;&gt;
        &lt;dt&gt;Github:&lt;&#x2F;dt&gt;
        &lt;dd class=&quot;contactItem&quot;&gt;&lt;a class=&quot;modalLink u-url url&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;worr&quot;&gt;github.com&#x2F;worr&lt;&#x2F;a&gt;&lt;&#x2F;dd&gt;
    &lt;&#x2F;span&gt;
    &lt;span class=&quot;group&quot;&gt;
        &lt;dt&gt;LinkedIn:&lt;&#x2F;dt&gt;
        &lt;dd class=&quot;contactItem&quot;&gt;&lt;a class=&quot;modalLink&quot; href=&quot;http:&#x2F;&#x2F;www.linkedin.com&#x2F;in&#x2F;willorr&quot;&gt;linkedin.com&#x2F;in&#x2F;willorr&lt;&#x2F;a&gt;&lt;&#x2F;dd&gt;
    &lt;&#x2F;span&gt;
    &lt;span class=&quot;group&quot;&gt;
        &lt;dt&gt;Email:&lt;&#x2F;dt&gt;
        &lt;dd class=&quot;contactItem&quot;&gt;&lt;a class=&quot;modalLink u-email email&quot; href=&quot;mailto:will@worrbase.com&quot;&gt;will@worrbase.com&lt;&#x2F;a&gt;&lt;&#x2F;dd&gt;
    &lt;&#x2F;span&gt;
    &lt;span class=&quot;group&quot;&gt;
        &lt;dt&gt;Fediverse:&lt;&#x2F;dt&gt;
        &lt;dd class=&quot;contactItem&quot;&gt;&lt;a class=&quot;modalLink u-url url&quot; href=&quot;https:&#x2F;&#x2F;bsd.network&#x2F;@worr&quot;&gt;bsd.network&#x2F;@worr&lt;&#x2F;a&gt;&lt;&#x2F;dd&gt;
    &lt;&#x2F;span&gt;
    &lt;span class=&quot;group&quot;&gt;
        &lt;dt&gt;Twitter:&lt;&#x2F;dt&gt;
        &lt;dd class=&quot;contactItem&quot;&gt;&lt;a class=&quot;modalLink&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;worr&quot;&gt;twitter.com&#x2F;worr&lt;&#x2F;a&gt;&lt;&#x2F;dd&gt;
    &lt;&#x2F;span&gt;
    &lt;span class=&quot;group&quot;&gt;
        &lt;dt&gt;Openhub:&lt;&#x2F;dt&gt;
        &lt;dd class=&quot;contactItem&quot;&gt;&lt;a class=&quot;modalLink&quot; href=&quot;https:&#x2F;&#x2F;www.openhub.net&#x2F;accounts&#x2F;worr&quot;&gt;openhub.net&#x2F;accounts&#x2F;worr&lt;&#x2F;a&gt;&lt;&#x2F;dd&gt;
    &lt;&#x2F;span&gt;
&lt;&#x2F;dl&gt;
&lt;a hidden class=&quot;u-url url&quot; href=&quot;https:&#x2F;&#x2F;onwednesdayswewear.pink&quot;&gt;onwednesdayswewear.pink&lt;&#x2F;a&gt;
&lt;a hidden class=&quot;u-url url&quot; href=&quot;https:&#x2F;&#x2F;worrbase.com&quot;&gt;worrbase.com&lt;&#x2F;a&gt;
&lt;&#x2F;section&gt;
</description>
            </item>
        
    </channel>
</rss>
