次のページ 前のページ 目次へ

7. マクロを作ってみる

さて、通信ソフトがうまく動き出したら、マクロを書いてみるのも おもしろいでしょう。

ここでは、kermit, xc, minicom のマクロの初歩を扱います。 さらに詳しいことはそれぞれの解説文書などを参照してください。

ここで紹介するマクロの例では例外の処理は行ないません。著者は 以下のマクロが動作することを確認していますが、場合によっては 不具合があるでしょう。

7.1 マクロの簡易デバッグ法

マクロを作っているとき問題になるのは、いちいちホストに繋がないと マクロの虫とりができない点です。

そこで、ホストに繋がずにある程度のデバッグをすることを考えます。 どうするかというと、自分でホストとターミナルの二役を演じるのです。 「馬鹿なことを」と思うかも知れませんが、これは効果的です。 毎回ホストに電話して接続する時間が省けますから、デバッグの 効率が上がります。しかもこうすれば無駄な電話代も不要になります。

では実際に挑戦してみましょう。まず X11 なら xterm などの ターミナルを二つ起動します。一つめが ttyp0、二つめが ttyp1 とします。 ここで、通信ソフトは ttyp0 で起動し、ttyp1 がホストの役を 務めます。コンソールなら tty1tty2 がそれぞれ ttyp0ttyp1 に相当します。

まず、ちょっと荒っぽいですが、/dev/ttyp1 に対して次のコマンドを 実行します。(コンソールなら /dev/tty2 です。)

chmod og+r /dev/ttyp1

この後、ttyp1 (ホスト側) で次のコマンドを実行します。

cat

これだけです。簡単ですね。次に、ttyp0 に移ります。ここでは、 通信ソフトのモデムのデバイスを指定する部分で、/dev/cua1 などの 代わりに /dev/ttyp1 (仮ホスト側) を指定します。その後、 ttyp0 側のシェルで通信ソフトを起動します。 例えば xc なら次のように起動します。

xc -l ttyp1

kermit の場合は、.kermrc の中の「set line」の行を

set line /dev/ttyp1

と設定し、このあと kermit を起動します。通信ソフトが無事 起動できたら、その時点ですでに二つのターミナルが結ばれています。 通信ソフトをターミナルモードにして、ttyp0 側で適当に文字を 打ち込んでみましょう。どうですか。打ち込んだ文字が ttyp1 (ホスト側) に表示されますね。ホスト側から文字を入力すると、 反対に ttyp0 に文字が出ます。これで「超簡易 BBS ホスト」の 完成です。:-)

さて、ttyp0 で起動した通信ソフトでマクロを実行してみます。また、 ttyp1 からは実際にホストが出力する文字を打ち込んでやります。 この ttyp1 からの入力に対して、マクロが期待どおり反応すれば 大成功です。うまく反応しなければ、一度 ttyp0 の通信ソフトを 終了し、エディタでマクロを書き直し、再度 ttyp0 で通信ソフトを 起動します。あとはこの手順を繰り返します。

マクロが完成したら、まず ttyp0 の通信ソフトを終了し、次に ttyp1 の「cat」を終了させます。「cat」が うまく終了しなければ、強引に kill してあげましょう。

最後に次のコマンドを実行して作業が終了です。

chmod og-r /dev/ttyp1

これでかなりの部分まで虫とりができるでしょう。 実際にホストにアクセスしてマクロがうまく動かなければ、 また同じように虫をとれば良いのです。

7.2 kermit でマクロ

~/.kermrc には各種設定を書きました。このファイルにはマクロも 記述できます。では命令を見ていきましょう。

set <項目など>....

各種の設定を行ないます。kermit のプロンプトで「set ?」と タイプすれば何を設定できるかが表示されます。

dial <電話番号>

電話をかけます。

input <数字> <文字列>

<数字> 秒の間 <文字列> が送られてこないかを監視します。 <文字列> が届いたら <数字> 秒が経過していなくても次の命令に 進みます。<数字> 秒たっても <文字列> が送られてこなければ、 次に進みます。

outut <文字列>

<文字列> をホストに送ります。文字列の中にある \13 は 改行文字をあらわします。

