[comp.sources.unix] v16i089: Archive net sources groups

rsalz@uunet.uu.net (Rich Salz) (11/18/88)

Submitted-by: Geoff Leach <laticorp!geoff>
Posting-number: Volume 16, Issue 89
Archive-name: narc


Narc is a collection of tools to help you with your NetNews habit.
They're intended to minimize the effort involved in saving and
cataloging sources from the Net.  The posting consists of one C source
and a number of C shell scripts.  The C program was developed under Sun OS,
but contains nothing that would make a System V or Xenix port difficult.
The C shell scripts are another matter, of course.

What you have here is tools to capture the postings as they arrive and
organize them as they are completed.  The author spends a few minutes
each day and gets everything he wants.

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of shell archive."
# Contents:  README CheckManifest.1 MakeArchiveIndex.1 assemble.1
#   narc.1 roffit.1 CheckManifest.csh MakeArchiveIndex.csh
#   assemble.csh makemap.csh roffit.csh narc.c patchlevel.h version.h
#   Makefile
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'README' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'README'\"
else
echo shar: Extracting \"'README'\" \(2179 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
X	Did you ever fail to capture a postings because it was too much hassle,
X	only to wish you had done so a few months later?  Hopefully its now not
X	so much of a problem.
X
X	This posting provides you with some relief for your NetNews habit.  In
X	particular, it helps you with the capture and organization of your
X	archive of NetNews source postings.  The posting consists of a single C
X	program and a few Csh scripts.  The program was developed under Sun OS
X	3.4 (i.e., BSD) but should not be too difficult to port to Xenix or
X	System V. The Csh scripts may be another matter.  Perhaps a Perl port?
X
X	What you have here is tools to capture the postings as they arrive and
X	organize them as they are completed.  The author spends a few minutes
X	each day and gets everything he wants.
X
X	Aliases and a configuration file, .narcrc, are part of the total system.
X	Here are the ones that the author finds useful.
X
X		alias ton	'pushd $ARCHIVE/$ARCDIR/$ARCVOL'
X		alias arc	'setenv ARCDIR \!*'
X		alias vol	'setenv ARCVOL v\!*'
X		alias text	'setenv ARCDIR text; setenv ARCVOL '
X		alias alt	'setenv ARCDIR alt; setenv ARCVOL '
X		alias doc	'setenv ARCDIR doc; setenv ARCVOL '
X		alias unix	'setenv ARCDIR unix; setenv ARCVOL v16'
X		alias misc	'setenv ARCDIR misc; setenv ARCVOL v04'
X		alias games	'setenv ARCDIR games; setenv ARCVOL v05'
X		alias x		'setenv ARCDIR x; setenv ARCVOL v01'
X
X	and from his .narcrc file
X
X		comp.sources.unix:unix:Posting-number
X		comp.sources.misc:misc:Posting-number
X		comp.sources.games:games:Comp.sources.games
X		comp.sources.x:x:Posting-number
X		alt.sources:alt
X		comp.doc:doc
X		comp.text:text
X
X	Suggestions and bug reports are welcome.  I'd particularly like to 
X	hear from Xenix and System V users who might wish to contribute diffs
X	for their particular environments.  Or a /bin/sh port of the scripts.
X	Whatever.
X
X	I've also included makemap.csh.  I spent some time figuring out a 
X	way to make use of the UseNet maps in a way that (a) did not require
X	a bunch of repeat processing and (b) did not require the deletion
X	of the posting after processing.  This is my solution.  
X
X	Enjoy!
X
X	Geoffrey Leach	
X	{att,bellcore,sun,ames,pyramid}!pacbell!laticorp!geoff
END_OF_FILE
if test 2179 -ne `wc -c <'README'`; then
    echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
fi
if test -f 'CheckManifest.1' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'CheckManifest.1'\"
else
echo shar: Extracting \"'CheckManifest.1'\" \(978 characters\)
sed "s/^X//" >'CheckManifest.1' <<'END_OF_FILE'
X.TH CHECKMANIFEST 1 "7 October 1988"
X.SH NAME
XCheckManifest \- Check the manifest from a posting against the delivered files.
X.sp
X.SH SYNOPSIS
X.B CheckManifest [
X.I manifest-file
X.B ]
X.sp
X.SH DESCRIPTION
X.I CheckManifest
Xis a C\-shell script that checks the files in the current directory
Xagainst a manifest.  The manifest is sought in files named
X.I MANIFEST
Xor
X.I Manifest.
XOptionally, the 
X.I manifest-file
Xmay be specified on the command line.
X.sp
X.SH OPTIONS
X.IP "manifest-file" .5i
XOverrides default file name.
X.sp
X.SH DIAGNOSTICS
X.I file-name
Xnot delivered.
X.sp
X.SH FILES
X.IP "MANIFEST" .5i
XDefault name for manifest file.
X.IP "Manifest" .5i
XAnother default name for manifest file.
X.sp
X.SH BUGS
XThe manifest file format is not standardized.  Confusion may result.
XNot a Bourne shell script (sorry).
XWould probably be better as a
X.I perl
Xscript.
X.sp
X.SH SEE ALSO
Xassemble(1)
X.sp
X.SH AUTHOR
X.PP
XGeoffrey Leach 
X.br
X.I {att,bellcore,sun,ames,pyramid}!pacbell!laticorp!geoff
END_OF_FILE
if test 978 -ne `wc -c <'CheckManifest.1'`; then
    echo shar: \"'CheckManifest.1'\" unpacked with wrong size!
fi
# end of 'CheckManifest.1'
fi
if test -f 'MakeArchiveIndex.1' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MakeArchiveIndex.1'\"
else
echo shar: Extracting \"'MakeArchiveIndex.1'\" \(796 characters\)
sed "s/^X//" >'MakeArchiveIndex.1' <<'END_OF_FILE'
X.TH MAKEARCHIVEINDEX 1 "7 October 1988"
X.SH NAME
XMakeArchiveIndex \- Gather individual indices into a sorted master file.
X.sb
XPrintArchiveIndex \- Print individual archive directories.
X.sp
X.SH SYNOPSIS
X.B MakeArchiveIndex
X.br
X.B PrintArchiveIndex
X.sp
X.SH DESCRIPTION
X.I MakeArchiveIndex
Xis a C\-shell script that gathers together the 
X.I Index
Xfiles in the given list of directories formats and sorts them.
X.sp
X.I PrintArchiveIndex
Xprints the directory listings of the directories in the archive.
X.sp
X.SH OPTIONS
XNone.
X.sp
X.SH DIAGNOSTICS
XNone.
X.sp
X.SH FILES
X.IP "Index" .5i
XCreated by the user in each archive directory.
X.sp
X.SH BUGS
XNot a Bourne shell script (sorry).
X.sp
X.SH SEE ALSO
Xassemble(1)
X.sp
X.SH AUTHOR
X.PP
XGeoffrey Leach 
X.br
X.I {att,bellcore,sun,ames,pyramid}!pacbell!laticorp!geoff
END_OF_FILE
if test 796 -ne `wc -c <'MakeArchiveIndex.1'`; then
    echo shar: \"'MakeArchiveIndex.1'\" unpacked with wrong size!
