Search this site


Metadata

Articles

Projects

Presentations

Eliminiating special cases in strtok loops

strtok has a "first case" and "other case" usage. The first time you call strtok, you pass it the string. Future calls must pass NULL for this same session. This leads to this kind of code:
void foo(char *mystr) {
  char *tok;

  tok = strtok(mystr, " ");
  while (tok != NULL) {
    // Do something with tok

    tok = strtok(NULL, " ");
  }
}
Notice the above duplicate code. You can use pointers properly and achieve this same result with only one line using strtok:
void foo(char *mystr) {
  char *tok;
  char *strptr = mystr;

  while ( (tok = strtok(strptr, " ")) != NULL ) {
    if (strptr != NULL)
      strptr = NULL;
    // Do something with tok
  }
}
This method lets you still invoke both first and nonfirst cases of strtok but you only have one line of code using strtok, making your code more maintainable and readable. This way has the great benefit of being able to use 'continue' inside your loop and you still move on to the next token.

Wrap method calls in python

Function wrapping is quite useful, especially when you need to make code threadsafe by wrapping with a mutex locker or adding debug entry/exit traces. We can easily wrap methods in python using lambda.

A standalone module for wrapping can be found here: wrap.py If you don't understand what the * and ** stuff means, that's fine. I'll post about those shortly.

A fun, crappy example can be found here: wrapexample.py

That example shows how to wrap a simple method (X.Foo) with pre- and post-execution function calls. Notice how we can access the parameters passed to the original function (Foo) in both the pre and post functions. That's all good and pretty, but how about a better example?

A better example would be to wrap a function call with a mutex locker.

Let's take an example class happyfoo. A sample script that uses happyfoo can be found here: main.py. However, time passes and now I require the happyfoo.makenoise method to be locked while we are inside it. If you look at the code, it doesn't lock and is not threadsafe (for our purposes).

In an ideal situation, you might add locking to the 'happyfoo.py' module itself. What if you can't do that (no access) or don't have time to hack through the code? There's an easier way.

Python lets you modify classes at runtime. The new locking code can be found here: main-locking.py

The coolest part about this is I do not have to modify the 'happyfoo.py' module. Perhaps this is a dangerous feature, but I think it's neat. Anyway, the bulk of the new code should be self explanatory, with the possible exception of this:

happyfoo.makenoise = wrap.wrapmethod(happyfoo.makenoise, do_lock, do_unlock)
This is where I override the 'happyfoo.makenoise' method with a generated one that calls the original 'happyfoo.makenoise' function wrapped in 'do_lock' and 'do_unlock' functions. If you run the script, you'll see it locking aswell as the threads waiting for the lock.

If you want to download all of the code from the post, try this tarball: python-method-wrapper.tar.gz

The wrap module needs a lot of work, potentially. It would be nice to be able to wrap and also pass other arguments to both pre and post functions. I've got a hack that adds a reference to the function being called to the keyword (kwds) list, which lets you figure out which function is actually being called. Useful if you use the same pre/post functions to wrap more than one function.

pam_captcha, The Human Challenge, version 1

I'll publish the code that makes this happen later this week when it's finished. At any rate, it's a fun pam module that requires you to pretty much be a human when SSH'ing somewhere.

log-watching expert system

I got bored and wrote an expert system for doing log analysis and reaction. It's original intention was to watch auth.log for brute-force login attempts and block them on the firewall. It has turned into a far more flexible system for doing generic log-based matching and reaction. Reactions are based on a threshold of hits over time. The 'reaction' section of the config file specifies what command is run (this could be a simple shell script you call, for example).

There are a few features I'll probably be adding soon such as multiple threshold/reactions per match type, but that's somewhat down the road for when I have more boredom to throw at the project. I also want to allow users to add their own meta globs (like %USERNAME%) into the config file so the program is even more flexible.

Currently it runs on my mirror server and blocks excess (brute force) ssh attempts, seems to be going good. The development process of this took me into learning a very slick perl module called Parse::RecDescent which parses documents based on a given grammar. I used this for the config file, it was pleasantly easy to use. Check out logwatch, download it

It requires the following perl modules:

  • File::Tail
  • Regexp::Common
  • Parse::RecDescent

note takery thing

For the longest time I've found myself jotting notes in files tossed throughout my home directory. Finding these files later has become a chore and half.
Some short while ago, the author of Ion, Tuomo Valkonen, wrote a little program called riot in haskel. I got this to build *once* and only once, so all future attempts to use this failed miserably. At any rate, riot is a useful tool to make notes of things. It stores notes in mbox format. All in all, a useful program, unless you can't get a haskell compiler working for your OS!

I quickly became annoyed, realizing the folly of my ways, having to put little jotted notes in various files that end up everywhere. Annoyed, I created a solution in a project I called 'note.' It's a simple perl Curses::UI interface to let me take notes and post followups in a thread-like manner. The config file needs to go in your home directory as ~/.noterc. The format of the file is:

dbuser = DATABASE_USER
dbpass = DATABASE_PASSWORD
dbname = DATABASE_NAME
dbhost = DATABASE_HOST

You'll need postgres and perl. Perl will need Curses::UI and File::Temp
I also have the sql you'll need to put in tables.sql

new project: solaudio

Solaris Audio Controller

I got tired of trying ot use Solaris' graphical audio controller, sdtaudiocontrol. It's slow locally, slower to xforward, etc. So I went on down to docs.sun.com and started perusing the documentation on audio(7I) and mixer(7I). A few hours later, BOOM, I've got a commandline audio control utility.
It's written in C and requires nothing. Compile it with: cc -o solaudio solaudio.c.

http://www.csh.rit.edu/~psionic/projects/solaudio/

redbull+perl=hottness

The 2nd annual Redbull Coding Competition was held here at RIT, and oh was it awesome. 12 straight hours of teams of 3-5 people coding in various languages trying to attain one of the given objectives and while consuming insane amounts of redbull.

My team went to work with perl and we pushed out a half-decent graphical filebrowser and our remote team-member, pete, finished up the compression objective in record time. The whole competition was a hell of a lot of fun.

<3 perl.