SMB HOWTO

David Wood, dwood@plugged.net.au

v1.0, 10 August 1996

中野武雄 nakano@apm.seikei.ac.jp

v1.0j1, 24 September 1996
これは SMB HOWTO です。この文書は Linux で Session Message Block (SMB) プロトコルを扱う方法について述べたものです。SMB プロトコルは、 NetBIOS プロトコル、LanManager プロトコルとも呼ばれています。

注意: この文書はかなり以前に書かれたものなので、 いまどきの Linux 環境にはあてはまらない箇所があります。 (JF Project)

1. はじめに

2. 他の情報

3. インストール

4. デーモンを起動する

5. /etc/smb.conf の設定

6. Linux のドライブを Windows マシンから共有する

7. Windows のドライブを Linux マシンで共有する

8. Linux マシンのプリンタを Windows マシンから利用する

9. Linux マシンから Windows のプリンタを使う

10. 著作権

11. 謝辞


1. はじめに

これは SMB HOWTO です。この文書は Linux で Session Message Block (SMB) プロトコルを扱う方法について述べたものです。SMB プロトコルは、 NetBIOS プロトコル、LanManager プロトコルとも呼ばれています。

この文書は David Wood ( dwood@plugged.net.au) が編集しています。追加情報や修正、訂正についてのメールは、このアドレス までお送りくだされば次回のリリースに反映させます。

SMB プロトコルは Microsoft Windows 3.11、NT、95 でディスクやプリン タを共有するために用いられます。Andrew Tridgell によって書かれた Samba ツールセットを用いれば、Linux などの Unix マシンでも Windows のホスト とディスクやプリンタを共有できます。

Samba を用いてできることは以下の 4 つです。

  1. Linux ホストのドライブを Windows ホストで共有する。
  2. Windows ホストのドライブを Linux ホストで共有する。
  3. Linux ホストのプリンタを Windows ホストで共有する。
  4. Windows ホストのプリンタを Linux ホストで共有する。

この文書は以上のケースをすべてカバーしています。

免責: この文書に記した方法やスクリプトは、著者を含めた何人かのグループ の中ではうまく働いています。しかし環境が異なると、うまくいかない可能 性もあります。そのような場合は著者にメールで知らせていただければ、この 文書の発展に役立ちます。ただし著者は何の保証もしません。何を期待して たんですか?著者はただ助言をしているにすぎないのです...

2. 他の情報

この HOWTO 文書では、Linux マシンで SMB のファイルサービス、プリントサー ビスを利用するための設定法について、基礎から説明しています。Samba は複 雑で高機能なシステムですので、この文書では Samba に関する情報すべてを 記述することはできませんし、またそのつもりもありません。

より多くの情報を知りたい人は以下の文献をみてください。

===訳注===

国内の Samba 公式ミラーサーバとしては、 ftp://ring.aist.go.jp/archives/net/samba/ ftp://ring.asahi-net.or.jp/archives/net/samba/ などがあります。この翻訳を書いている '96 9 月現在では、1.9.16p2 が最新 のリリースバージョンのようです。

日本語の解説文書としては以下のようなものがあります。ただしこれらは 1.9.15p8 をベースに書いてありますので、1.9.16p2 では細かな部分が変わっ ています。特に nmbd の扱いがだいぶ変わっているので、man nmbd しておくことを強くお勧めします。

ニュースでは、英語ですが comp.protocols.smb で Samba に関する議論 がされています。

==訳注終==

3. インストール

最新の Samba のソースは ftp://nimbus.anu.edu.au/pub/tridge/samba/ から得られます。

Redhat を使っている人なら Samba を rpm 形式でインストールすることもで きます。他の配布パッケージにも Samba のバイナリインストールが可能なも のがあります。

===訳注===

日本語のファイル名を有効にしたい場合は、コンパイルの際に Makefile での設定が必要になります。上記のようなバイナリパッケージで日本語ファイ ル名が有効になっているかどうか、ご存知の方がいらっしゃいましたら訳者ま でお知らせいただければ幸いです。

==訳注終==

Samba を利用するためには以下の 2 つのデーモンプログラムが必要です。 これらは通常 /usr/sbin にインストールされ、システム起動時にブー トアップスクリプトで起動されるか、または inetd から実行されます。 スクリプトの例は、 デーモンを起動する の節にあげてあります。

