in reply to Test project....

First, a few words on security: I don't see where @text comes from, and I don't think your readit sub works. Period. You probably don't mean to clobber your $query object by assigning an undefined, springs-into-being array element to it:
sub readit{ # should use a shared lock here open(READ,"guestbook.txt") || dienice("Couldn't open guestbook for + reading: $!"); local $/; # slurp mode my @text = <READ>; close READ: return split(/:/,@text); }
That way you don't have to pass in the CGI object (which is a good thing to do in your other subs, and I'm impressed with it), and we can get rid of the global @done this way. Instead, we return the array from this sub, and need to catch it in an array somewhere else.

This, of course, means printit() will have to change slightly:

sub printit { my $query = shift; print $query->h2('Current Results'); while (@_) { my $user = shift; my $comment = shift; print "Message by: $user<br>"; print "&lt;Message&gt;<br><blockquote>$comment</blockquote>&lt +;/Message&gt;"; print $query->hr(); } }
A more detailed version would check $user and $message for containing HTML tags or other nasty potential characters. For now, though, I think you'll do better making it run under -w, strict, and -T.