5.6.1

名前

perlfaq8 - System Interaction ($Revision$, $Date$)

perlfaq8 - システムとの対話 ($Revision$, $Date$)

説明

This section of the Perl FAQ covers questions involving operating system interaction. Topics include interprocess communication (IPC), control over the user-interface (keyboard, screen and pointing devices), and most anything else not related to data manipulation.

FAQのこのセクションでは、オペレーティングシステムとの対話に関する質問を 扱っています。これにはプロセス間(IPC)、ユーザーインターフェース (キーボード、スクリーン、ポインティングデバイス)の制御、 その他データ操作に関連しないほとんどの事柄を含みます。

あなたの使っているオペレーティングシステム向けの移植について特有のことは、 それに関するFAQとドキュメント(perlvms, perlplan9など)を読んでください。 そこには、あなたの使うperlについてのより詳しい情報があります。

実行しているオペレーティングシステムを見分けるには?

The $^O variable ($OSNAME if you use English) contains an indication of the name of the operating system (not its release number) that your perl binary was built for.

$^Oという変数(use Engishをしていれば $OSNAME)は、あなたの使っている perlの実行ファイルがビルドされたオペレーティングシステムの名前 (リリース番号ではありません)の情報を持っています。

なぜ exec()は戻ってこないのでしょう?

そういうものだからです: これはその時点で実行されているプログラムを 別のもので置き換えるのです。もし元のものを残しておきたい(あなたが この質問をしたときの状況のように)のなら、exec()の代わりに system()を使ってください。

キーボード/画面/マウスの凝った機能を使うにはどうすればいいでしょう?

キーボード、画面、ポインティングデバイス(“マウス”)にアクセスしたり それを制御することはシステム依存です。以下のモジュールを試してみてください:

Keyboard
    Term::Cap                   標準perl配布パッケージ
    Term::ReadKey               CPAN
    Term::ReadLine::Gnu         CPAN
    Term::ReadLine::Perl        CPAN
    Term::Screen                CPAN
Screen
    Term::Cap                   標準perl配布パッケージ
    Curses                      CPAN
    Term::ANSIColor             CPAN
Mouse
    Tk                          CPAN

Some of these specific cases are shown below.

これらの一部の特殊なケースは後述します。

色付きで何かを出力するには?

In general, you don't, because you don't know whether the recipient has a color-aware display device. If you know that they have an ANSI terminal that understands color, you can use the Term::ANSIColor module from CPAN:

一般的にはできません。なぜなら、あなたはディスプレイデバイスに 関するレシピについて何も知らないからです。 もしあなたがカラーの扱えるANSIターミナルについて知っているのなら、 CPANにあるTerm::ANSIColorモジュールを使うことができます。

    use Term::ANSIColor;
    print color("red"), "Stop!\n", color("reset");
    print color("green"), "Go!\n", color("reset");

あるいは次のようにも書けます:

    use Term::ANSIColor qw(:constants);
    print RED, "Stop!\n", RESET;
    print GREEN, "Go!\n", RESET;

リターンキーを待たずにキーのデータを一つ読み取るには?

Controlling input buffering is a remarkably system-dependent matter. On many systems, you can just use the stty command as shown in "getc" in perlfunc, but as you see, that's already getting you into portability snags.

入力バッファを制御するのは非常にシステムに依存したやりかたです。 多くのシステムでは、"getc" in perlfuncにあるように sttyコマンドを使うことができますが、今書いた通り 移植性の問題があるのです。

    open(TTY, "+</dev/tty") or die "no tty: $!";
    system "stty  cbreak </dev/tty >/dev/tty 2>&1";
    $key = getc(TTY);           # 多分うまく行く
    # OR ELSE
    sysread(TTY, $key, 1);      # 多分動作する
    system "stty -cbreak </dev/tty >/dev/tty 2>&1";

The Term::ReadKey module from CPAN offers an easy-to-use interface that should be more efficient than shelling out to stty for each key. It even includes limited support for Windows.

CPANにあるTerm::ReadKeyモジュールは、 sttyをキー毎にシェルに送るよりもより効果的に行ってくれて 使うのが簡単なインターフェースを提供します。このモジュールは 限定的ながら Windows にも対応しています。

    use Term::ReadKey;
    ReadMode('cbreak');
    $key = ReadKey(0);
    ReadMode('normal');

However, using the code requires that you have a working C compiler and can use it to build and install a CPAN module. Here's a solution using the standard POSIX module, which is already on your systems (assuming your system supports POSIX).

しかし、このコードを使うには C コンパイラを使えることが条件であり、かつ CPANモジュールのビルドとインストールができなければなりません。 以下の例は、標準のPOSIXモジュールを使った解決策で、 あなたの使っているシステムがPOSIXをサポートしていれば 即使えるものです。

    use HotKey;
    $key = readkey();

And here's the HotKey module, which hides the somewhat mystifying calls to manipulate the POSIX termios structures.

そして以下の例は、HotKeyモジュールを使ったものです。 このHotKeyモジュールはPOSIXのtermio構造体の操作を 包み隠します。

    # HotKey.pm
    package HotKey;

    @ISA = qw(Exporter);
    @EXPORT = qw(cbreak cooked readkey);

    use strict;
    use POSIX qw(:termios_h);
    my ($term, $oterm, $echo, $noecho, $fd_stdin);

    $fd_stdin = fileno(STDIN);
    $term     = POSIX::Termios->new();
    $term->getattr($fd_stdin);
    $oterm     = $term->getlflag();

    $echo     = ECHO | ECHOK | ICANON;
    $noecho   = $oterm & ~$echo;

    sub cbreak {
        $term->setlflag($noecho);  # echoは不要だからね
        $term->setcc(VTIME, 1);
        $term->setattr($fd_stdin, TCSANOW);
    }

    sub cooked {
        $term->setlflag($oterm);
        $term->setcc(VTIME, 0);
        $term->setattr($fd_stdin, TCSANOW);
    }

    sub readkey {
        my $key = '';
        cbreak();
        sysread(STDIN, $key, 1);
        cooked();
        return $key;
    }

    END { cooked() }

    1;

キーの入力待ちがあるかどうかチェックするには?

The easiest way to do this is to read a key in nonblocking mode with the Term::ReadKey module from CPAN, passing it an argument of -1 to indicate not to block:

