ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/AnyEvent-MP/bin/aemp
Revision: 1.3
Committed: Mon Aug 10 19:19:30 2009 UTC (14 years, 9 months ago) by root
Branch: MAIN
Changes since 1.2: +1 -9 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.1 #!/opt/bin/perl
2    
3     =head1 NAME
4    
5     aemp - AnyEvent:MP utility
6    
7     =head1 SYNOPSIS
8    
9     aemp command args...
10    
11     # protocol commands
12     aemp snd <port> <arg...> # send a message
13     aemp mon <port> # wait till port is killed
14    
15     # node configuration: secret
16     aemp gensecret # generate a random shared secret
17     aemp setsecret <secret> # set the shared secret
18     aemp clrsecret # remove the secret
19    
20     # node configuration: TLS
21     aemp setcert <file> # set a certificate (key.pem + certificate.pem)
22     aemp clrcert # remove certificate
23     aemp gencert # generate a random certificate
24    
25     =head1 DESCRIPTION
26    
27     With aemp you can configure various aspects of AnyEvent::MP and it's protocol.
28    
29     =cut
30    
31     use common::sense;
32    
33     use Carp ();
34    
35     use AnyEvent;
36     use AnyEvent::MP::Config;
37     use AnyEvent::MP;
38    
39     sub run_cmd {
40     my $cmd = shift;
41    
42     require POSIX;
43    
44     local $^F = 1023; #d#
45    
46     my $cv = AE::cv;
47    
48     my %redir;
49     my @exe;
50    
51     while (@_) {
52     my $type = shift;
53    
54     my $fd = $type =~ s/^(\d+)// ? $1 : undef;
55    
56     if ($type eq ">") {
57     my ($pr, $pw) = AnyEvent::Util::portable_pipe;
58     my $cb = shift;
59    
60     $cv->begin;
61     my $w; $w = AE::io $pr, 0,
62     "SCALAR" eq ref $cb
63     ? sub {
64     sysread $pr, $$cb, 8192, length $$cb
65     and return;
66     undef $w; $cv->end;
67     }
68     : sub {
69     my $buf;
70     sysread $pr, $buf, 8192
71     and return $cb->($buf);
72     undef $w; $cv->end;
73     }
74     ;
75     $redir{defined $fd ? $fd : 1} = $pw;
76    
77 root 1.2 } elsif ($type eq "<") {
78     my ($pr, $pw) = AnyEvent::Util::portable_pipe;
79     my $cb = shift;
80    
81     #TODO
82     # $cv->begin;
83     # my $w; $w = AE::io $pw, 0,
84     # "SCALAR" eq ref $cb
85     # ? sub {
86     # my $len = syswrite $pr, $$cb, 8192, length $$cb
87     # and return;
88     # undef $w; $cv->end;
89     # }
90     # : sub {
91     # my $buf;
92     # sysread $pr, $buf, 8192
93     # and return $cb->($buf);
94     # undef $w; $cv->end;
95     # }
96     # ;
97     # $redir{defined $fd ? $fd : 0} = $pr;
98    
99 root 1.1 } elsif ($type =~ s/^>//) {
100     push @exe, sub {
101     open my $fh, ">", $type
102     or POSIX::_exit (125);
103     $redir{defined $fd ? $fd : 1} = $fh;
104     };
105    
106     } elsif ($type =~ s/^<//) {
107     push @exe, sub {
108     open my $fh, "<", $type
109     or POSIX::_exit (125);
110     $redir{defined $fd ? $fd : 0} = $fh;
111     };
112     }
113     }
114    
115     my $pid = fork;
116    
117     defined $pid
118     or Carp::croak "fork: $!";
119    
120     unless ($pid) {
121     # step 1, execute
122     $_->() for @exe;
123    
124     # step 2, move any existing fd's out of the way
125     my @oldfh;
126     for my $fh (values %redir) {
127     push @oldfh, $fh;
128     $fh = fileno $fh;
129    
130     defined ($fh = POSIX::dup ($fh)) or POSIX::_exit (124)
131     while exists $redir{$fh};
132     }
133    
134     # step 3, execute redirects
135     while (my ($k, $v) = each %redir) {
136     defined POSIX::dup2 ($v, $k)
137     or POSIX::_exit (123);
138     }
139    
140     # step 4, close everything else
141     for (3..1023) { #TODO
142     POSIX::close ($_)
143     unless exists $redir{$_};
144     }
145    
146     exec @$cmd;
147    
148     POSIX::_exit (126);
149     }
150    
151     close $_ for values %redir;
152    
153     my $status;
154     $cv->begin (sub { shift->send ($status) });
155     my $cw; $cw = AE::child $pid, sub {
156     $status = $_[1];
157     undef $cw; $cv->end;
158     };
159    
160     $cv
161     }
162    
163     sub my_run_cmd {
164     my ($cmd) = @_;
165    
166     my $cv = &run_cmd;
167     my $status = $cv->recv;
168    
169     $status
170     and die "@$cmd: command failed with exit status $status.";
171     }
172    
173     sub gen_cert {
174 root 1.2 my_run_cmd [qw(openssl req
175     -new -nodes -x509 -days 3650
176     -newkey rsa:2048 -keyout /dev/fd/3
177     -batch -subj /CN=AnyEvent::MP
178     )],
179 root 1.1 "</dev/null",
180     ">" , \my $cert,
181     "3>", \my $key,
182     "2>/dev/null";
183    
184     "$cert$key"
185     }
186    
187     our $cfg = \%AnyEvent::MP::Config::CFG;
188 root 1.3 our $nodecfg = $cfg;
189 root 1.1
190     sub resolve_port {
191     my ($node, $port) = split /#/, $_[0], 2;
192    
193     $node = (resolve_node $node)->recv;
194     "$node#$port"
195     }
196    
197     our %CMD = (
198     snd => sub {
199     my $port = resolve_port shift @ARGV;
200     initialise_node "slave/", node_of $port;
201    
202     snd $port, @ARGV;
203    
204     my $cv = AE::cv;
205     mon $port, $cv;
206     my $reply = port { &$cv };
207     snd node_of $port, relay => $reply, "ok";
208    
209     print join " ", $cv->recv, "\n";
210     },
211    
212     mon => sub {
213     my $port = resolve_port shift @ARGV;
214     initialise_node "slave/", node_of $port;
215    
216     mon $port, my $cv = AE::cv;
217     print join " ", $cv->recv, "\n";
218     },
219    
220     setsecret => sub {
221     @ARGV == 1
222     or die "shared secret missing\n";
223    
224     $nodecfg->{secret} = shift @ARGV;
225     ++$cfg->{dirty};
226     },
227     gensecret => sub {
228     $nodecfg->{secret} = AnyEvent::MP::Base::asciibits AnyEvent::MP::Base::nonce 64;
229     ++$cfg->{dirty};
230     },
231     clrsecret => sub {
232     delete $nodecfg->{secret};
233     ++$cfg->{dirty};
234     },
235    
236     setcert => sub {
237     @ARGV == 1
238     or die "key+certificate pem filename missing\n";
239    
240     open my $fh, "<", $ARGV[0]
241     or die "$ARGV[0]: $!";
242    
243     local $/;
244     $nodecfg->{cert} = <$fh>;
245     ++$cfg->{dirty};
246     },
247     gencert => sub {
248     $nodecfg->{cert} = gen_cert;
249     ++$cfg->{dirty};
250     },
251     clrcert => sub {
252     delete $nodecfg->{cert};
253     ++$cfg->{dirty};
254     },
255     );
256    
257     sub docmd {
258     my $cmd = shift @ARGV;
259    
260     $CMD{$cmd}
261     or die "$cmd: no such aemp command (try man aemp)";
262    
263     $CMD{$cmd}();
264     }
265    
266     @ARGV
267     or die "Usage: aemp subcommand ... (try man aemp)\n";
268    
269     docmd;
270    
271