home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume17 / rkive / part01 next >
Internet Message Format  |  1991-02-24  |  59KB

  1. From: kent@sparky.imd.sterling.com (Kent Landfield)
  2. Newsgroups: comp.sources.misc
  3. Subject: v17i017:  rkive - Usenet sources archiver, Part01/06
  4. Message-ID: <1991Feb24.222443.26916@sparky.IMD.Sterling.COM>
  5. Date: 24 Feb 91 22:24:43 GMT
  6. Approved: kent@sparky.imd.sterling.com
  7. X-Checksum-Snefru: d5cc926c 7c64445d e7d6c411 76275ddb
  8.  
  9. Submitted-by: Kent Landfield <kent@sparky.imd.sterling.com>
  10. Posting-number: Volume 17, Issue 17
  11. Archive-name: rkive/part01
  12.  
  13.         RKIVE 2.0 && ARTICLE 2.0
  14.  
  15. The following are a few of the changes made between the previous
  16. versions of article and rkive and the 2.0 releases.
  17. ----
  18. Article and rkive now supports comp.archives auxiliary headers and
  19. archiving.
  20.  
  21. Article and rkive now supports comp.sources.apple2 format correctly.
  22.  
  23. Added compression recognition to Article so that it can deal
  24. transparently with compressed/packed files. There is no longer
  25. a need to "zcat filename | article".
  26.  
  27. Rkive can now accept articles on stdin.
  28.  
  29. Rkive is able to take the filename of articles to be archived
  30. from a batch file created from the news system.
  31.  
  32. Added NNTP support so that the archives can be maintained on a remote
  33. system(s) Now, an archive site can use multiple spool directories 
  34. located on multiple systems to assure timely update and better news 
  35. access reliability.
  36.  
  37. Rkive can use the X-Checksum-Snefru: header used in c.s.unix and 
  38. c.s.misc to verify the inbound article. The snefru utility is
  39. not supplied and is availble from your local c.s.u archives.
  40.  
  41. Added the ability to support globbing.  rkive now allows the user to
  42. specify a match string to search for in the newsgroup. When a match is
  43. found, that article is archive. Only articles that match the specific
  44. patterns are archived. This mechanism works for all the different types
  45. of archiving.
  46.  
  47. Added the ability for archive to execute external applications as
  48. if it was done internally. It logs and writes index files for these
  49. as specified in the rkive.cf configuration file.
  50.  
  51. Added the update_netdocs script and the appropriate entries in the 
  52. supplied rkive.cf. This script provides an _example_ of how the
  53. external archive mechanism works. It allows a site to maintain the
  54. the set of periodic postings that are specified in the rkive.cf and
  55. the update_netdocs. This script was a QUICK AND DIRTY EXAMPLE. It
  56. needs rewriting to be really used. Please don't flame me about this
  57. since it was just an example...
  58.  
  59. Added aditional format specifications to format.c so that the information
  60. contained in the rkive.cf file could be supplied to external commands
  61. for their specific use.
  62.  
  63. Added the ability for the person configuring the rkive.cf to specify
  64. where the .patchlog and .archived files are to reside. 
  65.  
  66. Options can be passed with the commands specified in rkive.cf.
  67. (e.g.  COMPRESS=compress -f)
  68.  
  69. Removed alot of duplicated code and added some more. :-)
  70.  
  71. Plus others I have forgotten...
  72.  
  73. I want to thank all the people who spent time sending me suggestions.
  74. I especially want to thank the people who took the time to beta test 
  75. this version for me.
  76.  
  77. Petri Ojala <ojala@finland.eu.net>
  78. Chris Myers <chris@wugate.wustl.edu>
  79. Neil Gorsuch <neil@cpd.com>
  80. Karl Lovink <karl@ofssrv.syssup.tds.philips.nl>
  81. David Schmidt <uunet!isc-br.isc-br.com!os-d!davids>
  82. Mark J. Bailey <uunet!mjbtn!mjb>
  83. Paul Vickers <paulv@logitek.co.uk>
  84. Ed Vielmetti <emv@ox.com>
  85. Heikki Suonsivu <hutcs.hut.fi!hsu>
  86.  
  87. Special thanks to Paul and Ed for showing me how dumb I really can be... :-)
  88. And to Heikki, who supplied the basis for the globbing functionality, I'll
  89. get that beer to you somehow... :-) :-) THANKS ALL!!!
  90.  
  91.             -Kent+
  92. ----
  93. #! /bin/sh
  94. # This is a shell archive.  Remove anything before this line, then feed it
  95. # into a shell via "sh file" or similar.  To overwrite existing files,
  96. # type "sh file -c".
  97. # The tool that generated this appeared in the comp.sources.unix newsgroup;
  98. # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
  99. # If this archive is complete, you will see the following message at the end:
  100. #        "End of archive 1 (of 6)."
  101. # Contents:  rkive rkive/news_arc.c rkive/port rkive/port/README.port
  102. #   rkive/rkive.cf
  103. # Wrapped by kent@sparky on Sun Feb 24 16:11:21 1991
  104. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  105. if test ! -d 'rkive' ; then
  106.     echo shar: Creating directory \"'rkive'\"
  107.     mkdir 'rkive'
  108. fi
  109. if test -f 'rkive/news_arc.c' -a "${1}" != "-c" ; then 
  110.   echo shar: Will not clobber existing file \"'rkive/news_arc.c'\"
  111. else
  112. echo shar: Extracting \"'rkive/news_arc.c'\" \(28314 characters\)
  113. sed "s/^X//" >'rkive/news_arc.c' <<'END_OF_FILE'
  114. X/*
  115. X** This software is Copyright (c) 1989, 1990, 1991 by Kent Landfield.
  116. X**
  117. X** Permission is hereby granted to copy, distribute or otherwise 
  118. X** use any part of this package as long as you do not try to make 
  119. X** money from it or pretend that you wrote it.  This copyright 
  120. X** notice must be maintained in any copy made.
  121. X**
  122. X*/
  123. X
  124. X#if !defined(lint) && !defined(SABER)
  125. Xstatic char SID[] = "@(#)news_arc.c    2.2 2/23/91";
  126. X#endif
  127. X
  128. X#include <sys/types.h>
  129. X#include <sys/stat.h>
  130. X#include <stdio.h>
  131. X#include <time.h>
  132. X#include <ctype.h>
  133. X#include "article.h"
  134. X#include "cfg.h"
  135. X
  136. X/*
  137. X** Defines for the type of "problems"
  138. X** encountered in saving the articles.
  139. X*/
  140. X#define DUP_PROB        0
  141. X#define NAME_PROB       1
  142. X#define VOL_PROB        2
  143. X#define TYPE_PROB    3
  144. X#define CHECKHASH_PROB  4
  145. X#define MSNG_HASH_PROB  5
  146. X#define CA_NAME_PROB    6
  147. X#define EXTERNAL_PROB   7
  148. X
  149. Xint test = 0;
  150. Xint inum = 0;
  151. Xint problem_article;
  152. X
  153. Xextern struct group_archive *newsgrp;
  154. Xextern int overwrite;
  155. X
  156. Xint  fclose();
  157. Xint  stat();
  158. Xint unlink();
  159. Xint  do_checkhash();
  160. Xint  remove_suffix();
  161. Xchar *strchr();
  162. Xchar *strcpy();
  163. Xchar *strcat();
  164. Xchar *do_problem();
  165. Xchar *basename();
  166. Xchar *suffix();
  167. Xchar *expand_name();
  168. Xchar *copy_article();
  169. XFILE *efopen();
  170. Xvoid init_article();
  171. Xvoid store_line();
  172. Xvoid dump_article();
  173. Xvoid record_problem();
  174. X
  175. Xvoid get_header(filename)
  176. X    char *filename;
  177. X{
  178. X    char *dp;
  179. X    int header_ok = 0;
  180. X    int last = TEXT;
  181. X    FILE *gfp;
  182. X
  183. X    init_article();
  184. X
  185. X    gfp = efopen(filename,"r");
  186. X
  187. X    (void) strcpy(article.newsarticle, filename);
  188. X
  189. X    while (fgets(s,sizeof s,gfp) != NULL) {
  190. X        if (debug)
  191. X            (void) fprintf(logfp, "BUF = [%s]",s);
  192. X
  193. X        if (!isalpha(*s) || (strchr(s,':') == NULL)) {
  194. X           header_ok++;
  195. X           if (header_ok >= 2) {
  196. X               if (*s == '\n' && last == BLANK)
  197. X                   continue;
  198. X               break;
  199. X           }
  200. X           if (*s == '\n')
  201. X              last = BLANK;
  202. X           else 
  203. X              last = TEXT;
  204. X           continue;
  205. X        }
  206. X
  207. X        last = TEXT;
  208. X        dp = s;
  209. X        while (*++dp)
  210. X           if (*dp == '\n')
  211. X               *dp = '\0';
  212. X
  213. X        store_line();
  214. X    }
  215. X    (void) fclose(gfp);
  216. X
  217. X    if (debug)
  218. X        dump_article();
  219. X}
  220. X
  221. X#ifdef REDUCE_HEADERS
  222. X
  223. Xstruct hdrstokeep {
  224. X    char     *ststr;
  225. X    int    stbytes;
  226. X};
  227. X
  228. Xstruct hdrstokeep hdrs[] = {
  229. X{    "From:",        (sizeof "From:")        },
  230. X{    "Newsgroups:",        (sizeof "Newsgroups:")        },
  231. X{    "Subject:",        (sizeof "Subject:")        },
  232. X{    "Message-ID:",        (sizeof "Message-ID:")        },
  233. X{    "Date:",        (sizeof "Date:")        },
  234. X{    "Approved:",        (sizeof "Approved:")        },
  235. X{    "X-Checksum-Snefru:",    (sizeof "X-Checksum-Snefru:")    },
  236. X{    NULL,            0                },
  237. X};
  238. X
  239. Xint keep_line(argstr)
  240. X    char *argstr;
  241. X {
  242. X    int strncmp();
  243. X
  244. X    struct hdrstokeep *pt;
  245. X
  246. X    pt = &hdrs[0];
  247. X    while ((pt->ststr) != NULL) {
  248. X        if (strncmp(argstr, pt->ststr, (pt->stbytes-1)) == 0) 
  249. X            return(TRUE);
  250. X        pt++;
  251. X    }
  252. X    return(FALSE);
  253. X}
  254. X#endif /* REDUCE_HEADERS */
  255. X
  256. Xint copy(source, target)
  257. X    char *source, *target;
  258. X{
  259. X    char *strchr();
  260. X    int fputs();
  261. X
  262. X    FILE *from, *to;
  263. X    char fbuf[BUFSIZ];
  264. X
  265. X#ifdef REDUCE_HEADERS
  266. X    int inheader;
  267. X
  268. X    inheader = TRUE;  
  269. X#endif /* REDUCE_HEADERS */
  270. X
  271. X    if (verbose) {
  272. X        (void) fprintf(logfp,"archive <%s> to <%s>\n",source,target);
  273. X        if (test) 
  274. X            return(0);
  275. X    }
  276. X    if ((from = fopen(source, "r")) == NULL) {
  277. X        (void) fprintf(errfp,"%s: cannot open %s\n",progname,source);
  278. X        return (-1);
  279. X    }
  280. X    if ((to = fopen(target, "w")) == NULL) {
  281. X        (void) fclose(from);
  282. X        (void) fprintf(errfp,"%s: cannot create %s\n",progname,target);
  283. X        return (-1);
  284. X    }
  285. X
  286. X    while (fgets(fbuf, BUFSIZ, from) != NULL) {
  287. X#ifdef REDUCE_HEADERS
  288. X        /*
  289. X        ** Read the source and do not print any headers 
  290. X        ** unless specified in the "keep" headers table.
  291. X        */
  292. X        if (inheader) {
  293. X            /* 
  294. X            ** Have I encountered a line without a line type ? 
  295. X            */
  296. X            if (!isalpha(*fbuf) || (strchr(fbuf,':') == NULL)) 
  297. X                inheader = FALSE;
  298. X
  299. X            else {
  300. X                /*
  301. X                ** Determine the type of the header line and 
  302. X                ** decide if this is a line to be kept or pitched.
  303. X                */
  304. X                if (!keep_line(fbuf))
  305. X                    continue;
  306. X            }
  307. X        }
  308. X#endif /* REDUCE_HEADERS */
  309. X        if (fputs(fbuf, to) == EOF) {
  310. X            (void) unlink(target);
  311. X            (void) fclose(from);
  312. X            (void) fclose(to);
  313. X            (void) fprintf(errfp,"%s: bad copy to %s\n",progname,target);
  314. X            return (-1);
  315. X        }
  316. X    }
  317. X    (void) fclose(from);
  318. X    (void) fclose(to);
  319. X    return(0);
  320. X}
  321. X
  322. X/*
  323. X** mkparents:
  324. X**
  325. X** If any parent directories in 
  326. X** fullname don't exist, create them.
  327. X*/
  328. X
  329. Xint mkparents(fullname)
  330. Xchar *fullname;
  331. X{
  332. X    int access();
  333. X    int makedir();
  334. X    char *strrchr();
  335. X
  336. X    register char *p;
  337. X    char b[MAXNAMLEN];
  338. X    int rc;
  339. X
  340. X    (void) strcpy(b, fullname);
  341. X
  342. X    if ((p = strrchr(b, '/')) != NULL) 
  343. X            *p = '\0';
  344. X    else                  /* no directories in fullname */
  345. X       return(0);
  346. X
  347. X    if (*b == '\0')           /* are we at the root ? */
  348. X        return(0);
  349. X
  350. X    if (access(b, 0) == 0)
  351. X        return(0);
  352. X
  353. X    if (mkparents(b) == -1)
  354. X        return(-1);
  355. X
  356. X    if ((rc = makedir(b, DIR_MODE, newsgrp->owner, newsgrp->group)) != 0) 
  357. X        record_problem("makedir failed attempting to make %O", b, newsgrp);
  358. X
  359. X    return(rc);
  360. X}
  361. X
  362. Xchar *copy_article(ng, filename,path)
  363. Xstruct group_archive *ng;
  364. Xchar *filename;
  365. Xchar *path;
  366. X{
  367. X    void write_archived();
  368. X    void write_patch_log();
  369. X
  370. X    if (copy(filename,path) != 0) {  
  371. X        (void) fprintf(errfp,"copy failed for %s to %s\n",filename,path);
  372. X        return(NULL);
  373. X    }  
  374. X
  375. X    /* 
  376. X    ** Write the message-id to the .archived file in the newsgroup's
  377. X    ** BASEDIR directory since we do not want it rearchived tomorrow.
  378. X    */
  379. X    write_archived(header.ident, path);
  380. X
  381. X    /*
  382. X    ** Check if the file is a patch. If so, log
  383. X    ** the patch information into the patch log
  384. X    ** in a *non-configurable* format so that
  385. X    ** applications can be written to access the
  386. X    ** file's "known format".
  387. X    */
  388. X
  389. X    if (article.rectype == PATCH)
  390. X        write_patch_log(ng,path);
  391. X
  392. X    /*
  393. X    ** Return the path to the archived file.
  394. X    */
  395. X    return(path);
  396. X}
  397. X
  398. Xchar *save_article (filename,ng)
  399. Xchar *filename;
  400. Xstruct group_archive *ng;
  401. X{
  402. X    char *format_output();
  403. X    void check_archive_name();
  404. X    void chronpath();
  405. X
  406. X    char *final_path;
  407. X    char *kp;
  408. X
  409. X    char cmdline[BUFSIZ];
  410. X    char command[BUFSIZ];
  411. X    static char path[MAXNAMLEN];
  412. X    struct stat sb;
  413. X
  414. X    problem_article = FALSE;
  415. X    path[0] = '\0';
  416. X
  417. X    /*
  418. X    ** The news article has been read and the header
  419. X    ** information is filled into the appropriate
  420. X    ** data structures.
  421. X    */
  422. X
  423. X    /*
  424. X    ** If the Snefru header exists, check the article checksum for validity.
  425. X    */
  426. X    if (header.x_checksum_snefru[0]) {
  427. X    if (*(ng->checkhash)) {
  428. X        if (do_checkhash(ng->checkhash, filename) != 0)
  429. X        return(do_problem(CHECKHASH_PROB,ng,filename,path));
  430. X    }
  431. X    else if(*checkhash) {
  432. X        if (do_checkhash(checkhash, filename) != 0)
  433. X        return(do_problem(CHECKHASH_PROB,ng,filename,path));
  434. X    }
  435. X    }
  436. X    else {
  437. X    if (*(ng->checkhash) || *checkhash)
  438. X        return(do_problem(MSNG_HASH_PROB,ng,filename,path));
  439. X    }
  440. X
  441. X    /*
  442. X    ** Build the path string for the final resting spot
  443. X    ** for the new archive member.
  444. X    */
  445. X    switch(ng->type) {
  446. X    case ARCHIVE_NAME:
  447. X            /*
  448. X            ** The header's archive_name contains the filename in
  449. X            ** an "elm/part06" format.
  450. X            */
  451. X
  452. X            if ((article.volume == -1) || (!header.archive_name[0])) {
  453. X                /* 
  454. X                ** If the posting is an administration (ADM) posting
  455. X        ** then create a valid Archive-Name:. In other words,
  456. X                ** cheat bigtime... c.s.apple2 uses these headers and does 
  457. X        ** not put in any auxiliary headers. They should be pitched
  458. X        ** in that newsgroup, according to Jonathan, but I like to
  459. X        ** keep a copy of everything that goes through the newsgroup.
  460. X        ** The history thing ya know.. :-)
  461. X                */
  462. X                if (article.rectype == ADMINISTRATION)
  463. X                    (void) sprintf(header.archive_name,".admin/ADM%d",article.issue);
  464. X                else
  465. X                    return(do_problem(NAME_PROB, ng,filename,path));
  466. X            }
  467. X            /*
  468. X            ** Assure the address is relative and
  469. X            ** that some prankster can not do nasty
  470. X            ** things to your system files by having
  471. X            ** an Archive-name line like:
  472. X            **    ../../../../../etc/passwd
  473. X            */
  474. X
  475. X            check_archive_name(header.archive_name);
  476. X
  477. X            /* 
  478. X            ** Check to see if the article is a patch. If so,
  479. X            ** check to see if the administrator wishes to
  480. X            ** store the patch with the initially posted
  481. X            ** articles. This really relys on the archive name
  482. X            ** being correct.
  483. X            */
  484. X            
  485. X            if (article.rectype == PATCH && ng->patch_type == PACKAGE)
  486. X                /*
  487. X                ** Store the patch in the volume specified with the
  488. X                ** Archive-name: specified file name.
  489. X                */
  490. X#ifdef ZEROFILL
  491. X                (void) sprintf(path,"%s/%s%.02d/%s", ng->location, VOLUME,
  492. X#else
  493. X                (void) sprintf(path,"%s/%s%d/%s", ng->location, VOLUME,
  494. X#endif 
  495. X                    article.patch_volume, header.archive_name);
  496. X
  497. X            else 
  498. X#ifdef ZEROFILL
  499. X                (void) sprintf(path,"%s/%s%.02d/%s", ng->location, VOLUME,
  500. X#else
  501. X                (void) sprintf(path,"%s/%s%d/%s", ng->location, VOLUME,
  502. X#endif 
  503. X                article.volume, header.archive_name);
  504. X            break;
  505. X    case VOLUME_ISSUE:
  506. X            /*
  507. X            ** The article filename contains the filename in
  508. X            ** a "v01i001" format.
  509. X            */
  510. X            if ((article.volume == -1) || (!article.filename[0])) 
  511. X                return(do_problem(VOL_PROB,ng,filename,path));
  512. X
  513. X#ifdef ZEROFILL
  514. X            (void) sprintf(path,"%s/%s%.02d/%s", ng->location, VOLUME,
  515. X#else
  516. X            (void) sprintf(path,"%s/%s%d/%s", ng->location, VOLUME,
  517. X#endif
  518. X                article.volume, article.filename);
  519. X            break;
  520. X    case ARTICLE_NUMBER:
  521. X            /*
  522. X            ** Store in same filename - thanks news...
  523. X            */
  524. X            (void) sprintf(path,"%s/%s", ng->location, filename);
  525. X            break;
  526. X    case CHRONOLOGICAL:
  527. X            /*
  528. X            ** The chronpath() is called to create a path for an article
  529. X            ** to be stored in chronological ordering. We need to be sure
  530. X            ** that the issue number is not in use. This is necessary to
  531. X            ** handle multiple runs of the program on the same day.
  532. X            **
  533. X            ** The idea here is to have the program check to see if the
  534. X            ** issue number to be used is available. 
  535. X            ** There should be no duplicates here ever... :-)
  536. X            ** [ just don't blow away your .archived file... :-( ]
  537. X            */
  538. X            do {
  539. X                ++inum;
  540. X        chronpath(ng->location, path, inum);
  541. X            } while (stat(path ,&sb) == 0); 
  542. X            break;
  543. X    case ONLY_ARCHIVE_NAME:
  544. X            /*
  545. X            ** This is for searching for articles with an Archive-name:
  546. X            ** no other information.  The header's archive_name contains 
  547. X            ** the filename in an "elm/part06" format.
  548. X            */
  549. X            if (!header.archive_name[0])
  550. X                return(NULL);
  551. X    
  552. X            /*
  553. X            ** Assure the address is relative and that some prankster can 
  554. X            ** not do nasty things to your system files by having an 
  555. X            ** Archive-name line like:
  556. X            **    ../../../../../etc/passwd
  557. X            */
  558. X            check_archive_name(header.archive_name);
  559. X
  560. X            (void) sprintf(path,"%s/%s",ng->location,header.archive_name);
  561. X            break;
  562. X    case COMP_ARCHIVES:
  563. X            /*
  564. X            ** Comp.archives supplies an Archive-name: but no volume
  565. X            ** so it has to be treated as an separate type of archiving.
  566. X            ** It could have been squeezed into ARCHIVE-NAME but that
  567. X            ** does not allow for easy changes in the future for either.
  568. X            **
  569. X            ** The header's archive_name contains the filename in
  570. X            ** an "elm/part06" format.
  571. X            */
  572. X
  573. X            if (!header.archive_name[0])
  574. X                return(do_problem(CA_NAME_PROB, ng,filename,path));
  575. X    
  576. X            /*
  577. X            ** Assure the address is relative and
  578. X            ** that some prankster can not do nasty
  579. X            ** things to your system files by having
  580. X            ** an Archive-name line like:
  581. X            **    ../../../../../etc/passwd
  582. X            */
  583. X
  584. X            check_archive_name(header.archive_name);
  585. X
  586. X            (void) sprintf(path,"%s/%s",ng->location,header.archive_name);
  587. X            break;
  588. X     case EXTERNAL_COMMAND:
  589. X            /*
  590. X            ** This type of archiving is being handled by a script/application
  591. X            ** outside of the rkive program. In this situation, rkive is being
  592. X            ** used to locate the articles to be archived, pipe the information
  593. X            ** about the article to the external command to process and wait for
  594. X            ** a success/failure status to be returned.  At that point, rkive
  595. X            ** logs the status. Compression is bypassed regardless of whether or
  596. X            ** not it is specified. Index records are written with the info as
  597. X            ** specified by the format. This means that the external command 
  598. X            ** will have to know about duplicates, reposts and compression. The
  599. X            ** execution command string will be expanded to see if the external 
  600. X            ** command specified in the rkive.cf file has any parameters to be 
  601. X            ** filled in...
  602. X            */ 
  603. X
  604. X            /*
  605. X            ** Need to build a path to the archive location if there was one.
  606. X            ** Just using Article-Number for the file name. If there is a better
  607. X            ** idea here, I am all ears... 
  608. X            */
  609. X            (void) sprintf(path,"%s/%s", ng->location, filename);
  610. X
  611. X            /* 
  612. X            ** Make any required parent directories along the way.
  613. X            ** Done so that the external applications will have a
  614. X            ** base directory in which to perform there "thing".
  615. X            */
  616. X            if (mkparents(path) == -1)
  617. X                return(NULL);
  618. X
  619. X            /*
  620. X            ** Expand and build the command line to execute.
  621. X            ** The file to be archived will always be the first command line 
  622. X            ** argument regardless of what is supplied in the ARCHIVE_CMD line.
  623. X            **
  624. X            ** First separate the command from the options.
  625. X            **    If a space is found after the cmdline is striped put a
  626. X            **    null there and then replace it with a space after the check...
  627. X            ** Rebuild the command string.
  628. X            */
  629. X
  630. X            if (*ng->arch_command) 
  631. X                (void) strcpy(command, ng->arch_command);
  632. X            else if (*arch_command) 
  633. X                (void) strcpy(command, ng->arch_command);
  634. X            else
  635. X                return(do_problem(EXTERNAL_PROB,ng,filename,path));
  636. X            
  637. X            if ((kp = strchr(command,' ')) != NULL)
  638. X                *kp = '\0';
  639. X
  640. X            (void) sprintf(cmdline,"%s %s/%s/%s", 
  641. X                     command, spooldir, newsgrp->ng_path, filename);
  642. X
  643. X            if (kp != NULL) {  /* There are options to be stored... */
  644. X                *kp = ' ';
  645. X                (void) strcat(cmdline,kp);
  646. X            }
  647. X            
  648. X            kp = format_output(cmdline, filename, ARCHIVE);
  649. X
  650. X            /* 
  651. X            ** Execute the command and wait for a completion status.
  652. X            ** If a problem exists then alert the administrator to the problem
  653. X            */
  654. X
  655. X            if (verbose)
  656. X                (void) fprintf(logfp,"executing <%s>\n",kp);
  657. X
  658. X            if (!test) {
  659. X                if (system(kp) != 0)
  660. X                    return(do_problem(EXTERNAL_PROB,ng,filename,path));
  661. X            }
  662. X
  663. X
  664. X            /*
  665. X             ** Write the message-id to the .archived file in the newsgroup's
  666. X             ** BASEDIR directory since we do not want it rearchived tomorrow.
  667. X             */
  668. X             write_archived(header.ident, path);
  669. X
  670. X             /*
  671. X             ** Check if the file is a patch. If so, log
  672. X             ** the patch information into the patch log
  673. X             ** in a *non-configurable* format so that
  674. X             ** applications can be written to access the
  675. X             ** file's "known format".
  676. X             */
  677. X
  678. X             if (article.rectype == PATCH)
  679. X                 write_patch_log(ng,path);
  680. X
  681. X             /*
  682. X             ** Return the path to the archived file.
  683. X             */
  684. X             return(path);
  685. X            
  686. X    default:
  687. X            /*
  688. X            ** We have got problems....
  689. X            */
  690. X            return(do_problem(TYPE_PROB,ng,filename,path));
  691. X    }
  692. X
  693. X#ifdef ADD_REPOST_SUFFIX
  694. X    if (article.repost == TRUE)
  695. X        /*
  696. X        ** The ADD_REPOST_SUFFIX code adds the REPOST_SUFFIX
  697. X    ** to any file that has been indicated as a repost
  698. X    ** by the moderator. This should not be used with 
  699. X    ** Archive-Name archiving on a filesystem with 14
  700. X    ** character filename limits or filename truncation
  701. X    ** can occur. You have been warned... :-(
  702. X    **
  703. X     ** After adding the REPOST_SUFFIX, the filename is
  704. X    ** treated as any other file with the duplication
  705. X    ** checks and all...
  706. X    */
  707. X    (void) strcat(path,REPOST_SUFFIX);
  708. X#endif /* ADD_REPOST_SUFFIX */
  709. X
  710. X    /* 
  711. X    ** expand the path to the file to include the 
  712. X    ** compression suffix if necessary.
  713. X    */
  714. X
  715. X    final_path = expand_name(path, ng);
  716. X
  717. X    /*
  718. X    ** Make any necessary directories 
  719. X    ** along the way. 
  720. X    */
  721. X    if (mkparents(path) == -1)
  722. X        return(NULL);
  723. X
  724. X    /*
  725. X    ** Check to assure that there is not already 
  726. X    ** a file with the same file name. If so
  727. X    ** copy (or archive) the file to the problems 
  728. X    ** directory. 
  729. X    **
  730. X    ** This works for REPOSTS as well.
  731. X    ** If the REPOST arrives and there is
  732. X    ** no file currently at the archive location, the
  733. X    ** REPOST is installed in the correct archive 
  734. X    ** location.
  735. X    ** If there is a file that exists when a REPOST
  736. X    ** arrives, the REPOST is then handled in do_problem().
  737. X    */
  738. X
  739. X    if ((stat(final_path ,&sb) == 0) && !overwrite)  /* duplicate found */
  740. X        return(do_problem(DUP_PROB,ng, filename, final_path));
  741. X
  742. X    return(copy_article(ng, filename, path));
  743. X}
  744. X
  745. X
  746. Xchar *do_problem(type_of_problem, ng, file, path)
  747. Xint type_of_problem;
  748. Xstruct group_archive *ng;
  749. Xchar *file;
  750. Xchar *path;
  751. X{
  752. X    void set_ownership();
  753. X
  754. X#ifdef MV_ORIGINAL
  755. X    char crnt_path[MAXNAMLEN];
  756. X#endif /*MV_ORIGINAL */
  757. X
  758. X    char pmess[BUFSIZ];
  759. X    int nm;
  760. X    struct stat sb;
  761. X
  762. X    problem_article = TRUE;
  763. X
  764. X    /* ALERT THE ADMINISTRATOR THAT A PROBLEM WAS ENCOUNTERED 
  765. X    **
  766. X    ** A problem has been encountered. It could be that there is an
  767. X    ** format mismatch or there is already a file with the same 
  768. X    ** issue/archive/msg-id name.
  769. X    ** Copy the problem file to the problems directory. 
  770. X    ** Alert the Administrator that a problem was received.
  771. X    */
  772. X    
  773. X    (void) sprintf(pmess,"PROBLEM: Article %s in %s ",file,ng->ng_name);
  774. X
  775. X    switch( type_of_problem ) {
  776. X       case NAME_PROB:
  777. X          (void) strcat(pmess,"does not support Archive-Name Archiving.\n");
  778. X          break;
  779. X       case VOL_PROB:
  780. X          (void) strcat(pmess,"does not support Volume-Issue Archiving.\n");
  781. X          break;
  782. X       case TYPE_PROB:
  783. X          (void) strcat(pmess,"has an invalid archive TYPE specified.\n");
  784. X          break;
  785. X       case CHECKHASH_PROB:
  786. X          (void) strcat(pmess,"failed Snefru checkhash test.\n");
  787. X          break;
  788. X       case MSNG_HASH_PROB:
  789. X          (void) strcat(pmess,"is missing expected Snefru header.\n");
  790. X          break;
  791. X       case DUP_PROB:
  792. X          if (article.repost != TRUE) 
  793. X              (void) strcat(pmess,"is a Duplicate article.\n");
  794. X          else 
  795. X             (void) strcat(pmess,"is a Reposted article.\n");
  796. X          (void) sprintf(pmess,"%s\tExisting Archived path - %s", pmess,path);
  797. X          break;
  798. X       case CA_NAME_PROB:
  799. X          (void)strcat(pmess,"does not have a valid Archive-name specified.\n");
  800. X          break;
  801. X       case EXTERNAL_PROB:
  802. X          (void)strcat(pmess,"System of External command returned Non-zero value...\n");
  803. X    }
  804. X
  805. X    /* print the message out to the screen, crontab output, etc */
  806. X
  807. X    (void) fprintf(errfp,"%s\n",pmess);
  808. X
  809. X    /* log the initial detection message. */
  810. X
  811. X    record_problem(pmess, file, ng);
  812. X
  813. X    /* Handling Repostings.
  814. X    **
  815. X    ** MV_ORIGINAL
  816. X    **     The original article is placed into a "original" directory in 
  817. X    **     the problems directory (if duplicated). The inbound reposted
  818. X    **     article is placed into the archive in the correct position.
  819. X    **
  820. X    ** ADD_REPOST_SUFFIX 
  821. X    **     If ADD_REPOST_SUFFIX is defined, all reposts will have the 
  822. X    **     string specified in REPOST_SUFFIX appended to the archive
  823. X    **     filename so that a repost of elm/part07 would appear in
  824. X    **     the archive as elm/part07-repost prior to any compression.
  825. X    **     The addition of the suffix was done in save_article().
  826. X    **     Handle this as the true duplicated article that it is.
  827. X    **
  828. X    ** No Reposting Defines specified:
  829. X    **    The inbound article would be placed into the archive in the 
  830. X    **    correct position only if the initial article is not in the archive.
  831. X    **    Otherwise the reposted article is placed in the problems directory 
  832. X    **    as a normal duplicate article as it is now.
  833. X    */
  834. X
  835. X#ifdef MV_ORIGINAL
  836. X    if ((article.repost == TRUE) && (ng->type != EXTERNAL_COMMAND)) {
  837. X        /*
  838. X        ** save the duplicated path 
  839. X        ** Caution: may have compression suffix attached
  840. X        */
  841. X        (void) strcpy(crnt_path, path);
  842. X
  843. X        /* create the storage path for original copy */
  844. X        /* no slash needed between Originals and crnt_path below.. */
  845. X
  846. X        (void) sprintf(path,"%s/%s%s",problems_dir,"Originals",crnt_path);
  847. X
  848. X        /* Display and record the actions */ 
  849. X        (void) sprintf(pmess,"\tMoving %s (original)\n\tto %s",crnt_path,path);
  850. X        (void) fprintf(errfp,"%s\n",pmess);
  851. X        record_problem(pmess, file, ng);
  852. X
  853. X        /* Make any necessary directories along the way. */
  854. X        if (mkparents(path) == -1)
  855. X            return(NULL);
  856. X
  857. X        /* copy the original out of the way */
  858. X        if (copy(crnt_path,path) != 0) {
  859. X            (void) fprintf(errfp,"copy failed for %s to %s\n", crnt_path, path);
  860. X            return(NULL);
  861. X        }
  862. X
  863. X        set_ownership(path, path, ng);
  864. X
  865. X        /* restore the destination path for inbound article */
  866. X        (void) strcpy(path,crnt_path);
  867. X
  868. X        /* remove the existing file */
  869. X        (void) unlink(path);
  870. X        /*
  871. X        ** Must assure that "path" does not have a .Z type
  872. X        ** of suffix used in compression. If it does, it must 
  873. X    ** be removed before continuing. This is cheating and
  874. X        ** will probably break but what the hell.
  875. X        */
  876. X        (void) remove_suffix(path);
  877. X    }
  878. X    else 
  879. X
  880. X#endif /* MV_ORIGINAL */
  881. X
  882. X    /*
  883. X    ** Build the path string for the location of the article in 
  884. X    ** the problems directory. Place the file in the appropriate 
  885. X    ** directory in Article-Number format. First check to see if
  886. X    ** that Article-Number named file does not exist. This extra 
  887. X    ** check is being done to assure that no conflict exists for
  888. X    ** NNTP sites.  In this manner problems will be assured to
  889. X    ** be stored as uniquely named, separate files. 
  890. X    */
  891. X
  892. X    (void) sprintf(path,"%s/%s/%s",problems_dir,ng->ng_path,file);
  893. X
  894. X    nm = 1;
  895. X
  896. X    while (stat(path, &sb) == 0) {
  897. X         (void) sprintf(path,"%s/%s/%s.%d",problems_dir,ng->ng_path,file,nm);
  898. X         ++nm;
  899. X    }
  900. X
  901. X    /* Display and record the actions */ 
  902. X    (void) sprintf(pmess,"\tStoring Article %s at %s\n", file, path);
  903. X    (void) fprintf(errfp,"%s\n",pmess);
  904. X    record_problem(pmess, file, ng);
  905. X
  906. X    /* Make any necessary directories along the way. */
  907. X    if (mkparents(path) == -1)
  908. X        return(NULL);
  909. X
  910. X    return(copy_article(ng, file, path));
  911. X}
  912. X
  913. X
  914. X#ifndef NO_MONTH_DIR
  915. Xstatic char *month[] = {    
  916. X    "Jan", "Feb", "Mar", "Apr", "May", "Jun", 
  917. X    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" 
  918. X};
  919. X#endif /* NO_MONTH_DIR */
  920. X
  921. Xvoid chronpath(dirloc, path, seqnum)
  922. X    char *dirloc;
  923. X    char *path;
  924. X    int seqnum;
  925. X{
  926. X    long time();
  927. X    struct tm *localtime();
  928. X
  929. X    long clk;
  930. X    struct tm *crnt;
  931. X    static struct tm now;
  932. X    static int no_time = 1;
  933. X
  934. X    if (no_time) {
  935. X       clk = time((long *)0);
  936. X       crnt = localtime(&clk); 
  937. X       no_time = 0;
  938. X       now = *crnt;
  939. X    }
  940. X#ifdef NO_MONTH_DIR
  941. X    /*
  942. X    ** Format:
  943. X    **     /usenet/alt/sources/volume89/890629.01
  944. X    */
  945. X# ifdef ZEROFILL
  946. X    (void) sprintf(path,"%s/%s%.02d/%.02d%.02d%.02d.%.02d",dirloc, 
  947. X# else
  948. X    (void) sprintf(path,"%s/%s%d/%.02d%.02d%.02d.%.02d",dirloc, 
  949. X# endif
  950. X                     VOLUME, now.tm_year,
  951. X                     now.tm_year,now.tm_mon+1,now.tm_mday,seqnum);
  952. X#else /*!NO_MONTH_DIR*/
  953. X    /*
  954. X    ** Format:
  955. X    **     /usenet/alt/sources/volume89/Jun/890629.01
  956. X    */
  957. X# ifdef ZEROFILL
  958. X    (void) sprintf(path,"%s/%s%.02d/%s/%.02d%.02d%.02d.%.02d",dirloc, 
  959. X# else
  960. X    (void) sprintf(path,"%s/%s%d/%s/%.02d%.02d%.02d.%.02d",dirloc, 
  961. X# endif
  962. X                     VOLUME, now.tm_year, month[now.tm_mon],
  963. X                     now.tm_year,now.tm_mon+1,now.tm_mday,seqnum);
  964. X#endif /* NO_MONTH_DIR */
  965. X}
  966. X
  967. Xvoid write_patch_log(ng, path)
  968. X    struct group_archive *ng;
  969. X    char *path;
  970. X{
  971. X    int strlen();
  972. X
  973. X    char *sp;
  974. X    FILE *plfp;
  975. X    struct stat sb;
  976. X
  977. X    if (test)
  978. X        return;
  979. X
  980. X    /* 
  981. X    ** The .patchlog file is used to record the
  982. X    ** information specific to patches that come
  983. X    ** through the newsgroup.
  984. X    **
  985. X    ** The format of the .patchlog file is:
  986. X    ** #
  987. X    ** #    Patch log for comp.sources.whatever
  988. X    ** #
  989. X    ** # Path To                   Patch       Package     Initial
  990. X    ** # Patchfile             Volume  Issue     Name   Volume   Issue
  991. X    ** #
  992. X    ** volume4/conquer4/Part04    6     86    conquer4     4      42-49
  993. X    ** volume4/conquer4/Part06    6     88    tests3       4      42,47,51
  994. X    ** volume6/conquer4/Part07    6     89    Unknown      6      89
  995. X    */
  996. X
  997. X    /*
  998. X    ** If this is the first time that an entry is written to the
  999. X    ** patch log, add a header on top of the file for informational
  1000. X    ** purposes only... Output in the patch log is not intended
  1001. X    ** to be centered under these columns... :-) I'm laaaazy.
  1002. X    */
  1003. X    if ((stat(ng->patchlog ,&sb) != 0)) {
  1004. X        if (mkparents(path) == -1) 
  1005. X            return;          /* unable to build parent directories */
  1006. X
  1007. X        plfp = efopen(ng->patchlog,"a+");
  1008. X
  1009. X        (void) fprintf(plfp,"#\n#\tPatch log for %s\n#\n", ng->ng_name);
  1010. X
  1011. X        (void) fprintf(plfp,"# %-27s%-12s%-15s%-s\n", 
  1012. X                    "Path To", "Patch", "Package", "Initial");
  1013. X
  1014. X        (void) fprintf(plfp,"# %-22s%-18s%-10s%-15s\n#\n", 
  1015. X                    "Patchfile", "Volume  Issue", "Name",
  1016. X                    "Volume  Issue");
  1017. X        (void) fclose(plfp);
  1018. X    }
  1019. X
  1020. X    /* 
  1021. X    ** Get rid of the base directory.
  1022. X    */
  1023. X    sp = path + (strlen(ng->location)+1);
  1024. X
  1025. X    plfp = efopen(ng->patchlog,"a+");
  1026. X    (void) fprintf(plfp,"%-25s %3d   %5d  %-14s  %3d  %s\n", sp,
  1027. X            article.volume, article.issue, article.package_name,
  1028. X            article.patch_volume, article.patch_issue);
  1029. X    (void) fclose(plfp);
  1030. X    return;
  1031. X}
  1032. X
  1033. X
  1034. Xint do_checkhash(hashit,filename)
  1035. Xchar *hashit;
  1036. Xchar *filename;
  1037. X{
  1038. X    int system();
  1039. X
  1040. X    char *kp;
  1041. X    char *comp_cmd;
  1042. X    char cmd[BUFSIZ];
  1043. X
  1044. X    /* 
  1045. X    ** get the basename of the command to use.
  1046. X    ** strip off possible arguments.
  1047. X    */
  1048. X
  1049. X    (void) strcpy(cmd, hashit);
  1050. X    if ((kp = strchr(cmd,' ')) != NULL)
  1051. X        *kp = '\0';
  1052. X    else if ((kp = strchr(cmd,'\t')) != NULL)
  1053. X        *kp = '\0';
  1054. X
  1055. X    comp_cmd = basename(cmd);
  1056. X
  1057. X    if (verbose)
  1058. X       (void) fprintf(logfp,"%s %s\n", comp_cmd, filename);
  1059. X
  1060. X    /*
  1061. X    ** build command to execute.
  1062. X    */
  1063. X    (void) sprintf(cmd,"%s %s", hashit, filename);
  1064. X
  1065. X    if (!test) 
  1066. X       return(system(cmd) >> 8);
  1067. X    else
  1068. X       return(0);
  1069. X}
  1070. X
  1071. END_OF_FILE
  1072. if test 28314 -ne `wc -c <'rkive/news_arc.c'`; then
  1073.     echo shar: \"'rkive/news_arc.c'\" unpacked with wrong size!
  1074. fi
  1075. # end of 'rkive/news_arc.c'
  1076. fi
  1077. if test ! -d 'rkive/port' ; then
  1078.     echo shar: Creating directory \"'rkive/port'\"
  1079.     mkdir 'rkive/port'
  1080. fi
  1081. if test -f 'rkive/port/README.port' -a "${1}" != "-c" ; then 
  1082.   echo shar: Will not clobber existing file \"'rkive/port/README.port'\"
  1083. else
  1084. echo shar: Extracting \"'rkive/port/README.port'\" \(1110 characters\)
  1085. sed "s/^X//" >'rkive/port/README.port' <<'END_OF_FILE'
  1086. X            port/README
  1087. X
  1088. XThis directory contains source needed to bring up rkive on other systems.
  1089. XI have been successful in bringing rkive up on a wide range of machines
  1090. Xbut some machines have a couple pieces missing... :-(
  1091. X
  1092. XIf your system does not have getopt() then use getopt.c This source was
  1093. Xposted to comp.sources.unix in volume3 so there is no problem supplying
  1094. Xit here... You will have to edit the makefile and uncomment the GETOPTO
  1095. Xand GETOPTC entries for including getopt.c.
  1096. X
  1097. XIf you are on a sequent and do not have Doug Gwyn's POSIX Directory access
  1098. Xlibrary installed, you need to edit the makefile and assure that the
  1099. XSsequent's SFLAGS is uncommented.
  1100. X
  1101. XI recommend that you get Doug's Directory access library if you do not
  1102. Xhave POSIX compatible directory access routines already supplied on your 
  1103. Xsystem.  If you need a copy, send me some email and I will gladly send you
  1104. Xa copy...
  1105. X
  1106. XIf you run across something else that can be added to this directory to
  1107. Xmake rkive more portable, please send it to me and I will include it in
  1108. Xfuture releases.  Thanks.
  1109. X
  1110. X            Kent Landfield
  1111. X            kent@sparky.imd.sterling.com
  1112. X
  1113. END_OF_FILE
  1114. if test 1110 -ne `wc -c <'rkive/port/README.port'`; then
  1115.     echo shar: \"'rkive/port/README.port'\" unpacked with wrong size!
  1116. fi
  1117. # end of 'rkive/port/README.port'
  1118. fi
  1119. if test -f 'rkive/rkive.cf' -a "${1}" != "-c" ; then 
  1120.   echo shar: Will not clobber existing file \"'rkive/rkive.cf'\"
  1121. else
  1122. echo shar: Extracting \"'rkive/rkive.cf'\" \(22268 characters\)
  1123. sed "s/^X//" >'rkive/rkive.cf' <<'END_OF_FILE'
  1124. X#
  1125. X#        @(#)rkive.cf    2.2 2/23/91
  1126. X#
  1127. X#        An rkive.cf template.
  1128. X#        Copy and edit this to reflect the local archive conditions.
  1129. X#        After editing, run ckconfig to display how rkive will interpret
  1130. X#        the local specifications.
  1131. X#
  1132. X#        The format of the configuration file is as follows:
  1133. X#
  1134. X######################################################################
  1135. X#
  1136. X#        Global variables
  1137. X#               SPOOLDIR - the base directory for the news subsystem
  1138. X#               PROBLEMS - The name of the base directory used to store any
  1139. X#                          duplicate or "problem" articles. All articles are
  1140. X#                          stored under this directory in a newsgroup/volume
  1141. X#                          directory.
  1142. X#                   TYPE - This is the archive type (or the archive key)
  1143. X#                          There are 6 possible keys:
  1144. X#                               Volume-Issue, Archive-Name,
  1145. X#                               Chronological, Article-Number,
  1146. X#                               Comp-Archives, External-Command,
  1147. X#                               or Only-Archive-Name.
  1148. X#                          These are used to determine if you wish the 
  1149. X#                          articles archived in a 
  1150. X#                                /basedir/amiga/Volume1/v001i22 or
  1151. X#                                /basedir/amiga/Volume1/sitonit or
  1152. X#                                /basedir/amiga/Volume89/890619001 or
  1153. X#                                /basedir/amiga/Volume1/44 format
  1154. X#                          Comp-Archives is used only for the comp.archives
  1155. X#                          newsgroup or newsgroups that supply Archive-name: 
  1156. X#                          but do not supply a volume number. 
  1157. X#                          External-Command is used if you want to have an 
  1158. X#                          external program/script deal with the article. 
  1159. X#                          The External-Command type must be accompanied with
  1160. X#                          an ARCHIVE_CMD entry with specifies the external 
  1161. X#                          program for rkive to use.
  1162. X#                          Only-Archive-Name is used to archive only those
  1163. X#                          articles that contain an Archive-name: header line.
  1164. X#                PATCHES - This variable determines the way in which patches
  1165. X#                          are installed into the archive. If the PATCHES
  1166. X#                          entry is not defined either globally or within
  1167. X#                          the newsgroup, the article is handled as a regular
  1168. X#                          article and is stored according to the specified
  1169. X#                          parameters of the newsgroup. The following are
  1170. X#                          the valid possible values for the PATCHES variable:
  1171. X#                             PATCHES=Historical 
  1172. X#                                 This is the same as if no PATCHES entry
  1173. X#                                 existed at all. It is useful if Historical
  1174. X#                                 patches archiving is the default but there
  1175. X#                                 are certain newsgroups that have it specified
  1176. X#                                 differently.
  1177. X#                             PATCHES=Package 
  1178. X#                                 Package patches archiving allows the inbound
  1179. X#                                 patch to be placed with the directory with
  1180. X#                                 the initially posted articles. In this manner
  1181. X#                                 all parts and fixes of a package are together
  1182. X#                                 making it easier for software retrieval by
  1183. X#                                 uucp requests and mail request facilities
  1184. X#                                 such as netlib.
  1185. X#                   MAIL - If specified, all actions are mailed to the
  1186. X#                          list of users specified. The user names are
  1187. X#                          a comma separated list. It is not necessary to
  1188. X#                          specify any users. 
  1189. X#                  OWNER - The unix login name for the owner of the 
  1190. X#                          archive files after they are stored in the archive.
  1191. X#                  GROUP - The unix group value for the group ownership of 
  1192. X#                          the archive files after they are stored in the 
  1193. X#                          archive.
  1194. X#                   MODE - The modes of the files residing in the archive.
  1195. X#                    LOG - The location of the master log in which all 
  1196. X#                          actions are logged. 
  1197. X#             LOG_FORMAT - The format of the records of the master log file.
  1198. X#                          See the man page for article for a discussion of
  1199. X#                          the available selection format capabilities.
  1200. X#                  INDEX - The location of the master index (if one is kept).
  1201. X#                          The index can be used to interface with the netlib 
  1202. X#                          source retrieval software facility.
  1203. X#           INDEX_FORMAT - The format of the records of the master log file.
  1204. X#                          See the man page for article for a discussion of
  1205. X#                          the available selection format capabilities.
  1206. X#               COMPRESS - The location of the compression utility if the 
  1207. X#                          files are to be reduced.
  1208. X#              CHECKHASH - The location of the checkhash utility if  the
  1209. X#                          files  are  to  be tested for transit damage.
  1210. X#                          Currently,  only  comp.sources.unix  supports
  1211. X#                          this test with the X-Checksum-Snerfu: header.
  1212. X#                          If this variable is specified, it  must  con-
  1213. X#                          tain  the  full  path  to the command used to
  1214. X#                          perform the test.
  1215. X#                   NNTP - The location of the NNTP server where the articles
  1216. X#                          are to be archived from. This can be specified
  1217. X#                          globally if all or most newsgroups are archived
  1218. X#                          from a single NNTP server. 
  1219. X#            ARCHIVE_CMD - This is the path to an external command to pass
  1220. X#                          all articles to that are in need of archiving.
  1221. X#                          This is used when with the archive specification
  1222. X#                          TYPE=External-Command.  This command line may
  1223. X#                          be augmented with variables specified in the 
  1224. X#                          rkive.cf file. See article.1 for a description
  1225. X#                          of the format specification characters available.
  1226. X#                  MATCH - rkive allows you to use globbing to determine if
  1227. X#                          an article is to be archived or not. This is the
  1228. X#                          specification by which articles must match to be
  1229. X#                          archived. The match specification may span
  1230. X#                          multiple lines. A \ at the end of a line is used
  1231. X#                          to indicate that the specification is continued on 
  1232. X#                          another line.
  1233. X#
  1234. X######################################################################
  1235. XSPOOLDIR=/usr/spool/news      
  1236. XPROBLEMS=/usenet/problems
  1237. XTYPE= Volume-Issue
  1238. X#TYPE= External-Command
  1239. X#ARCHIVE_CMD=update_netdocs
  1240. XPATCHES=Historical
  1241. XMAIL=kent
  1242. XOWNER=src
  1243. XGROUP=archive
  1244. XMODE=0444
  1245. X#LOG=/usenet/archive.log
  1246. X#LOG_FORMAT= "%B %a\t%T"
  1247. X#INDEX= /usenet/index
  1248. X#INDEX_FORMAT= "%O\t%a\t%T"
  1249. XCOMPRESS=/usr/ucb/compress -f
  1250. X#CHECKHASH=/usr/local/bin/checkhash -s
  1251. X
  1252. X######################################################################
  1253. X#
  1254. X#     Each Newsgroup to be archived has an entry with the following
  1255. X#     possible variables. (Note that all variables are not necessary)
  1256. X#        
  1257. X#       BASEDIR - This is the path to the base directory of the archive
  1258. X#       TYPE    - This is the archive type (or the archive key)
  1259. X#                 There are 6 possible keys:
  1260. X#                       Volume-Issue, Archive-Name,
  1261. X#                       Chronological, Article-Number,
  1262. X#                       Comp-Archives, External-Command.
  1263. X#                       or Only-Archive-Name.
  1264. X#                These are used to determine if you wish the articles
  1265. X#                archived in a 
  1266. X#                        /basedir/amiga/Volume1/v001i22 or
  1267. X#                        /basedir/amiga/Volume1/sitonit or
  1268. X#                        /basedir/amiga/Volume89/890619001 or
  1269. X#                        /basedir/amiga/Volume1/44 format
  1270. X#                Comp-Archives is used only for the comp.archives
  1271. X#                newsgroup or newsgroups that supply Archive-name: 
  1272. X#                but do not supply a volume number. 
  1273. X#                External-Command is used if you want to have an 
  1274. X#                external program/script deal with the article. 
  1275. X#                The External-Command type must be accompanied with
  1276. X#                an ARCHIVE_CMD entry with specifies the external 
  1277. X#                program for rkive to use.
  1278. X#                Only-Archive-Name is used to archive only those
  1279. X#                articles that contain an Archive-name: header line.
  1280. X#      PATCHES - This variable determines the way in which patches
  1281. X#                are installed into the archive. If the PATCHES
  1282. X#                entry is not defined either globally or within
  1283. X#                the newsgroup, the article is handled as a regular
  1284. X#                article and is stored according to the specified
  1285. X#                parameters of the newsgroup. The following are
  1286. X#                the valid possible values for the PATCHES variable:
  1287. X#                PATCHES=Historical 
  1288. X#                       This is the same as if no PATCHES entry
  1289. X#                       existed at all. It is useful if Historical
  1290. X#                       patches archiving is the default but there
  1291. X#                       are certain newsgroups that have it specified
  1292. X#                       differently.
  1293. X#                PATCHES=Package 
  1294. X#                       Package patches archiving allows the inbound
  1295. X#                       patch to be placed with the directory with
  1296. X#                       the initially posted articles. In this manner
  1297. X#                       all parts and fixes of a package are together
  1298. X#                       making it easier for software retrieval by
  1299. X#                       ftp, uucp requests and mail request facilities
  1300. X#                       such as netlib.
  1301. X#         MAIL - If specified, all actions are mailed to the
  1302. X#                list of users specified. The user names are
  1303. X#                a comma separated list.
  1304. X#        OWNER - The unix login name for the owner of the archive files 
  1305. X#                after they are stored in the archive.
  1306. X#        GROUP - The unix group value for the group ownership of the archive 
  1307. X#                files after they are stored in the archive.
  1308. X#         MODE - The modes of the files residing in the archive.
  1309. X#          LOG - The location of the log in which all actions are logged. 
  1310. X#   LOG_FORMAT - The format of the records of the master log file.
  1311. X#                See the man page for article for a discussion of
  1312. X#                the available selection format capabilities.
  1313. X#        INDEX - The location of the master index (if one is kept).
  1314. X#                The index can be used to interface with the netlib 
  1315. X#                source retrieval software facility.
  1316. X# INDEX_FORMAT - The format of the records of the master log file.
  1317. X#                See the man page for article for a discussion of
  1318. X#                the available selection format capabilities.
  1319. X#     COMPRESS - The location of the compression utility if the files 
  1320. X#                are to be reduced.
  1321. X#    CHECKHASH - The location of the checkhash utility if  the
  1322. X#                files  are  to  be tested for transit damage.
  1323. X#                Currently,  only  comp.sources.unix  supports
  1324. X#                this test with the X-Checksum-Snerfu: header.
  1325. X#                If this variable is specified, it  must  con-
  1326. X#                tain  the  full  path  to the command used to
  1327. X#                perform the test.
  1328. X#         NNTP - The location of the NNTP server where the articles
  1329. X#                are to be archived from.  This can be specified either
  1330. X#                globally, if all or most newsgroups are archived
  1331. X#                from a single NNTP server, or on a by newsgroup basis.
  1332. X#                If specified globally and you wish to archive a 
  1333. X#                newsgroup from your local system, add the following
  1334. X#                entry to the newsgroup specifications. 
  1335. X#                          NNTP: local
  1336. X#                This tells rkive to negate the global value. Case 
  1337. X#                does not matter in the specification of local.
  1338. X#  ARCHIVE_CMD - This is the path to an external command to pass
  1339. X#                all articles to that are in need of archiving.
  1340. X#                This is used when with the archive specification
  1341. X#                TYPE=External-Command.  This command line may
  1342. X#                be augmented with variables specified in the 
  1343. X#                rkive.cf file. See article.1 for a description
  1344. X#                of the format specification characters available.
  1345. X#        MATCH - rkive allows you to use globbing to determine if
  1346. X#                an article is to be archived or not. This is the
  1347. X#                specification by which articles must match to be
  1348. X#                archived. The match specification may span
  1349. X#                multiple lines. A \ at the end of a line is used
  1350. X#                to indicate that the specification is continued on 
  1351. X#                another line.
  1352. X# ARCHIVED_LOG - rkive requires that it be able to determine if an article
  1353. X#                has been previously archived. By default, rkive uses
  1354. X#                a file named .archived ($BASEDIR/.archived) which stores the
  1355. X#                message-id of the previously archived articles. If it is
  1356. X#                inconvient to store the .archived file in the base directory
  1357. X#                of the archive, a alternate path/location can be specified
  1358. X#                by the use of ARCHIVED_LOG.
  1359. X#     PATCHLOG - rkive writes an entry to a file called .patchlog when it
  1360. X#                it encounters a Patch-To: line.  By default, rkive uses
  1361. X#                a file named .patchlog ($BASEDIR/.patchlog) If it is
  1362. X#                inconvient to store the .patchlog file in the base directory
  1363. X#                of the archive, a alternate path/location can be specified
  1364. X#                by the use of PATHLOG.
  1365. X#        
  1366. X######################################################################
  1367. X$$comp.sources.amiga        
  1368. X    BASEDIR: /usenet/amiga 
  1369. X    TYPE: Volume-Issue
  1370. X        INDEX: /usenet/amiga/index
  1371. X        INDEX_FORMAT: "%B %a %T" 
  1372. X    COMPRESS: /usr/ucb/compress -f
  1373. X
  1374. X$$comp.sources.atari.st
  1375. X    BASEDIR: /usenet/atari/st
  1376. X    TYPE: Volume-Issue
  1377. X        INDEX: /usenet/atari/st/index
  1378. X        INDEX_FORMAT: "%B %a %T" 
  1379. X    COMPRESS: /usr/ucb/compress -f
  1380. X
  1381. X$$comp.sources.games        
  1382. X    BASEDIR: /usenet/games
  1383. X    TYPE: Volume-Issue
  1384. X        INDEX: /usenet/games/index
  1385. X        INDEX_FORMAT: "%B %a %T" 
  1386. X    COMPRESS: /usr/ucb/compress -f
  1387. X
  1388. X$$comp.sources.mac        
  1389. X    BASEDIR: /usenet/mac
  1390. X    TYPE: Chronological
  1391. X        INDEX: /usenet/misc/index
  1392. X        INDEX_FORMAT: "%O\t%T" 
  1393. X    COMPRESS: /usr/ucb/compress -f
  1394. X
  1395. X$$comp.sources.misc        
  1396. X    BASEDIR: /usenet/misc
  1397. X    TYPE: Volume-Issue
  1398. X        INDEX: /usenet/misc/index
  1399. X        INDEX_FORMAT: "%B %a %T" 
  1400. X    COMPRESS: /usr/ucb/compress -f
  1401. X
  1402. X$$comp.sources.unix            
  1403. X        BASEDIR: /usenet/unix
  1404. X    TYPE: Volume-Issue
  1405. X        INDEX: /usenet/unix/index
  1406. X        INDEX_FORMAT: "%B %a %T" 
  1407. X#       CHECKHASH: /usr/local/bin/checkhash -s
  1408. X    COMPRESS: /usr/ucb/compress -f
  1409. X
  1410. X$$comp.sources.x        
  1411. X    BASEDIR: /usenet/x
  1412. X    TYPE: Volume-Issue
  1413. X        INDEX: /usenet/x/index
  1414. X        INDEX_FORMAT: "%B %a %T" 
  1415. X    COMPRESS: /usr/ucb/compress -f
  1416. X
  1417. X$$comp.sources.sun        
  1418. X    BASEDIR: /usenet/sun
  1419. X    TYPE: Volume-Issue
  1420. X        INDEX: /usenet/sun/index
  1421. X        INDEX_FORMAT: "%B %a %T" 
  1422. X    COMPRESS: /usr/ucb/compress -f
  1423. X
  1424. X$$comp.sources.bugs
  1425. X    BASEDIR: /usenet/patches/bugs
  1426. X    TYPE: Chronological
  1427. X        INDEX: /usenet/patches/bugs/index
  1428. X        INDEX_FORMAT: "%B\t%S" 
  1429. X    COMPRESS: /usr/ucb/compress -f
  1430. X
  1431. X$$comp.sources.3b1
  1432. X    BASEDIR: /usenet/3b1
  1433. X    TYPE: Volume-Issue
  1434. X        INDEX: /usenet/3b1/index
  1435. X        INDEX_FORMAT: "%B\t%S" 
  1436. X    COMPRESS: /usr/ucb/compress -f
  1437. X
  1438. X$$comp.sources.apple2
  1439. X    BASEDIR: /usenet/apple2
  1440. X    TYPE: Volume-Issue
  1441. X        INDEX: /usenet/apple2/index
  1442. X        INDEX_FORMAT: "%B\t%S" 
  1443. X    COMPRESS: /usr/ucb/compress -f
  1444. X
  1445. X$$alt.sources
  1446. X    BASEDIR: /usenet/alt/sources
  1447. X    TYPE: Only-Archive-Name
  1448. X        INDEX: /usenet/alt/sources/index
  1449. X        INDEX_FORMAT: "%B\t%S" 
  1450. X    COMPRESS: /usr/ucb/compress -f
  1451. X
  1452. X$$alt.sources.amiga
  1453. X    BASEDIR: /usenet/alt/sources.amiga
  1454. X    TYPE: Chronological
  1455. X        INDEX: /usenet/alt/sources.amiga/index
  1456. X        INDEX_FORMAT: "%O\t%T" 
  1457. X    COMPRESS: /usr/ucb/compress -f
  1458. X
  1459. X$$alt.sources.patches
  1460. X    BASEDIR: /usenet/alt/src.patches
  1461. X    TYPE: Chronological
  1462. X        INDEX: /usenet/alt/src.patches/index
  1463. X        INDEX_FORMAT: "%B\t%S" 
  1464. X    COMPRESS: /usr/ucb/compress -f
  1465. X
  1466. X$$u3b.sources
  1467. X    BASEDIR: /usenet/u3b
  1468. X    TYPE: Chronological
  1469. X        INDEX: /usenet/u3b/index
  1470. X        INDEX_FORMAT: "%O\t%T" 
  1471. X    COMPRESS: /usr/ucb/compress -f
  1472. X
  1473. X$$unix-pc.sources
  1474. X    BASEDIR: /usenet/unix-pc
  1475. X    TYPE: Article-Number
  1476. X        INDEX: /usenet/unix-pc/index
  1477. X        INDEX_FORMAT: "%O\t%T" 
  1478. X    COMPRESS: /usr/ucb/compress -f
  1479. X
  1480. X$$vmsnet.sources
  1481. X    BASEDIR: /usenet/vmsnet
  1482. X    TYPE: Chronological
  1483. X        INDEX: /usenet/vmsnet/index
  1484. X        INDEX_FORMAT: "%O\t%T" 
  1485. X    COMPRESS: /usr/ucb/compress -f
  1486. X
  1487. X$$comp.archives
  1488. X    BASEDIR: /usenet/archives
  1489. X    TYPE: Chronological
  1490. X        INDEX: /usenet/archives/index
  1491. X        INDEX_FORMAT: "%B %a %T" 
  1492. X    COMPRESS: /usr/ucb/compress -f
  1493. X
  1494. X
  1495. X#$$space.shuttle
  1496. X#        BASEDIR: /pub/ftp/pub/archive/sci.space.shuttle
  1497. X#        TYPE: Article-Number
  1498. X#        LOG: /pub/ftp/pub/archive/sci.space.shuttle/log
  1499. X#        INDEX: /pub/ftp/pub/archive/sci.space.shuttle/index
  1500. X#        LOG_FORMAT: "%O %S"
  1501. X#        MATCH: subject glob-matches "space news from * AW&ST*" \
  1502. X#        or subject glob-matches "Shuttle Status for ??/??/?? (Forwarded)*" \
  1503. X#        or ( subject glob-matches "* (Forwarded)*" and \
  1504. X#                not subject glob-matches "Re:*" )
  1505. X
  1506. X$$sci.space
  1507. X        BASEDIR: /usenet/sci.space
  1508. X        TYPE: Article-Number
  1509. X        LOG: /usenet/sci.space/log
  1510. X        INDEX: /usenet/sci.space/index
  1511. X        LOG_FORMAT: "%O %S"
  1512. X        MATCH: subject glob-matches "space news from * AW&ST*" \
  1513. X        or subject glob-matches "Voyager Status for ??/??/?? (Forwarded)*" \
  1514. X        or subject glob-matches "Voyager Update*" \
  1515. X        or \
  1516. X        subject glob-matches "NASA Headline News for ??/??/?? (Forwarded)*" \
  1517. X        or subject glob-matches "News of the Week,*" \
  1518. X        or subject glob-matches "Magellan Update - ??/??/??" \
  1519. X        or subject glob-matches "Hubble Space Telescope Update - ??/??/??" \
  1520. X        or ( subject glob-matches "* (Forwarded)*" and \
  1521. X                not subject glob-matches "Re:*" )
  1522. X
  1523. X$$comp.misc
  1524. X        BASEDIR: /usr/doc/news
  1525. X        TYPE: External-Command
  1526. X        ARCHIVE_CMD: /usr/local/lib/rkive/update_netdocs $m $o $g $U
  1527. X        ARCHIVED_LOG: /usr/doc/.admin/misc.archived
  1528. X        PATCHLOG: /usr/doc/.admin/misc.patchlog
  1529. X        INDEX: /usr/doc/.admin/index
  1530. X        LOG: /usr/doc/.admin/log
  1531. X        INDEX: /usr/doc/.admin/index
  1532. X        LOG_FORMAT: "%O %S"
  1533. X        MATCH: subject glob-matches "Anonymous FTP list"
  1534. X
  1535. X$$comp.mail.misc
  1536. X        BASEDIR: /usr/doc/.admin
  1537. X        TYPE: External-Command
  1538. X        ARCHIVE_CMD: /usr/local/lib/rkive/update_netdocs $m $o $g $U
  1539. X        LOG: /usr/doc/.admin/log
  1540. X        INDEX: /usr/doc/.admin/index
  1541. X        LOG_FORMAT: "%O %S"
  1542. X        MATCH: subject glob-matches "Inter-Network Mail Guide"
  1543. X
  1544. X$$comp.std.unix
  1545. X        BASEDIR: /usr/doc/.admin
  1546. X        TYPE: External-Command
  1547. X        ARCHIVE_CMD: /usr/local/lib/rkive/update_netdocs $m $o $g $U
  1548. X        LOG: /usr/doc/.admin/log
  1549. X        INDEX: /usr/doc/.admin/index
  1550. X        LOG_FORMAT: "%O %S"
  1551. X        MATCH: subject glob-matches "Access to UNIX-Related Standards" \
  1552. X        or subject glob-matches "Calendar of UNIX-related Events" \
  1553. X        or subject glob-matches "Access to UNIX User Groups" \
  1554. X        or subject glob-matches "Access to UNIX-Related Publications"
  1555. X
  1556. X$$comp.windows.x
  1557. X        BASEDIR: /usr/doc/.admin
  1558. X        TYPE: External-Command
  1559. X        ARCHIVE_CMD: /usr/local/lib/rkive/update_netdocs $m $o $g $U
  1560. X        LOG: /usr/doc/.admin/log
  1561. X        INDEX: /usr/doc/.admin/index
  1562. X        LOG_FORMAT: "%O %S"
  1563. X        MATCH: subject glob-matches "Frequently Asked Questions about X *"
  1564. X
  1565. X$$news.admin
  1566. X        BASEDIR: /usr/doc/.admin
  1567. X        TYPE: External-Command
  1568. X        ARCHIVE_CMD: /usr/local/lib/rkive/update_netdocs $m $o $g $U
  1569. X        LOG: /usr/doc/.admin/log
  1570. X        INDEX: /usr/doc/.admin/index
  1571. X        LOG_FORMAT: "%O %S"
  1572. X        MATCH: subject glob-matches "Checkgroups message *" \
  1573. X        or subject glob-matches "How to Create a New Trial Newsgroup" \
  1574. X        or subject glob-matches "How to Construct the Mailpaths File" 
  1575. X
  1576. X$$news.announce.newusers
  1577. X        BASEDIR: /usr/doc/.admin
  1578. X        TYPE: External-Command
  1579. X        ARCHIVE_CMD: /usr/local/lib/rkive/update_netdocs $m $o $g $U
  1580. X        LOG: /usr/doc/.admin/log
  1581. X        INDEX: /usr/doc/.admin/index
  1582. X        LOG_FORMAT: "%O %S"
  1583. X        MATCH: subject glob-matches "How to Get Information about Networks" \
  1584. X        or subject glob-matches "USENET Software: History and Sources" \
  1585. X        or subject glob-matches "A Primer on How to Work With the Usenet Community" \
  1586. X        or subject glob-matches "Answers to Frequently Asked Questions" \
  1587. X        or subject glob-matches "Emily Postnews Answers Your Questions on Netiquette" \
  1588. X        or subject glob-matches "Hints on writing style for Usenet" \
  1589. X        or subject glob-matches "Regional Newsgroup Hierarchies *" \
  1590. X        or subject glob-matches "Rules for posting to Usenet" \
  1591. X        or subject glob-matches "How to Create a New Newsgroup" \
  1592. X        or subject glob-matches "List of Periodic Informational Postings" \
  1593. X        or subject glob-matches "List of Active Newsgroupsj" \
  1594. X        or subject glob-matches "Alternative Newsgroup Hierarchies" \
  1595. X        or subject glob-matches "List of Moderators" \
  1596. X        or subject glob-matches "Publicly Accessible Mailing Lists" 
  1597. X
  1598. END_OF_FILE
  1599. if test 22268 -ne `wc -c <'rkive/rkive.cf'`; then
  1600.     echo shar: \"'rkive/rkive.cf'\" unpacked with wrong size!
  1601. fi
  1602. # end of 'rkive/rkive.cf'
  1603. fi
  1604. echo shar: End of archive 1 \(of 6\).
  1605. cp /dev/null ark1isdone
  1606. MISSING=""
  1607. for I in 1 2 3 4 5 6 ; do
  1608.     if test ! -f ark${I}isdone ; then
  1609.     MISSING="${MISSING} ${I}"
  1610.     fi
  1611. done
  1612. if test "${MISSING}" = "" ; then
  1613.     echo You have unpacked all 6 archives.
  1614.     rm -f ark[1-9]isdone
  1615. else
  1616.     echo You still need to unpack the following archives:
  1617.     echo "        " ${MISSING}
  1618. fi
  1619. ##  End of shell archive.
  1620. exit 0
  1621. exit 0 # Just in case...
  1622. -- 
  1623. Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
  1624. Sterling Software, IMD           UUCP:     uunet!sparky!kent
  1625. Phone:    (402) 291-8300         FAX:      (402) 291-4362
  1626. Please send comp.sources.misc-related mail to kent@uunet.uu.net.
  1627.