CWB-CQI
view release on metacpan or search on metacpan
lib/CWB/CQI/Server.pm view on Meta::CPAN
Returns a B<true> value if a suitable CQPserver binary is installed on the local machine and
can be started with the B<cqi_server> function.
=cut
sub cqi_server_available {
return (defined $CQPserver) ? 1 : 0;
}
=item (I<$user>, I<$passwd>, I<$host>, I<$port>) = B<cqi_server>();
=item I<@details> = B<cqi_server>(I<$flags>);
C<cqi_server()> searches for a free port on the local machine, then
launches a single-user B<CQPserver> process and returns the connection details
required by the B<cqi_connect> function from B<CWB::CQI::Client> (in the appropriate order).
The simplest way to establish a connection with a private, local CQPserver is
cqi_connect(cqi_server());
Be sure to check with B<cqi_server_available> whether the required C<cqpserver>
command-line program is available first.
An optional argument to B<cqi_server> is appended to the C<cqpserver> command-line flags
and can be used to specify further start-up options (e.g. to read a macro definition file).
Keep in mind that arguments containing shell metacharacters need to be quoted appropriately.
B<WARNING:> Since B<CQPserver> runs as a separate process in the background, it is
important to establish a connection B<as soon as possible>. If the user's
program aborts before B<cqi_connect> is called and contacts the new CQPserver,
this process will accept further connections from other users (on the local machine),
which might compromise confidential data.
=cut
#
#
# Start CQPserver in the background and return (host, port, user, passwd) list for cqi_connect()
# An init file is generated which adds a random user/passwd to the server's user list,
# so you can connect to the newly created server with the user/passwd combination returned
# by cqi_server() only. (NB uses '-I' at the moment, so .cqprc won't be read)
#
#
sub cqi_server {
my $user = "cqi_server_$$";
my $passwd = "pass" . int rand(42000);
my $flags = "-1 -L -q "; # single-client server, localhost only (for security reasons)
$flags .= "@_" if @_; # append optional command-line flags
croak "CQPserver is not installed on this machine"
unless cqi_server_available();
# generate temporary user list file for CQPserver
my $passfile = "/tmp/CQI::Server.$$";
my $fh = new FileHandle "> $passfile";
croak "Can't create temporary user list file. Aborting."
unless defined $fh;
print $fh "user $user \"$passwd\";\n";
$fh->close;
chmod 0600, $passfile; # so no one can spy on us
# scan for free port (using rand() so two servers invoked at the same time won't collide)
my $port = 10000 + int rand(2000);
my %in_use =
map {$_ => 1}
map {(/\*\.([0-9]+)/) ? $1 : 0}
`netstat -a -n | grep LISTEN`;
while ($port < 60000 and $in_use{$port}) {
$port += rand(20); # jump randomly to avoid collisions
}
croak "Can't find free port for CQPserver. Abort."
unless $port < 60000;
# now start CQPserver on this port
croak "CQPserver failed to launch: $!\n"
if system "$CQPserver $flags -P $port -I $passfile >/dev/null 2>&1" or $? != 0;
# delete user list file
unlink $passfile;
# return connection information suitable for cqi_connect()
return $user, $passwd, "localhost", $port;
}
1;
__END__
=back
=head1 COPYRIGHT
Copyright (C) 1999-2022 Stephanie Evert [http::/purl.org/stephanie.evert]
This software is provided AS IS and the author makes no warranty as to
its use and performance. You may use the software, redistribute and
modify it under the same terms as Perl itself.
=cut
( run in 0.412 second using v1.01-cache-2.11-cpan-0bb4e1dffa6 )