home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume31 / pgnews2 / part01 < prev    next >
Encoding:
Text File  |  1992-08-21  |  11.5 KB  |  393 lines

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