第12章 プログラミング

目次

12.1. シェルスクリプト
12.1.1. POSIX シェル互換性
12.1.2. シェル変数
12.1.3. シェル条件式
12.1.4. シェルループ
12.1.5. シェル環境変数
12.1.6. シェルコマンドライン処理シーケンス
12.1.7. シェルスクリプトのためのユーティリティープログラム
12.2. インタープリター言語でのスクリプティング
12.2.1. インタープリター言語コードのデバグ
12.2.2. シェルスクリプトを使った GUI プログラム
12.2.3. GUI フィルター用のカスタム動作集
12.2.4. 究極の短い Perl スクリプト
12.3. コンパイル言語でのコーディング
12.3.1. C
12.3.2. 単純な C プログラム (gcc)
12.3.3. Flex — 改良版 Lex
12.3.4. Bison — 改良版 Yacc
12.4. 静的コード分析ツール
12.5. デバグ
12.5.1. 基本的な gdb 実行
12.5.2. Debian パッケージのデバグ
12.5.3. バックトレースの収集
12.5.4. 高度な gdb コマンド
12.5.5. ライブラリーへの依存の確認
12.5.6. 動的呼び出し追跡ツール
12.5.7. X エラーのデバグ
12.5.8. メモリーリーク検出ツール
12.5.9. バイナリーのディスアッセンブリー
12.6. ビルドツール
12.6.1. Make
12.6.2. Autotools
12.6.2.1. プログラムをコンパイルとインストール
12.6.2.2. プログラムのアンインストール
12.6.3. Meson
12.7. ウェッブ
12.8. ソースコード変換
12.9. Debian パッケージ作成

Debian システム上でプログラミングを学ぶ人がパッケージ化されたソースコードを読み込めるようになるための指針を示します。以下はプログラムに関する特記すべきパッケージと対応する文書パッケージです。

オンラインリファレンスは manpagesmanpages-dev パッケージをインストールした後で "man name" とタイプすると利用可能です。GNU ツールのオンラインリファレンスは該当する文書パッケージをインストールした後で "info program_name" とタイプすると使えます。一部の GFDL 文書は DFSG に準拠していないと考えられているので main アーカイブに加えて contribnon-free アーカイブを含める必要があるかもしれません。

バージョン コントロール システム ツールの使用を考えましょう。「Git」を参照下さい。

[警告] 警告

"test" を実行可能なテストファイルの名前に用いてはいけません。"test" はシェルのビルトインです。

[注意] 注意

ソースから直接コンパイルしたソフトウェアープログラムは、システムプログラムとかち合わないように、"/usr/local" か "/opt" の中にインストールします。

[ヒント] ヒント

"99ボトルのビールの歌" 作成のコード例はほとんど全てのプログラム言語に関する理解のための非常に好適です。

シェルスクリプトは実行ビットがセットされたテキストファイルで、以下に示すフォーマットのコマンドを含んでいます。

#!/bin/sh
 ... command lines

最初の行はこのファイル内容を読み実行するシェルインタープリタを指定します。