smbd

SMB デーモンです。

nmbd

クライアントへ NetBIOS による名前解決機能を提供します。

以下の Samba プログラムは通常 /usr/bin にインストールされます (この場所は選択可能です)。

smbclient

UNIX ホストのための SMB クライアントプログラム

smbprint

SMB ホストのプリンタを利用するためのスクリプト

smbprint.sysv

SVR4 用の smbprint

smbstatus

ローカルホストへの SMB 接続をリストするプログラム

smbrun

SMB ホストで必要なアプリケーションを実行させるための補助 的な役割をするスクリプトプログラム

さらに、この HOWTO 文書には print という名前のスクリプトが入って います。これは smbprint スクリプトのフロントエンドで、印刷をより 簡単にするものです。

Samba のパッケージをインストールするのは簡単です。上記の URL からソー スを手に入れ、配布アーカイブの中の README ファイルを見てください。また docs/INSTALL.txt にはインストール手順の詳細な解説が書いてあります。

インストールに続いて、デーモンを /usr/sbin へ、プログラムを /usr/bin へ、man ページを /usr/local/man に置きましょ う。

Samba のパッケージを作るとき、smbd のコンフィギュレーションファイ ルである smb.conf の置き場所を Makefile の中で指定します。好 きなところに置くことができますが、通常は /etc/smb.conf が良い でしょう。ログファイルとロックディレクトリについては以下のように設定し ておくことをお勧めします。


   log file=/var/log/samba-log.%m
   lock directory = /var/lock/samba

===訳注===

Samba パッケージのデフォルトの設定では、デーモンおよびプログラムは /usr/local/samba/bin へ、また smb.conf などは /usr/local/samba/lib に置かれます。

また log filelock directory の設定は Makefile でもできますが、smb.conf に書いておく方がドキュメン ト性が高くなるので良いと思います。

==訳注終==

smb.conf をインストールします。Samba のプログラムをコンパイルした ディレクトリに行き、さらに example/simple ディレクトリに移動 して README を読んで下さい。続いてディレクトリにある smb.conf/etc にコピーします。ここでちょっと注意。 Redhat などの配布パッケージから Samba をインストールした場合には、既に /etcsmb.conf があるかもしれません。この場合は、この ファイルから設定をはじめると良いでしょう。

% smb.conf/etc に置きたくない場合には、好きな場所にお いてシンボリックリンクを /etc に作りましょう。


    ln -s /path/to/smb.conf /etc/smb.conf

4. デーモンを起動する

SMB のデーモンは /usr/sbin/smbd/usr/sbin/nmbd の 2 つです。

Samba のデーモンを実行するやりかたは 2 つあります。inetd から起動 する方法と、スタンドアローンのプロセスとして起動する方法です。専用のファ イルサーバとして用いる場合は inetd から起動する方が良いでしょう。 そうすれば何らかの理由でこれらのデーモンプロセスが死んでも、次のリクエ ストによって再実行されます。SMB サーバサービスを時々しか利用しない(シ ステム管理のときだけとか)ならば、/etc/rc.d/init.d スクリプト から実行すると良いでしょう。必要なときだけ手動で実行しても良いでしょう。

===訳注===

スピードの点からは、デーモンプロセスの方がわずかながら有利という意見も あります。また、訳者のホストで 3 ヶ月ほど Samba を使用した間、落ちたこ とはありませんでした。

==訳注終==

inetd からデーモンを起動する場合は、以下の行を inetd の設定 ファイル /etc/inetd.conf に加えます。


# SAMBA NetBIOS services (for PC file and print sharing)
netbios-ssn stream tcp nowait root /usr/sbin/smbd smbd
netbios-ns dgram udp wait root /usr/sbin/nmbd nmbd

書き換えたら、以下のコマンドを実行して inetd をリスタートします。


    kill -HUP <pid of inetd>

<pid of inetd> には inetd のプロセス ID を入れてく ださい。ps コマンドで確認するか、"cat /var/run/inetd.pid" などでもわかります。

デーモンをシステムの起動スクリプトから実行する場合は、以下の内容を /etc/rc.d/init.d/smb として作製し、スクリプト中のコメントで指 定されているファイルへのシンボリックリンクを作ってください。


#!/bin/sh

