1#! @PERL@
2#
3# Create userdb database
4#
5# Usage: makeuserdb
6#
7#
8# Copyright 1998 - 2006 Double Precision, Inc.  See COPYING for
9# distribution information.
10
11use Fcntl ':flock';
12
13$prefix="@prefix@";
14$exec_prefix="@exec_prefix@";
15$bindir="@bindir@";
16
17$ENV{'PATH'}="@bindir@:/usr/bin:/usr/local/bin:/bin";
18
19$dbfile="@userdb@";
20
21$makedat="@makedat@";
22
23$name=shift @ARGV;
24if ($name eq "-f") {
25	$dbfile=shift @ARGV;
26	$dbfile=~s/\/$//;
27}
28
29$datfile=$dbfile.".dat";
30# XXX the lock file here is etc/userdb.lock but the userdb command uses etc/.lock.userdb
31$lockfile=$dbfile.".lock";
32$shadowfile=$dbfile."shadow.dat";
33$tmpdatfile=$dbfile.".tmp";
34$tmpshadowfile=$dbfile."shadow.tmp";
35
36$mode=(stat($dbfile))[2];
37die "$dbfile: not found.\n" unless defined $mode;
38
39die "$dbfile: MAY NOT HAVE GROUP OR WORLD PERMISSIONS!!\n"
40	if ( $mode & 077);
41
42eval {
43	die "SYMLINK\n" if -l $dbfile;
44};
45
46die "ERROR: Wrong makeuserdb command.\n       ($dbfile is a symbolic link)\n"
47	if $@ eq "SYMLINK\n";
48
49eval {
50	die "SYMLINK\n" if -l $datfile;
51};
52
53die "ERROR: Wrong makeuserdb command.\n       ($datfile is a symbolic link)\n"
54	if $@ eq "SYMLINK\n";
55
56eval {
57	die "SYMLINK\n" if -l $shadowfile;
58};
59
60die "ERROR: Wrong makeuserdb command.\n       ($shadowfile is a symbolic link)\n"
61	if $@ eq "SYMLINK\n";
62
63umask (022);
64open(LOCK, ">$lockfile") or die "Can't open $lockfile: $!";
65flock(LOCK,LOCK_EX) || die "Can't lock $lockfile: $!";
66
67open (DBPIPE, "| ${makedat} - $tmpdatfile $datfile") || die "$!\n";
68umask (066);
69open (SHADOWPIPE, "| ${makedat} - $tmpshadowfile $shadowfile")
70	|| die "$!\n";
71
72eval {
73
74	if ( -d $dbfile )
75	{
76	my (@dirs);
77	my (@files);
78
79		push @dirs, $dbfile;
80		while ( $#dirs >= 0 )
81		{
82			$dir=shift @dirs;
83			opendir(DIR, $dir) || die "$!\n";
84			while ( defined($filename=readdir(DIR)))
85			{
86				next if $filename =~ /^\./;
87				if ( -d "$dir/$filename" )
88				{
89					push @dirs, "$dir/$filename";
90				}
91				else
92				{
93					push @files, "$dir/$filename";
94				}
95			}
96			closedir(DIR);
97		}
98
99		while (defined ($filename=shift @files))
100		{
101			&do_file( $filename );
102		}
103	}
104	else
105	{
106		&do_file( $dbfile );
107	}
108
109	print DBPIPE ".\n" || die "$!\n";
110	print SHADOWPIPE ".\n" || die "$!\n";
111} ;
112
113$err=$@;
114if ($err)
115{
116	print "$err";
117	exit (1);
118}
119
120close(DBPIPE) || die "$!\n";
121exit (1) if $?;
122close(SHADOWPIPE) || die "$!\n";
123exit (1) if $?;
124
125exit (0);
126
127sub do_file {
128my ($filename)=@_;
129my ($addr, $fields);
130my (@nonshadow, @shadow);
131
132my $location=substr($filename, length("@userdb@"));
133
134	$location =~ s/^\///;
135	$location =~ s/\/$//;
136	$location .= "/" if $location ne "";
137
138	open (F, $filename) || die "$filename: $!\n";
139	while (<F>)
140	{
141		if ( /^[\n#]/ || ! /^([^\t]*)\t(.*)/ )
142		{
143			print DBPIPE;
144			print SHADOWPIPE;
145			next;
146		}
147		($addr,$fields)=($1,$2);
148		undef @nonshadow;
149		undef @shadow;
150
151		foreach ( split (/\|/, $fields ) )
152		{
153			if ( /^[^=]*pw=/ )
154			{
155				push @shadow, $_;
156			}
157			else
158			{
159				push @nonshadow, $_;
160			}
161		}
162
163		push @nonshadow, "_=$location";
164		( print DBPIPE "$addr\t" . join("|", @nonshadow) . "\n"
165			|| die "$!\n" ) if $#nonshadow >= 0;
166		( print SHADOWPIPE "$addr\t" . join("|", @shadow) . "\n"
167			|| die "$!\n" ) if $#shadow >= 0;
168	}
169	print DBPIPE "\n";
170	print SHADOWPIPE "\n";
171}
172