fi
# end of 'MakeArchiveIndex.1'
fi
if test -f 'assemble.1' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'assemble.1'\"
else
echo shar: Extracting \"'assemble.1'\" \(6441 characters\)
sed "s/^X//" >'assemble.1' <<'END_OF_FILE'
X.TH ASSEMBLE 1 "7 October 1988"
X.SH NAME
Xassemble \- gather files that constitute a posting into a single directory
X.br
Xarchive \- move program directory into the appropriate place in an archive tree
X.br
Xretrieve \- put an expanded archive file in the current directory
X.sp
X.SH SYNOPSIS
X.B assemble [\-a \fIarchive-directory \fB[\-v \fIarchive-volume\fB]]
X[-s] [\-e \fIfile-name ...\fB]
X.ti 1.0i
X.br
X.B \-n 
X.I archive-name \ first-issue
X.B [\fInumber-of-issues\fB]
X.sp
X.B archive [\-a \fIarchive-directory \fB[\-v \fIarchive-volume\fB]]
X.I archive-name
X.sp
X.B retrieve [\-a \fIarchive-directory \fB[\-v \fIarchive-volume\fB]]
X.I archive-name
X.sp
X.SH DESCRIPTION
X.I Assemble
Xis a C\-shell script that permits the assembly of a group of related 
Xfiles (generally from UseNet newsgroup postings) into 
X.I archive-name
Xfor archiving.  Unshar (or tar) is applied to the files, which are then moved
Xinto a subdirectory for later removal.  
XIf 
X.I uhshar 
Xproduces a 
X.I .hdr
Xheader file, it is moved into 
X.I HDRS;
Xsaving headers can be helpful in identifying the source
Xof the posting at a later date.  The names of the files themselves
Xare saved in 
X.I FILES
Xand will be deleted by 
X.I assemble.
XIf a manifest is posted, it will be checked.  If files with
Xan appropriate extension (.man, .nro, .[1-8]) are found within the directory,
X.I nroff \-man
Xwill be applied to each, the result being stored in a subdirectory
Xunder 
X.I manl
Xwithin the archive.
X.sp
XThe files to be
X.I assembled
Xmay be specified either as a starting issue number (with optional number
Xof issues) or (with the 
X.B \-e
Xoption), a file name.
XIn the former case, the name of the file to be retrieved is implied
Xfrom the name of the 
X.B ARCVOL 
Xdirectory.  For instance, if we are 
Xdealing with comp.sources.unix volume 16, we will be 
X.I assembling
Xfiles whose name is of the form 
X.I v16innn.
XAssuming that the archive has been set up with 
X.B ARCDIR
Xset to "unix"
X.B ARCVOL 
Xset to "16",
X.I assemble \-n example 23 4
Xwill assemble 
X.Iv16i023, v16i024, v16i025 
Xand 
X.I v16i026
Xfrom 
X.I unix/v16
Xrelative to the base directory specified by
X.B ARCHIVE
Xinto the directory 
X.I example
X.sp
X.I Archive
Xis a C\-shell script that permits an 
X.I assembled
Xset of files to be archived in the user's archive hierarchy.
XThe directory specified by
X.I archive-name
Xis saved as a compressed tar file.
XIf 
X.I archive-name.tar.Z
Xexists, it is silently replaced by the new file.
XWithin the 
X.I archive-name
Xdirectory, the directory 
X.I ARCF 
Xis removed and the files specified by 
X.I FILES
Xare deleted.
X.sp
X.I Retrieve
Xis a C\-shell script that permits an
X.I archived
Xdirectory to be copied form the archive hierarchy and restored in
Xconventional form in the current directory.
XThe archive file is untouched.
X.sp
X.SH OPTIONS
X.IP "\-a archive-directory" .5i
XThe archive directory.  This directory (which must already exist)
Xis on the first level below the archive base, which is specified by the
Xenvironment variable 
X.B ARCHIVE.  
XThe specification for 
X.B \-a
Xoverrides the value of the environment variable 
X.B ARCDIR.
XIf
X.B \-a
Xis used,
X.B \-v
Xis required.
X.sp
X.IP "\-e" .5i
XThe 
X.I extract
Xflag can be set to indicated that even though a directory
Xis a moderated newsgroup, the file(s) are to be extracted
Xby name rather than by number.
XThis option is useful if you are re-organizing an existing directory.
X.sp
X.IP "\-n archive-name" .5i
XThe name 
Xgiven to the directory into which files are
X.I assembled
Xand from which an archive file is created by 
X.I archive.
XThe
X.I archive-name
Xgiven to
X.I retrieve
Ximplies
X.I archive-name.tar.Z
Xwithin the archive directory.
X.sp
X.IP "\-s" .5i
XShort assemble.  "Just the files, ma'm."
X.sp
X.IP "\-v archive-volume" .5i
XThe archive volume.  This directory (which must already exist)
Xis on the second level of the archive, below 
X.B ARCDIR.  
XIt is useful for the management of moderated newsgroups.  
X.B \-v
Xoverrides the value of the environment variable 
X.B ARCVOL.
XIf
X.B\-a
Xis used,
X.B\-v
Xis required.
X.sp
X.SH ENVIRONMENT VARIABLES
X.IP "ARCHIVE" .5i
XSpecifies the path (full or relative, as appropriate) for the 
Xdirectory in which the archives directories are maintained.
X.B ARCHIVE 
Xmust be defined, or an equivalent definition made in
X.I assemble
Xand
X.I narc.
X.sp
X.IP "ARCDIR" .5i
XSpecifies the volume used for archiving.
XIf not defined, 
X.B \-a
Xmust be used with all commands.  Value is overridden by
X.B \-a.
X.sp
X.IP "ARCVOL" .5i
XSpecifies the volume used for archiving.  Relevant only if 
X.B ARCDIR
Xis a moderated newsgroup.  If not defined, 
X.B \-v
Xmust be used with all commands.  Value is overridden by
X.B \-v.
X.sp
X.SH DIAGNOSTICS
XPrompts are provided if 
X.I archive-directory
Xor
X.I archive-name
Xis missing where required.  
X.sp
X"File not found" is given if a file specified or implied by a command is not
Xlocated, but the script will attempt to go on, especially if a range of files
Xis implied.
X.sp
X.I CheckManifest
Xand
X.I roffit
XAre called by
X.I assemble.
XThey have their own diagnostics.
X.sp
X.SH FILES
X.IP "ARCF" .5i
XSubdirectory created to hold the original files prior to deletion by
X.I archive.
X.sp
X.IP "FILES" .5i
XList of files used to create the archive.  Created by
X.I assemble
Xfor deletion by
X.I archive.
X.sp
X.IP "HDRS" .5i
XA subdirectory created for the saving of the 
X.I .hdr
Xfile left behind by the action of (some)
X.I unshar
Xprograms.
X.sp
X.IP "manl" .5i
XA subdirectory in the 
X.B ARCHIVE
Xdirectory where a subdirectory for
X.I archive-name
Xis created to hold formatted man pages.
X.sp
X.IP "PATCHES" .5i
XA handy directory created for later collection of patches.
X.sp
X.bp
X.SH EXAMPLE
XHere is a sample archive directory:
X.sp
X.nf
X/dbase/central/news/netsrc/x:
Xv00	v01
X
X/dbase/central/news/netsrc/x/v00:
XIndex		Indexr		awm.tar.Z	xwatch.tar.Z
X
X/dbase/central/news/netsrc/x/v01:
XIndex		menupane.tar.Z	xfig.tar.Z	xmoire.tar.Z	xsecure.tar.Z
XIndexr		qix.tar.Z		xipr.tar.Z	xphoon.tar.Z	xtools.tar.Z
Xdclock.tar.Z	twm.tar.Z	xmille.tar.Z	xplaces.tar.Z
X.fi
X.sp
X.SH BUGS
XIndividual users will want to modify to their tastes and needs.
XThe author is continually fiddling with them.
X.I Assemble
Xassumes you're using the version of 
X.I shar
Xposted by Rick $altz to comp.sources.unix.
XNot a Bourne shell script (sorry).
XWould probably be better as a
X.I perl
Xscript.
X.sp
X.SH SEE ALSO
Xnarc(1), unshar(1), compress(1), tar(1), CheckManifest(1), roffit(1)
X.sp
X.SH AUTHOR
X.PP
XGeoffrey Leach 
X.br
X.I {att,bellcore,sun,ames,pyramid}!pacbell!laticorp!geoff
END_OF_FILE
if test 6441 -ne `wc -c <'assemble.1'`; then
    echo shar: \"'assemble.1'\" unpacked with wrong size!
