Path: maczuka-news!localhost!kaz From: kaz@maczuka.hitachi.ibaraki.jp (Ito Kazumitsu) Newsgroups: fj.sources Subject: The Poor Man's Internet Utility Package Followup-To: fj.sources.d Date: 31 Aug 1996 15:37:06 GMT Organization: K. & M. Ito, Hitachi, Ibaraki, JAPAN Lines: 1106 Message-ID: NNTP-Posting-Host: localhost.maczuka.hitachi.ibaraki.jp 伊藤@日立市です. 私が自家用に用いている The Poor Man's Internet Utility Package Version 1.00 (Aug 31 1996) なるものを投稿します. このパッケージは, 個人でどこかのプロバイダと契約して, 端末型 ダイアルアップ IP 接続でインターネットを利用する場合に, 通信料金を なるべく節約し, 今では時代遅れとなった 14.4 kbps のモデムを 使っても, テレホーダイを使わなくても, 快適にインターネットが 利用できるようにするための, 姑息な道具を集めたものです. 要するに, ダイアルしてプロバイダに接続し 必要な処理をして 終わったら回線を切る という一連の処理をバッチ処理で行なうことによって, 回線がつながった ままダラダラと流れる時間を極力排除しようというものです. 含まれているのは (1) ppp の起動・終了を制御するスクリプト (2) ニュースの定期または不定期の購読 (3) お決まりの WWW の内容取得 です. POP に関しても同じようなことができると思われますが, 当方では 電子メールの利用に POP を使っていませんので, このパッケージには 含まれていません. また, あくまでも個人用のものですので, 組織において複数のユーザに 共用されるマシンでの利用はおすすめできません. 30 キロバイトほどですので, shar したものを投稿します. ------ cut here ------ # This is a shell archive. Save it in a file, remove anything before # this line, and then unpack it by entering "sh file". Note, it may # create directories; files and directories will be owned by you and # have default permissions. # # This archive contains: # # Makefile # README # batch-fetch-recursive.in # config.sed # control-ppp.in # get-news-batch.in # get-news-gen.in # get-news.in # rnews-batch.in # echo x - Makefile sed 's/^X//' >Makefile << 'END-of-Makefile' X################################################################ X# Makefile for Poor man's Internet Utilities X# Aug 31, 1996 by Ito Kazumitsu X################################################################ X XGENCOMMAND = sed -f config.sed XRM = rm XCHMOD = chmod X XSCRIPTS = batch-fetch-recursive control-ppp get-news get-news-batch get-news-gen rnews-batch X Xall: X @for i in $(SCRIPTS); do \ X echo "make $$i..."; \ X $(GENCOMMAND) $$i.in > $$i; \ X $(CHMOD) +x $$i; \ X done X Xclean: X @for i in $(SCRIPTS) *~ ; do \ X echo "rm $$i..."; \ X $(RM) $$i; \ X done END-of-Makefile echo x - README sed 's/^X//' >README << 'END-of-README' X The Poor Man's Internet Utility Package X X Version 1.00 (Aug 31 1996) X X 伊藤一光 X kaz@maczuka.hitachi.ibaraki.jp X1. 概要 X Xこのパッケージは, 個人でどこかのプロバイダと契約して, 端末型 Xダイアルアップ IP 接続でインターネットを利用する場合に, 通信料金を Xなるべく節約し, 今では時代遅れとなった 14.4 kbps のモデムを X使っても, テレホーダイを使わなくても, 快適にインターネットが X利用できるようにするための, 姑息な道具を集めたものです. X X要するに, X X ダイアルしてプロバイダに接続し X 必要な処理をして X 終わったら回線を切る X Xという一連の処理をバッチ処理で行なうことによって, 回線がつながった Xままダラダラと流れる時間を極力排除しようというものです. X X含まれているのは X X (1) ppp の起動・終了を制御するスクリプト X (2) ニュースの定期または不定期の購読 X (3) お決まりの WWW の内容取得 X Xです. X XPOP に関しても同じようなことができると思われますが, 当方では X電子メールの利用に POP を使っていませんので, このパッケージには X含まれていません. X Xまた, あくまでも個人用のものですので, 組織において複数のユーザに X共用されるマシンでの利用はおすすめできません. X X X2. 動作環境 X X当方の動作環境は FreeBSD 2.1.0-RELEASE です. X XPerl 5 および url_get (http://uts.cc.utexas.edu/~zippy/url_get.html) を X必要とします. X Xローカルなニュースサーバとして INN 1.4unoff4 を動かしており, X取得したニュースの記事は rnews でローカルのニュースサーバに X渡します. X X X3. インストール X X適当なディレクトリの下にこのパッケージを展開し, config.sed ファイルを X編集して必要事項を設定したあと make とタイプすれば, X Xbatch-fetch-recursive, Xcontrol-ppp Xget-news Xget-news-batch Xget-news-gen Xrnews-batch X Xという 6個のファイルができます. これらを適当なディレクトリの X下にコピーしてお使いください. X Xconfig.sed の書き方は config.sed の中に説明されています. X X X4. 実行 X X4.1 プロバイダとの接続および回線切断 X X control-ppp start X control-ppp check X control-ppp kill X control-ppp auto X X start X iijppp を起動する. resolv.conf を接続先プロバイダ対応の X ものに切替える. X X check X iijppp が動いているかどうかを調べ, 次の文字列を標準出力に出力する. X X off : iijppp は動いていない. X on : iijppp は動いていてプロバイダとの接続ができている. X dead : iijppp は動いているが, 接続はできていない. X fail : iijppp 起動後ダイアルに失敗して iijppp は終了した. X X kill X iijppp のプロセスを強制的に終了させる. これによって回線も X 切断される. X X auto X check の結果が on になるまで start の再試行を行なう. X X 環境変数 X control-ppp では次の環境変数を参照する. X X PPP_target X X 接続したいプロバイダに応じて, /etc/ppp/ppp.conf の中に X 書かれた destination label name を指定する. X この環境変数が設定されていない場合は, インストール時に X %DEFAULT_ PPP_TARGET で指定したものが仮定される. X X PPP_retries X X control-ppp auto のときに, 再試行を何回まで行なうかを X 指定する. この環境変数が設定されていない場合は, X インストール時に %DEFAULT_ PPP_RETRIES で指定した値が X 仮定される. X X4.2 ニュースの購読 X X get-news [-s サーバ ] [-n 最大記事数 ] [-d ] list ニュースグループ X get-news [-s サーバ ] article X X list X 指定されたニュースグループの記事のヘッダ情報をニュースサーバから X 受けとり, Subject と Message-ID を取り出して, 標準出力に書き出す. X 出力の内容は, get-news article を実行するためのスクリプトであり, X X get-news article <<'EOF' X # Subject 1 X X # Subject 2 X X : X # Subject n X X EOF X X となっている. これをファイルに出力し, エディタで編集して必要と X する記事だけを選んでから実行すれば記事が入手できる. X X オプション X X -s サーバ X ニュースサーバの名前を指定する. 省略するとインストール時に X %NEWS_SERVER で指定したものが仮定される. X X -n 最大記事数 X 最大何個の記事を入手するかを指定する. 省略すると X インストール時に %MAXARTICLECOUNT で指定した値が仮定される. X X -d X デバッグのための詳細メッセージを出力する. X X article X 標準入力から Message-ID の羅列を入力し, その記事を入手して X 標準出力に書き出す. 標準入力のうち, 行頭が < で始まっていない X 行は無視される. X X オプション X X -s サーバ X ニュースサーバの名前を指定する. 省略するとインストール時に X %NEWS_SERVER で指定したものが仮定される. X X X4.3 ニュースの定期購読 X X get-news-batch X X 定期購読するニュースグループの記事をニュースサーバから入手し, X ローカルに動いているニュースサーバにフィードする. X X 定期購読するニュースグループの指定は, インストール時に X %NEWSGROUPSFILE で指定した名前の後にハイフンでニュースサーバ名を X 連結した名前のファイルで行なう. そのファイルの中には, 行頭から X ニュースグループ名を書き, 1個以上の空白で区切って, 入手済の X 最終記事番号を書いたものを羅列する. このファイルの中の記事番号は, X 初期作成時には, ニュースサーバに保存されている記事を調べて, X 適当な記事番号を書いておけばよい. 以後 get-news-batch の処理中に X 自動的に更新される. X X X4.4 WWW の内容取得 X X batch-fetch-recursive -u 情報源URL -d 出力先ディレクトリ \ X [ -r ルートディレクトリ ] [ -n 探索の深さ ] [ -i ] X X 指定された URL の内容を入手してローカルの出力先ディレクトリの X 下のファイルに書き出す. 書き出されたファイルのうち, ファイル名の X 末尾が .html または .htm のもの中で参照されているファイルも X 入手して同じようにローカルのファイルに書く. X X こうして, ファイルの参照関係が完結するか, または指定された X 深さに達するまでファイルの入手を繰り返す. X X オプション X X -u 情報源URL X 情報源の URL を指定する. URL の末尾の / は省略する. X X -d 出力先ディレクトリ X X -r ルートディレクトリ X 入手したファイルから参照されたファイルの名前が / で始まって X いた場合に, そのファイルを格納すべきローカルのディレクトリを X 指定する. 省略すると -d で指定した出力先ディレクトリを X 仮定する. X X -n 探索の深さ X 1回めの探索は, -d で指定されたディレクトリの直下にある X ファイルのうちファイル名の末尾が .html または .htm の X ものを調べ, その中で参照されているファイルを入手する. X X r 回めの探索では, (r-1) 回めの探索で得られたファイルの X うち, ファイル名の末尾が .html または .htm のものを調べ, X その中で参照されているファイルのうち, 未入手のものを入手する. X X このような探索の r の最大値を -n 探索の深さ で指定する. X 省略時は 1 を仮定する. X X -i X イメージファイルを入手しないことを指定する. 省略時は X イメージファイルも入手する. なお, イメージファイルと X みなされるのは, ファイル名の末尾が .jpg, .jpeg, .gif の X ものである. X X 注意事項 X X (1) 出力先ディレクトリに, ファイル名の末尾が .html または .htm X であるファイルが最初存在していない場合, "" X という内容の .boot というファイルを作って, それを探索の X 起点とする. X X このような安直な仮定が好ましくない場合は, あらかじめ X url_get -b 情報源URL/ > 出力先ディレクトリ/index.html X を実行しておくとよい. X X (2) 入手した HTML ファイルの中で参照されているファイルの X 名称の先頭の文字が / で始まっている場合, それは X -r または -d で指定したディレクトリの下に格納される. X ローカルに格納されたファイルを参照しようとしても, X / で始まるファイル名のファイルは, 一般には正しく X 参照できない. END-of-README echo x - batch-fetch-recursive.in sed 's/^X//' >batch-fetch-recursive.in << 'END-of-batch-fetch-recursive.in' X#!/usr/local/bin/perl X X$depth=1; X$get_image=1; X X$i=0; X$a=$ARGV[$i]; Xwhile($a) { X if($a eq "-u") { X $i++; X $urlbase=$ARGV[$i]; X } X elsif($a eq "-d") { X $i++; X $targetdir=$ARGV[$i]; X } X elsif($a eq "-r") { X $i++; X $rootdir=$ARGV[$i]; X } X elsif($a eq "-n") { X $i++; X $depth=$ARGV[$i]; X } X elsif($a eq "-i") { X $get_image=0; X } X $i++; X $a=$ARGV[$i]; X} X Xif(!$urlbase || !$targetdir) { X die "Usage: batch-fetch-recursive [-i] -u URL -d DIR [-r ROOTDIR][-n DEPTH]\n"; X} X Xif(!($depth > 0)) { X $depth=1; X} X Xif(!$rootdir) { X $rootdir=$targetdir; X} X X$urlroot=$urlbase; X$urlroot=~s|^([A-z]+://[^/]+)/*.*$|$1|; X Xchdir $targetdir; X Xopendir(dir1,".") || die "directory $targetdir cannot be opened\n"; Xwhile($a=readdir(dir1)) { X if((-f $a) && ($a=~/.*\.htm[l]*$/)) { X push(@filelist,($a)); X $url{$a}="$urlbase/$a"; X } X} Xclosedir(dir1); X Xif(!$filelist[0]) { X open(boot,"> .boot") || die ".boot cannot be opened\n"; X print boot "\n"; X close(boot); X $filelist[0]=".boot"; X $url{$filelist[0]}="$urlbase/$filelist[0]"; X} X X# How many url_get processes run at the same time. X$maxbgcnt=5; X Xwhile($depth) { X @newfilelist=(); X %newurl=(); X foreach $source (@filelist) { X open(source, $source) || die "cannot open $source\n"; X @l=(); X while() { X chop; X push(@l,&extract_html_ref($_)); X } X close(source); X X $cmd=""; X X @l1=sort(@l); X $i0=""; X $bgcnt=0; X $sourceurl=$url{$source}; X foreach $i (@l1) { X if($i eq $i0) { next; } X $i0=$i; X $i=~s/\n//; X if($get_image || !($i=~/(\.jpe*g$)|(\.gif$)/i)) { X if($i=~/^\//) { X $u="$urlroot$i"; X $i="$rootdir$i"; X } X else { X $a=$sourceurl; X $a=~s|/[^/]*$||; X $u="$a/$i"; X $a="/".$source; X $a=~s|/[^/]*$||; X $a=~s/^\///; X $i=($a ? "$a/$i" : $i); X } X $i=~s|/$|/index.html|; X if(! -s $i) { X ($d)=($i=~/^(.*)\/[^\/]+$/); X if($d && (! -d $d)) { X system("mkdirhier $d"); X } X $cmd.="url_get -b $u > $i & \n"; X $bgcnt++; X if($bgcnt>=$maxbgcnt) { X $cmd.="wait\n"; X $bgcnt=0; X } X if($i=~/.*\.htm[l]*$/) { X push(@newfilelist,($i)); X $newurl{$i}=$u; X } X } X } X } X if($cmd) { X $cmd.="wait\n" if $bgcnt; X print $cmd; X print "## now receiving\n"; X system($cmd); X print "## now out of communication\n"; X } X } X if($newfilelist[0]) { X $depth--; X @filelist=@newfilelist; X %url=%newurl; X } X else { X $depth=0; X } X} X Xsub extract_html_ref { X ($_)=@_; X local(@l); X local($s); X @l=(); X if(!$_=~/(href=)|(src=)|(background=)/i) { return @l; } X X $s=$_; $s=~tr/A-Z/a-z/; X X while($_) { X if($s=~/^href=/) { X ($ref,$_)=($_=~/^.....([^>]*)>(.*)$/); X ($s)=($s=~/^.....[^>]*>(.*)$/); X push(@l, &check_ref($ref)); X } X elsif($s=~/^src=/) { X ($ref,$_)=($_=~/^....([^>]*)>(.*)$/); X ($s)=($s=~/^....[^>]*>(.*)$/); X push(@l,&check_ref($ref)); X } X elsif($s=~/^background=/) { X ($ref,$_)=($_=~/^...........([^>]*)>(.*)$/); X ($s)=($s=~/^...........[^>]*>(.*)$/); X push(@l,&check_ref($ref)); X } X else{ X $_=~s/^.//; X $s=~s/^.//; X } X } X return @l; X} X Xsub check_ref { X local($ref)=@_; X if($ref=~/^"/) { X ($ref)=($ref=~/^\"([^\"]+)\".*/); X } X if($ref=~/^[A-z]+:/) { X return (); X } X $ref=~s/^\.\///; X# $ref=~s/^\///; X $ref=~s/\#.+$//; X return ($ref); X} END-of-batch-fetch-recursive.in echo x - config.sed sed 's/^X//' >config.sed << 'END-of-config.sed' X# The Poor Man's Internet Utility Package Configuration X# X# ------------------------------------------------------------------- X# iijppp X# IIJ-PPP コマンドのフルパス名を指定します. X# Xs|%PPP_CMD|/usr/sbin/ppp|g X# X# ------------------------------------------------------------------- X# Ping X# 1個のパケットを送出する ping コマンドの書き方を指定します. X# Xs|%PING|/sbin/ping -c 1|g X# X# ------------------------------------------------------------------- X# The name of resolv.conf X# 複数のプロバイダと契約しているとき, 接続先に応じて X# /etc/resolv.conf の内容を書き換える必要がありますが, X# /etc のパーミッションの問題がありますので, 私は次のように X# しています. X# X# ln -s /somehere/somefile /etc/resolv.conf X# X# 一方 /etc/ppp/ppp.conf の destination label name それぞれに X# 応じて, たとえば /somewhere/somefile.aaa というファイルを X# 作っておき X# X# rm /somewhere/somefile X# ln -s /somewhere/somefile.aaa /somewhere/somefile X# X# とすれば, 接続先 aaa に応じた /etc/resolv.conf を使える X# ことになります. X# X# もとより個人用の道具なので, /etc/resolv.conf を直接操作 X# してもよいのですが, なんとなく気持ちが悪いので, 一般利用者の X# 権限で操作可能な resolv.conf を別に設けています. X# Xs|%RESOLVCONF|/somewhere/somefile|g X# X# ------------------------------------------------------------------- X# The destination label name in /etc/ppp/ppp.conf X# ppp を制御する control-ppp において, 接続先は, X# 環境変数 PPP_target で指定しますが, この値が設定されて X# いない場合のデフォルト値を指定します. X# Xs/%DEFAULT_PPP_TARGET/foo/g X# X# ------------------------------------------------------------------- X# How many times to retry invoking ppp X# ppp によるプロバイダとの接続が失敗したとき, 何回まで再試行するかは X# 環境変数 PPP_retries で指定しますが, この値が設定されていない場合の X# デフォルト値を指定します. X# Xs/%DEFAULT_PPP_RETRIES/40/g X# X# ------------------------------------------------------------------- X# The name of the news server X# ニュースサーバの名前を指定します. 実行時に -s オプションで X# 指定できますが, そのデフォルト値を指定します. X# Xs/%NEWS_SERVER/news.server.somewhere/g X# X# ------------------------------------------------------------------- X# How many articles per newsgroup to get at the maximum X# ニュースの記事を取得するとき, ひとつのニュースグループあたり X# 最大何個の記事を取得するかを指定します. X# Xs/%MAXARTICLECOUNT/100/g X# X# ------------------------------------------------------------------- X# Maximum size of an article X# 定期購読するニュースグループにおいて, ひとつの記事の最大 X# サイズを指定します. これより大きい記事は取得しません. X# X# この指定は実行時に変更できるオプションはなく, インストール時 X# 指定だけが有効です. また, 不定期購読には適用されません. X# Xs/%MAXARTICLESIZE/8000/g X# X# ------------------------------------------------------------------- X# Character string to be inserted at the top of the path field X# 取得した記事を rnews でローカルのニュースサーバに渡すとき, X# Path フィールドに付加する文字列を指定します. X# X# ダイアルアップ IP 接続のほかに UUCP 接続を利用している場合, X# 入手した記事が UUCP の相手サイトにフィードされるのを防止する X# ための指定です. このパッケージは, 通信料を節約するための X# ものですから, 入手した記事が UUCP で別のところに転送されては X# 無意味です. それならば, はじめから UUCP でニュースを購読した X# ほうがよいわけです. X# Xs/%NEWS_INSERT_PATH/bar!/g X# X# ------------------------------------------------------------------- X# Where the list of newsgroups is kept X# 定期購読するニュースグループの名前を列挙したファイルの X# 名前を指定します. 実際には, ここで指定した名前のあとに X# ハイフンでニュースサーバの名前を連結した名前が使われます. X# Xs|%NEWSGROUPSFILE|/list/of/newsgroups|g X# X# ------------------------------------------------------------------- X# end of config.sed END-of-config.sed echo x - control-ppp.in sed 's/^X//' >control-ppp.in << 'END-of-control-ppp.in' X#! /bin/sh XLogfile=/tmp/control-ppp.log XPidfile=/tmp/control-ppp.pid XPPP_cmd="%PPP_CMD" X X# The file to which /etc/resolv.conf is symbolically linked. X# This file, when connecting a provider, is symlinked to X# $resolvconf.$PPP_target Xresolvconf=%RESOLVCONF X X# Environment variable PPP_target indicates which provider to use Xcase "$PPP_target" in X "") PPP_target="%DEFAULT_PPP_TARGET" X ;; Xesac Xcase "$PPP_retries" in X "") Retries=%DEFAULT_PPP_RETRIES X ;; X *) Retries=$PPP_retries X ;; Xesac X Xcase "$1" in X "start") # switch resolv.conf X /bin/rm $resolvconf X /bin/ln -s $resolvconf.$PPP_target $resolvconf X $PPP_cmd $PPP_target > $Logfile 2>& 1 & X echo $! > $Pidfile X ;; X "check") if [ -r $Pidfile ]; X then X PPP_PID=`cat $Pidfile` X else X PPP_PID="off" X fi X case "$PPP_PID" in X "off") PPP_STAT="off" X ;; X *) a=`grep 'dial.*failed' $Logfile` X case $a in X "") a=`grep '^PPP' $Logfile` X case "$a" in X "") PPP_STAT="dead" X ;; X *) PPP_STAT="on" X ;; X esac X ;; X *) PPP_STAT="failed" X rm $Logfile $Pidfile X ;; X esac X esac X echo $PPP_STAT X ;; X "kill") if [ -r $Pidfile ]; X then X kill `cat $Pidfile` X rm $Logfile $Pidfile X fi X ;; X "auto") cp /dev/null $Logfile X retries=$Retries X while [ $retries -gt 0 ] X do X $0 start X sleep 5 X a=`$0 check` X echo "Status=$a" X case "$a" in X "on") echo "Login successful" X exit 0 X ;; X "dead") sleep 30 X a=`$0 check` X case "$a" in X "on") echo "Login successful" X exit 0 X ;; X "dead") echo "Not working, waiting for a while" X sleep 20 X a=`$0 check` X ;; X esac X case "$a" in X "on") echo "Login successful" X exit 0 X ;; X "dead") echo "Login failed" X $0 kill X sleep 1 X ;; X esac X ;; X "failed") echo "Dial failed" X $0 kill X sleep 1 X ;; X esac X retries=`expr $retries - 1` X echo "I will retry $retries times" X done X exit 1 X ;; Xesac END-of-control-ppp.in echo x - get-news-batch.in sed 's/^X//' >get-news-batch.in << 'END-of-get-news-batch.in' X#! /bin/sh Xtmpf=/tmp/tf$$ Xnewsserver=%NEWS_SERVER X Xcontrol-ppp auto X X%PING $newsserver Xcase $? in X 0) ;; X *) f=1 X for i in 1 2 3 4 5; X do X %PING $newsserver X case $? in X 0) f=0; X break X ;; X esac X done X case $f in X 0) ;; X *) echo "News server is dead" X control-ppp kill X exit X ;; X esac Xesac X Xget-news-gen | sort | uniq > $tmpf.list Xget-news article < $tmpf.list > $tmpf.article Xcontrol-ppp kill Xcat $tmpf.list Xrnews-batch < $tmpf.article Xrm $tmpf.* END-of-get-news-batch.in echo x - get-news-gen.in sed 's/^X//' >get-news-gen.in << 'END-of-get-news-gen.in' X#!/usr/local/bin/perl X X$debug=0; X$server="%NEWS_SERVER"; X$maxarticles=%MAXARTICLECOUNT; X$maxarticlesize=%MAXARTICLESIZE; X$newsgroupsfile="%NEWSGROUPSFILE"; X XARGV_LOOP: while($op=$ARGV[0]) { X if($op eq "-s") { X $server=$ARGV[1]; X shift; shift; X } X elsif($op eq "-n") { X $maxarticles=$ARGV[1]; X shift; shift; X } X elsif($op eq "-d") { X $debug=1; X shift; X } X else { X last ARGV_LOOP; X } X} X Xrequire "open2.pl"; X$open2::debug=1 if $debug; X Xsub open_nntp { X local($pid); X $pid=&open2(rdr,wtr,"telnet $server nntp") || die "cannot open2\n"; X print "$pid\n" if $debug; X $nntp_opened=1; X} Xsub close_nntp { X close(rdr); X close(wtr); X $nntp_opened=0; X} X Xsub print_mid { X if($mid) { X if($size <= $maxarticlesize) { X print "$mid\n"; X } X } X} X Xopen(ngtbl,"$newsgroupsfile-$server") || X die "Newsgroups table cannot be opened\n"; Xwhile() { X next if $_=~/^\s*#/; X next if $_=~/^\s*\n*$/; X ($group,$lastno)=split; X $lastno{$group}=$lastno; X} Xclose(ngtbl); X Xdo open_nntp(); Xforeach $group (keys %lastno) { X $lastno=$lastno{$group}; X X print wtr "group $group\n"; X $n=0; $last=0; X $_=; X print "## $_" if $debug; X $f=1; X while($f) { X if($_=~/^[0-9][0-9][0-9]/ && $_!~/^20[01]/) { X $f=0; X } X else { X $_=; X print "## $_" if $debug; X } X } X $n=0; $first=0; $last=0; X if(/^211/) { X @a=split; X $n=$a[1]; X $first=$a[2]; X $last=$a[3]; X } X if(!($n && $last)) { X print "## $group: group info unknown\n"; X next; X } X $n=$maxarticles if $n > $maxarticles; X $first1=$last-$n+1; X $first=$first1 if $first1 > $first; X $first=$lastno+1 if $first <= $lastno; X $lastno{$group}=$last; X if($first<=$last) { X print wtr "xover $first-$last\n"; X $_=; X if($_=~/^224/) { X XOVER_LOOP: while() { X print "## $_" if $debug; X s/[\r\n]*$//; X if($_=~/^\.$/) { X last XOVER_LOOP; X } X @a=split(/ /); X $subj=$a[1]; X $from=$a[2]; X $mid=$a[4]; X $size=$a[6]; X do print_mid(); X } X } X } X} Xprint wtr "quit\n"; Xdo close_nntp(); X Xopen(ngtbl,"> /usr/local/lib/maczuka/newsgroups-$server") || X die "Newsgroups table cannot be opened\n"; Xforeach $group (keys %lastno) { X print ngtbl "$group $lastno{$group}\n"; X} Xclose(ngtbl); END-of-get-news-gen.in echo x - get-news.in sed 's/^X//' >get-news.in << 'END-of-get-news.in' X#!/usr/local/bin/perl X X$debug=0; X$server="%NEWS_SERVER"; X$maxarticles=%MAXARTICLECOUNT; X XARGV_LOOP: while($op=$ARGV[0]) { X if($op eq "-s") { X $server=$ARGV[1]; X shift; shift; X } X elsif($op eq "-n") { X $maxarticles=$ARGV[1]; X shift; shift; X } X elsif($op eq "-d") { X $debug=1; X shift; X } X else { X last ARGV_LOOP; X } X} X Xrequire "open2.pl"; X$open2::debug=1 if $debug; X Xsub open_nntp { X local($pid); X $pid=&open2(rdr,wtr,"telnet $server nntp") || die "cannot open2\n"; X print "$pid\n" if $debug; X $nntp_opened=1; X} Xsub close_nntp { X close(rdr); X close(wtr); X $nntp_opened=0; X} X Xsub print_mid { X if($subj && $mid) { X print "# $subj\n"; X print "$mid\n"; X print "\n"; X } X} X Xif($op eq "list") { X X $group=$ARGV[1] || die "Usage: get-news list groupname\n"; X X do open_nntp(); X print wtr "group $group\n"; X $n=0; $last=0; X $_=; X print "## $_" if $debug; X $f=1; X while($f) { X if($_=~/^[0-9][0-9][0-9]/ && $_!~/^20[01]/) { X $f=0; X } X else { X $_=; X print "## $_" if $debug; X } X } X $n=0; $first=0; $last=0; X if(/^211/) { X @a=split; X $n=$a[1]; X $first=$a[2]; X $last=$a[3]; X } X die "group info unknown\n" unless $n && $last; X $n=$maxarticles if $n > $maxarticles; X $first1=$last-$n+1; X $first=$first1 if $first1 > $first; X X print wtr "xover $first-$last\n"; X X print "get-news article <<\'EOF\'\n"; X $_=; X die "xover failed\n" unless $_=~/^224/; X XOVER_LOOP: while() { X print "## $_" if $debug; X s/[\r\n]*$//; X if($_=~/^\.$/) { X last XOVER_LOOP; X } X @a=split(/ /); X $subj=$a[1]; X $mid=$a[4]; X do print_mid(); X } X print "EOF\n"; X X print wtr "quit\n"; X X do close_nntp(); X} # if($op eq "list") X Xelsif($op eq "article") { X do open_nntp(); X open(midlist,"-") || die "message-id list cannot be opened\n"; X while() { X chop; X if($_=~/^); X print wtr "quit\n"; X while() { X print $_; X } X do close_nntp(); X} # if($op eq "article") { X Xelse { X print "Usage: get-news {list | article}\n"; X} X Xif($nntp_opened) { X do close_nntp(); X} END-of-get-news.in echo x - rnews-batch.in sed 's/^X//' >rnews-batch.in << 'END-of-rnews-batch.in' X#! /usr/local/bin/perl X X# When $distlocal==1, "Distribution: local" is inserted in the X# header of the article to prevent it from being sent to other X# sites. But using $insert_path seems more suitable for this X# purpose. So using -d flag is not recommended. X X$distlocal=0; Xif($ARGV[0] eq "-d") { X $distlocal=1; X} X X# $insert_path is inserted at the beginning of the "Path:" field X# to prevent the article from being sent to other sites. X# $insert_path="iijnet!"; X$insert_path="%NEWS_INSERT_PATH"; X X# Let's start! X X$article=0; X Xopen(spool,"-"); XLOOP: while() { X $_=~s/[\r\n]*$//; X if(!$article && $_=~/^220 /) { X $article=1; X open(rnews,"| /bin/rnews") || die "rnews cannot be opened\n"; X $header=1; X $distribution=0; X next LOOP; X } X X if($header && $_=~/^[^: ]/) { X ($headername)=($_=~/^([^: ]+):.*/); X $headername=~tr/A-Z/a-z/; X } X X if($distlocal && $header && $headername eq "distribution") { X if($_=~/^[^ ]/) { X print rnews "Distribution: local\n"; X $distribution=1; X } X next LOOP; X } X X if($header && $headername eq "path" && $_=~/^[^ ]/) { X $_=~s/^[^ ]+[ ]*/Path: $insert_path/; X print rnews "$_\n"; X next LOOP; X } X X if($header && $_=~/^$/) { X $header=0; X if($distlocal && !$distribution) { X print rnews "Distribution: local\n"; X } X print rnews "\n"; X next LOOP; X } X X if($article && $_=~/^\.$/) { X $article=0; X close(rnews); X next LOOP; X } X X if($article) { X print rnews "$_\n"; X next LOOP; X } X} Xclose(spool); END-of-rnews-batch.in exit ------ cut here ------ -- ******************************************************************* 日立市在住 伊藤一光 kaz@maczuka.hitachi.ibaraki.jp Ito Kazumitsu Hitachi, Ibaraki, JAPAN http://www.jsdi.or.jp/~maczuka/