home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #18 / NN_1992_18.iso / spool / comp / sources / misc / 3817 < prev    next >
Encoding:
Text File  |  1992-08-18  |  11.7 KB  |  398 lines

  1. Newsgroups: comp.sources.misc
  2. Path: sparky!kent
  3. From: mcgough@wrdis01.af.mil (Jeffrey B. McGough)
  4. Subject:  v31i088:  pgnews2 - Perl NNTP client to save articles into mailbox, Part01/01
  5. Message-ID: <1992Aug18.214422.27596@sparky.imd.sterling.com>
  6. Followup-To: comp.sources.d
  7. X-Md4-Signature: f9884adb7bb2536de34a9c639faf15ce
  8. Sender: kent@sparky.imd.sterling.com (Kent Landfield)
  9. Organization: 1926CCSG Robins AFB
  10. Date: Tue, 18 Aug 1992 21:44:22 GMT
  11. Approved: kent@sparky.imd.sterling.com
  12. Lines: 384
  13.  
  14. Submitted-by: mcgough@wrdis01.af.mil (Jeffrey B. McGough)
  15. Posting-number: Volume 31, Issue 88
  16. Archive-name: pgnews2/part01
  17. Environment: Perl, NNTP
  18. Supersedes: pgnews: Volume 31, Issue 39
  19.  
  20. This is version 2.0 of pgnews, a PERL NNTP client that grabs news articles 
  21. by newsgroup from a specified NNTP server and and saves them to a specified 
  22. file in mailbox format.
  23.  
  24. Pgnews needs a file named .pgnews to read its newsgroup, last message, and 
  25. savefile from.  .pgnews format is:
  26.  
  27.     newsgroup number savefile
  28.  
  29. Example:
  30. comp.unix.wizards 7800 cuw
  31. comp.unix.shell 3203 cus
  32. comp.unix.questions 546 cuq
  33.  
  34. comp.unix.wizards will be saved to file cuw in mailbox format starting 
  35. at article 7800 etc.
  36.  
  37. The additions to this version are:
  38.   Make the From_ line more rfc976 compliant for mailers like ELM...  This 
  39.   was supplied by Chris Sherman sherman@unx.sas.com...  Thanks Chris...
  40.  
  41.   Added -h option to allow command line specification of NNTP server.
  42.   Thanks to Barry Hassler...
  43.  
  44.   Added $VERSION, no it doesn't do anything it just hangs around [:^)
  45.  
  46.   Added 15 minute timeout to the select stuff so that it would not
  47.   hang on a dead socket...
  48.  
  49. Exception:
  50. While actually slurping up the article the select does not work???  Barry
  51. Hassler seems to think that at that point PERL has already sucked the whole 
  52. thing into its own memory buffers...  Leaving nothing for the select to work 
  53. on.  Care to comment Larry??? Larry did comment... (Thanks) Barry is correct.
  54. The way around this is to use sysread or recv and parse the line ourselves...
  55. (I'm giving it some thought...) [:^)   Anyway I have commented out that 
  56. particular select until we can get some kind of work around... any takers [:^)
  57.  
  58. Jeffrey B. McGough
  59.  
  60. --- pgnews below ---
  61. #! /bin/sh
  62. # This is a shell archive.  Remove anything before this line, then unpack
  63. # it by saving it into a file and typing "sh file".  To overwrite existing
  64. # files, type "sh file -c".  You can also feed this as standard input via
  65. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  66. # will see the following message at the end:
  67. #        "End of shell archive."
  68. # Contents:  pgnews
  69. # Wrapped by mcgough@wrdis01 on Mon Jul 27 14:17:14 1992
  70. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  71. if test -f 'pgnews' -a "${1}" != "-c" ; then 
  72.   echo shar: Will not clobber existing file \"'pgnews'\"
  73. else
  74. echo shar: Extracting \"'pgnews'\" \(8260 characters\)
  75. sed "s/^X//" >'pgnews' <<'END_OF_FILE'
  76. X#!/usr/local/bin/perl 
  77. X#/****************************************************
  78. X#*****************************************************
  79. X#**
  80. X#** SOURCE NAME | pgnews, (Perl Get News)
  81. X#**             | 
  82. X#**    SYNOPSIS | pgnews [-h hostname]
  83. X#**             | 
  84. X#** DESCRIPTION | pgnews goes to a specified NNTP server
  85. X#**             | and retrieves news articles by newsgroup
  86. X#**             | and saves them to a specified file in
  87. X#**             | mailbox format.
  88. X#**             | Please see the NOTES section.
  89. X#**             | 
  90. X#**     CHANGES | Programmer:         Date:     Reason/Comments
  91. X#**             | Jeffrey B. McGough  09-05-91  initial
  92. X#**             | Jeffrey B. McGough  09-06-91  Added select (see FIXES)
  93. X#**             | Jeffrey B. McGough  10-06-91  Fixed erronious end of article
  94. X#**             | Jeffrey B. McGough  07-09-92  Fixed dup article bug
  95. X#**             | Jeffrey B. McGough  07-13-92  (See FIXES)
  96. X#**             | Jeffrey B. McGough  07-27-92  VERSION 2.0 (See FIXES)
  97. X#**             | 
  98. X#**       NOTES | Pgnews needs a file named .pgnews to read
  99. X#**             | its newsgroup, last message, and savefile from.
  100. X#**             | .pgnews format is:
  101. X#**             | newsgroup number savefile
  102. X#**             | Example:
  103. X#**             | comp.unix.wizards 7800 cuw
  104. X#**             | comp.unix.shell 3203 cus
  105. X#**             | comp.unix.questions 546 cuq
  106. X#**             | 
  107. X#**             | comp.unix.wizards will be saved to file cuw in
  108. X#**             | mailbox format starting at article 7800 etc.
  109. X#**             | 
  110. X#**       FIXES | 09-06-91: added select on S to keep the client
  111. X#**             | from getting out of sync.
  112. X#**             | Jeffrey B. McGough  mcgough@wrdis01.af.mil
  113. X#**             | 
  114. X#**             | 10-06-91: Fixed an overlooked END of ARTICLE
  115. X#**             | bug... Thanks to a member(s) of the issos
  116. X#**             | group at Ohio State.
  117. X#**             | Jeffrey B. McGough  mcgough@wrdis01.af.mil
  118. X#**             | 
  119. X#**             | 07-09-92: Fixed a duplicate article bug
  120. X#**             | pointed out to me by kenr@bridge.cc.rochester.edu
  121. X#**             | and gort@bridge.cc.rochester.edu. Thanks
  122. X#**             | for the help with the fix.
  123. X#**             | Jeffrey B. McGough  mcgough@wrdis01.af.mil
  124. X#**             | 
  125. X#**             | 07-13-92: Added code to take a -h option
  126. X#**             | for a host to use as a server...
  127. X#**             | Thanks to Barry Hassler...
  128. X#**             | Added code written by sherman@unx.sas.com
  129. X#**             | to make the header From_ line more RFC976
  130. X#**             | compatable for the ELM mailer...
  131. X#**             | Jeffrey B. McGough  mcgough@wrdis01.af.mil
  132. X#**             | 
  133. X#**             | 07-27-92: Added 15 minute timeout to the
  134. X#**             | select stuff. Just in case the server goes
  135. X#**             | away we won't sit around forever listening
  136. X#**             | to a dead connection...
  137. X#**             | Exception to the time out:
  138. X#**             | While in the loop where we slurp up the
  139. X#**             | article from the server, the select will not
  140. X#**             | work...
  141. X#**             | A friend of mine (Barry Hassler) seems to think
  142. X#**             | that at that point Perl has already sucked
  143. X#**             | the whole thing into its own buffers...
  144. X#**             | Care to comment Larry?
  145. X#**             | Anyway I commented out that select. If anyone
  146. X#**             | has any ideas please let me know...
  147. X#**             | Went ahead and built VERSION 2.0
  148. X#**             | Jeffrey B. McGough  mcgough@wrdis01.af.mil
  149. X#**             | 
  150. X#****************************************************/
  151. X
  152. Xrequire 'sys/socket.ph'; # The way I coded the sockets is this necessary?
  153. X
  154. X$VERSION = '2.0';
  155. X
  156. X$port = 119; # For NNTP
  157. X# HOSTNAME for the server...
  158. X#$host = 'localhost';
  159. X$host = 'emory.mathcs.emory.edu';
  160. X# Pack format...
  161. X$sockaddr = 'S n a4 x8';
  162. X
  163. X$DOMAIN = 2;
  164. X$STYLE = 1;
  165. X
  166. Xwhile ($arg = shift(@ARGV))
  167. X{
  168. X    if ($arg =~ /-.*h/)
  169. X    {
  170. X        $host=shift(@ARGV);
  171. X        if ($host eq "")
  172. X        {
  173. X            printf ("Need host name after -h\n");
  174. X            exit 1;
  175. X        }
  176. X        next;
  177. X    }
  178. X
  179. X    printf "Unknown option: '%s'\n", $arg;
  180. X    exit 1;
  181. X}
  182. X
  183. X
  184. X$newsfile = '.pgnews';
  185. X$nnewsfile = '.pgnews.new';
  186. X
  187. X$rin = $rout = '';
  188. X
  189. X($name, $aliases, $proto) = getprotobyname('tcp');
  190. X($name, $aliases, $type, $len, $hostaddr) = gethostbyname($host);
  191. X
  192. X$sock = pack($sockaddr, $DOMAIN, $port, $hostaddr);
  193. X
  194. Xsocket(S, $DOMAIN, $STYLE, $proto) || die $!;
  195. Xconnect(S, $sock) || die $!;
  196. Xselect(S); $| = 1; select(STDOUT);
  197. X#set up for select
  198. Xvec($rin, fileno(S), 1) = 1;
  199. X#this select will block until the server gives us something.
  200. X$nfound = select($rout=$rin, undef, undef, 900);
  201. Xif ($nfound == 0)
  202. X{
  203. X    print "Socket timed out...";
  204. X    exit 1;
  205. X}
  206. X$_ = <S>; #Read one line to see if we got a good connection.
  207. Xif ($_ !~ /^2../)
  208. X{
  209. X    print;
  210. X    die "Service unavailable";
  211. X}
  212. Xopen(GRP, "< $newsfile") || die "Could not open $newsfile: $!";
  213. Xopen(NGRP, "> $nnewsfile") || die "Could not open $nnewsfile: $!";
  214. Xselect(NGRP); $| = 1; select(STDOUT);
  215. Xwhile(<GRP>)
  216. X{
  217. X    chop;
  218. X    ($grp, $lgot, $file) = split;
  219. X    print(S "group $grp\n");
  220. X    #this select will block until the server gives us something.
  221. X    $nfound = select($rout=$rin, undef, undef, 900);
  222. X    if ($nfound == 0)
  223. X    {
  224. X        print "Socket timed out...";
  225. X        exit 1;
  226. X    }
  227. X    $_ = <S>; #Make sure the group change worked...
  228. X    ($stat, $num, $first, $last) = split;
  229. X    if( $stat !~ /^2../ )
  230. X    {
  231. X        print;
  232. X        warn "Bad group";
  233. X        print(NGRP "$grp $lgot $file\n");
  234. X        next;
  235. X    }
  236. X    # good group open output file...
  237. X    open(OUTFILE, ">>$file") || die "Could not open $file";
  238. X
  239. X    if ( $first > $lgot )
  240. X    {
  241. X        $lgot = $first;
  242. X    }
  243. X    if ( $lgot <= $last )
  244. X    {
  245. X        foreach $art ($lgot..$last)
  246. X        {
  247. X            print(S "article $art\n");
  248. X            #this select will block until the server gives us something.
  249. X            $nfound = select($rout=$rin, undef, undef, 900);
  250. X            if ($nfound == 0)
  251. X            {
  252. X                print "Socket timed out...";
  253. X                exit 1;
  254. X            }
  255. X            $_ = <S>; #get error if one exists
  256. X            if($_ !~ /^2../)
  257. X            {
  258. X                print;
  259. X                warn "No article by that number";
  260. X            }
  261. X            else
  262. X            {
  263. X# We now slurp the whole article into the array article...
  264. X# HMMM is this good or bad...
  265. X# It gives me the WILLIES   [:^)    Jeffrey B. McGough
  266. X                @article = ();
  267. X                do
  268. X                {
  269. X# The next few lines have been commented out because they don't work
  270. X# JBM 07-27-92
  271. X#                    $nfound = select($rout=$rin, undef, undef, 900);
  272. X#                    if ($nfound == 0)
  273. X#                    {
  274. X#                        print "Socket timed out...";
  275. X#                        exit 1;
  276. X#                    }
  277. X                    $lgot = $art;
  278. X                    $_ = <S>;
  279. X                    s/\r//;
  280. X                    if( $_ ne ".\n")
  281. X                    {
  282. X                        s/^\.//;
  283. X                        push(@article,$_);
  284. X                        s/^\./../;
  285. X                    }    
  286. X                    else
  287. X                    {
  288. X                        push(@article,"\n");
  289. X                    }
  290. X                } until $_ eq ".\n";
  291. X                # replace the Path: with a from line
  292. X                splice(@article, 0, 1, &from_line(@article));
  293. X                print OUTFILE @article;
  294. X            }
  295. X        }    
  296. X    }
  297. X    else
  298. X    {
  299. X        $lgot -= 1;
  300. X    }
  301. X    close(OUTFILE);
  302. X    $lgot += 1;
  303. X    print(NGRP "$grp $lgot $file\n");
  304. X}
  305. Xclose(NGRP);
  306. Xclose(GRP);
  307. Xsystem("mv $nnewsfile $newsfile");
  308. Xprint( S "quit\n");
  309. Xclose(S);
  310. X
  311. X# We parse through @article to build a more proper From_ line
  312. Xsub from_line
  313. X{
  314. X
  315. X    local(@article) = @_;
  316. X
  317. X    local($header) = $true;        # we are in the header of the mail
  318. X    local($date,$month,$year,$time,$day);
  319. X
  320. X    for (@article)
  321. X    {
  322. X        if ($header == $true)
  323. X        {
  324. X            if (/^Path: ([^ \n]+)/)
  325. X            {
  326. X                $path = $1;
  327. X            }
  328. X            elsif (/^Date: /)
  329. X            {
  330. X                if (/^Date: (\d*) (\D*) (\d*) (\S*)/) 
  331. X                {
  332. X                    $date = $1;
  333. X                    $month = $2;
  334. X                    $year = $3; 
  335. X                    $time = $4;
  336. X                }
  337. X                elsif (/^Date: (\D*), (\d*) (\D*) (\d*) (\S*)/)
  338. X                {
  339. X                    $day = $1;
  340. X                    $date = $2;
  341. X                    $month = $3;
  342. X                    $year = $4; 
  343. X                    $time = $5;
  344. X                }
  345. X                $year =~ s/^([0-9])([0-9])$/19$1$2/;    # convert 2 digit year to 4 
  346. X                if ($day eq "")
  347. X                {
  348. X                    $day = &day_of_week($month,$date,$year);
  349. X                }
  350. X            }
  351. X            $header = $false if /^\n$/;
  352. X        }
  353. X    }
  354. X    $from_line = sprintf("From %s %s %s %2s %s %s %s\n",
  355. X        $path, $day, $month, $date, $time, $year);
  356. X    return($from_line);
  357. X}
  358. X
  359. X# This gives us the day of week from the date...
  360. Xsub day_of_week
  361. X{
  362. X    local($month,$date,$year) = @_;
  363. X    local($day);
  364. X
  365. X
  366. X    if ($month <= 2)
  367. X    { 
  368. X        $month += 12;
  369. X        $year--;
  370. X    }
  371. X
  372. X    $day = ($date + $month * 2 + int(($month + 1) * 6 / 10) + $year + 
  373. X        int($year / 4) - int($year / 100) + int($year / 400) + 2) % 7;
  374. X
  375. X    if ($day == 0)
  376. X    {
  377. X         $day = 7;
  378. X    }
  379. X
  380. X    return (NULL, Sun, Mon, Tue, Wed, Thu, Fri, Sat, Sun)[$day];
  381. X}
  382. END_OF_FILE
  383. if test 8260 -ne `wc -c <'pgnews'`; then
  384.     echo shar: \"'pgnews'\" unpacked with wrong size!
  385. fi
  386. chmod +x 'pgnews'
  387. # end of 'pgnews'
  388. fi
  389. echo shar: End of shell archive.
  390. exit 0
  391. -- 
  392. Lator,                                       We cheat the other guy,
  393.                                              and pass the savings on to you.
  394. Jeffrey B. McGough
  395. WR-ALC UNIX Systems Administrator                    (mcgough@wrdis01.af.mil)
  396.  
  397. exit 0 # Just in case...
  398.