fi
# end of 'assemble.1'
fi
if test -f 'narc.1' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'narc.1'\"
else
echo shar: Extracting \"'narc.1'\" \(4873 characters\)
sed "s/^X//" >'narc.1' <<'END_OF_FILE'
X.TH NARC 1 "1 September 1988"
X.SH NAME
Xnarc \- take files from a newsreader and place them in a place suitable
Xfor
X.I assemble(1).
X.sp
X.SH SYNOPSIS
X.B narc 
X.B [\-px] [\-a
X.I archive-directory
X.B [\-v 
X.I archive-volume
X.B ]] 
X.sp
X.SH DESCRIPTION
X.I narc
X(\fBN\fRetnews \fBARC\fRhive) takes a stream of articles from 
X.I stdin
Xand figures out where they go, based on the 
X.I .narcrc 
Xfile in the user's home directory. If 
X.I .narcrc 
Xdoes not mention the newsgroup, the user will be prompted, if s/he has
Xnot specified a treatment with 
X.B \-a.
XThe first newsfile or 
X.B \-a 
Xsetting determines treatment for the entire run.
X.sp
XIf he newsgroup is moderated, a volume subdirectory and the file name
Xwithin that directory are determined from the posting.  Otherwise,
Xa three-digit name is given to the file, with numbering being
Xsupplied by a file 
X.I .names 
Xwithin the archive directory.  This file is created by 
X.I narc 
Xas required.  It ensures unique naming for files being saved 
X.I en bloc.
X.sp
X.SH OPTIONS
XAn illegal option will produce a diagnostic and a usage message.
X.IP "\-a archive-directory" .5i
XThe archive directory.  This directory (which must already exist)
Xis on the first level below the archive base, which is specified by the
Xenvironment variable 
X.B ARCHIVE.  
XThe specification for 
X.B \-a
Xoverrides the value of the environment variable 
X.B ARCDIR.
X.sp
X.IP "\-p" .5i
XThe 
X.I prompt
Xflag will cause the user to be prompted for an archive volume and for
Xthe name of each of the files into which the articles are to be saved.
X.sp
X.IP "\-v archive-volume" .5i
XThe archive volume.  This directory (which must already exist)
Xis on the second level of the archive, below 
X.B ARCDIR.  
XIt is useful for the management of moderated newsgroups.  
X.B \-v
Xoverrides the value of the environment variable 
X.B ARCVOL.
X.sp
X.IP "\-x" .5i
XDebugging.  
X.I Narc
Xwill tell you what its going to do, but then do it in the 
X.I cwd 
Xinstead.
X.sp
X.SH ENVIRONMENT VARIABLES
X.IP "ARCHIVE" .5i
XSpecifies the path for the 
Xdirectory in which the archives directories are maintained.
X.B ARCHIVE 
Xmust be defined, or an equivalent definition made in
X.I assemble
Xand
X.I narc.
X.sp
X.SH FILES
X.IP "~/.narcrc" .5i
XColon-separated fields that describe what to do for standard newsgroups.
XIn the format:
X.sp
X.ta 1i 2i
X	newsgroup:archive-directory[:volume-tag]
X.sp
Xwhere the interpretation of the colon-separated fields is as follows.
X.sp
X.in 1i
X.ip "newsgroup"
XThe 
X.I first
Xname to be found on the "Newsgroups: " line in the article header.
X.ip "archive-directory"
XThe directory associated with this newsgroup.
X.ip "volume-tag"
XThe beginning of the line in the archive header
Xthat flags the line that specifies the volume in a moderated newsgroup.
XIf this entry is empty, an un-moderated newsgroup is implied.
X.sp
XThe \fI.narcrc\fR entry for
X.I comp.sources.unix
Xis:
X.sp
X	comp.sources.unix:unix:Posting-number
X.sp
XThis is because the header for postings to this newsgroup has the entries
X.sp
X	Newsgroups: comp.sources.unix
X.br
Xand
X.br
X	Posting-number: Volume 16, Issue 1
X.sp
XThe volume-tag field is needed because not all moderated newsgroups
Xuse the same header to identify the current volume for the archive.  
XOn the other hand, they all use the header
X.sp
X	Archive-name: <stuff>
X.sp
Xto identify the name of the archive entry.
X.sp
X.IP ".names" .5i
XCreated in archive directory for un-moderated newsgroup to keep track of
Xsaved articles.
X.sp
X.IP "Indexr" .5i
XCreated in each archive directory to receive subject line (slightly modified)
Xfor each article saved in that directory.  It's expected that the user
Xwill extract one line for each group of related articles, clean it up
Xand place it in the Index file in that directory.
X.sp
X.SH DIAGNOSTICS
X.IP "<filename> exists! (a)ppend, (i)gnore or (r)eplace [r]? " 0.5i
XYou've already saved a file by this name.  Its not a repost, because we handle 
Xthat case.
X.sp
X.IP "Unable to rename %s" 0.5i
XFailure from the rename system call.
X.sp
X.IP "Could not find newsgroup (or volume) within nnn lines" 0.5i
X\fINarc\fR must read ahead in the input stream to find the headers.  Because
Xinput may be from a pipe, it must buffer in order to re-process what's already 
Xscanned.  You've just exceeded the size of the buffer!  
XEither this the Newsgroup header is missing or your favorite moderator has
Xpermitted an article to slip through without the volume-tag header.
X.sp
X.IP "Archive directory for %s? " 0.5i
XThe article you are processing is not one of those listed in your 
X\fI.narcrc\fR file.  You need to specify an archive directory.
X.sp
X.IP "Could not chdir to <directory>" 0.5i
XSorry, \fIchdir\fR failed.
X.sp
X.IP "Error opening %s" 0.5i
XGeneral-purpose error message, with interpreted system error to follow.
X.sp
X.SH SEE ALSO
Xassemble(1)
X.sp
X.SH AUTHOR
X.PP
XGeoffrey Leach 
X.br
X.I {att,bellcore,sun,ames,pyramid}!pacbell!laticorp!geoff
END_OF_FILE
if test 4873 -ne `wc -c <'narc.1'`; then
    echo shar: \"'narc.1'\" unpacked with wrong size!
