Installing BackupPC on OpenWRT

A Tech article with Comments posted 9 July 2009.
Tags: , , , ,

I wanted to have a backup server for my church that would automatically take backups when computers came on to our new wireless network. BackupPC immediately sprang to mind, but it only runs on Linux. How could I get a Linux server into the church in a very low cost way? Answer: An Asus wireless router running OpenWRT.

Keep reading…

Hacker Alarm Clock

A Tech article with Comments posted 25 August 2007.
Tags: , ,

I was at the ELCA Central States Synod Candidacy Retreat with my wife last night, and we realized far too late that we lacked a travel alarm clock. Also lacking an internet connection, it was impossible to download an alarm clock program from the Ubuntu apt repositories. Instead, I quickly coded up this Hacker Alarm Clock in perl. It sounds just like the alarm clock we have at home! Who says that you can’t use a Computer Science degree in ministry? If you can think of other approaches, post them in the comments.


#!/usr/bin/perl

my $s = time();
my $e = $s + (3600 * .005);

print "Starting at: $s\n";

while (time() < $e) {
print "Ending at: $e (".($e-time())." secs from now)\n";
sleep 5;
}
print "Press Control-C (or Mute) to turn off alarm.\n";

open( DSP, '>', '/dev/dsp' );
while (1) { print DSP (\001 x 150); sleep 1; }

Template Toolkit: how to generate static HTML on any path

A Tech article with Comments posted 4 April 2007.
Tags: , ,

My company generates our website using Template Toolkit’s ttree tool. We want our site to be built with absolute paths in the HTML, so we need to be able to accomodate that with file:// URLs when we test it. We use code like this:

The script to invoke ttree in our testing environment:

#!/bin/bash
cd `dirname $0`
rm -r ./out_test/*
ttree -a --relative --pre_process=./lib/config.test \\
         --pre_process=./lib/config.common \\
         --define basedir=`pwd` \\
         -f ./lib/ttree_test.cfg

In lib/config.test:

[% root = 'file://' _ basedir _ '/out_test' %]

In lib/config.deploy (when we build for production):

[% root = 'http://www.ideaworks.com/' %]

This way, rather than hard-coding the testing path in lib/config.test, it Just WorksTM.

The Value of Community, or Why I Love Perl

A Tech article with Comments posted 31 March 2007.
Tags: , , ,

I’ve been asked a number of times recently why I chose to use Perl to develop SAGrader, my company’s flagship essay grading product. I’ll be the first to admit that Perl tends to permit bad (unreadable, unmaintainable, overly terse) code in more ways then, say, Java. I think that those problems are mitigated by keeping to modern best practices in Perl and adhering to a coding standard, but that’s not why I love Perl. I love Perl because of the community.

SAGrader, for example, is only implemented in about 40,000 lines of code, split between actual application code, unit and acceptance tests, and HTML templates. That’s all! But if you ruthlessly reuse code from CPAN, the hub of the Perl community, you can implement computationally intelligent essay grading, a complete website to handle thousands of students, and everything else that goes on behind the scenes to make a website like SAGrader work in very little code and time. While SAGrader may only be 40,000 lines of code, we reuse almost a million lines of Perl from CPAN.

The downside of this much code reuse is that it increases the resident size of your program in memory. Frankly, memory is cheap, and programmer time, effort, and happiness is not. Perl might not be the best tool for every job, but for this job, it’s saved us (without exaggerating) man-years of time and effort.

Using next_successor with Graph::Traversal

A Tech article with Comments posted 17 January 2007.
Tags: , ,

I recently needed to do a graph traversal using the excellent perl Graph library, but I needed to determine the order for visiting new nodes in the fringe myself. Graph::Traversal provides a next_successor attribute which takes a code ref so that you can specify this behavior yourself. Unfortunately, in version 0.80 that feature isn’t well documented, and if you try to use it, you get an “unknown attribute” error. I’ve submitted a patch to enable, document, and test the feature. Now, if you want (for example) to do a breadth-first traversal, but visit the nodes in reverse alphabetical order, you can do this:

Graph::Traversal::BFS->new(
    first_root => 'a',
    pre => sub { print $_[0]; }
    next_successor => sub { (reverse sort keys %{$_[1]})[0]; },
)->bfs;

Dynamic CSS/JS/HTML in Template Toolkit wrappers

A Tech article with Comments posted 19 December 2006.
Tags: ,

I’ve been asked about this a few times on #tt, so I thought I’d provide it for future Googlers. If you’re looking to optionally include certain files in a Template Toolkit wrapper, it’s very easy. You just provide the file names as a parameter to the WRAPPER call.

First, the wrapper file itself, wrapper.tt:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>[% title %]</title>
<body>
[% IF includes %]
    <div id="sidebar">
    [% FOREACH include_file = includes %]
        [% INCLUDE $include_file %]
    [% END %]
    </div>
    <div id="content">
[% ELSE %]
    <div id="wide_content">
[% END %]

[% content %]</div>

</body>
</html>

And then you call the file like this:

[% WRAPPER wrapper.tt
    title = 'My Title'
    includes = [
        'includedfile1.tt',
        'includedfile2.tt'
    ]
%]

<h1>Content for middle</h1>

[% END %]

It’s pretty straightforward to adapt this to CSS or JS files, or whatever you need to customize in the wrapper.

Debugging long-running perl programs in Debian

A Tech article with Comments posted 15 December 2006.
Tags: , , ,

One of the slicker ways I’ve seen of trying to figure out what Perl is doing in a long-running process is defining a signal handler, like so:

use Carp ();
$SIG{‘USR2′} = sub {
Carp::confess(“Caught SIGUSR2: Dumping stacktrace and dieing:”);
};

It works great, dumping the current stacktrace to STDERR. But if you’re stuck in a loop inside the perl interpreter, that user-level signal is never handled, and you don’t get anything. Foiled again! You’re going to have to use (gasp!) the GNU debugger (gdb).

While the advice offered in Debugging mod_perl and Debugging mod_perl C internals is useful, most of the magic with gdb doesn’t work unless you are running a perl with debugging symbols on. How do you get that in Debian-based distributions?

sudo aptitude install perl-debug

Then run the process:

/usr/bin/debugperl path/to/program.pl

Attach gdb:

gdb

attach Process ID

Define the curinfo gdb macro. (see Analyzing the Core File.) If you see “my_perl” in a gdb backtrace, you’re running threaded perl, otherwise use the unthreaded version of curinfo.

(gdb) bt
#0 0xffffe410 in __kernel_vsyscall ()
#1 0xb7f78751 in accept () from /lib/tls/i686/cmov/libpthread.so.0
#2 0×081502de in Perl_pp_accept (my_perl=0×81c1008) at pp_sys.c:2565
#3 0×080d10b3 in Perl_runops_debug (my_perl=0×81c1008) at dump.c:1452
#4 0×08065c9b in S_run_body (my_perl=0×81c1008, oldscope=1) at perl.c:1995
#5 0×08065703 in perl_run (my_perl=0×81c1008) at perl.c:1919
#6 0×0805febd in main (argc=3, argv=0xbfccac44, env=0xbfccac54)
at perlmain.c:98

Looks like we’re running threaded perl, so define curinfo:

(gdb) define curinfo
Type commands for definition of “curinfo”.
End with a line saying just “end”.
> printf “%d:%s\n”, my_perl->Tcurcop->cop_line, \
my_perl->Tcurcop->cop_file
> end

Then use it:

(gdb) curinfo
196:/usr/local/share/perl/5.8.7/Catalyst/Engine/HTTP.pm
(gdb)

That’s what line was executing and what file you were in. It’s worth mentioning that this was not a buggy application, just an ordinary Catalyst application waiting for a connection. Not too exciting for ordinary perl debugging (much easier to run the process as perl -d), but when you’ve got an infinite loop in the perl interpreter (for example, an infinite loop in a regex), this can help point you in the right direction.

My first CPAN acknowledgement

A Tech article with Comments posted 2 October 2006.
Tags: , ,

It’s a small thing, but I’m listed in the acknowledgements for Test::Class, an excellent little xUnit-with-a-decisively-perl-twist module that we use at work. A star is born?