Home

Advertisement

Customize
binderofdaemons
19 November 2009 @ 11:18 pm

Mirrored from Obsolete Your Idols.

This post is addressed to people who more or less are in the situation I was in two months ago.  Notably:

  1. you manage an environment which is mostly Ubuntu 8.04.mumble LTS
  2. you know enough Ruby to recognize it when you see it
  3. you want to start using Puppet to manage your environment

I wrote this post because you’ll run into problems trying to use the probably otherwise fine examples in the documentation, through a combination of puppet being a moving target and LTS being a static environment.

First, if you get inexplicable errors about certificates while configuring and tweaking and experimenting, shut down the puppetmasterd on the master server, kill any puppet process on the client machine, and remove the contents of /var/lib/puppet/ssl on both systems involved.  This seems especially common if you’re doing any hostname tomfoolery.

Second, here’s what a very basic puppet.conf file might look like:

# This file is managed in //depot/ops/puppet/
[main]
logdir=/var/log/puppet
vardir=/var/lib/puppet
ssldir=/var/lib/puppet/ssl
rundir=/var/run/puppet
factpath=$vardir/lib/facter
pluginsync=true
certname=mask.play

[puppetmasterd]
templatedir=/var/lib/puppet/templates
server=mask.play

The only real changes from the shipped default are an explicit certname and server value. It might not be obvious what I’ve set them to, here, but that’s a server name (on an internal only TLD). On the client machines you won’t need either of those set and you can squelch some noise by getting rid of the pluginsync= option.  In my environment, because of DNS tomfoolery, I had to explicitly make a record in /etc/hosts for the puppetmasterd’s server on the client systems, telling them to look for puppet at a specific address.

To get started setting up puppet, refer to the Simplest Puppet Recipe page specifically Step four: Run a client.  What you’re wanting to achieve here is an introduction between the puppet client node and the puppetmasterd server.  You’ll see your success or failure in /var/log/daemon.log on both systems.  Now about the rest of that Simplest Puppet Recipe page.

If you read it in conjunction with the Puppet Best Practices page, you may get confused like I got confused, especially if you’re a congruent kind of dumb.  After going round and round, here’s what my puppet tree looks like in SCM and implicitly on the puppetmasterd server:

puppet
puppet/services
puppet/manifests
puppet/plugins
puppet/notes
puppet/clients
puppet/modules
puppet/modules/appserver
puppet/modules/appserver/manifests
puppet/modules/curl
puppet/modules/curl/manifests
puppet/modules/snmpd
puppet/modules/snmpd/manifests
puppet/modules/snmpd/files
puppet/modules/user
puppet/modules/screen
puppet/modules/screen/manifests
puppet/modules/ntp
puppet/modules/ntp/manifests
puppet/modules/ntp/files
puppet/modules/sudo
puppet/modules/sudo/manifests
puppet/modules/sudo/files
puppet/modules/bacula
puppet/modules/bacula/templates
puppet/modules/bacula/manifests
puppet/tools

You can see that most of the action is in puppet/modules.  Specifically, I would have started (if I knew then what I know now) with puppet/modules/sudo.  Notice two subdirectories under that.  The puppet/modules/sudo/files directory has in it the sudoers file we want to deploy to client systems.  The puppet/modules/sudo/manifests directory has in it the init.pp file.  For reference, here’s what my version of their simplest recipe looks like:

# /etc/puppet/modules/sudo/manifests/init.pp

class sudo {
	package { sudo: ensure => latest }

	file {
		"/etc/sudoers":
			owner => "root",
			group => "root",
			mode  => 440,
			source => "puppet:///sudo/sudoers",
			require => Package["sudo"];

		"/usr/bin/sudo":
			owner => "root",
			group => "root",
			mode  => 4755;
    }
}

As I recall, the permissions on Ubuntu 8.04 are different from those in the example and my choice of layout and file placement dictated the source parameter.  Speaking of file placement, the fileserver.conf I use:

[files]
  path /etc/puppet/modules/*/files
  allow *.playsomething.com
  allow *.play

Upon shutdown, puppetmasterd complains bitterly about that asterisk but it seems to otherwise work. I surmise I could well enumerate all the paths explicitly and shut up that bit of noise but it hasn’t seemed worth it, to date. The default fileserver.conf that ships in Ubuntu 8.04 expects you to serve files from /etc/puppet/files but that seems to conflict with the Puppet Best Practices so I went with the fancier place.

So under puppet/manifests are where your rules for which modules get applied to which systems.  Mine has three files, modules.pp, nodes.pp and site.pp.  They look like this:

# /etc/puppet/manifests/modules.pp
# managed from //depot/ops/puppet/manifests/modules.pp

import "sudo"

and

# /etc/puppet/manifests/nodes.pp
# managed at //depot/ops/puppet/manifests/nodes.pp

node basenode {
	include curl
	include ntp
	include screen
	include snmpd
	include sudo
}

node 'exhaust', 'gasket' inherits basenode {
	include bacula
}

node 'manifold', 'header' inherits basenode {
	include appserver
}

and

# /etc/puppet/manifests/site.pp

import "modules"
import "nodes"

filebucket { main: server => 'mask.play' }

File { backup => main }
Exec { path => "/usr/bin:/usr/sbin/:/bin:/sbin" }

Package {
	provider => $operatingsystem ? {
		debian	 	=> aptitude,
		openbsd		=> freebsd,
	}
}

If you can read between the lines there, puppet reads the site.pp file. That tells it, among other things, to read the modules.pp and nodes.pp files. The openbsd operatingsystem part is untested so don’t count on it, but that Ubuntu systems identify as debian is true and somewhat important to know.

The nodes.pp file is where all the action happens.  I’ve got five modules there defined as necessary for all kinds of systems; your environment almost certainly varies.  Then there are two kinds of nodes which inherit from basenode and add another module; each of those child node types names two servers which are that kind of a node, and includes a different module.  In this case, exhaust, gasket, manifold and header are all names of servers.

You can probably generalize from this to get a boost on rolling out Puppet.  Each of the things you want a server or set of similar servers to do is a module in puppet/modules/NAME/ with manifests/init.pp telling puppet all the rules of that module, and files/WHATEVER containing any files which should be pushed as part of enforcing that module.  You may have noticed that my puppet/modules/bacula doesn’t have a files subdirectory, but does have a templates subdirectory.

Here’s what the init.pp for bacula looks like:

# /etc/puppet/modules/bacula/manifests/init.pp

class bacula {

	package { bacula-client: ensure => latest }

    file {
		"/etc/bacula/bacula-fd.conf":
			owner => "root",
			group => "root",
			mode  => 640,
			content => template("bacula/bacula-fd.conf.erb"),
			require => Package["bacula-client"];

		"/usr/sbin/bacula-fd":
			owner => "root",
			group => "root",
			mode  => 755
    }

	exec {
		"/etc/init.d/bacula-fd restart":
			subscribe 	=> File["/etc/bacula/bacula-fd.conf"],
			refreshonly	=> true
	}
}

I’m providing it not because it’s the most awesome use of templates ever but because I found using templates very intimidating as a non-Ruby coder, so I had to do a couple shots of tequila before trying to write one. And here’s the puppet/modules/bacula/templates/bacula-fd.conf.erb file:

# /etc/bacula/bacula-fd.conf
# managed from //depot/ops/puppet/modules/bacula/templates/

Director {
	Name = akadi-dir
    Password = "yrmomsaidimthebestlickintown"
}

FileDaemon {
	Name = <%= hostname %>-fd
    FDport = 9102
	WorkingDirectory = /var/lib/bacula
	Pid Directory = /var/run/bacula
	Maximum Concurrent Jobs = 20
}

Messages {
	Name = Standard
    director = akadi-dir = all, !skipped, !restored
}

It’s a tiny substitution, just customizing the bacula-fd.conf file on the client systems to name themselves distinctly.  The point being I just took a bacula-fd.conf, figuring out the piece which needs to be different on different systems, and substituted a variable to differentiate them.  It’s easy.  There, I just saved you $7 on tequila.

Oh, so the last detail of absolute square one stuff.  Getting the important bits from your SCM workspace to the puppetmasterd workspace.  In our environment, we use a lot of Makefiles to deploy files from SCM so that’s what I did here.  It’s dead-simple but just in case you need a nudge, it looks like this:

# Makefile for puppetmasterd configuration.
# binder@manjusri.org takes the blame for this one

mask.push:
	rsync -av --delete --exclude '*/README' --exclude 'Makefile' .  root@mask.play:/etc/puppet/

