home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume17 / rkive / part03 < prev    next >
Internet Message Format  |  1991-02-24  |  56KB

  1. From: kent@sparky.imd.sterling.com (Kent Landfield)
  2. Newsgroups: comp.sources.misc
  3. Subject: v17i019:  rkive - Usenet sources archiver, Part03/06
  4. Message-ID: <1991Feb24.222521.27030@sparky.IMD.Sterling.COM>
  5. Date: 24 Feb 91 22:25:21 GMT
  6. Approved: kent@sparky.imd.sterling.com
  7. X-Checksum-Snefru: e7164d70 d77faeb8 20cbdf97 f2009fed
  8.  
  9. Submitted-by: Kent Landfield <kent@sparky.imd.sterling.com>
  10. Posting-number: Volume 17, Issue 19
  11. Archive-name: rkive/part03
  12.  
  13. #! /bin/sh
  14. # This is a shell archive.  Remove anything before this line, then feed it
  15. # into a shell via "sh file" or similar.  To overwrite existing files,
  16. # type "sh file -c".
  17. # The tool that generated this appeared in the comp.sources.unix newsgroup;
  18. # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
  19. # If this archive is complete, you will see the following message at the end:
  20. #        "End of archive 3 (of 6)."
  21. # Contents:  rkive/README rkive/header.c rkive/rkive.h
  22. # Wrapped by kent@sparky on Sun Feb 24 16:11:22 1991
  23. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  24. if test -f 'rkive/README' -a "${1}" != "-c" ; then 
  25.   echo shar: Will not clobber existing file \"'rkive/README'\"
  26. else
  27. echo shar: Extracting \"'rkive/README'\" \(15961 characters\)
  28. sed "s/^X//" >'rkive/README' <<'END_OF_FILE'
  29. X
  30. X                 USENET Sources Archiver             
  31. X
  32. X                 @(#)README    2.2 2/23/91
  33. X
  34. X             Copyright (c) 1989, 1990, 1991 by Kent Landfield.
  35. X
  36. X   Permission is hereby granted to copy, distribute or otherwise 
  37. X   use any part of this package as long as you do not try to make 
  38. X   money from it or pretend that you wrote it.  The copyright 
  39. X   notice must be maintained in any copy made.
  40. X  
  41. X   If you make modifications to this software that you feel 
  42. X   increases it usefulness for the rest of the community, please 
  43. X   email the changes, enhancements, bug fixes as well as any and 
  44. X   all ideas to me. This software is going to be maintained and 
  45. X   enhanced as deemed necessary by the community.
  46. X          
  47. X            -Kent+
  48. X             uunet!sparky!kent
  49. X                   kent@sparky.imd.sterling.com
  50. X  
  51. X------------------------------------------------------------------
  52. X                       DISCLAIMER
  53. X------------------------------------------------------------------
  54. XUse of this software constitutes acceptance for use in an AS IS 
  55. Xcondition. There are NO warranties with regard to this software.  
  56. XIn no event shall the author be liable for any damages whatsoever 
  57. Xarising out of or in connection with the use or performance of this 
  58. Xsoftware.  Any use of this software is at the user's own risk.
  59. X-------------------------------------------------------------------
  60. X
  61. X
  62. XWhen made, this package currently contains 3 executables:
  63. X
  64. X    o  rkive    - a USENET newsgroup archiver,
  65. X    o  article  - print formatted news article header information, and
  66. X        o  ckconfig - an rkive configuration file check program.
  67. X
  68. X
  69. XThis package was initially designed for archiving comp.sources.all newsgroups.
  70. XIt does however, support archiving of non-moderated, non-sources newsgroups.
  71. X
  72. X                        -----
  73. X                        rkive 
  74. X                        -----
  75. X
  76. Xrkive reads a configuration file to determine such things as:
  77. X
  78. X    o where the news directory resides,
  79. X    o where each newsgroup is to be archived,
  80. X    o the type of archiving to be done for each newsgroup,
  81. X    o the ownership and modes of the archived members,
  82. X
  83. Xas well as additional optional features such as:
  84. X
  85. X        o which users/accounts to mail the archived member information to,
  86. X    o the location and format of log files, 
  87. X    o the location and format of index files,
  88. X    o the compression program to use (if desired). 
  89. X
  90. XIt is intended that rkive be run by cron on a daily basis. In this manner,
  91. Xsoftware is archived and available for retrieval from the archives on the
  92. Xday it reaches the machine.  It allows for the archives to be managed by
  93. Xthe same or different people (or accounts).  It supports the building
  94. Xof indexes for later review or to interface to the netlib type of mail
  95. Xretrieval software. It also supports mailing notifications of the archiving
  96. Xto a specified list of users or aliases. The indexes and log file formats
  97. Xare specifiable by the person configuring the rkive configuration file.
  98. X
  99. X-------------------------------------------------------------------
  100. XThe following defines are possible. Please note that the Directory
  101. XCreation defines are specified in Makefile while the rest are specified
  102. Xin rkive.h.
  103. X
  104. X***************************
  105. Xrkive.h - General Defines
  106. X***************************
  107. X
  108. X-D REDUCE_HEADERS   :   Archived article header reduction code.
  109. X    Disk space is saved by removing header lines that have no 
  110. X    further use after the article is stored in the archive.
  111. X    As currently defined, all headers *except* for From:, Newsgroups:, 
  112. X    Subject:, Message-ID:, Approved:, and Date: are removed if this 
  113. X        is defined.
  114. X    The list of headers to be saved can be added to or reduced by
  115. X    modifying the table "hdrs" in news_arc.c.
  116. X
  117. X-D SUBJECT_LINE     :   Specify that the local mailer has -s option
  118. X        such as /usr/bin/mailx or /usr/ucb/Mail.
  119. X
  120. X*************************************
  121. XMakefile - Directory Creation Defines
  122. X*************************************
  123. X
  124. X-D HAVE_MKDIR       : use the mkdir() function in the system library. 
  125. X    (AT&T 5.2 or earlier systems are probably out of luck..)
  126. X
  127. X-D USE_SYSMKDIR     : have rkive system off /bin/mkdir.
  128. X    (not recommended for *real* use...)
  129. X
  130. XIf you do not define either, the function makedir() will create the 
  131. Xdirectory itself. I suggest that if you do not have mkdir() in your
  132. Xsystem libraries, use the builtin if you can. *Please* verify you can
  133. Xuse it *first*.
  134. X
  135. X---------------------------
  136. XArchive Member Compression:
  137. X---------------------------
  138. XIf you wish to have your archived articles compressed you may do so by
  139. Xspecifying the disk path to the compression program as the value for
  140. XCOMPRESS in the rkive configuration file. It is important that *if* you
  141. Xuse a compression program other that "compress" or "pack" that you add
  142. Xan entry to the compression routine table in the file suffix.h.
  143. XCurrently, this program recognizes just ".z" and ".Z" suffixes.
  144. X
  145. X----------------
  146. XREPOST Handling:
  147. X----------------
  148. XWarning:
  149. X    Repost handling is not a configurable parameter within the 
  150. X    rkive configuration file at this time.
  151. X
  152. XADD_REPOST_SUFFIX define added.
  153. X    This define allows the administrator to configure the software to
  154. X    add "-repost" (or whatever is defined in REPOST_SUFFIX) to the
  155. X    end of all files that are marked as REPOST by the newsgroup moderator.
  156. X    The suffix is added prior to compression. This feature should only be 
  157. X    configured/exist on systems whose filename limits are greater than 14.
  158. X
  159. XMV_ORIGINAL define added.
  160. X    This define allows the administrator to configure the software to
  161. X    move the original article into a "originals" directory in the 
  162. X    problems directory. The inbound reposted article is placed into 
  163. X    the archive in the correct position.
  164. X
  165. XIf neither define is specified then the inbound article is placed into 
  166. Xthe archive in the correct position only if the initial article is not 
  167. Xin the archive.  Otherwise the reposted article is placed in the problems 
  168. Xdirectory as normal duplicate articles are now.
  169. X
  170. X-----------------
  171. XPATCHES Handling:
  172. X-----------------
  173. Xrkive supports the Auxiliary header "Patch-To:". The Patch-To: line
  174. Xexists for articles that are patches to previously posted software. 
  175. XThe Patch-To: line only appears in articles that are posted, "Official", 
  176. Xpatches. The initial postings would not contain the Patch-To: auxiliary 
  177. Xheader line.
  178. X
  179. XAuxiliary Headers For Patch Postings:
  180. X
  181. X    Submitted-by: Kent Landfield <kent@sparky>
  182. X    Posting-number: Volume 23, Issue 14
  183. X->    Patch-To: rkive: Volume 19, Issue 98-101
  184. X    Archive-name: rkive/patch1
  185. X
  186. XPatch-To: syntax
  187. X    Patch-To: package-name: Volume X, Issue x[-y,z]
  188. X
  189. XPatch-To: examples. These are examples and do not reflect the
  190. Xaccurate volume/issue numbering for rkive.
  191. X
  192. XIn the first example, the article that contains the following line
  193. Xis a patch to a single part posting.
  194. X    Patch-To: rkive: Volume 19, Issue 98
  195. X
  196. XThis example shows that the 122-124 indicates the patch applies to
  197. Xa multi-part posting. The '-' is used to mean "article A through article
  198. XB, inclusive..
  199. X    Patch-To: rkive: Volume 19, Issue 98-101
  200. X
  201. XIf a patch applies to multiple part postings that are not consecutive, the
  202. X',' is used to separate the part issue numbers. It is possible to mix both
  203. X',' and '-' on a single Patch-To: line.
  204. X    Patch-To: rkive: Volume 99, Issue 122,125,126,127
  205. X    Patch-To: rkive: Volume 22, Issue 122,125-127
  206. X
  207. XThere are two different types of handling with regards to patches. 
  208. X
  209. X    Package     - This type of archiving of patches places the patches
  210. X                      in the same directory that the initial source was
  211. X                      posted to. This type of archiving is only available
  212. X                      to newsgroup archives that are using Archive-Name
  213. X                      archiving.
  214. X                   
  215. X    Historical  - This type of archiving patches is done by sites that 
  216. X                      want to place the patches in the volume/issue in 
  217. X                      which the patch originally arrived.
  218. X
  219. XArchive recognizes that the Patch-To: line indicates the article is 
  220. Xa patch.  For Archive-Name archiving which has specified "Package" 
  221. Xpatches archiving in the configuration file, rkive puts the article 
  222. Xinto the directory that contained the initial posting (volume19/rkive). 
  223. XFor Archive-Name that has not specified Package archiving or for 
  224. XVolume/Issue archiving, the article would still be labeled as
  225. Xvolume23/rkive/patch1 or volume23/v23i014 respectively.
  226. X
  227. Xrkive also writes a .patchlog file in the BASEDIR for the newsgroup
  228. Xthat is used to track patches to originally posted software. The
  229. X.patchlog is going to be used for the "random software downloader :-)"
  230. Xso that complete software packages (sources and patches) can be requested
  231. Xfrom sites that do not use combined Archive-Name and Package archiving.
  232. XThe format of the .patchlog file is:
  233. X
  234. X#
  235. X#    Patch log for comp.sources.whoknows
  236. X#
  237. X# Path To                    Patch       Package        Initial
  238. X# Patchfile             Volume  Issue     Name      Volume  Issue  
  239. X#
  240. Xvolume6/bb/patch01          6     86       bb          3    70-73
  241. X            or if volume issue format..
  242. Xvolume6/v06i86              6     86       bb          3    70-73
  243. X
  244. X-------------------------
  245. XArticle Header Reduction:
  246. X-------------------------
  247. XArticles that are stored just as they arrived on your system are potentially
  248. Xwasting disk space. Certain rfc822/rfc1036 header lines are of little use
  249. Xafter the article is archived.  If you wish to have the headers "trimmed" 
  250. Xwhen the file is archived, assure that REDUCE_HEADERS is defined. Currently 
  251. Xall header lines that are *not* either;
  252. X
  253. X    From:, Newsgroups:, Subject:, Message-ID: Approved:, and Date:
  254. X
  255. Xwill be removed. This can produce a savings of as much as 200 to 500 
  256. Xbytes per archived article.
  257. X
  258. XSee news_arc.c if you wish to add or subtract header lines to be kept.
  259. XThe modifications need to be made to the hdrstokeep table just above the
  260. Xkeep_line() function.
  261. X
  262. X---------
  263. XSecurity:
  264. X---------
  265. Xrkive sets the ownership, group and modes on the archived members according
  266. Xto the information specified in the configuration file. Currently though,
  267. Xrkive uses the default umask for creating the log and index files.
  268. X
  269. Xrkive will not archive files outside of the BASEDIR specified in the 
  270. Xconfiguration file so a "prankster" can not do nasty things to your
  271. Xsystem files by having an Archive-name line like:
  272. X    Archive-name: ../../../../../../etc/passwd
  273. X
  274. XIt will also not overwrite duplicate files. They are stored underneath
  275. Xthe problems directory specified in the configuration file. The admin 
  276. Xis alerted to the fact and it then becomes a manual cleanup problem.
  277. X
  278. X                        -------
  279. X                        article 
  280. X                        -------
  281. X
  282. XArticle allows you to view the article headers in much the same manner
  283. Xthat you use a printf statement.  This was initially done for debugging
  284. Xpurposes but I quickly found that it was extremely useful in dealing
  285. Xwith news articles in general. It works great in shell scripts to view
  286. Xarticles that need to be read.... Also super for perusing the archives
  287. Xdirectly and generating indexes to the archives in *many* different 
  288. Xways...:-)  If you do not want to use rkive for archiving sources or
  289. Xnewsgroups, do yourself a favor and compile article. It will be worth
  290. Xthe time it takes...
  291. X
  292. X                        --------
  293. X                        ckconfig 
  294. X                        --------
  295. X
  296. XThis program is used by the admin to verify just how rkive will 
  297. Xinterpret the variable specifications in an archive configuration
  298. Xfile. If you have problems, it will bomb out when it encounters
  299. Xthe problem. Not real smart but it does the job..
  300. X
  301. X------------------------------------------------------------------------
  302. XThis software set was developed under an archiving model similar to
  303. Xthat maintained currently on uunet. It was intended that the archiving
  304. Xfacilities were more of a "site" facility and not an individuals
  305. Xfacility. (That is unless the individual owned the site :-)). I have
  306. Xeven used rkive for maintaining private (many on a single machine)
  307. Xarchives. rkive will accept an rkive.cf file specified on the
  308. Xcommand line so it would be possible for an individual to have their own
  309. Xmini archive directory structure. This is not recommended if the site is
  310. Xdoing archiving since the software will store multiple copies thus wasting
  311. Xmore disk space than it is worth.
  312. X------------------------------------------------------------------------
  313. XCredits:
  314. X--------
  315. XI have to give credit to where credit is do.
  316. X
  317. XI used the code in header.c of the News 2.11 as the basis of ideas for
  318. Xdealing with the article headers. The code I have written is not the same
  319. Xbut most of the concepts and some of the flow control resulted from reviewing
  320. Xhow it was "suppose to be done". (rfcs only go so far.. :-)) For that I
  321. Xthank Rick Adams and the authors of B news for the excellent code to study
  322. Xfrom.. :-)
  323. X
  324. XI would also like to thank my beta testers for the headaches of dealing
  325. Xwith me, with forcing different ideas on me at a time when I was "almost"
  326. Xwilling to listen :-) and for the "full redistribution of sources" when
  327. XI had a new version. 
  328. X------------------------------------------------------------------------
  329. X
  330. XPlease read all the directions below before you proceed any 
  331. Xfurther, and then follow them carefully.  
  332. X
  333. X                    --------------
  334. X                     Installation
  335. X                    --------------
  336. X
  337. XThis package uses Doug Gwyn's directory access routines posted in
  338. Xcomp.sources.unix/volume9 (with the bug fix as well). You may need
  339. Xto get a copy if you don't already have one and your system does 
  340. Xnot support POSIX Compatible directory access routines.  rkive was
  341. Xwritten using the POSIX directory routines to make the code cleaner
  342. Xand easier to test. If you want to waste your time moving it to any
  343. Xother directory reading routines, don't send me your patches. These
  344. Xare the only patches I will not even consider including in the baseline
  345. Xsources.  Now with my rudeness aside... :-)
  346. X
  347. X1)  Take the time to format and read the man pages prior to continuing.
  348. X        make man | less/pg/more
  349. X
  350. X2)  Review/modify rkive.h to make sure system defines are correct.  
  351. X
  352. X3)  Determine the method for directory creation and edit the Makefile
  353. X    accordingly.
  354. X
  355. X4)  make
  356. X
  357. X    This will attempt to make the software in the current directory.
  358. X
  359. X5)  Put rkive, ckconfig, and article into a public directory 
  360. X    (normally /usr/local/bin), and put a template of the rkive
  361. X    configuration file  (if one does not exist) into an rkive specific
  362. X    library directory (normally as /usr/local/lib/rkive/rkive.cf).  Place 
  363. X    the man pages in the appropriate man directories for your site.
  364. X
  365. X
  366. X6)  I have set up an account for the source archives.  This is not really 
  367. X    necessary but is a personal preference. Archive needs to be run as 
  368. X    root *if* you do not have the mkdir () and wish to use the builtin
  369. X    since it needs to use mknod() to create directories. It also needs
  370. X    to run as root if the owner/group specified in the rkive.cf is 
  371. X    different from the user it is being run under.
  372. X
  373. X    ---x--x--x  1 root archive    43048 Apr  9 16:38 /usr/local/bin/rkive
  374. X    ---x--x--x  1 src  archive    14836 Apr  9 16:38 /usr/local/bin/article
  375. X    ---x--x--x  1 src  archive    27448 Apr  9 16:38 /usr/local/bin/ckconfig
  376. X    -r--r--r--  1 src  archive     6173 Apr  9 16:40 /usr/local/lib/rkive.cf
  377. X
  378. X7)  Re-read the manual entry for rkive.1 and rkive.5.
  379. X
  380. X8)  Modify the template rkive configuration file to reflect the local
  381. X    archive conditions. ckconfig should be used in order to check the
  382. X    information that you have just entered/modified in the rkive.cf file. 
  383. X
  384. X9)  VERY IMPORTANT! If you have a problem, there's someone else out there 
  385. X    who either has had or will have the same problem.  Please send all 
  386. X    patches, ideas, etc to kent@sparky.imd.sterling.com (or uunet!sparky!kent)
  387. X    so that I can continue to improve the functionality and portability of 
  388. X    this package. 
  389. END_OF_FILE
  390. if test 15961 -ne `wc -c <'rkive/README'`; then
  391.     echo shar: \"'rkive/README'\" unpacked with wrong size!
  392. fi
  393. # end of 'rkive/README'
  394. fi
  395. if test -f 'rkive/header.c' -a "${1}" != "-c" ; then 
  396.   echo shar: Will not clobber existing file \"'rkive/header.c'\"
  397. else
  398. echo shar: Extracting \"'rkive/header.c'\" \(26184 characters\)
  399. sed "s/^X//" >'rkive/header.c' <<'END_OF_FILE'
  400. X/*
  401. X** This software is Copyright (c) 1989, 1990, 1991 by Kent Landfield.
  402. X**
  403. X** Permission is hereby granted to copy, distribute or otherwise 
  404. X** use any part of this package as long as you do not try to make 
  405. X** money from it or pretend that you wrote it.  This copyright 
  406. X** notice must be maintained in any copy made.
  407. X**
  408. X*/
  409. X
  410. X#if !defined(lint) && !defined(SABER)
  411. Xstatic char SID[] = "@(#)header.c    2.2 2/23/91";
  412. X#endif
  413. X
  414. X#include <stdio.h>
  415. X#include <ctype.h>
  416. X#include <sys/types.h>
  417. X#include "article.h"
  418. X
  419. Xint fprintf();
  420. X
  421. Xint its(s1)
  422. Xregister char *s1;
  423. X{
  424. X    int strlen();
  425. X    int strncmp();
  426. X
  427. X    if (strncmp(s,s1,strlen(s1)) == 0)
  428. X        return(TRUE);
  429. X    return(FALSE);
  430. X}
  431. X
  432. Xint line_type()
  433. X{
  434. X    if (its("Path: "))
  435. X        return PATH;
  436. X    if (its("From: "))
  437. X        return FROM;
  438. X    if (its("Newsgroups: "))
  439. X        return NEWSGROUP;
  440. X    if (its("Subject: "))
  441. X        return SUBJECT;
  442. X    if (its("Keywords: "))
  443. X        return KEYWORDS;
  444. X    if (its("Date: "))
  445. X        return DATE;
  446. X    if (its("Message-ID: "))
  447. X        return MSG_ID;
  448. X    if (its("Lines: "))
  449. X        return NUMLINES;
  450. X    if (its("Approved: "))
  451. X        return APPROVED;
  452. X
  453. X    /* The following are the auxilliary headers used by */
  454. X    /* the moderators of the sources groups. In some    */
  455. X    /* cases, line checks are done with "historical"    */
  456. X    /* auxilliary headers. Most of the moderators have  */
  457. X    /* now standardized on comp.sources.unix's format.  */
  458. X
  459. X    /* Archive header lines for comp.sources.unix     */
  460. X    /* for comp.sources.amiga, comp.sources.atari.st, */
  461. X    /* comp.sources.misc, and comp.sources.x.         */
  462. X
  463. X    if (its("Submitted-by: "))         
  464. X        return SUBMITTED_BY;
  465. X    if (its("Posting-number: "))       
  466. X        return POSTING_NUMBER;
  467. X    if (its("Archive-name: "))
  468. X        return ARCH_NAME;
  469. X
  470. X    /* Auxiliary header used as a backward reference   */
  471. X    /* to the location of the initially posted sources */
  472. X    /* in the event of a patch. This line only exists  */
  473. X    /* if the current article is a patch.              */
  474. X
  475. X    if (its("Patch-To: "))
  476. X        return PATCH_TO;
  477. X    if (its("Patch-to: "))
  478. X        return PATCH_TO;
  479. X
  480. X    /* The X-Checksum-Snefru archive is being used by  */
  481. X    /* comp.sources.unix and comp.sources.misc to      */
  482. X    /* verify articles.                                */
  483. X
  484. X    if (its("X-Checksum-Snefru: "))
  485. X        return X_CHECKSUM_SNEFRU;
  486. X
  487. X    /* The following lines are used by comp.sources.games  */
  488. X    /* currently to indicate the environmental keywords    */
  489. X    /* indicating what is required by the software to run. */
  490. X
  491. X    if (its("Environment: "))
  492. X        return ENVIRONMENT;
  493. X    if (its("Supersedes: "))
  494. X        return SUPERSEDES;
  495. X    /* Archive header lines for historical purposes */
  496. X    /* once used in comp.sources.misc               */
  497. X
  498. X    if (its("Submitted-By: "))        
  499. X        return SUBMITTED_BY;
  500. X    if (its("comp.sources.misc: "))
  501. X        return POSTING_NUMBER;
  502. X    if (its("Archive-Name: "))
  503. X        return ARCH_NAME;
  504. X
  505. X    /* Archive header lines for supporting the  */
  506. X    /* uunet comp.sources.misc article archives */
  507. X
  508. X    if (its("subject: "))
  509. X        return SUBJECT;
  510. X    if (its("from: "))
  511. X        return FROM;
  512. X
  513. X    /* Archive header lines used in comp.sources.games   */
  514. X    /* Archive-name is the same as comp.sources.unix     */
  515. X
  516. X    if (its("Submitted by: "))        
  517. X        return SUBMITTED_BY;
  518. X    if (its("Comp.sources.games: "))
  519. X        return POSTING_NUMBER;
  520. X
  521. X    /* Archive header lines for historical purposes */
  522. X    /* once used in mod.sources articles.           */
  523. X
  524. X    if (its("Mod.sources: "))       
  525. X        return POSTING_NUMBER;
  526. X
  527. X    /* The following lines are used by comp.archives */
  528. X    /* to as auxiliary header lines.  Archive-name   */
  529. X    /* is also used.                                 */
  530. X
  531. X    if (its("Original-posting-by: "))       
  532. X        return ORIGINAL_POSTING_BY;
  533. X    if (its("Original-subject: "))       
  534. X        return ORIGINAL_SUBJECT;
  535. X    if (its("Archive-site: "))       
  536. X        return ARCHIVE_SITE;
  537. X    if (its("Archive-directory: "))       
  538. X        return ARCHIVE_DIRECTORY;
  539. X    if (its("Reposted-by: "))       
  540. X        return REPOSTED_BY;
  541. X    if (its("Archive: "))
  542. X    return ARCHIVE_;
  543. X
  544. X    /* The following lines are used by comp.sources.apple2 */
  545. X    /* to indicate the type of the system the software     */
  546. X    /* is to run on and the version of the software.       */
  547. X
  548. X    if (its("Architecture: "))
  549. X        return ARCHITECTURE;
  550. X    if (its("Version-number: "))
  551. X        return VERSION_NUMBER;
  552. X    /* The remainder are other types of lines included */
  553. X    /* headers and are includes for formatting output  */
  554. X    /* and for potential future use.                   */
  555. X
  556. X    if (its("References: "))
  557. X        return REFERENCES;
  558. X    if (its("Organization: "))
  559. X        return ORGANIZATION;
  560. X    if (its("Distribution: "))
  561. X        return DISTRIBUTION;
  562. X    if (its("Xref: "))
  563. X        return XREF;
  564. X    if (its("Expires: "))
  565. X        return EXPIRE;
  566. X    if (its("Article-I.D.: "))
  567. X        return ARTICLEID;
  568. X    if (its("Reply-To: "))
  569. X        return REPLY_TO;
  570. X    if (its("Control: "))
  571. X        return CONTROL;
  572. X    if (its("Sender: "))
  573. X        return SENDER;
  574. X    if (its("Followup-To: "))
  575. X        return FOLLOWUP_TO;
  576. X    if (its("Summary: "))
  577. X        return SUMMARY;
  578. X
  579. X    return OTHER;
  580. X}
  581. X
  582. Xvoid data(hpfield, size, fldname, header_id)
  583. Xchar *hpfield;
  584. Xint  size;
  585. Xchar *fldname;
  586. Xint  header_id;
  587. X{
  588. X    register char *ptr;
  589. X    register char *p;
  590. X    char *strncpy();
  591. X    char *strcpy();
  592. X    char *strchr();
  593. X
  594. X    for (ptr = strchr(s, ':'); isspace(*++ptr); )
  595. X        ;
  596. X    if (*ptr != '\0') {
  597. X        (void) strncpy(hpfield, ptr, size - 1);
  598. X        /*
  599. X         * Strip trailing newlines, blanks, and tabs from hpfield.
  600. X         */
  601. X        for (p = hpfield; *p; ++p)
  602. X             ;
  603. X        while (--p >= hpfield && (*p == '\n' || *p == ' ' || *p == '\t'))
  604. X             ;
  605. X        *++p = '\0';
  606. X    }
  607. X
  608. X    (void) strcpy(header.header[header_id], hpfield);
  609. X
  610. X    if (debug)
  611. X       (void) fprintf(logfp,"%s: %s\n",fldname, hpfield);
  612. X}
  613. X
  614. Xvoid dump_article()
  615. X{
  616. X    char *type_str;
  617. X
  618. X    switch(article.rectype) {
  619. X             case PATCH  : type_str = "PATCH";
  620. X                           break;
  621. X      case ADMINISTRATION: type_str = "ADMINISTRATION"; 
  622. X                           break;
  623. X      case INFORMATIONAL : type_str = "INFORMATIONAL"; 
  624. X                           break;
  625. X                 default : type_str = "NORMAL"; 
  626. X                           break;
  627. X    }
  628. X
  629. X    (void) fprintf(logfp,"Article:           [%s]\n",article.newsarticle);
  630. X    (void) fprintf(logfp,"   newsgroup:      [%s]\n",article.newsgroup);
  631. X    (void) fprintf(logfp,"   filename:       [%s]\n",article.filename);
  632. X    (void) fprintf(logfp,"   volume:         [%d]\n",article.volume);
  633. X    (void) fprintf(logfp,"   issue:          [%d]\n",article.issue);
  634. X    (void) fprintf(logfp,"   record type:    [%s]\n", type_str);
  635. X    if (article.rectype == PATCH) {
  636. X        (void) fprintf(logfp,"   patch volume:   [%d]\n",article.patch_volume);
  637. X        (void) fprintf(logfp,"   patch issue:    [%s]\n",article.patch_issue);
  638. X    }
  639. X    (void) fprintf(logfp,"   reposted:       [%s]\n", 
  640. X                   article.repost ? "YES": "NO");
  641. X    (void) fprintf(logfp,"   description:    [%s]\n",article.description);
  642. X    (void) fprintf(logfp,"   author's name:  [%s]\n",article.author_name);
  643. X    (void) fprintf(logfp,"   author's logon: [%s]\n\n",article.author_signon);
  644. X}
  645. X
  646. Xvoid init_article()
  647. X{
  648. X    article.newsgroup[0] = '\0';
  649. X    article.newsarticle[0] = '\0';
  650. X    article.filename[0] = '\0';
  651. X    article.volume = -1;
  652. X    article.issue = -1;
  653. X    article.rectype = NORMAL;
  654. X    article.repost = FALSE;
  655. X    article.patch_volume = -1;
  656. X    article.package_name[0] = '\0';
  657. X    article.patch_issue[0] = '\0';
  658. X    article.description[0] = '\0';
  659. X    article.author_name[0] = '\0';
  660. X    article.author_signon[0] = '\0';
  661. X
  662. X    header.from[0] = '\0';             /* From:                 */
  663. X    header.path[0] = '\0';             /* Path:                 */
  664. X    header.nbuf[0] = '\0';             /* Newsgroups:           */
  665. X    header.subject[0] = '\0';          /* Subject:              */
  666. X    header.ident[0] = '\0';            /* Message-ID:           */
  667. X    header.replyto[0] = '\0';          /* Reply-To:             */
  668. X    header.references[0] = '\0';       /* References:           */
  669. X    header.subdate[0] = '\0';          /* Date: (submission)    */
  670. X    header.subtime = 0;                /* subdate in secs       */
  671. X    header.expdate[0] = '\0';          /* Expires:              */
  672. X    header.ctlmsg[0] = '\0';           /* Control:              */
  673. X    header.sender[0] = '\0';           /* Sender:               */
  674. X    header.followup_to[0] = '\0';      /* Followup-to:          */
  675. X    header.distribution[0] = '\0';     /* Distribution:         */
  676. X    header.organization[0] = '\0';     /* Organization:         */
  677. X    header.numlines[0] = '\0';         /* Lines:                */
  678. X    header.intnumlines = 0;            /* Integer Version       */
  679. X    header.keywords[0] = '\0';         /* Keywords:             */
  680. X    header.summary[0] = '\0';          /* Summary:              */
  681. X    header.approved[0] = '\0';         /* Approved:             */
  682. X    header.xref[0] = '\0';             /* Xref:                 */
  683. X    header.supersedes[0] = '\0';       /* Supersedes:           */
  684. X    header.submitted_by[0] = '\0';     /* Submitted_by:         */
  685. X    header.posting_num[0] = '\0';      /* Posting-number:       */
  686. X    header.archive_name[0] = '\0';     /* Archive-name:         */
  687. X    header.patch_to[0] = '\0';         /* Patch-To:             */
  688. X    header.x_checksum_snefru[0] = '\0';    /* X-Checksum-Snefru:      */
  689. X    header.orig_poster[0] = '\0';    /* Original-posting-by:  */
  690. X    header.orig_subject[0] = '\0';    /* Original-subject:     */
  691. X    header.archive_site[0] = '\0';    /* Archive-site:         */
  692. X    header.archive_dir[0] = '\0';    /* Archive-directory:    */
  693. X    header.reposter[0] = '\0';        /* Reposted-by:          */
  694. X    header.architecture[0] = '\0';    /* Architecture:         */
  695. X    header.version_number[0] = '\0';    /* Version-number:       */
  696. X    header.archive[0] = '\0';        /* Archive:         */
  697. X    header.environment[0] = '\0';    /* Environment:         */
  698. X}
  699. X
  700. Xvoid store_line()
  701. X{
  702. X    int atoi();
  703. X    char *strchr(), *strcpy(), *strstrip(), *substr();
  704. X    char *dp, *sp;
  705. X    char wrk[256];
  706. X
  707. X    switch(line_type()) {
  708. X
  709. X    case PATH: /*PATH REQUIRED************************/
  710. X        data(header.path, sizeof(header.path), "PATH:", PATH);
  711. X        break;
  712. X
  713. X    case FROM: /*FROM REQUIRED************************/
  714. X        data(header.from, sizeof(header.from), "FROM:", FROM);
  715. X        break;
  716. X
  717. X    case NEWSGROUP: /*NEWSGROUP REQUIRED**************/
  718. X        data(header.nbuf, sizeof(header.nbuf), "NEWSGROUPS:", NEWSGROUP);
  719. X        if ((sp = strchr(s,':')) != NULL) {
  720. X             do {
  721. X                 ++sp;
  722. X             } while(!isalpha(*sp));
  723. X             /* remove all crossposting labels */
  724. X             if ((dp = strchr(sp,',')) != NULL)
  725. X                 *dp = '\0';
  726. X             (void) strcpy(article.newsgroup,sp);
  727. X        }
  728. X        break;
  729. X
  730. X    case SUBJECT: /*SUBJECT REQUIRED******************/
  731. X        data(header.subject, sizeof(header.subject), "SUBJECT:", SUBJECT);
  732. X        /* 
  733. X        ** Save the subject as the description for articles
  734. X        ** that have no volume/issue format. Later in the
  735. X        ** code, this subject line minus the volume/issue
  736. X        ** is stored back in the .description element if
  737. X        ** the volume/issue indicator is found.
  738. X        */
  739. X        (void) strcpy(article.description, header.subject);
  740. X
  741. X        /*
  742. X        ** Check to see if this article is a repost of
  743. X        ** a previously posted article.
  744. X        */
  745. X        if (substr(s, "REPOST") != NULL)
  746. X            article.repost = TRUE;
  747. X
  748. X        /*
  749. X        ** Time to get the filename. Assure that it is in a 
  750. X        ** volume/issue (v01INF1 or v01ADM1 or v01SRC001 or
  751. X        ** v01i001) format.
  752. X        */
  753. X        if ((sp = strchr(s,'v')) == NULL) 
  754. X            return;          /* no volume indicator */
  755. X
  756. X        /* 
  757. X        ** Is there a number that follows 
  758. X        ** the volume indicator ? 
  759. X        */
  760. X        if (*(sp+1) < '0' || *(sp+1) > '9')
  761. X            return;   /* The volume number is missing */
  762. X
  763. X        /*
  764. X        ** Is there a second ':' as well ?
  765. X        */
  766. X        (void) strcpy(article.filename,sp);
  767. X        if ((dp = strchr(article.filename,':')) == NULL) 
  768. X            return;   /* not in v01i001: format */
  769. X
  770. X        /*
  771. X        ** terminate the article's filename and 
  772. X        ** store the article's description 
  773. X        */
  774. X        *dp = '\0';
  775. X        (void) strcpy(article.description, strstrip(++dp));
  776. X
  777. X        /*
  778. X        ** Store the filename in a work 
  779. X        ** buffer so I can stomp on it. 
  780. X        */
  781. X        (void) strcpy(wrk, article.filename);
  782. X
  783. X        ++sp; /* increment past the 'v' */
  784. X
  785. X        /* 
  786. X        ** This is an informational posting.
  787. X        */
  788. X        if ((dp = substr(wrk, "INF")) != NULL) {
  789. X            article.rectype = INFORMATIONAL;
  790. X            article.issue = atoi((dp+3));
  791. X        }
  792. X
  793. X        /* 
  794. X        ** This is an administration posting.
  795. X        */
  796. X        else if ((dp = substr(wrk, "ADM")) != NULL) {
  797. X            article.rectype = ADMINISTRATION;
  798. X            article.issue = atoi((dp+3));
  799. X        }
  800. X
  801. X        /* 
  802. X        ** This is a comp.sources.apple2 posting.
  803. X        ** Why this is needed, I don't know...
  804. X        */
  805. X        else if ((dp = substr(wrk, "SRC")) != NULL) {
  806. X            article.issue = atoi((dp+3));
  807. X        }
  808. X
  809. X        /*
  810. X        **  check to see if there is an issue indicator 
  811. X        */
  812. X        else if ((dp = strchr(wrk,'i')) != NULL) {
  813. X             /* parse the issue from the filename */
  814. X             article.issue = atoi(dp+1);
  815. X        }
  816. X        else
  817. X            return;   /* proven guilty. not volume/issue format */
  818. X
  819. X        /* parse the volume from the filename */
  820. X        *dp = '\0';
  821. X        article.volume = atoi(sp);
  822. X
  823. X        break;
  824. X
  825. X    case DATE:
  826. X        data(header.subdate, sizeof(header.subdate), "DATE:", DATE);
  827. X        break;
  828. X
  829. X    case EXPIRE:
  830. X        data(header.expdate, sizeof(header.expdate), "EXPIRES:", EXPIRE);
  831. X        break;
  832. X
  833. X    case MSG_ID:
  834. X        data(header.ident, sizeof(header.ident), "MESSAGE-ID:", MSG_ID);
  835. X        break;
  836. X
  837. X    case REPLY_TO:
  838. X        data(header.replyto, sizeof(header.replyto), "REPLY-TO:", REPLY_TO);
  839. X        break;
  840. X
  841. X    case REFERENCES:
  842. X        data(header.references, sizeof(header.references), "REFERENCES:", REFERENCES);
  843. X        break;
  844. X
  845. X    case SENDER:
  846. X        data(header.sender, sizeof(header.sender), "SENDER:", SENDER);
  847. X        break;
  848. X
  849. X    case FOLLOWUP_TO:
  850. X        data(header.followup_to, sizeof(header.followup_to),"FOLLOWUP-TO:", FOLLOWUP_TO);
  851. X        break;
  852. X
  853. X    case CONTROL:
  854. X        data(header.ctlmsg, sizeof(header.ctlmsg),"CONTROL:", CONTROL);
  855. X        break;
  856. X
  857. X    case DISTRIBUTION:
  858. X        data(header.distribution, sizeof(header.distribution),"DISTRIBUTION:", DISTRIBUTION);
  859. X        break;
  860. X
  861. X    case ORGANIZATION:
  862. X        data(header.organization, sizeof(header.organization),"ORGANIZATION:", ORGANIZATION);
  863. X        break;
  864. X
  865. X    case NUMLINES:
  866. X        data(header.numlines, sizeof(header.numlines),"LINES:", NUMLINES);
  867. X        header.intnumlines = atoi(header.numlines);
  868. X        break;
  869. X
  870. X    case KEYWORDS:
  871. X        data(header.keywords, sizeof(header.keywords), "KEYWORDS:",KEYWORDS);
  872. X        break;
  873. X
  874. X    case APPROVED:
  875. X        data(header.approved, sizeof(header.approved), "APPROVED:",APPROVED);
  876. X        break;
  877. X
  878. X    case ENVIRONMENT:
  879. X        data(header.environment, sizeof(header.environment),"ENVIRONMENT:",ENVIRONMENT);
  880. X        break;
  881. X
  882. X    case SUPERSEDES:
  883. X        data(header.supersedes, sizeof(header.supersedes),"SUPERSEDES:",SUPERSEDES);
  884. X        break;
  885. X
  886. X    case XREF:
  887. X        data(header.xref, sizeof(header.xref),"XREF:",XREF);
  888. X        break;
  889. X
  890. X    case SUMMARY:
  891. X        data(header.summary, sizeof(header.summary),"SUMMARY:", SUMMARY);
  892. X        break;
  893. X
  894. X    case POSTING_NUMBER:
  895. X        data(header.posting_num, sizeof(header.posting_num), "POSTING_NUMBER:", POSTING_NUMBER);
  896. X        /*
  897. X        ** Well we almost have a standard here...
  898. X        **
  899. X        ** comp.sources.amiga, comp.sources.atari.st, comp.sources.games
  900. X        ** comp.sources.sun, comp.sources.x, comp.sources.unix all use 
  901. X        ** Posting-Number: lines as follows:
  902. X        **    Volume #, Issue #
  903. X        ** indicates a source posting while
  904. X        **    Volume #, Info #
  905. X        ** is used for all the periodic and administration postings.
  906. X        ** For informational only... c.s.u once used
  907. X        **    Volume #, Number # 
  908. X        ** to indicate a source posting. Really. Check volume 10...
  909. X        ** 
  910. X        ** comp.sources.misc uses the same Posting-number: lines for
  911. X        ** source postings but used 
  912. X        **    Volume #, Administrivia #
  913. X        ** for all the periodic and administration postings.
  914. X        ** In the future, comp.sources.misc will use the Info format
  915. X        ** in order to move towards a standard.
  916. X        **
  917. X        ** comp.sources.apple2 uses the following Posting-number:
  918. X        ** lines for the INF, source and Administration postings.
  919. X        **    Volume 1, Information: 1
  920. X        **    Volume 1, Source:1
  921. X        **    Volume 1, Administrivia: 17
  922. X        **
  923. X        ** If the volume number and issue cannot be determined from
  924. X        ** the subject line then lets give it a try here...
  925. X        */
  926. X        if (article.volume == -1 || article.issue == -1) {
  927. X            if ((sp = strchr(s,'V')) != NULL) {
  928. X                do {
  929. X                    ++sp;
  930. X                } while((*sp) && (!isdigit(*sp)));
  931. X                /* Is there something there... */
  932. X
  933. X                if (!*sp)
  934. X                    return;
  935. X
  936. X                /*
  937. X                ** Time to get the volume number..
  938. X                ** Save it off so that the string can
  939. X                ** be stomped on..  What I am going to do here
  940. X                ** is to assure that I have both a volume and
  941. X                ** an issue number prior to setting any variables
  942. X                ** the describe the article type...
  943. X                */
  944. X                (void) strcpy(wrk,sp);
  945. X                if ((dp = strchr(wrk,',')) != NULL)
  946. X                    *dp++ = '\0';
  947. X                else          /* bad format, bail out... */
  948. X                    return;
  949. X    
  950. X                /*
  951. X                ** Now let's position to the type of the posting..
  952. X                */
  953. X                while((*dp) && (!isalpha(*dp)))
  954. X                     ++dp;
  955. X
  956. X                if (!*dp)      /* Is there something there... */
  957. X                    return;
  958. X
  959. X                /*
  960. X                ** Now it is time to get the Info,Issue,Administrivia,
  961. X                ** Information or Source number....
  962. X                */
  963. X                sp = dp;
  964. X            
  965. X                do {
  966. X                    ++sp;
  967. X                } while((*sp) && (!isdigit(*sp)));
  968. X                if (!*sp)      /* Is there something there... */
  969. X                    return;
  970. X
  971. X                /*
  972. X                ** We have a seemingly valid Posting-number: line.
  973. X                ** Now we can start setting values...
  974. X                */
  975. X                article.volume = atoi(wrk);
  976. X                article.issue = atoi(sp);
  977. X
  978. X                /*
  979. X                ** Determine the type of the posting and
  980. X                ** set the rectype variable.
  981. X                */
  982. X                if (strncmp(dp,"Info",4) == 0) 
  983. X                    /* covers c.s.u and c.s.a2 as well */
  984. X                    article.rectype = INFORMATIONAL;
  985. X
  986. X                if (strncmp(dp,"Administrivia",4) == 0) {
  987. X                    if (strcmp(article.newsgroup,"comp.sources.misc") == 0)
  988. X                        article.rectype = INFORMATIONAL;
  989. X                    else /* comp.sources.apple2 */
  990. X                        article.rectype = ADMINISTRATION;
  991. X                }
  992. X                /*
  993. X                ** fill in the volume/issue filename
  994. X                */
  995. X                if (strcmp(article.newsgroup,"comp.sources.apple2") == 0) {
  996. X                    if (article.rectype == INFORMATIONAL) 
  997. X                        (void) sprintf(article.filename,"v%3.3dINF%3.3d",
  998. X                                          article.volume, article.issue);
  999. X                    else if (article.rectype == ADMINISTRATION) 
  1000. X                            (void) sprintf(article.filename,"v%3.3dADM%3.3d",
  1001. X                                              article.volume, article.issue);
  1002. X                    else 
  1003. X                            (void) sprintf(article.filename,"v%3.3dSRC%3.3d",
  1004. X                                              article.volume, article.issue);
  1005. X                }
  1006. X                else {
  1007. X                    if (article.rectype == INFORMATIONAL) 
  1008. X                        (void) sprintf(article.filename,"v%2.2dINF%1.1d",
  1009. X                                          article.volume, article.issue);
  1010. X                    else
  1011. X                        (void) sprintf(article.filename,"v%2.2di%3.3d",
  1012. X                                        article.volume, article.issue);
  1013. X                }
  1014. X            }
  1015. X        }
  1016. X        break;
  1017. X
  1018. X    case SUBMITTED_BY:
  1019. X        data(header.submitted_by, sizeof(header.submitted_by), "SUBMITTED_BY:", SUBMITTED_BY);
  1020. X        /* 
  1021. X        ** Save the author's name and sign on if specified 
  1022. X        ** Can be in any of the following formats:
  1023. X    **    kent@sparky.uucp 
  1024. X    **    kent@sparky.imd.sterling.com (Kent Landfield)
  1025. X    **    Kent Landfield <kent@sparky.imd.sterling.com>
  1026. X        */
  1027. X        if ((sp = strchr(s,':')) != NULL) {
  1028. X            (void) strcpy(article.author_signon,(sp+2));
  1029. X            /*
  1030. X            ** Has a name been attached to the signon ?
  1031. X            */
  1032. X            if ((dp = strchr(article.author_signon,'<')) != NULL) {
  1033. X                *(dp-1) = '\0';
  1034. X                (void) strcpy(article.author_name, article.author_signon);
  1035. X                (void) strcpy(article.author_signon, ++dp);
  1036. X                /*
  1037. X                ** Save the name, removing the <>.
  1038. X                */
  1039. X                if ((dp = strchr(article.author_signon,'>')) != NULL)
  1040. X                    *dp = '\0';
  1041. X            }
  1042. X            else if ((dp = strchr(article.author_signon,'(')) != NULL) {
  1043. X                *(dp-1) = '\0';
  1044. X                /*
  1045. X                ** Save the name, removing the ().
  1046. X                */
  1047. X                (void) strcpy(article.author_name, ++dp);
  1048. X                if ((dp = strchr(article.author_name,')')) != NULL)
  1049. X                    *dp = '\0';
  1050. X            }
  1051. X        }
  1052. X        break;
  1053. X
  1054. X    case ARCH_NAME:
  1055. X        data(header.archive_name,sizeof(header.archive_name),"ARCH_NAME:", ARCH_NAME);
  1056. X        break;
  1057. X
  1058. X    case PATCH_TO:
  1059. X        data(header.patch_to,sizeof(header.patch_to),"PATCH_TO:", PATCH_TO);
  1060. X        article.rectype = PATCH;        /* set the article type */
  1061. X
  1062. X        /*
  1063. X    ** Parse the initially posted article's package-name, volume 
  1064. X        ** and issue.  The format of the auxiliary header is:
  1065. X        ** 
  1066. X        ** Patch-To: rkive: Volume 5, Issue 110
  1067. X        ** Or in the case of multipart initial postings,
  1068. X        ** Patch-To: rkive: Volume 5, Issue 110-120
  1069. X        ** Or in the case of multipart non-sequential initial postings,
  1070. X        ** Patch-To: rkive: Volume 5, Issue 110, 115, 116-120
  1071. X        **
  1072. X        */
  1073. X
  1074. X        /* 
  1075. X        ** First get the package-name
  1076. X        */
  1077. X
  1078. X        dp = strchr(s,':');    /* This exists or we would not be here */
  1079. X        while ((*++dp == ' ') || *dp == '\t');  /* skip spaces, tabs  */
  1080. X
  1081. X        sp = dp;
  1082. X        if ((dp = strchr(sp,':')) != NULL) {
  1083. X             *dp = '\0';
  1084. X             /* 
  1085. X             ** Now let's check to see if the moderator got it right...
  1086. X             ** Check to assure that a valid archive-name has been 
  1087. X             ** specified in the Patch-To: line...
  1088. X             */
  1089. X             if (strchr(sp,' ') != NULL)  {
  1090. X                 dp = s;  /* reset to start of string if no package-name */
  1091. X                 (void) strcpy(article.package_name,"Unknown");
  1092. X             }
  1093. X             else 
  1094. X                 (void) strcpy(article.package_name,sp);
  1095. X        }
  1096. X        else {
  1097. X             dp = s;  /* reset to start of string if no package-name */
  1098. X             (void) strcpy(article.package_name,"Unknown");
  1099. X        }
  1100. X            
  1101. X        /* 
  1102. X        ** Next, get the volume number.
  1103. X        */
  1104. X
  1105. X        ++dp;
  1106. X        while (*dp && (!isdigit(*dp)))
  1107. X              ++dp;
  1108. X        sp = dp;
  1109. X        while (*dp && (isdigit(*dp)))
  1110. X              ++dp;
  1111. X        *dp = '\0';
  1112. X        article.patch_volume = atoi(sp);
  1113. X
  1114. X        /* 
  1115. X        ** Now get the issue number. 
  1116. X        ** It is stored as a string but error check that
  1117. X        ** just numbers, '-' and ',' are in the string.
  1118. X        */
  1119. X
  1120. X        ++dp;
  1121. X        while (*dp && (!isdigit(*dp)))
  1122. X              ++dp;
  1123. X
  1124. X        sp = article.patch_issue;
  1125. X        while (*dp && (isdigit(*dp) || *dp == '-' || 
  1126. X                         *dp == ',' || *dp == ' ')) {
  1127. X              if (*dp != ' ')
  1128. X                  *sp++ = *dp;
  1129. X              ++dp;
  1130. X        }
  1131. X        *sp = '\0';
  1132. X        break;
  1133. X
  1134. X    case X_CHECKSUM_SNEFRU:
  1135. X        data(header.x_checksum_snefru,sizeof(header.x_checksum_snefru),"X_CHECKSUM_SNEFRU:", X_CHECKSUM_SNEFRU);
  1136. X        break;
  1137. X
  1138. X    case ORIGINAL_POSTING_BY:
  1139. X        data(header.orig_poster,sizeof(header.orig_poster),"ORIGINAL_POSTING_BY:",ORIGINAL_POSTING_BY);
  1140. X        break;
  1141. X
  1142. X    case ORIGINAL_SUBJECT:
  1143. X        data(header.orig_subject,sizeof(header.orig_subject),"ORIGINAL-SUBJECT:",ORIGINAL_SUBJECT);
  1144. X        break;
  1145. X
  1146. X    case ARCHIVE_SITE:
  1147. X        data(header.archive_site,sizeof(header.archive_site),"ARCHIVE_SITE:",ARCHIVE_SITE);
  1148. X        break;
  1149. X
  1150. X    case ARCHIVE_DIRECTORY:
  1151. X        data(header.archive_dir,sizeof(header.archive_dir),"ARCHIVE_DIRECTORY:",ARCHIVE_DIRECTORY);
  1152. X        break;
  1153. X
  1154. X    case REPOSTED_BY:
  1155. X        data(header.reposter,sizeof(header.reposter),"REPOSTED_BY:",REPOSTED_BY);
  1156. X        break;
  1157. X
  1158. X    case ARCHITECTURE:
  1159. X        data(header.architecture,sizeof(header.architecture),"ARCHITECTURE:",ARCHITECTURE);
  1160. X        break;
  1161. X
  1162. X    case VERSION_NUMBER:
  1163. X        data(header.version_number,sizeof(header.version_number),"VERSION_NUMBER:",VERSION_NUMBER);
  1164. X        break;
  1165. X
  1166. X    case ARCHIVE_:
  1167. X        data(header.archive,sizeof(header.archive),"ARCHIVE:",ARCHIVE_);
  1168. X    break;
  1169. X    }
  1170. X    return;
  1171. X}
  1172. END_OF_FILE
  1173. if test 26184 -ne `wc -c <'rkive/header.c'`; then
  1174.     echo shar: \"'rkive/header.c'\" unpacked with wrong size!
  1175. fi
  1176. # end of 'rkive/header.c'
  1177. fi
  1178. if test -f 'rkive/rkive.h' -a "${1}" != "-c" ; then 
  1179.   echo shar: Will not clobber existing file \"'rkive/rkive.h'\"
  1180. else
  1181. echo shar: Extracting \"'rkive/rkive.h'\" \(9824 characters\)
  1182. sed "s/^X//" >'rkive/rkive.h' <<'END_OF_FILE'
  1183. X/*
  1184. X**     @(#)rkive.h    2.2 2/23/91
  1185. X**
  1186. X**    This is the rkive source configuration header file. 
  1187. X**    Please examine and change to suite your own site's needs..
  1188. X**
  1189. X*/
  1190. X
  1191. X/*
  1192. X** The default owner, group and modes of the archived files
  1193. X** need to be stated below. The values are only used if the
  1194. X** appropriate values are not in the configuration file.
  1195. X*/ 
  1196. X
  1197. X#define OWNER    0
  1198. X#define GROUP    3
  1199. X#define MODES    0444
  1200. X#define DIR_MODE 0755         /* directory creation modes */
  1201. X
  1202. X/* 
  1203. X** If you have a smart mailer that supports a "-s subject" command
  1204. X** and you wish to have the subject line added when archived mail
  1205. X** is sent, define SUBJECT_LINE. 
  1206. X*/
  1207. X
  1208. X#define SUBJECT_LINE 
  1209. X
  1210. X#ifdef SUBJECT_LINE
  1211. X#define MAIL        "/usr/ucb/Mail"    /* mail program to use */
  1212. X# ifdef NOTDEF
  1213. X#  define MAIL        "/usr/local/bin/elm"
  1214. X#  define MAIL        "/usr/bin/mailx"      /* mail program to use */
  1215. X#  define MAIL        "/usr/local/bin/mush"
  1216. X# endif /*NOTDEF*/
  1217. X#else
  1218. X#define MAIL        "/bin/mail"     /* mail program to use */
  1219. X#endif
  1220. X
  1221. X/*
  1222. X** The PROBLEMS_DIR is the default directory to use in the event 
  1223. X** problems are encountered such as duplicate article names and 
  1224. X** the execution flags do not specify overwriting. 
  1225. X**
  1226. X** The new, inbound article is stored in the PROBLEMS_DIR in the 
  1227. X** problems_dir/newsgroup/volume/filename so that the administrator 
  1228. X** can review and fix the problem whenever time becomes available...
  1229. X**
  1230. X** The PROBLEMS_DIR define is used only if the administrator has not 
  1231. X** specified the PROBLEMS path variable inside of the LOCATION 
  1232. X** (config) file.
  1233. X*/
  1234. X
  1235. X#define PROBLEMS_DIR "/usenet/problems"  
  1236. X
  1237. X/* 
  1238. X** Home directory for news    
  1239. X*/
  1240. X
  1241. X#define SPOOLDIR     "/usr/spool/news"   
  1242. X
  1243. X/* 
  1244. X** Location of the default rkive configuration file.
  1245. X*/
  1246. X
  1247. X#define LOCATION     "/usr/local/lib/rkive/rkive.cf"  
  1248. X
  1249. X/*
  1250. X** Defines to control the handling of repostings.
  1251. X**
  1252. X** ADD_REPOST_SUFFIX && REPOST_SUFFIX
  1253. X**
  1254. X**     If ADD_REPOST_SUFFIX is defined, all reposts will have the 
  1255. X**     string specified in REPOST_SUFFIX appended to the archive
  1256. X**     filename so that a repost of elm/part07 would appear in
  1257. X**     the archive as elm/part07-repost prior to any compression.
  1258. X**
  1259. X**     CAUTION: This should *not* be used on a filesystem with
  1260. X**        14 character file name limits. If you are going
  1261. X**        to be making your archive available to the general
  1262. X**        community do *not* use this. The portability of
  1263. X**        filenames is greatly reduced. This has been added
  1264. X**        with much hesitation. The rational was that there
  1265. X**        was no reason to punish/limit the functionality
  1266. X**        just because of limitations of a specific "brand"
  1267. X**        of unix and since that "brand" was correcting its
  1268. X**        "error" in the future, why not put it in now ?
  1269. X**        This is not a configuration item on a per newsgroup
  1270. X**        basis. It might be useful for Historical archiving
  1271. X**        using only Volume/Issue archiving with no COMPRESSION.
  1272. X**
  1273. X** MV_ORIGINAL
  1274. X**     The original article is placed into a "original" directory in 
  1275. X**     the problems directory (if duplicated). The inbound reposted
  1276. X**     article is placed into the archive in the correct position.
  1277. X**
  1278. X** No Reposting Defines specified:
  1279. X**    The inbound article would be placed into the archive in the 
  1280. X**    correct position only if the initial article is not in the archive.
  1281. X**    Otherwise the reposted article is placed in the problems directory 
  1282. X**    as a normal duplicate article is now.
  1283. X*/
  1284. X
  1285. X/* #define ADD_REPOST_SUFFIX */
  1286. X#define MV_ORIGINAL 
  1287. X
  1288. X#ifdef ADD_REPOST_SUFFIX 
  1289. X#define REPOST_SUFFIX  "-repost" 
  1290. X#endif
  1291. X
  1292. X/* 
  1293. X** If you wish your volume directories to be Volume, VOL, vOLuMe
  1294. X** or any other such nonsense, change the VOLUME define below.
  1295. X*/
  1296. X
  1297. X#define VOLUME       "volume"
  1298. X
  1299. X/*
  1300. X** Very small change to construct change the volume directory names 
  1301. X** from "volume1" to "volume01". In this manner all of the archive
  1302. X** volume directories appear in lexical order instead of jumbled 
  1303. X** together in directory listings. This option was "requested"...
  1304. X*/
  1305. X
  1306. X/*#define ZEROFILL*/
  1307. X
  1308. X/* 
  1309. X** If you wish to have the headers "trimmed" when the file is archived,
  1310. X** assure that REDUCE_HEADERS is defined. Currenlty all header lines that
  1311. X** are not either;
  1312. X**    From:, Newsgroups:, Subject:, Message-ID: Approved:, and Date:
  1313. X** will be removed. See news_arc.c if you wish to add or subtract header
  1314. X** lines to keep. This can produce a savings of between 200 to 500 bytes
  1315. X** per archived article.
  1316. X*/
  1317. X
  1318. X#define REDUCE_HEADERS 
  1319. X
  1320. X/* 
  1321. X** The following define specifies a default format for generating
  1322. X** index file records in the event that there is no index format
  1323. X** specified for either the newsgroup or for the global default.
  1324. X** See article.1 for a discussion of the different types of selection
  1325. X** characters available for use in the format specifications.
  1326. X*/
  1327. X
  1328. X#define DEFAULT_INDEX_FORMAT       "%B\t%S"
  1329. X
  1330. X/* 
  1331. X** The following define specifies a default format for generating
  1332. X** log file records in the event that there is no log format
  1333. X** specified for either the newsgroup or for the global default.
  1334. X*/
  1335. X#define DEFAULT_LOG_FORMAT         "%O\t%T"
  1336. X
  1337. X/*
  1338. X** The size of the group array. If you are archiving the world
  1339. X** you might need to bump this up...
  1340. X*/
  1341. X
  1342. X#define NUM_NEWSGROUPS  32
  1343. X
  1344. X/**********************************************************************
  1345. X*******************  NO CHANGES REQUIRED PAST HERE  *******************
  1346. X**********************************************************************/
  1347. X
  1348. X/*
  1349. X** check to assure repost defines are in order...
  1350. X*/
  1351. X
  1352. X#if defined(ADD_REPOST_SUFFIX) + defined(MV_ORIGINAL) > 1
  1353. X#include "ERROR - Can only specify a maximum of one way to handle reposts!"
  1354. X#endif
  1355. X
  1356. X#include <dirent.h>
  1357. X
  1358. Xint fprintf();
  1359. X
  1360. X/*
  1361. X** Standard stuff
  1362. X*/
  1363. X
  1364. X#ifndef TRUE
  1365. X#define TRUE   1
  1366. X#endif
  1367. X
  1368. X#ifndef FALSE
  1369. X#define FALSE  0
  1370. X#endif
  1371. X
  1372. X/*
  1373. X** The MAXNAMLEN define is here for systems such as SCO
  1374. X** that have MAXNAMLEN in other then dirent.h
  1375. X**         Samuel Lam <uunet!van-bc!skl> 
  1376. X*/
  1377. X#ifndef MAXNAMLEN
  1378. X#define MAXNAMLEN  255
  1379. X#endif 
  1380. X
  1381. X/*
  1382. X** retrieve_article() return values
  1383. X*/
  1384. X#define ERROR_ENCOUNTERED -1
  1385. X#define DONE 0
  1386. X#define RETRIEVED 1
  1387. X
  1388. X/*
  1389. X** retrieve_article() from defines
  1390. X*/
  1391. X#define FROM_DISK       0
  1392. X#define FROM_NAME       1
  1393. X#define FROM_BATCHFILE  2
  1394. X#ifdef NNTP
  1395. X# define FROM_NNTP      3
  1396. X#endif /*NNTP*/
  1397. X
  1398. X/*
  1399. X** archive type defines 
  1400. X**
  1401. X** These defines are used to determine which type of archiving 
  1402. X** methods the administrator has requested for the newsgroup.
  1403. X**
  1404. X*/
  1405. X
  1406. X#define ARCHIVE_NAME     0    /* Archive as "elm/part03"  */
  1407. X                                /* and moderator info also. */
  1408. X#define VOLUME_ISSUE     1    /* Archive as "v16i003"     */
  1409. X#define ARTICLE_NUMBER   2    /* Archive with same name   */
  1410. X                /* as the file to archive   */
  1411. X#define CHRONOLOGICAL    3    /* Archive as "890619002"   */
  1412. X                                /* or YYMMDDIII format      */
  1413. X#define COMP_ARCHIVES    4    /* Archive for comp.archives*/
  1414. X#define EXTERNAL_COMMAND 5    /* Archive by piping the    */
  1415. X                                /* articles to the external */
  1416. X                                /* command specified int the*/
  1417. X                                /* rkive.cf file.           */
  1418. X#define ONLY_ARCHIVE_NAME 6    /* Archive as "elm/part03"  */
  1419. X
  1420. X#define MAXMATCHLEN   10000   /* Length for Match-expression. */
  1421. X
  1422. X
  1423. X/*
  1424. X** patch handling type defines 
  1425. X**
  1426. X** These defines are used to determine which type of 
  1427. X** method the administrator has requested for the the
  1428. X** handling of patches received in the newsgroup.
  1429. X**
  1430. X*/
  1431. X
  1432. X#define HISTORICAL   0        /* Archive as normally done.        */
  1433. X#define PACKAGE      1        /* Archive patches in the directory */
  1434. X                                /* containing the initial posting.  */
  1435. X
  1436. Xstruct group_archive {
  1437. X    int owner;                  /* owner id of the archive files     */
  1438. X    int group;                  /* group id of the archive files     */
  1439. X    int modes;                  /* modes of the stored archive files */
  1440. X    int type;                   /* Type of archiving to be used.     */
  1441. X                /*        0 = Archive-Name           */
  1442. X                                /*        1 = Volume-Issue           */
  1443. X                                /*        2 = Article-Number         */
  1444. X                                /*        3 = Chronological          */
  1445. X                                /*        4 = Comp-Archives          */
  1446. X                                /*        5 = External-Command       */
  1447. X    int patch_type;             /* Method of handling patches.       */
  1448. X                                /*        0 = Historical             */
  1449. X                                /*        1 = Package                */
  1450. X    char ng_name[MAXNAMLEN];    /* Newsgroup to be archived.         */
  1451. X    char ng_path[MAXNAMLEN];    /* Path to archive's base directory. */
  1452. X    char location[MAXNAMLEN];    /* Path to archive's base directory. */
  1453. X    char arc_done[MAXNAMLEN];    /* Archive's .archived already file  */
  1454. X    char mail_list[BUFSIZ];    /* List of users to mail when new    */
  1455. X                /* members are added to the archive. */
  1456. X    char logfile[MAXNAMLEN];    /* Path to archive specific log file */
  1457. X    char index[MAXNAMLEN];     /* Path to archive specific index.   */
  1458. X    char patchlog[MAXNAMLEN];    /* Path to archive's patches log.    */
  1459. X    char logformat[BUFSIZ];    /* Format of the logfile entry.      */
  1460. X    char indformat[BUFSIZ];    /* Format of the index entry.        */
  1461. X    char compress[MAXNAMLEN];    /* Command line to use to compress   */
  1462. X                /* new archive members, optional.    */
  1463. X    char arch_command[MAXNAMLEN]; /* Command line to use to archive  */
  1464. X                                  /* the articles in the newsgroup.    */
  1465. X    char checkhash[MAXNAMLEN];    /* Command line to use to test       */
  1466. X                /* articles for transit damage.      */
  1467. X    char match[MAXMATCHLEN];    /* Match-expression                  */
  1468. X#ifdef NNTP
  1469. X    char nntp[MAXNAMLEN];    /* Name of system with nntp server   */
  1470. X#endif /*NNTP*/
  1471. X};
  1472. END_OF_FILE
  1473. if test 9824 -ne `wc -c <'rkive/rkive.h'`; then
  1474.     echo shar: \"'rkive/rkive.h'\" unpacked with wrong size!
  1475. fi
  1476. # end of 'rkive/rkive.h'
  1477. fi
  1478. echo shar: End of archive 3 \(of 6\).
  1479. cp /dev/null ark3isdone
  1480. MISSING=""
  1481. for I in 1 2 3 4 5 6 ; do
  1482.     if test ! -f ark${I}isdone ; then
  1483.     MISSING="${MISSING} ${I}"
  1484.     fi
  1485. done
  1486. if test "${MISSING}" = "" ; then
  1487.     echo You have unpacked all 6 archives.
  1488.     rm -f ark[1-9]isdone
  1489. else
  1490.     echo You still need to unpack the following archives:
  1491.     echo "        " ${MISSING}
  1492. fi
  1493. ##  End of shell archive.
  1494. exit 0
  1495. exit 0 # Just in case...
  1496. -- 
  1497. Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
  1498. Sterling Software, IMD           UUCP:     uunet!sparky!kent
  1499. Phone:    (402) 291-8300         FAX:      (402) 291-4362
  1500. Please send comp.sources.misc-related mail to kent@uunet.uu.net.
  1501.