notes on javascript, linux, and more


Zenburn Blogger Template with Syntax Highlighting for Code Examples

I love the Zenburn color scheme. I use it for vim, xterm, Visual Studio, PuTTY, Notepad++. Its really easy to look at all day, much nicer than a high contrast color scheme like black text on a white background. So, I decided to make my blogger template look like Zenburn. I recommend that you load the SyntaxHighlighter scripts from a server under your control just in case I move my scripts later. Here is the template if you are interested in using it:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "">
<html expr:dir='data:blog.languageDirection' xmlns='' xmlns:b='' xmlns:data='' xmlns:expr=''>
<meta content='HTML Tidy for Linux/x86 (vers 11 February 2007), see' name='generator'/>
<b:include data='blog' name='all-head-content'/>
* Blogger Template Style
* Simple Zenburn
* October 2008 - elijah rutschman
* based on Simple II by Jason Sutter
* and zenburn.vim by Jani Nurminen

/* Variable definitions
<Variable name="bgcolor" description="Page Background Color"
type="color" default="#444" value="#3f3f3f">
<Variable name="textcolor" description="Text Color"
type="color" default="#eed" value="#dcdccc">
<Variable name="pagetitlecolor" description="Blog Title Color"
type="color" default="#eed" value="#dcdccc">
<Variable name="titlecolor" description="Post Title Color"
type="color" default="#eb9" value="#dfaf8f">
<Variable name="footercolor" description="Date and Footer Color"
type="color" default="#8A8" value="#7f9f7f">
<Variable name="linkcolor" description="Link Color"
type="color" default="#9dd" value="#8cd0d3">
<Variable name="visitedlinkcolor" description="Visited Link Color"
type="color" default="#9ee" value="#93e0e3"> Used to be #969
<Variable name="bordercolor" description="Border Color"
type="color" default="#c99" value="#cc9393">
<Variable name="bodyfont" description="Text Font"
type="font" default="normal normal 80% Trebuchet MS, Verdana, Arial, Sans-serif"
value="normal normal 80% Trebuchet MS, Verdana,Arial, Sans-serif">
<Variable name="pagetitlefont" description="Blog Title Font"
default="normal bold 150% Trebuchet MS, Verdana, Arial, Sans-serif"
value="normal bold 150% Trebuchet MS, Verdana, Arial, Sans-serif">
<Variable name="codefont" description="Code Example Font"
default="normal normal 90% Monaco, Bitstream Vera Sans Mono, Lucida Sans Typewriter, monospace"
value="normal normal 90% Monaco, Bitstream Vera Sans Mono, Lucida Sans Typewriter, monospace">
<Variable name="startSide" description="Start side in blog language"
type="automatic" default="left" value="left">
<Variable name="endSide" description="End side in blog language"
type="automatic" default="right" value="right">
body {
a:link {
a:visited {
a:hover {
a img {
#outer-wrapper {
margin-top: 0px;
margin-$endSide: 3em;
margin-bottom: 0;
margin-$startSide: 3em;
h1 {
border-bottom:dotted 1px $bordercolor;
color: $pagetitlecolor;
font: $pagetitlefont;
h1 a, h1 a:link, h1 a:visited {
color: $pagetitlecolor;
h2 {
padding: 0px;
blockquote, cmd, code {
color: $bordercolor;
font: $codefont;
#main .widget {
border-bottom:dotted 1px $bordercolor;
clear: both;
#main .Header {
border-bottom-width: 0px;
} {
font-size: 90%;
} {
font-size: 140%;
color: $titlecolor;
.post {
.post-footer {
#comments {
#comments .comment-footer {
.comment-author {
margin-top: 3%;
.comment-body {
.deleted-comment {
.comment-link {
.feed-links {
clear: both;
line-height: 2.5em;
#blog-pager-newer-link {
float: $startSide;
#blog-pager-older-link {
float: $endSide;
#blog-pager {
text-align: center;
.clear {
clear: both;
.profile-img {
float: $startSide;
margin-top: 0;
margin-$endSide: 5px;
margin-bottom: 5px;
margin-$startSide: 0;
body#layout #outer-wrapper {
margin-top: 0px;
margin-$endSide: 50px;
margin-bottom: 0;
margin-$startSide: 50px;
<div id='outer-wrapper'>
<b:section class='main' id='main' showaddelement='yes'>
<b:widget id='Header1' locked='false' title='elijahr (Header)' type='Header'/>
<b:widget id='BlogArchive1' locked='false' title='Blog Archive' type='BlogArchive'/>
<b:widget id='Blog1' locked='true' title='Blog Posts' type='Blog'/>
<b:widget id='Profile1' locked='false' title='About Me' type='Profile'/>
<b:widget id='Label1' locked='false' title='Labels' type='Label'/>
<b:widget id='LinkList1' locked='false' title='links' type='LinkList'/>
<script src='' type='text/javascript'/>
<script src='' type='text/javascript'/>
<script src='' type='text/javascript'/>
<script src='' type='text/javascript'/>
<script src='' type='text/javascript'/>
<script src='' type='text/javascript'/>
<script type='text/javascript'>
</script><style type='text/css'>
.dp-highlighter {
background-color: #3f3f3f;
font-family: Monaco, Lucida Sans Typewriter, Bitstream Vera Sans Mono, monospace;
font-size: 12px;
margin: 18px 0 18px 0 !important;
overflow: auto;
padding-top: 1px;
width: 99%;
.dp-highlighter ol, .dp-highlighter ol li, .dp-highlighter ol li span {
border: none;
margin: 0;
padding: 0;
.dp-highlighter a, .dp-highlighter a:hover {
background: none;
border: none;
margin: 0;
padding: 0;
.dp-highlighter .bar {
padding-left: 45px;
.dp-highlighter.collapsed .bar, .dp-highlighter.nogutter .bar {
padding-left: 0px;
.dp-highlighter ol {
background-color: #3f3f3f;
color: #dcdccc;
list-style: decimal;
margin: 0px 0px 1px 45px !important;
padding: 0px;
.dp-highlighter.nogutter ol, .dp-highlighter.nogutter ol li {
list-style: none !important;
margin-left: 0px !important;
.dp-highlighter ol li, .dp-highlighter .columns div {
background-color: #3f3f3f;
border-left: 3px solid #3f3f3f;
color: #4c7073;
line-height: 14px;
list-style: decimal-leading-zero;
list-style-position: outside !important;
margin: 0 !important;
padding: 0 3px 0 10px !important;
.dp-highlighter.nogutter ol li, .dp-highlighter.nogutter .columns div {
border: 0;
.dp-highlighter .columns {
background-color: #3f3f3f;
color: gray;
overflow: hidden;
width: 100%;
.dp-highlighter .columns div {
padding-bottom: 5px;
.dp-highlighter ol li span {
color: #dcdccc;
.dp-highlighter.collapsed ol {
margin: 0px;
.dp-highlighter.collapsed ol li {
display: none;
.dp-highlighter.printing {
border: none;
.dp-highlighter.printing .tools {
display: none !important;
.dp-highlighter.printing li {
display: list-item !important;
.dp-highlighter .tools {
background-color: #3f3f3f;
border-left: 3px solid #3f3f3f;
color: silver;
font: 9px Verdana, Geneva, Arial, Helvetica, sans-serif;
padding: 3px 8px 3px 10px;
padding-bottom: 10px;
.dp-highlighter.nogutter .tools {
border-left: 0;
.dp-highlighter.collapsed .tools {
border-bottom: 0;
.dp-highlighter .tools a {
color: #dcdccc;
font-size: 9px;
margin-right: 10px;
text-decoration: none;
.dp-highlighter .tools a:hover {
text-decoration: underline;
.dp-about {
background-color: #3f3f3f;
color: #dcdccc;
margin: 0px;
padding: 0px;
.dp-about table {
font-family: Tahoma, Verdana, Arial, sans-serif !important;
font-size: 11px;
height: 100%;
width: 100%;
.dp-about td {
padding: 10px;
vertical-align: top;
.dp-about .copy {
border-bottom: 1px solid #3f3f3f;
height: 95%;
.dp-about .title {
color: #93e0e3;
font-weight: bold;
.dp-about .para {
margin: 0 0 4px 0;
.dp-about .footer {
background-color: #3f3f3f;
border-top: 1px solid #3f3f3f;
color: #dcdccc;
text-align: right;
.dp-about a {
color: #93e0e3;
.dp-about .close {
background-color: #3f3f3f;
color: #dcdccc;
font-family: Tahoma, Verdana, Arial, sans-serif !important;
font-size: 11px;
height: 22px;
width: 60px;
.dp-highlighter .plain, .dp-xml .cdata, .dp-xml .attribute {
color: #dcdccc;
.dp-highlighter .comment, .dp-highlighter .comments {
color: #7f9f7f;
.dp-highlighter .string, .dp-xml .attribute-value {
color: #cc9393;
.dp-highlighter .keyword, .dp-xml .tag, .dp-xml .tag-name {
color: #f0dfaf;
font-weight: bold
.dp-highlighter .preprocessor {
color: #dcdccc;


A Threading Class for Javascript: Reworked

I was playing around with my threading class for Javascript, and decided to rework it a little bit. The little research I've done indicates that as of this writing, no browser's Javascript engine implements actual threading under the hood. So, perhaps a better title for this post would be "An Asynchronous Execution Class for Javascript." Basically, you pass an array of Callback objects into the constructor for a Thread. When you call Thread.start() the sequence of callbacks are executed synchronously, from a "driver" function that is queued to run after the current call stack terminates. Not very robust, but I could see it coming in handy in some circumstances, especially involving page interactivity and event-handling.

Array.prototype.add = function(object) {
// easy way to append to an array
this[this.length] = object;
Callback = function(fun, args) { = function(){
Thread = function (callbacks) {
/* simulates thread-like functionality for javascript
callbacks = new Array();
// an array to hold callback functions
callbacks.add( new Callback(
function(words) {
["hello ","from callback 1"]));

callbacks.add( new Callback(
function(words) {
["hello ","from callback 2"]));

callbacks.add( new Callback(
function(words) {
["hello ","from callback 3"]));

callbacks.add( new Callback(
function(words) {
["hello ","from callback 4"]));

var myThread = new Thread(callbacks);
this.start = function() {
var thread = function () {
for (var i=0;i<callbacks.length;i++) {
// initiates the asynchronous call and returns control back to original caller
Thread.sleep = function (delay){
/* simulates a Thread pause for 'delay' milliseconds
known issues:
while sleeping, browser is non-interactive
some browsers will warn the user that an infinite loop may be in progress
var startTime = new Date().getTime();
while (new Date().getTime() < startTime + delay){}


A Threading Class for Javascript

Note: please see this post for an updated version of this code.

Most modern programming languages have a Threading class that allows the user to fork from a program's main thread and execute code asynchronously. I have been using Javascript a lot lately, and although it doesn't provide a Threading class or even a Thread.sleep() type of function, it turns out it is not so hard to throw something together using setTimeout and setInterval with anonymous functions.
Thread = function (threadFunction,
threadProgressCallbackTimeout) {
/* creates a fork off of the main Javascript thread and allows that thread to have callbacks for different states.
Example usage:
var myThread = new Thread( function(){alert('in the main function');},
function(){alert('thread completed');},
function(){alert('thread started ');},
function(){alert('checking progress...');},
500 ); // the progress checking function is looped every 500 ms

// private variables
var threadProgressCallbackSwitch = true;
var progressCallbackId;

// the progress callback is repeatedly called by setInterval
// so this wrapper is used to allow the loop to exit at some point via clearInterval
var threadProgressCallbackCaller = function() {
threadProgressCallbackSwitch ? threadProgressCallback() : clearInterval(progressCallbackId);

// replace undefined parameters with empty functions
if (threadFunction == undefined) threadFunction = function(){}
if (threadCompletedFunction == undefined) threadCompletedFunction = function(){}
if (threadStartedFunction == undefined) threadStartedFunction = function(){}

// define the main thread driver
this.start = function() {
var thread = function () {
if (threadProgressCallback != undefined) {
// if there is a progress checking callback, start looping it
if (threadProgressCallbackTimeout == undefined) threadProgressCallbackTimeout = 300;
progressCallbackId = setInterval(threadProgressCallbackCaller, threadProgressCallbackTimeout);
threadProgressCallbackSwitch = false;
setTimeout(thread,0); // initiates the asynchronous call and returns control back to original caller
Thread.sleep = function (delay){
/* simulates a Thread pause for 'delay' milliseconds
known issues:
while sleeping, browser is non-interactive
some browsers will warn the user that an infinite loop may be in progress
var startTime = new Date().getTime();
while (new Date().getTime() &lt; startTime + delay){}


IE6 peek-a-boo bug

I was trying to manipulate the DOM to workaround the IE6 peekaboo bug, but none of the recommended methods seemed to work. I thought up this neat trick:

<!-- elijahr peekaboo fix -->
<img src="" alt="" style="display:none" onload="javascript:this.parentNode.innerHTML=this.parentNode.innerHTML+' ';"/>

It basically just rebuilds the corrupted DOM section through javascript and forces IE 6 to render correctly. You can put it only in the places you need it, or right under the body tag. Just make the img element a child of whatever element is giving you issues. A broader, but somewhat slower approach that might work would be to simply set the onload event of the body tag to:

<body onload="javascript:this.innerHTML=this.innerHTML+' ';">

But, that might not work in every case. Peek-a-boo is a sneaky fiend of a bug.



unpacking tarballs efficiently onto flash devices

I recently installed NetBSD/hpcmips onto an old Windows CE based handheld PC. I tried installing pkgsrc, NetBSD's package management system, but the tarball was nowhere near done extracting to the CompactFlash card, even after leaving tar -xzf running all night. This is expected, given the incredibly low specs of the handheld PC, but I wanted to do something faster.

I fired up a blank virtual machine in VMWare Server, allocating a single gigabyte of disk space and a half gigabyte of RAM. I also added a USB controller to access my CF disk with later. I booted the machine from a NetBSD installation ISO image, and proceeded with a minimal installationg of NetBSD/i386. NetBSD is incredibly optmized and minimalist, so this took less than 5 minutes. I then rebooted the VM, and ran these commands:

mount /dev/sd-my-cf-card's-netbsd-partition /mnt/
tar -xzf pkgsrc.tar.gz -b 52000 -C /mnt/usr/

This finished a lot more quickly. The -b parameter sets the block size. I set this to approximately 26MB, which is the size of the pkgsrc tarball, meaning that the tarball was unpacked completely to RAM before being written to disk. This is a lot faster than:

mount /dev/sd-my-cf-card's-netbsd-partition /mnt/
tar -xzf pkgsrc.tar.gz -C /mnt/usr/

Try it and see! If working with dd, use the bs parameter to set the block size and see that you will get things done a lot faster as well. You'll have to play around with numbers; obviously you don't want to make the block size any bigger than your available RAM or your operating system will start swapping to disk anyway. My general rule of thumb is to use half of my available RAM as the blocksize, which should usually provide maximum efficiency and speed. Cheers.


Installing Debian Etch-and-a-half onto a Powerbook G3 (Wallstreet)

This is the hardware and software I used, since my bay CD Drive was broken. As you can see, I have a lot of handy junk laying around. It helps to live 3 blocks from Micro Center as well.
  • 1x PCMCIA->USB adapter
  • 1x 2GB USB Flash Drive
  • 1x IDE CD/DVD-RW Drive
  • 1x USB -> IDE hard drive enclosure, opened up (to connect the CD Drive)
  • BootX 1.2.2
  • CarbonLib_1.0.4.smi.bin
  • aladdin-expander-6.0.sea.hqx
  • Mac OS 8.1, installed to Mac's HD
  • debian-40r4a-powerpc-netinst.iso, burned to CD
  • Ethernet connection to internet
  • method to transfer files to and from the powerbook (I used a FAT32 formatted CF card in a PCMCIA adapter)

The first step is to get the bootloader installed. I used the BootX bootloader, but for some reason the downloaded .sit files wouldn't expand, except for v1.1.3. I had Stuffit Expander 5, so decided to find an upgrade. I googled around for aladdin-expander-6.0.sea.hqx and got what I needed. However, this required me to download CarbonLib. After that, the .sit files expanded with no problem. The latest BootX at the time of this writing was BootX v.1.2.2.

I placed the BootX App into Control Panels, and the BootX Extension into Extensions.
I tranferred a copy of the /boot/initrd and /boot/vmlinux files from the Etch CD to my Powerbook. I placed initrd.gz and vmlinux in /System Folder/Linux Kernels on my PowerBook. Then I unplugged my PCMCIA cards, rebooted and was presented with the BootX bootloader window. I hit tab to select linux, then I went into Options, and turned SCSI on, and set the ram disk to initrd.gz. I saved the preferences, plugged in both the USB Flash drive and the USB CD Drive to the PCMCIA adapter and booted linux.

I was presented with the Debian installer. Video was a little strange, but I figured I could deal with that later. I had to manually set the CD-ROM device to /dev/sr0 (check the debug console with ALT+F4 for info on your devices if your CD drive isn't autodetected). The ethernet drivers loaded and DHCP assigned an IP, then I partitioned my USB Flash drive (/dev/sda, NOT /dev/hda -> that's MacOS and we need it to boot with BootX). Installation of the core packages took a while with my meager 64MB of RAM.

When installation completed, I opted not to install a bootloader, as I saw reports of issues with quik and the Wallstreet. Instead, I pressed ALT+F4 to open a terminal, and copied /boot/vmlinux and /boot/initrd.img to my web server using netcat. I pressed ALT+F1 to get back to the installer, and let it reboot. I booted into MacOS, and downloaded the ramdisk image and kernel to my Linux Kernels folder, reconfigured BootX for the new kernel, initrd, and root device (/dev/sda), saved the preferences, and rebooted.. voila! A customizable debian has revived this computer. Well, not quite. My PCMCIA-> USB adapter wasn't being registered when the kernel loaded modules from the initial ram disk. So, on my main Linux desktop, I did this, using the initrd.img from the powerbook's copy of Debian.

mkdir /tmp/initrd_ppc/
cd /tmp/initrd_ppc
gunzip < /path/to/ppc/initrd.img | cpio -i --make-directories

Then I plugged in the Flash drive with the Powerbook's Debian on it:

mount /dev/sdb2 /mnt
cp -R /mnt/lib/modules/2.6.18-6-powerpc/kernel/drivers/pcmcia /tmp/initrd_ppc/lib/modules/2.6.18-6-powerpc/kernel/drivers/
cp -R /mnt/lib/modules/2.6.18-6-powerpc/kernel/drivers/usb /tmp/initrd_ppc/lib/modules/2.6.18-6-powerpc/kernel/drivers/

I didn't know what modules I would specifically need, so I just lazily added everything from PCMCIA and added USB core:

echo "rsrc_nonstatic" >> conf/modules
echo "pcmcia_core" >> conf/modules
echo "pcmcia" >> conf/modules
echo "yenta_socket" >> conf/modules
echo "usb_core" >> conf/modules
echo "i82092" >> conf/modules
echo "pd6729" >> conf/modules

Then all I had to do was pack the initrd up again:

find /tmp/initrd_ppc/ | cpio -H newc -o > initrd.cpio
gzip initrd.cpio
mv initrd.cpio.gz initrd-custom.img

Copy initrd-custom.img to the Powerbook's Mac OS partition, have BootX point to it, and you should be able to reboot into Linux. Make sure you pass 'root=/dev/sda2' as kernel arguments (or /dev/whereveryourdebianpartitionis).


PS - I later upgraded to Lenny (current Debian testing) and it went quite well. All i had to do was the standard modification of /etc/apt/sources.list and then a dist-upgrade. Then I just modifed the initrd again. I'm in the process of repurposing the laptop as a videophone and cookie dispenser for my sweet old pit bull mutt while I am at work.



Preventing update abuse

I have been using the free service at to keep tabs on my home server's IP address. However, I replaced my wireless/ethernet router, and the new one did not have built in updating, as my old one did.

I decided to use a software solution on my Debian based server. At first, I tried ddclient, but for some reason, it would stop sending updates after a few hours. Then I tried inadyn, but that caused my hostnames to get flagged for abuse. It seemed that neither of the tools was correctly checking the IP address before attempting to make the update, they were just sending the updates periodically even when my IP hadn't changed. This violates's abuse policy, so I just decided to write a simple wrapper script.

DYNIP=${DYNIP#* has address }

wget -O- 2>/dev/null > /tmp/currentip

echo current ip\: `cat /tmp/currentip`
echo ip on file\: $DYNIP

if [[ \"`cat /tmp/currentip`\" = *\"$DYNIP\"* ]]; then
echo "ip is up to date"
echo "must update"

rm /tmp/currentip

then i set up inadyn as follows:

# /etc/inadyn.conf

--username myuser --password mypass --alias --iterations 1

So now I just have my script running as a cron job once every hour. From my understanding, I shouldn't need this wrapper, but both inadyn and ddclient were mysterously updating my hostname mapping when they shouldn't have. I could very well have configured them wrong, but things looked ok to me and this solution works, so I'll let it be.


Damn Small Linux on a USB-ZIP for Via C3 / Epia Motherboard

The VIA C3 is an x86 compatible chip used in a a bunch of popular and cheap motherboards. It isn't fully instruction-set compatible with the newer intel chips, though, so a lot of the minor and mundane optimizations people use with their compiler will produce binaries that crash when run on the VIA C3. So, I had trouble finding a linux distribution that would actually run. Debian seemed to work, but a lot of the packages in the apt repositories did not.
Eventually, I just wanted to make a little network appliance with the board, but I had trouble getting it to boot from any distributions I installed to a USB flash drive. It turns out that there are some issues booting these motherboards with USB-HDD media. USB-ZIP mode was said to work, though, which basically puts everything on partition 4 and does some strange stuff with the cylinder information. Sounds ok.

I decided to go with Damn Small Linux (4.2.5 in my case) with syslinux as the boot loader, using a FAT filesystem, of course.

So, first thing was to correctly format my Flash drive. From the syslinux/usbboot documentation:

The script "mkdiskimage" which is supplied with the syslinux
distribution can be used to initialize USB keys in a Zip-like fashion.
To do that, calculate the correct number of cylinders (31 in the
example above), and, if your USB key is /dev/sda (CHECK THE KERNEL

mkdiskimage -4 /dev/sd[X] 0 64 32

(The 0 means automatically determine the size of the device, and -4
means mimic a zipdisk by using partition 4.)

After that finished up, I ran:

syslinux /dev/sdb4

to install the bootloader. then it was a simple matter of getting the latest from one of damn small linux's mirrors, and unzipping its contents onto the mounted /dev/sdb4 partition. unmount, stick the USB-ZIP drive i just made into the Via computer, and bang. damn small linux.


Samsung SGH-T509, T-Mobile GPRS, Bluetooth DUN on a Debian GNU/Linux Laptop

My Setup:
  • Asus EeePC with Debian GNU/Linux Lenny/Sid, custom real-time patched 2.6.23 kernel
  • Bluetooth enabled T-Mobile Samsung SGH-T509
  • Zoom USB bluetooth adapter
  • GPRS Internet (T-MobileWeb aka T-zones)
  • installed packages: bluetooth ppp gnome-ppp
Technically speaking, any Bluetooth phone with DUN support should work, but the breadth of hackery here is in the details. For instance, with my phone, doing a scan with 'hcitool scan' produced no results for my t509, although it should have. Once I successfully paired my phone and laptop, I found my DUN channel mostly through guesswork (its on channel 1). The only reliable way I was able to get my phone to dial was by using a patched version of gnome-ppp for ubuntu, run as the root user.

Googling around turned up Using the Palm Treo 650 with Debian GNU/Linux and Modem Script for Samsung t509. Looking through scripts on those pages, I was able to piece together the initialization strings I needed to open a GPRS connection.

My /root/.wvdial.conf is as follows:

[Dialer Defaults]
Modem = /dev/rfcomm0
ISDN = off
Modem Type = USB Modem
Baud = 115200
Init = ATX3
Init2 = AT
Init3 = ATQ0 V1 E1 S0=0 &C1 &D2 +FCLASS=0
Init4 = AT&K3
Init6 =
Init7 =
Init8 =
Init9 =
Phone = *99***1#
Phone1 =
Phone2 =
Phone3 =
Phone4 =
Dial Prefix =
Dial Attempts = 1
Dial Command = ATM1L3DT
Ask Password = off
Password = guest
Username = guest
Auto Reconnect = off
Abort on Busy = off
Carrier Check = off
Check Def Route = off
Abort on No Dialtone = off
Stupid Mode = on
Idle Seconds = 0
Auto DNS = on
;Minimize = off
;Dock = on
;Do NOT edit this file by hand!

To connect just create a menu entry for 'gksudo gnome-ppp' and you should be all set. You will need to use a web proxy to surf the web, and most ports are blocked. Still, it is useful to have internet wherever you have cell phone coverage. T-Mobile has a proxy you can use, google around. If you don't have a /dev/rfcomm0, this may help:



Netcat, the network swiss army knife

What is netcat?

From the official GNU page:

Netcat is a featured networking utility which reads and writes data across network connections, using the TCP/IP protocol.

Have you ever been in a bind, where you need to transfer a file between two networked computers, but neither of them has any file transfer services running? You could install and configure SMB, NFS, or FTP, but if you just need to transfer a few files occasionally, or you are working with very limited system resources, perhaps it is best to just use netcat.

However, netcat is not just a file transfer utility. It’s beauty lies in it’s simplicity; you can use netcat to pipe data across a network, in the exact same way that you can pipe data on a Unix or Windows shell. This makes it extremely simple for novice scripters to transfer any kind of data over the network, even continuous streams of data.

Here’s how to send a file to hostname or IP address ‘foo’, for some port number ‘bar’.

On ‘foo’, run this command:

nc -lp bar > /path/to/save/file/to

Then on the file sender:

cat /path/to/original/file | nc foo bar

So, what else can you do with netcat? Here’s a fun example: on some machine with a microphone connected, and mixer levels set accordingly:

cat /dev/dsp | netcat -d -h foo -p bar

And then on some other machine, ‘foo’, with the firewall configured to allow TCP connections to port ‘bar’:

netcat -lp bar > /dev/dsp

What does this do?

It streams your microphone input to the speakers of ‘foo’. At least, it should in theory. I don’t have a way to test it right now, but let me know if it works for you. It may require slight modification. Careful that the speakers and microphone aren’t in the same room, or you’ll get feedback!

Here’s another fun example: a very tiny webserver (modified example from

printf "Content-Type: text/html\n\n" > ~/mywebpage.html

echo 'hello world' >> ~/mywebpage.html

while true ; do cat ~/mywebpage.html | nc -l -p 80 | head –bytes 2000 >> /tmp/requests ; date>> /tmp/requests ; done

Of course, I can’t test that right now either…

Well, hope you had fun, and I hope it worked. Let me know if you found any modifications that were necessary to get things to work right. Cheers.


synthesizer programming pipe dreams

I have a Nord Modular synthesizer, by Clavia. It is really a fantastic synthesizer; 4 DSPs and there is a nice GUI to create your synth patches with.

There are a plethora of software programs that do the same thing, such as SynthEdit, OpenSoundWorld, MaxMSP, and PureData. I've used them all, and I constantly find myself wishing that there was a more powerful sequencer module built-in to all of these synthesizers. I don't like using multiple programs to make music (sequencer/tracker, audio recording, synthesizer, etc), because I find all the switching modes to be distracting. I like the MSP and PD approach of building it all from scratch and keeping it all together, but the interface is very important to me, and the one thing I don't like to mix are the controls in the same place as the "code behind".

So, early in my computer science career, I decided to write my own modular synthesizer, with a heavy emphasis on the sequencer. First, I played around with C++, then I learned Java, and I tried that, but neither of those languages really seemed very nice for creating a modular synthesizer. I really loved the Scheme programming language, and thought that its functional style and emphasis on tail-recursion would be ideal for DSP and modularity. However, I didn't want to have to build my own MIDI and audio libraries from scratch, and I wasn't a good enough programmer to figure out how to write a foreign-function-interface (once I started mixing C pointers in with Scheme, I just got confused). So, along comes Python. Python has extensive libraries, many related to MIDI, audio, and music, and it has a nice, elegant style somewhat reminiscent of Scheme. I am looking into PySndObj and Csound right now. I'll update here as things progress, if they do.


unix one-liners: sorted filesystem usage

i have a total storage capacity of 6gb in my laptop, so its often necessary to do a little housecleaning. the best way I've found to do this, so far, is to get a list of the directories with the highest disk usage, and sort it for easy viewing. from there, I might see some stray files I don't need anymore that I can dispose.

sudo du -c / | sort -g > sorted

"sudo du -c /" will recursively get directory disk usage for the entire filesystem. I pipe that into "sort -g" which does a generic numeric sort, and then I pipe that into a file called "sorted" which I can then look through at my convenience.


april fools prank: 'when doves cry' on all the office printers' display panels


doves=( "Dig if u will the picture" "Of u and I engaged in a kiss" "The sweat of your body covers me" "Can u my darling" "Can u picture this?" "Dream if u can a courtyard" "An ocean of violets in bloom" "Animals strike curious poses" "They feel the heat" "The heat between me and u" "How can u just leave me standing?" "Alone in a world thats so cold? (so cold)" "Maybe Im just 2 demanding" "Maybe Im just like my father 2 bold" "Maybe youre just like my mother" "Shes never satisfied (shes never satisfied)" "Why do we scream at each other" "This is what it sounds like" "When doves cry" "Touch if u will my stomach" "Feel how it trembles inside" "Youve got the butterflies all tied up" "Dont make me chase u" "Even doves have pride" "How can u just leave me standing?" "Alone in a world so cold? (world so cold)" "Maybe Im just 2 demanding" "Maybe Im just like my father 2 bold" "Maybe youre just like my mother" "Shes never satisfied (shes never satisfied)" "Why do we scream at each other" "This is what it sounds like" "When doves cry" "How can u just leave me standing?" "Alone in a world thats so cold? (a world thats so cold)" "Maybe Im just 2 demanding (maybe maybe Im like my father)" "Maybe Im just like my father 2 bold (ya know hes 2 bold)" "Maybe youre just like my mother (maybe youre just like my mother)" "Shes never satisfied (shes never never satisfied)" "Why do we scream at each other (why do we scream why)" "This is what it sounds like" "When doves cry" "When doves cry (doves cry doves cry)" "When doves cry (doves cry doves cry)" "Dont cry (dont cry)" "When doves cry" "When doves cry" "When doves cry" "When doves cry (doves cry doves cry doves cry" "Dont cry" "Darling dont cry" "Dont cry" "Dont cry" "Dont dont cry")

#55 for doves
while [ 1 ]; do
for (i=0;i<55;i+=1) {
./ \"${doves[i]}\"

This will output the contents of the 'doves' array to the LCD panel on an HP printers in my office. Just swap out the IP address for the IP of some HP printer in your office, and run the script. You can do it from cygwin for windows if you don't have any unix boxen. There was a problem with some of the printers, they would error out after a few minutes, I think the memory was filling up too fast maybe? Who knows. It was fun while it lasted. Maybe I'll work that out for next April.

Of course unix or not, you'll still need bash, perl, and the script at
put the perl script in the same directory as the bash script.

My thanks to the writer of


debian-eeepc suspend issues with networkmanager

I was having issues with NetworkManager being unable to talk to my wireless card after resuming my Eee running Debian (sid) with Xfce4.

I was using the eeepc-acpi-scripts from the main debian repository, and not using the 'zzz' or 'wifi' scripts that some people recommend download, as they caused video issues on resume.

So I made changes to the file at /etc/acpi/actions/ You'll find my modified below:

# do nothing if package is removed
[ -d /usr/share/doc/eeepc-acpi-scripts ] || exit 0
if (runlevel | grep -q [06]) || (pidof '/sbin/shutdown' > /dev/null); then
exit 0
brightness=$(cat $brn_control)
#turn off wireless, stop network-manager
/etc/acpi/actions/ off

/etc/init.d/dbus stop
pm-suspend --quirk-s3-bios --quirk-dpms-on
#picks up here for resume
echo $brightness > $brn_control
#restart dbus (and thus nm), turn wireless back on
/etc/init.d/dbus start
/etc/acpi/actions/ on

you may want to modify to retry turning wireless on until it is successful... i've found sometimes it quits, and it seems unnecessary for it to give up so soon. maybe i'll post those changes later... just ask if you need them.
related links:

About Me

My photo
chicago, il, United States
I'm a software engineer by profession.