It’s just an invocation of rsync which blows away any local crap, leaves the README and Makefile files in the SCM workspace, and copies everything else into the /etc/puppet directory on the puppetmasterd server. Reloading of the daemon is done manually at this point but you could always modify this Makefile to reload your configuration once you push.

OK, that’s it.  That’s everything I think I know about Puppet which I didn’t know two months ago.

 
 
binderofdaemons
05 November 2009 @ 11:02 pm

Mirrored from Obsolete Your Idols.

Or what I learned from Werner Vogels at LISA 2009.

I’ve been at LISA 2009 and saw the keynote given by Amazon’s CTO.  Here’s what I learned from it:  figure out what you’re spending more than 50% of your resources doing, then figure out how to eliminate it.  Repeat.

Before I go deeper into why I thought that’s what he was saying, two points.

  1. Yes, I saw the sexist slide.  I didn’t feel offended at the time because it seemed his reaction was genuine. He prefaced his talk by saying many people had asked him to restructure his talk to target it more at the audience of system administrators.  He explained he’d rearranged his slide deck and there had already been some spots where it seemed to me he was working to change his usual points.  So when he pulled up a slide with a girl pointing a gun and seemed to blank on what he wanted to say, it seemed genuine to me.  It could have been staged.  What seemed like an attempt to get a laugh out of the audience and move on could have been scripted.  But it didn’t seem that way to me at the time.
  2. My closest friends may well be wondering why I’m taking seriously anything Amazon has to say.  I’m still mad about the 1-click patent, I actively advocate for people to buy from Powell’s if they want to buy books online, I haven’t bought anything from Amazon from years and even then it was gifts for other people. The crowd around me during his speech reacted badly, perceiving it as nothing more than a sales pitch for Amazon Web Services.  Which, yes, there was a lot of that to it.  But I think that’s understandable.  If you’re a CxO at a company and you’re speaking to an audience and you’re not selling your company at least a little bit all the time, you worry me more.

So.  Why would I be talking about Amazon’s CTO?  It’s because of what I thought I was hearing when I filtered out the sales pitch.  Perhaps it’s just the CTOs I’ve worked with recently but it seemed to me that there was a pattern to the way they think about company operations that I can finally wrap my head around and see the similarities in.  It’s this:  a CTO looks for big technological patterns inside and outside the organization.  I know, I’m the last to notice this.

But now I took this observation and tried to think like a CTO for myself and I realized the first thing I need to do is get better at measuring the time I put in to things.  My intuition is that better than half of my time is spent changing configurations.  Maybe I’m wrong, but it’s something I can record and measure and analyze.  Whatever it is that’s consuming all of my time at work, I can look for a way to drastically reduce it.  Whether it’s as simple as stopping doing it or as complex as automating it or as pedestrian as paying someone else to do it, I think I can take this epiphany and I make my job better.

So that’s what I got out of his talk.

I hated it less than some other people, less than I expected myself to.  In fact, I didn’t hate it at all, I learned something from it and it’s going to change how I do my job.  Which is perhaps the best I can hope for from a keynote address at a technical conference.

Tags: ,
 
 
binderofdaemons
26 October 2009 @ 04:27 pm

Mirrored from Obsolete Your Idols.




inboxzero

Originally uploaded by Binder Of Daemons

BEHOLD MY GLORY.

 
 
binderofdaemons
19 October 2009 @ 06:21 am

Mirrored from Obsolete Your Idols.

I read another Charles Stross novel, Halting State. Overall, I think I enjoyed Glasshouse slightly more, but this one was more amusing more often. It starts with a bank inside an MMORPG getting robbed and ends with a 419 nod, so it’s an internet-savvy narrative. It’s got some characters who are likable, though their flaws don’t seem to really hinder them. The shy nerd with a sexcrime history gets laid, the cop with the uppity kid never has to take time off from the case to settle his hash, the accountant with the brittle work situation never suffers from office politics during the course of the story. It’s pretty light on the characters but correspondingly there’s some meaty cryptographic and augmented reality dealt to the reader in careful doses.

The more I think about it, the less satisfied I am with the way things resolve, so I’m optimistic about a rumored sequel which I hope will explain more about why Scotland’s software infrastructure survives the threat which emerges in this novel, but that’s just quibbling. This is a pretty good near future sf novel with varied characters and a briskly moving storyline.

Who might like it

  • Gamers, both the tabletop and mmorpg flavors, and possibly casino to a lesser degree.
  • Fans of nerd protagonists.
  • People who just can’t get enough of the intricate crinkling of police procedurals.

Who might not like it

  • People who think you’re getting a whole novel about people playing an MMORPG.
  • People who felt Orcbusters in The Computer Always Shoots Twice was fundamentally cheating.
 
 
binderofdaemons
11 October 2009 @ 12:26 pm

Mirrored from Obsolete Your Idols.

I made some tiny updates to bring my resume up to date since it’d been awhile and put it online again. It’s linked from the top of the manjusri.org domain.

Then I played around a little bit with the Powell’s Partner Bookshelf thing and have a shelf of some of my favorite books.

Also added to the Socialize Me page if you want it again later.

 
 
binderofdaemons
11 October 2009 @ 11:52 am

Mirrored from Obsolete Your Idols.

Did you like Brimstone? Did you like Unknown Armies? The novel Godwalker? The comic book Lucifer? Immortal the RPG?  Delta Green?

If you didn’t say yes to at least one of those, you’re excused.  Go skip ahead to something else in your flist or your feed reader.

Still here? Then you’ll like Sandman Slim.  It’s a novel which could have been told as a story in any of those settings but wasn’t, because it was told by Richard Kadrey.  It’s a revenge story, it’s a modern era magic story, it’s a buddy story, it’s a story about a lucky loser who more or less emerges triumphant from his character arc.  It’s really good.  But I don’t know how much appeal it’ll have to someone who isn’t already into that gritty street magic paranormal anti-romance groove when this book hits their eyes.

