Tough to be a (textin') pimp

 Eric Williams | 19 July, 2021

It's hard to find a replacement for a beloved tool. No matter what you're shopping around for, there are a lot of things that look good on paper. There are specs and features, pics and reviews, but in the end what you're trying to find is the satisfaction you felt when using the old thing. That is something altogether different.

You're not going to have the same sense of fulfilment from new video games if you're an old boomer gamer. Same goes for that kick-ass Snap-On screwdriver with the slot-in magnetic bit that you lost years and years ago. Sure, there are things that meet and exceed the tech specs of whatever it is that you're missing, but they won't feel the same, they'll just sort of, kind of work the same way.

I'll never have the satisfaction of using WordPerfect 5.1 to type out documents again; wearing out the '/' key while making spreadsheets nothing more than a fond memory; admiring the ascii-art page ruler of PFS: Write while immersed in the 80x25 document view is as tears in rain. I guess the combination of the perfect tool for the perfect time in your life is easy early on, but gets harder as the years march by.

I tried out an old Amstrad PCW word processing package today, Locoscript. It was fine, and had a bit of PFS flair to it. In college, I probably would have fallen instantly in love. But I knew it wasn't the same, and I managed to resist putting too much time into it. It was nice, for an 80s word processor.

But I've seen better.

Atari Video Mods

 Eric Williams | 26 March, 2019

This is a list of mods for the Atari 5200 and 2600 that give you S-Video and/or composite video out.

Because I keep finding them and losing them.

Atari 5200

CD4050 + Transistor mod:

Good-looking mod that I'm breadboarding at the moment, just to see if it fixes some of the issues with the two-transistor mod that I'm currently using.

Transistor + CD4050

Single-transistor mod

Pretty basic mod, though it eats up a lot of soldering tin. And time.

I get buzzing on the audio with this one, and the colors aren't very stable.

There is lots of noise and bleeding to be dealt with on the picture. This is almost certainly due to my poor implementation of the mod and use of low- quality parts.

Atari 2600

Two-transistor mod

This mod blew me away. It was a pain in the ass to solder together, being as it was for an Atari 2600 Jr. PAL (UK) model. I couldn't really find any pictures online of the tapping points for the Chroma, Luma, etc. I'll post some here.

Colors look great, audio is squeaky clean. All in all, definitely happy with how this one turned out.

The S-Video jack fits perfectly into the RF jack socket. I opted to install a 3.5 mm stereo jack instead of RCA to save space and keep drilling down to a minimum.

In the future, I'll see about wiring up a composite jack, just for completeness. The composite wire could be passed through the Color / BW switch (although this is sometimes used in games; maybe not a good idea). Another possibility would be to just add a dp/st switch to the case, or finally track down a video driver IC that separates out CVBS from Y/C.

Brexit: A Primer

 Eric Williams | 24 June, 2016
For all my EU friends currently living in the UK, here’s what the country’s referendum means to you.
Table of mass units
Unit Pounds Grams Kilograms Notes
grain (gr) 17000 0.06479891
Exactly 64.79891 milligrams.
drachm (dr) 1256 1.7718451953125
ounce (oz) 116 28.349523125
pound (lb) 1 453.59237 0.45359237
Exactly 453.59237 grams by definition.
stone (st) 14 6350.29318 6.35029318
The plural stone is often used when providing a weight (e.g. "this sack weighs 8 stone").[30] A person's weight is often quoted in stones and pounds in English-speaking countries that use the avoirdupois system, with the exception of the United States and Canada, where it is usually quoted in pounds.
quarter (qr or qtr) 28 12.70058636
One quarter is equal to two stones or a quarter of a hundredweight. The term quarter was also commonly used to refer to a quarter of a pound in a retail context.
hundredweight(cwt) 112 50.80234544
One imperial hundredweight is equal to eight stones. This is the long hundredweight as opposed to the short hundredweight of 100 pounds as used in the United States and Canada.[31]
ton (t) 2240 1016.0469088
As with the US and Canadian[31] systems, twenty hundredweights equal a ton. The imperial hundredweight is 12% greater than the US and Canadian equivalent. The imperial ton (or long ton) is 2240 pounds, which is much closer to a metric tonne (about 2204.6pounds), compared to the short ton of 2000 pounds (907.185 kg).
Gravitational units
slug (slug) 32.17404856 14593.90294 14.59390294
The slug, a unit associated with imperial and US customary systems, is a mass that accelerates by 1 ft/s2 when a force of one pound (lbF) is exerted on it.[32]
F = ma (Newton's second law)
1 lbF = 1 slug × 1 ft/s2 (as defined above)
1 lbF = 1 lbm × g (by definition of the pound force)
g 32.17404856 ft/s2
1 slug 32.17404856 pounds

Running a Django Server at Home

 Eric Williams | 26 April, 2016
linux sysadmin django 

This is a quick run-down of how to host a Django website on your home broadband connection.

Why in the world would you want to do this? It has some advantages: Broadband has decent bandwidth these days, and cloud VMs generally can't compete with run-of-the-mill PC hardware in terms of memory, disk throughput, and CPU power.

There are disadvantages too, obviously, but for non-production systems running your own server can be a lot of fun!

Install Ubuntu Server

Ubuntu Server is fine and stable, and a brand new version just came out.

This post refers to 14.04 (Trusty), since I haven't gotten around to setting up a new version as of yet. 14.04 still has a few years of support left, so don't be afraid to deploy with it.

Install Apache

I know all the cool kids like Nginx, but Apache has modwsgi and modpython, so I find it suits my needs.

sudo apt-get install apache2-server libapache-mod-wsgi

Create a project directory

You can put your Django projects anywhere, but make sure it's readable / writable by the user or group that's running Apache: www-data.

sudo mkdir -p /srv/projects/
sudo chown myuser:www-data
cd /srv/projects

Create a virtual environment to host your Django stuff.

sudo apt-get install python-virtualenv
virtualenv .
. bin/activate
pip install django
django-admin startproject website

Now, setup your website Django project as you like.

Configure Apache

Setup a conf file for your website, /etc/apache/sites-available/website.conf

WSGIPythonPath /srv/projects/website/:/srv/projects/lib/python2.7:/srv/projects/lib/python2.7/plat-x86_64-linux-gnu:/srv/projects/lib/python2.7/lib-tk:/srv/projects/lib/python2.7/lib-old:/srv/projects/lib/python2.7/lib-dynload:/usr/lib/python2.7:/usr/lib/python2.7/plat-x86_64-linux-gnu:/usr/lib/python2.7/lib-tk:/srv/projects/local/lib/python2.7/site-packages:/srv/projects/lib/python2.7/site-packages

<VirtualHost *:80>
    SetEnv DJANGO_SETTINGS_MODULE website.settings

    WSGIScriptAlias / /srv/projects/subc/subc/

    Alias /static/ /var/www/static/
    Alias /media/ /var/www/media/

    <Directory "/srv/projects/website/website/">
        Require all granted

    <Location /static/>
        Order allow,deny
        Allow from all
        SetHandler none
    <Location /media/>
        Order allow,deny
        Allow from all
        SetHandler none

Enable the website

sudo a2dissite 00-default 
sudo a2ensite website 
sudo service apache2 restart

Check the website internally


Forward your Router

Make sure to forward port 80 and 443 from your router to your internal server.

Setup Dynamic DNS

If you have a website on a dynamic IP address, which is usually the case with home IP connections, you need to have some way of keeping that IP address known.

PyDDNS can help with this, as long as your domain is hosted on Amazon's Route 53. Otherwise, you can use Dynamic DNS services like No-IP to take care of that.

Django Simpleticket

 Eric Williams | 20 April, 2016
django reddit 

Just saw this flash past on Reddit:

The intent of this project is to provide a simple ticket-tracking app that can easily be dropped into a new or existing Django site. It aims for bare bones simplicity rather than elaborate features, minimizing dependencies and allowing the app to be set up in as little time as possible.

And while I enjoy seeing Apps for Django going by, I’m not sure I’m going to have the time to look at this one. I miss my sabbatical.

Getting started with Ansible

 Eric Williams | 16 June, 2014
ansible devops 

Setting up an Ansible test environment with LXC

These examples are made using Ubuntu 12.04 LTS and LXC.

To make this as easy as possible, it's a good idea to be using a local dnsmasqd to handle DHCP, DNS, and dynamic DNS for container instances.

We're going to make a small environment that simulates a few webservers, a database server, and an HTTP load-balancer. This will make 6 LXC containers, including the Ansible workstation that we'll be using for the ansible commands.

First, create a few machines using the lxc-create command:

sudo lxc-create -t ubuntu -n ansible-workstation -- -r precise --auth-file ~/.ssh/
sudo lxc-start -n ansible-workstation -d
for i in {1..3}; 
do sudo lxc-create -t ubuntu -n ansible-web-${i} -- -r precise --auth-key ~/.ssh/
   sudo lxc-start -n ansible-web-${i} -d

SSH into the Ansible workstation and setup Ansible:

ssh -l ubuntu ansible-workstation
sudo locale-gen en_{US,GB}{.UTF-8,}
sudo apt-get install -y python-software-properties
sudo apt-add-repository ppa:rquillo/ansible
sudo apt-get update
sudo apt-get install -y ansible

Ansible should be installed now. We're going to setup the ansible clients (ansible-web-{1,2,3}), add our ssh key now, and update the sudoers file to make things easy. Ansible keeps its list of hosts under /etc/ansible/hosts:

$ cat /etc/ansible/hosts

Create the sudoers file:

cat 10_ubuntu

Now see if your connection to the clients is working:

$ ansible -m ping all | success >> {
    "changed": false,
    "ping": "pong"
} | success >> {
    "changed": false,
    "ping": "pong"
} | success >> {
    "changed": false,
    "ping": "pong"

Copy our ssh key and sudoers file over to all those machines:

ansible all -m copy -a "src=~/.ssh/ dest=~/.ssh/authorized_keys mode=0600" -k
ansible all -m copy -a "src=10_ubuntu dest=/etc/sudoers.d/10_ubuntu mode=0440 \
   owner=root group=root" --sudo --ask-sudo-pass

At this point, we should be able to run commands via sudo on these machines.

Using Playbooks to Install Packages

These machines are all going to be web servers, so we're going to do the most basic thing: Install Apache.

We'll create a simple playbook, apache.yml:

- hosts: webservers
  sudo: yes
      - name: Installs apache web server
      apt: pkg=apache2 state=installed update_cache=true

Apply it using the ansible-playbook command:

$ ansible-playbook apache.yml

PLAY [webservers] *************************************************************

GATHERING FACTS ***************************************************************
ok: []
ok: []
ok: []
ok: []
ok: []

TASK: [Installs apache web server] ********************************************
failed: [] => {"failed": true}
msg: Could not import python modules: apt, apt_pkg. Please install python-apt package.
FATAL: all hosts have already failed -- aborting

Doh! We need to install python-apt on these machines.

ansible  -m shell -a 'sudo apt-get update && sudo apt-get install -y python-apt' webservers
ansible-playbook apache2.yml

You can run it again to see that everything is as expected:

$ ansible-playbook apache2.yml
PLAY RECAP ******************************************************************** : ok=2    changed=0    unreachable=0    failed=0 : ok=2    changed=0    unreachable=0    failed=0 : ok=2    changed=0    unreachable=0    failed=0 : ok=2    changed=0    unreachable=0    failed=0 : ok=2    changed=0    unreachable=0    failed=0 : ok=2    changed=0    unreachable=0    failed=0


  • Setup ansible
  • Setup LXC containers as ansible clients
  • Transfer files
  • Install packages via Ad Hoc commands
  • Run a simple playbook

Making Fedora Not Look Like Ass

 Eric Williams | 22 December, 2013

It's been a while since I monkeyed around with Fedora. 10 years ago, I was all about SuSE; then I bought a PowerBook G4, which was immune to Linux for the most part, but I ran Debian on it a couple of times just to see what PowerPC Linux was looking like. Around 2005, I started using Fedora Core, and actually liked it quite a bit.

When I was toiling away at Red Hat, starting in 2007, I tried to use RHEL on the desktop. This lasted about 2 hours, at which point I blew it away and put Fedora 7 on it and never looked back. I never actually looked forward, either, and wound up running Fedora 7 until I left the company in 2010. This turned out to be a running gag with the team, who scoffed at my old-man-on-the-porch attitude towards newer releases, with their "features" and "SVGA displays".

Once I left Red Hat and started working for Canonical, I put Ubuntu on my MacBook Air; it was enjoyable for the most part. Ubuntu's a nice desktop distribution, and a good match for the MacBook Air's SSD and compact display. By the time Precise came out last year, installation was painless and the hardware support pretty top-notch.

Leaving Canonical, I figured it was time to revisit Fedora. I tore down my Precise installation and went about trying to get Fedora 19 installed. This resulted in gigantic failure, mainly because of this bug. Don't bother trying to install this version, it won't work and you'll just be beating your head against a wall. Go for either Fedora 18 or the Fedora 20 beta.


When you're done installing Fedora 20, you'll notice the fonts look like ASS compared to Ubuntu or Mac OS X. This appears to be due, in part, to the version of Freetype that Fedora uses.

This is taken from here.

  • Install the 'nonfree' version of freetype-freeworld from rpmfusion
  • Set the Xft.lcdfilter property in your Xresources file
  • Set up the hinting and antialising styles in gsettings
$ cat ~/.Xresources
  Xft.lcdfilter: lcddefault
$ gsettings "set" "org.gnome.settings-daemon.plugins.xsettings" "hinting" "slight"
$ gsettings "set" "org.gnome.settings-daemon.plugins.xsettings" "antialiasing" "rgba"
$ xrdb -query
Xft.antialias: 1
Xft.dpi: 96
Xft.hinting: 1
Xft.hintstyle: hintslight
Xft.lcdfilter: lcddefault
Xft.rgba: rgb

Now, I don't know why one has to do that, but one does. After this, you'll notice that the standard fonts start looking great. Even in Terminator.

Missing Fonts

I did find on occasion that I'd run across web pages, emails, etc. that included fonts that, once again, looked like 1997 Linux. Figuring this was because of shit font substitution, I installed the following:

  • Microsoft ttf core fonts
    • Arial
    • Times New Roman
    • Tahoma
    • etc

  • The Ubuntu font collection
  • Mac OS X Fonts

    • Lucida Grande
    • Apple Garamond

Even after doing all of this, though, I still have to put put up with font horridness. DejaVu Sans, specifically. It is jaggy and horrible, and unfortunately it can't be uninstalled because of LibreOffice's ill-advised package dependency on it. It basically just means that whenever I go to Fedora Project sites, I get eye-raped by unreadable fonts.


Despite the eye-rape, I quite like GNOME Shell, and GNOME 3.10 in general. It's a nice, productive desktop, and very attractive to look at. With natural scrolling turned on and apps running full-screen, it's a great match with the MacBook Air.

I do think that it makes inefficient use of my 11-inch screen, though. The title bars in application windows are gigantic, for example, with a big gray stripe that does nothing except waste my pixels and remind you that yes, you are running GNOME 3.

I quite like the fact that when I setup online accounts in the control panel, they actually do something. In Ubuntu, the underlying GNOME infrastructure does less and less, but they don't bother taking out the user interface bits that make you think that when you configure something, it will actually be used somewhere.

Changing the hostid in Linux

 Eric Williams | 14 November, 2011
linux sysadmin 

The hostid on some systems, like Suns, is set in the hardware and uniquely identifies the system. On Linux, the hostid is more of a suggestion than a hard-and-fast rule. It's usually generated at install time, and can be changed with a few lines of python code:

      from struct import pack
      hostid = pack("I",int("0x210a2500",16))
      filename = "/etc/hostid"

You can check this then with the hostid command.

  # hostid

Protip: It's always a good idea to back up /etc/hostid first, just in case.

This can help workaround issues with applications like flexlm, that naively assume that hostid is in some way significant on Linux.

Launchd in Ubuntu

 Eric Williams | 1 September, 2011
linux sysadmin launchd 

In the various flavors of UNIX, you usually have an init or init-like process which wrangles all the sundry system services. Things like your mail server, your ftp server, etc. all have to be started by something.

In Ubuntu, we use Upstart since Lucid. It's a modern, event-based init daemon. Red Hat Enterprise Linux 5 uses the fine old SysVInit system. In RHEL 6, you also have Upstart, but it's being run in a SysVInit-compatibility mode. RHEL's cousin, Fedora, uses systemd.

Under Mac OS X Tiger and later, there's launchd. This not only replaces init, but also cron and a couple of other traditional UNIX facilities.

According to The Book of Knowledge

The Ubuntu Linux distribution considered using launchd in 2006. However, launchd was rejected as an option because it was released under the Apple Public Source License – which at the time was described as an "inescapable licence problem".

In August 2006, Apple relicensed launchd under the Apache License, Version 2.0 in an effort to make adoption by other open source developers easier.

I'm not so convinced that licensing was the main reason that launchd was passed over. I wasn't around Ubuntu or Canonical at the time, and I've heard conflicting accounts from various Canonical employees on the matter.

With as much time and effort as we've put into Upstart in the meanwhile, it's turned out to be a pretty good solution.

People complain about the upstart configuration file syntax. If you compare it aginast the property list approach, though, it's like writing hot buttered biscuits and bacon.

For comparison, here's a property list for postfix (stolen from Macworld):

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "">
    <plist version="1.0">

Postfix isn't upstartified in Ubuntu (yet), but here's a comparable rsyslog upstart config:

# rsyslog is an enhanced multi-threaded replacement for the traditional
# syslog daemon, logging messages from applications

description     "system logging daemon"

start on filesystem
stop on runlevel [06]

expect fork

    . /etc/default/rsyslog
    exec rsyslogd $RSYSLOGD_OPTIONS
end script

Launchd might be stable, and it's what all the cool BSD kids are running these days, but it breaks one of the commandments: XML is not to be considered human-writable. It's a data format.

Heading to Canada

 Eric Williams | 16 April, 2011
travel Canadia 

I'm getting ready to head over to Montreal, or "Mon' cccchhhhrayall" as the indigenous people of Canadia refer to it. It's all about business, though, and I unfortunately will not be seeing any hockey playoffs, except maybe on TV.

Not that it's sounding bad at the moment, mind you. I'm sitting in a bar in Heathrow's Terminal 5 watching two televisions. TV #1 is displaying cricket, which is England's version of baseball. TV #2 is playing Fawlty Towers with subtitles, which is England's version of waterboarding. God damn, I hate Fawlty Towers.

Montreal looks to have some sights to see, but I'm not sure what the opening hours look like. I've been living on the goofy side of the pond for going on 13 years now, and I'm actually accustomed to things like paying a license fee for television ownership and bars closing at 10 o'clock at night. Not to mention dog tax. With that in mind, it could be that bars are open 24x7, the restaurants never close, and we'll never get any older and we won't ever die. This is my expectation, and you should know I don't react well to disappointment.

This will be my first trip to Canada. I've been to a fair number of countries, but the list has been pretty static for a while now. In the past months I've expanded it with Greece and Canada. Next month, I'll be heading to Hungary for the first time.

Coming up: How to handle a full passport.

Asimo Freaks Me Out

 Eric Williams | 4 February, 2010
robots freak 

This creepy-ass little robot crossed with an Aibo would just about weird the shit out of anybody.

Pro tip: If you really want to feel your skin crawl, watch that video with Bauhaus's "Bela Lugosi's Dead" playing in the background.

OS News Makes You Stupid

 Eric Williams | 9 September, 2007

I like reading OSNews for some reason. I think I like to catch the geeky news about SkyOS, or the occasional retro curmudgeonry that rolls by about Lotus 1-2-3 or OS/2. Being the old-timer that I am, it's hard to resist a paean from my youth about 10-finger productivity.

Unfortunately, they've become the epicenter of stupid for the tech press. Check out this article, which explodes the myths about competition being good: "Competition is not Good"

'It gives consumers more choice'

Choice is good when there's one agreed base standard, and a number of compatible approaches. For example, there are many Linux distributions, but they are all Linux, and they can all run the same software. They are 'flavours' of the same thing, that is a good choice. People like different flavours.

Competition does not produce easier choices for consumers. All they get is added un-interoperability and complexity with competitive choices.

Now, if you go read that article, which I do not recommend, you'll slowly come to the realization that this moron is just annoyed that he has to make the effort to choose between HD-DVD and Blu-Ray. He's willing to surrender his entire free will to some (hopefully) benevolent dictator, abolish brand names, and forsake the free market economy because choosing which format to buy the Firefly special edition box set in is hard. What a hopeless, whiny-assed sissy.

Of course, things don't get better when they start tossing political analysis at you. "Net Neutrality" is one monikers that has overshadowed the thing named. The discussion is often framed in a way that an uninformed listener would assume there was lobbying going on to abolish some sort of laws that are now protecting consumers from big, bad tiered-Internet ninjas.

But: There is no net neutrality legislation, there never was, and hopefully, there never will be. The argument over "Net Neutrality" is about whether or not the U.S. government should introduce legislation forbidding bandwidth throttling by ISPs. It's the "have you stopped beating your wife?" straw man for the Slashdot crowd. You'll notice that this article calls the Supreme Court's decision that the U.S. government shouldn't step in and configure the ISPs' Cisco routers for them, "Backing for Two-Tier Internet":

The US Justice Department has said that internet service providers should be allowed to charge for priority traffic. The agency said it was opposed to 'network neutrality', the idea that all data on the net is treated equally. The comments put the agency at odds with companies such as Microsoft and Google, who have called for legislation to guarantee equal access to the net.

Of course, this would also mean that an enforcement infrastructure would also have to be put in place, making sure that everyone got their "fair share" of said bandwidth, as if backbone routers and POPs just fell off a tree somewhere. God forbid ISPs be allowed to tune the services that they developed and paid for as they wish. Let's let the government decides who gets bandwidth, and how much is enough! That will make it all fair and neutral-like. Whenever a politician uses the word "fair", hang on to your wallet.

Crappy Wordpress

 Eric Williams | 9 September, 2007
wordpress crap 

Well, my trackbacks are now working, it seems. There's some ugly Python spaghetti-code going on behind the scenes that translates back and forth between absolute urls, non-absolute relative urls, and upper-lower-camel case; but it works.

Trackbacks are only good for Movable Type, though. Which I can't stand anymore. MT used to be the only thing out there, but there's something that really, really, really galls me about the way it rebuilds your entire site into static HTML pages everytime you update a post. I'm sure it's awesomeness if you've got your server running on an old TV remote, but nowadays we're all running our web servers on 100-core 64-bit terahertz moonshot computers that can simultaneously compute π, encode MPEG video, and mix the best goddam margaritas you've ever tasted, all without breaking a sweat.

So yeah, I figured out how to implement trackbacks in Django, to a point where they more or less work. Now why is Wordpress fucking with me? It seems to be thrown off by the fact that Wordpress sends a HEAD request before it downloads and parses the page, in the vain hope that the X-Pingback header will be set. I can't figure out how to do that in Django's generic views, so I just use the secondary method, that being a link element in the XHTML code. But now, whenever a Worpdress blog pings me, I get this kind of crap:

  [09/Sep/2007 15:04:23] "GET /blog/2007/sep/08/vacation/ HTTP/1.1" 200 27367
Traceback (most recent call last):
  File "/home/rubeon/lib/python2.4/django/core/servers/", line 273, in run
  File "/home/rubeon/lib/python2.4/django/core/servers/", line 312, in finish_response
  File "/home/rubeon/lib/python2.4/django/core/servers/", line 396, in write
  File "/usr/local/lib/python2.4/", line 248, in write
  File "/usr/local/lib/python2.4/", line 235, in flush
error: (104, 'Connection reset by peer')
Traceback (most recent call last):
  File "/home/rubeon/lib/python2.4/django/core/servers/", line 273, in run
  File "/home/rubeon/lib/python2.4/django/core/servers/", line 312, in finish_response
  File "/home/rubeon/lib/python2.4/django/core/servers/", line 396, in write
  File "/usr/local/lib/python2.4/", line 248, in write
  File "/usr/local/lib/python2.4/", line 235, in flush
error: (32, 'Broken pipe')

Being the half-assed programmer that I am, I am at a total loss. I can't even do a Lazyweb request here, seeing as my 4 visits a day are unlikely to bring the Django HTTP gurus by. I won't be able to sleep at night, thinking of all the enlightened Wordpress Users who are probably out there try to "Keep the discussion going" with me.