Posts | Tags | Archive

Dynamic DNS client for Namecheap using bash & cron

In addition to running this website, I also run a home server. For convenience, I point a subdomain of cmetcalfe.ca at it so even though it's connected using a dynamic IP (and actually seems to change fairly frequently), I can get access to it from anywhere.

As a bit of background, the domain for this website is registered and managed through Namecheap. While they do provide a recommended DDNS client for keeping a domain's DNS updated, it only runs on Windows.

Instead, after enabling DDNS for the domain and reading Namecheap's article on using the browser to update DDNS I came up with the following dns-update script.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
#!/bin/sh

# Abort if anything goes wrong (negates the need for error-checking)
set -e

# Uses drill instead of dig
resolve() {
    #dig "$1" @resolver1.opendns.com +short 2> /dev/null
    line=$(drill "$1" @resolver1.opendns.com 2> /dev/null | sed '/;;.*$/d;/^\s*$/d' | grep "$1")
    echo "$line" | head -1 | cut -f5
}

dns=$(resolve <subdomain>.cmetcalfe.ca)
curr=$(resolve myip.opendns.com)
if [ "$dns" != "$curr" ]; then
    if curl -s "https://dynamicdns.park-your-domain.com/update?host=<subdomain>&domain=cmetcalfe.ca&password=<my passkey>" | grep -q "<ErrCount>0</ErrCount>"; then
        echo "Server DNS record updated ($dns -> $curr)"
    else
        echo "Server DNS record update FAILED (tried $dns -> $curr)"
    fi
fi

It basically checks if the IP returned by a DNS query for the subdomain matches the current IP of the server (as reported by an OpenDNS resolver) and if it doesn't, sends a request to update the DNS. The echo commands are there just to output some record of the IP changing. Maybe I'll do some analysis of it at some point.

To run the script every 30 minutes and redirect any output from it to the syslog, the following crontab entry can be used:

1
*/30 * * * * /path/to/dns-update | /usr/bin/logger -t dns-update

With the script automatically running every 30 minutes I can now be confident that my subdomain will always be pointing at my home server whenever I need access to it.

Note

A previous version of this article used curl -sf http://curlmyip.com to find the server's current IP address. However, after curlmyip went down for a few days, I decided to take the advice in this StackExchange answer and use OpenDNS instead.


Remove an application from the cmd-tab switcher on macOS

At work, I use iTerm2 as my main terminal emulator. For quick access, I have it configured to drop down from the top of the screen when F12 is pressed.

Unfortunately, it also shows up in the application switcher, bumping up into the 'last used' position whenever it's activated and getting in the way. Since I already have access to the terminal via F12, there's no need for it to be shown in the application switcher as well.

Changing how an application behaves can be done by editing its Info.plist file. The key LSUIElement (according to the Apple documentation) "Specifies whether the app is an agent app, that is, an app that should not appear in the Dock or Force Quit window."

To set this key, open the application's Info.plist at /Applications/[application name].app/Contents/Info.plist and add <key>LSUIElement</key><true/> after the first <dict> tag. The result should look something like this:

1
2
3
4
5
6
7
8
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>LSUIElement</key><true/>
    <!-- The rest of the plist data -->
</dict>
</plist>

Once the LSUIElement key is set to true, relaunch the application to see the changes.

Be warned that not only does this remove the application from the application switcher, it also removes it from the dock and stops it from showing the menu bar on the top of the screen.


Adding Xbox 360 controller support to a Nexus 5

Update

CyanogenMod has effectively been replaced by LineageOS. The links in this article originally all pointed to CyanogenMod but since it no longer exists, I've updated them to use the LineageOS equivilents where possible. The instructions will also need to be slightly modified for use with LineageOS builds.

Introduction

I finally just bought a new phone (a Nexus 5), and after flashing CyanogenMod onto it, I've been messing around with its OTG support. My old phone (a Nexus 4) didn't have the capability so being able to plug in keyboards, mice, external hard drives, and various other peripherals was (embarrassingly enough) a thrill.

Keyboards worked, mice worked, but when an Xbox 360 controller was plugged in, nothing happened. Turns out that while the kernel didn't have support for it enabled out of the box, getting it enabled and pushing the change upstream into the CyanogenMod project was easier than I thought.

Beware that this post is going to be more of a record of what I did so that I can do it again and less of a coherent tutorial.

Building CyanogenMod

First step was to download and compile CyanogenMod for my phone. I'm not going to go into this in any detail on this because there's already a good overview on the CyanogenMod wiki that covers the entire process, as well as a customized guide for the Nexus 5. If those articles are followed correctly, you should be able to build a fresh CyanogenMod image with:

1
brunch hammerhead

Enabling the kernel module

Once the image was flashed to the phone and verified to be working, the next step was to enable the xpad kernel module.

Copy current kernel config to the kernel directory for editing:

1
2
cd <build dir>/kernel/lge/hammerhead/
cp arch/arm/configs/cyanogenmod_hammerhead_defconfig .config

Edit the config:

1
make menuconfig ARCH=arm

At this point, a menu will come up. Search for xpad (type /xpad), and take note of the paths. ESC out of the search, navigate the tree and enable the modules found with the search. Save and exit.

Copy the config back and clean up any stray *.o files:

1
2
cp .config arch/arm/configs/cyanogenmod_hammerhead_defconfig
make mrproper

After enabling the module, rebuild CyanogenMod using the normal brunch hammerhead and flash it to the phone.

Submitting the change upstream

Since Xbox controller support had already been requested in a JIRA ticket(dead link), I went through the process to submit the change on the CyanogenMod Gerrit instance for inclusion in the next release. There's a guide for this here. As well as the guide, I found the people in #cyanogenmod-dev on Freenode to be very helpful.

A short while after submitting the change to Gerrit, it was merged into the cm-11.0 branch as commit i7ef4f6a and pushed out in the next nightly build (changelog screenshot).

Wrap-up

It feels great to be able to contribute to an amazing open source project that had at least a million people using it at one point or another. I recognize that the change by itself was just changing a config file to enable functionality that already existed, but it's helped me get through some of the non-coding hurdles of contributing to an Android fork like CyanogenMod (adb, fastboot, unlocking and rooting phones, compiling AOSP, flashing images, the contribution process, etc). This time the actual contribution itself was minor, but it's gotten me more familier with the process, hopefully making it easier to contribute something more substantial in the future.

In the end, I learned a lot about Android development and how all the different pieces that I had read about at one point or another actually fit together. During the whole process I also lost a lot of the fear I had about messing with phones and other more expensive locked down devices. Going forward, I'm going to attempt to compile and flash open source operating systems like CyanogenMod onto more devices that I own. I like being able to tweak things and feel like I really own them, hardware and software.

© Carey Metcalfe. Built using Pelican. Theme is subtle by Carey Metcalfe. Based on svbhack by Giulio Fidente.