PDA

View Full Version : pack / unpack problem


VortexCortex
11-13-2005, 07:28 PM
I'm having a problem using the pack / unpack functions with fixed length records in a file. The appendUser function works fine. The error happens when I try to use the value returned by the unpack function.


#!/usr/bin/perl -w
use strict;
use CGI qw(:standard);
use CGI::Carp qw(warningsToBrowser fatalsToBrowser);
use Fcntl qw(:flock :seek);

#File containing fixed length records.
my $logFile = 'allusers.log';
#array containing IP
my @ip = split(/[.]/,$ENV{'REMOTE_ADDR'});
#current time
my $time = time;

#IP[0], IP[1], IP[2], IP[3], Time, UserIDNumber, UserName, Access, PW, Posts, Votes, Score, Joined, Quote, PW Rest Question, PW Reset Ans
my $userFormat = 'C4L2a20Ca13L4a128a64a13';
my @user = ($ip[0],$ip[1],$ip[2],$ip[3],$time,1234,'VortexCortex',0x1,'password',15,5,30,$time,'Quote','Question','Answer');
my $recordLen = length(pack($userFormat));

sub appendUser{
my @ar = @{$_[0]};
open LOG, '>', $logFile; #clobers file for testing purposes. will change to +< later.
binmode LOG;
flock LOG, LOCK_NB;
seek LOG, 0, SEEK_END;
syswrite(LOG,pack($userFormat, @ar));
flock LOG, LOCK_UN;
close LOG;
}

appendUser(\@user);

sub showUser{
open LOG, '<', $logFile;
binmode LOG;
flock LOG, LOCK_NB;
seek LOG, 0, SEEK_SET;
my $data = '';
print "Bytes Read:".sysread(LOG,$data,$recordLen)."<br />";
my @ul = unpack($userFormat, $data);

#commenting out the next 3 lines will allow the code to run without error.
for (@ul){
print $_."<br />\n";
}

flock LOG, LOCK_UN;
close LOG;
}

print<<"endHtml";
Content-type:text/html
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head></head><body>
endHtml
#print the user record.
showUser();
print "</body></html>";

Here's a link to the above code: example.cgi (http://cgi.freewebs.com/vortexcortex/cgi-bin/example.cgi)

My guess is that I'm not using the unpack function properly.

Thanks in advance for your help.

FishMonger
11-13-2005, 09:02 PM
I don't see any problem with how you're using the unpack function.

Your link is not working, so I can't see the results.

What error are you getting?

After the sysread, is $data the same length as $recordLen?

If the code runs without error when you comment out the printing of the @ul array, I'd say that the @ul may be empty (undef).

You imported the warningsToBrowser function, but you never used it, which means the warnings won't be sent to the browser i.e., you won't see the warning that @ul is undefined.

Why have
use CGI qw(:standard);
but never actually use it?

EDIT:
You should always check the return of the filehandle opening.
open LOG, '<', $logFile or die "can't read from $logfile $!";

VortexCortex
11-14-2005, 05:28 PM
@ul was defined (defined function returned true). $data and $recordLen were the same length. The error I was getting could be seen by clicking the link (internal server error, sorry I don't have access to the log file). I imported the CGI package because it will be used later in the scope of the program (collecting user data to store). I took your advice and used the die function to check the result of the open function, but that was not the problem either.

I don't know what was wrong, but I scrapped the code, started over, and it works. Here's the new code I used.
sub showLog{
open LOG, '+<', $logFile or die "Can't open: $logFile";
binmode LOG;
flock LOG, LOCK_NB;
seek LOG, 0, SEEK_SET;
my $data = '';
while(sysread(LOG,$data,$recordLen)==$recordLen){
my @ul = unpack($userFormat, $data);
for (my $i = 0; $i <= $#ul; $i++){
$ul[$i] =~ s/\0+//g;
print $ul[$i].' | ';
}
print "<hr />\n";
}
flock LOG, LOCK_UN;
close LOG;
}

I guess my problem wasn't with pack / unpack. This is the first time I've used those functions so I was unsure.

You were a big help, as always, FishMonger.
Thanks for pointing me in the right direction :thumbsup: