Imported upstream version 0.60.1
[hcoop/debian/courier-authlib.git] / userdb / userdb.pl.in
1 #! @PERL@
2 #$Id: userdb.pl.in,v 1.13 2007/10/07 02:50:45 mrsam Exp $
3 #
4 # Copyright 1998 - 1999 Double Precision, Inc. See COPYING for
5 # distribution information.
6
7 use Fcntl ':flock';
8
9 $prefix="@prefix@";
10 $exec_prefix="@exec_prefix@";
11 $userdb="@userdb@";
12
13 eval {
14 die "SYMLINK\n" if -l $userdb;
15 };
16
17 die "ERROR: Wrong userdb command.\n ($userdb is a symbolic link)\n"
18 if $@ eq "SYMLINK\n";
19
20 sub 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
31 if ($name eq "-show")
32 {
33 $doshow=1;
34 $name=shift @ARGV;
35 }
36
37 if ($name eq "-f")
38 {
39 $userdb=shift @ARGV;
40 $name=shift @ARGV;
41 }
42 elsif ( $name =~ /^(.*)\/([^\/]*)$/ )
43 {
44 $userdb="$userdb/$1";
45 $name=$2;
46 }
47
48
49 if ($doshow)
50 {
51 &usage unless $userdb =~ /./;
52 }
53 else
54 {
55 $verb=shift @ARGV;
56
57 &usage unless $verb =~ /./ && $name =~ /./ && $userdb =~ /./;
58 }
59
60 while (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
70 if ( $doshow && ! defined $name)
71 {
72 }
73 else
74 {
75 die "Invalid name: $name\n"
76 unless $name =~ /^[\@a-zA-Z0-9\.\-\_\:\+]+$/;
77 }
78
79 grep( (/[\|\n]/ && die "Invalid field or value.\n"), @ARGV);
80
81 umask(066);
82
83 open(LOCK, ">$lockuserdb") or die "Can't open $lockuserdb: $!";
84 flock(LOCK,LOCK_EX) || die "Can't lock $lockuserdb: $!";
85
86 if ( $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 }
116 elsif ( $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 }
129 elsif ( $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 }
138 elsif ( $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 }
148 else
149 {
150 &usage;
151 }
152 exit 0;
153
154 sub doadd {
155 my (%FIELDS);
156 my ($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
210 sub dodel {
211 my (%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
253 sub safe_readlink {
254 my ($l)=@_;
255 my ($err,$link);
256
257 eval {
258
259 $link=readlink($l);
260 } ;
261
262 $link=undef if $@;
263 return $link;
264 }