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.