fi
# end of 'narc.1'
fi
if test -f 'roffit.1' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'roffit.1'\"
else
echo shar: Extracting \"'roffit.1'\" \(1148 characters\)
sed "s/^X//" >'roffit.1' <<'END_OF_FILE'
X.TH ROFFIT 1 "7 October 1988"
X.SH NAME
Xroffit \- Look for files which might contain man page documentation and 
Xformat them into the 
X.I manl
Xdirectory in the archive hierarchy.
X.sp
X.SH SYNOPSIS
X.B roffit [
X.I man-files
X.B ]
X.sp
X.SH DESCRIPTION
X.I Roffit
Xis a C\-shell script which checks the files in the current directory tree
Xfor files with extensions
X.I l, man, nro and [1-8]
Xand applies
X.I nroff -man
Xto each, directing the output to the
X.I manl
Xdirectory in the archive hierarchy.  If name conflicts arise, the user
Xis prompted.
X.sp
X.SH OPTIONS
X.IP "man-file" .5i
XProcess these files instead of searching.
X.sp
X.SH ENVIRONMENT VARIABLES
X.IP "ARCHIVE" .5i
XThe location of the archive hierarchy.
X.sp
X.SH BUGS
XNot a Bourne shell script (sorry).
X.sp
X.SH DIAGNOSTICS
X.IP "Man page <file> exists.  (i)gnore, (o)verwrite or new name(n) [i]? " 0.5i
XAll of the formatted man pages are placed in the same directory.
XOften, a posting will include some useful items that are not
Xuniversally available.  Getopt(3) often shows up.
X.sp
X.SH SEE ALSO
Xassemble(1)
X.sp
X.SH AUTHOR
X.PP
XGeoffrey Leach 
X.br
X.I {att,bellcore,sun,ames,pyramid}!pacbell!laticorp!geoff
END_OF_FILE
if test 1148 -ne `wc -c <'roffit.1'`; then
    echo shar: \"'roffit.1'\" unpacked with wrong size!
fi
# end of 'roffit.1'
fi
if test -f 'CheckManifest.csh' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'CheckManifest.csh'\"
else
echo shar: Extracting \"'CheckManifest.csh'\" \(520 characters\)
sed "s/^X//" >'CheckManifest.csh' <<'END_OF_FILE'
X#!	/bin/csh	-f
X
X# If there's a manifest here, check it against what's been delivered
X
X# Geoffrey Leach
X# LatiCorp Inc.	
X# {att,bellcore,sun,ames,pyramid}!pacbell!laticorp!geoff
X
Xif ( $#argv == 1 ) then
X    set MANIFEST = $1
Xelse
X    if ( -e MANIFEST ) then
X	set MANIFEST = "MANIFEST"
X    else
X	if ( -e Manifest ) set MANIFEST = "Manifest"
X    endif
Xendif
Xif ( $?MANIFEST ) then
X    echo Checking manifest
X    foreach f ( `awk '{if ( NR > 2 ) print $1}' ${MANIFEST}` )
X	if ( ! -e $f ) echo $f not delivered
X    end
Xendif
END_OF_FILE
if test 520 -ne `wc -c <'CheckManifest.csh'`; then
    echo shar: \"'CheckManifest.csh'\" unpacked with wrong size!
fi
chmod +x 'CheckManifest.csh'
# end of 'CheckManifest.csh'
fi
if test -f 'MakeArchiveIndex.csh' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MakeArchiveIndex.csh'\"
else
echo shar: Extracting \"'MakeArchiveIndex.csh'\" \(1261 characters\)
sed "s/^X//" >'MakeArchiveIndex.csh' <<'END_OF_FILE'
X#!	/bin/csh	-f
X
X# Geoffrey Leach
X# LatiCorp Inc.	
X# {att,bellcore,sun,ames,pyramid}!pacbell!laticorp!geoff
X
Xset NAME = $0
Xset NAME = $NAME:t
X
Xset LIST = ( \
X	games/v00 \
X	games/v01 \
X	games/v02 \
X	games/v03 \
X	games/v04 \
X	games/v05 \
X	misc/v02 \
X	misc/v03 \
X	misc/v04 \
X	misc/v05 \
X	x/v00 \
X	x/v01 \
X	x/v02 \
X	unix/v00 \
X	unix/v01 \
X	unix/v02 \
X	unix/v03 \
X	unix/v04 \
X	unix/v05 \
X	unix/v06 \
X	unix/v07 \
X	unix/v08 \
X	unix/v09 \
X	unix/v10 \
X	unix/v11 \
X	unix/v12 \
X	unix/v13 \
X	unix/v14 \
X	unix/v15 \
X	unix/v16 \
X	benchmarks \
X	graphics \
X	patches \
X	lang \
X	util \
X	text \
X	gnu \
X	doc \
X	dos \
X	lib \
X	alt )
X
Xcd $ARCHIVE
Xswitch ( $NAME )
X    case MakeArchiveIndex:	
X	if ( -e I ) rm I
X	foreach f ( ${LIST} )
X	awk -F: '{n = $1 " (" v "):"; \
X	    if ( substr($2, 1, 1) == "\t" ) $2 = substr($2, 2); \
X	    if ( substr($2, 1, 1) == "\t" ) $2 = substr($2, 2); \
X	    $2 = substr($2,1,46); \
X	    if ( length(n) <  8 ) n = n "\t"; \
X	    if ( length(n) < 16 ) n = n "\t"; \
X	    if ( length(n) < 24 ) n = n "\t"; \
X	    printf "%s\t%s\n", n, $2 }' v=$f $f/Index  >> I
X	end
X	sort -f I > Index
X	rm I
X	exit
X    case PrintArchiveIndexes:
X	cp /dev/null ~/tmp/netls
X	foreach f ( ${LIST} )
X	    ls -RC $f >> /tmp/netls
X	end
X	cd /tmp
X	print netls
X	exit
X    default:
Xendsw
END_OF_FILE
if test 1261 -ne `wc -c <'MakeArchiveIndex.csh'`; then
    echo shar: \"'MakeArchiveIndex.csh'\" unpacked with wrong size!
fi
chmod +x 'MakeArchiveIndex.csh'
# end of 'MakeArchiveIndex.csh'
fi
if test -f 'assemble.csh' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'assemble.csh'\"
else
echo shar: Extracting \"'assemble.csh'\" \(6382 characters\)
sed "s/^X//" >'assemble.csh' <<'END_OF_FILE'
X#!	/bin/csh	-f
X
X# Archive management scripts.  Use in conjunction with narc
X
X# Geoffrey Leach
X# LatiCorp Inc.	
X# {att,bellcore,sun,ames,pyramid}!pacbell!laticorp!geoff
X
X# assemble	Assemble a group of files into an archive directory
X# archive	Put and archive directory in its place
X# retrieve	Get an archive directory into the cwd
X
X# This shell script implements an archive management facility.  The
X# idea is that you have a archive whose path is in the environment
X# variable ARCHIVE.  The directories here are your archive.  
X# Files in an archive directory are compressed tar files if they were
X# put there by this archive.  If they were put there by narc, then they
X# are plain text files, which you will assemble into compressed tar, depending
X# on how they got there.  Moderated archives are handled in a way that 
X# lets you refer to a series of postings with shorthand.  BTW, moderated
X# groups are assumed to be organized by volume in your archive.  Retrieve
X# just helps you get a particular archive file into your cwd.
X
X# Usage - options apply as stated in the usage messages
X#
X#	-a	Specify ARCDIR.  Forces ARCVOL to ""
X#	-e	Extract.  Overrides shorthand for moderated groups
X#	-n	Specify archive file.  $1 defaults
X#	-s	"Short" assemble; just get the files
X#	-v	Specify ARCVOL
X
X
X# Environment variable usage 
X
X#    ARCHIVE	base directory of archive
X#    ARCPATH	directory name
X#    ARCVOL	subdirectory name for moderated groups
X
X# Commands that are used by this script that you might not have
X
X#    unshar
X
Xset MYNAME   = $0
Xset MYNAME   = $MYNAME:t
X
X# usage
Xif ( $#argv == 0 ) then
X    echo -n "Usage: $MYNAME [-a archive [-v volume]] "
X    switch ( $MYNAME )
X	case "assemble":
X	    echo "[-s] [-e name] [-n archive-name] base-issue [number-of-issues]"
X	    exit
X	case "archive":
X	    echo "file"
X	    exit
X	case "retrieve":
X	    echo "file"
X	    exit
X	default:
X	    echo ""
X	    exit
X    endsw
Xendif
X
X# Check for environment usage
Xif ( ! $?ARCHIVE ) set ARCHIVE
Xif ( ! $?ARCDIR )  set ARCDIR
Xif ( ! $?ARCVOL )  set ARCVOL
X
X# Check for switches
Xset SWSCAN
Xwhile ( $?SWSCAN )
X    switch ( $1 )
X    case -a:
X        set ARCDIR = $2
X	set ARCVOL = ""
X	shift
X	shift
X	breaksw
X    case -e:
X	if ( ! $?EXTRACT ) then 
X	    set EXTRACT
X	else
X	    unset EXTRACT
X	endif
X	shift
X	breaksw
X    case -n:
X	set ARCFILE = $2
X	shift
X	shift
X	breaksw
X    case -s:
X	set SHORT
X	shift
X	breaksw
X    case -v:
X	if ( $2 <= 9 ) then 
X	    set ARCVOL = v0$2
X	else
X	    set ARCVOL = v$2
X	endif
X	shift
X	shift
X	breaksw
X    case -*:
X	echo "Unrecognized option $1"
X	exit
X    default:
X	unset SWSCAN
X	breaksw
X    endsw
Xend
X
Xif ( $ARCDIR == "" ) then
X    echo -n "Archive directory? "
X    set ARCDIR = $<
Xendif
X
Xif ( $ARCVOL == "" ) then
X    switch ( $ARCDIR )
X	case x:
X	case unix:
X	case misc:
X	case games:
X	    echo -n "Archive volume? "
X	    set ARCVOL = $<
X	    if ( $ARCVOL <= 9 ) then
X		set ARCVOL = v0$ARCVOL
X	    else
X		set ARCVOL = v$ARCVOL
X	    endif
X	    breaksw
X	default:
X	    breaksw
X    endsw
Xendif
Xset PREFIX = ${ARCVOL}i
X
Xif ( $ARCVOL == "" ) then
X    set ARCPATH = $ARCHIVE/$ARCDIR
Xelse
X    set ARCPATH = $ARCHIVE/$ARCDIR/$ARCVOL
Xendif
X
X# Here is where we do the real work
Xswitch ( $MYNAME )
X    case assemble:
X
X	# For moderated groups, we usually have the number of the first posting,
X	# and (optionally) the number of postings.  These
X	# are combined to give a sequence of file names.  Otherwise, we assume
X	# that the argument is the prefix of the file(s) to be retrieved.
X	# There may be more than one file with that name as prefix.
X	switch ( $ARCDIR )
X	    case "x":
X	    case "unix":
X	    case "misc":
X	    case "games":
X		if ( ! $?EXTRACT ) then
X		    set MODERATED
X		    set BASE = $1
X		    if ( $#argv == 2 ) then
X			set COUNT = $2
X		    else
X			set COUNT = 1
X		    endif
X		endif
X		breaksw
X	    default:
X		breaksw
X	endsw
X
X	# Set up the directory structure for the archive.
X	# Conditional so that we can assemble into an existing directory.
X	# ARCF		is where we put the raw input for later deletion
X	# FILES		is the lis of original files, for later deletion
X	# HDRS		contains the .hdr files produced by unshar, so you can
X	#		find our later where all of this came from.
X	# PATCHES	is where you accumulate patch files.  I save these
X	#		so they can be un-applied later.  Useful if you are
X	#		applying unofficial patches to a maintained source.
X	if ( ! $?ARCFILE ) then
X	    if ( $?MODERATED ) then
X		echo -n "Archive name? "
X		set ARCFILE = $<
X	    else
X		set ARCFILE = $1
X	    endif
X	endif
X	if ( ! -d $ARCFILE ) mkdir $ARCFILE
X	cd $ARCFILE
X	if ( ! -d HDRS ) mkdir HDRS
X	if ( ! -d ARCF ) mkdir ARCF
X	if ( ! -d PATCHES ) mkdir PATCHES
X
X	if ( $?MODERATED ) then
X	    while ( $COUNT )
X		if ( $BASE <  10 ) set BASE = 0$BASE
X		if ( $BASE < 100 ) set BASE = 0$BASE
X		set f = $ARCPATH/${PREFIX}${BASE}
X		if ( ! -e $f ) echo $f not found
X		chmod +w $f
X		cp $f .
X		echo $f >> FILES
X		unshar $f:t
X		mv $f:t ARCF
X		@ COUNT = $COUNT - 1
X		@ BASE = $BASE + 1
X	    end
X	else
X	    foreach f ( $ARCPATH/$1* )
X		chmod +w $f
X		cp $f .
X		echo $f >> FILES
X		# You may want to assemble pre-existing archives.  We handle
X		# Compressed files, which may also be tar or shar.
X		set f = $f:t
X		if ( $f:e == "Z" ) then
X		    set f = $f:r
X		    uncompress $f
X		endif
X		if ( $f:e == "tar" ) then
X		    tar xvf $f
X		    set f = $f:r
X		else
X		    unshar $f:t
X		endif
X		mv $f:t ARCF
X	    end
X	endif
X	mv *hdr HDRS
X
X	if ( -e ark1isdone ) mv ark*isdone ARCF
X
X	if ( $?SHORT ) exit
X
X	# This maintains an archive of formatted documentation
X	roffit
X
X	CheckManifest
X	ls -C
X	exit
X
X    case archive:
X	if ( ! $?ARCFILE ) then
X	    if ( $#argv != 1 ) then
X		echo -n "Archive name? "
X		set ARCFILE = $<
X	    else
X		set ARCFILE = $1
X	    endif
X	endif
X	if ( ! -d $ARCFILE ) then
X	    echo archive: $ARCFILE not found
X	    exit
X	endif
X	if ( -e $ARCFILE/FILES ) then
X	    set F = ( `cat $ARCFILE/FILES` )
X	    rm -r $ARCFILE/FILES
X	else
X	    set F
X	endif
X	if ( ! -d $ARCPATH ) then
X	    echo "$ARCPATH not found"
X	    exit
X	endif
X	if ( -d $ARCFILE/ARCF ) rm -r $ARCFILE/ARCF
X	tar cvf $ARCPATH/$ARCFILE.tar $ARCFILE
X	if ( -e $ARCPATH/$ARCFILE.tar.Z ) rm -f $ARCPATH/$ARCFILE.tar.Z
X	compress $ARCPATH/$ARCFILE.tar
X	chmod -w $ARCPATH/$ARCFILE.tar.Z
X	rm -rf $ARCFILE $F
X	exit
X
X    case retrieve:
X	set f = $ARCPATH/$1.tar.Z
X	if ( ! -e $f ) then
X	    echo $f not found
X	    exit
X	endif
X	zcat $f | tar xvf -
X	exit
X    default:
X	exit
Xendsw
END_OF_FILE
if test 6382 -ne `wc -c <'assemble.csh'`; then
    echo shar: \"'assemble.csh'\" unpacked with wrong size!
fi
chmod +x 'assemble.csh'
# end of 'assemble.csh'
fi
if test -f 'makemap.csh' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'makemap.csh'\"
else
echo shar: Extracting \"'makemap.csh'\" \(678 characters\)
sed "s/^X//" >'makemap.csh' <<'END_OF_FILE'
X#!	/bin/csh	-f
X
Xset BDIR	= /local/bin
Xset PDIR	= /local/lib/palias
Xset MAPDIR	= /local/lib/palias/uumap
Xset NEWSDIR	= /news/comp/mail/maps
Xset LOG		= $PDIR/makemap.log
X
Xset BASE = `cat $MAPDIR/.last`
Xcd $NEWSDIR
Xset MAPS = ( `ls` )
Xif ( $#MAPS == 0 ) exit
X
Xforeach m ( $MAPS )
X    if ( $m > $BASE ) then
X	$BDIR/unshar -n -c$MAPDIR $m >>& $LOG
X	set NEWMAP
X    endif
Xend
Xif ( ! $?NEWMAP ) exit
X
Xecho $m > $MAPDIR/.last
Xcd $PDIR
Xrm paths.pag paths.dir
Xmv paths paths.old
X$BDIR/pathalias Path.* uumap/[du].* | sed -e 's/	ptsfa\!/	/' -e '/^ptsfa/d'  | sort | $BDIR/pathprune > paths
X$BDIR/makedb -o paths paths
X#add sentinel for uumail >>& $LOG
X$BDIR/makedb -a -o paths @@@ >>& $LOG
END_OF_FILE
if test 678 -ne `wc -c <'makemap.csh'`; then
    echo shar: \"'makemap.csh'\" unpacked with wrong size!
fi
chmod +x 'makemap.csh'
# end of 'makemap.csh'
fi
if test -f 'roffit.csh' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'roffit.csh'\"
else
echo shar: Extracting \"'roffit.csh'\" \(871 characters\)
sed "s/^X//" >'roffit.csh' <<'END_OF_FILE'
X#!	/bin/csh 	-f
X# Find something that might be a man page and 'roff it.
X
X# Geoffrey Leach
X# LatiCorp Inc.	
X# {att,bellcore,sun,ames,pyramid}!pacbell!laticorp!geoff
X
Xset DIR = `pwd`
Xset DIR = $DIR:t
X
Xif ( $#argv == 0 ) then
X    set DOC = `find . \( -name "*.l" -o -name "*.man" -o -name "*.nro" -o -name "*.[1-8]" \) -print`
Xelse
X    set DOC = ( $* )
Xendif
Xforeach f ( $DOC )
X    if ( $f:h != "./ARCF" ) then
X	set D = $ARCHIVE/manl/$f:t 
X	if ( $f:t == README ) set $f = ${DIR}.$f
Xrepeat:
X	if ( -e $D ) then
X	    echo -n "Man page $f exists.  Ignore(i), overwrite(o) or new name(n) [i]? "
X	    set ans = $<
X	    switch ( $ans )
X		case "i":
X		default:
X		    continue
X		case "o":
X		    breaksw
X		case "n":
X		    echo -n "Enter new name: "
X		    set ans = <$
X		    set D = $ARCHIVE/manl/$ans
X		    goto repeat
X		    breaksw
X	    endsw
X	endif
X	nroff -man $f > $D
X    endif
Xend
END_OF_FILE
if test 871 -ne `wc -c <'roffit.csh'`; then
    echo shar: \"'roffit.csh'\" unpacked with wrong size!
fi
chmod +x 'roffit.csh'
# end of 'roffit.csh'
fi
if test -f 'narc.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'narc.c'\"
else
echo shar: Extracting \"'narc.c'\" \(11664 characters\)
sed "s/^X//" >'narc.c' <<'END_OF_FILE'
X/*
X**	Narc -- archive NetNews articles
X**
X**	Geoffrey Leach
X**	LatiCorp Inc.	
X**	{att,bellcore,sun,ames,pyramid}!pacbell!laticorp!geoff
X*/
X
X#include <stdio.h>
X#include <strings.h>
X#include <sys/file.h>
X#include "version.h"
X#include "patchlevel.h"
X
X#define	TRUE		1
X#define FALSE		0
X#define MATCH		0
X#define EXISTS		0
X#define PROMPT		0
X#define SUBJECT		1
X#define INDEX		2
X#define PNULL		(char *)0
X#define FNULL		(FILE *)0
X#define NGNULL		(sNewsGroup *)0
X#define INDEXR		"Indexr"
X
Xtypedef struct
X{
X    char *	name;
X    char *	archive;
X    char *	volume_tag;
X    int		moderated;
X} sNewsGroup;
X
Xextern char *	fgets();
Xextern char *	malloc();
Xextern char *	getenv();
Xextern char *	strpbrk();
Xextern char *	optarg;
Xextern int	optind;
X
XsNewsGroup *	NewsGroups[100];
XsNewsGroup 	prompted = {PNULL, PNULL, PNULL, FALSE};
XFILE *		rc;
XFILE *		tty;
XFILE *		out;
XFILE *		aindex;
Xchar	 	arcdir[1024];
Xchar	 	descr[1024];
Xchar	 	arc_dir[1024];
Xchar		line[1024];
Xchar		head_buf[10240];
Xchar *		head_buf_ptr = head_buf;
Xchar		tmp_file[] = {"Narc.XXXXXX"};
Xchar		arc_file[256];
Xchar		arc_name[256];
Xchar		p_archive[256];
Xint		debug = FALSE;
Xint		named = FALSE;
Xint		repost = FALSE;
Xint		selected = FALSE;
Xint		subjected = FALSE;
Xint		head_buf_lines = 0;
X
XsNewsGroup*
Xlookup(name)
X    char	*name;
X{
X    int 	 i = -1;
X
X    /*
X     *  A little surgery: get rid of the  leading "Newsgroups: "
X     *  and remove any secondary newsgroups
X     */
X    name += 12;
X    *(strpbrk(name, ",\n")) = '\0';
X
X    /*
X     *  See if this newsgroup was listed in the user's rc file
X     */
X    while ( NewsGroups[++i] )
X    {
X	if ( strcmp(name, NewsGroups[i]->name) == MATCH )
X	    return NewsGroups[i];
X    }
X    return NGNULL;
X}
X
Xvoid
Xrename_article(tmp_file, name)
X    char *tmp_file;
X    char *name;
X{
X    char  ans[10];
X    char  rcmd[1024];
X
X    if ( access(name, R_OK) == EXISTS )
X    {
X	printf("%s exists! (a)ppend, (i)gnore or (r)eplace [r]? ", arc_file);
X	fflush(stdout);
X	fgets(ans, 10, tty);
X	switch ( ans[0] )
X	{
X	    default:
X	    case 'r':
X		break;
X	    case 'a':
X		sprintf(rcmd, "cat %s >> %s", tmp_file, name);
X		if ( debug )
X		    printf("%s\n", rcmd);
X		system(rcmd);
X		unlink(tmp_file);
X		return;
X	    case 'i':
X		return;
X	}
X    }
X
X    if ( rename(tmp_file, name) )
X    {
X	sprintf(rcmd, "Unable to rename %s", name);
X	perror(rcmd);
X	exit(1);
X    }
X}
X
Xvoid
Xclose_article()
X{
X    /*
X     *  The beginning of an article, and not the first.
X     *  Therefore, we have an article open that must be closed.
X     */
X    named     = FALSE;
X    repost    = FALSE;
X    subjected = FALSE;
X    if ( strlen(arc_name) )
X    {
X	fputs(arc_name, aindex);
X	fputs(":  ",    aindex);
X	fputs(descr,    aindex);
X    }
X    fclose(out);
X
X    if ( selected )
X    {
X	rename_article(tmp_file, arc_file);
X	out = fopen(tmp_file,"w");
X	selected = FALSE;
X    }
X    else
X	rewind(out);
X}
X
Xvoid
Xchop(str)
X    char *	str;
X{
X    *(str +strlen(str) - 1) = '\0';
X}
X
Xvoid
Xfgets_buffer()
X{
X    if ( (head_buf_ptr + strlen(line)) >= (head_buf + sizeof(head_buf)) )
X    {
X	printf("Could not find newsgroup (or volume) within %d lines\n",
X	       head_buf_lines);
X	exit(1);
X    }
X
X    fgets(line, sizeof(line), stdin);
X    strcpy(head_buf_ptr, line);
X    head_buf_ptr += strlen(line) + 1;
X    head_buf_lines++;
X}
X
Xchar *
Xfgets_unbuffer()
X{
X    if ( head_buf_lines )
X    {
X	strcpy(line, head_buf_ptr);
X	head_buf_ptr += strlen(line) + 1;
X	head_buf_lines--;
X	return line;
X    }
X    return fgets(line, sizeof(line), stdin);
X}
X
Xvoid
Xmain(argc, argv)
X    int		 argc;
X    char	*argv[];
X{
X    int		 i;
X    int		 opt;
X    int	 	 vol;
X    int	 	 mode = INDEX;
X    int	 	 name_fd = 0;
X    int		 article_name = 0;
X    char *	 cmd;
X    char *	 name;
X    char *	 subj;
X    sNewsGroup * NewsGroup;
X
X    while ( (opt = getopt(argc, argv, "a:px")) != EOF )
X    {
X	switch ( opt )
X	{
X	    case 'a':
X		prompted.archive = optarg;
X		break;
X	    case 'p':
X		mode = PROMPT;
X		break;
X	    case 'x':
X		debug = TRUE;
X		break;
X	    default:
X		fprintf(stderr, "Usage: narc [-px] [-a archive]\n");
X		fprintf(stderr, "       version %s level %d\n", VERSION, PATCHLEVEL);
X		exit(1);
X	}
X    }
X
X    /*
X     * Get the archive directory from the environment
X     */
X    strcpy(arcdir, getenv("ARCHIVE"));
X
X    /*
X     * Read the user's ~/.narc file (if he has one) for the 
X     * newsgroups to watch.  What we are looking for is 
X     * The base of the archive directory (full path) this is the
X     * prefix for the archive directory specified for each newsgroup.
X     * Then, tab separated fields as follows:
X     *	    newsgroup:  what fillows Newsgroups: in the header.
X     *	    archive:    the directory under arcdir.
X     *	    volume_tag: the tag for the line that says what the volume is 
X     *			(moderated newsgroups only).
X     *	    moderated:  is this a moderated newsgroup? (0/1)
X     */
X    sprintf(line, "%s/.narcrc", getenv("HOME"));
X    if ( (rc = fopen(line, "r")) != FNULL )
X    {
X	i = 0;
X	while ( fgets(line, sizeof(line), rc ) != PNULL )
X	{
X	    NewsGroup       =
X	    NewsGroups[i++] = (sNewsGroup *)malloc(sizeof(sNewsGroup));
X
X	    *(name = index(line, ':')) = '\0';
X	    NewsGroup->name = malloc(strlen(line) + 1);
X	    strcpy(NewsGroup->name, line);
X
X	    subj = ++name;
X	    if ( (name = index(subj, ':')) == PNULL )
X	    {
X		NewsGroup->moderated = FALSE;
X		subj[strlen(subj) - 1] = '\0';
X	    }
X	    else
X	    {
X		NewsGroup->moderated = TRUE;
X		*name = '\0';
X	    }
X	    NewsGroup->archive = malloc(strlen(subj) + 1);
X	    strcpy(NewsGroup->archive, subj);
X
X	    if ( NewsGroup->moderated )
X	    {
X		subj = ++name;
X		NewsGroup->volume_tag = malloc(strlen(subj));
X		strncpy(NewsGroup->volume_tag, subj, strlen(subj) - 1);
X	    }
X
X	    if ( debug )
X		printf("%s\t%s\t%s\t%d\n", NewsGroup->name,
X					   NewsGroup->archive,
X					   NewsGroup->volume_tag,
X					   NewsGroup->moderated);
X	}
X	fclose(rc);
X    }
X
X    if ( (tty = fopen("/dev/tty", "r")) == FNULL )
X    {
X	perror("Error opening tty");
X	exit(1);
X    };
X
X    /*
X     *  If the user has not forced an archive, find one.
X     *  As we will skip past the first subject line, we need
X     *  to buffer the head of the file.
X     */
X    if ( prompted.archive )
X	NewsGroup = &prompted;
X    else
X    {
X	/*
X	 *  Look for the Newsgroups line in the header
X	 */
X	do 
X	{
X	    fgets_buffer();
X	}
X	while ( strncmp(line, "Newsgroups: ", 12) != MATCH );
X
X	/*
X	 *  Is the newsgroup on the list?  Note that we only look
X	 *  at the first newsgroup that's specified.  
X	 */
X	if ( (NewsGroup = lookup(line)) == NGNULL )
X	{
X	    printf("Archive directory for %s? ", line);
X	    fflush(stdout);
X	    fgets(p_archive, sizeof(p_archive), tty);
X	    chop(p_archive);
X	    prompted.archive = p_archive;
X	    NewsGroup = &prompted;
X	}
X
X	/*
X	 *  If we find that we have a moderated newsgroup, we assume
X	 *  that somewhere there will be a line in the header that tells
X	 *  us about the current volume and the archive name of the 
X	 *  program that's in this article.
X	 */
X	if ( NewsGroup->moderated )
X	{
X	    if ( mode != PROMPT )
X		mode = SUBJECT;
X
X	    do
X	    {
X		fgets_buffer();
X	    }
X	    while ( strncmp(line, NewsGroup->volume_tag,
X			    strlen(NewsGroup->volume_tag)) != MATCH );
X
X	    vol = atoi(&line[strlen(NewsGroup->volume_tag) + 8 ]);
X	}
X    }
X
X    /*
X     *  Everything that we need to know about output is determined.
X     */
X    if ( NewsGroup->moderated )
X	sprintf(arc_dir, "%s/%s/v%02d", arcdir, NewsGroup->archive, vol);
X    else
X	sprintf(arc_dir, "%s/%s", arcdir, NewsGroup->archive);
X
X    if ( debug )
X    {
X	printf("Archive directory selected is: %s\n", arc_dir);
X	strcpy(arc_dir, ".");
X    }
X    else
X    {
X	if ( chdir(arc_dir) )
X	{
X	    sprintf(arc_file, "Could not chdir to %s", arc_dir);
X	    perror(arc_file);
X	    exit(1);
X	}
X    }
X
X    /*
X     *  The tmp file is created in the archive directory
X     */
X    mktemp(tmp_file);
X    if ( (out = fopen(tmp_file,"w")) == FNULL )
X    {
X	sprintf(arc_file, "Error opening %s" , tmp_file);
X	perror(arc_file);
X	exit(1);
X    };
X
X    /*
X     *  This is the "scratch" index that gets the raw data from
X     *  each article subject.  The user will extract one line for
X     *  each submission for the "real" index.
X     */
X    if ( (aindex = fopen(INDEXR, "a")) == FNULL )
X    {
X	perror("Error opening index");
X	exit(1);
X    };
X
X    /*
X     *  If we are not moderated and the user has not requested us
X     *  to prompt for names, then we need to generate a name.  No
X     *  advance preparation is required for this; if the .names file
X     *  does not exist, we will start naming at 000.
X     */
X    if ( !NewsGroup -> moderated && mode != PROMPT )
X    {
X	if ( (name_fd = open(".names", O_RDWR | O_CREAT, 0666)) == NULL )
X	{
X	    perror("Error opening .names");
X	    exit(1);
X	}
X
X	read(name_fd, &article_name, sizeof(int));
X	lseek(name_fd, 0L, L_SET);
X    }
X
X    /*
X     *  Now that we have somewhere to put the input, restart the input and
X     *  skip the first line which is (we hope) Path: ..
X     */
X    head_buf_ptr = head_buf;
X    fgets_unbuffer(line);
X    fputs(line, out);
X
X    /*
X     *  Process stdin until EOF.  We expect to have a sequence of net news
X     *  articles, each of which has a subject line.
X     */
X    while ( fgets_unbuffer() != PNULL )
X    {
X	if ( strncmp(line, "Path: ", 6) == MATCH )
X	    close_article();
X
X	/*
X	 *  Now that we have the new file (if that's what happened),
X	 *  dispose of the current line
X	 */
X	fputs(line, out);
X
X	/*
X	 *  Does this line define the archive name?
X	 */
X	if ( !named && (strncmp(line, "Archive-name: ", 13) == MATCH) )
X	{
X	    /*
X	     *  Process only one archive name per article
X	     */
X	    named = TRUE;
X
X	    strcpy(arc_name, &line[14]);
X	    *(strpbrk(arc_name, "/ \n")) = '\0';
X	}
X
X	/*
X	 *  Do we have a Subject?
X	 */
X	if ( !subjected && (strncmp(line, "Subject: ", 9) == MATCH) )
X	{
X	    /*
X	     *  Process only one Subject: per article
X	     */
X	    selected  = TRUE;
X	    subjected = TRUE;
X
X	    /*
X	     *  Generate a name, using the subject line is possible
X	     */
X
X	    /*
X	     *  First, drop the "Subject: "
X	     */
X	    subj = &line[9];
X
X	    /*
X	     *  Then, if this is a re-posting note the fact so that we
X	     *  don't hassle the user if the first posting happens to
X	     *  be in the archive and skip the "REPOST "
X	     */
X	    if ( strncmp(subj, "REPOST ", 7) == MATCH )
X	    {
X		subj += 7;
X		repost = TRUE;
X	    }
X
X	    /*
X	     *  How we generate the name depends on what kind of newsgroup
X	     */
X	    switch ( mode )
X	    {
X		case SUBJECT:		/* moderated groups */
X		    /*
X		     *  Tell the user what's happening
X		     */
X		    printf("%s", subj);
X
X		    /*
X		     *  Name should begin with something like v02i023:
X		     *  Assume this, and use the fist 7 characters for
X		     *  the file name
X		     */
X		    strncpy(arc_file, subj, 7);
X		    break;
X		case PROMPT:		/* user wants us to prompt for name */
X		    /*
X		     *  This is the article
X		     */
X		    printf("%s", subj);
X		    fputs("Output file? ", stdout);
X		    fflush(stdout);
X		    fgets(arc_name, sizeof(arc_name), tty);
X		    chop(arc_name);
X		    if ( strlen(arc_name) == 0 )
X		    {
X			/*
X			 *  User declines to save this item
X			 */
X			selected = FALSE;
X			continue;
X		    }
X		    strcpy(arc_file, arc_name);
X		    break;
X		case INDEX:		/* generate name */
X		    sprintf(arc_file, "%03d", article_name++);
X		    strcpy(arc_name, arc_file);
X		    /*
X		     *  Tell the user what we did
X		     */
X		    printf("%s: %s", arc_file, subj);
X		    break;
X		default:
X		    break;
X	    }
X	    strcpy(descr, subj);
X	}
X    }
X
X    close_article();
X    unlink(tmp_file);
X
X    if ( name_fd )
X    {
X	write(name_fd, &article_name, sizeof(int));
X	close(name_fd);
X    }
X}
END_OF_FILE
if test 11664 -ne `wc -c <'narc.c'`; then
    echo shar: \"'narc.c'\" unpacked with wrong size!
fi
# end of 'narc.c'
fi
if test -f 'patchlevel.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'patchlevel.h'\"
else
echo shar: Extracting \"'patchlevel.h'\" \(21 characters\)
sed "s/^X//" >'patchlevel.h' <<'END_OF_FILE'
X#define PATCHLEVEL 0
END_OF_FILE
if test 21 -ne `wc -c <'patchlevel.h'`; then
    echo shar: \"'patchlevel.h'\" unpacked with wrong size!
fi
# end of 'patchlevel.h'
fi
if test -f 'version.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'version.h'\"
else
echo shar: Extracting \"'version.h'\" \(22 characters\)
sed "s/^X//" >'version.h' <<'END_OF_FILE'
X#define VERSION "1.0"
END_OF_FILE
if test 22 -ne `wc -c <'version.h'`; then
    echo shar: \"'version.h'\" unpacked with wrong size!
fi
# end of 'version.h'
fi
if test -f 'Makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Makefile'\"
else
echo shar: Extracting \"'Makefile'\" \(117 characters\)
sed "s/^X//" >'Makefile' <<'END_OF_FILE'
Xnarc:	narc.o
X	cc -O -o narc narc.c
X
Xclean:
X	-rm core *.o narc
X
Xnarc.o:	narc.c
Xnarc.o:	version.h
Xnarc.o:	patchlevel.h
END_OF_FILE
if test 117 -ne `wc -c <'Makefile'`; then
    echo shar: \"'Makefile'\" unpacked with wrong size!
fi
# end of 'Makefile'
fi
echo shar: End of shell archive.
exit 0


-- 
Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.