home *** CD-ROM | disk | FTP | other *** search
/ PC Professionell 2004 December / PCpro_2004_12.ISO / files / webserver / tsw / TSW_3.4.0.exe / Apache2 / perl / Win32IO.pm < prev    next >
Encoding:
Perl POD Document  |  2003-09-26  |  15.9 KB  |  562 lines

  1. package IPC::Run::Win32IO;
  2.  
  3. =head1 NAME
  4.  
  5. IPC::Run::Win32IO - helper routines for IPC::Run on Win32 platforms.
  6.  
  7. =head1 SYNOPSIS
  8.  
  9. use IPC::Run::Win32IO;   # Exports all by default
  10.  
  11. =head1 DESCRIPTION
  12.  
  13. IPC::Run needs to use sockets to redirect subprocess I/O so that the select()
  14. loop will work on Win32. This seems to only work on WinNT and Win2K at this
  15. time, not sure if it will ever work on Win95 or Win98. If you have experience
  16. in this area, please contact me at barries@slaysys.com, thanks!.
  17.  
  18. =cut
  19.  
  20. =head1 DESCRIPTION
  21.  
  22. A specialized IO class used on Win32.
  23.  
  24. =cut
  25.  
  26. use strict ;
  27. use Carp ;
  28. use IO::Handle ;
  29. use Socket ;
  30. require POSIX ;
  31.  
  32. use Socket qw( IPPROTO_TCP TCP_NODELAY ) ;
  33. use Symbol ;
  34. use Text::ParseWords ;
  35. use Win32::Process ;
  36. use IPC::Run::Debug qw( :default _debugging_level );
  37. use IPC::Run::Win32Helper qw( _inherit _dont_inherit );
  38. use Fcntl qw( O_TEXT O_RDONLY );
  39.  
  40. use base qw( IPC::Run::IO );
  41. my @cleanup_fields;
  42. BEGIN {
  43.    ## These fields will be set to undef in _cleanup to close
  44.    ## the handles.
  45.    @cleanup_fields = (
  46.       'SEND_THROUGH_TEMP_FILE', ## Set by WinHelper::optimize()
  47.       'RECV_THROUGH_TEMP_FILE', ## Set by WinHelper::optimize()
  48.       'TEMP_FILE_NAME',         ## The name of the temp file, needed for
  49.                                 ## error reporting / debugging only.
  50.  
  51.       'PARENT_HANDLE',       ## The handle of the socket for the parent
  52.       'PUMP_SOCKET_HANDLE',  ## The socket handle for the pump
  53.       'PUMP_PIPE_HANDLE',    ## The anon pipe handle for the pump
  54.       'CHILD_HANDLE',        ## The anon pipe handle for the child
  55.  
  56.       'TEMP_FILE_HANDLE',    ## The Win32 filehandle for the temp file
  57.    );
  58. }
  59.  
  60. use fields (
  61.    @cleanup_fields
  62. );
  63.  
  64.  
  65. ## REMOVE OSFHandleOpen
  66. use Win32API::File qw(
  67.    GetOsFHandle
  68.    OsFHandleOpenFd
  69.    OsFHandleOpen
  70.    FdGetOsFHandle
  71.    SetHandleInformation
  72.    SetFilePointer
  73.    HANDLE_FLAG_INHERIT
  74.    INVALID_HANDLE_VALUE
  75.  
  76.    createFile
  77.    WriteFile
  78.    ReadFile
  79.    CloseHandle
  80.  
  81.    FILE_ATTRIBUTE_TEMPORARY
  82.    FILE_FLAG_DELETE_ON_CLOSE
  83.    FILE_FLAG_WRITE_THROUGH
  84.  
  85.    FILE_BEGIN
  86. ) ;
  87.  
  88. #   FILE_ATTRIBUTE_HIDDEN
  89. #   FILE_ATTRIBUTE_SYSTEM
  90.  
  91.  
  92. BEGIN {
  93.    ## Force AUTOLOADED constants to be, well, constant by getting them
  94.    ## to AUTOLOAD before compilation continues.  Sigh.
  95.    () = (
  96.       SOL_SOCKET,
  97.       SO_REUSEADDR,
  98.       IPPROTO_TCP,
  99.       TCP_NODELAY,
  100.       HANDLE_FLAG_INHERIT,
  101.       INVALID_HANDLE_VALUE,
  102.    );
  103. }
  104.  
  105.  
  106. use constant temp_file_flags => (
  107.    FILE_ATTRIBUTE_TEMPORARY()   |
  108.    FILE_FLAG_DELETE_ON_CLOSE()  |
  109.    FILE_FLAG_WRITE_THROUGH()
  110. );
  111.  
  112. #   FILE_ATTRIBUTE_HIDDEN()    |
  113. #   FILE_ATTRIBUTE_SYSTEM()    |
  114. my $tmp_file_counter;
  115. my $tmp_dir;
  116.  
  117. sub _cleanup {
  118.     my IPC::Run::Win32IO $self = shift;
  119.     my ( $harness ) = @_;
  120.  
  121.     $self->_recv_through_temp_file( $harness )
  122.        if $self->{RECV_THROUGH_TEMP_FILE};
  123.  
  124.     CloseHandle( $self->{TEMP_FILE_HANDLE} )
  125.        if defined $self->{TEMP_FILE_HANDLE};
  126.  
  127.     $self->{$_} = undef for @cleanup_fields;
  128. }
  129.  
  130.  
  131. sub _create_temp_file {
  132.    my IPC::Run::Win32IO $self = shift;
  133.  
  134.    ## Create a hidden temp file that Win32 will delete when we close
  135.    ## it.
  136.    unless ( defined $tmp_dir ) {
  137.       $tmp_dir = File::Spec->catdir(
  138.          File::Spec->tmpdir, "IPC-Run.tmp"
  139.       );
  140.  
  141.       ## Trust in the user's umask.
  142.       ## This could possibly be a security hole, perhaps
  143.       ## we should offer an option.  Hmmmm, really, people coding
  144.       ## security conscious apps should audit this code and
  145.       ## tell me how to make it better.  Nice cop-out :).
  146.       unless ( -d $tmp_dir ) {
  147.          mkdir $tmp_dir or croak "$!: $tmp_dir";
  148.       }
  149.    }
  150.  
  151.    $self->{TEMP_FILE_NAME} = File::Spec->catfile(
  152.       ## File name is designed for easy sorting and not conflicting
  153.       ## with other processes.  This should allow us to use "t"runcate
  154.       ## access in CreateFile in case something left some droppings
  155.       ## around (which should never happen because we specify
  156.       ## FLAG_DELETE_ON_CLOSE.
  157.       ## heh, belt and suspenders are better than bug reports; God forbid
  158.       ## that NT should ever crash before a temp file gets deleted!
  159.       $tmp_dir, sprintf "Win32io-%06d-%08d", $$, $tmp_file_counter++
  160.    );
  161.  
  162.    $self->{TEMP_FILE_HANDLE} = createFile(
  163.       $self->{TEMP_FILE_NAME},
  164.       "trw",         ## new, truncate, read, write
  165.       {
  166.          Flags      => temp_file_flags,
  167.       },
  168.    ) or croak "Can't create temporary file, $self->{TEMP_FILE_NAME}: $^E";
  169.  
  170.    $self->{TFD} = OsFHandleOpenFd $self->{TEMP_FILE_HANDLE}, 0;
  171.    $self->{FD} = undef;
  172.  
  173.    _debug
  174.       "Win32 Optimizer: temp file (",
  175.       $self->{KFD},
  176.       $self->{TYPE},
  177.       $self->{TFD},
  178.       ", fh ",
  179.       $self->{TEMP_FILE_HANDLE},
  180.       "): ",
  181.       $self->{TEMP_FILE_NAME}
  182.       if _debugging_details;
  183. }
  184.  
  185.  
  186. sub _reset_temp_file_pointer {
  187.    my $self = shift;
  188.    SetFilePointer( $self->{TEMP_FILE_HANDLE}, 0, 0, FILE_BEGIN )
  189.       or confess "$^E seeking on (fd $self->{TFD}) $self->{TEMP_FILE_NAME} for kid's fd $self->{KFD}";
  190. }
  191.  
  192.  
  193. sub _send_through_temp_file {
  194.    my IPC::Run::Win32IO $self = shift;
  195.  
  196.    _debug
  197.       "Win32 optimizer: optimizing "
  198.       . " $self->{KFD} $self->{TYPE} temp file instead of ",
  199.          ref $self->{SOURCE} || $self->{SOURCE}
  200.       if _debugging_details;
  201.  
  202.    $self->_create_temp_file;
  203.  
  204.    if ( defined ${$self->{SOURCE}} ) {
  205.       my $bytes_written = 0;
  206.       my $data_ref;
  207.       if ( $self->binmode ) {
  208.      $data_ref = $self->{SOURCE};
  209.       }
  210.       else {
  211.          my $data = ${$self->{SOURCE}};  # Ugh, a copy.
  212.      $data =~ s/(?<!\r)\n/\r\n/g;
  213.      $data_ref = \$data;
  214.       }
  215.  
  216.       WriteFile(
  217.          $self->{TEMP_FILE_HANDLE},
  218.          $$data_ref,
  219.          0,              ## Write entire buffer
  220.          $bytes_written,
  221.          [],             ## Not overlapped.
  222.       ) or croak
  223.          "$^E writing $self->{TEMP_FILE_NAME} for kid to read on fd $self->{KFD}";
  224.       _debug
  225.          "Win32 optimizer: wrote $bytes_written to temp file $self->{TEMP_FILE_NAME}"
  226.          if _debugging_data;
  227.  
  228.       $self->_reset_temp_file_pointer;
  229.  
  230.    }
  231.  
  232.  
  233.    _debug "Win32 optimizer: kid to read $self->{KFD} from temp file on $self->{TFD}"
  234.       if _debugging_details;
  235. }
  236.  
  237.  
  238. sub _init_recv_through_temp_file {
  239.    my IPC::Run::Win32IO $self = shift;
  240.  
  241.    $self->_create_temp_file;
  242. }
  243.  
  244.  
  245. ## TODO: USe the Win32 API in the select loop to see if the file has grown
  246. ## and read it incrementally if it has.
  247. sub _recv_through_temp_file {
  248.    my IPC::Run::Win32IO $self = shift;
  249.  
  250.    ## This next line kicks in if the run() never got to initting things
  251.    ## and needs to clean up.
  252.    return undef unless defined $self->{TEMP_FILE_HANDLE};
  253.  
  254.    push @{$self->{FILTERS}}, sub {
  255.       my ( undef, $out_ref ) = @_;
  256.  
  257.       return undef unless defined $self->{TEMP_FILE_HANDLE};
  258.  
  259.       my $r;
  260.       my $s;
  261.       ReadFile(
  262.      $self->{TEMP_FILE_HANDLE},
  263.      $s,
  264.      999_999,  ## Hmmm, should read the size.
  265.      $r,
  266.      []
  267.       ) or croak "$^E reading from $self->{TEMP_FILE_NAME}";
  268.  
  269.       _debug "ReadFile( $self->{TFD} ) = $r chars '$s'" if _debugging_data ;
  270.  
  271.       return undef unless $r;
  272.  
  273.       $s =~ s/\r\n/\n/g unless $self->binmode;
  274.  
  275.       my $pos = pos $$out_ref;
  276.       $$out_ref .= $s;
  277.       pos( $out_ref ) = $pos;
  278.       return 1;
  279.    };
  280.  
  281.    my ( $harness ) = @_;
  282.  
  283.    $self->_reset_temp_file_pointer;
  284.  
  285.    1 while $self->_do_filters( $harness );
  286.  
  287.    pop @{$self->{FILTERS}};
  288.  
  289.    IPC::Run::_close( $self->{TFD} );
  290. }
  291.  
  292.  
  293. sub poll {
  294.    my IPC::Run::Win32IO $self = shift;
  295.  
  296.    return if $self->{SEND_THROUGH_TEMP_FILE} || $self->{RECV_THROUGH_TEMP_FILE};
  297.  
  298.    return $self->SUPER::poll( @_ );
  299. }
  300.  
  301.  
  302. ## When threaded Perls get good enough, we should use threads here.
  303. ## The problem with threaded perls is that they dup() all sorts of
  304. ## filehandles and fds and don't allow sufficient control over
  305. ## closing off the ones we don't want.
  306.  
  307. sub _spawn_pumper {
  308.    my ( $stdin, $stdout, $debug_fd, $binmode, $child_label, @opts ) = @_ ;
  309.    my ( $stdin_fd, $stdout_fd ) = ( fileno $stdin, fileno $stdout ) ;
  310.  
  311.    _debug "pumper stdin = ", $stdin_fd if _debugging_details;
  312.    _debug "pumper stdout = ", $stdout_fd if _debugging_details;
  313.    _inherit $stdin_fd, $stdout_fd, $debug_fd ;
  314.    my @I_options = map qq{"-I$_"}, @INC;
  315.  
  316.    my $cmd_line = join( " ",
  317.       qq{"$^X"},
  318.       @I_options,
  319.       qw(-MIPC::Run::Win32Pump -e 1 ),
  320. ## I'm using this clunky way of passing filehandles to the child process
  321. ## in order to avoid some kind of premature closure of filehandles
  322. ## problem I was having with VCP's test suite when passing them
  323. ## via CreateProcess.  All of the ## REMOVE code is stuff I'd like
  324. ## to be rid of and the ## ADD code is what I'd like to use.
  325.       FdGetOsFHandle( $stdin_fd ), ## REMOVE
  326.       FdGetOsFHandle( $stdout_fd ), ## REMOVE
  327.       FdGetOsFHandle( $debug_fd ), ## REMOVE
  328.       $binmode ? 1 : 0,
  329.       $$, $^T, _debugging_level, qq{"$child_label"},
  330.       @opts
  331.    ) ;
  332.  
  333. #   open SAVEIN,  "<&STDIN"  or croak "$! saving STDIN" ;       #### ADD
  334. #   open SAVEOUT, ">&STDOUT" or croak "$! saving STDOUT" ;       #### ADD
  335. #   open SAVEERR, ">&STDERR" or croak "$! saving STDERR" ;       #### ADD
  336. #   _dont_inherit \*SAVEIN ;       #### ADD
  337. #   _dont_inherit \*SAVEOUT ;       #### ADD
  338. #   _dont_inherit \*SAVEERR ;       #### ADD
  339. #   open STDIN,  "<&$stdin_fd"  or croak "$! dup2()ing $stdin_fd (pumper's STDIN)" ;       #### ADD
  340. #   open STDOUT, ">&$stdout_fd" or croak "$! dup2()ing $stdout_fd (pumper's STDOUT)" ;       #### ADD
  341. #   open STDERR, ">&$debug_fd" or croak "$! dup2()ing $debug_fd (pumper's STDERR/debug_fd)" ;       #### ADD
  342.  
  343.    _debug "pump cmd line: ", $cmd_line if _debugging_details;
  344.  
  345.    my $process ;
  346.    Win32::Process::Create( 
  347.       $process,
  348.       $^X,
  349.       $cmd_line,
  350.       1,  ## Inherit handles
  351.       NORMAL_PRIORITY_CLASS,
  352.       ".",
  353.    ) or croak "$!: Win32::Process::Create()" ;
  354.  
  355. #   open STDIN,  "<&SAVEIN"  or croak "$! restoring STDIN" ;       #### ADD
  356. #   open STDOUT, ">&SAVEOUT" or croak "$! restoring STDOUT" ;       #### ADD
  357. #   open STDERR, ">&SAVEERR" or croak "$! restoring STDERR" ;       #### ADD
  358. #   close SAVEIN             or croak "$! closing SAVEIN" ;       #### ADD
  359. #   close SAVEOUT            or croak "$! closing SAVEOUT" ;       #### ADD
  360. #   close SAVEERR            or croak "$! closing SAVEERR" ;       #### ADD
  361.  
  362.    close $stdin  or croak "$! closing pumper's stdin in parent" ;
  363.    close $stdout or croak "$! closing pumper's stdout in parent" ;
  364.    # Don't close $debug_fd, we need it, as do other pumpers.
  365.  
  366.    # Pause a moment to allow the child to get up and running and emit
  367.    # debug messages.  This does not always work.
  368.    #   select undef, undef, undef, 1 if _debugging_details ;
  369.  
  370.    _debug "_spawn_pumper pid = ", $process->GetProcessID 
  371.       if _debugging_data;
  372. }
  373.  
  374.  
  375. my $next_port = 2048 ;
  376. my $loopback  = inet_aton "127.0.0.1" ;
  377. my $tcp_proto = getprotobyname('tcp');
  378. croak "$!: getprotobyname('tcp')" unless defined $tcp_proto ;
  379.  
  380. sub _socket {
  381.    my ( $server ) = @_ ;
  382.    $server ||= gensym ;
  383.    my $client = gensym ;
  384.  
  385.    my $listener = gensym ;
  386.    socket $listener, PF_INET, SOCK_STREAM, $tcp_proto
  387.       or croak "$!: socket()";
  388.    setsockopt $listener, SOL_SOCKET, SO_REUSEADDR, pack("l", 0)
  389.       or croak "$!: setsockopt()";
  390.  
  391.    my $port ;
  392.    my @errors ;
  393. PORT_FINDER_LOOP:
  394.    {
  395.       $port = $next_port ;
  396.       $next_port = 2048 if ++$next_port > 65_535 ; 
  397.       unless ( bind $listener, sockaddr_in( $port, INADDR_ANY ) ) {
  398.      push @errors, "$! on port $port" ;
  399.      croak join "\n", @errors if @errors > 10 ;
  400.          goto PORT_FINDER_LOOP;
  401.       }
  402.    }
  403.  
  404.    _debug "win32 port = $port" if _debugging_details;
  405.  
  406.    listen $listener, my $queue_size = 1
  407.       or croak "$!: listen()" ;
  408.  
  409.    {
  410.       socket $client, PF_INET, SOCK_STREAM, $tcp_proto
  411.          or croak "$!: socket()";
  412.  
  413.       my $paddr = sockaddr_in($port, $loopback );
  414.  
  415.       connect $client, $paddr
  416.          or croak "$!: connect()" ;
  417.     
  418.       croak "$!: accept" unless defined $paddr ;
  419.  
  420.       ## The windows "default" is SO_DONTLINGER, which should make
  421.       ## sure all socket data goes through.  I have my doubts based
  422.       ## on experimentation, but nothing prompts me to set SO_LINGER
  423.       ## at this time...
  424.       setsockopt $client, IPPROTO_TCP, TCP_NODELAY, pack("l", 0)
  425.      or croak "$!: setsockopt()";
  426.    }
  427.  
  428.    {
  429.       _debug "accept()ing on port $port" if _debugging_details;
  430.       my $paddr = accept( $server, $listener ) ;
  431.       croak "$!: accept()" unless defined $paddr ;
  432.    }
  433.  
  434.    _debug
  435.       "win32 _socket = ( ", fileno $server, ", ", fileno $client, " ) on port $port" 
  436.       if _debugging_details;
  437.    return ( $server, $client ) ;
  438. }
  439.  
  440.  
  441. sub _open_socket_pipe {
  442.    my IPC::Run::Win32IO $self = shift;
  443.    my ( $debug_fd, $parent_handle ) = @_ ;
  444.  
  445.    my $is_send_to_child = $self->dir eq "<";
  446.  
  447.    $self->{CHILD_HANDLE}     = gensym;
  448.    $self->{PUMP_PIPE_HANDLE} = gensym;
  449.  
  450.    ( 
  451.       $self->{PARENT_HANDLE},
  452.       $self->{PUMP_SOCKET_HANDLE}
  453.    ) = _socket $parent_handle ;
  454.  
  455.    ## These binmodes seem to have no effect on Win2K, but just to be safe
  456.    ## I do them.
  457.    binmode $self->{PARENT_HANDLE}      or die $!;
  458.    binmode $self->{PUMP_SOCKET_HANDLE} or die $!;
  459.  
  460. _debug "PUMP_SOCKET_HANDLE = ", fileno $self->{PUMP_SOCKET_HANDLE}
  461.    if _debugging_details;
  462. ##my $buf ;
  463. ##$buf = "write on child end of " . fileno( $self->{WRITE_HANDLE} ) . "\n\n\n\n\n" ;
  464. ##POSIX::write(fileno $self->{WRITE_HANDLE}, $buf, length $buf) or warn "$! in syswrite" ;
  465. ##$buf = "write on parent end of " . fileno( $self->{CHILD_HANDLE} ) . "\r\n" ;
  466. ##POSIX::write(fileno $self->{CHILD_HANDLE},$buf, length $buf) or warn "$! in syswrite" ;
  467. ##   $self->{CHILD_HANDLE}->autoflush( 1 ) ;
  468. ##   $self->{WRITE_HANDLE}->autoflush( 1 ) ;
  469.  
  470.    ## Now fork off a data pump and arrange to return the correct fds.
  471.    if ( $is_send_to_child ) {
  472.       pipe $self->{CHILD_HANDLE}, $self->{PUMP_PIPE_HANDLE}
  473.          or croak "$! opening child pipe" ;
  474. _debug "CHILD_HANDLE = ", fileno $self->{CHILD_HANDLE}
  475.    if _debugging_details;
  476. _debug "PUMP_PIPE_HANDLE = ", fileno $self->{PUMP_PIPE_HANDLE}
  477.    if _debugging_details;
  478.    }
  479.    else {
  480.       pipe $self->{PUMP_PIPE_HANDLE}, $self->{CHILD_HANDLE}
  481.          or croak "$! opening child pipe" ;
  482. _debug "CHILD_HANDLE = ", fileno $self->{CHILD_HANDLE}
  483.    if _debugging_details;
  484. _debug "PUMP_PIPE_HANDLE = ", fileno $self->{PUMP_PIPE_HANDLE}
  485.    if _debugging_details;
  486.    }
  487.  
  488.    ## These binmodes seem to have no effect on Win2K, but just to be safe
  489.    ## I do them.
  490.    binmode $self->{CHILD_HANDLE};
  491.    binmode $self->{PUMP_PIPE_HANDLE};
  492.  
  493.    ## No child should ever see this.
  494.    _dont_inherit $self->{PARENT_HANDLE} ;
  495.  
  496.    ## We clear the inherit flag so these file descriptors are not inherited.
  497.    ## It'll be dup()ed on to STDIN/STDOUT/STDERR before CreateProcess is
  498.    ## called and *that* fd will be inheritable.
  499.    _dont_inherit $self->{PUMP_SOCKET_HANDLE} ;
  500.    _dont_inherit $self->{PUMP_PIPE_HANDLE} ;
  501.    _dont_inherit $self->{CHILD_HANDLE} ;
  502.  
  503.    ## Need to return $self so the HANDLEs don't get freed.
  504.    ## Return $self, $parent_fd, $child_fd
  505.    my ( $parent_fd, $child_fd ) = (
  506.       fileno $self->{PARENT_HANDLE},
  507.       fileno $self->{CHILD_HANDLE}
  508.    ) ;
  509.  
  510.    ## Both PUMP_..._HANDLEs will be closed, no need to worry about
  511.    ## inheritance.
  512.    _debug "binmode on" if _debugging_data && $self->binmode;
  513.    _spawn_pumper(
  514.       $is_send_to_child
  515.      ? ( $self->{PUMP_SOCKET_HANDLE}, $self->{PUMP_PIPE_HANDLE} )
  516.      : ( $self->{PUMP_PIPE_HANDLE}, $self->{PUMP_SOCKET_HANDLE} ),
  517.       $debug_fd,
  518.       $self->binmode,
  519.       $child_fd . $self->dir . "pump" . $self->dir . $parent_fd,
  520.    ) ;
  521.  
  522. {
  523. my $foo ;
  524. confess "PARENT_HANDLE no longer open"
  525.    unless POSIX::read( $parent_fd, $foo, 0 ) ;
  526. }
  527.  
  528.    _debug "win32_fake_pipe = ( $parent_fd, $child_fd )"
  529.       if _debugging_details;
  530.  
  531.    $self->{FD}  = $parent_fd;
  532.    $self->{TFD} = $child_fd;
  533. }
  534.  
  535. sub _do_open {
  536.    my IPC::Run::Win32IO $self = shift;
  537.  
  538.    if ( $self->{SEND_THROUGH_TEMP_FILE} ) {
  539.       return $self->_send_through_temp_file( @_ );
  540.    }
  541.    elsif ( $self->{RECV_THROUGH_TEMP_FILE} ) {
  542.       return $self->_init_recv_through_temp_file( @_ );
  543.    }
  544.    else {
  545.       return $self->_open_socket_pipe( @_ );
  546.    }
  547. }
  548.  
  549. =head1 AUTHOR
  550.  
  551. Barries Slaymaker <barries@slaysys.com>.  Funded by Perforce Software, Inc.
  552.  
  553. =head1 COPYRIGHT
  554.  
  555. Copyright 2001, Barrie Slaymaker, All Rights Reserved.
  556.  
  557. You may use this under the terms of either the GPL 2.0 ir the Artistic License.
  558.  
  559. =cut
  560.  
  561. 1;
  562.