connect

オンラインモードに移行します。

define <マクロ名> マクロの本体 ....

マクロを定義します。

マクロ内で複数の命令を繋げるにはコンマ (,) を使います。

input 10 *,    output C NIF\13

マクロが複数の行にまたがる時には、行末にマイナス (-) を付加 します。

input 10 *,               output C NIF\13,-
,-
input 10 Connection-ID,   output SVC\13

マクロの中では空白行にも「,-」が必要です。

:標識

goto 命令の飛び先である標識は、最初にコロン (:) を付けて目印にします。

:come_here

if <条件> <命令>

<条件> が真ならば <命令> を実行します。

log session <ファイル>

通信の記録を <ファイル> に保存します。

quit, exit

ともに kermit を終了します。

kermit の命令 (予約語) は大文字か小文字かは区別されません。 読みやすいと思うように大文字と小文字を使い分ければ良いでしょう。 当然ですが、送受信する文字列では大文字と小文字は区別されます。

これだけの記述法を覚えれば大抵のことができます。

では、NIFTY-Serve のログインマクロを見てみましょう。 このマクロは ROAD-2 用です。~/.kermrc にこれを追加し、 kermit のプロンプトで「nifty」とタイプすれば、このマクロが 動きます。

define nifty set input timeout-action proceed ,-
    set input echo on ,-
    set input case observe ,-
    set input silence 0 ,-
    ,-
    dial ここに電話番号を書きます,-
    :begin,-
      output @P\13,-
      input 2 NAME?,-
      if failure goto begin,-
    ,-
    input 10 *,              output C NIF\13,-
    input 10 Connection-ID,  output SVC\13,-
    input 10 User-ID,        output ここには ID を書きます\13,-
    input 10 Password,       output ここはパスワードです\13,-
    ,-
    log session ~/kermit.log append,-
    connect

それそれの命令の使い方や意味は kermit のプロンプトで 「help input」のように入力すると表示されます。また、 プロンプトで「?」を入力すると、その時点で入力できる命令などが ぜんぶ表示されます。

kermit の命令は、他にもここに書ききれないくらいの量がありますから、 必要に応じて kermit のオンラインマニュアルや kermit のヘルプ機能を 使って調べましょう。

crontab に項目を加えれぱ kermit で自動運転することも可能です。 cron 機能の詳しい使い方は UNIX のシステム管理などの本を 参考にしてください。

kermit で自動運転を実現するマクロは、NIFTY-Serve・FUNIX の Linux 用 13 番ライブラリにあります。 54 番の「kermitでNIFTY autoaccess」がそれです。

kermit でマクロを書く際の問題点

起動すると「C-Kermit 5A(188), 23 Nov 92, POSIX」と表示される kermit や、これより古い kermit では、2 バイト文字は input 命令などでは 判定できません。つまり

input 10 Connection-ID

は正常に処理されますが、漢字などを使って

input 10 未読分

のようには記述できないのです。このように書いたとしても、 kermit はその文字列がホストから送られてきたか判断できません。

kermit のソースファイルを持っている人は、パッチを当てて コンパイルしなおせば、この問題が解決します。書き換えるのは ckuus4.c の以下の部分です。

