Namazu-devel-ja(旧)


[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

util::systemcmd()



 From: knok@xxxxxxxxxxxxx
 Subject: [namazu-devel-ja] Re: Win98,ME で pdf.pl(Namazu2.0.12) の不具合?
 Date: Wed, 4 Sep 2002 14:42:16 JST

 >   やはりやるなら Open3 ですかね...

しばらく考えていたのですが、pl/util.pl での systemcmd() を、以下の
ような感じにするのはどうでしょうか。open3() あるいは system(LIST) 
で起動したコマンドのstdout出力およびstderr出力へのファイルハンドル
を返し値に含めてしまうというものです。あんまり普通じゃないことは承
知していますが、フィルタは簡潔にできるという特長があります。

たとえば、出力の要らない
  system("$wordconvpath $options $tmpfile $ofile");
は、
  util::systemcmd($wordconvpath, @options, $tmpfile, $ofile);
にして単に返値を無視すればいい。

        my $fh_cmd = util::efopen("$wvversionpath $tmpfile |");
        while (<$fh_cmd>) {
は
	my @cmd = ($wvversionpath, $tmpfile);
        my ($status, $fh_out, $fh_err) = util::systemcmd(@cmd);
        while (<$fh_out>) {

でいいですし。

        system("$utfconvpath -Iu8 -Oej $tmpfile > $tmpfile2");
        my $fh = util::efopen("< $tmpfile");
        $$cont = util::readfile($fh);
は
	my @cmd = ($utfconvpath, "-Iu8", "-Oej", $tmpfile);
        my ($status, $fh_out, $fh_err) = util::systemcmd(@cmd);
        $$cont = util::readfile($fh_out);

という感じ。

テストプログラムで試した感じでは、Linux ではいずれでも動きますが、
Windows98 だと Open3 版は呼び出すプログラムによって動くものと動か
ないものとがあるようです。後者のものなら試した範囲ではだいたい動く
ようです。NT系でどうなっているかはわかりませんが。
--
馬場  肇 ( Hajime BABA )                  E-mail: baba@xxxxxxxxxxxxxxxx
宇宙科学研究所 宇宙科学企画情報解析センター
--


=======================================================================
IPC::Open3 版

sub systemcmd(@) {
    my $status = undef;
    my @args = ();
    if ($mknmz::SYSTEM eq "MSWin32" || $mknmz::SYSTEM eq "os2") {
        foreach my $tmp (@_) {
            # To avoid an error: 'Modification of a read-only value attempted'
            (my $tmp2 = $tmp) =~ s!/!\\!g;
            push @args, $tmp2;
        }
    } else {
        @args = @_;
    }
    util::dprint(join(' ', @args));

    my $fh_out = IO::File->new_tmpfile();
    my $fh_err = IO::File->new_tmpfile();
    {
	use IPC::Open3;
	use Symbol qw(gensym);
	my $pid = open3(gensym, $fh_out, $fh_err, @args);
	waitpid($pid, 0);
	$status = ($? >> 8);
    }

    return ($status, $fh_out, $fh_err);
}


=======================================================================
system() 版

sub systemcmd(@) {
    my $status = undef;
    my @args = ();
    if ($mknmz::SYSTEM eq "MSWin32" || $mknmz::SYSTEM eq "os2") {
        foreach my $tmp (@_) {
            # To avoid an error: 'Modification of a read-only value attempted'
            (my $tmp2 = $tmp) =~ s!/!\\!g;
            push @args, $tmp2;
        }
    } else {
        @args = @_;
    }
    util::dprint(join(' ', @args));

    my $saveout = new IO::File (">&" . STDOUT->fileno()) 
        or die "Can't dup SAVEOUT: $!";
    my $saveerr = new IO::File (">&" . STDERR->fileno()) 
        or die "Can't dup SAVEERR: $!";
    my $fh_out = IO::File->new_tmpfile();
    my $fh_err = IO::File->new_tmpfile();
    STDOUT->fdopen($fh_out->fileno(), 'w') or die "Can't open fh_out: $!";
    STDERR->fdopen($fh_err->fileno(), 'w') or die "Can't open fh_err: $!";

    # Use an indirect object: see Perl Cookbook Recipe 16.2 in detail.
    $status = system { $args[0] } @args;

    STDOUT->fdopen($saveout->fileno(), 'w') or die "Can't restore saveout: $!";
    STDERR->fdopen($saveerr->fileno(), 'w') or die "Can't restore saveerr: $!";

    # Note that the file position of filehandles must be rewinded.
    seek($fh_out, 0, SEEK_SET) or die "seek: $!";
    seek($fh_err, 0, SEEK_SET) or die "seek: $!";

    return ($status, $fh_out, $fh_err);
}

=======================================================================