3 usage: ../fyvzl [-lLENGTH] [-mMAXPERUSER] [-dDOM] [-qQUALDOM] DATABASE-FILE ACTION ARG
8 update LOCAL-PART REDIRECT-TO
15 insert-exact LOCAL-PART USER REDIRECT
16 donate LOCAL-PART USER
17 enable-user|disable-user USER
26 our $maxperuser = 10000;
34 die "too few arguments\n" unless @ARGV;
36 die "option too late on command line\n" if $v =~ m/^-/;
41 die "too many arguments\n" if @ARGV;
47 $dis_q ||= $dbh->prepare("SELECT * FROM disabled_users WHERE user=?");
49 my $row = $dis_q->fetchrow_arrayref();
55 my $u = $row->{'user'};
57 if (!defined $last_u or $last_u ne $u) {
58 print "# user $u ".(isdisabled($u) ? 'disabled' : 'enabled')."\n";
61 my $pa = $row->{'localpart'};
62 $pa .= '@'.$dom if defined $dom;
63 if (defined $row->{'redirect'}) {
64 print "$pa: $row->{'redirect'}\n";
66 print "# reject $pa\n";
74 read(R, $ch, 1) == 1 or die $!;
77 next unless $o-$v+$lim < 256;
78 # print STDERR "goodrand($lim)=$v\n";
85 return $t if $t =~ m/\@/;
86 die "unqualified redirection target\n" unless defined $qualdom;
87 return $t.'@'.$qualdom;
93 "INSERT INTO addrs (".
94 (join ",", sort keys %$row).
95 ") VALUES (?, ?, ?) ";
96 $dbh->do($stmt, {}, map { $row->{$_} } sort keys %$row);
101 if (@ARGV) { $redirect = nextarg; nomoreargs; } else { $redirect = $user; }
102 $redirect = qualify $redirect;
103 open R, "/dev/urandom" or die $!;
105 my $countq = $dbh->prepare("SELECT count(*) FROM addrs WHERE user=?");
106 $countq->execute($user);
107 my ($count) = $countq->fetchrow_array();
108 die unless defined $count;
109 die "too many aliases for this user\n" if $count >= $maxperuser;
110 my $q = $dbh->prepare("SELECT localpart FROM addrs WHERE localpart=?");
113 $s = chr(ord('a')+goodrand(26));
114 while (length $s < $randlength) {
115 my $v = goodrand(36);
120 # print STDERR "$s\n";
122 my $row = $q->fetchrow_arrayref();
126 my $row = {'localpart'=>$s, 'user'=>$user, 'redirect'=>$redirect};
133 my ($localpart) = @_;
134 my $q = $dbh->prepare("SELECT * FROM addrs WHERE localpart=?");
135 $q->execute($localpart);
136 my $row = $q->fetchrow_hashref();
137 die "unknown localpart\n" unless defined $row;
138 die "not owned by you\n" unless $priv || $row->{user} eq $user;
143 my $localpart = nextarg;
144 my $redirect = qualify nextarg;
146 begin_row($localpart);
147 $dbh->do("UPDATE addrs SET redirect=? WHERE localpart=?",
148 {}, $redirect, $localpart);
153 my $localpart = nextarg;
155 begin_row($localpart);
156 $dbh->do("UPDATE addrs SET redirect=NULL WHERE localpart=?",
162 my $localpart = nextarg;
164 my $row = begin_row($localpart);
170 my $q = $dbh->prepare("SELECT * FROM addrs WHERE user=?".
171 " ORDER BY localpart");
173 while (my $row = $q->fetchrow_hashref()) {
178 sub action_list_user {
185 sub action_insert_exact {
187 my $localpart = nextarg;
189 my $redirect = nextarg;
191 my $row = {'localpart'=>$localpart, 'user'=>$user, 'redirect'=>$redirect};
198 my $localpart = nextarg;
199 my $newuser = nextarg;
201 begin_row($localpart);
202 $dbh->do('UPDATE addrs SET user=? WHERE localpart=?',
203 {}, $newuser, $localpart);
207 sub action_enable_user {
211 $dbh->do('DELETE FROM disabled_users WHERE user=?',{},$user);
215 sub action_disable_user {
219 $dbh->do('INSERT INTO disabled_users VALUES user (?)',{},$user);
223 sub action_list_actions {
224 print $usage2 or die $!;
228 last unless $ARGV[0] =~ m/^-/;
233 } elsif (m/^-m(\d+)$/) {
235 } elsif (m/^-d(\S+)$/) {
237 } elsif (m/^-q(\S+)$/) {
240 print $usage1.$usage2 or die $!;
242 die "unknown option \`$_'\n";
246 my $dbfile = nextarg();
248 if (defined $ENV{'USERV_USER'}) {
250 $user = $ENV{'USERV_USER'};
253 $user = ((getpwuid $<)[0]) or die;
256 $usage2 .= "LOCAL-PART is implicitly qualified with \@$dom\n"
258 $usage2 .= "REDIRECT is implicitly qualified with \@$qualdom if it has no \@\n"
261 $dbh = DBI->connect("dbi:SQLite:dbname=$dbfile","","",
262 { PrintError => 0, AutoCommit => 0, RaiseError => 1 })
265 my $action = nextarg();
267 { no strict qw(refs); &{"action_$action"}(); }