int
doinput(timo,s) int timo; char *s; {
  int x, y, i, icn;
  char *xp, *xq = (char *)0;
  CHAR c;
  ^^^^

の下線部 "CHAR" を単に "char" に変更します。 reinput コマンドを 実現している関数・doreinput() (同じく ckuus4.c にあり) も同様に変更します。これで、input コマンドの文字列中で シフト JIS 漢字コードを使用することができるそうです。

また、この問題は「C-Kermit 5A(189), 30 June 93, POSIX」では 解決されているそうです。

この節の情報は川俣吉広さんに提供していただきました。感謝します。

この文書の筆者は kermit のソースファイルを持っていませんので、 このパッチの動作は確認していません。

7.3 xc でマクロ

xc のスクリプト (マクロ) 言語は Bourne シェルのスクリプト言語に 似せて作られています。しかし、まったく同じではありません。

kermit とは違い、xc では一つのファイルに一つのマクロだけを 記述できます。つまり、サブルーチンは別々のファイルに 書かなければなりません。

改行文字とセミコロン (;) は、ともにコマンド間の区切りに 使います。

#」よりうしろの部分は注釈になり、xc には無視されます。

以下はスクリプトで使える命令の一部です。

dial <電話番号>

電話をかけます。

redial

dial 命令で接続に失敗した時に、同じ番号にもう一度電話を かけ直します。

waitfor <文字列> <数字>

特定の文字列がホストから送られてくるのを待つために使います。 <数字> 秒の間 <文字列> を待ちます。<文字列> が 送られてきた時点、または <数字> 秒たった時点で次の命令に進みます。

transmit "<文字列>"

文字列をモデムに送ります。改行文字も送る時には ^M を使います。

pause <数字>

<数字> 秒のあいだ何もしません。

if <条件> ; then <命令>

<条件> が真ならば <命令> を実行します。

capture "on|off"

on で通信の内容をログに保存し、off で保存をやめます。

では NIFTY-Serve 用のマクロ例です。これも ROAD-2 用です。

このマクロは、ログイン後、新しくメールが届いていれば全部 ダウンロードします。そのあと、ダウンロードしたメールを ホストで削除し、ログアウトして回線を切ります。メールを ダウンロードしている時にだけ、その内容をログに保存します。 メールが届いていなければそのままログアウトして回線を切ります。

マクロの命令については、xc のマニュアルにさらに詳しいことが 書かれていますから参照してください。

# xc macro for NIFTY-Serve FENICS-ROAD 2

dial "ここにホストに接続するための電話番号を書きます"
while ! waitfor "CONNECT" 50
        do
                redial
        done

pause 1
transmit "@P^M"
while ! waitfor "HOST NAME?" 3
        do
                transmit "@P^M"
        done

waitfor "*" 5
transmit "C NIF^M"

waitfor "Enter Connection-ID  --->" 20
transmit "SVC^M"

waitfor "Enter User-ID  --->" 20
transmit "ここに ID を書きます^M"

waitfor "Enter Password --->" 20
transmit "ここにパスワードを書きます^M"

waitfor "LOG OUT"
if waitfor "未読分" 10; then
        waitfor "E. " 30
        transmit "MAIL^M"
        waitfor "電子メール" 10
        pause 1
        transmit "DOWN NEW PROT:NON^M"
        pause 1
        transmit "1^M"
        waitfor "ロード開始−" 300      # メールの表示を開始
        capture "on"
        waitfor "ロード終了−" 600      # メールの表示が終了
        capture "off"
        transmit "1^M"                  # ホストでメールを削除
endif

waitfor "^M>" 10

transmit "off^M"
waitfor "*" 30
transmit "off^M"
quit

# end of NIFTY macro

文字列の最初や最後にある「^M」は改行文字をあらわします。

このマクロを実行するには、例えば nifty.xc というファイル名で 保存して、xc のプロンプトで

s nifty.xc

とタイプします。

コマンドラインから次のようにタイプすると、xc はコマンドモードに ならずに直接指定したマクロを実行し、マクロが終了したら xc も 終了します。

xc -l デバイス名 -s スクリプトファイル名

このような項目を crontab に加えれば、指定した時間に自動的に マクロを走らせ、BBS にアクセスすることが可能になります。 (crontab をつかうには crond を動かしておかなければ なりません。) cron 機能の詳しい使い方は UNIX のシステム管理などの本を 参考にしてください。

xc でオートパイロットを実現するマクロ集は、NIFTY-Serve・FUNIX の 1 番ライブラリ・「Free software UNIX source」にあります。 353 番・「xcscript.tar.gz xc用 オートパイロット」がそれです。

7.4 minicom でマクロ

minicom のスクリプト言語は比較的命令数が少ないので、コツがつかめれば あとは楽にマクロを書けるでしょう。

サブルーチンは、kermit と同様、ひとつのファイルの中にいくつも 書くことができます。

では命令などを見てみましょう。

set <変数> <値>

<変数> (アルファベットの a 〜 z が一文字だけ) に <値> を 設定します。

expect { }

文字列を待つために使う命令です。この命令では一度に複数の文字列を 待つことが可能です。

expect {
        "紅茶"                goto cafe
        "ウイスキー"          goto bar
        "オレンジジュース"    goto VendingMachine
        timeout 10            goto end
}

{} の間には各行に

<文字列> <その文字列が来た時に実行する命令>

と書きます。命令の部分がなければ、expect を終了して } の次の行に制御を移します。また {} の中にある

