Blog style under construction!

Posted at 9:04PM on Saturday, February 11, 2006 in geekstuff.

How do we look? I'm the middle of restyling the blog and spending some quality time with the CSS spec. All of the archive and search results pages will look a little weird until I get an index page that I'm happy with.

Updated on Saturday, February 11, 2006: Our site rebuild is complete. Refresh yer caches!

Real (AAARRGH) Media

Posted at 8:30PM on Saturday, February 12, 2005 in geekstuff.

Once in a while it becomes necessary to install software to deal with the hideous closed proprietary real media format. Unfortunately there's no utility that will convert real audio format files, so we're stuck with am equally hideous closed proprietary application to play these files. The last time I installed this monstrosity I had to clean thousands of bogus and unwanted entries out of my computer's registry. The player wants to be your web browser, messenging app, and god knows what other kind of app as well. This program is an ad-filled, bloated piece of shit!

Well, if you must re-install this player, at least we have a special version created for BBC listeners that is minus a lot of the the crapware that accompanies the normal product. Seems the BBC, being a publically-funded company, has a special build because of concerns about all the adware garbage in the regular real player build.

PhpNuke Username/IP Tap - follow-up

Posted at 9:57AM on Friday, January 21, 2005 in geekstuff.

The hack previously documented here to help us track activity on a phpnuke site that's been targeted for abuse by a troll has proven to be ineffective. Specifically, it does not record any of the specific actions we want to track. Well, that's not really true -- it does not allow us to quickly cross reference a forum poster's username to his or her IP address. The following code, added right at the beginning of /includes/function_post.php records the identity and originating address of all posts to the site's forums, which is where the site under scrutiny is having it's troll problem.

$dt = date("r");
$uip = $_SERVER["REMOTE_ADDR"];
$uname = $userdata['user_id'];
$sql = "insert into nuke_tap(uname,udate,uip) values('$uname','$dt','$uip')";
$db->sql_query($sql);

$uname, in this new code, is actually the index (user_id) of the posting user's account as found in the nuke_users table. That's good enough for getting the IP address of the poster, which is what we really want.

PhpNuke Username/IP Tap

Posted at 4:55PM on Monday, January 10, 2005 in geekstuff.

I've been asked to identify IP addresses associated with a particular username or two on a phpnuke site. After spending a couple of minutes parsing the code, I have come up with the following scheme to record all username/IP address pairs visiting a site.

Add the following table to the target site's database:

CREATE TABLE nuke_tap (
  ndx int(11) NOT NULL auto_increment,
  uname varchar(100) NOT NULL default '',
  udate varchar(100) NOT NULL default '',
  uip varchar(100) NOT NULL default '',
  PRIMARY KEY  (ndx)
) TYPE=MyISAM;

In /mainfile.php, function online(), insert the following code:

$dt = date("r");
$sql = "insert into nuke_tap(uname,udate,uip) values('$uname','$dt','$ip')";
$db->sql_query($sql);

This will dump all accessing username/IP address pairs to the nuke_tap table.

Warning! This table will grow rapidly depending on the activity of the target phpnuke site.

There is no interface to this data at all besides the MySQL command line utilities, or, if you're lucky, phpMyAdmin.

The state of the personal computer industry, December 2004

Posted at 11:29PM on Sunday, December 26, 2004 in geekstuff and musings.

