3 usage: ../fyvzl [OPTIONS DATABASE-FILE ACTION ARG
9 -C (show comments in output)
12 our $usage2 = <<'END';
14 create [REDIRECT] [#COMMENT]
15 update LOCAL-PART [REDIRECT] [#COMMENT]
19 empty value for REDIRECT means reject
21 our $usage3 = <<'END';
24 insert-exact LOCAL-PART USER REDIRECT COMMENT
25 donate LOCAL-PART USER
26 enable-user|disable-user USER
35 our $maxperuser = 10000;
44 die "too few arguments\n" unless @ARGV;
46 die "option too late on command line\n" if $v =~ m/^-/;
51 die "too many arguments\n" if @ARGV;
57 $dis_q ||= $dbh->prepare("SELECT * FROM disabled_users WHERE user=?");
59 my $row = $dis_q->fetchrow_arrayref();
65 my $u = $row->{'user'};
67 if (!defined $last_u or $last_u ne $u) {
68 print "# user $u ".(isdisabled($u) ? 'disabled' : 'enabled')."\n";
71 my $pa = $row->{'localpart'};
72 $pa .= '@'.$dom if defined $dom;
73 if (length $row->{'redirect'}) {
74 print "$pa: $row->{'redirect'}" or die $!;
76 print "# reject $pa" or die $!;
78 if ($showcomment || !$priv) {
79 print " #$row->{'comment'}" or die $!;
88 read(R, $ch, 1) == 1 or die $!;
91 next unless $o-$v+$lim < 256;
92 # print STDERR "goodrand($lim)=$v\n";
99 if (defined $$ref && $$ref =~ m/[^\041-\177]/) {
100 die "bad characters in redirection target\n";
102 if (defined $$ref && length $$ref && $$ref !~ m/\@/) {
103 die "unqualified redirection target\n" unless defined $qualdom;
104 $$ref .= '@'.$qualdom;
111 "INSERT INTO addrs (".
112 (join ",", sort keys %$row).
114 (join ",", map { "?" } sort keys %$row).
116 $dbh->do($stmt, {}, map { $row->{$_} } sort keys %$row);
123 my $f = (s/^\#// ? 'comment' : 'redirect');
124 die "$f supplied twice\n" if exists $row->{$f};
127 qualify $row->{'redirect'};
132 my $newrow = rhsargs({'redirect'=>$user, 'comment'=>''});
133 open R, "/dev/urandom" or die $!;
135 my $countq = $dbh->prepare("SELECT count(*) FROM addrs WHERE user=?");
136 $countq->execute($user);
137 my ($count) = $countq->fetchrow_array();
138 die unless defined $count;
139 die "too many aliases for this user\n" if $count >= $maxperuser;
140 my $q = $dbh->prepare("SELECT localpart FROM addrs WHERE localpart=?");
143 $s = chr(ord('a')+goodrand(26));
144 while (length $s < $randlength) {
145 my $v = goodrand(36);
150 # print STDERR "$s\n";
152 my $row = $q->fetchrow_arrayref();
156 $newrow->{'user'} = $user;
157 $newrow->{'localpart'} = $s;
164 my ($localpart) = @_;
165 our $row_q ||= $dbh->prepare("SELECT * FROM addrs WHERE localpart=?");
166 $row_q->execute($localpart);
167 return $row_q->fetchrow_hashref();
171 my ($localpart) = @_;
172 my $q = $dbh->prepare("SELECT * FROM addrs WHERE localpart=?");
173 my $row = selectrow $localpart;
174 die "unknown localpart\n" unless defined $row;
175 die "not owned by you\n" unless $priv || $row->{user} eq $user;
180 my $localpart = nextarg;
181 my $updrow = rhsargs({});
183 begin_row($localpart);
184 foreach my $f (qw(redirect comment)) {
185 my $v = $updrow->{$f};
186 next unless defined $v;
187 $dbh->do("UPDATE addrs SET $f=? WHERE localpart=?",
190 my $row = selectrow $localpart;
196 my $localpart = nextarg;
198 my $row = begin_row($localpart);
204 my $q = $dbh->prepare("SELECT * FROM addrs WHERE user=?".
205 " ORDER BY localpart");
207 while (my $row = $q->fetchrow_hashref()) {
212 sub action_list_user {
219 sub action_insert_exact {
222 $row->{'localpart'} = nextarg;
223 $row->{'user'} = $user = nextarg;
224 $row->{'redirect'} = nextarg;
225 $row->{'comment'} = nextarg;
233 my $localpart = nextarg;
234 my $newuser = nextarg;
236 begin_row($localpart);
237 $dbh->do('UPDATE addrs SET user=? WHERE localpart=?',
238 {}, $newuser, $localpart);
242 sub action_enable_user {
246 $dbh->do('DELETE FROM disabled_users WHERE user=?',{},$user);
250 sub action_disable_user {
254 $dbh->do('INSERT INTO disabled_users VALUES user (?)',{},$user);
258 sub action_list_actions {
259 print $usage2 or die $!;
263 last unless $ARGV[0] =~ m/^-/;
270 } elsif (s/^-m(\d+)$//) {
272 } elsif (s/^-d(\S+)$//) {
274 } elsif (s/^-q(\S+)$//) {
279 print $usage1.$usage2.$usage3 or die $!;
282 die "unknown option \`$_'\n";
287 my $dbfile = nextarg();
289 if (defined $ENV{'USERV_USER'}) {
291 $user = $ENV{'USERV_USER'};
294 $user = ((getpwuid $<)[0]) or die;
297 $usage2 .= "LOCAL-PART is implicitly qualified with \@$dom\n"
299 $usage2 .= "REDIRECT is implicitly qualified with \@$qualdom if it has no \@\n"
302 $dbh = DBI->connect("dbi:SQLite:dbname=$dbfile","","",
303 { PrintError => 0, AutoCommit => 0, RaiseError => 1 })
306 my $action = nextarg();
308 { no strict qw(refs); &{"action_$action"}(); }