Learning Perl

Learning PerlSearch this book
Previous: 17.2 Opening and Closing DBM HashesChapter 17
User Database Manipulation
Next: 17.4 Fixed-Length Random Access Databases
 

17.3 Using a DBM Hash

Once the database is opened, accesses to the DBM hash are mapped into references to the database. Changing or adding a value in the hash causes the corresponding entries to be immediately written into the disk files. For example, once %FRED is opened from the earlier example, we can add, delete, or access elements of the database, like this:

$FRED{"fred"} = "bedrock";  # create (or update) an element
delete $FRED{"barney"};     # remove an element of the database
foreach $key (keys %FRED) { # step through all values
    print "$key has value of $FRED{$key}\n";
}

That last loop has to scan through the entire disk file twice: once to access the keys, and a second time to look up the values from the keys. If you are scanning through a DBM hash, it's generally more disk-efficient to use the each operator, which makes only one pass:

while (($key, $value) = each(%FRED)) {
    print "$key has value of $value\n";
}

If you are accessing system DBM databases, such as the ones created by sendmail or NIS, you must be aware that dubiously written C programs sometimes tack on a trailing NUL (\0) character to the end of their strings. The DBM library routines do not need this NUL (they handle binary data using a byte count, not a NUL-delimited string), and so the NUL is stored as part of the data. You must therefore append a NUL character to the end of your keys and discard the NUL from the end of the returned values to have the data make sense. For example, to look up merlyn in the aliases database, try something like this:

dbmopen(%ALI, "/etc/aliases", undef) || die "no aliases?";
$value = $ALI{"merlyn\0"};                     # note appended NUL
chop($value);                                  # remove appended NUL
print "Randal's mail is headed for: $value\n"; # show result

Your version of UNIX may stick the aliases database over in /usr/lib rather than /etc. You'll have to poke around to find out. Newer versions of sendmail are free of the NUL bug.


Previous: 17.2 Opening and Closing DBM HashesLearning PerlNext: 17.4 Fixed-Length Random Access Databases
17.2 Opening and Closing DBM HashesBook Index17.4 Fixed-Length Random Access Databases