#
# /etc/rc.d/init.d/smb - starts and stops SMB services.
#
# The following files should be synbolic links to this file:
# symlinks: /etc/rc.d/rc1.d/K35smb  (Kills SMB services on shutdown)
#           /etc/rc.d/rc3.d/S91smb  (Starts SMB services in multiuser mode)
#           /etc/rc.d/rc6.d/K35smb  (Kills SMB services on reboot)
#

# Source function library.
. /etc/rc.d/init.d/functions

# Source networking configuration.
. /etc/sysconfig/network

# Check that networking is up.
[ ${NETWORKING} = "no" ] && exit 0

# See how we were called.
case "$1" in
  start)
    echo -n "Starting SMB services: "
    daemon smbd -D      
    daemon nmbd -D 
    echo
    touch /var/lock/subsys/smb
    ;;
  stop)
    echo -n "Shutting down SMB services: "
    killproc smbd
    killproc nmbd
    rm -f /var/lock/subsys/smb
    echo ""
    ;;
  *)
    echo "Usage: smb {start|stop}"
    exit 1
esac

===訳注===

Slackware の場合は、/etc/rc.d/rc.local に以下のような行を追加 しておけば良いでしょう。


if [ -f /usr/sbin/nmbd ]; then
  echo "SAMBA servers"
  /usr/sbin/smbd -D
  /usr/sbin/nmbd -D
fi

==訳注終==

5. /etc/smb.conf の設定

Linux でも他の Unix 上でも、Samba の設定は /etc/smb.conf とい うファイルにまとめて記されています。どのシステムリソースを公開するか、 またそれらにどのような制限を科すかなどは、このファイルで設定します。

この節に続く 2 節では Linux のドライブやプリンタを Windows マシンから 共有する方法について述べます。この節で示す smb.conf は、できるだ け簡単にこれらの機能を実現するように書いたものですので、あくまで導入的 なものと考えてください。

この smb.conf の詳細が解らなくても心配する必要はありません。重要 な概念については後の節であらためて説明します。

smb.conf 中の各々のセクションは、セクションヘッダ ([global][homes][printers] 等)から始まります。

global セクションでは全てのセクションに共通な変数を指定します。

homes セクションを指定すると、リモートユーザは自分のホームディレ クトリへアクセスできるようになります。つまり Samba ホストである Linux マシンにアカウントを持っている人が Windows マシンで接続すると、彼ら個 人個人のホームディレクトリを利用できるようになります。このサービスを利 用するには Linux マシンにアカウントを持っていなければなりません。

ここに示した smb.conf の例では、リモートユーザが自分のホームディ レクトリにアクセスし、/tmp ディレクトリに書きこみできるように しています。Windows ユーザにこれらのリソースを見せるには、Linux のホス トがローカルなネットワーク上になければなりません。Windows のファイルマ ネージャやエクスプローラを用いれば、これらのドライブをネットワークドラ イブとして接続できます。

この文書の以下の節では、他のリソースを共有させるための smb.conf ファイルの書式についても述べています。参考にしてください。


; /etc/smb.conf
;
; Make sure and restart the server after making changes to this file, ex:
; /etc/rc.d/init.d/smb stop
; /etc/rc.d/init.d/smb start
[global]
; Uncomment this if you want a guest account
; guest account = nobody
   log file = /var/log/samba-log.%m
   lock directory = /var/lock/samba
   share modes = yes

[homes]
   comment = Home Directories
   browseable = no
   read only = no
   create mode = 0750

[tmp]
   comment = Temporary file space
   path = /tmp
   read only = no
   public = yes

6. Linux のドライブを Windows マシンから共有する

上にあげた簡単な smb.conf からも解るように、Linux のドライブを Windows のユーザが共有するのは簡単です。しかし Samba のシステムでは非 常に多くの項目をカスタマイズできます。以下にいくつか例を示します。

あるディレクトリを制限なしに公開するには、先程の節で挙げたsmb.conftmp セクションをまねして、いくつかのパラメータを設定 します。


[public]
   comment = Public Stuff
   path = /home/public
   public = yes
   writable = yes
   printable = yes

このディレクトリの制限をちょっと変えて、読み出しはだれでも可能とし、書 き込みを staff グループのユーザに限るには、以下のようにします。


[public]
   comment = Public Stuff
   path = /home/public
   public = yes
   writable = yes
   printable = no
   write list = @staff

ドライブ共有に関する他の手法については、Samba 付属の文書や man ページ を見てください。

===訳注===

Win 95 で作成したファイルで大文字小文字の区別をしたり、日本語を正しく 表示させるためには、global セクションに以下のエントリを追加してお くと良いようです。


   mangle case = no
   case sensitive = no
   default case = upper
   preserve case = yes
   short preserve case = yes

日本語を利用するには、コンパイル時に Makefile

        -DKANJI=\"euc\"
などと指定する必要があります。また 1.9.16p2 からは、smb.conf
   coding system = <コード系>

のように指定することが可能になり、また CAP と同時に使うための "cap" という漢字コード系が追加されました。

なおコード系を unicode にしておくと、日本語 Windows 95 から Samba のド ライブを接続した場合、新規フォルダの作成ができなくなるという不具合があ るそうです。

==訳注終==

7. Windows のドライブを Linux マシンで共有する

Samba の配布パッケージには、Unix マシンのための SMB クライアントプログ ラムが含まれています。このプログラムは ftp のようなコマンド指向のイン ターフェースを持っています。このプログラムを使えば、Windows のサーバと、 Linux のクライアントとのあいだで、ファイルのやり取りができます。

===訳注===

2.0 以上などの最近のカーネルでは smbfs というファイルシステムがあ り、NT などのネットワークドライブを直接マウントできるようです。詳細は、 カーネルディレクトリ下 Documentation/filesystems/smbfs.txt を 見て下さい。

==訳注終==

あるホストでどんな共有サービスが利用出来るかを調べるためには、以下の ようなコマンドを実行します。


    /usr/sbin/smbclient -L host

host には調べたいホストの名前を入れます。このコマンドを実行すると、 サービス名のリストが得られます。サービス名とは、あなたがこのホストで利 用できるドライブやプリンタの名前です。もし SMB サーバに何らかのセキュ リティ制限がかかっているとパスワードを聞かれますので、guest アカ ウントのパスワードか、そのホストでのあなたの個人アカウントのパスワード を入れて下さい。

実行例を示します。


    smbclient -L zimmerman

実行結果は以下のようになるでしょう。


Server time is Sat Aug 10 15:58:27 1996
Timezone is UTC+10.0
Password: 
Domain=[WORKGROUP] OS=[Windows NT 3.51] Server=[NT LAN Manager 3.51]

Server=[ZIMMERMAN] User=[] Workgroup=[WORKGROUP] Domain=[]

        Sharename      Type      Comment
        ---------      ----      -------
        ADMIN$         Disk      Remote Admin
        public         Disk      Public 
        C$             Disk      Default share
        IPC$           IPC       Remote IPC
        OReilly        Printer   OReilly
        print$         Disk      Printer Drivers


This machine has a browse list:

        Server               Comment
        ---------            -------
        HOPPER               Samba 1.9.15p8
        KERNIGAN             Samba 1.9.15p8
        LOVELACE             Samba 1.9.15p8
        RITCHIE              Samba 1.9.15p8
        ZIMMERMAN            

ブラウズリスト(browse list)は、ネットワーク上の他の SMB サーバの共有 リソースを示したものです。

クライアントとして利用するには以下のように実行します。


    /usr/sbin/smbclient service <password>

service にはホスト名と共有名を指定します。ホスト zimmerman において public という名前で公開されているディレクトリを利用する ためには、service\\zimmerman\public となります。シェルのプロンプトからこのコマンドを利用する場合は、バック スラッシュをエスケープしないといけませんから、結局次のように入力する必 要があります。


    /usr/sbin/smbclient \\\\zimmerman\\public mypasswd

mypassword には、あなたの パスワードをそのまま書いてください。

===訳注===

以下は松本@京大人間環境さんによるもうちょっと簡単な入力方法です。


    /usr/sbin/smbclient '\\zimmerman\public' mypasswd

==訳注終==

以下のような smbclient のプロンプトが出てきます。


Server time is Sat Aug 10 15:58:44 1996
Timezone is UTC+10.0
Domain=[WORKGROUP] OS=[Windows NT 3.51] Server=[NT LAN Manager 3.51]
smb: \> 

h と打てば、smbclient のヘルプが得られます。


smb: \> h
ls             dir            lcd            cd             pwd            
get            mget           put            mput           rename         
more           mask           del            rm             mkdir          
md             rmdir          rd             prompt         recurse        
translate      lowercase      print          printmode      queue          
cancel         stat           quit           q              exit           
newer          archive        tar            blocksize      tarmode        
setmode        help           ?              !              
smb: \> 

ftp を使える人なら、man ページを見るまでもなく smbclient が使える ようになるでしょう。

8. Linux マシンのプリンタを Windows マシンから利用する

Linux のプリンタを Windows から利用するには、Linux 上でプリンタがちゃ んと動作するように正しく設定されている必要があります。Linux でのプリン トができていれば SMB での共有は簡単です。

ローカルプリンタの設定については Printing HOWTO をみてください。

筆者自身は Windows NT に接続されているプリンタを使っているので、この節 に書いてあることは絶対に正しいとは限りません。助言程度に受けとめておい てください。もし具体的な使用経験を持っている方がいらっしゃいましたら、 どうぞ dwood@plugged.net.au まで知らせてください。そうすればこの章の内容を完成できます。

smb.conf にプリンタの設定を加えます。


[global]
   printing = bsd
   printcap name = /etc/printcap
   load printers = yes
   log file = /var/log/samba-log.%m
   lock directory = /var/lock/samba

[printers]
   comment = All Printers
   security = server
   path = /var/spool/lpd/lp
   browseable = no
   printable = yes
   public = yes
   writable = no
   create mode = 0700

[ljet]
   security = server
   path = /var/spool/lpd/lp
   printer name = lp
   writable = yes
   public = yes
   printable = yes
   print command = lpr -r -h -P %p %s

プリンタのセクションにおける path には、/etc/printcap で 設定したスプールディレクトリと同じディレクトリを指定してください。

注意: Samba を使って Unix マシンのプリンタを Windows NT マシンから共有 させる際には問題点がいくつかあります。そのうちの一つは、NT からは 共有プリンタが正しく見えないというものです。この問題を解決するには Samba 配布パッケージの docs/WinNT.txt ファイルを参照して下さ い。パスワードに関する問題もあります。こちらの方は同ファイルを見ても、 いらいらするだけで解決にはなりません...

===訳注===

訳者は Linux につながっている Epson MJ-700V2C を Samba で公開し Windows 95 から使っていますので、その設定内容を以下に記します。ただし、 公開先はプライベートアドレスのついたネットワークなので、基本的にセキュ リティのことは考えていません。

まず smb.conf です。


[global]
        lock directory = /var/locks/samba

        workgroup = WORKGROUP
        browseable = yes
        allow hosts = 192.168.111.

        printing = bsd
        load printers = no
        printcap name = /etc/printcap

        password level = 8
        create mode = 0750

        mangle case = no
        case sensitive = no
        default case = upper
        preserve case = yes
        short preserve case = yes

[lp]
        comment = MJ-700V2C
        printer name  = lp
        path = /var/tmp

        printable = yes
        writable = yes
        create mode = 0700

/etc/printcap です。


lp:\
        :lp=/dev/lp1:\
        :sd=/var/spool/lpd/lp:\
        :lf=/var/spool/lpd/lp/errs:\
        :if=/var/spool/lpd/lp/incat:\
        :mx#0:\
        :sh:\
        :sf:

インプットフィルタの /var/spool/lpd/lp/incat です。


#!/bin/sh
/bin/cat
exit 0

Windows 95 からは、ネットワークドライブを選択した後 MJ-700V2C のドラ イバを手で選んでインストールする必要があります。

==訳注終==

9. Linux マシンから Windows のプリンタを使う

Windows マシン上のプリンタを共有するためには以下の作業が必要です。

  1. /etc/printcap に正しいエントリが必要で、それらはローカ ルなディレクトリ構造に準じたものである必要があります(スプールディレク トリの設定など)。
  2. /usr/bin/smbprint スクリプトが必要です。これは Samba の ソースパッケージに付いてきますが、Samba のバイナリ配布パッケージには付 いてこないかもしれません。後でオリジナルを少々修正したものを載せます。
  3. ASCII ファイルを Postscript 形式に変換する必要がある場合には、 nenscript などの Postscript コンバータを準備する必要があります。 nenscript は通常は /usr/bin にインストールされています。
  4. Samba を利用した印刷を容易にしてくれるようなフロントエンドが欲し ければ、以下に記した簡単な perl スクリプトを試して下さい。ASCII、 Postscript、created Postscript が扱えるようになっています。

以下に記すのは、Windows NT プリンタに接続された HP 5MP プリンタを利用 するための /etc/printcap へのエントリです。それぞれの内容は以 下の通りです。

cm

コメント

lp

出力に使うデバイス名

sd

このプリンタのためのスプールディレクトリ

af

アカウントファイル

mx

最大のファイルサイズ(0 にすれば無制限になります)

if

入力に用いられるフィルタ(またはスクリプト)

さらに情報が必要なら、Printing HOWTO や printcap の man ページを 見て下さい。


# /etc/printcap
#
# //zimmerman/oreilly via smbprint
#
lp:\
        :cm=HP 5MP Postscript OReilly on zimmerman:\
        :lp=/dev/lp1:\
        :sd=/var/spool/lpd/lp:\
        :af=/var/spool/lpd/lp/acct:\
        :mx#0:\
        :if=/usr/bin/smbprint:

スプールディレクトリとアカウントファイルが存在しており、書き込み可能で あることを確認しておいて下さい。また printcapif 行に、以 下に記す smbprint スクリプトへの正しいパスが設定されていること、 lp 行に /dev ディレクトリにある正しいデバイスが設定され ていることも確認して下さい。

次は smbprint です。これは通常 /usr/bin に置かれており、 Samba を作った Andrew Tridgell 本人によって書かれたものです(筆者の知 らない Samba の共作者が他にいらっしゃったらすみません)。これは Samba のソースパッケージに入っていますが、バイナリ配布の場合には無いかも知れ ませんので、以下に私が少々手を加えたものを示しておきます。

以下に記したスクリプトを注意深く見て下さい。これはオリジナルを修正した もので、多少使いやすくなっていると思います。


#!/bin/sh -x

# This script is an input filter for printcap printing on a unix machine. It
# uses the smbclient program to print the file to the specified smb-based 
# server and service.
# For example you could have a printcap entry like this
#
# smb:lp=/dev/null:sd=/usr/spool/smb:sh:if=/usr/local/samba/smbprint
#
# which would create a unix printer called "smb" that will print via this 
# script. You will need to create the spool directory /usr/spool/smb with
# appropriate permissions and ownerships for your system.

# Set these to the server and service you wish to print to 
# In this example I have a WfWg PC called "lapland" that has a printer 
# exported called "printer" with no password.

#
# Script further altered by hamiltom@ecnz.co.nz (Michael Hamilton)
# so that the server, service, and password can be read from 
# a /usr/var/spool/lpd/PRINTNAME/.config file.
#
# In order for this to work the /etc/printcap entry must include an 
# accounting file (af=...):
#
#   cdcolour:\
#       :cm=CD IBM Colorjet on 6th:\
#       :sd=/var/spool/lpd/cdcolour:\
#       :af=/var/spool/lpd/cdcolour/acct:\
#       :if=/usr/local/etc/smbprint:\
#       :mx=0:\
#       :lp=/dev/null:
#
# The /usr/var/spool/lpd/PRINTNAME/.config file should contain:
#   server=PC_SERVER
#   service=PR_SHARENAME
#   password="password"
#
# E.g.
#   server=PAULS_PC
#   service=CJET_371
#   password=""

#
# Debugging log file, change to /dev/null if you like.
#
logfile=/tmp/smb-print.log
# logfile=/dev/null

#
# The last parameter to the filter is the accounting file name.
#
spool_dir=/var/spool/lpd/lp
config_file=$spool_dir/.config

# Should read the following variables set in the config file:
#   server
#   service
#   password
#   user
eval `cat $config_file`

#
# Some debugging help, change the >> to > if you want to same space.
#
echo "server $server, service $service" >> $logfile

(
# NOTE You may wish to add the line `echo translate' if you want automatic
# CR/LF translation when printing.
        echo translate
        echo "print -"
        cat
) | /usr/bin/smbclient "\\\\$server\\$service" $password -U $user -N -P >> $log
file

