Imported upstream version 0.60.1
[hcoop/debian/courier-authlib.git] / userdb / userdb.pl.in
CommitLineData
d9898ee8 1#! @PERL@
dd184caf 2#$Id: userdb.pl.in,v 1.13 2007/10/07 02:50:45 mrsam Exp $
d9898ee8 3#
4# Copyright 1998 - 1999 Double Precision, Inc. See COPYING for
5# distribution information.
6
7use Fcntl ':flock';
8
9$prefix="@prefix@";
10$exec_prefix="@exec_prefix@";
11$userdb="@userdb@";
12
13eval {
14 die "SYMLINK\n" if -l $userdb;
15};
16
17die "ERROR: Wrong userdb command.\n ($userdb is a symbolic link)\n"
18 if $@ eq "SYMLINK\n";
19
20sub usage {
21 print "Usage: $0 [path/.../ | -f file ]name set field=value field=value...\n";
22 print " $0 [path/.../ | -f file ]name unset field field...\n";
23 print " $0 [path/.../ | -f file ]name del\n";
24 print " $0 -show [path/... | -f file ] [name]\n";
25 exit 1;
26}
27
28$name=shift @ARGV;
29$doshow=0;
30
31if ($name eq "-show")
32{
33 $doshow=1;
34 $name=shift @ARGV;
35}
36
37if ($name eq "-f")
38{
39 $userdb=shift @ARGV;
40 $name=shift @ARGV;
41}
42elsif ( $name =~ /^(.*)\/([^\/]*)$/ )
43{
44 $userdb="$userdb/$1";
45 $name=$2;
46}
47
48
49if ($doshow)
50{
51 &usage unless $userdb =~ /./;
52}
53else
54{
55 $verb=shift @ARGV;
56
57 &usage unless $verb =~ /./ && $name =~ /./ && $userdb =~ /./;
58}
59
60while (defined ($link= &safe_readlink($userdb)))
61{
62 $userdb .= "/";
63 $userdb = "" if $link =~ /^\//;
64 $userdb .= $link;
65}
66
67$tmpuserdb= $userdb =~ /^(.*)\/([^\/]*)$/ ? "$1/.tmp.$2":".tmp.$userdb";
68$lockuserdb= $userdb =~ /^(.*)\/([^\/]*)$/ ? "$1/.lock.$2":".lock.$userdb";
69
70if ( $doshow && ! defined $name)
71{
72}
73else
74{
75 die "Invalid name: $name\n"
dd184caf 76 unless $name =~ /^[\@a-zA-Z0-9\.\-\_\:\+]+$/;
d9898ee8 77}
78
79grep( (/[\|\n]/ && die "Invalid field or value.\n"), @ARGV);
80
81umask(066);
82
83open(LOCK, ">$lockuserdb") or die "Can't open $lockuserdb: $!";
84flock(LOCK,LOCK_EX) || die "Can't lock $lockuserdb: $!";
85
86if ( $doshow )
87{
88 if (open (OLDFILE, $userdb))
89 {
90 stat(OLDFILE);
91 die "$userdb: not a file.\n" unless -f _;
92
93 while ( defined($_=<OLDFILE>) )
94 {
95 chop if /\n$/;
96 next if /^#/;
97 next unless /^([^\t]+)(\t(.*))?$/;
98 ($addr,$vals)=($1,$3);
99 if (defined $name)
100 {
101 if ($name eq $addr)
102 {
103 $vals =~ s/\|/\n/g;
104 print "$vals\n";
105 last;
106 }
107 }
108 else
109 {
110 print "$addr\n";
111 }
112 }
113 }
114 close (OLDFILE);
115}
116elsif ( $verb eq "set" )
117{
118 $isatty=1;
119
120 eval {
121 $isatty=0 unless -t STDIN;
122 } ;
123
124 &doadd;
125 $mode= (stat $userdb)[2];
126 chmod ($mode & 0777,$tmpuserdb ) if defined $mode;
127 rename $tmpuserdb,$userdb;
128}
129elsif ( $verb eq "unset" )
130{
131 if ($#ARGV >= 0 && &dodel)
132 {
133 $mode= (stat $userdb)[2];
134 chmod ($mode & 0777 ,$tmpuserdb) if defined $mode;
135 rename ($tmpuserdb,$userdb)
136 }
137}
138elsif ( $verb eq "del" )
139{
140 &usage unless $#ARGV < 0;
141 if (&dodel)
142 {
143 $mode= (stat $userdb)[2];
144 chmod ($mode & 0777 ,$tmpuserdb) if defined $mode;
145 rename ($tmpuserdb,$userdb)
146 }
147}
148else
149{
150 &usage;
151}
152exit 0;
153
154sub doadd {
155my (%FIELDS);
156my ($key, $in);
157
158 foreach $key (@ARGV)
159 {
160 next if $key =~ /=/;
161 print "$name.$key: " if $isatty;
162 exit 1 unless defined ($in=<STDIN>);
163 chop $in if $in =~ /\n$/;
164 die "Invalid value.\n" if $in =~ /[\|\n]/;
165 $key = "$key=$in";
166 }
167
168 open (NEWFILE, ">$tmpuserdb") || die "$!\n";
169 if (open (OLDFILE, $userdb))
170 {
171 stat(OLDFILE);
172 die "$userdb: not a file.\n" unless -f _;
173 while ( defined($_=<OLDFILE>) )
174 {
175 chop if /\n$/;
176 if ( /^([^\t]+)(\t(.*))?$/ && ($1 eq $name))
177 {
178 grep( (/^([^=]*)(=.*)?$/,
179 $FIELDS{$1}="$2"), split(/\|/, $3));
180 while ( defined ($key=shift @ARGV))
181 {
182 $key =~ /^([^=]*)(=.*)?$/;
183 $FIELDS{$1}="$2";
184 }
185 $name="$name\t";
186 grep ( $name="$name$_$FIELDS{$_}|",
187 keys %FIELDS);
188 chop $name;
189 print NEWFILE "$name\n" || die "$!\n";
190 while (<OLDFILE>)
191 {
192 print NEWFILE || die "$!\n";
193 }
194 close (OLDFILE);
195 close (NEWFILE) || die "$!\n";
196 return;
197 }
198 print NEWFILE "$_\n" || die "$!\n";
199 }
200 close (OLDFILE);
201 }
202
203 $name="$name\t";
204 grep ( $name="$name$_|", @ARGV );
205 chop $name;
206 print NEWFILE "$name\n" || die "$!\n";
207 close (NEWFILE) || die "$!\n";
208}
209
210sub dodel {
211my (%FIELDS);
212
213 open (NEWFILE, ">$tmpuserdb") || die "$!\n";
214 if (open (OLDFILE, $userdb))
215 {
216 stat(OLDFILE);
217 die "$userdb: not a file.\n" unless -f _;
218 while ( defined($_=<OLDFILE>) )
219 {
220 chop if /\n$/;
221 if ( /^([^\t]+)(\t(.*))?$/ && ($1 eq $name))
222 {
223 if ($#ARGV >= 0)
224 {
225 grep( (/^([^=]*)(=.*)?$/,
226 $FIELDS{$1}=$2),
227 split(/\|/, $3));
228 grep( delete $FIELDS{$_}, @ARGV);
229
230 $name="$name\t";
231 grep ( $name="$name$_$FIELDS{$_}|",
232 keys %FIELDS);
233 chop $name;
234 $name="$name\n";
235 print NEWFILE "$name" || die "$!\n";
236 }
237 while (<OLDFILE>)
238 {
239 print NEWFILE || die "$!\n";
240 }
241 close (OLDFILE);
242 close (NEWFILE) || die "$!\n";
243 return (1);
244 }
245 print NEWFILE "$_\n" || die "$!\n";
246 }
247 close (OLDFILE);
248 }
249 unlink "$tmpuserdb";
250 return (0);
251}
252
253sub safe_readlink {
254my ($l)=@_;
255my ($err,$link);
256
257 eval {
258
259 $link=readlink($l);
260 } ;
261
262 $link=undef if $@;
263 return $link;
264}