I noticed this at the end of a New York Times article about the greyline dealings of some entrepenureal internet marketeers. This poor guy has the same problems as just about everyone else who owns a windoze computer. I liked the way the NYT website capitalized `random' with effect.

John Morgan, 51, owner of a truck brokerage service in Columbia, S.C., said the onslaught of e-mail messages that he had received after filling out forms related to a Consumer Research offering overwhelmed the computer he used to run his business.

Maybe you shouldn't give your e-mail address out to anyone unless you have a legitimate reason to do so? I suppose the "consumer research site" has no problem selling your e-mail address to spammers. Didn't you read the fine print? At the very least use a throwaway e-mail address that has off-site storage instead of your business computer.

RANDOM spam filled the in-box he relies on for orders, and legitimate e-mail messages got lost, he said. The situation worsened when he tried to use the "unsubscribe" option on a spam note. He said his computer locked up, and after it was restarted, files began opening 50 to 60 times in row and the computer ran at a crawl.

Don't use Internet Exploder. Don't use Outlook Express. Don't click on unsubscribe requests. You have been 0wn3d by the spammers. Don't blame "consumer research" for your stupidity, unless their web site says explicitly that their website will not give or sell your e-mail address to spammers.

Of course, it could be another spammer from another place where you dropped your business e-mail address on the internet who is ultimately responsible for making all that malware appear in your inbox and your web browser.

Although ultimately the company assisted him in efforts to eradicate the spam, he said, it has remained a problem. "Once it gets put into all these systems, there's nothing on God's green earth that will stop it," he said.

I guess I've been too hard on you. No problem, I'll reformat yer hard disk. I strongly suggest that you change yer e-mail address and take greater care protecting yerself in the future. Did you wanna save any files before I give this computer a frontal lobotomy?

radio Obscura 2 loses it's way

Posted at 10:31PM on Wednesday, November 24, 2004 in geekstuff and musings.

The original radio Obscura machine has suffered a hardware fault and is offline. This private webcast machine is somewhat notorious as having originated the wbcq.com "after hours" webcast reliabily every day for at least two years. Today the machine was sitting at one of those ominous boot prompts that said something like "press F1 to continue or press F2 to specify boot device" where no hard disk drives were recognized by the system's BIOS. Bummer.

I had anticipated this system's imminent failure, as it's boot disk has been making strange sounds for some time, although Microsoft Windows 2000 Advanced Server was not able to detect the ominous sounds or any errors of any kind originating from the soon-to-crap-out hard disk drive. I figured I'd just let it run 'til it was done and see what happened.

A cold boot brought back the operating system, so the system is not quite failed. However I thought it was prudent to power down the machine and let it rest for the extended weekend while we tried to find a replacement drive. After all, we migrated the bulk of radio Obscura to a new machine back in the summer, and this system was doing beta tests for the new version of SAM and relaying a nice random feed of Hour of Slack episodes and the occasional Radio Free Euphoria show -- so we didn't lose any data at all, just this server's webcast.

I sometimes get nostalgic when long running servers start to die, especially those that have faithfully served their mission reliably for a long time. Two years of constant service is not too bad for your typical souped up desktop Dell machine, but under conditioned power and safe corporate surroundings, I am a bit disappointed that the disk drive wasn't reliable enough to go for some real uptime records.

And now, video

Posted at 3:09PM on Wednesday, August 18, 2004 in entertainment and geekstuff.

Well, Scott came home from an extended business gig in the desert, and discovered that his local fone company had chosen him to be the pilot test case for fiber optic to the premises. Sure enough, he ran a bandwidth test and comes back drooling all over himself with his nice 2Mbps downlink and uplink capacity to the 'net.

Now, as all good hackers, we know what happens next. How to test out this seemingly incredible underutilized bandwidth? Let's first add big fat shoutcast relays to our existing internet audio properties. What about video? Where are all the high bandwidth video stream sites? How many 800K video streams can we run concurrently off a single super-broadband connection?

The developers that brought us Winamp and Shoutcast (sadly minus creator Justin Frankle, who departed AOL recently), have been working on a next generation streaming format that is surprisingly easy to implement.

This new format, called Nullsoft Streaming Video (NSV), is fully supported by the latest generation of the Winamp media player, and NSV streams can be served up by the same Shoutcast streaming server software that has been providing the means of distribution for thousands of internet broadcasters for several years.

Scott downloaded, installed and configured a video server using NSV GUI from scvi.net. After just a few hours of hacking, a stable setup is up and running classic television and film from Scott's new bandwidth farm.

Check it out at www.katiebecker.com and click on the (now somewhat inappropriately named) "Listen Live" link. The future is here.

Blog comments and spam

Posted at 11:12AM on Wednesday, June 9, 2004 in geekstuff.

I have completed a software upgrade here to the latest and greatest version of Movable Type. The only major change is that comments will now have to wait for approval before appearing. Don't worry, I do not plan to censor any appropriate or on-topic material. But if you are a robot blog spammer, kiss your ass goodbye because your advertising for pornography, penis enlargement, or other scams will never show up here again.

Force a stream title update

Posted at 9:45PM on Tuesday, May 18, 2004 in geekstuff.

Here is some PAL code to force a stream title update. This is especially useful for live broadcasts.

var Song : TSongInfo;

Song := TSongInfo.Create;

Song['artist'] := '975 Pirate Radio';
Song['title'] := '**** Special Live Broadcast ****';
song['duration'] := 300*60*1000; {30*60*1000 = 30 minutes}

Encoders.SongChange(Song);

Song.Free;

Switching between line input and archive

Posted at 4:33PM on Thursday, May 13, 2004 in geekstuff.

Here are the two PAL scripts I use to switch between line fed programming and the traditional hard disk drive archive.

{ startlive.pal

switch to line fed input, immediately
}

var thePlayer: TPlayer;

PAL.LockExecution();
thePlayer := ActivePlayer;
Queue.Clear;
Queue.AddFile('mic://',ipTop);
thePlayer.FadeToNext;
PAL.UnlockExecution();

{
stoplive.pal

switch to archive input, immediately
}

var thePlayer: TPlayer;

PAL.LockExecution();
thePlayer := ActivePlayer;
thePlayer.FadeToNext;
PAL.UnlockExecution();

Die, blog spammers

Posted at 11:30AM on Tuesday, April 6, 2004 in geekstuff.

I am starting to spend an inordinate amount of time santizing spurious comments from scumbags who abuse the comments feature of my blog in an attempt to get free advertising for their worthless products. Effective immediately I will be more carefully monitoring if and when an article allows comments, and if you try to post a comment on my blog after a certain short time your IP address will be banned.

I really hate to do this, but I want to do more to keep the scumbag blog spammers away from this place. MovableType has promised some enhancements to comments authorization with an upcoming release, and hopefully this will allow us to stay one step ahead of the scumbags.

Automatically running serialized content in order over time

Posted at 1:40PM on Sunday, February 22, 2004 in geekstuff.

Consider an archive of serialized content that we want to run on our internet radio station, in order, over time. An example of a serialized show is the classic Adventures of Superman radio show. Starting with the twentieth episode, this show began to use a multi-part serialized format, with new episodes airing every two or three days.

We would like to run the Superman shows in order at pre-programmed times using SAM's event scheduler. Here we will present one possible way this can be done.

First we need to create a SAM category called 'adventures of superman' and fill it with content. We will assume the Superman show files are named in such a way so that when the list of files is sorted the shows will be in chronological order, e.g.

400322 18 Mystery of Dyervi.mp3 400325 19 Mystery of Dyervi.mp3 400327 20 Mystery of Dyervi.mp3 400329 21 Mystery of Dyervi.mp3 400401 22 The Emerald Of Th.mp3 400403 23 The Emerald Of Th.mp3 400405 24 The Emerald Of Th.mp3 400408 25 The Emerald Of Th.mp3 400410 26 The Emerald Of Th.mp3 400412 27 The Emerald Of Th.mp3 400415 28 Donelli's Protect.mp3 400417 29 Donelli's Protect.mp3 400419 30 Donelli's Protect.mp3 400422 31 Donelli's Protect.mp3 400424 32 Donelli's Protect.mp3 400426 33 Donelli's Protect.mp3

The PAL script we will use to allow us to run these radio shows in order over time assumes that the files are named so if sorted they're in chronological order with the oldest show listed first.

We will make use of a column in an existing SAM table to flag the most recently played show. We've picked the 'info' column in the songlist table for use here. This column is accessible in SAM under the 'comments' tab in the song information editor. We will be tagging the most recently played show by placing the string 'most recent' in that track's info field. The script will clear this data when a new track is selected.

The script that plays the show will check for the 'most recent' tag associated with a track entry, queue the file immediately following this one in the sorted list, and update the value for the file just queued. If the tag isn't found associated with any files, we can assume we're at the beginning of the run and we will queue up the first file in the list. Likewise if the 'most recent' tag is the last track in the list, we'll assume we're at the end of the run and queue up the first track.

{ serial.pal - play serialized content in order over time written by cosmikdebris at rfma dot net on February 22, 2004

usage notes:

1. assumes the 'target category' exists and is filled with content

2. the content file names should be named so that when the file list
is sorted the files appear in chronological order, with oldest first

3. this script uses the 'info' colum in the sam database, aka the
'comments' tab in the song information editor dialog box in SAM

4. this script is designed to be run from sam's event scheduler
}

const targetCategory = 'adventures of superman';

var getCategoryID : String;
var targetCategoryID : Integer;
var q: TDataSet;
var r: TDataSet;
var getTrackList : String;
var foundMostRecent : Boolean;

foundMostRecent := False;
getCategoryID := 'select id from category where name = ''' + targetCategory + '''';
q := Query(getCategoryID,[],True);
if q.EOF then
begin
WriteLn('target category ''' + targetCategory + ''' was not found.');
end
else
begin
q.First;
WriteLn('found target category ' + IntToStr(q['id']));
getTrackList :=
'select songlist.id,songlist.filename,songlist.info ' +
'from songlist,categorylist ' +
'where songlist.id = categorylist.songid ' +
'and categorylist.categoryid = ' + IntToStr(q['id']) + ' ' +
'order by songlist.filename';
q := Query(getTrackList,[],True);
if q.EOF then
begin
WriteLn('no matching tracks in the target category');
end
else
begin
q.First;
while not q.EOF and not foundMostRecent do
begin
if q['info'] = 'most recent' then
begin
WriteLn('found most recently played track ''' + q['filename'] + '''');
foundMostRecent := True;
{ clear most recent tag in the current track }
r := Query('update songlist set info=NULL where id = ' + IntToStr(q['id']), [], True);
{ get the next track }
q.Next;
if q.EOF then
begin
q.First;
end;
WriteLn('queuing track ''' + q['filename'] + '''');
Queue.Clear;
Queue.AddFile(q['filename'],ipTop);
{ update the most recent tag for the current track }
r := Query('update songlist set info=''most recent'' where id = ' + IntToStr(q['id']), [], True);
end;
q.Next;
end;
end;
end;

Selectively disabling regularly scheduled events in SAM

Posted at 12:17PM on Saturday, February 14, 2004 in geekstuff.

SAM offers the ability to execute regularly scheduled events. We've made use of this to run regularly scheduled special broadcasts, e.g. the Canvas Prog Hour, Lumpy Gravy, and KBLU, Doc's new blues show; and perform other regularly scheduled tasks, such as downloading and queuing up network news on the hour.

The current version of SAM does not provide the ability to temporarily disable scheduled events without physically removing them. Doc's 91.9 FM gig is an experimental station, and does on occasion have the need to disable one or more of the regularly scheduled events. For example, an impromptu live show may happen, and it will mess with the host if SAM decides to download and queue the network news in the middle of a previously created live playlist.

The following enhancement to SAM provides a set of small PAL scripts, a database enhancement, and modifications to existing PAL scripts to facilitate quickly and easily disabling or enabling the execution of PAL scripts tied to SAM's event scheduler.

This script creates a new table in SAM's database that will store the current status of events tied to PAL scripts. After the table is created, the script queries the event scheduler table for all events that are tied to the execution of a PAL script. An entry for each of these events is then added to the new event status table, and each entry is marked 'active'.

{ initialize_event_status.pal }

const createQuery : String =
'CREATE TABLE eventstatus (' +
' name varchar(255) NOT NULL default '''',' +
' status varchar(255) NOT NULL default '''',' +
' PRIMARY KEY (name)' +
' ) TYPE=MyISAM';

var i : Integer;
var programs : TDataSet;

{ create the event status table }
Query(createQuery,[],True);

{ get a list of all events where a PAL script is executed }
programs := Query('select name from event where action = ''PAL''',[],True);
programs.First;

{ for each PAL event found, add a row in the eventstatus table }
while not programs.EOF do
begin
Query(
'insert into eventstatus (name, status)' +
'values (''' + programs['name'] + ''', ''active'')',[], True);
programs.Next;
end;

Here are a pair of scripts that respectively enable and disable the running status of all events tied to PAL scripts.

{ enable_all_events.pal }

PAL.LockExecution;
Query('update eventstatus set status = ''active''', [], True);
PAL.UnlockExecution;

{ disable_all_events.pal }

PAL.LockExecution;
Query('update eventstatus set status = ''inactive''', [], True);
PAL.UnlockExecution;

Similar scripts can be created to enable and disable the execution of individual scheduled events, e.g.

{ disable_network_news.pal }

PAL.LockExecution;
Query('update eventstatus set status = ''inactive'' where name = ''network news''', [], True);
PAL.UnlockExecution;

To make use of the system, modifications need to be made to each of the PAL scripts tied to scheduled events. This is pretty straightforward - all we have to do is check the event status table entry for the status associated with the particular action we want to run. If the event status is 'inactive' we don't run the event; otherwise the event processing is done as normal. The following example shows how this is done for an event called 'run racing news':

{ run racing news.pal }

var status : TDataSet;
const name : String = 'run racing news';

status := Query('select status from eventstatus where name = ''' +
name + '''', [], True);

status.First;

if status['status'] = 'active' then
Queue.AddFile('e:\racingnews\garagepass.mp3',ipTop)
else
WriteLn('download racing news event is disabled');

This screen grab shows the system up and running. The PAL scripts used in this article are compiled in this archive for your convenience.

The on-demand archive

Posted at 2:23PM on Sunday, February 8, 2004 in geekstuff.

Now that we have a reasonably stable setup for sharing WBCQ's programming to a worldwide listing audience on the internet, we had an idea about providing an on-demand archive of past programming to our listeners. Our idea is based on the cool setup that's being done by Georgia Tech's WREK. WREK's web site presents a schedule grid with hyperlinks for each program initiating playback of the most recent program.

There are all kinds of applications we can develop to make the on-demand archive useful. For example, we could link the Annotated WBCQ Program Guide with the archive. But first we need to get the basic archive mechanism developed. This turns out to be relatively easy.

Basic assumptions:

  • Our live webcast runs from about 3:45pm through 12:15am daily, except for a couple of days a week when programming runs late (i.e. the excellent Juliet's Wild Kingdom Sunday morning at 1:00am ET) and early (the Rabbi starts at 2PM on Sundays). For purposes of the proof of concept system we will be archiving every day between 3PM and 2AM ET.

  • Most programming starts at the top of the hour and runs for an hour. Of course there are quite a few exceptions, but to keep things simple for the prototype we will split archive entries into sixty minute blocks.

  • The source webcast is a low bandwidth 16K mono stream, since Monticello is using a dial-up to get the programming to the internet. Each hour of programming will consume about 7 MB of disk space, which works out to about 77 MB per day, or roughly 2 GB per month. (An 80 GB hard disk drive dedicated to the archive could hold over three years of programming!) For now we will assume that a human operator will periodically backup/purge the oldest programming to keep the hard disk from filling up.

  • Our host platform for this project is Windows 2000 Professional.

We picked the excellent StreamRipper to save each hour's programming to file. More specifically, we will be using the console version of StreamRipper, which is described in a tutorial on the creators' site.

To manage the hourly stream rip, we picked pycron, an excellent scheduling service with a nice graphical front end to managing scheduled events. cron-like scheduling is somewhat easier than using the native Windows scheduler.

Here's a picture of the schedule database we created to do the hourly stream rip. This tells the scheduler service to execute the batch file archive.bat every hour on the hour between 1500 (3PM ET local time) and 0100 (1AM ET local time).

The batch file itself looks like this:

@echo off

for /F "tokens=1-4 delims=/- " %%A in ('date/T') do set DATE=%%D-%%B%%C
for /F "tokens=1-4 delims=:., " %%a in ('time/T') do set TIME=%%a%%b%%c

set ARCHDIR=c:\archive\%DATE%-%TIME%
md %ARCHDIR%
cd %ARCHDIR%

consolewin32 http://192.168.1.9:7415 -l 3780 -d %ARCHDIR% -s

The date/time manipulations are adapted from examples at this useful batch programming archive site. The archive directory is based on the current date and time, so, for example, the script executed at 3PM on Sunday, February 8, will have the name '2004-0208-300p'.

consolewin32 is the command line stream ripper. The parameters we use are decoded as follows:

  • http://192.168.1.9:7415 is the URL of the shoutcast server we're ripping from.

  • -l 3780 tells StreamRipper to run for 63 minutes. The additional time accounts for the fact that the stream runs about 1 to 2 minutes behind the live broadcast.

  • -d %ARCHDIR% tells StreamRipper to place it's output in the directory named by date and time as described above.

  • -s tells StreamRipper not to create a directory for each stream it rips.

This completes the proof-of-concept for the archive system's back end. Next we need to place a web interface on this system to make it a really useful on-demand archive.

Canvas Prog Hour script

Posted at 9:22PM on Saturday, January 31, 2004 in geekstuff.

This script chooses a random Canvas Prog Hour show and appends each part of the show to the queue in file name order.

The shows are named accoring to the following format:

cph111part1.mp3

where 111 represents show number (111) and part number (1).

In case the random show number does not exist, another random show in the range 0..showCount will be selected until a match is found.

To protect from a runaway loop, in case, for example, something bas has happened and there are no matching shows, the loopCount variable and maxLoop constant are used to stop execution after (maxloop) tries.

{ canvas prog hour.pal

written on January 24, 2004 by cosmikdebris at rfma dot net
}

const showCount : Integer = 200;
const maxLoop : Integer = 30;
var target : Integer;
var targetStr : String;
var queryStr : String;
var data : TDataSet;
var selected : Boolean;
var loopCount : Integer;

PAL.LockExecution;

selected := False;
loopCount := 0;

while not selected do
begin

Randomize;
target := RandomInt(showCount);
targetStr := IntToStr(target);
WriteLn('I have chosen ' + targetStr);

queryStr :=
'select filename from songlist where filename like ' +
'"%cph' +
targetStr +
'%" order by filename';

data := Query(queryStr, [], True);

if not data.EOF then
begin
Queue.Clear;
while not data.EOF do
begin
WriteLn(data['filename']);
Queue.AddFile(data['filename'],ipBottom);
data.Next;
end;
selected := True;
end;
loopCount := loopCount + 1;
if loopCount > maxLoop then
selected := True;
end;

data.Free;
PAL.UnlockExecution;

Blog spammers

Posted at 10:20AM on Wednesday, January 28, 2004 in geekstuff.

A blog spammer hit us last night and left 266 identical comments advertising some kind of internet scam.

Fortunately there is a quick way to deal with these people:

delete from mt_comment where comment_author like '%video%'

This site's occasionally been hit with random spam entries in article comments, which are easily purged manually. This is the first time we've been flooded with spam. I do not want to turn off comments unless I must.

movabletype.org has released an interim release (v2.661) to help along with this issue, which installed quickly and painlessly.

Goodbye, scumbag spammers!

Random category playlist tricks

Posted at 2:29PM on Monday, January 26, 2004 in geekstuff.

Here is another script for SAM that will pick selections in a particular category, in random order, and add the tracks to the queue. The script will continue to add tracks until the sum of the tracks' duration hits a pre-defined limit. This is really useful for special programming. I am using this script to queue up an hour's worth of Firesign Theater on our station during it's special slot on the weekends.

A couple of special points worth mentioning:


  • Track duration in SAM's songlist table is specified in milliseconds, so to play an hour we add up track durations until they reach 3,600,000 (1000*60*60).
  • The sample script below grabs from the category named 'weird wild stuff' and clears the queue before adding new tracks.
  • This script can be run at pre-programmed times using the event scheduler, or manually as desired.

{ weird wild stuff.pal }

const category : String = 'weird wild stuff';
var show, trackList : TDataSet;
var duration : Integer;

show := Query(
'select id, name from category where name like ''' + category + '''' +
' order by rand() limit 1',[],True);
WriteLn('Playing show ' + show['name']);

trackList := Query(
'select songlist.filename, songlist.duration' +
' from categorylist, songlist' +
' where categorylist.songid = songlist.id' +
' and categoryid = :sid' +
' order by rand()',[show['id']],True);

PAL.LockExecution;
trackList.First;
duration := 0;
Queue.Clear;
while not trackList.EOF do
begin
if (duration + trackList['duration'] < 3600000) then
begin
WriteLn('Adding track ' + trackList['filename']);
Queue.AddFile(trackList['filename'],ipBottom);
duration := duration + trackList['duration'];
end;
trackList.Next;
end;
PAL.UnlockExecution;

trackList.Free;
show.Free;

A variation on the "play scheduled show" theme

Posted at 2:28PM on Saturday, January 17, 2004 in geekstuff.

I noticed that the SQL query that selects a random "Lost Discs Radio Show" for play at a scheduled time on radio Obscura was choosing show number one more often than it should when the selection script runs at 5PM daily. This may be a bug in the MySQL rand() function used to select the show. Perhaps the function uses the system time to seed the random number chosen, and since the script runs at the same time every day, show number one is picked more than it should be.

The Lost Discs Radio Show is a great obscure oldies show that runs on Friday evenings on WBCQ. The shows hosts have graciously made available MP3 archives of past shows available to their listeners, so I added a regular broadcast of past shows to radio Obscura's schedule, which is simulcast on Dr. Becker's wbcq.com stream when WBCQ 7415 is off air. The MP3 archives consist of two files per show, so I can't use the much easier method of adding a random file via a clockwheel script in SAM.

The following script picks a random show and adds the show in order to the playlist queue. The script also takes into account a missing show. Not all of the Lost Discs shows are available on the archive, so there will be times when the script picks a show that does not exist in our local archive. Also, something bad may have happened and there may be no shows in the database. So this script will try to find a matching show up to ten times before aborting.

{ lostdiscs.pal

This script chooses a random lost discs radio show
and appends each part of the show to the queue in
file name order.

The shows are named accoring to the following format:
Lost Discs Radio Show - 01-1.mp3
where 01-1 represents show number (01) and part number (1).

In case the random show number does not exist, another
random show in the range 0..showCount will be selected
until a match is found.

To protect from a runaway loop, in case, for example,
something bas has happened and there are no matching shows,
the loopCount variable is used to stop execution after ten
tries.
}

const showCount : Integer = 90;
var target : Integer;
var targetStr : String;
var queryStr : String;
var data : TDataSet;
var selected : Boolean;
var loopCount : Integer;

PAL.LockExecution;

selected := False;
loopCount := 0;

while not selected do
begin

Randomize;
target := RandomInt(showCount);
targetStr := IntToStr(target);
if (target < 10) then
begin
targetStr := '0' + IntToStr(target);
end;
WriteLn('I have chosen ' + targetStr);

queryStr :=
'select filename from songlist where filename like ' +
'"%Lost Discs Radio Show - ' +
targetStr +
'%" order by filename';

data := Query(queryStr, [], True);

if not data.EOF then
begin
Queue.Clear;
while not data.EOF do
begin
WriteLn(data['filename']);
Queue.AddFile(data['filename'],ipBottom);
data.Next;
end;
selected := True;
end;
loopCount := loopCount + 1;
if loopCount > 10 then
selected := True;
end;

data.Free;
PAL.UnlockExecution;

Special show broadcast automation

Posted at 12:51PM on Tuesday, January 6, 2004 in geekstuff.

Here again is another script that automates playing special pre-programmed content using Spacial Audio's SAM.

This script choose random category with name starting with a certain string
of characters and play all selections in the chosen category in order. It's based on older scripts that loop forever waiting for particular dates and times to run. The date/time loop has been removed and now execution is scheduled using the event scheduler in SAM 2.7.7 or higher. Earlier examples using logic like this can be found in Festerhead's example in Spacial Audio's knowledge base.

Canvas Prog Hour is a very cool progressive music show produced by Canvas Productions. Canvas Prog Hour is distributed as four MP3 files, each running about 30 minutes in duration. The individual episode files are named sequentially. We have dozens of Canvas Prog Hour shows in the archive. At a certain time we want to pick a random Canvas Prog Hour show from the archive and play each of the tracks in order.

Now for the implementation. Using the example above, create SAM category folders for each Canvas Prog Hour show. Name the category folders so that each folder starts with the characters 'cph' followed by the show index, i.e. the four MP3 files making up Canvas Prog Hour show 150 will be stored in the SAM category folder 'cph150'. Assign the constant 'category' below to 'cph'. The PAL script will choose a random category with name beginning with 'cph', clear the queue, and queue up the tracks in this category in order.

This is also useful for playing an album from beginning to end, assuming the tracks are named in order. On radio Obscura we have a Grateful Dead show with categories named by show/date and tracks named sequentially in performance order.

The script follows. This screen grab shows the script in action.

{ catplay.pal }

const category : String = 'gd';
var show, trackList : TDataSet;

show := Query(
'select id, name from category where name like ''' + category + '%''' +
' order by rand() limit 1',[],True);
WriteLn('Playing show ' + show['name']);

trackList := Query(
'select songlist.filename' +
' from categorylist, songlist' +
' where categorylist.songid = songlist.id' +
' and categoryid = :sid' +
' order by songlist.filename',[show['id']],True);

PAL.LockExecution;
trackList.First;
Queue.Clear;
while not trackList.EOF do
begin
WriteLn('Adding track ' + trackList['filename']);
Queue.AddFile(trackList['filename'],ipBottom);
trackList.Next;
end;
PAL.UnlockExecution;

trackList.Free;
show.Free;


Overlay a station ID with PAL

Posted at 12:19PM on Friday, December 12, 2003 in geekstuff.

Here's a PAL script that overlays a station ID on top of a running stream. This script can be invoked manually from the SAM interface, or programmed at certain times using the event scheduler that's been added with SAM 2.7.7.

{ overlay a station id }

var tunePlayer : TPlayer;
var stationID : TSongInfo;
var tuneVolume : Integer;

stationID := CAT['Station IDs (All)'].ChooseSong(smRandom,NoRules);
SoundFX.QueueSong(stationID);
tunePlayer := ActivePlayer;
tuneVolume := tunePlayer.Volume;
tunePlayer.Volume := tuneVolume / 2;
SoundFX.Play;
tunePlayer.Volume := tuneVolume / 3;
tunePlayer.Volume := tuneVolume / 4;
while (SoundFX.Status = 0) do;
tunePlayer.Volume := tuneVolume / 3;
tunePlayer.Volume := tuneVolume / 2;
tunePlayer.Volume := tuneVolume;

Fun with the iTrip

Posted at 6:56PM on Sunday, December 7, 2003 in geekstuff and music.

After two or three months on backorder, the iTrip FM transmitter accessory for my iPod MP3 player arrived on Friday. It took so long that my 30GB iPod is now obsolete, having been replaced by a 40GB model.

There are a number of disheartening reviews about the iTrip on the 'net, but I can honestly say that I am impressed with this tiny accessory. Sure, sound quality is nowhere near line input, and it's a Part 15 device so it's coverage is rather limited, but it's a mini radio station and it works!

Here are a couple of config notes. I long ago removed the horrible MusicMatch software that is the standard iPod synchronization app for Windows users. I much prefer MediaFour's XPlay to the crappy MusicMatch. Unfortunately Griffith's iTrip software assumes you are running MusicMatch and refuses to install without it.

However there is an easy workaround for this. iTrip configurations, such as the transmit frequency and LED status, are set by tone combinations. For example, there's a little MP3 called "87.9.mp3" that plays the tones that set the iTrip to it's default 87.9FM (coincidentally this is the default frequency for Radio Free Mount Aity, but I digress). Fortunately the iTrip installation CD has all the little MP3s to set frequency and turn on and off the LED in uncompressed form. So it's really trivial to copy them to the iPod and create a iTrip playlist.

Installing MySQL support into PHP 4 on OpenBSD

Posted at 6:10PM on Monday, October 27, 2003 in geekstuff.

Now, I've done this a couple of dozen times and I always forget this last crucial step, I'm documenting this tip here now to help me avoid wasting hours of valuable time in the future. Here's how to activate MySQL support in PHP using the package library that comes with OpenBSD.

The OpenBSD and packages are from version 3.4-current:

OpenBSD 3.4-current (GENERIC) #49: Tue Oct 21 19:43:54 MDT 2003

We will be adding php and php-mysql packages using the pkg_add(1) command, and using the phpxs command to activate and deactivate the modules in the configuration file php.ini.

# pkg_add php4-core-4.3.3.tgz # /usr/local/sbin/phpxs -s # cp /usr/local/share/doc/php4/php.ini-recommended /var/www/conf/php.ini # pkg_add php4-mysql-4.3.3.tgz # /usr/local/sbin/phpxs -a mysql

I found this tip in the PHP OpenBSD Installation Guide, duh.

Sweepers, jingles, and special programming

Posted at 7:59AM on Monday, October 27, 2003 in broadcast media and geekstuff.

The default playlist rotation scheme in SAM provides for weighted rotation of musical selections using a mini-PAL script inside the "Category Playlist Rotation Logic Module." This can be viewed and changed under SAM's config menu, under "Playlist Rotation Rules." The default rules are as follows:

Cat.QueueBottom('Tracks',smLRP, prEnforceRules); Cat.QueueBottom('Music (All)',smWeighted, prEnforceRules); Cat.QueueBottom('Music (All)',smLemmingLogic, prEnforceRules);

In "Auto" Mode (unattended operation), SAM will run each line of this script in order to fill the queue with selections. Notice that the second and third lines do not restrict picking selections from the "Tracks" category. This explains why special programming assigned to a different category than "Tracks" will show up in the queue if one forgets to assign the selections a type besides the default "S" (for Songs == Music).

To play a jingle after every third song, first add all your station jingles to the playlist and assign them type "J". Next, add a line to the playlist rotation module config like this:

Cat.QueueBottom('Jingles (All)',smRandom, prNoRules);

This directs SAM to "grab a random jingle, ignoring any rotation rules, and place it in the queue."

If you have only a few jingles you will want to use the prNoRules directive or else a global rotation rule may prevent a jingle from being played. The default rotation rules are

  • Do not play the same artist within 120 minutes
  • Do not play the same song within 240 minutes

The GUI in SAM config makes adding to and changing the playlist rotation module logic really easy, and all kinds of creative things can be dreamt up using custom defined categories.

More broadcast automation with PAL

Posted at 2:37PM on Saturday, October 18, 2003 in geekstuff.

Here is a script for SAM that facilitates the scheduling and play of a web stream every hour at a pre-determined time and duration.

// Schedule, start, play, and stop a remote webcast every hour // Written by Larry Will (cosmikdebris@zappahead.net) // Copyright © 2003 Becker Broadcast Systems // Freely distributable as long as this header remains unmodified // Yowza. // // Version 1.0 October 18, 2003

PAL.Loop := True;

// pick the URL of the webcast
const streamURL : String = 'mms://66.250.32.204/usaradio';

// pick the start and end times (minutes after the hour)
// that the stream should run every hour
const startTime : String = '12';
const endTime : String = '13';

var n : Integer;
var startPlay : String;
var endPlay : String;
var theActivePlayer : TPlayer;
var queueEntry : TSongInfo;

n := 0;
startPlay := 'XX:' + startTime + ':00';
endPlay := 'XX:' + endTime + ':00';
while n < 24 do begin
PAL.WaitForTime(T[startPlay]);
Queue.AddFile(streamURL, ipTop);
theActivePlayer := ActivePlayer;
theActivePlayer.FadeToNext;
PAL.WaitForTime(T[endPlay]);
theActivePlayer := ActivePlayer;
theActivePlayer.FadeToNext;
Query('DELETE FROM songlist WHERE title = :streamURL', [streamURL], True);
end;

Shoutcast cutover script using winbatch

Posted at 8:41PM on Thursday, August 28, 2003 in geekstuff.

We have two shoutcast sources and one server. One source appears around 4pm daily with live programming from the console of a remote radio station. We want to play this source (the "live" source) on the shoutcast server until 1215am on weekdays, 130am on Saturdays, and 1245am on Sundays. At all other times we want to play the second source (the "after hours" source). The shoutcast sources are hundreds of miles apart and are both distant from the shoutcast server.

Background: The Shoutcast server software is completely passive and is run from a config file in two possible modes: it can sit and wait for a source, or grab a relay, i.e. from another shoutcast server.

The shoutcast source can be Winamp 2 with a Shoutcast DSP Plug-in for Winamp, or programmable broadcast automation warez capable of streaming to a shoutcast server, such as SAM.

Solution 1: Install a new shoutcast server on the after hours source machine and point the source to the local shoutcast server.

Setup two config files for the shoutcast server, one as a relay to the new server we just set up, the other as a passive server.

Program a Winbatch script on the primary shoutcast server as follows:

  1. Wait til 4pm.

  2. Kill the shoutcast server.

  3. Load the shoutcast server in passive mode.

  4. Wait til 1215am (during weekdays) or 130am (Saturdays) or 1245am (Sundays)

  5. Kill the shoutcast server.

  6. Load the shoutcast server as a relay to the new secondary shoutcast, and repeat.

This is a rather inelegant approach as it kicks all listeners during the transition between the two sources.

Solution 2: Program a winbatch script on the after hours source system to start the shoutcast relay at 4pm, and stop it after midnight at the respective times noted above.

This solution doesn't require kicking the shoutcast server twice a day, so the listeners can stay connected during the tranisition. However, care must be taken to ensure that both sources stream at the same bitrate and encoding scheme or else weird things will happen.

Implementation notes: Might need to slip all times a couple of minutes late to account for the delay in encoding and transmitting the streams.

243 days uptime, busted by a power failure

Posted at 10:18PM on Thursday, August 14, 2003 in geekstuff and musings and openbsd.

My intranet web server running OpenBSD 3.0 was up for 243 days bfore a power failure took it down this afternoon at about 3PM eastern time. The other OpenBSD boxes here had uptimes of 195, 93 and 51 days, and they survived the power failure on battery backup.

I was really bummed about the web server. The last time I encountered a server up for more than a year was a NetWare 4.11 box that did around 500 days before it needed a reboot.

That all seemed trivial when I watched, on tv, the failure of the northeastern power grid in the United States.

Last login: Thu Aug 14 15:48:59 2003 from 172.16.1.100
OpenBSD 3.3 (GENERIC) #44: Sat Mar 29 13:22:05 MST 2003

Welcome to OpenBSD: The proactively secure Unix-like operating system.

Simple Daemon
Got a gleam in
His one and only eye.
"Human users
Are system abusers."
He said, with a sigh.
"My only recourse is
All system resources
To daemons I shall tie."


http://www.multicians.org/multics-humor.html
Terminal type? [vt100]
uptime
11:24PM up 51 days, 7:09, 1 user, load averages: 0.08, 0.08, 0.08
ssh 172.16.1.100
root@172.16.1.100's password:
Last login: Thu Aug 14 07:28:05 2003 from pumpkin.tst.tracor.com
OpenBSD 3.3 (GENERIC) #44: Sat Mar 29 13:22:05 MST 2003

"I have no fear of the future. Let us go forward into
its mysteries, let tear aside the veils which hide it
from our eyes and let move onward with confidence and
courage."

-- Winston S. Churchill
Terminal type? [vt100]
uptime
3:08PM up 93 days, 5:01, 1 user, load averages: 0.20, 0.11, 0.09

MOTD

Posted at 8:17PM on Sunday, August 3, 2003 in geekstuff and musings and openbsd.

Last login: Wed Jul 9 09:34:50 2003 from no@way.jose
OpenBSD 3.3 (GENERIC) #44: Sat Mar 29 13:22:05 MST 2003

Welcome to OpenBSD: The proactively secure Unix-like operating system.

Simple Daemon
Got a gleam in
His one and only eye.
"Human users
Are system abusers."
He said, with a sigh.
"My only recourse is
All system resources
To daemons I shall tie."


http://www.multicians.org/multics-humor.html

{fydo@obfuscate:~}

Playlist automation, continued

Posted at 10:31PM on Saturday, July 12, 2003 in geekstuff.

Continuing our adventure into programming web streams using Spacial Audio Solution's SAM package, we present a script that plays a special show at a fixed time we determine. Working on the program schedule, we've added the Canvas Prog Hour, a two hour show in four parts, that will play at midnight Saturday and 8PM Sunday on our station (all times central).

The following script automates adding a Canvas Prog Hour show to the stream source machine's queue, giving us four hours a week with Matt and some fine progressive rock.

{ Simple PAL script to play Canvas Prog Hour at midnight Saturday and 8PM Sunday

Assumes the Canvas Prog Hour shows are in individual category folders, one
for each show, and the folder name contains the word 'canvas'
}

var show, trackList : TDataSet;

PAL.Loop := True;


if ((now >= T['00:00:00']) and (now <= T['00:00:30']) and (DayOfWeek(Now) = Sunday)) or
((now >= T['20:00:00']) and (now <= T['20:00:30']) and (DayOfWeek(Now) = Sunday)) then
begin
show := Query(
'select id, name from category where name like ''Canvas%''' +
' order by rand() limit 1',[],True);
WriteLn('Playing:');
WriteLn(show['name']);

trackList := Query(
'select songlist.filename' +
' from categorylist, songlist' +
' where categorylist.songid = songlist.id' +
' and categoryid = :sid' +
' order by songlist.filename',[show['id']],True);

trackList.First;
Queue.Clear;
while not trackList.EOF do
begin
WriteLn(trackList['filename']);
Queue.AddFile(trackList['filename'],ipBottom);
cat['station id'].QueueBottom(smLemmingLogic,false);
trackList.Next;
end;

trackList.Free;
show.Free;
end;

Playlist automation and scheduling

Posted at 2:35PM on Sunday, May 18, 2003 in broadcast media and geekstuff and wbcq.

We're slowly assembling and configuring all the building blocks to automate the WBCQ console stream. Starting with an audio stream point on the internet, add a radio station broadcasting live on the air from about 3:30PM through about 1:00AM seven days a week, more or less. When the station's off-air, we will be providing programming from a variety of archival and internet sources. The tools we've assembled thus far to make this happen include the following

Now, the key to this whole bag of tricks is SAM, the cool software developed by our friends at Spacial Audio Solutions. SAM is designed for automating broadcast streams for the internet broadcaster, and it includes a number of nice features and building blocks itself to make this happen. SAM includes a Delphi-based scripting language called PAL that one can use to automate all kinds of back end tasks, such as downloading and scheduling news updates from an internet site. SAM uses the MySQL database, and can be integrated with the web through HTML, PHP, and other web scripting environments.

So, we have our WBCQ console stream, and we're building a substantial library of archived material to stream when WBCQ 7415 is off the air. The first thing to develop then is a scheduling mechanism to drop on top of SAM. In it's simplest form, it should work like this

while true {  find what should be streaming now;  if not found use alternative source;  if it's on the air now    wait til next check;   else    start it up;    if we were unsuccessful     start up alternate source;    wait til next check; }

SAM does not contain a scheduling mechanism, but it's got all the tools we need to develop it. Taking a look at the pseudo code above, we see we're going to run a loop that checks the state of the stream every so often. The first thing that's done is

find what should be streaming now;

This means we should look at the schedule and determine what's supposed to be broadcasting. Okay, but SAM doesn't have a schedule feature built in. So, we need to create a SQL table to implement our schedule, and a nice web front end to make it easy for us to update it, and give our listeners a chance to see what's on and when. There's two ways to implement a schedule. The simplest is to have a single table

schedule = program_name + day_of_week + start_time + end_time + program_description

This will certainly handle our needs, but it's not the most elegant implementation. Some programs will be run every day, with various start and end times. Why duplicate the program entries for each instance? A better schedule consists of two tables

entry = program_id + day_of_week + start_time + end_time

program =
program_id +
program_name +
program_description

A program be live input from the sound card, a relay of another internet hosted stream, or a file or group of media files hosted locally or at some host on the network. The easiest way to group content into "programs" with SAM is to use it's native media arrangement scheme, by divising program content into categories in playlist. Individual playlist entries in category folders can be a file or a URL. (I've also discovered that even though there are different SAM functions for OpenFile() and OpenURL(), OpenFile() does not care if you're opening a file or URL).

So, we're able to check the current state of our broadcast. There must be a variable that keeps track of the program_id of the currently running program. If the stream's active and the program_id matches, we'll assume all is well. If something's wring, like network problems preventing a particular relay stream from being accessed, we will try and launch an alternative source (the infamous "filler material").

Now, when the schedule indicates that a new program needs to be started, we will attempt to start it up, reset the current program_id, and wait for the next check. That completes a run through our main automation loop.

This application can be implemented with


  • a relatively simple SAM script,
  • some MySQL database hacking,
  • a PHP application to allow viewing and updating the schedule.

Tobor Radio does 116 hours

Posted at 11:25PM on Saturday, April 19, 2003 in entertainment and geekstuff and music and wbcq.

On Monday night, I fired up Tobor the CD Server and started a Shoutcast stream from nine CDs picked by Dr. Becker for a test. The machine performed admirably, continuously spinning an 80 hour playlist until this afternoon, when the SCSI chain timed out and the server hung.

From the shoutcast server log:

<04/15/03@23:31:09> [source] icy-irc:na ; icy-icq:0 ; icy-aim:na [...] <04/19/03@19:56:21> [source] no data (30s timeout). disconnecting.

This corresponds to the error message on Tobor's console:

Apr 19 18:47:05 tobor /bsd: cd4(iha0:4:0): SCSI OpCode 0x08 timed out

Four hours shy of five days (~116 hours) continuous streaming isn't too bad for a test run, though.

Tobor Radio

Posted at 5:50PM on Sunday, April 6, 2003 in broadcast media and geekstuff and music and wbcq.

We're putting the final touches on Tobor, our big CD server project. Earlier today I replaced a failed power supply and installed and verified the last two CD-ROM drives. Tobor now has 23 CD-ROMs online, all powered by OpenBSD 3.2 running on a vintage Pentium 133 with 32 megs of memory.

The final burn-in test consists of wiring Tobor to a LAN and streaming music off his many CD-ROMs. Next to him, I have a P266 running Windows 2000 acting as a shoutcast source, and the P266 sends a stream back to my main machine in the basement running a shoutcast server, which is then available for testing from the internet.

Tobor and his companion external CD tower are very large and heavy, which makes it difficult (if not impossible) to move him to the basement for tinkering. And I'm sure that Jane would not appreciate a CD server in the dining room. So, Tobor lives in the garage. Tobor has a 3com 10/100 ethernet adapter, which we crosswired to the P266. The P266 has a nifty Linksys USB 802.11b wireless LAN adapter, which is used to communicate back to the basement and internet via an equally nifty wireless access point.

Tobor serves up tunes very well in a streaming environment. I observed CPU utilization between 2 and 5 percent streaming MP3s and no higher than 12 percent streaming a compressed waveform. I believe the unit will handle at least five simultaneous streams with no problem, and probably more.

Beware of dirty CDs. If a CD-ROM in Tobor is dirty or has bad tracks, the system hangs as the SCSI system starts generating media errors on the console. This can be extremely annoying when selecting a dozen selections from one directory on a CD-ROM that Tobor does not like. Winamp will scan each file as it adds it to the playlist, and the system shuts down while it's processing a chain of SCSI media errors.

Here is the output from mount(8):

/dev/wd0a on / type ffs (local) /dev/cd0a on /cd/cd00 type cd9660 (local, read-only, norrip) /dev/cd1a on /cd/cd01 type cd9660 (local, read-only, norrip) /dev/cd2a on /cd/cd02 type cd9660 (local, read-only, norrip) /dev/cd3a on /cd/cd03 type cd9660 (local, read-only, norrip) /dev/cd4a on /cd/cd04 type cd9660 (local, read-only, norrip) /dev/cd5a on /cd/cd05 type cd9660 (local, read-only, norrip) /dev/cd6a on /cd/cd06 type cd9660 (local, read-only, norrip) /dev/cd7a on /cd/cd07 type cd9660 (local, read-only, norrip) /dev/cd8a on /cd/cd08 type cd9660 (local, read-only, norrip) /dev/cd9a on /cd/cd09 type cd9660 (local, read-only, norrip) /dev/cd10a on /cd/cd10 type cd9660 (local, read-only, norrip) /dev/cd11a on /cd/cd11 type cd9660 (local, read-only, norrip) /dev/cd12a on /cd/cd12 type cd9660 (local, read-only, norrip) /dev/cd13a on /cd/cd13 type cd9660 (local, read-only, norrip) /dev/cd14a on /cd/cd14 type cd9660 (local, read-only, norrip) /dev/cd15a on /cd/cd15 type cd9660 (local, read-only, norrip) /dev/cd16a on /cd/cd16 type cd9660 (local, read-only, norrip) /dev/cd17a on /cd/cd17 type cd9660 (local, read-only, norrip) /dev/cd18a on /cd/cd18 type cd9660 (local, read-only, norrip) /dev/cd19a on /cd/cd19 type cd9660 (local, read-only, norrip) /dev/cd20a on /cd/cd20 type cd9660 (local, read-only, norrip) /dev/cd21a on /cd/cd21 type cd9660 (local, read-only, norrip) /dev/cd22a on /cd/cd22 type cd9660 (local, read-only, norrip)

And here is Tobor's boot message:

OpenBSD 3.2 (GENERIC) #25: Thu Oct 3 19:51:53 MDT 2002 deraadt@i386.openbsd.org:/usr/src/sys/arch/i386/compile/GENERIC cpu0: F00F bug workaround installed cpu0: Intel Pentium (P54C) ("GenuineIntel" 586-class) 75 MHz cpu0: FPU,V86,DE,PSE,TSC,MSR,MCE,CX8 real mem = 33140736 (32364K) avail mem = 25227264 (24636K) using 430 buffers containing 1761280 bytes (1720K) of memory mainbus0 (root) bios0 at mainbus0: AT/286+(6c) BIOS, date 02/24/97, BIOS32 rev. 0 @ 0xfb340 apm0 at bios0: Power Management spec V1.2 apm0: AC on, battery charge unknown pcibios0 at bios0: rev. 2.1 @ 0xf0000/0xb804 pcibios0: PCI BIOS has 6 Interrupt Routing table entries pcibios0: PCI Interrupt Router at 000:07:0 ("Intel 82371SB PCI-ISA" rev 0x00) pcibios0: PCI bus #2 is the last bus bios0: ROM list: 0xc0000/0x8000 0xc8000/0x4000 0xcc000/0x4000 pci0 at mainbus0 bus 0: configuration mode 1 (no bios) pchb0 at pci0 dev 0 function 0 "Intel 82437VX" rev 0x02 pcib0 at pci0 dev 7 function 0 "Intel 82371SB PCI-ISA" rev 0x01 pciide0 at pci0 dev 7 function 1 "Intel 82371SB IDE" rev 0x00: DMA, channel 0 wired to compatibility, channel 1 wired to compatibility pciide0: channel 0 ignored (disabled) wd0 at pciide0 channel 1 drive 0: wd0: 16-sector PIO, LBA, 4111MB, 8354 cyl, 16 head, 63 sec, 8420832 sectors wd0(pciide0:1:0): using PIO mode 4, DMA mode 2 xl0 at pci0 dev 11 function 0 "3Com 3c905 100Base-TX" rev 0x00: irq 5 address 00:60:97:84:d6:db nsphy0 at xl0 phy 24: DP83840 10/100 media interface, rev. 1 ppb0 at pci0 dev 13 function 0 "DEC 21152 PCI-PCI" rev 0x01 pci1 at ppb0 bus 1 iha0 at pci1 dev 0 function 0 "Initio INIC-950 SCSI" rev 0x01: irq 9 scsibus0 at iha0: 8 targets iha0: target 0 using 8 bit 8.0 MHz 8 REQ/ACK offset xfers cd0 at scsibus0 targ 0 lun 0: SCSI2 5/cdrom removable iha0: target 1 using 8 bit 8.0 MHz 8 REQ/ACK offset xfers cd1 at scsibus0 targ 1 lun 0: SCSI2 5/cdrom removable iha0: target 2 using 8 bit 8.0 MHz 8 REQ/ACK offset xfers cd2 at scsibus0 targ 2 lun 0: SCSI2 5/cdrom removable iha0: target 3 using 8 bit 8.0 MHz 8 REQ/ACK offset xfers cd3 at scsibus0 targ 3 lun 0: SCSI2 5/cdrom removable iha0: target 4 using 8 bit 8.0 MHz 8 REQ/ACK offset xfers cd4 at scsibus0 targ 4 lun 0: SCSI2 5/cdrom removable iha0: target 5 using 8 bit 8.0 MHz 8 REQ/ACK offset xfers cd5 at scsibus0 targ 5 lun 0: SCSI2 5/cdrom removable iha0: target 6 using 8 bit 8.0 MHz 8 REQ/ACK offset xfers cd6 at scsibus0 targ 6 lun 0: SCSI2 5/cdrom removable iha1 at pci1 dev 4 function 0 "Initio INIC-950 SCSI" rev 0x01: irq 9 scsibus1 at iha1: 8 targets iha1: target 0 using 8 bit 5.0 MHz 15 REQ/ACK offset xfers cd7 at scsibus1 targ 0 lun 0: SCSI2 5/cdrom removable iha2 at pci1 dev 8 function 0 "Initio INIC-950 SCSI" rev 0x01: irq 9 scsibus2 at iha2: 8 targets iha2: target 0 using 8 bit 8.0 MHz 8 REQ/ACK offset xfers cd8 at scsibus2 targ 0 lun 0: SCSI2 5/cdrom removable iha2: target 1 using 8 bit 8.0 MHz 8 REQ/ACK offset xfers cd9 at scsibus2 targ 1 lun 0: SCSI2 5/cdrom removable iha2: target 2 using 8 bit 8.0 MHz 8 REQ/ACK offset xfers cd10 at scsibus2 targ 2 lun 0: SCSI2 5/cdrom removable iha2: target 3 using 8 bit 8.0 MHz 8 REQ/ACK offset xfers cd11 at scsibus2 targ 3 lun 0: SCSI2 5/cdrom removable iha2: target 4 using 8 bit 8.0 MHz 8 REQ/ACK offset xfers cd12 at scsibus2 targ 4 lun 0: SCSI2 5/cdrom removable iha2: target 5 using 8 bit 8.0 MHz 8 REQ/ACK offset xfers cd13 at scsibus2 targ 5 lun 0: SCSI2 5/cdrom removable iha2: target 6 using 8 bit 8.0 MHz 8 REQ/ACK offset xfers cd14 at scsibus2 targ 6 lun 0: SCSI2 5/cdrom removable iha3 at pci1 dev 12 function 0 "Initio INIC-950 SCSI" rev 0x01: irq 9 scsibus3 at iha3: 8 targets ppb1 at pci0 dev 15 function 0 "DEC 21152 PCI-PCI" rev 0x01 pci2 at ppb1 bus 2 iha4 at pci2 dev 0 function 0 "Initio INIC-950 SCSI" rev 0x01: irq 7 scsibus4 at iha4: 8 targets iha5 at pci2 dev 4 function 0 "Initio INIC-950 SCSI" rev 0x01: irq 7 scsibus5 at iha5: 8 targets iha5: target 0 using 8 bit 8.0 MHz 8 REQ/ACK offset xfers cd15 at scsibus5 targ 0 lun 0: SCSI2 5/cdrom removable iha5: target 1 using 8 bit 8.0 MHz 8 REQ/ACK offset xfers cd16 at scsibus5 targ 1 lun 0: SCSI2 5/cdrom removable iha5: target 2 using 8 bit 8.0 MHz 8 REQ/ACK offset xfers cd17 at scsibus5 targ 2 lun 0: SCSI2 5/cdrom removable iha5: target 3 using 8 bit 8.0 MHz 8 REQ/ACK offset xfers cd18 at scsibus5 targ 3 lun 0: SCSI2 5/cdrom removable iha5: target 4 using 8 bit 8.0 MHz 8 REQ/ACK offset xfers cd19 at scsibus5 targ 4 lun 0: SCSI2 5/cdrom removable iha5: target 5 using 8 bit 8.0 MHz 15 REQ/ACK offset xfers cd20 at scsibus5 targ 5 lun 0: SCSI2 5/cdrom removable iha5: target 6 using 8 bit 8.0 MHz 8 REQ/ACK offset xfers cd21 at scsibus5 targ 6 lun 0: SCSI2 5/cdrom removable iha6 at pci2 dev 8 function 0 "Initio INIC-950 SCSI" rev 0x01: irq 7 scsibus6 at iha6: 8 targets iha7 at pci2 dev 12 function 0 "Initio INIC-950 SCSI" rev 0x01: irq 7 scsibus7 at iha7: 8 targets isa0 at pcib0 isadma0 at isa0 pckbc0 at isa0 port 0x60/5 pckbd0 at pckbc0 (kbd slot) pckbc0: using irq 1 for kbd slot wskbd0 at pckbd0: console keyboard vga0 at isa0 port 0x3b0/48 iomem 0xa0000/131072 wsdisplay0 at vga0: console (80x25, vt100 emulation), using wskbd0 wsdisplay0: screen 1-5 added (80x25, vt100 emulation) pcppi0 at isa0 port 0x61 midi0 at pcppi0: sysbeep0 at pcppi0 npx0 at isa0 port 0xf0/16: using exception 16 fdc0 at isa0 port 0x3f0/6 irq 6 drq 2 fd0 at fdc0 drive 0: 1.44MB 80 cyl, 2 head, 18 sec biomask 82c0 netmask 82e0 ttymask 82e2 pctr: 586-class performance counters and user-level cycle counter enabled dkcsum: wd0 matched BIOS disk 80 root on wd0a rootdev=0x0 rrootdev=0x300 rawdev=0x302

Kulpsville redux

Posted at 3:07PM on Sunday, March 9, 2003 in broadcast media and geekstuff and hf and pirates and wbcq.

This year's SWL Winterfest in Kulpsville, Penisvlvania proved to be an awe-inspiring spectacle. I was greatly impressed by all the good vibes I encountered during my first visit to Kulpsville.

Noted highlights and tidbits include:

  • WDCD Radio on FM 91.3 non-stop during the fest, playing the complete collection of WDCD shows with the exception of the traditional Pancho Villa broadcast, aired at midnight on Saturday. My off-air recording of Pancho Villa is chopped at the beginning. I will try and get a clean MP3 later.

  • FM 89.5 was also noted sporadically all weekend. Signal not quite as strong as WDCD. On Friday afternoon, heard a Glenn Hauser parody with lines like "The propagation outlook is.. shit." They also played a lot of Captain Ganja material. IDs heard on Friday afternoon included "Maximum power this is K 2000 worldwide," "K 2000 p o box 146 stoneham mass 02116," and "K 2000 listener driven radio."

  • At around 0400 Saturday Jay Smilkstein arrived at the show, and wandered into the hosptiality keg area just after Dr Tornado and El Nino from Radio Metallica Worldwide arrived. Surreal.

  • Traffic on 6955 was sporadic. Noted lots of transmitter testing between 1800 and 1900 with various voice checks and Captain Ganja material, e.g. "Man am I ripped". Big band music from 2300 with killer sound. Free form content and Pink Floyd music all night.

  • Watched Allan Weiner Worldwide, Radio Timtron Worldwide, and the Real Amateur Radio Show all live with Allan and Tim at the helm in Room 412 (What's a 412? Tim revealed the secret hidden answer on one of the many carts comprising his show bits). Tim cound not locate the cart containing the theme to the Real Amateur Radio Show, so we were treated to an a capella Timtron version. Look for Tony T-O-N-Y Straka S-T-R-A-K-A on Tim's show, as well as me.

  • Very interesting live tests of DRM technology, and a corresponding technical presentation, during the conference portion of the show.

  • Dr Adrian Peterson, from Adventist World Radio, gave a fascinating presentation of his sixty year history of monitoring worldwide radio and the thousands of QSL cards in his private collection. In the thick binder marked United States the cards are arranged by call letters and date from the 1930s to the present. Many cards from pre-war stations and World War II stations. He even has three WGTG QSLs signed by Dave Franz. And KBCQ, Roswell, New Mexico.

  • A brand spanking new Captain Ganja Show documenting Moe and the Captain's journey from New York to Kulpsville and all the entertaining characters they encounter along the way.

  • Thanks to the kindness of certain fest participants, I was given thirty six episodes of Juliette's Wild Kingdom (Saturday 130AM ET on WBCQ 7415), including episode 34, "Dr Becker's Car". These and are on their way to Dr Becker so they can be streamed worldwide over the internet.

Optimizing bandwidth with OpenBSD

Posted at 12:33PM on Thursday, March 6, 2003 in geekstuff and openbsd.

A recent thread on the OpenBSD Journal shows us some of the enhancements that are being built into altq, which provides "a framework to manage queueing disciplines on network interfaces" [altq(9)]. Specific enhancements to altq include the ability to optimize bandwidth over WAN connections such as ADSL.

Since the original article at benzedrine.cx appears to be offline for the time being, I've archived it here.

I'm running three OpenBSD 3.3-current servers in my lab at work (two of which are multiple-interface firewalls), and the beta versions appear to be very stable. In addition to the bandwidth optimization features, the new enhancements also provide for traffic prioritization by address group, With this feature on a firewall system, for example, you can guarantee bandwidth available to critical resources like internet web servers while making sure the users on the local network don't eat up all the bandwidth downloading MP3s from Kazaa.

Low budget webcasting

Posted at 3:48PM on Saturday, March 1, 2003 in entertainment and geekstuff and music and rfma and wbcq.

Good ol' Comcast is capping upload bandwidth for it's cable modem users, like myself, to 19.2K. This is done mostly because cable modem customers aren't allowed to put any services on the 'net, like web servers, and for surfing the net it's download speeds that really matter. Besides, they'd love to sign you up for a business class account if you want any kind of upload bandwidth.

I'm not interested in putting up a web server on my comcast account. I have a more than capable web hosting provider for that. However, I'd really like to send a live music and entertainment stream once in a while to an audio server out on the net. Last night, I built and ran such a beast.

The same problem with upload bandwidth is a bigger concern for dial-up accounts. I was building and configuring a computer to help an international shortwave radio station send a live stream of it's console feed to an internet streaming server. Right now, their primary means of getting on the internet is a dial-up account. They've been doing this for some time now, thanks to Dr. Becker's wizardry. The same scheme can be used to send a low bandwidth stream from a severely capped cable modem connection.

First, you start out with a reasonably equipped computer. In this experiment we used a Pentium II-450, with 128MB of RAM and a 10GB HDD. The system has a nice SoundBlaster PCI card which will handle the hardware side of encoding an audio feed. I installed Windows 2000 Workstation on the computer, and it was happy with this and ready to go.

The machine has a 3Com 3c905 10/100 ethernet card, and I salvaged two US Robotics Courier external modems to support a dial-up. The hardware checked out okay.

Next, I installed Winamp 2.81. Note, the tricks we're doing requires the "classic" Winamp. The new Winamp does not work with our broadcasting tools, just yet.

The next software needed is the Shoutcast DSP plug-in, that facilitates redirecting Winamp'e output to a Shoutcast or Shoutcast-like streaming server. This version is a little older than what Shoutcast is shipping, because we want to use a low bandwidth output setting that the newer versions of the plug-in don't support.

Finally, to support all different kinds of MP3 encoding schemes, we need to install the MP3 CODEC and supporting files. This is the final piece of the puzzle, and now we're ready to webcast.

Through experimentation and experience with this technology, Dr. Becker recommends a setting of 16/11 mono as an optimal setting for dial-up use. Considering the low encoder setting, I thought music would sound really crappy. However, once we poked a couple of holes in the firewall and started up a Shoutcast server to test the feed on, I was surprised at how well the stream sounded. It's not CD quality by any means, but it's not like listening to music that sounds like it was recorded inside a coffee can either.

Our test consisted of running a live stream of a small sample of Radio Free Mount Airy's music and entertainment library across the net to Dr. Becker's Shoutcast server in Kansas, which he then relayed to WBCQ's studio feed (which is offline right now, hence this activity in setting up a new streaming computer). We ran that stream overnight and it was surprisingly reliable and listenable. It was a lot of fun, too!

The last thing, which I didn't test but should work just fine, is running a true live feed. Presumably you'd have your mikes and mixers and various audio sources run through a mixer and other audio hardware and gizmos, and fed directly into the sound card's microphone input. It is easy to tell Winamp to take input live from the mic input rather than use a library of wave files and MP3s like I did. This will increase your CPU and memory requirements, but our PII-450 should handle this with cycles to spare.

This setup should reliably stream over a 33.6 dial-up, if line conditions are good. It helps to have a better quality modem, like the USRs I have sitting around from my BBS days.

I just noticed something

Posted at 5:58PM on Tuesday, February 25, 2003 in geekstuff.

If you call your OpenBSD box reboot, and you enter the "reboot" command at a console prompt, the machine responds with

reboot reboot: rebooted by root

How to completely muck up your new Unix box

Posted at 10:28PM on Monday, February 24, 2003 in geekstuff and openbsd.

I installed the latest build of OpenBSD the other day. This was, as usual, a painless and quick intsallation even considering I installed over the internet. Within an hour, I had a brand new firewall with three network interfaces ready to configure for a lab firewall.

Then I made a simple, yet crucial mistake.

The first thing I do is install the bash shell on a new machine, because, well, I like bash. This is a simple thing to do -- download the bash package and use pkg_add to install it. However, I grabbed the nearest bash package to me, which happened to be from an OpenBSD 3.2 release. I installed it. And then, breaking every rule from my personal operating system installation book...

I changed root's shell to bash without testing it out.

The OpenBSD 3.2 bash, as I found out, is not quite compatible with the operating system I just finished installing, and I got a really nasty linker error when I logged in and the operating system attempted to run root's shell. SOL.

As embarrassed as I am at this mistake, I don't feel so bad as Brian has related some equally horrific OpenBSD installation stories (Hi James!).

The latest OpenBSD packages work just fine with the latest build. The moral here is to always test new packages before you goof with the root account. And don't let the fact that it's Friday afternoon and that everything's going well cloud your judgement and cause you to mess up a perfect installation.

Increase network performance on your OpenBSD box

Posted at 11:58PM on Thursday, February 20, 2003 in geekstuff and openbsd.

Here is a system tweak I discovered today when I was optimizing network performance on an OpenBSD 3.2 firewall. This tweak effectively increased throughput by at least ten percent.

In /etc/sysctl.conf, add the following lines:

# tweaks added by Lw on Feb 20 2003 # Increase TCP Window size for increase in network performance # default values are 16384 and 41600 respectively net.inet.tcp.recvspace=65535 net.inet.tcp.sendspace=65535

You can either reboot the system for the changes to take effect, or if you're working on a new uptime record, you can enter these commands (as the root user) to change the variables without rebooting

sysctl -w net.inet.tcp.recvspace=65535 sysctl -w net.inet.tcp.sendspace=65535

This tip came from the OpenBSD firewall using pf page and the Enabling High Performance Data Transfers page at the Pittsburgh Supercomputing Center.

A bootable OpenBSD CD-ROM

Posted at 3:17PM on Wednesday, February 19, 2003 in geekstuff and openbsd.

We have a couple of buggy servers here that are suffering from an intermittant SCSI disk lock up. Our wizards have been unable to pinpoint the problem to hardware or the Windows 2000 Server operating system.

The history of these servers seem to indicate that the hardware is at fault. So, I thought I'd boot 'em up with a real operating system and see if OpenBSD's verbose hardware probing during it's boot sequence and set of useful diagnostic tools could help isolate the problem.

Unfortunately the buggy servers are based on a bizarre VME bus architecture, and they don't have a floppy disk. The only way to boot them is from a bootable CD-ROM. I don't have a current bootable OpenBSD installation disc here, as I almost always boot from floppy and do an installation off the net.

After a couple minutes of searching I discovered OpenBSD 3.1-memorable, which is a concise and detailed description of how one goes about creating a bootable OpenBSD CD-ROM installation. To save time, the author includes a sample bootable ISO image of one of his builds (27MB). Although this is OpenBSD 3.1, one version away from the current, this is close enough for my testing needs.

Francisco's bootable disc works well. The sacrificial Dell Workstation I used to test boot this operating system suffered no ill effects, and was up and running on the network immediately. This is a great debugging tool. When I get a few minutes with my OpenBSD box at home, I will try and build a current version.

The bootable OpenBSD is also an excellent source of entertainment! Just boot up a co-worker's unattended Windows workstation with OpenBSD, remove the CD-ROM, and wait to see the expression on their face when they think the computer's been totally destroyed by Evil Hackers.

For more information, check out this document that describes how to go about creating a bootable OpenBSD CD-ROM.

The Organizational Standard Software Process

Posted at 5:44PM on Friday, January 31, 2003 in geekstuff and rants.

Does anyone else have an expansive bureaucracy to methodologize, categorize, and obfuscate software engineering activities at their workplace?

One of my coworkers described our "Organizational Standard Software Process" quite succinctly today using the following code snippet:

<ossp>
 <loop_step>
  <body_part name="Pud" action="Pull" />
 </loop_step>
</ossp>

Computer of the month, December 2002

Posted at 2:48PM on Monday, December 30, 2002 in geekstuff.

There's something about a blue LCD that just screams "cool" to us computer types. The computer of the month for December is our first server with a blue LCD.

As you can see from our rack, we've been investing lately in the Dell PowerEdge line of rack mount servers. The newest of these is the top system, a Dell PowerEdge 1650. This beastie is packed with:

  • a 1.13 GHz Pentium III CPU with 512K cache
  • 512 MB of 133M DIMMs
  • Redundant power supplies
  • Three 10,000 RPM 73 GB SCSI hard disk drives
  • Onboard SCSI RAID 5
  • Dual 10/100/1000 onboard ethernet

Here's a closeup of the front of this machine, with it's grille removed. The blue LED is the power indicator, and also can be set to blink to identify the system in a rack. The blue LED will change color and blink amber if an error condition is detected. The main keyboard, mouse and monitor connections are on the rear of the unit, but there are convenient keyboard and monitor connectors on the front as well in case the system ever needs to be troubleshooted with your favorite crash cart.

The big button on the front panel to the right of all the various LEDs is the top cover release latch. It is normally locked down with a screw on top, but I wanted to show the inside of this machine, so the screw's been removed.

Here is the system with the top cover removed. On the left you can see the redundant power supply module.

Now, a view from the top. As you can see this machine is dual processor capable. We're only using it for a file server so one CPU is enough. We're only using two of the four DIMM memory slots. The dual onboard ethernet adapters are shown to the left. There's also a management port in the back of the unit. You can see the connectors to cables going to a keyboard/video/mouse (KVM) switch at the lower left. The rackmount kit has a cool cable management arm that allows you to pull the system completely out of the rack for maintenance yet leave all the back-attached cables nice and mounted to the individual rack assembly.

Notice all the little fans in this machine. There's one for each hard disk drive bay and a fourth at the top of this photo. The systems are designed to push the air completely horizontally so it's possible to fully load a rack with systems like this if you have good airflow and temperature control.

This machine is very fast. It replaced a five year old monstrously large Hewlett-Packard NetServer. The new PowerEdge has a processor fifty times faster than the HP, more RAM, and twice the disk space, and three discs instead of eight.

We've been using pizza box servers like the PowerEdge 1650, 1550, and 2550 series ever since they were released. With the exception of the very first unit we bought (a first generation 1550 that has had some hardware "issues"), these machines have been rock solid dependable and stable. The price is certainly right when compared to similarly equipped systems from, say, Compaq. This system came in between four and five thousand dollars, a far cry from the thirty grand we paid for it's predecessor only five years ago.

A management interface for Tobor

Posted at 12:06PM on Monday, December 30, 2002 in geekstuff and wbcq.

Today we continued working on Tobor, a big heavy CD Server we saved from destruction a month ago. We're making Tobor easy to remotely manage, by installing a software package called Webmin, a web-based interface for managing Unix systems.

Webmin is a stable and well-developed product, and we were able to get it installed and running quickly. Tobor's OpenBSD 3.2 installation contains all that we need to run Webmin withour requiring any OS mods or additional software. The biggest requirement for Webmin is Perl, which is included as part of the default OpenBSD installation. Webmin itself is happy with OpenBSD.

I decided to install the Webmin software under /etc. The directory the software ended up in is /etc/webmin-1.050.

There are a few configuration entries you make when installing Webmin. In most cases we chose default values. Here are the specific choices we made for Tobor:

  • Config file directory: /etc/webmin
  • Log file directory: /var/webmin
  • Path to Perl: /usr/bin/perl
  • Web server port: 31337
  • Login name: admin
  • Start Webmin at boot time: yes

The installation script then creates the Webmin configuration entries, and adds a command to start Webmin to the startup script /etc/rc.local. The script performs a few more installation tasks and starts the "mini web server" that serves up Webmin's web interface on port 31337.

The next step is to fire up a web browser and check to see if all is happy. As you can see here, it looks like we were successful. After entering a valid user name and password, we're presented with the main Webmin page.

Since Tobor is a CD server, one of the main system admin tasks will be managing the stack of CD-ROMs that Tobor will be serving up. So, we click on the System icon on the main Webmin page and are presented with the System page. What we want to examine further is Disk and Network File Systems, which are shown on this page. Recall that we earlier built a script that attempts to mount all CD-ROMs attached to Tobor, whether or not they have CD-ROMs in each drive or not. As you can see, all CD-ROMs are mounted except for /dev/cd6a, which is having a problem and needs to be replaced.

All file systems in the Unix operating system are logically "mounted" off of a root mount point called "/". When we installed OpenBSD on Tobor we created a directory called /cd and a subdirectory for each CD-ROM underneath it, starting with /cd/cd00, /cd/cd01, and so on. Then, using Samba, the Windows file system emulator for Unix systems, we created a Windows share called "cd" so that a single shared drive on a Windows server or workstation can access all the data on all the CDs mounted on Tobor.

The directories we created for each CD-ROM are used as "mount points" for logically attaching the root directory of each CD-ROM, using the mount command. Recall that our startup script, upon finding a CD-ROM in the drive corresponding to the device /dev/cd0a will attemt to mount that CD-ROM's file system using the command

mount_cd9660 /dev/cd0a /cd/cd00

As you can see from this Webmin details page, all of these details are displayed in graphical form.

Now, the process of mounting and dismounting CD-ROMs can be completely managed through the Webmin interface. An example of mounting a CD-ROM in device /dev/cd19a under mount point /cd/cd19 is shown in this Webmin page.

That's all there is to it.

A couple of notes on today's activity:

  1. The page fault crash we experienced earlier returned today after the Webmin installation had completed. It looks as if we got ahold of a bad RAM chip or two, but fortunately I had a couple of spares sitting around which (hopefully) will prevent future page faults.

  2. The mount point creation page has the option to "save and mount at boot". This corresponds to the "permanent" column in Webmin's file system status page. We can set all CD-ROM mounts as permanent and we won't need to startup script we developed earlier.

  3. While I was at it, I configured Webmin to handle management of the Samba module.

I'll be doing a final hardware prep and burn-in party for Tobor over the New Year's holiday and hopefully he'll be ready for shipment by the end of the week.

But what does it mean?

Posted at 9:02AM on Tuesday, December 17, 2002 in geekstuff.

Here is the Error Screen of the Month, which showed up in the application event log of a newly installed Windows 2000 Advanced Server that unfortunately hangs it's GUI upon boot. You've got to hand it to whoever came up with this:

Default local machine policy cannot be created. Error -2146893802 to create recovery policy blob.

What is the significance of the negative two billion error code to the process of creating the recovery policy blob? What is the recovery policy blob? Should I be alarmed that my machine is infected with a blob?

Tobor hacking, part two

Posted at 4:20PM on Saturday, November 23, 2002 in geekstuff and openbsd and wbcq.

Today I continued the next step in preparing Tobor the CD Server for his ultimate goal as an on-demand multimedia file server for WBCQ. Only a couple of minor problems were encountered.

It is getting cold here in Mount Airy, and Tobor is living in the garage, which isn't heated. This is no big problem. To work on Tobor and keep warm, I took a Cisco Aironet 4800 wireless access point, and wired it's ethernet interface to Tobor's ethernet card with a crossover cable. No hub or switch required with a crossover cable! The access point's IP address is is 10.1.1.2/24 and Tobor is 10.1.1.254/24.

Next, I filled up all CD-ROM drives with data CDs from my archive. The NEC Multispin CD-ROM appears to need a CD-tray, but the lone tray I have here at the house would not fit. Also, the seventh CD-ROM in the first chain is offline. It's either got a detached data cable or is bad. I will have to debug these minor problems later.

Ok, time to move inside. I fired up the laptop, stuck in an Aironet 4800 PCMCIA adapter, and hard-configured it's address to 10.1.1.4/24. This was successful, as the laptop associated to the access point quickly, and I am able to reach both the AP and Tobor.

OpenBSD is secure out of the box, and the only default communications service is the secure shell (ssh). So, I opened up TeraTerm with it's ssh add-on and started a terminal session with Tobor.

Now, to mount the CD-ROMs. OpenBSD doesn't do this automatically. The first thing I noticed is that OpenBSD only creates four CD devices when it installs, to cover 99.99 percent of all possible CD configurations -- two primary and tow secondary (i.e. as in IDE) CD devices. So, I can mount the first two CDs but that's it.

The solution here is a little script called MAKEDEV which lives in /dev. This simplifies the nasty mknod program that's used to create device pointers for OpenBSD. After reading through the script and checking the man pages for mknod and mount, I creates device pointers for all the CD_ROMs using the following command

/dev/MAKEDEV cdn

where n runs from 3 to 25 (I added device pointers for a few more drives than we've got in Tobor in case we add more later). Now, each MAKEDEV creates two device pointers; for example

/dev/MAKEDEV cd5

creates the following device pointers

/dev/cd5a /dev/cd5c

We will use the "a" device pointer to mount the CD-ROM into the file system...but first, an brief interruption:

CRASH! Suddenly, after executing

/dev/MAKEDEV cd10

Tobor crashed with the following message:

uvm_fault(0xd6816e14, 0x0, 0, 3) -> e

Kernel: page trap fault, code=0

Stopped at

_uvm_fault+0xaaf: incb 0 (%ecx)

This is not good; I hope this is not the start of a trend. Perhaps playing around with the mknod and mount commands is to blame. So, I reset Tobor and he booted back up okay.

I was able to MAKEDEV the remaining CD device pointers with no difficulty; in fact, Tobor was happy and crash free for the rest of the day.

ls /dev/cd* /dev/cd0a /dev/cd13a /dev/cd17a /dev/cd20a /dev/cd24a /dev/cd4a /dev/cd8a /dev/cd0c /dev/cd13c /dev/cd17c /dev/cd20c /dev/cd24c /dev/cd4c /dev/cd8c /dev/cd10a /dev/cd14a /dev/cd18a /dev/cd21a /dev/cd25a /dev/cd5a /dev/cd9a /dev/cd10c /dev/cd14c /dev/cd18c /dev/cd21c /dev/cd25c /dev/cd5c /dev/cd9c /dev/cd11a /dev/cd15a /dev/cd19a /dev/cd22a /dev/cd2a /dev/cd6a /dev/cd11c /dev/cd15c /dev/cd19c /dev/cd22c /dev/cd2c /dev/cd6c /dev/cd12a /dev/cd16a /dev/cd1a /dev/cd23a /dev/cd3a /dev/cd7a /dev/cd12c /dev/cd16c /dev/cd1c /dev/cd23c /dev/cd3c /dev/cd7c

Now that we have the device pointers created, the next step is to mount each CD drive and build a script that mounts them when the system boots.

Ultimately, we want to make all CDs visible from a single Windows drive mapping across the network. The device pointers need to have a corresponding mount point in the file system to attach to. So, keeping both os these goals in mind, I created a directory off the root of the file system called /cd

mkdir cd

and under /cd, I created a directory for each CD's mount point

mkdir /cd/cd00 mkdir /cd/cd01

[...]

mkdir /cd/cd25

All file systems are mounted using the mount(8) command. mount(8) invokes the mount_cd9660(8) command when dealing with ISO-9660 CD-ROM file systems. This is what we will use to build a script to automatically mount all the CD-ROMs in Tobor and his companion unit. Basically, the command goes like this

mount_cd9660 /dev/cd0a /cd/cd00

where /dev/cd0a is the device pointer we created above for the cd0 device (the first CD-ROM in the SCSI chain), and /cd/cd00 is the mount point directory in the file system. When this command is run, assuming there is a CD-ROM in the first drive in the chain, the CD's root directory will appear in /cd/cd00.

Hey, this works. I then built a script, called mount_all_cds, which looks like this

mount_cd9660 /dev/cd0a /cd/cd00 mount_cd9660 /dev/cd1a /cd/cd01 mount_cd9660 /dev/cd2a /cd/cd02 mount_cd9660 /dev/cd3a /cd/cd03 mount_cd9660 /dev/cd4a /cd/cd04 mount_cd9660 /dev/cd5a /cd/cd05 mount_cd9660 /dev/cd6a /cd/cd06 mount_cd9660 /dev/cd7a /cd/cd07 mount_cd9660 /dev/cd8a /cd/cd08 mount_cd9660 /dev/cd9a /cd/cd09 mount_cd9660 /dev/cd10a /cd/cd10 mount_cd9660 /dev/cd11a /cd/cd11 mount_cd9660 /dev/cd12a /cd/cd12 mount_cd9660 /dev/cd13a /cd/cd13 mount_cd9660 /dev/cd14a /cd/cd14 mount_cd9660 /dev/cd15a /cd/cd15 mount_cd9660 /dev/cd16a /cd/cd16 mount_cd9660 /dev/cd17a /cd/cd17 mount_cd9660 /dev/cd18a /cd/cd18 mount_cd9660 /dev/cd19a /cd/cd19 mount_cd9660 /dev/cd20a /cd/cd20

Next, make sure the script is executable

chmod mount_all_cds 755

and run it. This works just fine, and the only error is gives is on the NEC drive that does not have a CD inside of it:

./mount_all_cds mount_cd9660: /dev/cd6a on /cd/cd06: Input/output error

Now, it's time to install Samba. When OpenBSD 3.2 was released, I downloaded all the packages (add-on applications) onto two CD-ROMs, and Tobor's first two CD-ROM drives contain those two CDs. The Samba package is on cd01:

cd cd01/packages/i386/ ls sam* sam-4.3.19980506.tgz samba-2.2.5.tgz

So, let's add the package. Open BSD has an simple utility that installs and de-installs applications. The pkg_add(1) command is used to install applications. So, we run

pkg_add samba-2.2.5.tgz

to install Samba. But, we encounter the next bug-of-the-day:

Nov 23 14:08:38 tobor /bsd: cd1(iha0:1:0): Check Condition on opcode 0x8 Nov 23 14:08:38 tobor /bsd: cd1(iha0:1:0): Check Condition on opcode 0x8 Nov 23 14:08:38 tobor /bsd: SENSE KEY: Media Error Nov 23 14:08:38 tobor /bsd: SENSE KEY: Media Error Nov 23 14:08:38 tobor /bsd: INFO FIELD: 132913 Nov 23 14:08:38 tobor /bsd: INFO FIELD: 132913 Nov 23 14:08:38 tobor /bsd: ASC/ASCQ: L-EC Uncorrectable Error Nov 23 14:08:38 tobor /bsd: ASC/ASCQ: L-EC Uncorrectable Error Nov 23 14:08:39 tobor /bsd: cd1(iha0:1:0): Check Condition on opcode 0x8 Nov 23 14:08:39 tobor /bsd: cd1(iha0:1:0): Check Condition on opcode 0x8 Nov 23 14:08:39 tobor /bsd: SENSE KEY: Media Error Nov 23 14:08:39 tobor /bsd: SENSE KEY: Media Error Nov 23 14:08:39 tobor /bsd: INFO FIELD: 132914 Nov 23 14:08:39 tobor /bsd: INFO FIELD: 132914 Nov 23 14:08:39 tobor /bsd: ASC/ASCQ: L-EC Uncorrectable Error Nov 23 14:08:39 tobor /bsd: ASC/ASCQ: L-EC Uncorrectable Error

Dammit! This CD-ROM is bad. I have had a lot of problems with my new machine's CD burner. Perhaps a rant directed towards Dell's piece-of-shit hardware is in order; maybe later. Is it 4:20 yet?

We have to take a break, and go burn a new CD. Fortunately OpenBSD maintains a worldwide net of fast distribution mirror servers, so I can grab the Samba package quickly and burn a new CD. After this is done, it needs to be mounted on Tobor, but we have to unmount the bad one first:

umount /dev/cd1a mount /dev/cd1a /cd/cd01

Now we're ready to install Samba if this CD is indeed not a coaster like it's predecessor.

cd cd01/warez

ls
COOL-K.COM cooledit96.exe samba-2.2.5.tgz

pkg_add samba-2.2.5.tgz

+---------------
| The samba-2.2.5 configuration files in /etc/samba,
| have been installed. Please view these files and change
| the configuration to meet your needs.
+---------------

Cool. that worked.

Whenever I install a Unix operating system, it's almost an unconscious reflex to create a "larry" user account so there's some way to get in to the system besides using the root account. Now, I want to create a "scott" account for Dr. Becker. We want to set up Windows networking access permissions using non-root users to keep things safe and secure.

adduser

Use option ``-silent'' if you don't want to see all warnings and questions.

Reading /etc/shells
Check /etc/master.passwd
Check /etc/group

Ok, let's go.
Don't worry about mistakes. I will give you the chance later to correct any input.
Enter username [a-z0-9_-]: scott
Enter full name []: Scott Becker
Enter shell bash csh ksh nologin sh [bash]:
Uid [1001]:
Login group scott [scott]:
Login group is ``scott''. Invite scott into other groups: guest no
[no]:
Enter password []:
Enter password again []:

Name: scott
Password: ****
Fullname: Scott Becker
Uid: 1001
Gid: 1001 (scott)
Groups: scott
HOME: /home/scott
Shell: /usr/local/bin/bash
OK? (y/n) [y]: y
Added user ``scott''
Copy files from /etc/skel to /home/scott
Add another user? (y/n) [y]: n
Goodbye!

Now to configure samba. The first thing to do is edit /etc/samba/smb.conf, the Samba configuration file. I added the following two lines:

workgroup = WBCQ server string = Tobor

This is how the system will appear on the LAN. Next, I set up a share point for the CDs by adding these lines to smb.conf:

[cd] comment = Tobor's CD-ROMs path = /cd valid users = larry scott public = no writable = no

This says that the Windows share point "cd" points to /cd on Tobor, and that user accounts larry and scott can access the share point with read-only access. The "public = no" line directs Samba to keep this share point private, meaning it will be hidden from the Windows networking browse list.

Now, make Samba passwords for the two user accounts:

/usr/local/bin/smbpasswd larry larrys_password /usr/local/bin/smbpasswd scott scotts_password

and we're ready to start the two Samba daemon processes:

/usr/local/libexec/smbd -D /usr/local/libexec/nmbd -D

Let's check Tobor's resource usage using the top(1) command:

load averages: 0.22, 0.18, 0.17 14:47:10 16 processes: 1 running, 15 idle CPU states: % user, % nice, % system, % interrupt, % idle Memory: Real: 7940K/19M act/tot Free: 38M Swap: 0K/155M used/tot

PID USERNAME PRI NICE SIZE RES STATE WAIT TIME CPU COMMAND
14373 root 2 0 356K 868K idle select 0:02 0.83% sshd
22501 root 2 0 380K 1148K sleep select 0:04 0.00% sshd
23052 root 10 0 648K 1112K sleep wait 0:00 0.00% bash
8541 root 2 0 860K 824K sleep select 0:00 0.00% sendmail
16470 root 2 0 100K 388K sleep select 0:00 0.00% syslogd
6249 root 3 0 652K 1096K idle ttyin 0:00 0.00% bash
20173 root 2 0 228K 460K sleep select 0:00 0.00% cron
3451 root 2 0 1004K 840K sleep select 0:00 0.00% nmbd
1 root 10 0 336K 200K idle wait 0:00 0.00% init
17790 root 29 0 124K 628K run - 0:00 0.00% top
28671 root 3 0 48K 424K idle ttyin 0:00 0.00% getty
16049 root 3 0 48K 424K idle ttyin 0:00 0.00% getty
15342 root 3 0 44K 420K idle ttyin 0:00 0.00% getty
31093 root 3 0 48K 424K idle ttyin 0:00 0.00% getty
28512 root 2 0 64K 348K idle select 0:00 0.00% inetd
30910 root 2 0 1884K 792K idle select 0:00 0.00% smbd

which shows the two Samba processes using a little less than three megabytes of RAM.

All looks good, so let's try to map a drive from the laptop to Tobor:

C:\WINDOWS>net use y: \\10.1.1.254\cd /user:larry larrys_password System error 1240 has occurred.

The account is not authorized to log in from this station.

Whoops, I forgot about the "encrypted passwords" thingie in Samba. By default Samba is set up not to encrypt Windows passwords, and newer operating systems like Windows 2000 and Windows XP can't attach to the Samba shares because they encrypt passwords when doing things like "net use", so we have to uncomment the line

encrypt passwords = yes

in /etc/samba/smb.conf.

Now we save this file, and unload the two samba daemons

kill 30910 kill 3451

and restart them

/usr/local/libexec/nmbd -D /usr/local/libexec/smbd -D

and, finally, try to connect to the Samba share:

C:\WINDOWS>net use y: \\10.1.1.254\cd /user:larry larryspassword The command completed successfully.

Success! We can see all the CDs from the laptop, and play a tune.

Next we need to add some commands to Tobor's boot scripts so that Samba is started automatically, and so all the CDs are mounted automatically. There are several ways to do this, but the method I used is first, to add the following lines to the botton of /etc/rc.local:

# start samba daemons /usr/local/libexec/nmbd -D /usr/local/libexec/smbd -D

This will start the two Samba daemons. Next, move the mount_all_cds script to /etc and add these lines to /etc/rc.local:

# mount all CDs (duh) /etc/mount_all_cds

Now we can have some more fun. cd13 has a cd master of Marion's Attic from December 9, 2000. This is not an off-air recording; it's a direct cassette to wave master. I got the casettes directly from Marion (she is such a sweetheart). The CD has lossless shn-compressed waveforms. So Tobor is serving up compressed waveforms across the wireless LAN to my laptop, and Winamp on the laptop is decompressing the shn files to waves (using the shnamp plug-in) and playing them.

I played ten minutes or so of Marion's show across the WLAN this way and never skipped a beat. This is a great proof-of-concept for Tobor and shows he can serve up waveforms as easily as MP3s.

The final test for today is to reboot and see if the daemons start and the CDs mount. This went off without a hitch so we declare success and head to the basement to document our adventure and fire up the ol' shortwave just in time for Radio Timtron Worldwide. What a cool show! I hope Tobor serves up Timtron archives sometime in the future.

Information assurance runs amok

Posted at 8:02PM on Wednesday, November 20, 2002 in geekstuff and rants.

The "Information Assurance" people are driving us nuts by demanding that our network and systems designs conform to a rigidly defined methodology consisting of verifiable audit plans designed to guarantee compliance with Government criteria for Information Assurance. When we ask what the criteria are, the IA people can't answer---those criteria haven't been developed yet. Worse, they want us to pay them for telling us this!

Now, thanks to a tip-off via a post on alt.binaries.slack, we have proof that "Information Assurance", AKA "Information Awareness" in this case, is completely out of hand.

Don't get me wrong. I believe that a consistent and steadily funded research and development effort is crucial to the future of any technology effort. Still, it's been a long time since I saw such a huge pile of buzzwords all squashed together in one place.

The following is extracted from DARPA's Information Awareness Office web site:

"IAO Mission: The DARPA Information Awareness Office (IAO) will imagine, develop, apply, integrate, demonstrate and transition information technologies, components and prototype, closed-loop, information systems that will counter asymmetric threats by achieving total information awareness useful for preemption; national security warning; and national security decision making.

"IAO Vision: The most serious asymmetric threat facing the United States is terrorism, a threat characterized by collections of people loosely organized in shadowy networks that are difficult to identify and define. IAO plans to develop technology that will allow understanding of the intent of these networks, their plans, and potentially define opportunities for disrupting or eliminating the threats. To effectively and efficiently carry this out, we must promote sharing, collaborating and reasoning to convert nebulous data to knowledge and actionable options. IAO will accomplish this by pursuing the development of technologies, components, and applications to produce a proto-type system. Example technologies include:


  • Collaboration and sharing over TCP/IP networks across agency boundaries
  • Large, distributed repositories with dynamic schemas that can be changed interactively by users
  • Foreign language machine translation and speech recognition
  • Biometric signatures of humans
  • Real time learning, pattern matching and anomalous pattern detection
  • Entity extraction from natural language text
  • Human network analysis and behavior model building engines
  • Event prediction and capability development model building engines
  • Structured argumentation and evidential reasoning
  • Story telling, change detection, and truth maintenance
  • Business rules sub-systems for access control and process management
  • Biologically inspired algorithms for agent control
  • Other aids for human cognition and human reasoning

"It is difficult to counter the threat that terrorists pose. Currently, terrorists are able to move freely throughout the world, to hide when necessary, to find unpunished sponsorship and support, to operate in small, independent cells, and to strike infrequently, exploiting weapons of mass effects and media response to influence governments. This low-intensity/low-density form of warfare has an information signature, albeit not one that our intelligence infrastructure and other government agencies are optimized to detect. In all cases, terrorists have left detectable clues that are generally found after an attack. Even if we could find these clues faster and more easily, our counter-terrorism defenses are spread throughout many different agencies and organizations at the national, state, and local level. To fight terrorism, we need to create a new intelligence infrastructure to allow these agencies to share information and collaborate effectively, and new information technology aimed at exposing terrorists and their activities and support systems. This is a tremendously difficult problem, because terrorists understand how vulnerable they are and seek to hide their specific plans and capabilities. The key to fighting terrorism is information. Elements of the solution include gathering a much broader array of data than we do currently, discovering information from elements of the data, creating models of hypotheses, and analyzing these models in a collaborative environment to determine the most probable current or future scenario. DARPA has sponsored research in some of these technology areas, but additional research and development is warranted to accelerate, integrate, broaden, and automate current approaches."

Computer of the month, November 2002

Posted at 4:32PM on Wednesday, November 20, 2002 in geekstuff.

My latest project, introduced in these articles from last Sunday, is the revival of Tobor the CD Server.

The huge computer in this picture is Tobor. To his right you'll notice a companion Todd CD server with seven drives. The drive covers on the bottom right of Tobor's front case have been removed and you can see the SCA backplane that drives plug into. (Yes, that is a pair of classic Macintoshes in the backround on the center of the toolbench. One of these is a Mac Classic and the other is a Mac Plus, and they both work fine.)

This image shows Tobor with his left panel removed, exposing the P133 motherboard, floppy and hard disk drives, and SCSI ribbons to the back of the backplane and to the external SCSI-1 connectors that the Todd drive plugs into. Note the two huge fans at the top of the back case! This unit is seriously equipped with not one, not two, but three power supplies, as you can see from this rear view. Note also the abnormally long keyboard cable from the vintage IBM PC-AT keyboard. The AT keyboard is IMO the best computer keyboard ever made. Now I finally know why IBM made their keyboard cables so long.

Finally, we see Tobor at rest, with his covers safely locked up. The cooler at the lower right of this image is an excellent bench for resting when reading hardware configuration guides, and also makes excellent storage for iced-down refreshing beverages.

Tobor is alive

Posted at 12:17PM on Sunday, November 17, 2002 in geekstuff and openbsd and wbcq.

It figures. It was warm and sunny on Thursday and Friday and this weekend it's been rainy, damp and downright cold. Tobor, however, does not care, and seems to like the cold weather.

Today, I replaced the 1275MB Seagate ST32176A HDD with a 4311MB Seagate Medalist 4310. I also removed the old 2x16 RAM and added 2x32 SIMMs (the P133 motherboard is one of those transitional types that had old RAM and SIMM slots. He didn't like both old RAMs and SIMMs together, so I removed the old RAM and the 64MB works just fine.

I briefly considered replacing the old P133 with something newer, but gave up on that for now, as it wold require some chassis and power supply mods I was not interested in pursuing today.

Tobor has 15 internal SCSI CD-ROMs, and the external "Todd 8050" unit plugged into the back has another 7 CD-ROMs in it. Amazingly, the Todd unit was seen right away by Tobor, although the last CD in the chain isn't there (IIRC the last time the Todd unit was running under Windows NT, the seventh drive was acting weirdly).

Using the OpenBSD "B" boot floppy, I started the operating system installation. Success! tobor.wbcq.com is alive. I assigned IP 10.1.1.254/24 and defgate 10.1.1.1 for testing, set timezone to CST6CDT, BIOS time to GMT, and installed bash.

Looking at Tobor's boot message, we have 21 CD-ROMs conveniently labeled starting with cd0. For simplicity I configured a single 3.7GB partition. I need to borrow either a crossover cable or switch from work to verify the network interface.

Tobor saved from destruction

Posted at 10:32AM on Sunday, November 17, 2002 in geekstuff and openbsd and wbcq.