!!!main program 目次 {{outline}} !!main programとは main programは設定以下から exit; までを指し、動作の分岐点としてSOSIIの土台となる部分です サブルーチンではないが、改造によって新たな機能を追加する際によく修正が必要になる部分でもあります。 ここでは、スクリプトのはじまりから exit; までを解説します。 !!ソースコードの解説 #!/usr/local/bin/perl # ↑サーバに合わせて設定 CGIを動かすためのおまじない。 PerlというCGIによく使われるプログラム言語へのパスで、これによってperlのある場所を指定しています。 サーバによってperlが置かれている場所が違うので、サーバに合わせて書き換えなければいけません。 多くの場合サーバのFAQや仕様の書かれたページにperlへのパスが載っているので調べてみましょう。 # ################################################################## # Script of Saga II $ver = '1.10'; # Copyright (C) 2001-2003 Missing Link. # : # ################################################################## $ver にバージョン情報を代入。 require 'jcode.pl'; # jcode.plのパス 644 require関数によりjcode.plを読み込みます。 # ---------- FILE PATH $cgiurl = './sos2.cgi'; # sos.cgiのパス 755(705) $sosdat = './sos.dat'; # sos.datのパス 666(606) $jobdat = './job.dat'; # job.datのパス 666(606) $itmdat = './itm.dat'; # itm.datのパス 666(606) : # ---------- METHOD $method = 'POST'; # アクションメソッド (POST Only) 設定をひとまとめにした部分。 改造を行ったさい新しい設定が必要になった場合は、ここに追加すると都合がいい。 改造サイトで「設定に追加してください」などの指定があった場合はこの部分を指します。 また、マシマロ分割・統合版のファイル名から、init.iniと呼ばれることもあり、 「init.iniに追加」などの指定があった場合もこの部分を指していると思ってまず間違いないでしょう。 # Main Program # ここからメインプログラムと呼ばれる部分です。 &decode; sub decode を呼び出します。 ここでフォームから送られてきた情報にデコード処理を行い、 $Fm{id} などの連想配列 %Fm に代入しています。 if ($Fm{'id'} =~ /\W/) { &error('不正な入力です') } if ($Fm{'pd'} =~ /\W/) { &error('不正な入力です') } if ($Fm{'pd2'} =~ /\W/) { &error('不正な入力です') } *$Fm{id} (フォームから送られてきた、プレイヤーのID) *$Fm{pd} (フォームから送られてきた、パートナーのID) *$Fm{pd2}(テキストフォームに直接入力されたパートナーID) の3つの変数の中に\W(半角英数字[a-zA-Z0-9_]以外の文字)が入っていればエラー処理を行います。 これはフォームから送られてきたIDを利用してファイルを開くために必要な処理で、 この処理を行わない場合、予測しない文字列がIDに含まれると 別のファイルを開いてしまうなどの脆弱性につながる危険性があります。 &lock; sub lock を呼び出します。 ファイルロックを実行し、ロックが解除されるまでは他のリクエストに待機させる排他処理を行います。 if (!$Fm{'mode'}) { &main_form } if ($Fm{'mode'} eq 'norm_save') { &save_game } if ($Fm{'mode'} eq 'hide_save') { &save_game } if ($Fm{'mode'} eq 'make_new') { &make_new } if ($Fm{'mode'} eq 'make_con') { &make_con } if ($Fm{'mode'} eq 'new_game') { &enter_form } if ($Fm{'mode'} eq 'con_game') { &enter_form } if ($Fm{'mode'} eq 'find_partner') { &contact_form } if ($Fm{'mode'} eq 'find_item') { &play_form } if ($Fm{'mode'} eq 'dump_before') { &play_form } if ($Fm{'mode'} eq 'dump_after') { &play_form } if ($Fm{'mode'} eq 'goods_before') { &action_form } if ($Fm{'mode'} eq 'goods_after') { &play_form } if ($Fm{'mode'} eq 'use_before') { &action_form } if ($Fm{'mode'} eq 'use_after') { &play_form } if ($Fm{'mode'} eq 'stell_before') { &action_form } if ($Fm{'mode'} eq 'stell_after') { &play_form } if ($Fm{'mode'} eq 'stell_comp') { &play_form } if ($Fm{'mode'} eq 'judge_before') { &action_form } if ($Fm{'mode'} eq 'judge_after') { &play_form } if ($Fm{'mode'} eq 'trade_before') { &action_form } if ($Fm{'mode'} eq 'trade_after') { &contact_form } if ($Fm{'mode'} eq 'sell_before') { &action_form } if ($Fm{'mode'} eq 'sell_after') { &contact_form } if ($Fm{'mode'} eq 'buy_before') { &action_form } if ($Fm{'mode'} eq 'buy_after') { &contact_form } if ($Fm{'mode'} eq 'fee_before') { &play_form } if ($Fm{'mode'} eq 'fee_after') { &play_form } if ($Fm{'mode'} eq 'cr') { &contact_form } if ($Fm{'mode'} eq 'rv') { &contact_form } if ($Fm{'mode'} eq 'com_before') { &play_form } if ($Fm{'mode'} eq 'com_after') { &play_form } if ($Fm{'mode'} eq 'note_before') { &play_form } if ($Fm{'mode'} eq 'note_after') { &play_form } if ($Fm{'mode'} eq 'poem_before') { &play_form } if ($Fm{'mode'} eq 'poem_after') { &play_form } if ($Fm{'mode'} eq 'name_before') { &play_form } if ($Fm{'mode'} eq 'name_after') { &play_form } if ($Fm{'mode'} eq 'words_before') { &contact_form } if ($Fm{'mode'} eq 'words_after') { &contact_form } if ($Fm{'mode'} eq 'goodbye') { &play_form } if ($Fm{'mode'} eq 'list') { &list_order } if ($Fm{'mode'} eq 'list') { &player_list } if ($Fm{'mode'} eq 'sale') { &sale_order } if ($Fm{'mode'} eq 'my_record') { &my_record } if ($Fm{'mode'} eq 'reward') { &play_form } if ($Fm{'mode'} eq 'fight') { &contact_form } if ($Fm{'mode'} eq 'del_before') { &play_form } if ($Fm{'mode'} eq 'del_after') { &main_form } if ($Fm{'mode'} eq 'back_up') { &play_form } if ($Fm{'mode'} eq 'levy') { &levy } $Fm{mode} の内容によってプログラムを分岐しています。 $Fm{mode} がなければ sub main_form へ、 あれば *sub save_game *sub make_new *sub make_con *sub main_form *sub enter_form *sub play_form *sub contact_form *sub action_form *sub list_order *sub player_list *sub sale_order *sub my_record *sub levy のうち、対応するサブルーチンへ移行します。 多くの場合、プレイヤーの行動は *sub play_form *sub contact_form *sub action_form のどれかを通って実行されます。 SOS2の改造によってプレイヤーが実行するアクションを追加する場合、この部分に *if ($Fm{'mode'} eq '*****_before') { &play_form } *if ($Fm{'mode'} eq '*****_after') { &play_form } 上記のようなコードを必ずと言っていいほど追加することになります。 &unlock; &footer; exit; sub unlock を呼び出してファイルロックを解除し sub footer を呼び出して著作権表示とHTMLの終了をprint、 exit関数でプログラムを終了します。 !!キーワード解説 !require EXPR EXPRをPerlスクリプトファイルとして呼び出し、実行します。 実行する前に指定されたファイルが既に読み込まれていないか確認します。 実行したファイルは%INCに *$INC{$filename} = $realfilename; 形式で記録され、一度読み込んだファイルは二度呼び出されることはありません。 requireは実行結果の戻り値を必要とするので、読み込むファイルの最後に 1; と書いておく必要があります。これは *return 1; と同等です。 !&xxxxx(ARGUMENT) sub xxxxx を呼び出します。引数としてARGUMENTを渡すことが出来ます。 ARGUMENTは特殊変数 @_ という配列に格納され、配列としてサブルーチンに渡されます。 // //&xxxxxはPerl6からはサブルーチン呼び出しではなくリファレンスを返すようになるのであまり推奨しませんが、 //*明示的にサブルーチン呼び出しであることを宣言できる(perlに使用されている関数とサブルーチン名がかぶっても安心) //*引数を渡さない(空のリストでさえ)ので僅かではあるがパフォーマンスに優れる //という利点がありますし、デメリットもSOS2には関係ない話しだしべつにいいか。 // !exit EXPR プログラムの実行を終了してステータスコードとしてEXPRの値を返します。 EXPRが未定義の場合 0 を返します。 // //exitが返す値についてWWWサーバは参照しないという話ですがよく分かりません //プロセスが正しく終了したかのチェックに向いている? // !!関連項目 *コラム *sub decode *sub lock *sub unlock ---- !!!このページのコメント