For those of you would like this, go read it.  It’s a fast moving story with very few aggravations.  If you’re not one of the people who would like this, you suck.  What are you doing still reading this, anyway?  I told you to beat it!

 
 
binderofdaemons
30 September 2009 @ 08:53 pm

Mirrored from Obsolete Your Idols.

Remember when I read Revelation Space and wrote a brief review? Between then and now, probably while in Denver at a reading with Vylar, I picked up Redemption Ark, the sequel. Seems to be the middle book in a trilogy. It does a solid job of being the middle child, not wasting too many pages recapitulating the plot of the first book, sheds a new light on what’s gone before and foreshadows, hopefully, a resolution to The Big Problem forthcoming in the third book. Well, forthcoming to me. It’s been in print for some time now, I suppose.

It’s more space opera, with some striking relativistic scale combats, some tough people solving thorny problems, some unlucky people failing, compromises made with the best of intentions and blowing up in everyone’s faces.

Who might like this

  • Fans of space opera
  • People who read the first book and wonder what happens next
  • Fans of tough women and wily old men

Who might not like this

  • Fans of dragons, unicorns, wizards, magicians, chicken pablum for the soul
  • Readers who find middle books in trilogies disappointing in general
  • People looking for a fast breezy read
 
 
binderofdaemons
12 September 2009 @ 06:59 pm

Mirrored from Obsolete Your Idols.

I’m testing something minor and not very sexy but if you read this post, please make a brief comment telling me where you read it.  I’m anticipating answers like ‘on Livejournal’, ‘in Google Reader’, ‘in Google Reader shared by <someone>’, ‘on your planet’, etc.  Surprise me if it’s something I didn’t anticipate or reassure me of my powers of interpretation, if you would.

ETA: if you are seeing this in livejournal and have no idea how to comment click on the link ‘Obsolete Your Idols’ after Mirrored from. That will bring you to the blog itself where you can comment. Sorry for the hassle.

 
 
binderofdaemons
29 August 2009 @ 09:14 pm

Mirrored from Obsolete Your Idols.

This kludgy patch is the minimum needed to get peep-0.5.0-rc2 to compile without warning or error.  If I liked it more, I’d try to feed it upstream.  As it is, this is a place for me to tuck this so I don’t lose it. peep patch

Tags: , , , ,
 
 
binderofdaemons
21 August 2009 @ 07:43 am

Mirrored from Obsolete Your Idols.

I don’t really know who Emily Devenport is.  Because of the way I came by one of her books, I suspect she’s a member of Broad Universe.  At a Wiscon a few years ago, I wandered past the Broad Universe table and one of the book covers caught my eye.  It’s got a dark skinned woman in what looks a bit like Star Wars Stormtrooper armor kneedeep in a pitted dessert landscape while behind her a looming egg shape contains (reflects?) a bright and complicated landscape, possibly a distorted version of the one she stands in.  It’s called EggHeads.

It’s the story of a lucky woman who takes chances to improve her lot and ends up potentially altering the course of human history.  I gather it’s the start of a series and not the only work by Emily Devenport so if it turns out to be the kind of thing you like, there’s more of it available.  I’ll be seeking out more of her stuff, myself.

What I liked

  • The structure of the story.  It’s in three major sections, each titled and each well-divided from the others
  • The protagonist.  She’s fierce and lucky, two of my favorite qualities.
  • The reveals in this story, where things we are told make no sense until later in the story

What I didn’t like

  • The protagonist forgiving her asshole boyfriend.  Repeatedly.
  • The ending was a little too pat for my tastes but perhaps later works in this setting undo the happily ever after.

Overall it’s a strong far future science fiction story once you get past the crutch of near-light travel.  It’s got a likable protagonist facing tough odds and beating at least some of those odds.

Who might like this book

  • People who like sf by women about women

Who might not like this book

  • People who don’t like sf by women
  • Or about women
Tags: , ,
 
 
binderofdaemons
02 August 2009 @ 07:30 pm

Mirrored from Obsolete Your Idols.

In the unlikely event that you, like me, become interested in Peep, the aural network analyzer, and try to compile it, here is the start of a patch which will silence many of the warnings and fix the one compilation error you may see.  Not fully complete, but this is as far as I got before a warning baffled and balked me.  Here in a file:  peep.patch