ほとんどの Linux パッケージには、ASCII 文書を Postscript にする nenscript コマンドが含まれています。以下の perl スクリプトは、 smbprint を使って印刷する際に、よりシンプルなインターフェースを提 供するものです。


Usage: print [-a|c|p] <filename>
       -a prints <filename> as ASCII
       -c prints <filename> formatted as source code
       -p prints <filename> as Postscript
        If no switch is given, print attempts to
        guess the file type and print appropriately.

smbprint を使って ASCII ファイルを印刷すると、長い行は改行されて しまいます。このスクリプトでは、可能な限り単語の途中ではなく、空白で改 行するようにしています。

ソースコードのフォーマットには nenscript を用いています。ASCII ファ イルは 2 段組みに整形され、ヘッダ(日付、ファイル名など)がつきます。 このスクリプトを雛形にして、他の整形方法を用いることもできるでしょう。

Postscript の文書はすでに整形されているものとみなして、そのまま通すよ うになっています。


#!/usr/bin/perl

# Script:   print
# Authors:  Brad Marshall, David Wood
#           Plugged In Communications
# Date:     960808
#
# Script to print to oreilly which is currently on zimmerman
# Purpose:  Takes files of various types as arguments and 
# processes them appropriately for piping to a Samba print script.
#
# Currently supported file types:
# 
# ASCII      - ensures that lines longer than $line_length characters wrap on
#              whitespace.
# Postscript - Takes no action.
# Code       - Formats in Postscript (using nenscript) to display
#              properly (landscape, font, etc).
#

# Set the maximum allowable length for each line of ASCII text.
$line_length = 76;

# Set the path and name of the Samba print script
$print_prog = "/usr/bin/smbprint";

# Set the path and name to nenscript (the ASCII-->Postscript converter)
$nenscript = "/usr/bin/nenscript";

unless ( -f $print_prog ) {
        die "Can't find $print_prog!";
}
unless ( -f $nenscript ) {
        die "Can't find $nenscript!";
}

&ParseCmdLine(@ARGV);

# DBG
print "filetype is $filetype\n";

if ($filetype eq "ASCII") {
        &wrap($line_length);
} elsif ($filetype eq "code") {
        &codeformat;
} elsif ($filetype eq "ps") {
        &createarray;
} else {
        print "Sorry..no known file type.\n";
        exit 0;
}
# Pipe the array to smbprint
open(PRINTER, "|$print_prog") || die "Can't open $print_prog: $!\n";
foreach $line (@newlines) {
        print PRINTER $line;
}
# Send an extra linefeed in case a file has an incomplete last line.
print PRINTER "\n";
close(PRINTER);
print "Completed\n";
exit 0;

# --------------------------------------------------- #
#        Everything below here is a subroutine        #
# --------------------------------------------------- #

sub ParseCmdLine {
        # Parses the command line, finding out what file type the file is

        # Gets $arg and $file to be the arguments (if the exists)
        # and the filename
        if ($#_ < 0) {
                &usage;
        }
        # DBG
#       foreach $element (@_) {
#               print "*$element* \n";
#       }

        $arg = shift(@_);
        if ($arg =~ /\-./) {
                $cmd = $arg;
# DBG
#       print "\$cmd found.\n";

                $file = shift(@_);
        } else {
                $file = $arg;
        }
        
        # Defining the file type
        unless ($cmd) {
                # We have no arguments

                if ($file =~ /\.ps$/) {
                        $filetype = "ps";
                } elsif ($file =~ /\.java$|\.c$|\.h$|\.pl$|\.sh$|\.csh$|\.m4$|\.inc$|\.html$|\.htm$/) {
                        $filetype = "code";
                } else {
                        $filetype = "ASCII";
                }

                # Process $file for what type is it and return $filetype 
        } else {
                # We have what type it is in $arg
                if ($cmd =~ /^-p$/) {
                        $filetype = "ps";
                } elsif ($cmd =~ /^-c$/) {
                        $filetype = "code";
                } elsif ($cmd =~ /^-a$/) {
                        $filetype = "ASCII"
                }
        }
}

sub usage {
        print "
Usage: print [-a|c|p] <filename>
       -a prints <filename> as ASCII
       -c prints <filename> formatted as source code
       -p prints <filename> as Postscript
        If no switch is given, print attempts to
        guess the file type and print appropriately.\n
";
        exit(0);
}