シェルスクリプトを読むのは Unix 的なシステムがどのように機能しているのかを理解する最良の方法です。ここでは、シェルプログラムに関する指針や心がけを記します。失敗から学ぶために "シェルの失敗" (https://www.greenend.org.uk/rjk/2001/04/shell.html) を参照下さい。

シェル対話モード (「シェルプロンプト」「Unix 的テキスト処理」を参照下さい) と異なり、シェルスクリプトは変数や条件文やループを繁用します。

多くのシステムスクリプトは POSIX シェル (表1.13「シェルプログラムのリスト」を参照下さい) のどれで解釈されるか分かりません。

  • デフォールトの非インタラクティブなシェル "/usr/bin/sh" は /usr/bin/dash をさしているシムリンクで、多くのシステムプログラムで使われます。

  • デフォルトのインタラクティブなシェルは /usr/bin/bash です。

全ての POSIX シェル間でポータブルとするために bashismszshisms を使うシェルスクリプトを書くのを避けます。checkbashisms(1) を使うとこれがチェックできます。


"echo" コマンドはその実装がシェルビルトインや外部コマンド間で相違しているので以下の注意点を守って使わなければいけません。

  • "-n" 以外のどのコマンドオプション使用も避けます。

  • 文字列中にエスケープシーケンスはその取扱いに相違があるので使用を避けます。

[注記] 注記

"-n" オプションは実は POSIX シンタックスではありませんが、一般的に許容されています。

[ヒント] ヒント

出力文字列にエスケープシーケンスを埋め込む必要がある場合には、"echo" コマンドの代わりに "printf" コマンドを使います。

特別なシェルパラメーターがシェルスクリプト中ではよく使われます。


覚えておくべき基本的なパラメーター展開を次に記します。


ここで、これら全てのオペレーターのコロン ":" は実際はオプションです。

  • ":" 付き = 演算子は存在非ヌル文字列をテストします

  • ":" 無し = 演算子は存在のみをテストします


各コマンドは条件式に使えるエグジットステイタスを返します。

  • 成功: 0 ("真")

  • エラー: 非0 ("偽")

[注記] 注記

シェル条件文の文脈において "0" は "真" を意味しますが、C 条件文の文脈では "0" は "偽" を意味します。

[注記] 注記

"[" は、"]" までの引数を条件式として評価する、test コマンドと等価です。

覚えておくべき基本的な条件文の慣用句は次です。

  • "command && 成功したらこのcommandも実行 || true"

  • "command || もしcommandが成功しないとこのコマンドも実行 || true"

  • 以下のような複数行のスクリプト断片

if [ conditional_expression ]; then
 if_success_run_this_command
else
 if_not_success_run_this_command
fi

ここで、シェルが "-e" フラグ付きで起動された際にシェルスクリプトがこの行で誤って exit しないようにするために、末尾の "|| true" が必要です。



条件式中の算術整数比較演算子は "-eq" と "-ne" と "-lt" と "-le" と "-gt" と "-ge" です。

シェルはおおよそ以下のシーケンスでスクリプトを処理します。

  • シェルは1行読み込みます。

  • シェルは、もし "…"'…' の中なら、行の一部を1つのトークンとしてグループします。

  • シェルは1行を以下のによってトークンに分割します。

    • 空白: space tab newline

    • メタ文字: < > | ; & ( )

  • "…"'…' の中でない場合、シェルは各トークンを予約語に対してチェックしその挙動を調整します。

    • 予約語: if then elif else fi for in while unless do done case esac

  • "…"'…' の中でない場合、シェルはエイリアスを展開します。

  • "…"'…'の中でない場合、シェルはティルダを展開します。

    • "~" → 現ユーザーのホームディレクトリー

    • "~user" → user のホームディレクトリー

  • '…' の中でない場合、シェルは パラメーター"をその値に展開します。

    • パラメーター: "$PARAMETER" or "${PARAMETER}"

  • '…' の中でない場合、シェルは コマンド置換を展開します。

    • "$( command )" → "command" の出力

    • "` command `" → "command" の出力

  • "…"'…' の中でない場合、シェルは パス名のグロブを展開します。

    • * → あらゆる文字

    • ? → 1文字

    • […] → "" 中の1つ

  • シェルはコマンドを次から検索して実行します。

    • 関数定義

    • ビルトインコマンド

    • "$PATH" 中の実行ファイル

  • シェルは次行に進みこのプロセスを一番上から順に反復します。

ダブルクォート中のシングルクォートに効果はありません。

シェル環境中で "set -x" を実行したり、シェルを "-x" オプションで起動すると、シェルは実行するコマンドを全てプリントするようになります。これはデバグをするのに非常に便利です。

Debian システム上でできるだけポータブルなシェルプログラムとするには、ユーティリティープログラムを essential パッケージで提供されるプログラムだけに制約するのが賢明です。

  • "aptitude search ~E" はessential (必須) パッケージをリストします。

  • "dpkg -L パッケージ名 |grep '/man/man.*/'" は パッケージ名 パッケージによって提供されるコマンドのマンページをリストします。


[ヒント] ヒント

moreutils は Debian の外では存在しないかも知れませんが、興味深い小さなプログラムを提供します。もっとも特記すべきは、オリジナルファイルを上書きしたいときに非常に有効な sponge(8) です。

例は「Unix 的テキスト処理」を参照下さい。


Debian 上のタスクを自動化したい場合には、まず最初にインタープリター言語でタスクをスクリプト化すべきです。 インタープリター言語選択のガイドラインは:

  • もしタスクがシェルプログラムでできた CLI プログラムを組み合わせる簡単なタスクなら、dash を使います。

  • もしタスクが簡単なタスクではなく何もないところから書くなら、python3 を使います。

  • もしタスクをするための加筆をする必要がある perl, tcl, ruby, ... で書かれたコードが Debian 上にすでに存在する場合には、その言語を使います。

もし出来上がったコードがおそすぎる場合には、実行速度にクリチカルな部分のみコンパイラー言語で書き直しインタープリター言語から呼びます。

シェルスクリプトは魅力的な GUI プログラムを作るまで改善できます。echoread コマンドを使う鈍いやりとりに代えて、いわゆるダイアログプログラムを使うのがこのトリックです。


簡単なシェルスクリプトだけでできるほど GUI プログラムがいかに簡単ということを示す GUI プログラムの例は以下です。

このスクリプトはファイルの選択(デフォルトは/etc/motd) に zenity を使い、それを表示します。

このスクリプトの GUI ローンチャーは以下のようにして生成できます 「GUI からプログラムをスタート」.

#!/bin/sh -e
# Copyright (C) 2021 Osamu Aoki <[email protected]>, Public Domain
# vim:set sw=2 sts=2 et:
DATA_FILE=$(zenity --file-selection --filename="/etc/motd" --title="Select a file to check") || \
  ( echo "E: File selection error" >&2 ; exit 1 )
# Check size of archive
if ( file -ib "$DATA_FILE" | grep -qe '^text/' ) ; then
  zenity --info --title="Check file: $DATA_FILE" --width 640  --height 400 \
    --text="$(head -n 20 "$DATA_FILE")"
else
  zenity --info --title="Check file: $DATA_FILE" --width 640  --height 400 \
    --text="The data is MIME=$(file -ib "$DATA_FILE")"
fi

シェル スクリプトでの GUI プログラムへのこのようなアプローチは簡単な選択ケースでのみ有効です。何らかの複雑のあるプログラムを書く場合には、もっと能力あるプラットフォームで書くことを考えましょう。


ここで、「Flex — 改良版 Lex」「Bison — 改良版 Yacc」は、コンパイラーのようなプログラムがどのように高レベル記述を C 言語にすることで C 言語で書かれているかを示すために含めています。

C プログラム言語で書かれたプログラムをコンパイルする適正な環境を以下のようにして設定できます。

# apt-get install glibc-doc manpages-dev libc6-dev gcc build-essential

GNU C ライブラリーパッケージである libc6-dev パッケージは、C プログラム言語で使われるヘッダーファイルやライブラリールーチンの集合である C 標準ライブラリーを提供します。

C のリファレンスは以下を参照下さい。

  • "info libc" (C ライブラリー関数リファレンス)

  • gcc(1) と "info gcc"

  • 各 C ライブラリー関数名(3)

  • Kernighan & Ritchie 著, "The C Programming Language", 第2版 (Prentice Hall)

簡単な例の "example.c" は"libm" ライブラリーを使って実行プログラム "run_example" に以下のようにしてコンパイル出来ます。

$ cat > example.c << EOF
#include <stdio.h>
#include <math.h>
#include <string.h>

int main(int argc, char **argv, char **envp){
        double x;
        char y[11];
        x=sqrt(argc+7.5);
        strncpy(y, argv[0], 10); /* prevent buffer overflow */
        y[10] = '\0'; /* fill to make sure string ends with '\0' */
        printf("%5i, %5.3f, %10s, %10s\n", argc, x, y, argv[1]);
        return 0;
}
EOF
$ gcc -Wall -g -o run_example example.c -lm
$ ./run_example
        1, 2.915, ./run_exam,     (null)
$ ./run_example 1234567890qwerty
        2, 3.082, ./run_exam, 1234567890qwerty

ここで、"-lm" はsqrt(3) のために libc6 パッケージで提供されるライブラリー "/usr/lib/libm.so" をリンクするのに必要です。実際のライブラリーは "/lib/" 中にあるファイル名 "libm.so.6" で、それは "libm-2.7.so" にシムリンクされています。

出力テキスト中の最後のパラメーターを良く見ましょう。"%10s" が指定されているにもかかわらず10文字以上あります。

上記のオーバーラン効果を悪用するバッファーオーバーフロー攻撃を防止のために、sprintf(3) や strcpy(3) 等の境界チェック無しのポインターメモリー操作関数の使用は推奨できません。これに代えて snprintf(3) や strncpy(3) を使います。

FlexLex 互換の高速字句解析生成ソフトです。

flex(1) の入門書は "info flex" の中にあります。

シンプルな例が "/usr/share/doc/flex/examples/" の下にあります。 [7]

Yacc 互換の前方参照可能な LR パーサーとか LALR パーサー生成ソフトは、いくつかのパッケージによって Debian 上で提供されています。


bison(1) の入門書は "info bison" の中にあります。

あなた自身の "main()" と "yyerror()" を供給する必要があります。"main()" は、Flex によって通常作成された "yylex()" を呼び出す "yyparse()" を呼び出します。

シンプルなターミナル上の計算機プログラムの作成例をここに示します。

example.y を作成しましょう:

/* calculator source for bison */
%{
#include <stdio.h>
extern int yylex(void);
extern int yyerror(char *);
%}

/* declare tokens */
%token NUMBER
%token OP_ADD OP_SUB OP_MUL OP_RGT OP_LFT OP_EQU

%%
calc:
 | calc exp OP_EQU    { printf("Y: RESULT = %d\n", $2); }
 ;

exp: factor
 | exp OP_ADD factor  { $$ = $1 + $3; }
 | exp OP_SUB factor  { $$ = $1 - $3; }
 ;

factor: term
 | factor OP_MUL term { $$ = $1 * $3; }
 ;

term: NUMBER
 | OP_LFT exp OP_RGT  { $$ = $2; }
  ;
%%

int main(int argc, char **argv)
{
  yyparse();
}

int yyerror(char *s)
{
  fprintf(stderr, "error: '%s'\n", s);
}

example.l を作成しましょう:

/* calculator source for flex */
%{
#include "example.tab.h"
%}

%%
[0-9]+ { printf("L: NUMBER = %s\n", yytext); yylval = atoi(yytext); return NUMBER; }
"+"    { printf("L: OP_ADD\n"); return OP_ADD; }
"-"    { printf("L: OP_SUB\n"); return OP_SUB; }
"*"    { printf("L: OP_MUL\n"); return OP_MUL; }
"("    { printf("L: OP_LFT\n"); return OP_LFT; }
")"    { printf("L: OP_RGT\n"); return OP_RGT; }
"="    { printf("L: OP_EQU\n"); return OP_EQU; }
"exit" { printf("L: exit\n");   return YYEOF; } /* YYEOF = 0 */
.      { /* ignore all other */ }
%%

そして、これを試すためにシェルプロンプトから以下を実行しましょう:

$ bison -d example.y
$ flex example.l
$ gcc -lfl example.tab.c lex.yy.c -o example
$ ./example
1 + 2 * ( 3 + 1 ) =
L: NUMBER = 1
L: OP_ADD
L: NUMBER = 2
L: OP_MUL
L: OP_LFT
L: NUMBER = 3
L: OP_ADD
L: NUMBER = 1
L: OP_RGT
L: OP_EQU
Y: RESULT = 9

exit
L: exit

静的解析(lint) のようなツールは、自動静的コード分析に役立ちます。

Indent のようなツールは整合性をもってソースコードの再フォーマットすることで人間によるコードレビューを助けます。

Ctags のようなツールは、ソースコード中に見つかる名前のインデックス(とかタグ)を生成することで、人間がコードのレビューするのを助けます。

[ヒント] ヒント

あなたの好きなエディター (emacsvim) を非同期の lint エンジン プラグインを使うように設定することはあなたがコードを書く際に役立ちます。このようなプラグインは Language Server Protocol を利用することで非常にパワフルになっています。プラグインは非常に変化の激しいので、Debian パッケージではなくアップストリーム コードを使うのは良い方策かもしれません。

表12.12 静的コード分析ツールのリスト

パッケージ ポプコン サイズ 説明
vim-ale I:0 2591 Vim 8 や NeoVim 用の非同期静的解析エンジン
vim-syntastic I:3 1379 Vim 用のシンタックスシェックのハック
elpa-flycheck V:0, I:1 808 Emacs 用の現代的な同時進行のシンタックスチェック
elpa-relint V:0, I:0 147 Emacs Lisp の正規表現 (regexp) の間違い検出器
cppcheck-gui V:0, I:1 7224 静的 C/C++ コード分析ツール (GUI)
shellcheck V:2, I:13 18987 シェルスクリプトの静的解析(lint)ツール
pyflakes3 V:2, I:15 20 Python 3 の受動チェッカー
pylint V:4, I:20 2018 Python コード静的チェックソフト
perl V:707, I:989 673 静的コードチェックソフト付きのインタープリタ: B::Lint(3perl)
rubocop V:0, I:0 3247 Ruby 静的コード分析ツール
clang-tidy V:2, I:11 21 Clang に基づく C++ の静的解析(lint)ツール
splint V:0, I:2 2320 C プログラムを静的にバグのチェックするためのツール
flawfinder V:0, I:0 205 C/C++ ソースコードを検査してセキュリティーの脆弱性を探すツール
black V:3, I:13 660 非妥協的な Python コードフォーマッター
perltidy V:0, I:4 2493 Perl スクリプトのインデントとリフォーマット
indent V:0, I:7 431 C 言語ソースコード フォーマッター プログラム
astyle V:0, I:2 785 C と C++ と Objective-C と C# と Java のソースコード インデンター
bcpp V:0, I:0 111 C(++) の美化プログラム
xmlindent V:0, I:1 53 XML ストリームリフォーマッタ
global V:0, I:2 1908 ソースコードの検索と閲覧のツール
exuberant-ctags V:2, I:20 341 ソースコード定義のタグファイルのインデックスの構築
universal-ctags V:1, I:11 3386 ソースコード定義のタグファイルのインデックスの構築

デバッグはプログラミング活動において重要です。プログラムのデバッグ法を知ることで、あなたも意味あるバグリポートを作成できるような良い Debian ユーザーになれます。


Debian 上の第一義的デバッガは、実行中のプログラムを検査できるようにする gdb(1) です。

gdb と関連プログラムを以下のようにインストールしましょう。

# apt-get install gdb gdb-doc build-essential devscripts

gdb のよいチュートリアルについては以下を参照下さい:

次は gdb(1) を"-g" を使ってデバッグ情報を付けてコンパイルされた "program" に使う簡単な例です。

$ gdb program
(gdb) b 1                # set break point at line 1
(gdb) run args           # run program with args
(gdb) next               # next line
...
(gdb) step               # step forward
...
(gdb) p parm             # print parm
...
(gdb) p parm=12          # set value to 12
...
(gdb) quit
[ヒント] ヒント

多くの gdb(1) コマンドは省略できます。タブ展開はシェル同様に機能します。

全てのインストールされたバイナリーはデフォルトでは Debian システム上ではストリップされているべきなので、ほとんどのデバグシンボルは普通のパッケージからは除かれています。gdb(1) を使って Debian パッケージをデバグするためには、*-dbgsym パッケージ(例えばcoreutils の場合は coreutils-dbgsym)をインストールする必要があります。ソースパッケージは、普通のバイナリーパッケージとともに *-dbgsym パッケージを自動生成し、そうしたデバグパッケージは別にして debian-debug アーカイブ中に置かれます。詳細は Debian Wiki の記事を参照下さい。

デバッグしようとしているパッケージに*-dbgsym パッケージが無い場合は、以下のようにしてリビルドした後でインストールする必要があります。

$ mkdir /path/new ; cd /path/new
$ sudo apt-get update
$ sudo apt-get dist-upgrade
$ sudo apt-get install fakeroot devscripts build-essential
$ apt-get source package_name
$ cd package_name*
$ sudo apt-get build-dep ./

必要に応じてバグを修正します。

例えば以下のように、既存パッケージを再コンパイルする時は "+debug1" を後ろに付けたり、リリース前のパッケージをコンパイルする時は "~pre1" を後ろに付けたりと、正規の Debian バージョンとかち合わないようにパッケージバージョンを増やします。

$ dch -i

以下のようにしてデバグシンボル付きでパッケージをコンパイルしてインストールします。

$ export DEB_BUILD_OPTIONS="nostrip noopt"
$ debuild
$ cd ..
$ sudo debi package_name*.changes

パッケージのビルドスクリプトを確認して、バイナリーのコンパイルに確実に "CFLAGS=-g -Wall" が使われているようにします。

プログラムがクラッシュするのに出会った場合に、バックトレース情報をバグレポートに切り貼りして報告するのは良い考えです。

バックトレースはgdb(1) によって以下のような段取りで得られます。

無限ループやキーボードが凍結した場合、Ctrl-\Ctrl-C を押すか “kill -ABRT PID” を実行することでプログラムを強制終了できます。(「プロセスの停止」を参照下さい)

[ヒント] ヒント

しばしば、一番上数行が "malloc()" か "g_malloc()" 中にあるバックトレースを見かけます。こういったことが起こる場合は、大体あまりあなたのバックトレースは役に立ちません。有用な情報を見つけるもっとも簡単な方法は環境変数 "$MALLOC_CHECK_" の値を 2と設定することです (malloc(3))。gdb を実行しながらこれを実行するには以下のようにします。

 $ MALLOC_CHECK_=2 gdb hello

Make はプログラムのグループを管理するためのユーティリティーです。make(1) を実行すると、make は"Makefile" というルールファイルを読み、ターゲットが最後に変更された後で変更された前提ファイルにターゲットが依存している場合やターゲットが存在しない場合にはターゲットを更新します。このような更新は同時並行的にされるかもしれません。

ルールファイルのシンタックスは以下の通りです。

target: [ prerequisites ... ]
 [TAB]  command1
 [TAB]  -command2 # ignore errors
 [TAB]  @command3 # suppress echoing

上記で、"[TAB]" は TAB コードです。各行は make による変数置換後シェルによって解釈されます。スクリプトを継続する行末には "\" を使います。シェルスクリプトの環境変数のための "$" を入力するためには "$$" を使います。

ターゲットや前提に関するインプリシット (暗黙) ルールは、例えば以下のように書けます。

%.o: %.c header.h

上記で、ターゲットは "%" という文字を (1つだけ) 含んでいます。"%" は実際のターゲットファイル名の空でないいかなる部分文字列ともマッチします。前提もまた同様にそれらの名前が実際のターゲットファイル名にどう関連するかを示すために "%" を用いることができます。



"make -p -f/dev/null" を実行して自動的な内部ルールを確認下さい。

Autotools は多くの Unix-like システムに移植可能なソースコードパッケージを作ることを援助するように設計された一連のプログラムツールです。

  • Autoconf は "configure.ac" から "configure" を生成します。

    • その後、"configure" は "Makefile.in" から "Makefile" を生成します。

  • Automake は "Makefile.am" から "Makefile.in" を生成します。

  • Libtool は共有ライブラリーをソースコードからコンパイルする時のソフトウェアー移植性問題を解決するためのシェルプログラムです。

ソフトウェアービルドシステムは進化してきています:

  • Make の上に構築された Autotools は 1990 年代より移植可能なビルドインフラのデファクトスタンダードです。これは非常に遅いです。

  • 2000 年に最初にリリースされた CMake は、スピードが大幅向上させたが、依然として本質的に遅い Make の上に構築されていました。(現在は、Ninja がバックエンドで使えます。)

  • 2012 年に最初にリリースされた Ninja は、さらなるビルド速度の向上のために Make の置き換えを意図し、その入力ファイルはハイレベルビルドシステムが生成するように設計されています。

  • 2013 年に最初にリリースされた Meson は、新しく人気ある Ninja をバックエンドに使うハイレベルビルドシステムです。

"The Meson Build system" や "The Ninja build system" にある文書を参照下さい。

基本的な対話式動的ウェッブページは以下のようにして作られます。

  • 質問 (クエリー) はブラウザーのユーザーに HTML フォームを使って提示されます。

  • フォームのエントリーを埋めたりクリックすることによって以下の符号化されたパラメーター付きの URL 文字列をブラウザーからウェッブサーバーに送信します。

    • "https://www.foo.dom/cgi-bin/program.pl?VAR1=VAL1&VAR2=VAL2&VAR3=VAL3"

    • "https://www.foo.dom/cgi-bin/program.py?VAR1=VAL1&VAR2=VAL2&VAR3=VAL3"

    • "https://www.foo.dom/program.php?VAR1=VAL1&VAR2=VAL2&VAR3=VAL3"

  • URL 中の "%nn" は16進数で nn の値の文字と置き換えられます。

  • 環境変通は以下のように設定されます: "QUERY_STRING="VAR1=VAL1 VAR2=VAL2 VAR3=VAL3"".

  • ウェッブサーバー上の CGI プログラム ("program.*" のいずれでも) が環境変数 "$QUERY_STRING" の下で実行されます。

  • CGI プログラムの STDOUT (標準出力) がウエブブラウザーに送られ対話式の動的なウェッブページとして表示されます。

セキュリティー上、CGI パラメーターを解釈する手作りの急ごしらえのプログラムは作らない方が賢明です。Perl や Python にはこのための確立したモジュールが存在します。PHP はこの様な機能が同梱されています。クライアントでのデーターのストレージの必要がある場合、HTTP クッキーが使われます。クライアントサイドのデーター処理が必要な場合、Javascript が良く使われます。

詳しくは、Common Gateway InterfaceThe Apache Software FoundationJavaScript を参照下さい。

https://www.google.com/search?hl=en&ie=UTF-8&q=CGI+tutorial を URL として直接ブラウザーのアドレスに入れ Google で"CGI tutorial" を検索するとグーグルサーバー上の CGI スクリプトが動いているのを観察する良い例です。

ソースコード変換するプログラムがあります。


Debian パッケージを作りたい場合には、次を読みましょう。

debmakedh-makedh-make-perl 等のパッケージングを補助するパッケージがあります。



[7] 現行のシステム下でこれらを動かすには少々微調整が必要かもしれません。