mtn diff –diff-args=-u  –external –revision=8ceea9d20d313dbf6715b4f1e34ad2c517811786
#
# old_revision [8ceea9d20d313dbf6715b4f1e34ad2c517811786]
#
# patch “peep-0.5.0-rc2/server/Makefile.in”
#  from [ef4bccc99a35e0974eff71a7c1fa545fcf3aee45]
#    to [e26423ae2636eefc1dd8507fb6fc662fee0217ba]
#
# patch “peep-0.5.0-rc2/server/cmdline.c”
#  from [9a76bcfe4baaf11a9994d462f1bdbbcf9c9d53b8]
#    to [d464590f8c8981ac93769bda0db0ace9c0c04f85]
#
# patch “peep-0.5.0-rc2/server/cmdline.h”
#  from [83e62a8db5117b75f333450ef240ca94239e4aff]
#    to [80677cbd08b164cd949eac4306ef14625393c6ad]
#
# patch “peep-0.5.0-rc2/server/debug.c”
#  from [d57e2db5bfa388a43a2e2ca2a54a0b7df9bb6fff]
#    to [1df39546ba7eb7e845006b490e24e862fd215ee5]
#
# patch “peep-0.5.0-rc2/server/debug.h”
#  from [94fa9d4f58d4cf8337be4110a0bc576d298dbe16]
#    to [caa26a381625a860730579c6a5b627b49019e6b8]
#
# patch “peep-0.5.0-rc2/server/engine.c”
#  from [193790ce9a81312816cf826228de8c71dcafb6ae]
#    to [4e68651c2c01ae59178edf958b2b7d515ff794f6]
#
# patch “peep-0.5.0-rc2/server/engine.h”
#  from [9f8ee670d0a42f1d3ef68d7933e4caf5dc46673a]
#    to [d77e4bc5126fb0cfbe3b7583b7157a9fad8497ce]
#
# patch “peep-0.5.0-rc2/server/main.c”
#  from [a8e02bd355754afd429afce4583f8e961e299b0a]
#    to [d731c64a931310a24a66a04ea8ceea100e720f1e]
#
# patch “peep-0.5.0-rc2/server/mixer_queue.h”
#  from [6ada4f50ad42c9e7e130b3e284a4f86cd25599ef]
#    to [6cc9e810bc4566051ea3bb22e9f66986534e0bcd]
#
— peep-0.5.0-rc2/server/Makefile.in    old
+++ peep-0.5.0-rc2/server/Makefile.in    new
@@ -157,7 +157,7 @@
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
CCLD = $(CC)
LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
-CFLAGS = @CFLAGS@
+CFLAGS = @CFLAGS@ -Wall -Werror
DIST_SOURCES = $(peepd_SOURCES)
DIST_COMMON = Makefile.am Makefile.in
SOURCES = $(peepd_SOURCES)
— peep-0.5.0-rc2/server/cmdline.c    old
+++ peep-0.5.0-rc2/server/cmdline.c    new
@@ -316,7 +316,7 @@
{

printVersion ();
-    printf (”
+    printf (”\
Usage: %s [OPTIONS]…\n\
-h         –help                Print help and exit\n\
-V         –version             Print version and exit\n\
— peep-0.5.0-rc2/server/cmdline.h    old
+++ peep-0.5.0-rc2/server/cmdline.h    new
@@ -71,8 +71,9 @@

#define GET_INT_ARG(x, y) \
{ if (argv[1][2] != ‘\0′) \
-        if (!sscanf ((char *)&(argv[1][2]), “%d”, &x)) \
+        { if (!sscanf ((char *)&(argv[1][2]), “%d”, &x)) \
optError (y); \
+        } \
else { \
argc–; argv++; \
if (!sscanf (argv[1], “%d”, &x)) \
— peep-0.5.0-rc2/server/debug.c    old
+++ peep-0.5.0-rc2/server/debug.c    new
@@ -43,7 +43,7 @@
{

if (!boolean)
-        log (DBG_ASSRT, “Assertion %s failed in line %d of file %s\n”, boolstr, line, file);
+        mylog (DBG_ASSRT, “Assertion %s failed in line %d of file %s\n”, boolstr, line, file);
/* else log(DBG_ASSRT, “Assertion %s succeeded in line %d of file %s\n”,
* boolstr,line,file);
*/
@@ -78,7 +78,7 @@

}

-int logClose (void)
+void logClose (void)
{

if (fclose (log_handle) != 0)
@@ -86,7 +86,7 @@

}

-void log (int level, char *s, …)
+void mylog (int level, char *s, …)
{

va_list ap;
@@ -114,7 +114,7 @@
sprintf (log_string, “[%s] %s”, time_string, output);

/* Output and flush the stream so we don’t hang onto logging info */
-        fprintf (log_handle, log_string);
+        fprintf (log_handle, “%s”, log_string);
fflush (log_handle);

free (log_string);
— peep-0.5.0-rc2/server/debug.h    old
+++ peep-0.5.0-rc2/server/debug.h    new
@@ -56,15 +56,17 @@
int logInit (char *log_file);

/* Close the logfile and clean up */
-int logClose (void);
+void logClose (void);

#define LOG_BUF 1024

/* Include stdio so we don’t have problems with using
* a FILE * type */
#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>

/* Variable argument logging function */
-void log (int level, char *s, …);
+void mylog (int level, char *s, …);

#endif
— peep-0.5.0-rc2/server/engine.c    old
+++ peep-0.5.0-rc2/server/engine.c    new
@@ -21,6 +21,7 @@
#include <string.h>
#include “engine.h”
#include “engine_queue.h”
+#include “mixer_queue.h”
#include “thread.h”
#include “mixer.h”
#include “playback.h”
@@ -138,11 +139,9 @@
int index = engineSoundHash (name);
struct sound_entry *p = NULL;

-    for (p = sound_table[index]; p; p ->next) {
-
+    for (p = sound_table[index]; p; p=p->next) {
if (!strcasecmp (p->name, name))
return p;
-
}

return NULL;
@@ -398,7 +397,7 @@

if (! playbackRecordEvent (*engine_event)) {

-            log (DBG_GEN, “WARNING: Error recording an event. Event not recorded.\n”);
+            mylog (DBG_GEN, “WARNING: Error recording an event. Event not recorded.\n”);
/* continue anyway */

}
@@ -615,8 +614,6 @@
void engineShutdown (void)
{

-    int i, j;
-
/* Free the engine scheduler data structure */
cfree (sched);

— peep-0.5.0-rc2/server/engine.h    old
+++ peep-0.5.0-rc2/server/engine.h    new
@@ -104,7 +104,7 @@
};

/* Allocate and create the sound table data structure */
-int engineSoundTableInit (void);
+int engineInitSoundTable (void);

/* Inserts an event entry into the sound table */
int engineSoundTableInsertEvent (char *name, EVENT_ENTRY *event);
— peep-0.5.0-rc2/server/main.c    old
+++ peep-0.5.0-rc2/server/main.c    new
@@ -30,6 +30,7 @@
#include “mixer.h”
#include “playback.h”
#include “debug.h”
+#include “parser.h”

static struct args_info args_info;
static FILE *pid_file = NULL;
@@ -77,14 +78,14 @@

if ((pid_file = fopen (pid_path, “w”)) == NULL) {

-            log (DBG_DEF, “Couldn’t write pid to file %s: %s.\n”, pid_path, strerror (errno));
-            log (DBG_DEF, “Continuing anyway…\n”);
+            mylog (DBG_DEF, “Couldn’t write pid to file %s: %s.\n”, pid_path, strerror (errno));
+            mylog (DBG_DEF, “Continuing anyway…\n”);

}
else {

/* Write our pid out to the file */
-            fprintf (pid_file, “%d\n”, pid_file);
+            fprintf (pid_file, “%d\n”, pid);
fflush (pid_file);
fclose (pid_file);

@@ -102,27 +103,27 @@
switch (DEBUG_LEVEL) {

case DBG_LOWER:
-            log (DBG_GEN, “%s %s\n”, str, “LOWER”);
+            mylog (DBG_GEN, “%s %s\n”, str, “LOWER”);
break;

case DBG_MEDIUM:
-            log (DBG_GEN, “%s %s\n”, str, “MEDIUM”);
+            mylog (DBG_GEN, “%s %s\n”, str, “MEDIUM”);
break;

case DBG_HIGHER:
-            log (DBG_GEN, “%s %s\n”, str, “HIGHER”);
+            mylog (DBG_GEN, “%s %s\n”, str, “HIGHER”);
break;

case DBG_HIGHEST:
-            log (DBG_GEN, “%s %s\n”, str, “HIGHEST”);
+            mylog (DBG_GEN, “%s %s\n”, str, “HIGHEST”);
break;

case DBG_ALL_W_ASSERT:
-            log (DBG_GEN, “%s %s\n”, str, “HIGHEST WITH ASSERTIONS!”);
+            mylog (DBG_GEN, “%s %s\n”, str, “HIGHEST WITH ASSERTIONS!”);
break;

default:
-            log (DBG_GEN, “%s %s\n”, str, “UNKNOWN. WEIRD.”);
+            mylog (DBG_GEN, “%s %s\n”, str, “UNKNOWN. WEIRD.”);
break;

}
@@ -132,14 +133,14 @@
if (!args_info.voices_given)
args_info.voices_arg = DEFAULT_MIXER_VOICES;

-    log (DBG_DEF, “Mixing voices: %d\n”, args_info.voices_arg);
-    log (DBG_DEF, “Initializing the sound engine and mixer…\n”);
+    mylog (DBG_DEF, “Mixing voices: %d\n”, args_info.voices_arg);
+    mylog (DBG_DEF, “Initializing the sound engine and mixer…\n”);

#ifdef STATIC_VOLUME
-    log (DBG_DEF, “Using static volume mixing…\n”);
+    mylog (DBG_DEF, “Using static volume mixing…\n”);
#endif
#ifdef DYNAMIC_VOLUME
-    log (DBG_DEF, “Using dynamic volume mixing…\n”);
+    mylog (DBG_DEF, “Using dynamic volume mixing…\n”);
#endif

/* Perform some error checking to set arguments correctly */
@@ -160,7 +161,7 @@

}

-    log (DBG_DEF, “Parsing configuration…\n”);
+    mylog (DBG_DEF, “Parsing configuration…\n”);

if (!args_info.config_given)
args_info.config_arg = DEFAULT_CONFIG_PATH;
@@ -179,20 +180,20 @@

if (parsed < 0) {

-            log (DBG_GEN, “Error parsing peep configuration file…\n”);
+            mylog (DBG_GEN, “Error parsing peep configuration file…\n”);
shutDown ();

}

}

-    log (DBG_DEF, “Finished configuration…\n”);
+    mylog (DBG_DEF, “Finished configuration…\n”);

-    log (DBG_DEF, “Starting mixer thread…\n”);
+    mylog (DBG_DEF, “Starting mixer thread…\n”);

startThread (doMixing, 0, &mthread);

-    log (DBG_DEF, “Starting engine thread…\n”);
+    mylog (DBG_DEF, “Starting engine thread…\n”);

startThread (engineLoop, 0, &ethread);

@@ -216,11 +217,11 @@
if (!args_info.record_file_given)
args_info.record_file_arg = DEFAULT_RECORD_FILE;

-        log (DBG_DEF, “Initializing playback file…\n”);
+        mylog (DBG_DEF, “Initializing playback file…\n”);

if (!playbackFileInit (args_info.record_file_arg)) {

-            log (DBG_DEF, “Uh Oh! Couldn’t successfully initiliaze playback file! Giving up.\n”);
+            mylog (DBG_DEF, “Uh Oh! Couldn’t successfully initiliaze playback file! Giving up.\n”);
shutDown ();

}
@@ -232,7 +233,7 @@
*/
if (playbackModeOn (NULL) && playbackSetMode (NULL) == PLAY_MODE) {

-        log (DBG_DEF, “Entering playback mode…\n”);
+        mylog (DBG_DEF, “Entering playback mode…\n”);

if (!args_info.start_time_given)
args_info.start_time_arg = NULL;
@@ -245,12 +246,12 @@
}
else {

-        log (DBG_DEF, “Initializing server…\n”);
+        mylog (DBG_DEF, “Initializing server…\n”);

setSigHandlers ();

if (playbackModeOn (NULL) && playbackSetMode (NULL) == RECORD_MODE)
-            log (DBG_DEF, “Record mode on – Recording events to %s.\n”, args_info.record_file_arg);
+            mylog (DBG_DEF, “Record mode on – Recording events to %s.\n”, args_info.record_file_arg);

/* Check whether the port has been set */
if (!args_info.port_given)
@@ -260,29 +261,30 @@

if (serverInit () < 0) {

-            log (DBG_GEN, “Uh Oh! Error initializing server!\n”);
+            mylog (DBG_GEN, “Uh Oh! Error initializing server!\n”);
shutDown ();

}

-        log (DBG_DEF, “Starting server…\n”);
+        mylog (DBG_DEF, “Starting server…\n”);

serverStart ();

}

+    return 0;
}

void printGreeting (void)
{

-    log (DBG_DEF, “\n”);
-    log (DBG_DEF, “========================================================\n”);
-    log (DBG_DEF, “Welcome to Peep (The Network Auralizer).\n”);
-    log (DBG_DEF, “Copyright (C) 2000 Michael Gilfix.\n”);
-    log (DBG_DEF, “v%s\n”, PACKAGE_VERSION);
-    log (DBG_DEF, “=========================================================\n”);
-    log (DBG_DEF, “\n”);
+    mylog (DBG_DEF, “\n”);
+    mylog (DBG_DEF, “========================================================\n”);
+    mylog (DBG_DEF, “Welcome to Peep (The Network Auralizer).\n”);
+    mylog (DBG_DEF, “Copyright (C) 2000 Michael Gilfix.\n”);
+    mylog (DBG_DEF, “v%s\n”, PACKAGE_VERSION);
+    mylog (DBG_DEF, “=========================================================\n”);
+    mylog (DBG_DEF, “\n”);

}

@@ -293,24 +295,24 @@

if ((handler = signal (SIGINT, handleSignal)) == SIG_ERR) {

-        log (DBG_GEN, “Error registering SIGINT handler: %s\n”, strerror (errno));
+        mylog (DBG_GEN, “Error registering SIGINT handler: %s\n”, strerror (errno));
shutDown ();

}

#if DEBUG_LEVEL & DBG_SETUP
-    log (DBG_SETUP, “Registered SIGINT handler.\n”);
+    mylog (DBG_SETUP, “Registered SIGINT handler.\n”);
#endif

if ((handler = signal (SIGHUP, handleSignal)) == SIG_ERR) {

-        log (DBG_GEN, “Error registering SIGHUP handler: %s\n”, strerror (errno));
+        mylog (DBG_GEN, “Error registering SIGHUP handler: %s\n”, strerror (errno));
shutDown ();

}

#if DEBUG_LEVEL & DBG_SETUP
-    log (DBG_SETUP, “Registered SIGHUP handler.\n”);
+    mylog (DBG_SETUP, “Registered SIGHUP handler.\n”);
#endif

}
@@ -348,17 +350,17 @@
client_event = engineDequeue ();

#if DEBUG_LEVEL & DBG_SRVR
-        log (DBG_SRVR, “\n”);
-        log (DBG_SRVR, “Received Event:\n”);
-        log (DBG_SRVR, “\ttype:   %d\n”, client_event.type);
-        log (DBG_SRVR, “\tlen:    %d\n”, client_event.sound_len);
-        log (DBG_SRVR, “\tsound:  %s\n”, client_event.sound);
-        log (DBG_SRVR, “\tloc:    %d\n”, client_event.loc);
-        log (DBG_SRVR, “\tprior:  %d\n”, client_event.prior);
-        log (DBG_SRVR, “\tvol:    %d\n”, client_event.vol);
-        log (DBG_SRVR, “\tdither: %d\n”, client_event.dither);
-        log (DBG_SRVR, “\tflags:  0x%04x\n”, client_event.flags);
-        log (DBG_SRVR, “\n”);
+        mylog (DBG_SRVR, “\n”);
+        mylog (DBG_SRVR, “Received Event:\n”);
+        mylog (DBG_SRVR, “\ttype:   %d\n”, client_event.type);
+        mylog (DBG_SRVR, “\tlen:    %d\n”, client_event.sound_len);
+        mylog (DBG_SRVR, “\tsound:  %s\n”, client_event.sound);
+        mylog (DBG_SRVR, “\tloc:    %d\n”, client_event.loc);
+        mylog (DBG_SRVR, “\tprior:  %d\n”, client_event.prior);
+        mylog (DBG_SRVR, “\tvol:    %d\n”, client_event.vol);
+        mylog (DBG_SRVR, “\tdither: %d\n”, client_event.dither);
+        mylog (DBG_SRVR, “\tflags:  0x%04x\n”, client_event.flags);
+        mylog (DBG_SRVR, “\n”);
#endif

/* Check if we have a valid event */
@@ -366,8 +368,8 @@
if (entry == NULL) {

#if DEBUG_LEVEL & DBG_SRVR
-            log (DBG_SRVR, “Server does not have event [%s] in its sound table!\n”, client_event.sound);
-            log (DBG_SRVR, “Discarding….\n”);
+            mylog (DBG_SRVR, “Server does not have event [%s] in its sound table!\n”, client_event.sound);
+            mylog (DBG_SRVR, “Discarding….\n”);
#endif

continue;
@@ -376,7 +378,7 @@
else if (client_event.type != entry->type) {

#if DEBUG_LEVEL & DBG_SRVR
-                log (DBG_SRVR, “Received invalid event type or type does not match sound table.\n”);
+                mylog (DBG_SRVR, “Received invalid event type or type does not match sound table.\n”);
#endif

continue;
@@ -403,7 +405,7 @@
void handleSignal (int sig)
{

-    log (DBG_DEF, “Performing shutdown…\n”);
+    mylog (DBG_DEF, “Performing shutdown…\n”);

if (ethread)
threadKill (ethread);
@@ -413,23 +415,23 @@

/* cleanup */
-    log (DBG_DEF, “Cleaning up engine…\n”);
+    mylog (DBG_DEF, “Cleaning up engine…\n”);
engineShutdown ();

-    log (DBG_DEF, “Cleaning up mixer…\n”);
+    mylog (DBG_DEF, “Cleaning up mixer…\n”);
mixerShutdown ();

-    log (DBG_DEF, “Cleaning up server…\n”);
+    mylog (DBG_DEF, “Cleaning up server…\n”);
serverShutdown ();

if (playbackModeOn (NULL)) {

-        log (DBG_DEF, “Closing playback file…\n”);
+        mylog (DBG_DEF, “Closing playback file…\n”);
playbackFileShutdown ();

}

-    log (DBG_DEF, “Exiting…\n”);
+    mylog (DBG_DEF, “Exiting…\n”);

/* Close logging routines */
logClose ();
— peep-0.5.0-rc2/server/mixer_queue.h    old
+++ peep-0.5.0-rc2/server/mixer_queue.h    new
@@ -45,8 +45,8 @@
ENGINE_EVENT *mixerDequeue (void);

/* Check the status of the queue */
-int MixerQueueEmpty (void);
-int MixerQueueFull (void);
+int mixerQueueEmpty (void);
+int mixerQueueFull (void);

/***************************************************************
* Internal function

Tags: , , ,
 
 
binderofdaemons
02 August 2009 @ 05:10 pm

Mirrored from Obsolete Your Idols.

Possibly just on Ubuntu.  So here’s what I told the NRPE daemon my command was:

command[check_timer]=/usr/lib/nagios/plugins/check_file_age -w 7200 -c 14400 -f /usr/local/playfirst/run/var/TimerService.${HOSTNAME}.alive

and when reading it from nagios_local.cfg, the nrpe daemon reported it as:

/usr/lib/nagios/plugins/check_file_age -w 7200 -c 14400 -f /usr/local/playfirst/run/var/TimerService.${HOSTNAME}.alive$

Oops.

Because then it goes on to substitute the client hostname for ${HOSTNAME} but it turns out the $ at the end of the filename persists and no, there is no file of that name lying around.  So that’s kind of a curious artifact of trying to use an environment variable substitution.  The variable does substitute but you keep a bonus $ at the end.  So then I used a bit of sed trickery so that I push out N different config files, each with the hostname hardcoded.

But it still didn’t work.  Because it turns out that daemon runs as nagios, and that file was in a place where only user and group could see it.  Rather than turn on the bits for everyone else, I decided to let nrpe run  its commands with the sudo prefix option.

Meanwhile, on the server, all of these were flagging file not found.  I sure wish the second error state would have been reported as ‘no permission to read file FOO’ and the first, I wish the substitution didn’t have that weird side effect.

Yeah, I could write patch or patches for these and submit upstream but I’ve had bad luck providing patches to Debian and Ubuntu in the past.  I have to assume it’s something about me at this point.  But if anyone wants to patch something, these are things which bugged me this last week and made my job harder.

 
 
binderofdaemons
02 August 2009 @ 10:52 am

Mirrored from Obsolete Your Idols.

I’ve been reading a lot of airport language books lately, because my employer is undergoing some changes.  New people, new focus, new strategy, and I wanted to keep up with the thinking and jargon going into this transformation.  But when I haven’t been reading those, I’ve been reading short stuff to cleanse my palate.  Here’s something I read worth talking about, the collection by Eileen Gunn named Stable Strategies and Others.

I think this is it, all the collected Gunn, and I say that with keen disappointment because these stories range from the great to the mindblowingly awesome.

I’m not going to go line by line on these but I do want to especially call out “Fellow Americans” which is an alternate history where Nixon hosts a gameshow, “Nirvana High” which is set in and around Kurt Cobain High School and “Green Fire”, a round-robin story about Heinlein and Asimov and Hopper.  These stories were the highlights for me but here’s the thing:  if you read this collection I doubt you’d agree with me on which stories are the best but I bet you will really love some of the stories in it.

Who might like this collection

  • people with short attention spans, who generally like weird fiction
  • people who’ve lived in Seattle
  • people who remember the politics of the 60s and 70s

Who might not like this collection

  • people who don’t like the sf/f genres
  • people who don’t like in-jokes in their fiction
Tags: , ,
 
 
binderofdaemons
19 June 2009 @ 02:33 pm

Mirrored from Obsolete Your Idols.

So something awesome happened this morning.  The hard drive in Vy’s computer died.

That’s not the awesome part.  The awesome part is that because I took the advice of jwz AND paid for the SuperDuper program AND consulted the wise and informative ifixit.com site, I was able to restore her system with no data loss.  That’s pretty awesome.

So I wanted to say how thankful I am to jwz for his great advice, to the fine coder(s?) behind ShirtPocket who made a program which does well what it says it will do and the technicians at iFixit who are able to explain clearly and usefully exactly how to get into the guts of Mac hardware.  I couldn’t have had a morning this awesome without all of you.  Keyboard cat, play us some Danny Halfelf.

 
 
binderofdaemons
17 May 2009 @ 12:03 pm

Mirrored from Obsolete Your Idols.

This is TSR 9177 REF 3 The Book of Lairs by James M. Ward and Mike Breault p5.

Don’t worry.  If you’ve no idea what that means, this post isn’t directed at you.

  1. Door
    • Animated two-handed swords (2)
  2. Weapon forge
    • Animated hammers (6)
    • Animated spears (6)
    • Animated long swords (6)
    • Animated two-handed swords (6)
    • Animated morning stars (6)
  3. Armor forge
    • Suits of animated armor (2 * characters)
  4. Resting place
    • Iron golems (2)

If I ran this in 3.5 edition d20, the system I use most of the time I’m running these days, here’s how these four encounters might be converted.

Door:  Animated Object, obviously.  I’d make them Medium Greatswords, presuming them to be weapons crafted for Medium creatures and being two-handed, the same size class as the wielder.  Hardness 10 and flight seem appropriate additional special defense and special quality. I’d let them do Greatsword + 1 damage and leave their attack modifier at +2. I’d bump up the CR for these to 3 each instead of the CR2 for an ordinary Medium Animated Object monster.  So EL4, overall.

Weapon forge:  More Animated Objects.  The softer version considers the hammers to be light warhammers and thus Tiny, otherwise Small for the non-light version.  If the spears are short, Small.  If longspear, Medium.  Longswords are Small.  The two-handed swords become Medium Animated Object Greatswords, like the ones at the door.  The morning stars are Small. Again granting them Hardness 10, flight, and normal damage +1 for weapons of their type at +2 to hit over conventional Animated Object monsters bumps up the CRs.  The lowest range I’d use would be 6 + 12 + 12 + 18 + 12 and the high end would be 12 + 18 + 12 + 18 + 12.  Either way this is EL9 or EL10 territory.  If the party got clever and split up the attackers somehow, controlled terrain to only let a few come at them at a time, I’d award the full xp for an EL10 encounter.  Perversely if they went in against all the weapons at once, only EL9 xp.  I’m mean that way.

Armor forge: Surprise.  More Animated Object monsters.  I’d make them unmodified Medium.  At 2 suits per character, that makes this one EL (party size + 4).

Resting place:  Straight up pair of by the book Iron Golem monsters.  The only thing unusual about them is that these are chatty and being chatty isn’t a special attack.  EL15.

Given all that, I’d run this scenario for a party with an average character level of 10 or so.  Slightly lower would probably be okay if they are good at managing terrain or willing to back out when they hit the blade storm in the Weapon Forge.

 
 
binderofdaemons
17 May 2009 @ 06:41 am

Mirrored from Obsolete Your Idols.

While on the course of wondering something almost as silly, I decided to see what kind of distribution of software packages my laptop has installed.  It turns out to be skewed wildly in favor of the letter L.

dpkg –get-selections |  grep -v deinstall | cut -c 1 | sort | uniq -c

  • 1 9
  • 44 a
  • 44 b
  • 74 c
  • 44 d
  • 66 e
  • 57 f
  • 178 g
  • 26 h
  • 33 i
  • 9 j
  • 29 k
  • 1015 l
  • 61 m
  • 40 n
  • 44 o
  • 134 p
  • 8 q
  • 23 r
  • 65 s
  • 99 t
  • 45 u
  • 10 v
  • 17 w
  • 117 x
  • 1 y
  • 6 z
 
 
binderofdaemons
17 May 2009 @ 06:02 am

Mirrored from Obsolete Your Idols.

Some of my favorite stories were all written by the same person, Philip K. Dick. So I’m always on the lookout for more stories which remind me of those stories. If you’re similar, you may want to give a read to Walter Mosley’s Blue Light. It’s a story about a group of people around the San Francisco Bay Area who experience an uncanny blue light which changes them. They then work, together and apart, to change the world they live in. Or perhaps it’s the aftermath of a cult recorded by a delusional chronicler, an interpretation which would squint towards the inaccurate if not downright unreliable narrator.

I came to read this book not because it turned up in a search of stories like those PKD wrote but because when out walking near Berkeley one day at dusk, a pedestrian saw me and asked me if I read sf. When I acknowledged his intuition, he insisted that I seek out Walter Mosley’s science fiction stories.

People who might like this book

  • Fans of PKD
  • People who live, lived or want to live in Northern California
  • Fans of the early stages of a utopia

People who might not like this book

  • Those sensitive souls who think the past was a golden age where everyone was nice
  • Those who need complete closure to a story
  • Those who think the only interesting science fiction is the most currently written
Tags: , ,
 
 
binderofdaemons
19 April 2009 @ 10:07 pm

Mirrored from Obsolete Your Idols.

I was fiddling around for something to do with a Yahoo API and so now the MUD chatbot returns (simple) websearch results. Isn’t that nice? I think it’s nice.

#!/usr/bin/perl

# mudbot by Shannon Prickett <stp@manjusri.org>
# connect a pandorabots.com chatbot with a particular TinyMUCK, Pegasus.

package mudbot;

use Smart::Comments;
use Modern::Perl;
use Net::Telnet;
use Net::AIML;
use DB_File;
use WWW::Mechanize;

use vars qw{$being_quiet %global_exit $mud_connection $mud_conversation $mud_host $mud_name
            $mud_pass $mud_port $mud_sent $pid $robot %room_name $yahoo_id};
use subs qw{setup sometimes speak};

$mud_host       = 'ginka.armageddon.org';
$mud_port       = '4242';
$mud_name       = 'Somebot';
$mud_pass       = 'YRMEME';
$being_quiet    = 0;
$pid            = $$;

tie %room_name, 'DB_File', 'mapfile' or
    die "can't tie to mapfile: $!\n";

$robot          = Net::AIML->new( botid => 'BOTIDGOESHERE' ); 

$mud_connection = new Net::Telnet( Host => $mud_host, Port => $mud_port )
                    or die "Can't connect to $mud_host $mud_port: $!";

$yahoo_id = 'LALALALA';
setup( $mud_connection );

TALKLOOP: while (1) {
    ### TALKLOOP start

    my $atme = 0;
    my $prematch = '';
    my $postmatch = '';
    my $who_said;

    my ($stub_said, $what_said) =
        $mud_connection->waitfor(   Match => '/ says, ".*"/',
                                    Errmode => 'return', );

    next TALKLOOP unless defined $what_said;

    $stub_said =~ qr{ START \d+ .+ \b(\w+)\b }msx;
    $who_said = $1;

    $what_said =~ s{says, \"(.*)\"}{$1}g;

    ### Got: $who_said
    ### Got: $what_said

    if ($what_said =~ qr{$mud_name}msxi){
        ### saw my name
        $atme = 1;
    }

    $what_said =~ s{$mud_name}{}g;

    if ( ($atme) && ($what_said =~ qr{QUIT}) ) {
        $mud_connection->print("QUIT");
        exit;
    }

    if ( ($atme) && ($what_said =~ qr{be quiet}) ) {
        if ($being_quiet) {
            $mud_connection->print("say Maximum verbosity achieved.");
            $being_quiet = 0;
        } else
        {
            $mud_connection->print("say Shutting up now.");
            $being_quiet = 1;
        }
    }

    if ( ($atme) && ($what_said =~ qr{search for ([\w\s]+)}) ) {
        ### requested to search
        my $terms = $1;
        ### got: $terms

        my @terms = split ' ', $terms;
        my $querystring = join '+', @terms;

        if (sometimes( )) {
            $mud_connection->print("say Found http://lmgtfy.com/?q=$querystring");
        } else
        {
            my $web_connect = WWW::Mechanize->new( autocheck => 1);
            $web_connect->get( "http://boss.yahooapis.com/ysearch/web/v1/$querystring?appid=$yahoo_id&format=xml");

            my $results = $web_connect->content();
            if (defined $results) {
                speak( 'Found some URLs:' );
            }
            my @lines = split /\n/, $results;
            for my $line ( @lines ) {
            ### got: $line
                if ($line =~ qr{(.+)}) {
                    my $output = $1;
                    speak( $output );
                }
            }
        }

        next TALKLOOP;
    }

    if ( ($atme) && ($what_said =~ qr{explore}) ) {
        $mud_connection->print("say OK, going to poke around now.");
        sleep 3;
        $mud_connection->print('home');
        goto EXPLORELOOP;
    }

    if ($being_quiet) {
        next TALKLOOP;
    }

    my $response = $robot->tell($what_said);
    if ($atme) {
        print "response: $response\n";
        speak( $response );
    }
    else {
        if ( !$being_quiet && (sometimes()) ) {
            print "jumping in with $response\n";
            speak( $response );
        }
    }
}

EXPLORELOOP: while (1) {
    ### exploring

    my ($name, $desc);

    $mud_connection->print('look');
    my $startmark   = $mud_connection->getline( );
    $name           = $mud_connection->getline( );
    while (my $line = $mud_connection->getline( Errmode => 'return', )) {
        $desc .= $line;
    }

    $mud_connection->waitfor( Match => '/END$pid/', Errmode => 'return');
    chomp $name;
    chomp $desc;

    ### got: $name
    ### got: $desc

    $room_name{$name} = $desc;

    sleep 10;

    $mud_connection->print('out');
}

sub setup {
    my $mc = shift;

    $mc->dump_log('/home/binder/src/mb/logfile');

    $mc->waitfor('/connect\s+guest\s+guest/');
    $mc->print("connect $mud_name $mud_pass");

    $mc->waitfor('/Vote to ban the MisInformation SuperHighway/');
    $mc->print('@desc me=Just a Perl toy of Binder\'s.');

    $mc->print("OUTPUTPREFIX START$pid");
    $mc->print("OUTPUTSUFFIX END$pid");

    $mc->waitfor('/Description set/');
    $mc->print("home\nout\nvillage");
}

sub sometimes {
    return (rand() > .75);
}

sub speak {
    my $response = shift;
    my @lines = split /\n/, $response;
    for my $line (@lines) {
        $mud_connection->print("say $line");
    }
}
 
 
binderofdaemons
19 April 2009 @ 10:22 am

Mirrored from Obsolete Your Idols.

I’ve now sunk a number of hours into it and added some functionality, none of which really works yet. But in the interest of keeping things going, here’s where things stand now. Explore doesn’t quite work, and there are still weird undef matches in the dialogue. But I pulled out all of Expect.pm and went to Smart::Comments.


#!/usr/bin/perl

# mudbot by Shannon Prickett <stp@manjusri.org>
# connect a pandorabots.com chatbot with a particular TinyMUCK, Pegasus.

package mudbot;

use Smart::Comments;
use Modern::Perl;
use Net::Telnet;
use Net::AIML;
use DB_File;

use vars qw{$being_quiet %global_exit $mud_connection $mud_conversation $mud_host $mud_name
$mud_pass $mud_port $mud_sent $pid $robot %room_name };
use subs qw{setup};

$mud_host = ‘ginka.armageddon.org’;
$mud_port = ‘4242′;
$mud_name = ‘Somebot’;
$mud_pass = ‘YRMEME’;
$being_quiet = 0;
$pid = $$;

tie %room_name, ‘DB_File’, ‘mapfile’ or
die “can’t tie to mapfile: $!\n”;

$robot = Net::AIML->new( botid => ‘GETFROMPANDORABOTS’ );

$mud_connection = new Net::Telnet( Host => $mud_host, Port => $mud_port )
or die “Can’t connect to $mud_host $mud_port: $!”;

setup( $mud_connection );

TALKLOOP: while (1) {
### TALKLOOP start

my $atme = 0;
my $prematch = ”;
my $postmatch = ”;
my $who_said;

my ($stub_said, $what_said) =
$mud_connection->waitfor( Match => ‘/ says, “.*”/’,
Errmode => ‘return’, );

next TALKLOOP unless defined $what_said;

$stub_said =~ qr{ START \d+ .+ \b(\w+)\b }msx;
$who_said = $1;

$what_said =~ s{says, \”(.*)\”}{$1}g;

### Got: $who_said
### Got: $what_said

if ($what_said =~ qr{$mud_name}msxi){
### saw my name
$atme = 1;
}

$what_said =~ s{$mud_name}{}g;

if ( ($atme) && ($what_said =~ qr{QUIT}) ) {
$mud_connection->print(”QUIT”);
exit;
}

if ( ($atme) && ($what_said =~ qr{be quiet}) ) {
if ($being_quiet) {
$mud_connection->print(”say Maximum verbosity achieved.”);
$being_quiet = 0;
} else
{
$mud_connection->print(”say Shutting up now.”);
$being_quiet = 1;
}
}

if ( ($atme) && ($what_said =~ qr{search for ‘(.*)’}msxi) ) {
my $terms = $1;
my @terms = split $terms;
my $querystring = join ‘+’, @terms;
$mud_connection->print(”say Found http://lmgtfy.com/q=$querystring”);
}

if ( ($atme) && ($what_said =~ qr{explore}) ) {
$mud_connection->print(”say OK, going to poke around now.”);
sleep 3;
$mud_connection->print(’home’);
goto EXPLORELOOP;
}

if ($being_quiet) {
next TALKLOOP;
}

my $response = $robot->tell($what_said);
if ($atme) {
print “response: $response\n”;
speak( $response );
}
else {
if ( !$being_quiet && (rand() > .75) ) {
print “jumping in with $response\n”;
speak( $response );
}
}
}

EXPLORELOOP: while (1) {
### exploring

my ($name, $desc);

$mud_connection->print(’look’);
my $startmark = $mud_connection->getline( );
$name = $mud_connection->getline( );
while (my $line = $mud_connection->getline( Errmode => ‘return’, )) {
$desc .= $line;
}

$mud_connection->waitfor( Match => ‘/END$pid/’, Errmode => ‘return’);
chomp $name;
chomp $desc;

### got: $name
### got: $desc

$room_name{$name} = $desc;

sleep 10;

$mud_connection->print(’out’);
}

sub setup {
my $mc = shift;

$mc->dump_log(’/home/binder/src/mb/logfile’);

$mc->waitfor(’/connect\s+guest\s+guest/’);
$mc->print(”connect $mud_name $mud_pass”);

$mc->waitfor(’/Vote to ban the MisInformation SuperHighway/’);
$mc->print(’@desc me=Just a Perl toy of Binder\’s.’);

$mc->print(”OUTPUTPREFIX START$pid”);
$mc->print(”OUTPUTSUFFIX END$pid”);

$mc->waitfor(’/Description set/’);
$mc->print(”home\nout\nvillage”);
}

sub speak {
my $response = shift;
my @lines = split /\n/, $response;
for my $line (@lines) {
$mud_connection->print(”say $line”);
}
}

 
 
binderofdaemons
18 April 2009 @ 02:56 pm

Mirrored from Obsolete Your Idols.

I was feeling restless so I looked at what Google Webmaster Tools had to say about this blog. Mostly it thought my title tags weren’t interesting enough, which was true. So I took the tip from Perishable Press on making title tags without Yet Another Plugin.

Humans shouldn’t notice anything exciting but perhaps the Googlebot will be thrilled.

 
 
 
 

Advertisement

Customize