sub wrap {
        # Create an array of file lines, where each line is < the 
        # number of characters specified, and wrapped only on whitespace

        # Get the number of characters to limit the line to.
        $limit = pop(@_);

        # DBG
        #print "Entering subroutine wrap\n";
        #print "The line length limit is $limit\n";

        # Read in the file, parse and put into an array.
        open(FILE, "<$file") || die "Can't open $file: $!\n";
        while(<FILE>) {
                $line = $_;
                
                # DBG
                #print "The line is:\n$line\n";

                # Wrap the line if it is over the limit.
                while ( length($line) > $limit ) {
                        
                        # DBG
                        #print "Wrapping...";

                        # Get the first $limit +1 characters.
                        $part = substr($line,0,$limit +1);

                        # DBG
                        #print "The partial line is:\n$part\n";

                        # Check to see if the last character is a space.
                        $last_char = substr($part,-1, 1);
                        if ( " " eq $last_char ) {
                            # If it is, print the rest.

                            # DBG
                            #print "The last character was a space\n";

                            substr($line,0,$limit + 1) = "";
                            substr($part,-1,1) = "";
                            push(@newlines,"$part\n");
                        } else {
                             # If it is not, find the last space in the 
                             # sub-line and print up to there.

                            # DBG
                            #print "The last character was not a space\n";

                             # Remove the character past $limit
                             substr($part,-1,1) = "";
                             # Reverse the line to make it easy to find
                             # the last space.
                             $revpart = reverse($part);
                             $index = index($revpart," ");
                             if ( $index > 0 ) {
                               substr($line,0,$limit-$index) = "";
                               push(@newlines,substr($part,0,$limit-$index) 
                                   . "\n");
                             } else {
                               # There was no space in the line, so
                               # print it up to $limit.
                               substr($line,0,$limit) = "";
                               push(@newlines,substr($part,0,$limit) 
                                   . "\n");
                             }
                        }
                }
                push(@newlines,$line);
        }
        close(FILE);
}

sub codeformat {
        # Call subroutine wrap then filter through nenscript
        &wrap($line_length);
        
        # Pipe the results through nenscript to create a Postscript
        # file that adheres to some decent format for printing
        # source code (landscape, Courier font, line numbers).
        # Print this to a temporary file first.
        $tmpfile = "/tmp/nenscript$$";
        open(FILE, "|$nenscript -2G -i$file -N -p$tmpfile -r") || 
                die "Can't open nenscript: $!\n";
        foreach $line (@newlines) {
                print FILE $line;
        }
        close(FILE);
        
        # Read the temporary file back into an array so it can be
        # passed to the Samba print script.
        @newlines = ("");
        open(FILE, "<$tmpfile") || die "Can't open $file: $!\n";
        while(<FILE>) {
                push(@newlines,$_);
        }
        close(FILE);
        system("rm $tmpfile");
}

sub createarray {
        # Create the array for postscript
        open(FILE, "<$file") || die "Can't open $file: $!\n";
        while(<FILE>) {
                push(@newlines,$_);
        }
        close(FILE);
}

===訳注===

nenscrpt は日本語を通しませんが、JE には psconv という日本語 に対応したコマンドが入っています。他にも a2psps2asciips2txttoPS など様々なものがネットワークから入手可能です。

なお、訳者はこの章のスクリプトをテストできる環境がありませんので、原文 にあったスクリプトをそのまま載せておきました。改造して日本語を通すこと に成功した方は、ご連絡下されば幸いです。

==訳注終==

10. 著作権

この HOWTO 文書の著作権は 1996 年以降 David Wood にあるものとします。 この節の宣言を含むすべての文書が変更されない限りにおいて、あらゆる形式 へのこの文書の複製、およびその再配布を許可します。

11. 謝辞

もしメールで御意見をいただければ、次の版のリリースの際に、この節でお名 前を挙げて感謝したいと思います。

===訳注===

日本語への翻訳に当たっては、

岡本一幸さん ikko-@pacific.rim.or.jp
桑村 潤さん juk@rccm.co.jp
松本庄司さん shom@i.h.kyoto-u.ac.jp
箕浦逸史さん minoura@biol.s.u-tokyo.ac.jp
に誤訳の指摘や有益なコメントをいただきました。

==訳注終==