13 ###--------------------------------------------------------------------------
16 my $dom = $Odin::MAIL_DEFDOMAIN
;
19 sub record_opt
(\
%$$) {
20 my ($r, $o, $op) = @_;
22 if ($o eq "c") { $r->{comment
} = $op->arg; }
23 elsif ($o eq "x") { $r->{expire
} = Odin
::parse_time
$op->arg; }
24 elsif ($o eq "r") { $r->{recip
} = $op->arg; }
25 else { return undef; }
29 sub gen_opt
($\
$\
%$$) {
30 my ($dom, $g, $gp, $o, $op) = @_;
33 my $a = $op->arg; next OPT
unless defined $a;
34 $$g = Odin
::get_generator_class
$dom, $a;
36 defined (my $p = $op->arg) or next OPT
;
37 if ($p =~ /^([-\w]+)=(.*)$/) { $gp->{$1} = $2; }
38 else { $op->err("invalid parameter `$p'"); }
45 my $op = Odin
::OptParse
->new(@ARGV);
46 OPT
: while (my $o = $op->get) {
48 $dom = $op->arg or next OPT
;
49 exists $Odin::MAILDOM_POLICY
{$dom} or $op->err("unknown domain `$dom'");
55 print STDERR
"usage: $Odin::PROG [-d DOMAIN] COMMAND [ARGUMENT ...]\n";
60 my $op = shift(@ARGV) // "help";
63 Usage: $Odin::PROG [-d DOMAIN] COMMAND [ARGUMENTS ...]
72 new [-n COUNT] [-GENOPTS] [-RECOPTS] [RECIP]
76 set [-RECOPTS] LPART ...
78 GENOPTS ::= [-g GENERATOR] [-p PARAM=VALUE]
79 RECOPTS ::= [-c COMMENT] [-r RECIP] [-x EXPIRES]
81 } elsif ($op eq "list") {
82 @ARGV and Odin
::fail
"usage: list";
83 for my $r (Odin
::redir_query Odin
::open_db
, $dom, $Odin::WHO
,
84 "st = 'live' AND (expire = -1 OR expire >= ?)", $Odin::NOW
) {
85 my ($lpart, $expire, $recip, $comment) = @
$r;
87 Odin
::fmt_time
$expire => 25,
88 $lpart => 24, $recip => 32, $comment => 0;
90 } elsif ($op eq "dormant") {
91 @ARGV and Odin
::fail
"usage: list";
92 for my $r (Odin
::redir_query Odin
::open_db
, $dom, $Odin::WHO
,
94 (st = 'live' AND expire <> -1 AND expire < ?))",
96 my ($lpart, $expire, $recip, $comment) = @
$r;
97 Odin
::print_columns
$lpart => 24, $recip => 32, $comment => 0;
99 } elsif ($op eq "giveaway") {
100 @ARGV >= 2 or Odin
::fail
"usage: giveaway OWNER LPART ...";
101 my $owner = shift @ARGV;
103 getpwnam $owner or Odin
::fail
"unknown user `$owner'";
104 my %r = (owner
=> $owner);
105 Odin
::modify_redir
$dom, %r, @l;
106 } elsif ($op eq "reserved") {
107 @ARGV and Odin
::fail
"usage: reserved";
108 for my $r (Odin
::redir_query Odin
::open_db
, $dom, $Odin::WHO
,
109 "st = 'reserved' AND expire >= ?", $Odin::NOW
) {
110 my ($lpart, $expire, $recip, $comment) = @
$r;
111 Odin
::print_columns Odin
::fmt_time
$expire => 25, $lpart => 0;
113 } elsif ($op eq "new") {
114 my $op = Odin
::OptParse
->new(@ARGV);
115 my $gencls = Odin
::default_generator_class
$dom;
119 while (my $o = $op->get) {
120 if ($o eq "n") { $n = $op->intarg(undef, 0) }
122 gen_opt
$dom, $gencls, %gp, $o, $op
123 or record_opt
%r, $o, $op
128 if (@a) { $r{recip
} = shift @a; }
131 Odin
::fail
"usage: new [-n COUNT] [-GENOPTS] [-RECOPTS] [RECIP]";
132 my $gen = $gencls->new($dom, \
%gp);
133 my @l = Odin
::new_redir
$dom, $gen, %r, $n;
134 print map { $_ . "\n" } @l;
135 } elsif ($op eq "reserve") {
136 my $op = Odin
::OptParse
->new(@ARGV);
137 my $gencls = Odin
::default_generator_class
$dom;
139 while (my $o = $op->get) {
140 gen_opt
$dom, $gencls, %gp, $o, $op
147 $n =~ /^\d+$/ or $op->err("invalid count `$n'");
150 $op->ok or Odin
::fail
"usage: reserve [-GENOPTS] N";
151 my $gen = $gencls->new($dom, \
%gp);
152 for my $l (Odin
::reserve_redir
$dom, $gen, $n) { print $l, "\n"; }
153 } elsif ($op eq "release") {
154 my $op = Odin
::OptParse
->new(@ARGV);
156 while (my $o = $op->get) {
157 if ($o eq "a") { $all = 1; }
161 !!$all == !@a or $op->bad;
162 $op->ok or Odin
::fail
"usage: release {-a | LPART ...}";
163 if ($all) { Odin
::release_all_redir
$dom; }
164 else { Odin
::release_redir
$dom, @a; }
165 } elsif ($op eq "disable") {
166 @ARGV or Odin
::fail
"usage: disable LPART ...";
167 Odin
::disable_redir
$dom, @ARGV;
168 } elsif ($op eq "set") {
169 my $op = Odin
::OptParse
->new(@ARGV);
171 while (my $o = $op->get) {
172 record_opt
%r, $o, $op
177 $op->ok or Odin
::fail
"usage: set [-RECOPTS] LPART ...";
178 Odin
::modify_redir
$dom, %r, @a;
180 Odin
::fail
"unknown operation `$op'";