
use Fcntl ':seek';

# Take the record at the current position of $fh, 
# and replace it with $rec if possible
sub modify {
  my ($fh, $rec) = @_;
  my $pos = tell $fh;
  chomp(my $oldrec = <$fh>);
  seek $fh, $pos, SEEK_SET;

  if (length $oldrec == length $rec) {
    # easy case
    print $fh $rec;
  } elsif (length $rec < length $oldrec) {
    my $shortfall = length($oldrec) - length($rec);
    my $fill = "\n" x $shortfall;
    print $fh $rec, "\n", $fill;
  } else { # New record is too big
    my $fill = "\n" x length($oldrec);
    print $fh $fill;
    seek $fh, 0, SEEK_END;  # New record goes at the end
    print $fh $rec, "\n";
  }
}

# Locate the first record in the file that starts with '$key'
# Leave the filehandle positioned at its start
# Return the record, or undef if no such record
sub find {
  my ($fh, $key) = @_;
  seek $fh, 0, SEEK_SET;
  my $pos = 0;
  while (<$fh>) {
    chomp;
    next if $fh eq "";
    if (index($_, $key) == 0) {
      seek $fh, $pos, SEEK_SET;
      return $_;
    }
    $pos = tell $fh;
  }
  return;
}

open F, "+<", "MIP" or die $!;

($u, $p) = split /:/, find(\*F, 'gnat');
modify(\*F, "torkington:$p");
($u, $p) = split /:/, find(\*F, 'tchrist');
modify(\*F, "tom:$p");