最も簡単な方法は、CPANにあるTerm::ReadKeyに対して (ブロックを行わないという意味である)-1を引数に渡して 使用することによって 非ブロックモードでキーを読み取るという方法です。

    use Term::ReadKey;

    ReadMode('cbreak');

    if (defined ($char = ReadKey(-1)) ) {
        # input was waiting and it was $char
    } else {
        # no input was waiting
    }

    ReadMode('normal');                  # 通常のtty設定に戻す

画面をクリアするには?

それほど頻繁でないのなら、systemを使います:

    system("clear");

If you have to do this a lot, save the clear string so you can print it 100 times without calling a program 100 times:

頻繁に行う必要があるのなら、クリアの文字列を保存することによって プログラムを呼び出す回数を減らすことができます:

    $clear_string = `clear`;
    print $clear_string;

カーソル位置など、そのほかのスクリーン操作をしようと考えているのなら、 Term::Capモジュールを使うと良いかもしれません:

    use Term::Cap;
    $terminal = Term::Cap->Tgetent( {OSPEED => 9600} );
    $clear_string = $terminal->Tputs('cl');

画面サイズを得るには?

CPANにあるTerm::ReadKeyモジュールをインストールしているのなら、 キャラクターやピクセルでの幅と高さを得ることができます:

    use Term::ReadKey;
    ($wchar, $hchar, $wpixels, $hpixels) = GetTerminalSize();

This is more portable than the raw ioctl, but not as illustrative:

以下の例は生のioctlよりも移植性がありますが、 あまりわかりやすい例ではありません:

    require 'sys/ioctl.ph';
    die "no TIOCGWINSZ " unless defined &TIOCGWINSZ;
    open(TTY, "+</dev/tty")                     or die "No tty: $!";
    unless (ioctl(TTY, &TIOCGWINSZ, $winsize='')) {
        die sprintf "$0: ioctl TIOCGWINSZ (%08x: $!)\n", &TIOCGWINSZ;
    }
    ($row, $col, $xpixel, $ypixel) = unpack('S4', $winsize);
    print "(row,col) = ($row,$col)";
    print "  (xpixel,ypixel) = ($xpixel,$ypixel)" if $xpixel || $ypixel;
    print "\n";

ユーザーにパスワードを尋ねるには?

(この質問はwebとは関係ありません。それに関しては 別のFAQを 参照してください。)

この例が "crypt" in perlfuncにあります。第一に、端末を“no echo”モードにし、 それから通常通りにパスワードを読み込みます。 これを、古いスタイルのioctl()関数を使ってできますし、 あるいはPOSIXの端末制御(POSIXと、らくだ本を参照してください)を使うことも、 stty プログラムを呼び出すことも可能です(ただしこれは移植性は劣ります)。

あるいはほとんどのシステムで、CPANにある Term::ReadKeyを使って 行うこともできます。 これは使うのが簡単で、理論的にはより移植性があります。

    use Term::ReadKey;

    ReadMode('noecho');
    $password = ReadLine(0);

シリアルポートの読み書きを行うには?

これはプログラムを実行するオペレーティングシステムに依存します。 UNIXの場合、シリアルポートは/devにあるファイルを通じてアクセスが可能です。 他のシステムでは、デバイス名は異なったものであることでしょう。 全てのデバイス操作に共通の問題点として以下のものが挙げられます:

ロックファイル

あなたの使っているシステムは、多重アクセスを制御するためにロック ファイルを使用しているかもしれません。正しい手順に従うようにしてください。 予測のつかない振る舞いは一つのデバイスに対する複数のプロセスの読み出しが 原因かもしれません。

オープンモード

一つのデバイスに対して、読み込みと書き出しの両方の操作ができることを 期待しているのなら、それを更新モード(詳しくは "open" in perlfunc を参照)でオープンする必要があるでしょう。 sysopen()とFcntlモジュールにある O_RDWR|O_NDELAY|O_NOCTTY とを使って ブロッキングする危険性なしにオープンを実行したいと考えるかもしれません。 このアプローチに関する詳細は"sysopen" in perlfuncを参照してください。

行の末尾

幾つかのデバイスでは、行の終端に"\n"ではなく"\r"を期待しています。 perlの移植の一部では、"\r" と "\n"は通常の(UNIXの) ASCII値 である "\012" と "\015".とは異なったものになっています。 八進表記 ("\015")や十六進表記("0x0D")、 あるいはコントロールキャラクター指定("\cM")を使って 直接数値を与える必要があるかもしれません。

    print DEV "atv1\012";       # 一部のデバイスにとっては間違い
    print DEV "atv1\015";       # 一部のデバイスにとっては正しい

通常のテキストファイルでさえも、"\n"はいたずらを行う可能性があります。 全ての行を "\015\012"で終わらせ、出力から必要のないものを 取り除くということを除いては、UNIX、DOS/Win、Macintoshとの間で 互換性のある行の終端方法は未だに統一されていません。 これは特にソケットの入出力や自動フラッシュで適用されます。 これについては次に述べます。

出力のフラッシュ

If you expect characters to get to your device when you print() them, you'll want to autoflush that filehandle. You can use select() and the $| variable to control autoflushing (see perlvar/$ and "select" in perlfunc, or perlfaq5, ``How do I flush/unbuffer an output filehandle? Why must I do this?''):

デバイスに print() した時にそのキャラクタが反映されるようにしたいのなら、 そのハンドルを自動フラッシュするようにしたいでしょう。 自動フラッシュを制御するのに、$|という変数と、select()を 使うことができます(perlvar/$"select" in perlfunc または perlfaq5, ``How do I flush/unbuffer an output filehandle? Why must I do this?''を 参照してください)。

    $oldh = select(DEV);
    $| = 1;
    select($oldh);

これは、以下のように一時変数なしで行うこともできます

    select((select(DEV), $| = 1)[0]);

Or if you don't mind pulling in a few thousand lines of code just because you're afraid of a little $| variable:

$|というような変数に戸惑いを感じていて、 ニ、三千行のプログラムを引っ張りこむことを 気にしないのなら以下のようにできます:

    use IO::Handle;
    DEV->autoflush(1);

先のアイテムで述べたように、これでもまだ UNIXとMacintoshの間で ソケットI/Oを使った場合にはうまく動作しません。 その場合には、行の終端をハードコーディングする必要があるでしょう。

non-blocking input

