From: Mark Wooding Date: Fri, 7 Aug 2015 06:56:29 +0000 (+0100) Subject: Merge branch 'master' of git://git.distorted.org.uk/~mdw/odin-cgi X-Git-Url: https://git.distorted.org.uk/~mdw/odin-cgi/commitdiff_plain/3e12ff54361d996cd64056a76b45f69abeec278d?hp=fdabfd1375a8b9c8201ffe3d947b330e18dc1cc7 Merge branch 'master' of git://git.distorted.org.uk/~mdw/odin-cgi * 'master' of git://git.distorted.org.uk/~mdw/odin-cgi: lib/Odin.pm: Alter `redir_query' to break ties by local part. bin/mailredir.userv, lib/Odin.pm: Modify multiple redirections at once. bin/mailredir.userv, lib/Odin.pm: Allocate multiple local parts at once. lib/Odin.pm: New function for parsing and checking integer arguments. --- diff --git a/bin/mailredir.userv b/bin/mailredir.userv index ab8b54d..f5acb06 100755 --- a/bin/mailredir.userv +++ b/bin/mailredir.userv @@ -68,11 +68,11 @@ Commands available: dormant help list - new [-GENOPTS] [-RECOPTS] RECIP + new [-n COUNT] [-GENOPTS] [-RECOPTS] [RECIP] release LPART ... reserve [-GENOPTS] N reserved - set [-RECOPTS] LPART + set [-RECOPTS] LPART ... GENOPTS ::= [-g GENERATOR] [-p PARAM=VALUE] RECOPTS ::= [-c COMMENT] [-r RECIP] [-x EXPIRES] @@ -107,18 +107,23 @@ EOF my $gencls = Odin::default_generator_class $dom; my %gp = (); my %r = (); + my $n = 1; while (my $o = $op->get) { - gen_opt $dom, $gencls, %gp, $o, $op - or record_opt %r, $o, $op - or $op->unk; + if ($o eq "n") { $n = $op->intarg(undef, 0) } + else { + gen_opt $dom, $gencls, %gp, $o, $op + or record_opt %r, $o, $op + or $op->unk; + } } my @a = $op->rest; if (@a) { $r{recip} = shift @a; } !@a or $op->bad; - $op->ok or Odin::fail "usage: new [-GENOPTS] [-RECOPTS] RECIP"; + $op->ok or + Odin::fail "usage: new [-n COUNT] [-GENOPTS] [-RECOPTS] [RECIP]"; my $gen = $gencls->new($dom, \%gp); - my $l = Odin::new_redir $dom, $gen, %r; - print $l, "\n"; + my @l = Odin::new_redir $dom, $gen, %r, $n; + print map { $_ . "\n" } @l; } elsif ($op eq "reserve") { my $op = Odin::OptParse->new(@ARGV); my $gencls = Odin::default_generator_class $dom; @@ -160,10 +165,9 @@ EOF or $op->unk; } my @a = $op->rest; - my $l = shift @a or $op->bad; - @a and $op->bad; - $op->ok or Odin::fail "usage: set [-RECOPTS] LPART"; - Odin::modify_redir $dom, $l, %r; + @a or $op->bad; + $op->ok or Odin::fail "usage: set [-RECOPTS] LPART ..."; + Odin::modify_redir $dom, %r, @a; } else { Odin::fail "unknown operation `$op'"; } diff --git a/lib/Odin.pm b/lib/Odin.pm index 7182af2..a742839 100644 --- a/lib/Odin.pm +++ b/lib/Odin.pm @@ -501,7 +501,7 @@ sub redir_query ($$$;$@) { ("SELECT lpart, expire, recip, comment FROM odin_mailredir WHERE dom = ? AND owner = ?" . (defined $cond ? " AND $cond" : "") . " " . - "ORDER BY expire", undef, $dom, $owner, @args)}; + "ORDER BY expire, lpart", undef, $dom, $owner, @args)}; } sub clear_redir_reservations ($) { @@ -574,23 +574,27 @@ sub check_fixup_redir ($) { } } -sub new_redir ($$\%) { - my ($dom, $gen, $r) = @_; +sub new_redir ($$\%;$) { + my ($dom, $gen, $r, $n) = @_; my $db = open_db; - my $l; + my @l; + $n //= 1; check_fixup_redir $r; Odin::xact { clear_redir_reservations $db; - $l = Odin::gen_redir_name $db, $gen; - insert_record $db, "odin_mailredir", - lpart => $l, dom => $dom, owner => $WHO, st => 'live', - recip => $r->{recip} // qualify_recip $Odin::WHO, - expire => $r->{expire} // -1, - comment => $r->{comment} // ""; + while (@l < $n) { + my $l = Odin::gen_redir_name $db, $gen; + insert_record $db, "odin_mailredir", + lpart => $l, dom => $dom, owner => $WHO, st => 'live', + recip => $r->{recip} // qualify_recip $Odin::WHO, + expire => $r->{expire} // -1, + comment => $r->{comment} // ""; + push @l, $l; + } check_redir_limits $db; } $db; - return $l; + return @l; } sub reserve_redir ($$$) { @@ -657,31 +661,34 @@ sub disable_redir ($$) { } $db; } -sub modify_redir ($$\%) { - my ($dom, $l, $r) = @_; +sub modify_redir ($\%@) { + my ($dom, $r, @l) = @_; my $db = open_db; check_fixup_redir $r; Odin::xact { clear_redir_reservations $db; - my ($recip, $st) = $db->selectrow_array - ("SELECT recip, st FROM odin_mailredir - WHERE lpart = ? AND dom = ? AND owner = ?", undef, - $l, $dom, $WHO); - if (!defined $recip) { Odin::fail "unknown local part `$l'"; } - elsif ($recip eq "") { $r->{recip} //= qualify_recip $WHO; } - if ($st ne "live") { $r->{st} = "live"; $r->{expire} //= -1; } - my @var = (); - my @val = (); - for my $v (keys %$r) { - push @var, $v; - push @val, $r->{$v}; + for my $l (@l) { + my %r = %$r; + my ($recip, $st) = $db->selectrow_array + ("SELECT recip, st FROM odin_mailredir + WHERE lpart = ? AND dom = ? AND owner = ?", undef, + $l, $dom, $WHO); + if (!defined $recip) { Odin::fail "unknown local part `$l'"; } + elsif ($recip eq "") { $r{recip} //= qualify_recip $WHO; } + if ($st ne "live") { $r{st} = "live"; $r{expire} //= -1; } + my @var = (); + my @val = (); + for my $v (keys %r) { + push @var, $v; + push @val, $r{$v}; + } + @var or fail "nothing to change"; + $db->do("UPDATE odin_mailredir SET " . + join(", ", map { "$_ = ?" } @var) . " " . + "WHERE lpart = ? AND dom = ?", undef, + @val, $l, $dom); } - @var or fail "nothing to change"; - $db->do("UPDATE odin_mailredir SET " . - join(", ", map { "$_ = ?" } @var) . " " . - "WHERE lpart = ? AND dom = ?", undef, - @val, $l, $dom); } $db; } @@ -723,6 +730,19 @@ sub arg { return $a; } +sub intarg { + my ($me, $what, $min, $max) = @_; + $what //= "option `-$me->{opt}'"; + defined (my $a = $me->arg) or return undef; + if ($a !~ /^[-+]?\d+$/ || + (defined $min && $a < $min) || + (defined $max && $a > $max)) { + $me->err("invalid value `$a' for $what"); + $a = undef; + } + return $a; +} + sub rest { return @{$_[0]->{args}}; } sub ok { return $_[0]->{ok}; } sub bad { $_[0]->{ok} = 0; }