[MHpopd に関するテクニカルノウハウ集] 1.機種依存性吸収のために用意されている識別子  machine.h の中や、make config で生成される config.h の中で は、各種の識別子が定義されています。これらの識別子は、OS の 違いを吸収するために設けられています。  自分の環境で、うまくコンパイルできない、どうもおかしな挙動 を示すというような場合には、これらの識別子を定義したり、定義 を取り消したりして調整して下さい。  各識別子の意味を以下に列挙します。 SYSV SVR4 BSD4 BSD43 各種 OS の元となるタイプを示します。SYSV, SVR4 は、 machine.h の後半で、OS 特有の定義のために参照されて いますが、BSD4, BSD43 は、参考として定義されているだ けなので、実際にはソース中で参照されていません。 OSTYPE 各 OS を表す識別子を定義しています。フロッピードライ ブのデフォルト設定を OS に応じて行なうために使用され ています。 CODEEUC 漢字コードとして、EUC (Extended Unix Code) 漢字を用 います。未定義の場合は Shift JIS になります。インス トール後の man ページや、漢字コード未指定時のデフォ ルト値に影響します。 入出力やファイル名に用いる漢字コードに関しては、コン パイル後に動的に変更可能です。 DEFKCODE OS 標準で用いる漢字コードを示す文字列を指定します。 定義された場合には、漢字コードに関する各種内部変数の 初期値として用いられます。 UTF8DOC ドキュメントの漢字コードとして UTF-8 を用います。未 定義の場合は CODEEUC の定義に従います。DEFKCODE の値 が「utf8-mac」もしくは「utf8-iconv」の場合は、その指 定による UNICODE マッピングを用います。 UTF8LANG 環境変数 LANG に「UTF」が含まれている場合に、OS 標準 で用いる漢字コード及びドキュメントの漢字コードとして 用いる文字列を指定します。LANG が「UTF」を含まない場 合には意味を持ちません。 NOMULTIKANJI 複数の漢字コードが共存する環境を考慮する必要がありま せん。 PATHNOCASE パス名に含まれる大文字小文字の区別が無視されます。 COMMNOCASE シェルコマンド名に含まれる大文字小文字の区別が無視さ れます。 ENVNOCASE 環境変数名に含まれる大文字小文字の区別が無視されます。 NOUID ユーザ ID やグループ ID がありません。 NODIRLOOP ディレクトリ構造が絶対にループし得ません。 NOSYMLINK シンボリックリンクが実装されていません。 BSPATHDELIM パス名区切り子がバックスラッシュ文字です。 USECRNL テキストの改行文字として CR-NL を用います。 CWDINPATH コマンドサーチパスに暗黙の了解としてカレントディレク トリが含まれています。 DOUBLESLASH // (または \\) で始まるパス名が、特殊な意味を持つパ ス名 (実例としては Cygwin に於ける共有フォルダ) とし て許容されている。 USEMANLANG man(1) の参照する検索パス名が、/usr/man/ja_JP.SJIS/ のように環境変数 LANG で示される文字列を含み、多国語 対応されています。 LANGWIDTH USEMANLANG が設定されている場合に、環境変数 LANG で 示される文字列の先頭から man(1) の検索パス名に用いる 文字数を指定します。一般的な NLS (Native Language System) では 2 文字または 5 文字になります。 SUPPORTSJIS cc(1) や man(1) が完全に Shift JIS を正しく扱えます。 2 byte 目に '\' が来るような漢字に対しても、この '\' を meta character として扱いません。 BSDINSTALL BSD ライクな install(1) が標準のコマンド検索パス上に 実装されており、-c (copy) や -s (strip) といったオプ ションが使えます。 BSDINSTCMD BSD ライクな install(1) のコマンド名が "install" 以 外の場合、そのコマンド名を定義します。BSDINSTALL を 定義していない場合は意味を持ちません。 TARUSESPACE tar(1) の t オプションの出力の際に、各行のファイルモ ード文字列 (Ex:rw-rw-rw-) の直後に必ず空白が入ってい る場合に定義します。BSD 系の OS では、空白がなく直後 に UID/GID が続く場合が多いようです。GNU tar では空 白が入ります。 ここで仮に定義を間違えたとしても、.fd2rc や /etc/fd2rc の記述で動的に変更することは可能です。 TARFROMPAX tar(1) の実装が pax(1) 由来のもので、t オプションの 出力が pax(1) で使われている書式になっている場合に定 義します。 ここで仮に定義を間違えたとしても、.fd2rc や /etc/fd2rc の記述で動的に変更することは可能です。 BUGGYMAKE make(1) が、1 秒以内に連続して作成されたファイルの依 存関係を正しく判断できません。 CPP7BIT cpp(1) が、漢字などの 8bit 文字を通すことができませ ん。 OLDARGINT cc(1) が、古典タイプの関数引数を int 型と見なします。 CCCOMMAND 標準として用いるべき c コンパイラのフルパスを定義し ます。一部の OS では、BSD 版 cc と SYSV 版 cc が混在 することがありますので、どちらかに統一しておきましょ う。未定義の場合には cc が用いられます。 EXTENDCCOPT cc(1) に与えるオプションを定義します。未定義の場合は "-O" が指定されます。"-O"(Optimize) に未対応の場合に は、ヌルを定義しておきましょう。 CCOUTOPT コンパイルのみでリンクをしない場合 (-c オプション指 定時) に、出力ファイル名を cc(1) に与えるオプション を、出力ファイル名の make(1) マクロ付で定義します。 デフォルトの "-o $@" 以外を必要とする時に指定して下 さい。 CCLNKOPT 実行ファイルのリンクをする場合 (-c オプション無指定 時) に、出力ファイル名を cc(1) に与えるオプションを、 出力ファイル名の make(1) マクロ付で定義します。デフ ォルトの "-o $@" 以外の時に指定して下さい。 USETERMINFO 端末データベースとして、termcap(5) library の代わり に terminfo(5) library を用います。 TERMCAPLIB termcap(5) ライブラリとしてリンクしなくてはならない ライブラリを定義します。未定義の場合は -ltermcap が 指定されます。 REGEXPLIB 正規表現ライブラリとしてリンクしなければならないライ ブラリがある場合定義します。 SOCKETLIB ソケットライブラリとしてリンクしなければならないライ ブラリがある場合定義します。 EXTENDLIB その他追加でリンクしなくてはならないライブラリがある 場合定義します。 NOFILEMACRO cc(1) がマクロ __FILE__ を評価できません。 NOFUNCMACRO cc(1) がマクロ __FUNCTION__ を評価できません。 NOLINEMACRO cc(1) がマクロ __LINE__ を評価できません。 FORCEDSTDC __STDC__ がプリデファインされていないけれども、プロ トタイプ宣言等に ANSI 標準 C の書式を要求する仕様に なっている場合に定義します。ANSI 準拠であることが保 証されている場合、無条件にこれを定義してしまっても特 に支障ありません。 STRICTSTDC モダンタイプのプロトタイプ宣言と、K&R の旧式の関数宣 言との混在を許さない、頑なな ANSI 標準 C 仕様になっ ている場合に定義します。関数の引数の型絡みでエラーが 大量に出るときに定義して下さい。 NOSTDC __STDC__ がプリデファインされているけれども、K&R の 旧式の C 言語仕様が期待されている場合に定義します。 NOCONST __STDC__ がプリデファインされているけれども、修飾子 const に対応していない場合に定義します。 NOVOID void 型を用いることができません。 NOUINT u_int 型を用いることができません。 NOLONGLONG long long 型を使うことができません。 HAVELONGLONG long long 型に対応しています。 NOUID_T uid_t, gid_t が で定義されていません。 USEPID_T fork(2) や wait(2) がプロセス ID として pid_t 型を用 います。 DECLSIGLIST 大域変数 sys_siglist[] が の中で宣言され ており、ソースリスト中で改めて宣言する必要がありませ ん。 NOSIGLIST 大域変数 sys_siglist[] が標準ライブラリの中に存在し ません。 DECLERRLIST 大域変数 sys_errlist[] が または の中で宣言されており、ソースリスト中で改めて宣言する 必要がありません。 PWNEEDERROR /lib/libPW.a をリンクする際に、大域変数 Error[] をソ ース中に用意しなくてはなりません。 NOERRNO 大域変数 errno が の中で宣言されていません。 NOFILEMODE ファイルモードを示す定数 S_IRUSR, S_IWUSR 等が の中で定義されていません。 NOUNISTDH が存在しません。 NOSTDLIBH が存在しません。 NOTZFILEH が存在しません。 USELEAPCNT 構造体 tzhead がメンバ tzh_leapcnt を持ちます。 USESELECTH 関数 select(2) を利用する際に必要な構造体 fd_set が、 の中で定義されています。 USESYSDIRH ディレクトリファイルのブロックを示す定数 DEV_BSIZE が、 の中で定義されています。 USETIMEH 構造体 tm が、 を参照す るだけでは定義されず、 が必要です。 USESTDARGH 可変引数を扱う va_list 型が の中で定義さ れています。 USEMKDEVH デバイス番号用マクロ (または関数) major()/minor() が の中で定義されています。 USEMKNODH デバイス番号用マクロ (または関数) major()/minor() が の中で定義されています。 USELOCKFH ファイルロック関数 lockf(2) のコマンドを示す各定数が の中で定義されています。 USETERMIO 端末インタフェースとして、termio 構造体を用います。 USETERMIOS 端末インタフェースとして、termios 構造体を用います。 USETERMIO, USETERMIOS 共に未定義の場合には sgttyb 構造体を用います。 HAVECLINE 構造体 termios がメンバ c_line を持ちます。 USEDEVPTMX 擬似端末用デバイスとして /dev/ptmx と /dev/pts/? を 用います。 USEDEVPTY 擬似端末用デバイスとして /dev/ptyXX と /dev/ttyXX を 用います。 USEDIRECT 構造体 dirent の代わりに direct を用います。 SYSVDIRENT 構造体 dirent がメンバ d_fileno を持たず d_ino を持 ちます。 NODNAMLEN 構造体 dirent がメンバ d_namlen を持ちません。 NODRECLEN 構造体 dirent がメンバ d_reclen を持ちません。代わり にメンバ d_fd を持ちます。 DNAMESIZE 構造体 dirent のメンバ d_name のサイズを示します。 HAVETIMEZONE 大域変数 timezone が GMT からのオフセット値を表しま す。 NOTMGMTOFF 構造体 tm がメンバ tm_gmtoff を持ちません。 NOSTBLKSIZE 構造体 stat がメンバ st_blksize を持ちません。 NOFLAGS 構造体 stat がメンバ st_flags を持つにも拘らず実際に は対応していません。 NOFTPH が存在しません。 USEINSYSTMH を使用するた めに必要です。 NOHADDRLIST 構造体 hostent がメンバ h_addr_list を持ちません。 (以下の 5 個は排他的です。同時に複数定義できません。) USESTATVFSH ファイルシステム情報を得るために、 で 宣言されている関数群を用います。 USESTATFSH ファイルシステム情報を得るために、 で 宣言されている関数群を用います。 USEVFSH ファイルシステム情報を得るために、 で宣言 されている関数群を用います。 USEMOUNTH ファイルシステム情報を得るために、 で宣 言されている関数群を用います。 USEFSDATA ファイルシステム情報を得るために、構造体 fs_data を 用いる関数群を用います。 USEFFSIZE 構造体 statfs のメンバの中で、ファイルシステムのブロ ックサイズとして f_fsize を参照します。未定義の場合 は f_bsize を参照します。 USESTATVFSH, USEFSDATA を定義した場合は意味を持ちま せん。 NOFBLOCKS 構造体 statfs がメンバ f_blocks を持ちません。 NOFBFREE 構造体 statfs がメンバ f_bfree を持ちません。 NOFFILES 構造体 statfs がメンバ f_files を持ちません。 USESTATVFS_T 構造体 statvfs の代わりに statvfs_t を用います。 STATFSARGS 関数 statfs(2) の用いる引数の数を定義します。 USESTATVFSH, USEFSDATA を定義した場合は意味を持ちま せん。 USEFSTATFS ファイルシステム情報取得関数として statfs(2) を用い られず、代わりに fstatfs(2) を用います。 (以下の 10 個は排他的です。同時に複数定義できません。) USEMNTENTH マウント情報を得るために、 で宣言されてい る関数群を用います。 USEMNTTABH マウント情報を得るために、 で宣言され ている関数群を用います。 USEGETFSSTAT マウント情報を得るために、関数 getfsstat(2) を用いま す。 USEGETVFSTAT マウント情報を得るために、関数 getvfsstat(2) を用い ます。 USEMNTCTL マウント情報を得るために、関数 mntctl(3) を用います。 USEMNTINFOR マウント情報を得るために、関数 getmntinfo_r(3) を用 います。 USEMNTINFO マウント情報を得るために、関数 getmntinfo(3) を用い ます。 USEGETMNT マウント情報を得るために、関数 getmnt(3) を用います。 USEGETFSENT マウント情報を得るために、関数 getfsent(3) を用いま す。 (この手法はマウント前の情報を取得してしまうのでお奨 めできません。窮余の策だと思って下さい。) USEREADMTAB マウント情報を得るために、/etc/mtab を直接読みます。 USEPROCMNT マウント情報ファイルとして /proc/mounts を使用します。 (この手法は mount(8) ではなくカーネルからの情報を取 得してしまうのでお奨めできません。窮余の策だと思って 下さい。) HAVEPROCMNT /etc/mtab が存在しない場合に、マウント情報ファイルと して /proc/mounts を使用します。 (以下の 2 個は排他的です。同時に複数定義できません。上記の 8 つの選択肢のうち USEMNTINFO 以外を定義した場合は意味を持ちま せん。) USEVFCNAME 構造体 vfsconf のメンバの中で、マウントタイプを表す 文字列として vfc_name を参照します。また、vfsconf 型 の取得に getvfsbytype() を用います。 USEFFSTYPE 構造体 statfs のメンバの中で、マウントタイプを表す文 字列として f_fstypename を参照します。 (以下の 3 個は排他的です。同時に複数定義できません。) USERE_COMP 正規表現検索のために関数 re_comp(3) を用います。 USEREGCOMP 正規表現検索のために関数 regcomp(3) を用います。 USEREGCMP 正規表現検索のために関数 regcmp(3) を用います。 USERAND48 乱数発生用関数として random(3) ではなく rand48(3) を 用います。 USESETENV 環境変数設定用関数として setenv(3) が使えます。 NOSELECT 低レベル入出力関数 select(2) を使うことができません。 DEFFDSETSIZE 低レベル入出力関数 select(2) を使うために、予め識別 子 FD_SETSIZE にオープンファイルの最大数を定義してお く必要があります。 SELECTRWONLY 低レベル入出力関数 select(2) が、読書き用に open さ れているファイル記述子に反応しません。 NOVSPRINTF 書式付出力関数 vsprintf(3) を使うことができません。 NOTERMVAR termcap(5) ライブラリ内に PC, ospeed, BC, UP といっ た大域変数が用意されていません。 USEUTIME タイムスタンプ設定関数として utimes(2) を用いられず、 代わりに utime(3) を用います。 USEGETWD カレントディレクトリ検査関数として、getcwd(3) を用い られず、代わりに getwd(3) を用います。 ULONGIOCTL 入出力制御関数 ioctl(2) の第 2 引数として、unsigned long 型を用います。 NOFTRUNCATE ファイルサイズ制御関数 ftruncate(2) を使うことができ ません。 USEFCNTLOCK ファイル制御関数 fcntl(2) を flock(2) の代わりに用い ます。 USELOCKF ファイルロック関数として flock(2) を使うことができず、 代わりに lockf(2) を用います。 NOFLOCK ファイルロック関数として flock(2) も lockf(2) も使う ことができません。 NOSYSLOG システムロガー関数 syslog(3) を使うことができません。 USETIMELOCAL 時間変換関数 timelocal(3) が localtime(3) の逆関数と して使えます。 USEMKTIME 時間変換関数 mktime(3) を timelocal(3) の代わりに用 います。 USESYSCONF 設定情報取得関数 sysconf(3) を用いて各種システム設定 値を取得します。 USELLSEEK ファイル制御関数 _llseek(2) を lseek(2) の代わりに用 います。32bit Linux 環境では 2^32 bytes を越える範囲 の offset 指定ができないので _llseek(2) が必要です。 USEUNAME ホスト名取得関数 uname(2) を gethostname(2) の代わり に用います。 NOKILLPG プロセスグループ管理関数 killpg(2) を使うことができ ません。 USEWAITPID ソフトウェアシグナル待ち関数 waitpid(2) を wait3(2) の代わりに用います。 USESIGACTION シグナル操作関数 sigaction(2) を signal(2) の代わり に用います。 USESIGPMASK シグナル操作関数 sigprocmask(2) を sigsetmask(2) の 代わりに用います。 NODTABLESIZE ディスクリプタサイズ取得関数 getdtablesize(2) を使う ことができません。 USERESOURCEH リソース情報を取得・設定する際に で 定義された関数群を用います。 USEULIMITH リソース情報を取得・設定する際に で定義さ れた関数群を用います。 USEGETRUSAGE プロセス時間情報を取得する際に getrusage(2) を用いま す。 USETIMES プロセス時間情報を取得する際に times(2) を用います。 GETPGRPVOID プロセスグループ取得関数 getpgrp(2) が引数を持ちませ ん。 USESETPGID プロセスグループ設定関数 setpgid(2) を setpgrp(2) の 代わりに用います。 NOSETPGRP プロセスグループ設定関数 setpgrp(2) を使うことができ ません。 USETCGETPGRP 制御端末用関数として ioctl(2) ではなく tcgetpgrp(3) 及び tcsetpgrp(3) を用います。 USESETVBUF バッファリング関数 setvbuf(3) を setlinebuf(3) の代 わりに用います。 SIGARGINT ソフトウェアシグナル関数 signal(3) の第 2 引数として、 int 型を返す関数へのポインタが用いられます。 SIGFNCINT ソフトウェアシグナル関数 signal(3) の第 2 引数として、 int 型の引数を持つ関数へのポインタが用いられます。 USESTRERROR エラー文字列関数 strerror(3) を sys_errlist[] の代わ りに用います。 GETTODARGS 時刻取得関数 gettimeofday(2) の用いる引数の数を指定 します。デフォルトは 2 です。 GETTODNULL 時刻取得関数 gettimeofday(2) の第 2 引数が NULL でな くてはなりません。 USESETSID セッション制御関数 setsid(2) を用いることができます。 USEMMAP ファイルマップ関数 mmap(2) を用いることができます。 NOGETPASS パスワード入力関数 getpass(3) を使うことができません。 USESOCKLEN ソケット関数 bind(2)/connect(2)/accept(2) の第 3 引 数として socklen_t 型を用います。 NOSENDFLAGS ソケット関数 send(2) の第 4 引数にフラグを使うことが できません。 USEINETATON アドレス操作関数 inet_aton(3) を inet_addr(3) の代わ りに用います。 USEINETPTON アドレス操作関数 inet_pton(3) を inet_addr(3) の代わ りに用います。 NOGETPWENT ユーザ ID 取得関数 getpwent(3) を使うことができませ ん。 NOGETGRENT グループ ID 取得関数 getgrent(3) を使うことができま せん。 USESETREUID ユーザ ID 設定関数 setreuid(2) を seteuid(2) の代わ りに用います。 USESETRESUID ユーザ ID 設定関数 setresuid(2) を seteuid(2) の代わ りに用います。 USESETREGID グループ ID 設定関数 setregid(2) を setegid(2) の代 わりに用います。 USESETRESGID グループ ID 設定関数 setresgid(2) を setegid(2) の代 わりに用います。 USEGETGROUPS グループアクセスリスト取得関数 getgroups(2) が利用可 能です。 SENSEPERSEC 1 秒間にキー入力を関知する回数を指定します。端末通信 速度の遅い場合に定義すると良いでしょう。デフォルトは 50 回です。 WAITKEYPAD ESC キーコードの入力を受けてから待つ時間です。端末通 信速度の遅い場合に定義すると良いでしょう。デフォルト は 360ms です。 WAITTERMINAL 端末が応答するエスケープシーケンスの各文字を待つ時間 です。端末の反応が鈍い場合に定義すると良いでしょう。 デフォルトでは WAITKEYPAD の値を継承します。 WAITKANJI マルチバイト文字の入力中に次のキーコード入力を待つ時 間です。端末通信速度の遅い場合に定義すると良いでしょ う。デフォルトは 120ms です。 HDDMOUNT フロッピードライブ機能をハードディスクドライブに対応 させます。PC-UNIX 以外でこの機能を用いたい場合は設定 して下さい。 2.MH コマンドの起動  MHpopd は inc(1) や send(1) などの各 MH コマンドを利用しま すが、これは設定により他のコマンドによって置換えることもでき ます。  元々は MH コマンド用に設計されているので、他のコマンドを利 用する際には条件を合わせる必要があります。以下に各コマンド起 動時の条件をまとめておきますので参考にして下さい。 ・inc(1) コマンド名: 設定項目 incproc で指定 引数: なし 起動ディレクトリ: ~/Mail/inbox カレントフォルダ: inbox ・rmm(1) コマンド名: 設定項目 rmmproc で指定 引数: 対象メイルのメッセージ番号を列挙 起動ディレクトリ: 対象フォルダディレクトリ カレントフォルダ: 対象フォルダ ・send(1) コマンド名: 設定項目 sendproc で指定 引数: 「draft」または「/<メッセージ番号>」 起動ディレクトリ: ~/Mail カレントフォルダ: 指定なし ・pick(1) コマンド名: メイル振分け制御ファイルで指定 引数: メイル振分け制御ファイルで指定 起動ディレクトリ: ~/Mail/inbox カレントフォルダ: inbox 3.inc(1) コマンドの実行  MHpopd を利用するには各 MH コマンド用の環境整備も重要な要 件となりますが、中でも inc(1) の実行に関しては幾つかの注意が 必要となるでしょう。  まず、inc(1) が外部のサーバからメイルを受信しているような 環境では、inc(1) の実行の際にパスワードの入力を要求されます ので、このままでは自動的に実行することができません。  この回答の一つはサーバ設定ファイルの設定項目 incpromt でパ スワードプロンプトを指定しておくことです。  この手法では、inc(1) に対して疑似端末を用いて自動的にパス ワード入力を行ないます。但し、ここで入力されるパスワード文字 列は passwordfile または my-password で指定されるパスワード に限られます。  もう一つの回答は、expect(1) のような疑似端末ソフトを用いて inc(1) にパスワードを渡す処理をスクリプト化してしまうことで す。  例えば expect(1) の場合は次のようなスクリプトが使えると思 います。 #!/usr/local/bin/expect -f spawn /usr/local/bin/inc expect "Password *:" send "PASSWORD\r" expect eof exit  エラー処理などもっと厳密な処理をさせたい場合は、expect(1) の各ドキュメントを参照して下さい。  また別の回答は、.netrc を使ってパスワードの入力を不要にす ることです。  ホームディレクトリ直下の .netrc に 「machine SERVER.DOMAIN passwd PASSWORD」 という一行を記述しておくことで、メイルサーバ「SERVER.DOMAIN」 にアクセスする際にパスワード文字列「PASSWORD」を使うようにな ります。  これは純粋に MH の機能ですので、詳細は MH の各ドキュメント を参照して下さい。ローカル環境で inc(1) の動作を十分確認した 上で MHpopd から起動させるようにするといいでしょう。  また、inc(1) しただけではメイルの振分けやフィルタリングは 行なってくれないという点にも注意が必要です。  この回答の一つはサーバ設定ファイルの設定項目 pickfile と pick(1) を用いて振分けの指示を設定しておくことです。  単純に MH コマンドの pick(1) と refile(1) と使って振分け できるような場合にはこの手法が一番簡単でしょう。  もう一つの回答はやはり inc(1) をスクリプト化することです。 inc(1) を実行した後に inbox の中から pick(1) で取捨選択を行 なってから refile(1) するようなスクリプトを作ります。  これは単純に手続きを羅列するだけですので、一般的なシェルス クリプトで十分だと思います。pick(1) や refile(1) も MH コマ ンドですので、詳細は MH の各ドキュメントを参照して下さい。  また別の回答は MH コマンドの slocal(1) です。これは、ユー ザのメイルボックスに届く前にメイルをフィルタリングするソフト で、ホームディレクトリの .maildelivary の記述に従ってメイル の振分けを行ないます。  これも純粋に MH の機能ですので、詳細は MH の各ドキュメント を参照して下さい。 4.実行権限  セキュリティホールに繋がる心配もありますので、MHpopd から 起動する各コマンドは可能ならばシェルスクリプトで記述しない方 が安全だと思います。  但し、MHpopd はユーザ認証後はそのユーザの権限で実行されま すので、それらのコマンドがルート権限で実行されることはあり得 ないはずです。  また、そもそも MHpopd をルートではなく一般ユーザの権限で起 動しておけば、より安全な運用が期待されます。  この場合、POP3 や SMTP 用に 1024 未満の「良く知られたポー ト」を用いることが禁止されていることが多いので、大きなポート 番号を指定して回避すると良いでしょう。  但し、当然のことながら一般ユーザ権限で起動すると、そのユー ザのメイル以外を送受信することはできませんので、必要なユーザ の数だけ別々のポートを割り当てて起動する必要があります。  inetd(8) から起動する場合でも一般ユーザ権限で起動すること はできますが、この場合も別々のポートが必要になるので、ユーザ 数分のサービス名を /etc/services に記述することになるでしょ う。