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