If you are doing a blocking read() or sysread(), you'll have to arrange for an alarm handler to provide a timeout (see "alarm" in perlfunc). If you have a non-blocking open, you'll likely have a non-blocking read, which means you may have to use a 4-arg select() to determine whether I/O is ready on that device (see "select" in perlfunc.

ブロッキング read()やブロッキングsysread()を行うのであれば、 タイムアウトを実現するためにalarmハンドラーをアレンジする必要があるでしょう ("alarm" in perlfuncを参照)。 もしノンブロッキングopenを持っているのであれば、 デバイスが入出力完了の状態であるかどうかを決定するために 四つの引数を取るselect()を使う必要があるであろう ノンブロッキングreadも同様に持っていることでしょう("select" in perlfuncを参照)。

While trying to read from his caller-id box, the notorious Jamie Zawinski <[email protected]>, after much gnashing of teeth and fighting with sysread, sysopen, POSIX's tcgetattr business, and various other functions that go bump in the night, finally came up with this:

caller-id ボックスから読み出すことに挑戦したことで有名な Jamie Zawinski <[email protected]>は、 sysreadやsysopen、POSIXのtcgetattrその他さまざまな関数を扱い 悪戦苦闘しながら、最終的には以下のようものを作りました:

    sub open_modem {
        use IPC::Open2;
        my $stty = `/bin/stty -g`;
        open2( \*MODEM_IN, \*MODEM_OUT, "cu -l$modem_device -s2400 2>&1");
        # starting cu hoses /dev/tty's stty settings, even when it has
        # been opened on a pipe...
        system("/bin/stty $stty");
        $_ = <MODEM_IN>;
        chomp;
        if ( !m/^Connected/ ) {
            print STDERR "$0: cu printed `$_' instead of `Connected'\n";
        }
    }

暗号化されたパスワードファイルを復号化するには?

You spend lots and lots of money on dedicated hardware, but this is bound to get you talked about.

特別なハードウェアに非常に多額のお金を掛けてください。 しかしこれはあなたが何について話しているかによります。

まじめな話をすると、UNIXのパスワードに対してのものならできません-- UNIXのパスワードシステムは一方向の暗号化を採用しています。 それは暗号化というよりはむしろハッシュ化といえるものです。 あなたがチェックできる最善の方法は、同じ文字列に対する ハッシュかどうかを調べることです。 Crack のようなプログラムは考えられるパスワードを力づくで(そして知的に) 試しますが、即座に成功するものを生成することはしません(できません)。

もしあなたが、ユーザーが悪いパスワードを選択してしまうことを 心配しているのであれば、ユーザーが(たとえば passwd(1) を使って)自分の パスワードを変更しようとしたときに積極的にチェックをすべきでしょう。

バックグラウンドでプロセスを起動するには?

    system("cmd &")

とするか、"fork" in perlfuncで説明されているforkを使ってできます (perlipcには例もあります)。 あなたがUNIX的なシステムを使っているなら、注意すべき事柄があります。

STDIN, STDOUT, and STDERR are shared

(STDIN, STDOUT, STDERR は共有されます)

主プロセスとバックグラウンドプロセス(子プロセス)で同じ STDIN, STDOUT, STDERR のファイルハンドルが共有されます。 両方のプロセスが同時にアクセスしようとすると、 おかしな事が発生するかもしれません。 子プロセス用のこれらのハンドルを、クローズしたり再オープンしたり したくなるかもしれません。 これは、パイプをopenすることで行えますが、 一部のシステムにおいてはこれは子プロセスが親プロセスよりも 長生きすることはできないということになります。

シグナル

SIGCHLD シグナルを捕捉する必要があり、可能ならSIGPIPEも 捕捉する必要があるでしょう。 SIGCHLDはバックグラウンドプロセスが終了したときに送られます。 SIGPIPEは既にクローズされている子プロセスを所有するファイルハンドルに 書き込みを行ったときに送られます(トラップされていないSIGPIPEは、 あなたのプログラムを黙って終わらせてしまうかもしれません)。 これは system("cmd&")を使ったときには起こりません。

ゾンビ

子プロセスが終了したときにそれを“刈り取る”(reap)準備をする必要があります。

    $SIG{CHLD} = sub { wait };

これを行うサンプルは "Signals" in perlipc を参照してください。 ゾンビは system("prog &")を使ったときには発生しません。

コントロールキャラクターやシグナルをトラップするには?

You don't actually "trap" a control character. Instead, that character generates a signal which is sent to your terminal's currently foregrounded process group, which you then trap in your process. Signals are documented in "Signals" in perlipc and the section on ``Signals'' in the Camel.

実際にはコントロールキャラクターを“トラップ”できません。その代わりに、 そのキャラクターが生成して 端末のフォアグラウンドプロセスに送られることになる シグナルがトラップできます。 シグナルは "Signals" in perlipcとらくだ本の ``Signal'' の章に 説明があります。

再入可能(re-entrant)であるCライブラリは非常に少ないのだということに 注意してください。 したがって、あなたの内部構造に対して別のstdio操作を行っている最中に 起動されたハンドラーの中でprint()しようとすれば、 矛盾した状態に陥ってプログラムがコアダンプしてしまうでしょう。 print()の代わりに syswrite()を使えばこの問題を回避できることもあります。

注意深く処理しない限り、シグナルハンドラーの内側で安全に行えることは (1) 変数の設定と (2) exit だけです。 そして、最初のケースにおいては malloc() を呼び出さないような変数に対する 設定のみを行うべきです(つまり、既に値を持っている変数に対する設定のみということ)。

例を挙げましょう:

    $Interrupted = 0;   # 値を持つことを保証する
    $SIG{INT} = sub {
        $Interrupted++;
        syswrite(STDERR, "ouch\n", 5);
    }

However, because syscalls restart by default, you'll find that if you're in a "slow" call, such as <FH>, read(), connect(), or wait(), that the only way to terminate them is by "longjumping" out; that is, by raising an exception. See the time-out handler for a blocking flock() in "Signals" in perlipc or the section on ``Signals'' in the Camel book.

しかしながらデフォルト設定ではsyscallは再スタートされるので、<FH>, read(), connect(), wait()のような“遅い”呼び出しの中にある場合には ただ一つの方法は"longjumping" out によってそれらを終わらせることだということに 気がつくでしょう。 つまり、例外を発生させるということです。 "Signals" in perlipcにあるブロッキング flock()のためのタイムアウトハンドラーと、 らくだ本の ``Signal'' の章を参照してください。

UNIXシステムのシャドウパスワードファイルを変更するには?

perlが正しくインストールされていて、かつ、シャドウライブラリが きちんとインストールされていれば、perlfuncで説明されている getpw*() 関数がシャドウパスワードファイルに対する(リードオンリーの) アクセスを提供しています。 ファイルを変更するには、新たなシャドウパスワードファイルを作成して (フォーマットはシステム毎に異なります--詳しくは passwd(5)を参照してください)、 pwd_mkdb(8)を使ってそれをインストールします(詳細はpwd_mkdb(8)を参照のこと)。

日付や時刻を設定するには?

あなたが十分な権限を持っているとすれば、date(1) プログラムを実行すれば システム全体の日付や時刻を設定できるはずです (プロセス毎に日付や時刻を設定する方法はありません)。 この機構は、UNIX、MS-DOS、Windows、NTでうまくいくでしょう。 VMS には等価な set time があります。

あなたのやりたいことがタイムゾーンの変更であるのなら、 環境変数を変更することでそれができるでしょう。

    $ENV{TZ} = "MST7MDT";                  # UNIX
    $ENV{'SYS$TIMEZONE_DIFFERENTIAL'}="-5" # VMS
    system "trn comp.lang.perl.misc";

どうすれば一秒未満の時間に対する sleep() や alarm() ができますか?

If you want finer granularity than the 1 second that the sleep() function provides, the easiest way is to use the select() function as +documented in "select" in perlfunc. Try the Time::HiRes and +the BSD::Itimer modules (available from CPAN).

sleep()関数が一秒未満の単位での動作をサポートすることを求めているのなら、 "select" in perlfuncにあるように、select()を使うのが最も単純な方法です。 Time::Hires と BSD::Itimer モジュール(CPAN から利用可能です)も 試してみてください。

どうやれば一秒未満の時間を計測できますか?

一般的なことを言えば、そういったことはできないでしょう。 Time::HiRes モジュール(CPANで入手可能)は幾つかのシステムに対しては お望みの機能を提供しています。

あなたの使っているシステムがgettimeofday(2)のようなシステムコールと同様に Perlのsyscall()をサポートしているのであれば、以下のようにして できるかもしれません:

    require 'sys/syscall.ph';

    $TIMEVAL_T = "LL";

    $done = $start = pack($TIMEVAL_T, ());

    syscall(&SYS_gettimeofday, $start, 0) != -1
               or die "gettimeofday: $!";

       ##########################
       #  あなたの操作をここに  #
       ##########################

    syscall( &SYS_gettimeofday, $done, 0) != -1
           or die "gettimeofday: $!";

    @start = unpack($TIMEVAL_T, $start);
    @done  = unpack($TIMEVAL_T, $done);

    # fix microseconds
    for ($done[1], $start[1]) { $_ /= 1_000_000 }

    $delta_time = sprintf "%.4f", ($done[0]  + $done[1]  )
                                            -
                                 ($start[0] + $start[1] );

どうすれば atexit() や setjmp()/longjmp() ができますか? (例外処理)

Perlのリリース5では、ENDブロックが追加されました。これは atexit() を シミュレートするのに使うことができます。 各パッケージのENDブロックはプログラム、もしくはスレッド (perlmodを参照してください) が終了したときに呼び出されます(詳しくは perlmodを参照)。

For example, you can use this to make sure your filter program managed to finish its output without filling up the disk:

例を挙げると、あなたのフィルタープログラムが出力を確実に ディスクに送るようにするためには以下のようにできます:

    END {
        close(STDOUT) || die "stdout close failed: $!";
    } 

ENDブロックは、トラップされないシグナルが プログラムを強制終了させた場合には呼び出されません。 したがって、ENDブロックを使う場合には同時に

        use sigtrap qw(die normal-signals);

を使うべきでしょう。

Perlの例外処理機構(exception-handling mechanism)は eval()演算子です。 setjmp()としてeval()を、longjmp()としてdie()を使うことができます。 これに関する詳細は、シグナルに関するセクション、 特に"Signals" in perlipcにあるブロッキング flock()のための タイムアウトハンドラーと、らくだ本の ``Signal '' の章を参照してください。

例外処理そのものに興味があるのなら、exception.plライブラリ (これは標準perl配布キットの一部です)を試してみてください。

atexit() 構文(と、rmexit())が欲しいのなら、CPANにあるAtExitモジュールを 試してみてください。

なぜ私のソケットプログラムはSystem V (Solaris)ではうまく動かない のでしょうか? "Protocol not supported"というエラーメッセージの意味するところは?

一部の System 5 ベースのシステム、特に Solaris 2.xでは標準のソケット定数の 幾つかが再定義されています。 これらの定数は全てにアーキテクチャーに渡るものであったので、 しばしばperlコードにhardwiredされています。 これに対処する適切な方法は正しい値を得るために "use Socket" とすることです。

Note that even though SunOS and Solaris are binary compatible, these values are different. Go figure.

SunOS と Solaris とではバイナリ互換性があるにも関らず、 これらの値が異なるということに注意してください。予想通りです。

どうすれば、Perlから私のシステムに固有のC関数を呼び出すことができますか?

ほとんどの場合、その方法は外部モジュールを作るというものです-- "Where can I learn about linking C with Perl? [h2xs, xsubpp]" の回答を参照してください。 ただし、その関数がシステムコールでありあなたの使っているシステムが syscall()をサポートしているのであれば、 syscall関数(perlfuncに説明があります)を使うことができます。

一緒に配布されたモジュールやCPANにあるモジュールをチェックすることを 忘れないでください--誰かが求めるモジュールを既に作っているかもしれません。

ioctl() や syscall() で使うためのincludeファイルはどこで入手できますか?

伝統的に、これらのファイルは標準配布に含まれる h2ph というツールによって 生成されるものです。 このプログラムはCのヘッダーファイルにある cpp(1)ディレクティブを&SYS_getitimerのような、 関数に対する引数として使うことのできる サブルーチン定義を含むファイルに変換するものです。 これは完璧なものではありませんが、ほとんどの場合には十分な仕事を行います。 errno.h, syscall.h, socket.hのような単純なファイルはよいのですが、 ioctl.hのように難しいものはほとんど常に手で編集する必要があります。 以下の手順は、*.phファイルをインストールするためのものです。

    1.  スーパーユーザーになる
    2.  cd /usr/include
    3.  h2ph *.h */*.h

あなたの使っているシステムが動的ローディングをサポートしているのであれば、 移植性と健全性(sanity)のために、h2xsを使うべきでしょう (これも標準のperl配布キットに含まれています)。 このツールは、CのヘッダーファイルをPerlのエクステンションに変換します。 h2xsの使い方は perlxstutを参照してください。

あなたの使っているシステムが動的ローディングをサポートしていない 場合であっても、やはりh2xsを使うべきでしょう。 より詳しい情報は perlxstutExtUtils::MakeMaker を参照してください (簡単に言うと、新しい静的エクステションを伴ったperlを再ビルドするのに 通常のmakeを使うのではなく、make perl を使うだけです)。

なぜsetuid された perl スクリプトはカーネルの問題について 文句を言うのでしょうか?

幾つかのオペレーティングシステムは、setuidスクリプトを 本質的に 安全でなくするようなカーネルのバグを抱えています。 Perlは、そういったシステムに対処して動作させるための幾つかのオプションを 持っています(perlsecに説明があります)。

どうすればあるコマンドに対する双方向のパイプをオープンできますか?

IPC::Open2 モジュール(標準のperlの配布に含まれています)は内部的に pipe()、fork()、exec()を使ったeasy-to-useなアプローチです。 ただし、ドキュメントにあるデッドロックの警告をよく読んでください (IPC::Open2を参照)。 "Bidirectional Communication with Another Process" in perlipc"Bidirectional Communication with Yourself" in perlipcも参照してください。

IPC::Open3モジュール(標準配布パッケージに含まれています)を 使おうと考えたかもしれませんが、これはIPC::Open2とは 引数の順序が違うということに注意してください(IPC::Open3を 参照してください)。

なぜ system()を使ったコマンドの出力を得ることができないのでしょうか?

system()の目的とbackticks(``)の目的を混同しているのでしょう。 system()はコマンドを実行して、終了ステータス情報(16bit値として: 下位7bitは(もしあれば)終了したプロセスからのシグナルで、上位8bit は実際の終了ステータス)を返します。 backticks(``)はコマンドを実行し、 そのコマンドがSTDOUTに送ったものを返します。

    $exit_status   = system("mail-users");
    $output_string = `ls`;

どうすれば外部コマンドの STDERRを捕捉できますか?

外部コマンドを実行する基本的なやり方が三つあります:

    system $cmd;                # system() を使う
    $output = `$cmd`;           # backticks (``) を使う
    open (PIPE, "cmd |");       # open()を使う

system()を使った場合のSTDOUTとSTDERRは、system() コマンドがリダイレクトを 行っていない限りはそれぞれスクリプトが使っていた STDOUT と STDERRへ 出力されます。 backticksとopen()はコマンドのSTDOUT だけを読み込みます。

これらのどれでも、 呼び出しの前にファイルディスクリプターを変更することができます:

    open(STDOUT, ">logfile");
    system("ls");

Bourneシェルのファイルディスクリプターリダイレクション (file-descriptor redirection)を使うこともできます:

    $output = `$cmd 2>some_file`;
    open (PIPE, "cmd 2>some_file |");

同様に、STDERRをSTDOUTの複製にするためにファイルディスクリター リダイレクションを使うこともできます。

    $output = `$cmd 2>&1`;
    open (PIPE, "cmd 2>&1 |");

STDOUTの複製のために、Perlプログラムの中で単純にSTDERRをオープンすることは できないということと、リダイレクトのためのシェルの 呼び出しを避けることはできないということに注意してください。 以下の例はうまくいきません:

    open(STDERR, ">&STDOUT");
    $alloutput = `cmd args`;  # stderr はまだ変ったまま

This fails because the open() makes STDERR go to where STDOUT was going at the time of the open(). The backticks then make STDOUT go to a string, but don't change STDERR (which still goes to the old STDOUT).

これはopen()が、STDERRを(open()が呼び出された時点で)STDOUTが使っていた場所に 対応するようにするので失敗します。 その後でbackticksはSTDOUT(に出力された内容)を文字列にしますが、 STDERRを変更することはしません(これは以前のSTDOUTが指していたところです)。

backticlsの中では、csh(1)のリダイレクト構文ではなく、 Bourne shell (sh(1))のリダイレクト構文を 使わなければならない ということに注意してください! なぜ Perlのsystem()、backticks、パイプオープンの全てで Bourneシェルのものを使うかは http://www.perl.com/CPAN/doc/FMTEYEWTK/versus/csh.whynot で説明されています。

あるコマンドの標準出力と標準エラー出力を両方とも捉えるには:

    $output = `cmd 2>&1`;                       # backticksか、パイプと
    $pid = open(PH, "cmd 2>&1 |");              # 読み込みを使う
    while (<PH>) { }                            # 

あるコマンドの標準出力Tを捉え、標準エラー出力を捨てるには:

    $output = `cmd 2>/dev/null`;                # backtikcsか、パイプと
    $pid = open(PH, "cmd 2>/dev/null |");       # 読み込みを使う
    while (<PH>) { }                            # 

あるコマンドの標準エラー出力を捉え、標準出力を捨てるには:

    $output = `cmd 2>&1 1>/dev/null`;           # backtikcsか、パイプ
    $pid = open(PH, "cmd 2>&1 1>/dev/null |");  # 読み込みを使う
    while (<PH>) { }                            # 

To exchange a command's STDOUT and STDERR in order to capture the STDERR but leave its STDOUT to come out our old STDERR:

あるコマンドの標準エラー出力を捉えるために 標準出力と標準エラー出力を入れ替えるが、標準出力が 古い標準エラー出力に出るようにするには:

    $output = `cmd 3>&1 1>&2 2>&3 3>&-`;        #  backtikcsか、パイプと
    $pid = open(PH, "cmd 3>&1 1>&2 2>&3 3>&-|");# 読み込みを使う
    while (<PH>) { }                            #

標準出力と標準エラー出力の両方を分けて読み出すには、 別々のファイルにリダイレクトしてしまって、 その後でそのファイルをプログラムから読むというのが最も簡単で 安全な方法です:

    system("program args 1>/tmp/program.stdout 2>/tmp/program.stderr");

これらの例では順序が重要です。なぜなら、 シェルがリダイレクトのためのファイルディスクリプタを処理する順序は 正確に左から右へという順になっているからです。

    system("prog args 1>tmpfile 2>&1");
    system("prog args 2>&1 1>tmpfile");

最初のコマンドは標準出力と標準エラー出力の両方を 一時ファイルに送ります。二番目のコマンドは古い標準出力だけを ファイルへと送り、古い標準エラー出力は古い標準出力へと 送り出します。

なぜopen()は パイプのオープンに失敗したときに エラーを返さないのでしょうか?

Because the pipe open takes place in two steps: first Perl calls fork() to start a new process, then this new process calls exec() to run the program you really wanted to open. The first step reports success or failure to your process, so open() can only tell you whether the fork() succeeded or not.

パイプのオープンは二つのステップを踏んでいるからです。まず第一に Perlは新たなプロセスを開始するためにfork()を呼び出し、その後で あなたが本当に実行したいと考えていた プログラムを実行するために、この新たなプロセスがexec()を呼び出し ます。最初のステップはあなたのプロセスが成功したか失敗したか を報告します。そのため、open()はあなたに対してfork()が成功した かどうかだけしか知らせることができないのです。

To find out if the exec() step succeeded, you have to catch SIGCHLD and wait() to get the exit status. You should also catch SIGPIPE if you're writing to the child--you may not have found out the exec() failed by the time you write. This is documented in perlipc.

exec()ステップが成功したことを確認するには、SIGCHLDを捕捉して wait()を使ってその終了ステータスを得る必要があります。 子プロセスに対する出力を行っているのであれば、同様にして SIGPIPEを捕捉する必要があるでしょう。書き込み時に起きたexec()の 失敗は捉えられないかもしれません。これはperlipcに説明があります。

In some cases, even this won't work. If the second argument to a piped open() contains shell metacharacters, perl fork()s, then exec()s a shell to decode the metacharacters and eventually run the desired program. Now when you call wait(), you only learn whether or not the shell could be successfully started...it's best to avoid shell metacharacters.

一部の事態においては、これすらうまくいかない場合があります。 パイプをオープンするための第二引数がシェルのメタキャラクタを 含んでいる場合、perlはまずfork()し、それからメタキャラクタの 展開をするためのシェルを exec() し、最終的に要求されているプログラムを 実行します。 ここで wait() を使った場合、shell が正しく起動したかどうかだけが わかります...シェルメタキャラクタを避けるのが最善の方法です。

spawn()パラダイムに従ったシステムでは、おそらく open()はあなたが期待したように動作するでしょう-- perlがコマンドを実行するためにシェルを使わない限りは。 その場合、 fork()/exec() の説明はここでも適用されます。

voidコンテキストでbakticksを使うことのなにが悪いのでしょうか?

厳密に言えばありません。形式的に言えば、backticksは(潜在的にとても大きな) 戻り値を返していてあなたはそれを無視することになるので、 保守しやすいコードを書くための良い方法ではありません。 出力のすべてを読み込む必要があってそのためのメモリーを割りつけ、 それを捨て去ることになるので非常に非効率的になる可能性があります。 非常に多くの人が次のような書きかたをしてしまっています:

    `cp file file.bak`;

そしてその人達はこう考えるのです “おい、俺はプログラムを実行させるのに いつだってbackticksを使うんだぜ”と。これは悪い考えです: backticksは、プログラムの出力を取り込んでしまうからです。system() 関数はプログラムを実行させるためのものです。

以下のような行を考えてみましょう:

    `cat /etc/termcap`;

これは出力をどこにも代入してないので、 (多少なりとも)メモリーを浪費するだけのことになります。 それに加えて、プログラムが正しく実行されたかどうかを確認するために $?を見るのを忘れています。

    print `cat /etc/termcap`;

このコードは、以下のように書くべきでしょう

    system("cat /etc/termcap") == 0
        or die "cat program failed!";

これは即座に出力を得て(終了時にではなく、プログラムが生成した時点で)、 その戻り値のチェックも行います。

system() also provides direct control over whether shell wildcard processing may take place, whereas backticks do not.

system()はまた、シェルのワイルドカード処理を行えるかどうかを直接 制御しますが、backticksはそういった制御は行いません。

どうすればシェルの処理をせずにbackticksを呼び出すことができますか?

ちょっとトリッキーになります。

    @ok = `grep @opts '$search_string' @filenames`;

と書くのではなく、以下のようにする必要があります:

    my @ok = ();
    if (open(GREP, "-|")) {
        while (<GREP>) {
            chomp;
            push(@ok, $_);
        }
        close GREP;
    } else {
        exec 'grep', @opts, $search_string, @filenames;
    }

Just as with system(), no shell escapes happen when you exec() a list. Further examples of this can be found in "Safe Pipe Opens" in perlipc.

system()を使ったときと同じく、シェルエスケープはexec()のリストに 対して行われません。 さらなる例が "Safe Pipe Opens" in perlipc にあります。

Note that if you're stuck on Microsoft, no solution to this vexing issue is even possible. Even if Perl were to emulate fork(), you'd still be hosed, because Microsoft gives no argc/argv-style API. Their API always reparses from a single string, which is fundamentally wrong, but you're not likely to get the Gods of Redmond to acknowledge this and fix it for you.

もしあなたがマイクロソフトに捕まっているのなら、この悩ましい問題を 解決する方法は全くありません。 たとえ Perl が fork() をエミュレートしたとしても、 まだうまくいきません。 なぜならマイクロソフトは argc/argv 形式の API を提供していないからです。 これらの API は必ず単一の文字列を再パーズします。 これは根本的に間違っていますが、 これをレッドモンド(訳注:マイクロソフト本社の所在地)の神々に 認めさせて修正させるのはそう簡単ではないでしょう。

なぜEOF(UNIXでの^D、MSーDOSでの^Z)を受け取った後で STDINから読み込むことができないのでしょうか?

一部の stdio ではエラーフラグと eof フラグがセットされ、 それをクリアする必要があるからです。 POSIXモジュールはこのために使えるclearerr()を定義しています。 これは、フラグをクリアするための技術的に正しい方法です。 以下の方法はこれよりは信頼性にかけるやり方です:

  1. 以下の例のように、シークポインターを保存しておいてそこへ移動します:

        $where = tell(LOG);
        seek(LOG, $where, 0);
  2. 上のやりかたがだめなら、一度ファイルの別の部分にシークして、それから 元の場所にシークするようにします。

  3. これでもだめなら、ファイルの別の部分にシークして何かを読み出し、それから 元の場所にシークするようにします。

  4. これでだめならstdioパッケージで行うことはあきらめて、sysreadを使います。

どうやれば私のシェルスクリプトを perl に変換できますか?

Learn Perl and rewrite it. Seriously, there's no simple converter. Things that are awkward to do in the shell are easy to do in Perl, and this very awkwardness is what would make a shell->perl converter nigh-on impossible to write. By rewriting it, you'll think about what you're really trying to do, and hopefully will escape the shell's pipeline datastream paradigm, which while convenient for some matters, causes many inefficiencies.

Perl を学び、自分で書き直しましょう。まじめな話、単純なコンバーターと いうものはありません。 シェルで行うには不格好になるようなこともPerlでは簡単に行うことができ、 そして、このとても不格好なことがシェル→perlコンバーターを作製することを ほとんど不可能なことにしているのです。 自分で書き換えをすることで、あなたは自分が本当に試すべきことについて 考えるようになり、シェルの(便利なときもあるものの多くの非効率を持ち込む) パイプラインデータストリームパラダイムから逃れることができるでしょう。

telnetやftpのセッションを実行するためにperlを使うことができますか?

Net::FTP, TCP::Client, Net::Telnet といったモジュール(CPANで入手可能です)を 試してみてください。 http://www.perl.com/CPAN/scripts/netstuff/telnet.emul.shar も telnet プロトコルをエミュレートする助けになるでしょうが、 Net::Telnet は使うのがとても簡単です。

あなたのやりたいことが telnet のふりをすることであっても初期化時の telnet のハンドシェイクを必要としないのであれば、 標準的な dual-process アプローチで十分でしょう。

    use IO::Socket;             # 5.004で追加
    $handle = IO::Socket::INET->new('www.perl.com:80')
            || die "can't connect to port 80 on www.perl.com: $!";
    $handle->autoflush(1);
    if (fork()) {               # XXX: undef は失敗を意味する
        select($handle);
        print while <STDIN>;    # 標準入力からすべてをソケットへ
    } else {
        print while <$handle>;  # ソケットからのすべてを標準出力へ
    }
    close $handle;
    exit;

どうすれば Perlで expect を書けますか?

 Once upon a time, there was a library called chat2.pl (part of the
standard perl distribution), which never really got finished.  If you
find it somewhere, I<don't use it>.  These days, your best bet is to
look at the Expect module available from CPAN, which also requires two
other modules from CPAN, IO::Pty and IO::Stty.

昔々、chat2.pl と呼ばれたライブラリがありました(これは標準の perl 配布キットに含まれます)。 もしこれをどこかで見つけても使ってはいけません。 今日では、CPAN にある IO::Pty や IO::Stty といった ライブラリを探すのが最善でしょう。

“ps”のようなプログラムから、perlのコマンドラインを隠す方法はありますか?

まず初めに、あなたが(たとえば他人がパスワードを除くのを避けるためなどの) セキュリティ上の理由でそれを行おうとしてるのであれば、 重要な情報が引数として与えられることがないようにプログラムを 書き直すべきだということに注意してください。 引数を隠すことは、あなたのプログラムを完全に安全なものにすることはありません。

外部から見えるコマンドラインを実際に書き換えるために、perlvarで 説明されているように $0という変数に代入することができます。 ただし、これはすべてのオペレーティングシステムで実行できるというものでは ありません。 sendmailのようなデーモンプログラムは以下の例のように状態を設定します:

    $0 = "orcus [accepting connections]";

perlスクリプトの中で、ディレクトリを変更したり環境変数を変更しました. なぜ、スクリプトを終了したときこれらの変更は無効になってしまうのでしょうか? 変更が反映されるようにするには?

Unix

In the strictest sense, it can't be done--the script executes as a different process from the shell it was started from. Changes to a process are not reflected in its parent--only in any children created after the change. There is shell magic that may allow you to fake it by eval()ing the script's output in your shell; check out the comp.unix.questions FAQ for details.

もっとも厳密な意味で言うと、それはできません--スクリプトはそれを 起動したシェルとは異なるプロセスで実行されるのです。 あるプロセスに対する変更はその親に反映されることはありません --変更した後で生成された子プロセスに対してのみ反映されます。 あなたの使っているシェルにおいてスクリプトの出力をeval()することによって、 お望みのことをしたように見せかけるシェルマジック (shell magic)があります。 詳しくは comp.unix.questions FAQを調べてください。

プロセスの完了を待つことなしにそのファイルハンドルをクローズするには?

Assuming your system supports such things, just send an appropriate signal to the process (see "kill" in perlfunc). It's common to first send a TERM signal, wait a little bit, and then send a KILL signal to finish it off.

あなたの使っているシステムがそういった機能をサポートしていると仮定すると、 そのプロセスに対して適切なシグナルを送るだけです ("kill" in perlfuncを参照してください)。 最初にTERMシグナルを送り、ちょっとだけ待って、 終了させるためにKILLシグナルを送るというのが一般的なものです。

デーモンプロセスをfork()するには?

あなたのいうデーモンプロセスが detached されている (ttyと結び付けられていない)ものであれば、 以下の手順がほとんどのUNIX的なシステムで動作するということが報告されています。 非UNIXユーザーは Your_OS::Process モジュールで他の解決策のをあたるべきでしょう。

  • /dev/ttyをオープンし、それに TIOCNOTTY ioctl を使います。 詳しくは tty(4)を参照してください。 そのほかもっと良いのは、POSIX::setsid()関数を使うことです。 これによってプロセスグループに関して思い煩う必要がなくなります。

  • /へディレクトリを変更します。

  • STDIN、STDOUT、STDERRを再オープンします。 これでこれらのハンドルは以前のttyとは結び付けらていない状態になります。

  • 以下のようにしてバックグラウンドにします:

        fork && exit;

CPANで入手できる Proc::Daemonモジュールはこれらの操作を 行ってくれる関数を提供しています。

自分が対話的に実行されているかどうかを知るには?

良い質問です。-t STDIN and -t STDOUTが手掛かりを与えてくれるときもあるし、 そうでないときもあります。

    if (-t STDIN && -t STDOUT) {
        print "Now what? ";
    }

POSIXシステムでは以下のようにして、あなたが端末を制御しているカレントの プロセスグループにマッチするようなプロセスグループを 所有しているかどうかを検査できます:

    use POSIX qw/getpgrp tcgetpgrp/;
    open(TTY, "/dev/tty") or die $!;
    $tpgrp = tcgetpgrp(fileno(*TTY));
    $pgrp = getpgrp();
    if ($tpgrp == $pgrp) {
        print "foreground\n";
    } else {
        print "background\n";
    }

遅いイベントをタイムアウトするには?

Use the alarm() function, probably in conjunction with a signal handler, as documented in "Signals" in perlipc and the section on ``Signals'' in the Camel. You may instead use the more flexible Sys::AlarmCall module available from CPAN.

"Signals" in perlipcやらくだ本の ``Signal'' の章で説明されているように、 alarm()関数と、おそらくはシグナルハンドラーを組み合わせて使います。 この代わりに、CPANにあるより柔軟性のある Sys::AlarmCall モジュールを使うこともできます。

CPUのリミットを設定するには?

CPANにあるBSD::Resourceモジュールを使います。

UNIXシステムでゾンビを回避するには?

SIGCHLDを受け取ったときに wait()を呼び出すように "Signals" in perlipcにある 刈り取り機プログラム (reaper code)を使うか、"fork" in perlfuncで 説明されている double-fork テクニックを使います。

SQLデータベースを使うには?

SQLデータベースに対する優れたインターフェースが数多くあります。 http://www.perl.com/CPAN/modules/DBD で入手可能な DBD::* モジュールを 参照してください。 多くの情報が http://www.symbolstone.org/technology/perl/DBI/ で得られます。

コントロール-C で system() が exit するようにするには?

できません。system()呼び出しを模倣する必要があり (perlipcのサンプルコードを参照してください)、サブプロセスでのシグナルを送る INT シグナルのためのシグナルハンドラーを持つ必要があります。 あるいは、以下のようにしてチェックすることもできます:

    $rc = system($cmd);
    if ($rc & 127) { die "signal death" } 

ブロックせずにファイルをオープンするには?

幸運にもあなたの使っているシステムがノンブロッキング読み出し (ほとんどのUNIX的システムはサポートしています)をサポートしているのであれば、 FcntlモジュールのO_NDELAY や O_NONBLOCK というフラグを sysopne()と一緒に使うだけです。

    use Fcntl;
    sysopen(FH, "/tmp/somefile", O_WRONLY|O_NDELAY|O_CREAT, 0644)
        or die "can't open /tmp/somefile: $!":

モジュールを CPAN からインストールするには?

The easiest way is to have a module also named CPAN do it for you. This module comes with perl version 5.004 and later. To manually install the CPAN module, or any well-behaved CPAN module for that matter, follow these steps:

最も単純な方法は、その仕事をしてくれるCPANモジュールを入手することです。 このモジュールは、5.004以降のperlに付属しています。 CPANモジュールや問題に対して行儀よく振る舞うCPANモジュールを手作業で インストールするには、以下のステップに従います:

  1. ソースファイルを一時的な領域に展開します。

  2.     perl Makefile.PL
  3.     make
  4.     make test
  5.     make install

あなたの使っているperlが、動的ローディングを使わずにコンパイルされたものであれば、 ステップ 3 の (make)をmake perlで置き換える必要があり、 エクステンションをリンクした新しいperlの実行ファイルを入手することになります。

エクステンションのビルドについての詳細は ExtUtils::MakeMaker を参照して下さい。 次の質問``What's the difference between require and use?''も参照してください。

requireとuseの間の違いとは?

Perl offers several different ways to include code from one file into another. Here are the deltas between the various inclusion constructs:

Perlでは、あるファイルを別のファイルから取り込むのに何種類かの 方法を提供しています。以下はそれぞれの方法の違いを明確にしたものです:

    1)  do $fileは`cat $file`と似ていますが、以下の点が違います:
        1.1: @INCを検索し、%INCを更新します。
        1.2: evalされたコードに*関係ない*レキシカルスコープを残します。

    2)  require $fileは do $Fileに似ていますが、以下の点が違います:
        2.1: 余分なローディングをチェックし、既にロードしたファイルであれば
             スキップします。
        2.2: ファイルが見つからなかったり、コンパイルできなかったり実行でき
             なかったときには例外を発生します。

    3)  require Moduleは require "Module.pm"と似ていますが、以下の点が違います:
        3.1: "::"をあなたの使っているシステムのディレクトリセパレータ-に変換します。
        3.2: 間接オブジェクトとしてのクラスモジュールを明確にするための解析準備をします。

    4)  use Moduleはrequire Moduleに似ていますが、以下の点が違います:
        4.1: 実行時にではなくコンパイル時にモジュールをロードします。
        4.2: カレントのパッケージにその取り込んだパッケージでのシンボルと
             semanticsをインポートします。

一般的には、useと適切なPerlモジュールを使いたいと考えるでしょう。

自分自身のモジュール/ライブラリディレクトリを持つにはどうすればいいですか

モジュールを作成するときに、Makefileを生成する時点でPREFIXオプションを使います:

    perl Makefile.PL PREFIX=/u/mydir/perl

こうした後で、そのモジュールやライブラリを使用するスクリプトを 実行する前に環境変数 PERL5LIBを設定するか、

    use lib '/u/mydir/perl';

のようにします。これは、

    BEGIN {
        unshift(@INC, '/u/mydir/perl');
    }

とほとんど同じですが、libモジュールはマシン依存のサブディレクトリを 検査する点が異なります。

より詳しい情報はPerlのlibを参照してください。

私のプログラムの置いてある場所をモジュール/ライブラリの検索パスに 追加するには?

    use FindBin;
    use lib "$FindBin::Bin";
    use your_own_modules;

実行時に include path にディレクトリを追加するには?

include パスを変更するためのお薦めの方法を挙げておきましょう:

    the PERLLIB environment variable
    the PERL5LIB environment variable
    the perl -Idir command line flag
    the use lib pragma, as in
        use lib "$ENV{HOME}/myown_perllib";

後ろのものが特に便利です。なぜなら、これはマシン依存のアーキテクチャーについて わかるからです。プラグマ的モジュール(pragmatic module) lib.pmは Perl 5.002で最初に導入されました。

socket.ph とは一体何で、それはどこで入手できますか?

それは perl4 スタイルのファイルで、ネットワーク使用のための 値を定義しているものです。これは Perl がインストールされたときに h2ph を使って作成されることもありますが、そうでないときもあります。 最近のやり方ではuse Socketを代わりに使用します。

AUTHOR AND COPYRIGHT

Copyright (c) 1997-1999 Tom Christiansen and Nathan Torkington. All rights reserved.

When included as part of the Standard Version of Perl, or as part of its complete documentation whether printed or otherwise, this work may be distributed only under the terms of Perl's Artistic License. Any distribution of this file or derivatives thereof outside of that package require that special arrangements be made with copyright holder.

Irrespective of its distribution, all code examples in this file are hereby placed into the public domain. You are permitted and encouraged to use this code in your own programs for fun or for profit as you see fit. A simple comment in the code giving credit would be courteous but is not required.

POD ERRORS

Hey! The above document had some coding errors, which are explained below:

Around line 399:

alternative text 'perlvar/$' contains non-escaped | or /

Around line 407:

alternative text 'perlvar/$' contains non-escaped | or /