+#!/usr/bin/perl -w
+#
+# convert from linux passwd/shadow to master.passwd
+#
+use strict;
+use Class::Date qw(:errors date now);
+use Data::Dumper;
+
+
+sub read_file {
+ my ($f, $data, $fields) = @_;
+
+ open(FH, '<', $f) || die "can't open $f";
+ while (<FH>) {
+ chomp;
+ my @list = split(':');
+
+ for (my $i = 0; $i < scalar(@$fields); $i++) {
+ $data->{$list[0]}->{$fields->[$i]} = $list[$i];
+ }
+ }
+ close(FH);
+}
+
+sub write_file {
+ my ($fh, $data, $fields) = @_;
+
+ foreach my $key (keys(%$data)) {
+ print $fh join(':', map { my $x = $data->{$key}->{$_}; die $_ unless(defined($x)); $x } @$fields), "\n";
+ }
+}
+
+sub read_passwd {
+ my ($f, $users) = @_;
+ &read_file($f, $users,
+ ['login', 'pw', 'uid', 'gid', 'gecos', 'home', 'shell']);
+}
+
+sub read_shadow {
+ my ($f, $users) = @_;
+ &read_file($f, $users,
+ ['login', 'pw', 'last_changed', 'may_change', 'must_change', 'expire_warn', 'disable', 'disabled_since', 'reserved']);
+}
+
+sub write_bsd {
+ my ($users) = @_;
+ &write_file(\*STDOUT, $users,
+ [ 'login', 'pw', 'uid', 'gid', 'class', 'change', 'expire', 'gecos', 'home', 'shell' ]);
+}
+
+sub days_to_epoch_seconds {
+ my ($days) = @_;
+ my $from = now;
+ my $rel = new Class::Date::Rel { day => $days };
+ my $r = $from+$rel;
+ return $r->epoch;
+}
+
+sub conv_class {
+ my ($u, $d) = @_;
+ $d->{'class'} = '';
+}
+
+sub conv_change {
+ my ($u, $d) = @_;
+ my $f = $d->{'must_change'};
+
+ if (defined($f) && $f > 0) {
+ $d->{'change'} = &days_to_epoch_seconds($f);
+ } elsif ($f == '-1') {
+ $d->{'change'} = -1;
+ } else {
+ $d->{'change'} = '';
+ }
+}
+
+sub conv_expire {
+ my ($u, $d) = @_;
+ $d->{'expire'} = '';
+}
+
+sub conv_fields {
+ my ($data) = @_;
+
+ while (my ($user, $data) = each(%$data)) {
+ &conv_class($user, $data);
+ &conv_change($user, $data);
+ &conv_expire($user, $data);
+ }
+}
+
+sub usage {
+ print STDERR "Usage: $0 <passwd> <shadow>\n";
+ exit 1;
+}
+
+sub main {
+ &usage() if (scalar(@ARGV) != 2);
+ my %users;
+
+ &read_passwd($ARGV[0], \%users);
+ &read_shadow($ARGV[1], \%users);
+ &conv_fields(\%users);
+ &write_bsd(\%users);
+}
+
+&main;
+
+# all done!