timeout <数字> <命令> 

「<数字> 秒だけ列挙された文字列を待ち、その後 <命令> を 実行する」 という意味です。<命令> 部分に break と書くと expect を終了して } の次の行に制御を移します。<命令> 部分を省略すると マクロを 終了してしまいますので注意してください。

expect の中で timeout 命令を使わなければ 60 秒間だけ 文字列を待ち、 expect を終了します。

send "<文字列>"

<文字列> をモデムに送ります。ホストへの送信やモデムへの 命令に使えます。文字列の最後には minicom が自動的に改行文字を 付け加えてモデムに出力しますから、xc や kermit のように 明示する必要はありません。

sleep <数字>

<数字> 秒の間、なにもしません。

timeout <数字>

expect 命令の外で使うと、<数字> 秒たったらマクロの実行を 強制的に終了します。

標識:

gotogosub 命令で飛んでくる所を示します。最後に コロン (:) を書きます。

goto <標識>

<標識> に飛びます。

gosub <標識>

サブルーチン・<標識> に飛び、サブルーチン内に return 命令かあれば この次の行に戻ります。

return

サブルーチンを終了し、サブルーチンを呼び出した行の次の行に戻ります。

exit

マクロを終了します。

if <条件> <命令>

<条件> が真ならば <命令> を実行します。

マクロを実行するには、「Ctrl-A G」で開く窓の C の項目に マクロのファイル名を指定して、リターンキーを押します。

実際にマクロの例を見れば、それぞれの命令をどう使うかがわかると 思います。では、NIFTY-Serve・FENICS-ROAD2 用のマクロです。

# NIFTY-Serve 用超簡易スクリプト

# 画面に受信した文字を表示
verbose on

send    "ここに電話番号を書きます"
timeout 3600
set m 0
sleep 1
expect {
        "CONNECT"
}
sleep 1

loop:
        send    "@P"
        expect {
                "HOST NAME"
                timeout 2       goto loop
        }

        expect {
                "*"
        }
        send    "C NIF"
        expect {
                "Connection-ID  --->"
        }
        send    "SVC"

        expect {
                "User-ID  --->"
        }
        send    "ここに ID を書きます"

        expect {
                "Password --->"
        }
        send    "ここはパスワードです"

        #
        # −−メールが1通届いています(未読分1通)−−
        # があれば新しいメールが届いている
        #
        expect {
                "未読分"        set m 1
                "続き"
                "E. 終了"
                timeout 20
        }

        if m = 1 gosub mail
        send "off"

        expect {
                "HOST NAME"
        }
        expect {
                "*"
        }
        send    "off"
        sleep   2
        exit

#
# 電子メールをダウンロードするサブルーチン
#
mail:
        send    "mail"
        expect {
                "電子メール"
        }
        send    "down new prot:non"
        sleep   1

        # ダウンロード開始の許可
        send    "1"

        expect {
                "−ダウンロード終了−"
        }

        # ホスト上のメールを削除
        send    "1"

        sleep   1
        return

このマクロが実行することは、xc のマクロ例と同じです。ログイン後、 新しくメールが届いていれば全部ダウンロードします。そのあと、 ダウンロードしたメールをホストで削除し、ログアウトして回線を切ります。 メールが届いていなければそのままログアウトして回線を切ります。

この例では使っていない命令も少しあります。興味がある人は minicom に付属の Manual.scr ファイルを参照してください。

minicom の自動運転マクロは、5 章でも書いたように、 NIFTY-Serve・FUNIX の Linux 用ライブラリ(13 番) にある 「mc15bj.tgz minicom1.5b用パッチセット」の中に含まれています。


次のページ 前のページ 目次へ