v23i071: Complete reposting of TRN at patchlevel 1, Part12/14

Rich Salz rsalz at bbn.com
Sat Jan 5 08:06:03 AEST 1991


Submitted-by: Wayne Davison <0004475895 at mcimail.com>
Posting-number: Volume 23, Issue 71
Archive-name: trn/part12

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then feed it
# into a shell via "sh file" or similar.  To overwrite existing files,
# type "sh file -c".
# The tool that generated this appeared in the comp.sources.unix newsgroup;
# send mail to comp-sources-unix at uunet.uu.net if you want that tool.
# Contents:  MANIFEST Makefile.SH Rnmail.SH artio.c final.c kfile.h
#   newsetup.SH ngdata.c rthreads.c uudecode.c
# Wrapped by rsalz at litchi.bbn.com on Thu Dec 27 11:34:11 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
echo If this archive is complete, you will see the following message:
echo '          "shar: End of archive 12 (of 14)."'
if test -f 'MANIFEST' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MANIFEST'\"
else
  echo shar: Extracting \"'MANIFEST'\" \(5281 characters\)
  sed "s/^X//" >'MANIFEST' <<'END_OF_FILE'
XAfter unpacking, you should have the following files:
X
XFilename	Description
X--------	-----------
XConfigure       A shell script that installs everything system dependent.
XEXTERN.h        When included, makes other includes not belong to me.
XHACKERSGUIDE    A brief guide to the contorted innards of trn.
XINIT            Sample system-wide switch file.
XINTERN.h        When included, makes other includes belong to me.
XMANIFEST        This list of files.
XMakefile.SH     The makefile.
XNEW             List of new features with trn v1.0.
XPnews.1         Manual page for Pnews.
XPnews.SH        A news posting shell script that knows about -h.
XREADME          Installation instructions and other tidbits.
XRnmail.1        Manual page for Rnmail.
XRnmail.SH       A mailer that knows about -h.
XWishlist        What the next version wants in it.
Xaddng.c         Routines for scanning the active file for new newsgroups.
Xaddng.h         Public info regarding addng.c.
Xart.c           Routines to display an article.
Xart.h           Public info regarding art.c.
Xartio.c         Reserved for the article abstract type, someday.
Xartio.h         Public info regarding artio.c.
Xartsrch.c       Routines for searching among articles.
Xartsrch.h       Public info regarding artsrch.c.
Xartstate.h      Info on the current state of the article.
Xbackpage.c      Routines for paging backwards in articles.
Xbackpage.h      Public info regarding backpage.c.
Xbits.c          Bitmap management functions.
Xbits.h          Public info regarding bits.c.
Xcheat.c         Routines to do lookahead of several types.
Xcheat.h         Public info regarding cheat.c.
Xcommon.h        Global info.
Xfinal.c         Finalization (exit) routines.
Xfinal.h         Public info regarding final.c.
Xgetactive.c     Program used by shell scripts to the active file (trrn only).
Xgetdate.y       A yacc script for date parsing.
Xhead.c          Header parsing routines.
Xhead.h          Public info regarding head.c.
Xhelp.c          Help routines.
Xhelp.h          Public info regarding help.c.
Xinit.c          Initialization (startup) routines.
Xinit.h          Public info regarding init.c.
Xintrp.c         Filename expansion and % interpretation routines.
Xintrp.h         Public info regarding intrp.c.
Xkfile.c         KILL file routines.
Xkfile.h         Public info regarding kfile.c.
Xlast.c          Routines for handling the .rnlast file.
Xlast.h          Public info regarding last.c.
Xmakedepend.SH   Shell script to generate make dependencies.
Xmakedir.SH      Shell script to make nested subdirectories.
Xmbox.saver.SH   Shell script to save an article to a mailbox.
Xmt-lint.h       A kludge file included when lint'ing.
Xmt-process.c    Mthreads' article processing routines.
Xmt-read.c       Mthreads' data-file reading routines.
Xmt-write.c      Mthreads' data-file writing routines.
Xmt.check.SH     A sample mt.log checker/trimmer.
Xmthreads.1      The man page for mthreads.
Xmthreads.c      The main workloop for the mthreads database manager.
Xmthreads.h      The include file for accessing the 'mt' structures.
Xndir.c          4.2 directory routine emulation.
Xndir.h          Public info regarding ndir.c.
Xnewsetup.1      Manual page for newsetup.
Xnewsetup.SH     Shell script to create a .newsrc file.
Xnewsgroups.1    Manual page for newsgroups.
Xnewsgroups.SH   Shell script to list unsubscribed newsgroups.
Xnewsnews.SH     A motd-like file that trn may print at startup.
Xng.c            Routines to display a newsgroup.
Xng.h            Public info regarding ng.c.
Xngdata.c        General data fetching routines for a newsgroup.
Xngdata.h        Public info regarding ngdata.c.
Xngsrch.c        Routines to search among newsgroups.
Xngsrch.h        Public info regarding ngsrch.c.
Xngstuff.c       Support routines for ng.c.
Xngstuff.h       Public info regarding ng.c.
Xnorm.saver.SH   Shell script to save an article to a normal file.
Xonly.c          Routines to perform newsgroup restriction.
Xonly.h          Public info regarding only.c.
Xpatchlevel      Indicates current patch level.
Xrcln.c          Routines to mung a .newsrc line.
Xrcln.h          Public info regarding rcln.c.
Xrcstuff.c       Routines to mung the .newsrc file.
Xrcstuff.h       Public info regarding rcstuff.c.
Xrespond.c       Various routines for doing things with articles.
Xrespond.h       Public info regarding respond.c.
Xrn.c            Main program.
Xrn.h            Public info regarding rn.c.
Xrt-rn.c         Misc. threaded routines.
Xrt-select.c     The thread selector.
Xrthreads.c      Routines that read the thread data files in reader format.
Xrthreads.h      The include file for accessing the 'rt' structures.
Xsearch.c        Regular expression processing ala emacs.
Xsearch.h        Public info regarding search.c.
Xsw.c            Switch processing routines.
Xsw.h            Public info regarding switch.c.
Xterm.c          Terminal interface routines.
Xterm.h          Public info regarding term.c.
Xthreads.c       Routines common to both thread makers and readers.
Xthreads.h       The include file for common thread structures.
Xtrn.1           Manual pages for trn -- PLEASE READ.
Xutil.c          Utility routines.
Xutil.h          Public info regarding util.c.
Xuudecode.c      The uudecoder routines.
Xuudecode.h      The uudecoder's include file.
END_OF_FILE
  if test 5281 -ne `wc -c <'MANIFEST'`; then
    echo shar: \"'MANIFEST'\" unpacked with wrong size!
  fi
  # end of 'MANIFEST'
fi
if test -f 'Makefile.SH' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Makefile.SH'\"
else
  echo shar: Extracting \"'Makefile.SH'\" \(5981 characters\)
  sed "s/^X//" >'Makefile.SH' <<'END_OF_FILE'
Xcase $CONFIG in
X    '') . ./config.sh ;;
Xesac
Xecho "Extracting Makefile (with variable substitutions)"
Xcat >Makefile <<!GROK!THIS!
X# $Header: Makefile.SH,v 4.3.3.1 90/07/28 18:14:56 davison Trn $
X#
X# $Log:	Makefile.SH,v $
X# Revision 4.3.3.1  90/07/28  18:14:56  davison
X# Initial Trn Release
X# 
X# Revision 4.3.2.10  90/05/04  00:44:51  sob
X# Added socketlib to list of libs.
X# 
X# Revision 4.3.2.9  90/04/23  00:27:12  sob
X# Added better support for XENIX
X# 
X# Revision 4.3.2.8  89/12/20  23:20:14  sob
X# Added "hp-ux" to the list of files created by Configure.
X# 
X# Revision 4.3.2.7  89/12/09  01:49:48  sob
X# make clean cleans up better.
X# 
X# Revision 4.3.2.6  89/12/08  22:43:45  sob
X# Added suggestions by weening at gang-of-four.stanford.edu and 
X# jik at pit-manager.mit.edu. rrn manual page is now created when
X# doing an installation. getactive will only be made when rrn is being
X# created.
X# 
X# Revision 4.3.2.5  89/11/08  04:47:38  sob
X# Added VOIDSIG handling for SunOS 4.X
X# 
X# Revision 4.3.2.4  89/11/08  03:16:29  sob
X# Added server.h to list of things created by Configure
X# 
X# Revision 4.3.2.3  89/11/08  01:05:52  sob
X# Updated to work with RRN or RN
X# 
X# Revision 4.3.2.2  89/11/06  00:03:19  sob
X# Added RRN support originally distributed with NNTP 1.5
X# 
X# Revision 4.3.2.1  89/11/05  23:55:09  sob
X# RRN support branch
X#
X# Revision 4.3.1.2  85/05/13  17:21:18  lwall
X# System V make needs space before line-continuing backslash.
X# 
X# Revision 4.3.1.1  85/05/10  11:30:15  lwall
X# Branch for patches.
X# 
X# Revision 4.3  85/05/01  11:33:26  lwall
X# Baseline for release with 4.3bsd.
X# 
X
XCC = $cc
Xrnbin = $rnbin
Xrnlib = $rnlib
Xmansrc = $mansrc
Xmanext = $manext
X#NNTPNNTPDIR = $NNTPSRC
X#NNTPNNTPINC = $rrninclude
XCFLAGS = $iandd -O $include
XLDFLAGS = $iandd
XNDIRC = $ndirc
XNDIRO = $ndiro
X
Xlibs = $ndirlib $termlib $jobslib $socketlib
Xmlibs = $jobslib
X!GROK!THIS!
Xcat >>Makefile <<'!NO!SUBS!'
X#NNTPnntp=getactive
Xpublic = trn newsetup newsgroups Pnews Rnmail
Xprivate = norm.saver mbox.saver makedir\
X	filexp Pnews.header mthreads mt.check $(nntp)
Xmanpages = trn.1 Pnews.1 Rnmail.1 newsetup.1 newsgroups.1 mthreads.1
Xutil = Makefile makedepend newsnews
X
X
Xh1 = addng.h art.h artio.h artsrch.h backpage.h bits.h cheat.h common.h
Xh2 = final.h head.h help.h init.h intrp.h kfile.h last.h ndir.h ng.h
Xh3 = ngdata.h ngsrch.h ngstuff.h only.h rcln.h rcstuff.h
Xh4 = respond.h rn.h search.h sw.h term.h util.h uudecode.h
X#NNTPh5 = server.h
X
Xh = $(h1) $(h2) $(h3) $(h4) $(h5)
X
Xc1 = addng.c art.c artio.c artsrch.c backpage.c bits.c cheat.c
Xc2 = final.c head.c help.c init.c intrp.c kfile.c last.c $(NDIRC) ng.c
Xc3 = ngdata.c ngsrch.c ngstuff.c only.c rcln.c rcstuff.c respond.c rn.c
Xc4 = rthreads.c rt-rn.c rt-select.c search.c sw.c term.c threads.c util.c
Xc5 = uudecode.c
X#NNTPc6 = $(NNTPDIR)/common/clientlib.c
X
Xc = $(c1) $(c2) $(c3) $(c4) $(c5) $(c6)
Xmtc = mthreads.c mt-read.c mt-process.c mt-write.c threads.c $(c6)
X
Xobj1 = addng.o art.o artio.o artsrch.o backpage.o bits.o cheat.o
Xobj2 = final.o head.o help.o init.o intrp.o kfile.o last.o $(NDIRO) ng.o
Xobj3 = ngdata.o ngsrch.o ngstuff.o only.o rcln.o rcstuff.o respond.o rn.o
Xobj4 = rthreads.o rt-rn.o rt-select.o search.o sw.o term.o threads.o util.o
Xobj5 = uudecode.o
X#NNTPobj6 =  $(NNTPDIR)/common/clientlib.o
X
Xobj = $(obj1) $(obj2) $(obj3) $(obj4) $(obj5) $(obj6)
Xmtobj = mthreads.o mt-read.o mt-process.o mt-write.o threads.o getdate.o $(obj6)
X
Xlintflags = -phbvxac
X
Xadd1 = Makefile.old Pnews Rnmail
Xadd2 = bsd config.h config.sh eunice filexp
Xadd3 = loc makedepend makedir mbox.saver newsetup
Xadd4 = newsgroups newsnews norm.saver
Xadd5 = pdp11 usg v7 ultrix sun hp-ux pyr sgi xenix server.h
X
Xaddedbyconf = $(add1) $(add2) $(add3) $(add4) $(add5)
X
X# grrr
XSHELL = /bin/sh
X
X.c.o:
X	$(CC) -c $(CFLAGS) $*.c
X
Xall: $(public) $(private) $(util)
X	touch all
X
Xtrn: $(obj)
X	$(CC) $(LDFLAGS) $(obj) $(libs) -o trn
X
Xmthreads: $(mtobj)
X	$(CC) $(LDFLAGS) $(mtobj) $(mlibs) -o mthreads
X
X#NNTPgetactive: getactive.o $(NNTPDIR)/common/clientlib.o
X#NNTP	$(CC) $(LDFLAGS) getactive.o $(NNTPDIR)/common/clientlib.o -o getactive $(libs)
X
X# Eek! This is gross.
X$(NNTPDIR)/common/clientlib.o:
X	$(CC) -c $(CFLAGS) $(NNTPINC) $(NNTPDIR)/common/clientlib.c
X	mv clientlib.o $(NNTPDIR)/common/clientlib.o
X
X# if a .h file depends on another .h file...
X$(h):
X	touch $@
X
Xinstall: $(public) $(private) $(manpages)
X# won't work with csh
X	export PATH || exit 1
X	- mv $(rnbin)/trn $(rnbin)/trn.old
X#NNTP	- ln -s trn $(rnbin)/trrn
X	- if test `pwd` != $(rnbin); then cp $(public) $(rnbin); fi
X	cd $(rnbin); chmod 755 $(public); strip trn
X	chmod 755 makedir
X	- ./makedir `./filexp $(rnlib)`
X	- mv $(rnlib)/mthreads $(rnlib)/mthreads.old
X	- if test `pwd` != `./filexp $(rnlib)`; then cp INIT $(private) `./filexp $(rnlib)`; fi
X	- if test ! -f `./filexp $(rnlib)/newsnews`; then cp newsnews `./filexp $(rnlib)`; fi
X	cd `./filexp $(rnlib)`; chmod 755 $(private); chmod 644 INIT newsnews; strip mthreads
X	- if test `pwd` != $(mansrc); then \
Xfor page in $(manpages); do \
Xcp $$page $(mansrc)/`basename $$page .1`.$(manext); \
Xdone; \
X#NNTPecho ".so man$(manext)/trn.$(manext)" > $(mansrc)/trrn.$(manext) ; \
Xfi
X
Xclean:
X	rm -f *.o
X
Xrealclean:
X	rm -f trn mthreads *.o core $(addedbyconf) 
X#NNTP	rm -f $(NNTPDIR)/common/clientlib.o getactive
X
X# The following lint has practically everything turned on.  Unfortunately,
X# you have to wade through a lot of mumbo jumbo that can't be suppressed.
X# If the source file has a /*NOSTRICT*/ somewhere, ignore the lint message
X# for that spot.
X
Xlint: lint_trn lint_mt
X
Xlint_trn:
X	lint $(lintflags) $(defs) $(c) > trn.fuzz
X
Xlint_mt:
X	lint $(lintflags) $(mtc) > mt.fuzz
X
Xdepend:
X	./makedepend
X
X# AUTOMATICALLY GENERATED MAKE DEPENDENCIES--PUT NOTHING BELOW THIS LINE
X$(obj):
X	@ echo "You haven't done a "'"make depend" yet!'; exit 1
X!NO!SUBS!
Xcase "$isrrn" in
Xdefine)  sed < Makefile -e '/^#NNTP/s/^#NNTP//' > Makefile.new ;;
X*) sed < Makefile -e '/^#NNTP/d' > Makefile.new ;;
Xesac
Xmv Makefile.new Makefile
X$eunicefix Makefile
END_OF_FILE
  if test 5981 -ne `wc -c <'Makefile.SH'`; then
    echo shar: \"'Makefile.SH'\" unpacked with wrong size!
  fi
  chmod +x 'Makefile.SH'
  # end of 'Makefile.SH'
fi
if test -f 'Rnmail.SH' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Rnmail.SH'\"
else
  echo shar: Extracting \"'Rnmail.SH'\" \(6334 characters\)
  sed "s/^X//" >'Rnmail.SH' <<'END_OF_FILE'
Xcase $CONFIG in
X    '') . ./config.sh ;;
Xesac
Xecho "Extracting Rnmail (with variable substitutions)"
X$spitshell >Rnmail <<!GROK!THIS!
X$startsh
X# $Header: Rnmail.SH,v 4.3.3.2 90/08/20 16:22:29 davison Trn $
X# 
X# $Log:	Rnmail.SH,v $
X# Revision 4.3.3.2  90/08/20  16:22:29  davison
X# Use mbox.saver for MAILRECORD.  Fixed sitename handling.
X# 
X# Revision 4.3.3.1  90/07/24  22:02:49  davison
X# Initial Trn Release
X# 
X# Revision 4.3.2.1  89/11/06  00:30:54  sob
X# Added RRN support from NNTP 1.5
X# 
X# Revision 4.3.1.4  85/08/01  14:23:05  lwall
X# Added MAILRECORD.  Temp file is no longer in /tmp.  'e editor' added.
X# 
X# Revision 4.3.1.3  85/05/20  16:25:17  lwall
X# Shouldn't ask editor if EDITOR or VISUAL defined.
X# 
X# Revision 4.3.1.2  85/05/17  10:36:19  lwall
X# Added "-- " before .signature.
X# 
X# Revision 4.3.1.1  85/05/10  11:30:38  lwall
X# Branch for patches.
X# 
X# Revision 4.3  85/05/01  11:34:18  lwall
X# Baseline for release with 4.3bsd.
X# 
X#
X# syntax: Rnmail -h headerfile [oldart]		or
X#         Rnmail destination-list 		or just
X#         Rnmail
X
Xexport PATH || (echo "OOPS, this isn't sh.  Desperation time.  I will feed myself to sh."; sh \$0; kill \$\$)
X
X# System dependencies
X
Xmailer="${mailer-/bin/mail}"
X# if you change this to something that does signatures, take out signature code
X
X# your site name
Xcase $portable in
Xdefine)
X	case "$hostcmd" in
X	'') sitename="$sitename" ;;
X	*)  sitename=\`$hostcmd\` ;;
X	esac
X	case \$sitename in
X		*.*)
X			;;
X		*)
X			sitename=\${sitename}.$domain
X			;;
X	esac
X	;;
Xundef) sitename="$sitename" ;;
Xesac
X# your organization name
Xorgname="$orgname"
X# what pager you use--if you have kernal paging use cat
Xpager="\${PAGER-$pager}"
X# how you derive full names, bsd, usg, or other
Xnametype="$nametype"
X# default editor
Xdefeditor="$defeditor"
X# how not to do a newline with echo
Xn="$n"
Xc="$c"
X
Xtest=${test-test}
Xsed=${sed-sed}
Xecho=${echo-echo}
Xcat=${cat-cat}
Xgrep=${grep-grep}
Xrm=${rm-rm}
X
X!GROK!THIS!
X$spitshell >>Rnmail <<'!NO!SUBS!'
Xdotdir=${DOTDIR-${HOME-$LOGDIR}}
Xtmpart=$dotdir/.letter
X
Xheaderfile=""
Xcase $# in
X0) ;;
X*)  case $1 in
X    -h)
X	headerfile="$2"
X	case $# in
X	3) oldart=$3 ;;
X	esac
X	;;
X    esac
X    ;;
Xesac
X
Xcase $headerfile in
X'')
X    case $# in
X    0)
X	to=h
X	while $test "$to" = h ; do
X	    $echo ""
X	    $echo $n "To: $c"
X	    read to
X	    case $to in
X	    h)
X		$cat <<'EOH'
X
XType the net address of those people that you wish the message sent to.
XAdditional recipients may be added on the Cc: line when you edit.
X
XSeparate multiple addresses with spaces.
X
XEOH
X		;;
X	    esac
X	done
X	;;
X    *)
X	to="$*"
X	;;
X    esac
X    to=`$echo "$to" | $sed 's/  */ /g'`
X
X    title=h
X    while $test "$title" = h ; do
X	$echo ""
X	$echo $n "Title/Subject: $c"
X	read title
X	case $title in
X	h)
X	    $cat <<'EOH'
X
XType the title for your message.  
XEOH
X	    ;;
X	esac
X    done
X
X# now build a file with a header for them to edit
X    
X    orgname=${ORGANIZATION-$orgname}
X    case $orgname in
X    /*) orgname=`$cat $orgname` ;;
X    esac
X
X    $sed -e '/^Reply-To: $/d' > $tmpart <<EOHeader
XTo: $to
XSubject: $title
XOrganization: $orgname
XReply-To: $REPLYTO
XCc:
XBcc:
X
XEOHeader
X
X    ;;
X*)
X    $cat < $headerfile  > $tmpart
X    ;;
Xesac
X
X
Xfile=h
Xwhile $test "$file" = h ; do
X    $echo ""
X    $echo $n "Prepared file to include [none]: $c"
X    read file
X    case $file in
X    h)
X	$cat <<'EOH'
X
XIf you have already produced the body of your message, type the filename
Xfor it here.  If you just want to proceed directly to the editor, type a
XRETURN.  In any event, you will be allowed to edit as many times as you
Xwant before you send off the message.
XEOH
X	;;
X    '')
X	$echo "" >> $tmpart
X	state=edit
X	;;
X    *)
X	$cat $file >>$tmpart
X	state=ask
X	;;
X    esac
Xdone
X
X$echo ""
X
Xwhile true ; do
X    case $state in
X    edit)
X	rescue="sleep 1; $cat $tmpart >>${HOME-$LOGDIR}/dead.letter ; $echo Message appended to ${HOME-$LOGDIR}/dead.letter ; exit"
X	trap "$rescue" 1
X	trap : 2
X	case "${VISUAL-${EDITOR-}}" in
X	'')
X	    tmp=h
X	    ;;
X	*)
X	    tmp=''
X	    ;;
X	esac
X	while $test "$tmp" = h ; do
X	    $echo $n "Editor [${VISUAL-${EDITOR-$defeditor}}]: $c"
X	    read tmp
X	    case $tmp in
X	    h)
X		$cat <<'EOH'
X
XType a return to get the default editor, or type the name of the editor you
Xprefer.  The default editor depends on the VISUAL and EDITOR environment
Xvariables.
X
XEOH
X		;;
X	    '')
X		;;
X	    *)
X		VISUAL=$tmp
X		export VISUAL
X		;;
X	    esac
X	done
X	${VISUAL-${EDITOR-$defeditor}} $tmpart $oldart
X	trap "$rescue" 2
X	state=ask
X	;;
X	
X    ask)
X	$echo ""
X	$echo $n "Send, abort, edit, or list? $c"
X	read ans
X	
X	case $ans in
X	a*)
X	    state=rescue
X	    ;;
X	e*)
X	    set $ans
X	    case $# in
X	    2)  VISUAL="$2" ;;
X	    esac
X	    state=edit
X	    ;;
X	l*)
X	    $pager $tmpart
X	    state=ask
X	    ;;
X	s*)
X	    state=send
X	    ;;
X	h*)
X	    $cat <<'EOH'
X
XType s to send the message, a to abort and append the message to dead.letter,
Xe to edit the message again, or l to list the message.
X
XTo invoke an alternate editor, type 'e editor'.
XEOH
X	esac
X	;;
X    
X    send)
X	if $test -f $dotdir/.signature; then
X	    echo $n "Append .signature file? [y] $c"
X	    read ans
X	    case $ans in
X	    ''|y*)
X		echo "-- " >> $tmpart
X		cat $dotdir/.signature >> $tmpart
X		;;
X	    esac
X	fi
X	case $mailer in
X	*sendmail)
X	    $mailer -t <$tmpart
X	    ;;
X# but recmail does not know about Bcc, alas
X	*recmail)
X	    $mailer <$tmpart
X	    ;;
X	*)
X	    set X `$sed <$tmpart -n -e '/^To:/{' -e 's/To: *//p' -e q -e '}'`
X	    shift
X	    set X "$@" `$sed <$tmpart -n -e '/^Cc:/{' -e 's/Cc: *//p' -e q -e '}'`
X	    shift
X	    set X "$@" `$sed <$tmpart -n -e '/^Bcc:/{' -e 's/Bcc: *//p' -e q -e '}'`
X	    shift
X	    $grep -v "^Bcc:"  <$tmpart | $mailer "$@"
X	    ;;
X	esac
X	case $? in
X	0)
X	    state=cleanup
X	    ;;
X	*)
X	    state=rescue
X	    ;;
X	esac
X	;;
X    rescue)
X	$cat $tmpart >> ${HOME-$LOGDIR}/dead.letter
X	$echo "Message appended to ${HOME-$LOGDIR}/dead.letter"
X	$echo "A copy may be temporarily found in $tmpart"
X	exit
X	;;
X    cleanup)
X	case "${MAILRECORD-none}" in
X	none)
X	    ;;
X	*)
X	    set X ${USER-${LOGNAME-`who am i`}} unknown
X	    shift
X	    $rnlib/mbox.saver $tmpart "." "." 0 0 Pnews $MAILRECORD "From $1 `date`"
X	    if $test $? -eq 0 ; then
X		$echo "Message appended to $MAILRECORD"
X	    else
X		$echo "Cannot append to $MAILRECORD"
X	    fi
X	    ;;
X	esac
X	exit
X	;;
X    esac
Xdone
X!NO!SUBS!
X$eunicefix Rnmail
Xchmod 755 Rnmail
END_OF_FILE
  if test 6334 -ne `wc -c <'Rnmail.SH'`; then
    echo shar: \"'Rnmail.SH'\" unpacked with wrong size!
  fi
  chmod +x 'Rnmail.SH'
  # end of 'Rnmail.SH'
fi
if test -f 'artio.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'artio.c'\"
else
  echo shar: Extracting \"'artio.c'\" \(4781 characters\)
  sed "s/^X//" >'artio.c' <<'END_OF_FILE'
X/* $Header: artio.c,v 4.3.3.2 90/08/20 16:25:50 davison Trn $
X *
X * $Log:	artio.c,v $
X * Revision 4.3.3.2  90/08/20  16:25:50  davison
X * Fixed bug in artopen ==> nntpopen interaction.
X * 
X * Revision 4.3.3.1  90/07/21  20:11:03  davison
X * Initial Trn Release
X * 
X * Revision 4.3.2.5  90/03/22  23:04:04  sob
X * Fixes provided by Wayne Davison <drivax!davison>
X * 
X * Revision 4.3.2.4  89/11/27  01:29:57  sob
X * Altered NNTP code per ideas suggested by Bela Lubkin
X * <filbo at gorn.santa-cruz.ca.us>
X * 
X * Revision 4.3.2.3  89/11/26  22:55:31  sob
X * Add nntpopen() and nntpclose() routines to cut down on size of rrn
X * 
X * Revision 4.3.2.2  89/11/08  01:17:12  sob
X * Added changes to insure that this will compile for RN or RRN with no
X * changes to the source code.
X * 
X * Revision 4.3.2.1  89/11/06  00:07:25  sob
X * Added RRN support from NNTP 1.5
X * 
X * Revision 4.3  85/05/01  11:35:39  lwall
X * Baseline for release with 4.3bsd.
X * 
X */
X
X#include "EXTERN.h"
X#include "common.h"
X#ifdef SERVER
X#include "server.h"
X#endif
X#include "INTERN.h"
X#include "artio.h"
X
Xvoid
Xartio_init()
X{
X    ;
X}
X
X/* open an article, unless it's already open */
X
XFILE *
Xartopen(artnum)
XART_NUM artnum;
X{
X#ifdef SERVER
X    return nntpopen(artnum,GET_ARTICLE);
X#else
X    char artname[32];			/* filename of current article */
X
X    if (artnum < 1)
X	return Nullfp;
X    if (openart == artnum) {		/* this article is already open? */
X	fseek(artfp,0L,0);		/* just get to the beginning */
X	return artfp;			/* and say we succeeded */
X    }
X    if (artfp != Nullfp) {		/* it was somebody else? */
X	fclose(artfp);			/* put them out of their misery */
X	openart = 0;			/* and remember them no more */
X    }
X    sprintf(artname,"%ld",(long)artnum);
X					/* produce the name of the article */
X    if (artfp = fopen(artname,"r"))	/* if we can open it */
X	openart = artnum;		/* remember what we did here */
X#ifdef LINKART
X    {
X	char tmpbuf[256];
X	char *s;
X
X	if (fstat(artfp->_file,&filestat))
X	    return artfp;
X	if (filestat.st_size < (sizeof tmpbuf)) {
X	    fgets(tmpbuf,(sizeof tmpbuf),artfp);
X	    if (*tmpbuf == '/') {	/* is a "link" to another article */
X		fclose(artfp);
X		if (s=index(tmpbuf,'\n'))
X		    *s = '\0';
X		if (!(artfp = fopen(tmpbuf,"r")))
X		    openart = 0;
X		else {
X		    if (*linkartname)
X			free(linkartname);
X		    linkartname = savestr(tmpbuf);
X		}
X	    }
X	    else
X		fseek(artfp,0L,0);		/* get back to the beginning */
X	}
X    }
X#endif
X    return artfp;			/* and return either fp or NULL */
X#endif /* SERVER */
X}
X
X#ifdef SERVER
Xstatic long our_pid;
X
XFILE *
Xnntpopen(artnum,function)
XART_NUM artnum;
XART_PART function;
X{
X    char ser_line[256];
X    char artname[32];			/* filename of current article */
X    if (our_pid == 0)
X	our_pid = getpid();
X    if (artnum < 1)
X	return Nullfp;
X    if ((openart == artnum) && (openpart >= function))
X    {					/* this article is already open? */
X	fseek(artfp,0L,0);		/* just get to the beginning */
X	return artfp;			/* and say we succeeded */
X    }
X    if (artfp != Nullfp) {		/* it was somebody else? */
X	fclose(artfp);			/* put them out of their misery */
X	nntpclose();
X	openart = 0;			/* and remember them no more */
X    }
X    sprintf(artname,"/tmp/rrn%ld.%ld", (long) artnum, our_pid);
X    artfp = fopen(artname, "w+");	/* create the temporary article */
X    if (artfp == Nullfp) {
X	UNLINK(artname);
X	return Nullfp;
X    }
X    switch (function){
X	    case GET_STATUS:
X		function = GET_HEADER;	/* fall through */
X	    case GET_HEADER:
X		sprintf(ser_line, "HEAD %ld", (long)artnum);
X		break;
X	    case GET_ARTICLE:
X		sprintf(ser_line, "ARTICLE %ld", (long)artnum);
X		break;
X    }	    
X    put_server(ser_line);		/* ask the server for the article */
X    if (get_server(ser_line, sizeof(ser_line)) < 0) {
X	fprintf(stderr, "rrn: Unexpected close of server socket.\n");
X	finalize(1);
X    }
X    if (*ser_line != CHAR_OK) {		/* and get it's reaction */
X	fclose(artfp);
X	artfp = Nullfp;
X	UNLINK(artname);
X 	errno = ENOENT;		/* Simulate file-not-found */
X        return Nullfp;
X    }
X
X    for (;;) {
X        if (get_server(ser_line, sizeof(ser_line)) < 0) {
X	    fprintf(stderr, "rrn: Unexpected close of server socket.\n");
X	    finalize(1);
X	}
X	if (ser_line[0] == '.' && ser_line[1] == '\0')
X		break;
X	fputs((ser_line[0] == '.' ? ser_line + 1 : ser_line), artfp);
X	putc('\n', artfp);
X    }
X    openpart = function;
X    if (function == GET_HEADER)
X	 putc('\n', artfp); /* req'd blank line after header */
X    fseek(artfp, 0L, 0);		/* Then get back to the start */
X    openart = artnum;
X    return artfp;			/* and return either fp or NULL */
X}
X
Xvoid
Xnntpclose()
X{
X    char artname[32];			/* filename of current article */
X    if (our_pid == 0)
X	our_pid = getpid();
X    sprintf(artname, "/tmp/rrn%ld.%ld", (long) openart, our_pid);
X    UNLINK(artname);
X}
X#endif
END_OF_FILE
  if test 4781 -ne `wc -c <'artio.c'`; then
    echo shar: \"'artio.c'\" unpacked with wrong size!
  fi
  # end of 'artio.c'
fi
if test -f 'final.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'final.c'\"
else
  echo shar: Extracting \"'final.c'\" \(5193 characters\)
  sed "s/^X//" >'final.c' <<'END_OF_FILE'
X/* $Header: final.c,v 4.3.3.1 90/06/20 22:36:57 davison Trn $
X *
X * $Log:	final.c,v $
X * Revision 4.3.3.1  90/06/20  22:36:57  davison
X * Initial Trn Release
X * 
X * Revision 4.3.2.8  90/04/14  19:37:14  sob
X * Added better support for the NeXT.
X * 
X * Revision 4.3.2.7  90/03/17  21:33:49  sob
X * cleaned up a bit
X * 
X * Revision 4.3.2.6  90/03/17  16:48:25  sob
X * Added changes to insure that rrn cleans up its temporary files when
X * exiting.
X * 
X * Revision 4.3.2.5  89/11/28  01:51:28  sob
X * Now handles SIGWINCH correctly.
X * 
X * Revision 4.3.2.4  89/11/27  01:30:24  sob
X * Altered NNTP code per ideas suggested by Bela Lubkin
X * <filbo at gorn.santa-cruz.ca.us>
X * 
X * Revision 4.3.2.3  89/11/08  02:25:07  sob
X * Integrated modifications from other RRN patches colleceted from USENET
X * 
X * Revision 4.3.2.2  89/11/07  23:26:31  sob
X * Added some fixes that relate to SIGSTP
X * 
X * Revision 4.3.2.1  89/11/06  00:16:08  sob
X * Added RRN support from NNTP 1.5
X *
X * Revision 4.3  85/05/01  11:38:08  lwall
X * Baseline for release with 4.3bsd.
X * 
X */
X
X#include "EXTERN.h"
X#include "common.h"
X#include "util.h"
X#include "term.h"
X#include "ng.h"
X#include "init.h"
X#include "bits.h"
X#include "last.h"
X#include "rcstuff.h"
X#include "ngdata.h"
X#include "artio.h"
X#include "INTERN.h"
X#include "final.h"
X
Xvoid
Xfinal_init()
X{
X#ifdef SIGTSTP
X    sigset(SIGTSTP, stop_catcher);	/* job control signals */
X    sigset(SIGTTOU, stop_catcher);	/* job control signals */
X    sigset(SIGTTIN, stop_catcher);	/* job control signals */
X#endif
X
X    sigset(SIGINT, int_catcher);	/* always catch interrupts */
X    sigset(SIGHUP, sig_catcher);	/* and hangups */
X#ifndef lint
X    sigignore(SIGEMT);
X#endif /* lint */
X
X    sigset(SIGILL, sig_catcher);
X    sigset(SIGTRAP, sig_catcher);
X    sigset(SIGFPE, sig_catcher);
X    sigset(SIGBUS, sig_catcher);
X    sigset(SIGSEGV, sig_catcher);
X    sigset(SIGSYS, sig_catcher);
X    sigset(SIGTERM, sig_catcher);
X#ifdef SIGXCPU
X    sigset(SIGXCPU, sig_catcher);
X#endif
X#ifdef SIGXFSZ
X    sigset(SIGXFSZ, sig_catcher);
X#endif
X#ifdef SIGWINCH
X    sigset(SIGWINCH, winch_catcher);
X#endif
X}
X
Xvoid					/* very much void */
Xfinalize(status)
Xint status;
X{
X#ifdef SERVER
X    char artname[32];
X#endif /* SERVER */
X
X    if (bizarre)
X	resetty();
X    if (lockname && *lockname)
X 	UNLINK(lockname);
X#ifdef SERVER
X    if (*active_name)
X	UNLINK(active_name);
X    if (openart) {
X 	char artname[32];
X 	sprintf(artname, "/tmp/rrn%ld.%d", (long)openart, getpid());
X 	UNLINK(artname);
X    }
X    close_server();
X#endif /* SERVER */
X    if (status < 0) {
X	chdir("/usr/tmp");
X	sigset(SIGILL,SIG_DFL);
X	abort();
X    }
X    exit(status);
X}
X
X/* come here on interrupt */
X
Xint
Xint_catcher()
X{
X    sigset(SIGINT,int_catcher);
X#ifdef DEBUGGING
X    if (debug)
X	write(2,"int_catcher\n",12);
X#endif
X    if (!waiting) {
X	if (int_count) {		/* was there already an interrupt? */
X	    write(2,"\nBye-bye.\n",10);
X	    sig_catcher(0);		/* emulate the other signals */
X	}
X	int_count++;
X    }
X}
X
X/* come here on signal other than interrupt, stop, or cont */
X
Xint
Xsig_catcher(signo)
X{
X#ifdef VERBOSE
X    static char *signame[] = {
X	"",
X	"HUP",
X	"INT",
X	"QUIT",
X	"ILL",
X	"TRAP",
X	"IOT",
X	"EMT",
X	"FPE",
X	"KILL",
X	"BUS",
X	"SEGV",
X	"SYS",
X	"PIPE",
X	"ALRM",
X	"TERM",
X	"???"
X#ifdef SIGTSTP
X	,"STOP",
X	"TSTP",
X	"CONT",
X	"CHLD",
X	"TTIN",
X	"TTOU",
X	"TINT",
X	"XCPU",
X	"XFSZ"
X#ifdef SIGPROF
X	,"VTALARM",
X	"PROF"
X#endif
X#endif
X	};
X#endif
X
X#ifdef DEBUGGING
X    if (debug) {
X	printf("\nSIG%s--.newsrc not restored in debug\n",signame[signo]);
X	finalize(-1);
X    }
X#endif
X    if (panic)
X	abort();
X    (void) sigset(SIGILL,SIG_DFL);
X    panic = TRUE;			/* disable terminal I/O */
X    if (doing_ng) {			/* need we reconstitute rc line? */
X	yankback();
X	restore_ng();			/* then do so (hope this works) */
X    }
X    doing_ng = FALSE;
X    if (rc_changed)			/* need we write .newsrc out? */
X	write_rc();			/* then do so */
X    rc_changed = FALSE;
X    if (signo != SIGHUP)
X#ifdef VERBOSE
X	IF(verbose)
X	    printf("\nCaught %s%s--.newsrc restored\n",
X		signo ? "a SIG" : "an internal error", signame[signo]);
X	ELSE
X#endif
X#ifdef TERSE
X	    printf("\nSignal %d--bye bye\n",signo);
X#endif
X    switch (signo) {
X    case SIGBUS:
X    case SIGILL:
X    case SIGSEGV:
X	finalize(-signo);
X    }
X    finalize(1);				/* and blow up */
X}
X
X#ifdef SIGTSTP
X/* come here on stop signal */
X
Xint
Xstop_catcher(signo)
Xint signo;
X{
X    if (!waiting) {
X	checkpoint_rc();		/* good chance of crash while stopped */
X	if (clear_on_stop) {
X	    clear();
X	    putchar('\n') FLUSH;
X	}
X	resetty();			/* this is the point of all this */
X#ifdef DEBUGGING
X	if (debug)
X	    write(2,"stop_catcher\n",13);
X#endif
X	sigset(signo,SIG_DFL);	/* enable stop */
X#ifdef SIGBLOCK
X	sigsetmask(sigblock(0) & ~(1 << (signo-1)));
X#endif
X	kill(0,signo);		/* and do the stop */
X    	savetty();
X#ifdef MAILCALL
X    	mailcount = 0;			/* force recheck */
X#endif
X    	if (!panic) {
X	    if (!waiting) {
X	    	noecho();			/* set no echo */
X	    	crmode();			/* set cbreak mode */
X	    	forceme("\f");		/* cause a refresh */
X					/* (defined only if TIOCSTI defined) */
X		errno = 0;			/* needed for getcmd */
X	    }
X    	}
X    }
X    sigset(signo,stop_catcher);	/* unenable the stop */
X}
X#endif
END_OF_FILE
  if test 5193 -ne `wc -c <'final.c'`; then
    echo shar: \"'final.c'\" unpacked with wrong size!
  fi
  # end of 'final.c'
fi
if test -f 'kfile.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'kfile.h'\"
else
  echo shar: Extracting \"'kfile.h'\" \(530 characters\)
  sed "s/^X//" >'kfile.h' <<'END_OF_FILE'
X/* $Header: kfile.h,v 4.3 85/05/01 11:42:00 lwall Exp $
X *
X * $Log:	kfile.h,v $
X * Revision 4.3  85/05/01  11:42:00  lwall
X * Baseline for release with 4.3bsd.
X * 
X */
X
X#define KF_GLOBAL 0
X#define KF_LOCAL 1
X
X#ifdef KILLFILES
XEXT FILE *globkfp INIT(Nullfp);		/* global article killer file */
XEXT FILE *localkfp INIT(Nullfp);	/* local (for this newsgroup) */
X					/*  article killer file */
X#endif
X
Xvoid	kfile_init();
Xint	do_kfile();
Xvoid	kill_unwanted();
Xint	edit_kfile();
Xvoid	open_kfile();
Xvoid    kf_append();
Xvoid	setthru();
X
END_OF_FILE
  if test 530 -ne `wc -c <'kfile.h'`; then
    echo shar: \"'kfile.h'\" unpacked with wrong size!
  fi
  # end of 'kfile.h'
fi
if test -f 'newsetup.SH' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'newsetup.SH'\"
else
  echo shar: Extracting \"'newsetup.SH'\" \(5105 characters\)
  sed "s/^X//" >'newsetup.SH' <<'END_OF_FILE'
Xcase $CONFIG in
X    '') . ./config.sh ;;
Xesac
Xecho "Extracting newsetup (with variable substitutions)"
X$spitshell >newsetup <<!GROK!THIS!
X$startsh
X
X# $Header: newsetup.SH,v 4.3.2.7 90/03/17 20:34:48 sob Exp $
X# 
X# $Log:	newsetup.SH,v $
X# Revision 4.3.2.7  90/03/17  20:34:48  sob
X# Remove the /tmp/n.* files created when generating the .newsrc.
X# 
X# Revision 4.3.2.6  90/03/17  17:26:42  sob
X# Some versions of sed only take 9 wfiles.
X# 
X# Revision 4.3.2.5  89/11/28  01:15:32  sob
X# Fixed a bug that caused the active file to be removed on non-NNTP-based
X# systems.
X# 
X# Revision 4.3.2.4  89/11/28  00:31:20  sob
X# Changed news.announce.newuser to news.announce.newusers.
X# 
X# Revision 4.3.2.3  89/11/08  01:13:15  sob
X# Finished modifications to make work with RN and RRN
X#
X# Revision 4.3.2.2  89/11/07  23:25:50  sob
X#
X# Added support such that RN and RRN can be made from the same sources.
X# 
X# Revision 4.3.1.2  86/09/05  15:41:04  lwall
X# Changes for newsgroup renaming.
X# 
X# Revision 4.3.1.1  85/05/10  11:35:43  lwall
X# Branch for patches.
X# 
X# Revision 4.3  85/05/01  11:43:05  lwall
X# Baseline for release with 4.3bsd.
X# 
X
Xexport PATH || (echo "OOPS, this isn't sh.  Desperation time.  I will feed myself to sh."; sh \$0; kill \$\$)
X
X: syntax: newsetup
X
X: System dependencies
X: You will want to change the definitions below to reflect the distribution
X: areas around you.  If you have more areas than this you will need to modify
X: the sed below.
X
Xlocorg="$locpref"
Xorganization="$orgpref"
Xcity="$citypref"
Xstate="$statepref"
Xcntry="$cntrypref"
Xcont="$contpref"
X#NORMALactive="${active-/usr/lib/news/active}"
X#NNTPactive="/tmp/active.\$\$"
X
Xdotdir="\${DOTDIR-\${HOME-\$LOGDIR}}"
X$rm -f \$dotdir/.oldnewsrc
X$echo "Creating .newsrc in \$dotdir to be used by news programs."
X#NNTPrnlib=$rnlib
X#NNTPcase \$rnlib in
X#NNTP~*) rnlib=\`$filexp \$rnlib\` ;;
X#NNTPesac
X#NNTP\$rnlib/getactive \$active
X#NORMALcase \$active in
X#NORMAL~*) active=\`$filexp \$active\` ;;
X#NORMALesac
X
X: NOTE: SED WILL NOT TAKE MORE THAN 9 WFILES, SO BEWARE   
X
X$sort <\$active | $sed >/tmp/n.tmp\$\$	\\
X	-e 's/^\([^ ]*\) .*\$/\1:/'	\\
X	-e '/^control:/{'		\\
X 	-e "  s/:/!/"	\\
X	-e "  w /tmp/n.test\$\$"	\\
X	-e '  d'			\\
X	-e '}'				\\
X	-e '/^junk:/{'			\\
X 	-e "  s/:/!/"	\\
X	-e "  w /tmp/n.test\$\$"	\\
X	-e '  d'			\\
X	-e '}'				\\
X	-e '/test:/{'			\\
X 	-e "  s/:/!/"	\\
X	-e "  w /tmp/n.test\$\$"	\\
X	-e '  d'			\\
X	-e '}'				\\
X	-e "/^\$locorg\./{"		\\
X	-e "  w /tmp/n.\$locorg\$\$"	\\
X	-e '  d'			\\
X	-e '}'				\\
X	-e "/^\$organization\./{"	\\
X	-e "  w /tmp/n.\$organization\$\$"	\\
X	-e '  d'			\\
X	-e '}'				\\
X	-e "/^\$city\./{"		\\
X	-e "  w /tmp/n.\$city\$\$"	\\
X	-e '  d'			\\
X	-e '}'				\\
X	-e "/^\$cntry\./{" 		\\
X	-e "  w /tmp/n.\$cntry\$\$"	\\
X	-e '  d'			\\
X	-e '}'				\\
X	-e "/^\$state\./{" 		\\
X	-e "  w /tmp/n.\$state\$\$"	\\
X	-e '  d'			\\
X	-e '}'
X
X$sed </tmp/n.tmp\$\$ >/tmp/n.local\$\$	\\
X	-e "/^\$cont\./{" 		\\
X	-e "  w /tmp/n.\$cont\$\$"	\\
X	-e '  d'			\\
X	-e '}'
X
X$sed </tmp/n.tmp\$\$ >/tmp/n.local\$\$	\\
X	-e "/^to\./{"			\\
X	-e "  s/:/!/"	\\
X	-e "  w /tmp/n.to\$\$"		\\
X	-e '  d'			\\
X	-e '}'				\\
X	-e "/^comp\./{"			\\
X	-e "  w /tmp/n.comp\$\$"	\\
X	-e '  d'			\\
X	-e '}'				\\
X	-e "/^news\./{"			\\
X	-e "  w /tmp/n.news\$\$"	\\
X	-e '  d'			\\
X	-e '}'				\\
X	-e "/^rec\./{"			\\
X	-e "  w /tmp/n.rec\$\$"		\\
X	-e '  d'			\\
X	-e '}'				\\
X	-e "/^sci\./{"			\\
X	-e "  w /tmp/n.sci\$\$"		\\
X	-e '  d'			\\
X	-e '}'				\\
X	-e "/^soc\./{"			\\
X	-e "  w /tmp/n.soc\$\$"		\\
X	-e '  d'			\\
X	-e '}'				\\
X	-e "/\./{"			\\
X	-e "  w /tmp/n.misc\$\$"	\\
X	-e '  d'			\\
X	-e '}'
X
X
Xif $test -s \$dotdir/.newsrc ; then
X    $echo "Saving your current .newsrc as .oldnewsrc..."
X    $mv -f \$dotdir/.newsrc \$dotdir/.oldnewsrc
Xfi
X
X: newsrc order determined here
X
X$sed <\$active '
X	/^to\./d
X	s/ .*//
X	s/^/ /
X	s/^ '\$locorg'\./01&/
X	s/^ '\$organization'\./02&/
X	s/^ '\$city'\./03&/
X	s/^ '\$state'\./04&/
X	s/^ '\$cntry'\./05&/
X	s/^ '\$cont'\./06&/
X	s/^ news\./07&/
X	s/^ comp\./08&/
X	s/^ sci\./09&/
X	s/^ rec\./10&/
X	s/^ soc\./11&/
X	s/^ talk\./13&/
X	s/^ control\$/14&/
X	s/^ junk\$/14&/
X	s/^ test\$/14&/
X	/\.test\$/s/^[0-9]*/14/
X	s/^ .*\./12&/
X	s/^ /00&/
X' |
X$sort -u |
X$sed '
X	/^14 /!s/\$/:/
X	/^14 /s/\$/!/
X	s/^[0-9][0-9] //
X' >\$dotdir/.newsrc
X
X#NNTP$rm -f \$active
X$rm -f /tmp/n.misc\$\$ /tmp/n.sci\$\$ /tmp/n.soc\$\$ /tmp/n.news\$\$ /tmp/n.comp\$\$
X$rm -f /tmp/n.\$cont\$\$ /tmp/n.\$city\$\$ /tmp/n.\$cntry\$\$ /tmp/n.\$state\$\$
X$rm -f /tmp/n.to\$\$ /tmp/n.\$organization\$\$ /tmp/n.\$locorg\$\$ /tmp/n.test\$\$
X$rm -f /tmp/n.tmp\$\$ /tmp/n.local\$\$ /tmp/n.rec\$\$
X
X$cat <<'EOH'
XDone.
X
XIf you have never used the news system before, you may find the articles
Xin news.announce.newusers to be helpful.  There is also a manual entry for rn.
X
XTo get rid of newsgroups you aren't interested in, use the 'u' command.
XType h for help at any time while running rn.
XEOH
X!GROK!THIS!
Xcase "$isrrn" in
Xdefine)  sed < newsetup -e '/^#NNTP/s/^#NNTP//' -e '/^#NORMAL/d' > newsetup.new ;;
X*) sed < newsetup -e '/^#NNTP/d' -e '/^#NORMAL/s/^#NORMAL//' > newsetup.new ;;
Xesac
Xmv newsetup.new newsetup
X$eunicefix newsetup
Xchmod 755 newsetup
END_OF_FILE
  if test 5105 -ne `wc -c <'newsetup.SH'`; then
    echo shar: \"'newsetup.SH'\" unpacked with wrong size!
  fi
  chmod +x 'newsetup.SH'
  # end of 'newsetup.SH'
fi
if test -f 'ngdata.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'ngdata.c'\"
else
  echo shar: Extracting \"'ngdata.c'\" \(8677 characters\)
  sed "s/^X//" >'ngdata.c' <<'END_OF_FILE'
X/* $Header: ngdata.c,v 4.3.3.1 90/07/21 20:28:27 davison Trn $
X *
X * $Log:	ngdata.c,v $
X * Revision 4.3.3.1  90/07/21  20:28:27  davison
X * Initial Trn Release
X * 
X * Revision 4.3.2.10  90/04/14  22:05:15  sob
X * Removed redundant declaration of active_name
X * 
X * Revision 4.3.2.9  90/03/22  23:04:55  sob
X * Fixes provided by Wayne Davison <drivax!davison>
X * 
X * Revision 4.3.2.8  90/03/17  20:50:51  sob
X * Fixes provided by stewart at netxcom.iad-nxe.global-mis.dhl.com to handle
X * flaky transfers of the active file from the server.
X * 
X * Revision 4.3.2.7  90/03/17  17:11:08  sob
X * Added support for CNEWS active file flags.
X *
X * Revision 4.3.2.6  89/12/08  22:42:04  sob
X * Corrected typo in an #ifdef statement pointed out by
X * jik at pit-manager.mit.edu
X * 
X * Revision 4.3.2.5  89/11/28  01:51:14  sob
X * Removed redundant #include directive.
X * 
X * Revision 4.3.2.4  89/11/27  01:31:07  sob
X * Altered NNTP code per ideas suggested by Bela Lubkin
X * <filbo at gorn.santa-cruz.ca.us>
X * 
X * Revision 4.3.2.3  89/11/08  02:41:40  sob
X * Removed unneeded subroutine.
X * 
X * Revision 4.3.2.2  89/11/08  02:24:31  sob
X * Integrated modifications from other RRN patches colleceted from USENET
X * 
X * Revision 4.3.2.1  89/11/06  00:42:43  sob
X * Added RRN support from NNTP 1.5
X * 
X * Revision 4.3  85/05/01  11:44:38  lwall
X * Baseline for release with 4.3bsd.
X * 
X */
X
X#include "EXTERN.h"
X#include "common.h"
X#include "ndir.h"
X#include "rcstuff.h"
X#include "rn.h"
X#include "intrp.h"
X#include "final.h"
X#include "rcln.h"
X#include "util.h"
X#ifdef SERVER
X#include "server.h"
X#endif
X#include "INTERN.h"
X#include "ngdata.h"
X
Xvoid
Xngdata_init()
X{
X#ifdef SERVER
X    char ser_line[256];
X    int entries;
X#endif
X    char *cp;
X
X/* The following is only for systems that do not zero globals properly */
X#ifdef ZEROGLOB
X# ifdef CACHEFIRST
X    for (i=0; i<MAXRCLINE; i++)
X	abs1st[i] = 0;
X# endif
X#endif	/* ZEROGLOB */
X
X    /* open the active file */
X
X#ifdef SERVER
X
X#ifdef USETHREADS
X    if (use_threads) {
X	cp = filexp(ACTIVE2);
X	actfp = fopen(cp,"r");
X	if (actfp == Nullfp) {
X	    printf(cantopen,cp) FLUSH;
X	    finalize(1);
X	}
X	return;
X    }
X#endif
X
X    put_server("LIST");		/* tell server we want the active file */
X    get_server(ser_line, sizeof(ser_line));
X    if (*ser_line != CHAR_OK) {		/* and then see if that's ok */
X	fprintf(stdout, "Can't get active file from server: \n%s\n", ser_line);
X	finalize(1);
X    }
X
X    cp = filexp("/tmp/rrnact.%$");	/* make a temporary name */
X    strcpy(active_name, cp);
X    actfp = fopen(active_name, "w+");	/* and get ready */
X    if (actfp == Nullfp) {
X	printf(cantopen,active_name) FLUSH;
X	finalize(1);
X    }
X
X    entries = 0;
X    while (1) {
X	if (get_server(ser_line, sizeof(ser_line)) < 0) {
X	    printf("Can't get active file from server:\ntransfer failed after %d entries\n", entries);
X	    finalize(1);
X	}
X	if (ser_line[0] == '.')		/* while there's another line */
X		break;			/* get it and write it to */
X	entries++;
X	fputs(ser_line, actfp);
X	putc('\n', actfp);
X    }
X
X    fseek(actfp,0L,0);		/* just get to the beginning */
X
X#else /* not SERVER */
X
X#ifdef USETHREADS
X    if (use_threads)
X	cp = filexp(ACTIVE2);
X    else
X#endif
X	cp = filexp(ACTIVE);
X    actfp = fopen(cp,"r");
X    if (actfp == Nullfp) {
X	printf(cantopen,cp) FLUSH;
X	finalize(1);
X    }
X#endif
X}
X
X/* find the maximum article number of a newsgroup */
X
XART_NUM
Xgetngsize(num)
Xregister NG_NUM num;
X{
X    register int len;
X    register char *nam;
X    char tmpbuf[80];
X    ART_POS oldsoft;
X
X    nam = rcline[num];
X    len = rcnums[num] - 1;
X    softtries++;
X#ifdef DEBUGGING
X    if (debug & DEB_SOFT_POINTERS)
X	printf("Softptr = %ld\n",(long)softptr[num]) FLUSH;
X#endif
X    oldsoft = softptr[num];
X    if ((softptr[num] = findact(tmpbuf, nam, len, (long)oldsoft)) >= 0) {
X	if (softptr[num] != oldsoft) {
X	    softmisses++;
X	    writesoft = TRUE;
X	}
X    }
X    else {
X	softptr[num] = 0;
X	if (rcchar[num] == ':')		/* unsubscribe quietly */
X	    rcchar[num] = NEGCHAR;
X	return TR_BOGUS;		/* well, not so quietly, actually */
X    }
X	
X#ifdef DEBUGGING
X    if (debug & DEB_SOFT_POINTERS) {
X	printf("Should be %ld\n",(long)softptr[num]) FLUSH;
X    }
X#endif
X#ifdef MININACT
X    {
X	register char *s, ch;
X	ART_NUM tmp;
X
X	for (s=tmpbuf+len+1; isdigit(*s); s++) ;
X	if (tmp = atol(s))
X#ifdef CACHEFIRST
X	    abs1st[num] = tmp;
X#else
X	    abs1st = tmp;
X#endif
X	if (!in_ng) {
X	    for (s++; isdigit(*s); s++) ;
X	    while (isspace(*s)) s++;
X	    ch = *s;
X#ifdef USETHREADS
X	    if (isupper(ch)) {
X		ch = tolower(ch);
X		ThreadedGroup = FALSE;
X	    } else
X		ThreadedGroup = use_threads;
X#endif
X	    switch (ch) {
X	    case 'n': moderated = getval("NOPOSTRING"," (no posting)"); break;
X	    case 'm': moderated = getval("MODSTRING", " (moderated)"); break;
X	    /* This shouldn't even occur.  What are we doing in a non-existent
X	       group?  Disallow it. */
X	    case 'x': return TR_BOGUS;
X	    /* what should be done about refiled groups?  rn shouldn't even
X	       be in them (ie, if sci.aquaria is refiled to rec.aquaria, then
X	       get the news there) */
X	    case '=': return TR_BOGUS;
X	    default: moderated = nullstr;
X	    }
X	}
X    }
X#endif
X    return atol(tmpbuf+len+1);
X}
X
XACT_POS
Xfindact(outbuf,nam,len,suggestion)
Xchar *outbuf;
Xchar *nam;
Xint len;
Xlong suggestion;
X{
X    ACT_POS retval;
X
X    fseek(actfp,100000L,1);	/* hopefully this forces a reread */
X    if (suggestion == 0L || fseek(actfp,suggestion,0) < 0 ||
X      fgets(outbuf,80,actfp) == Nullch ||
X      outbuf[len] != ' ' ||
X      strnNE(outbuf,nam,len)) {
X#ifdef DEBUGGING
X	if (debug & DEB_SOFT_POINTERS)
X	    printf("Missed, looking for %s in %sLen = %d\n",nam,outbuf,len)
X	      FLUSH;
X#endif
X	fseek(actfp,0L,0);
X#ifndef lint
X	retval = (ACT_POS)ftell(actfp);
X#else
X	retval = Null(ACT_POS);
X#endif /* lint */
X	while (fgets(outbuf,80,actfp) != Nullch) {
X	    if (outbuf[len] == ' ' && strnEQ(outbuf,nam,len))
X		return retval;
X#ifndef lint
X	    retval = (ACT_POS) ftell(actfp);
X#endif /* lint */
X	}
X	return (ACT_POS) -1;		/* well, not so quietly, actually */
X    }
X    else
X#ifndef lint
X	return (ACT_POS) suggestion;
X#else
X	return retval;
X#endif /* lint */
X    /*NOTREACHED*/
X}
X
X/* determine the absolutely first existing article number */
X#ifdef SERVER
XART_NUM
Xgetabsfirst(ngnum,ngsize)
Xregister NG_NUM ngnum;
XART_NUM ngsize;
X{
X    register ART_NUM a1st;
X#ifndef MININACT
X    char ser_line[256];
X    ART_NUM x,y;
X#endif
X
X#ifdef CACHEFIRST
X    if (a1st = abs1st[ngnum])
X	return a1st;
X#endif
X#ifdef MININACT
X    getngsize(ngnum);
X# ifdef CACHEFIRST
X    return abs1st[ngnum];
X# else
X    return abs1st;
X# endif
X#else
X    sprintf(cp,"GROUP %s",rcline[ngnum]);
X    put_server(cp);
X    if (get_server(ser_line, sizeof(ser_line)) < 0) {
X	fprintf(stderr, "rrn: Unexpected close of server socket.\n");
X	finalize(1);
X    }
X    if (*ser_line != CHAR_OK) {		/* and then see if that's ok */
X	a1st = ngsize+1;		/* nothing there */
X    }
X    (void) sscanf(ser_line,"%d%d%d",&x,&y,&a1st);
X# ifdef CACHEFIRST
X    abs1st[ngnum] = a1st;
X# endif
X    return a1st;
X#endif
X}
X/* we already know the lowest article number with NNTP */
XART_NUM
Xgetngmin(dirname,floor)
Xchar *dirname;
XART_NUM floor;
X{
X    return(floor);
X}
X#else
XART_NUM
Xgetabsfirst(ngnum,ngsize)
Xregister NG_NUM ngnum;
XART_NUM ngsize;
X{
X    register ART_NUM a1st;
X#ifndef MININACT
X    char dirname[MAXFILENAME];
X#endif
X
X#ifdef CACHEFIRST
X    if (a1st = abs1st[ngnum])
X	return a1st;
X#endif
X#ifdef MININACT
X    getngsize(ngnum);
X# ifdef CACHEFIRST
X    return abs1st[ngnum];
X# else
X    return abs1st;
X# endif
X#else /* not MININACT */
X    sprintf(dirname,"%s/%s",spool,getngdir(rcline[ngnum]));
X    a1st = getngmin(dirname,0L);
X    if (!a1st)				/* nothing there at all? */
X	a1st = ngsize+1;		/* aim them at end of newsgroup */
X# ifdef CACHEFIRST
X    abs1st[ngnum] = a1st;
X# endif
X    return a1st;
X#endif /* MININACT */
X}
X
X/* scan a directory for minimum article number greater than floor */
X
XART_NUM
Xgetngmin(dirname,floor)
Xchar *dirname;
XART_NUM floor;
X{
X    register DIR *dirp;
X    register struct DIRTYPE *dp;
X    register ART_NUM min = 1000000;
X    register ART_NUM maybe;
X    register char *p;
X    char tmpbuf[128];
X    
X    dirp = opendir(dirname);
X    if (!dirp)
X	return 0;
X    while ((dp = readdir(dirp)) != Null(struct DIRTYPE *)) {
X	if ((maybe = atol(dp->d_name)) < min && maybe > floor) {
X	    for (p = dp->d_name; *p; p++)
X		if (!isdigit(*p))
X		    goto nope;
X	    if (*dirname == '.' && !dirname[1])
X		stat(dp->d_name, &filestat);
X	    else {
X		sprintf(tmpbuf,"%s/%s",dirname,dp->d_name);
X		stat(tmpbuf, &filestat);
X	    }
X	    if (! (filestat.st_mode & S_IFDIR))
X		min = maybe;
X	}
X      nope:
X	;
X    }
X    closedir(dirp);
X    return min==1000000 ? 0 : min;
X}
X#endif
END_OF_FILE
  if test 8677 -ne `wc -c <'ngdata.c'`; then
    echo shar: \"'ngdata.c'\" unpacked with wrong size!
  fi
  # end of 'ngdata.c'
fi
if test -f 'rthreads.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'rthreads.c'\"
else
  echo shar: Extracting \"'rthreads.c'\" \(6961 characters\)
  sed "s/^X//" >'rthreads.c' <<'END_OF_FILE'
X/* $Header: rthreads.c,v 4.3.3.2 90/08/20 16:58:14 davison Trn $
X**
X** $Log:	rthreads.c,v $
X** Revision 4.3.3.2  90/08/20  16:58:14  davison
X** Added message for missing/bad db.init file.
X** 
X** Revision 4.3.3.1  90/06/20  23:00:28  davison
X** Initial Trn Release
X** 
X*/
X
X#include "EXTERN.h"
X#include "common.h"
X#include "intrp.h"
X
X#ifdef USETHREADS
X#include "INTERN.h"
X#include "rthreads.h"
X
Xstatic FILE *fp_in;
X
Xstatic char *strings = Nullch;
X
Xstatic int read_item();
Xstatic void wp_bmap(), lp_bmap();
Xstatic void Free();
X
X/* Initialize our thread code by determining the byte-order of the thread
X** files and our own current byte-order.  If they differ, set flags to let
X** the read code know what we'll need to translate.
X*/
Xvoid
Xthread_init()
X{
X    char *filename;
X    int i;
X
X    word_same = long_same = TRUE;
X    filename = filexp( "%X/db.init" );
X    if( (fp_in = fopen( filename, "r" )) != Nullfp ) {
X	if( fread( &mt_bmap, 1, sizeof (BMAP), fp_in ) >= sizeof (BMAP)-1 ) {
X	    if( mt_bmap.version != DB_VERSION ) {
X		printf( "\nThread database is the wrong version -- ignoring it.\n" ) FLUSH;
X		use_threads = FALSE;
X	    }
X	    mybytemap( &my_bmap );
X	    for( i = 0; i < sizeof (LONG); i++ ) {
X		if( i < sizeof (WORD) ) {
X		    if( my_bmap.w[i] != mt_bmap.w[i] ) {
X			word_same = FALSE;
X		    }
X		}
X		if( my_bmap.l[i] != mt_bmap.l[i] ) {
X		    long_same = FALSE;
X		}
X	    }
X	} else {
X	    goto no_db_init;
X	}
X	fclose( fp_in );
X    } else {
X      no_db_init:
X	printf( "\ndb.init read failed -- assuming no byte-order translations.\n\n" ) FLUSH;
X    }
X}
X
X/* Open a thread file for the sole purpose of using it in a newsreader-
X** style application.  Everything is read into arrays in chunks and some
X** useful massaging of the data is performed to make the newsreader's life
X** easier.  Be sure to call unuse_data() before calling this a second time.
X*/
Xint
Xuse_data( threadname )
Xchar *threadname;
X{
X    register int i, j, k;
X    register char *ptr;
X
X    if( (fp_in = fopen( threadname, "r" )) == Nullfp ) {
X	if (errno != ENOENT) {
X	    printf( "\n\nOpen failed for thread data -- continuing unthreaded.\n" );
X	}
X	bzero( &total, sizeof (TOTAL) );
X	return 0;
X    }
X    if( fread( &total, 1, sizeof (TOTAL), fp_in ) < sizeof (TOTAL) ) {
X	printf( "\n\nRead failed for thread data -- continuing unthreaded.\n" );
X	fclose( fp_in );
X	bzero( &total, sizeof (TOTAL) );
X	return 0;
X    }
X    lp_bmap( &total.first, 4 );
X    wp_bmap( &total.root, 5 );
X
X    if( !read_item( &author_cnts, (MEM_SIZE)total.author * sizeof (WORD) )
X     || !read_item( &strings, (MEM_SIZE)total.string1 ) 
X     || !read_item( &subject_cnts, (MEM_SIZE)total.subject * sizeof (WORD) )
X     || !read_item( &p_roots, (MEM_SIZE)total.root * sizeof (PACKED_ROOT) )
X     || !read_item( &p_articles, (MEM_SIZE)total.article * sizeof (PACKED_ARTICLE) ) ) {
X	printf( "\n\nRead failed for thread data -- continuing unthreaded.\n" );
X	fclose( fp_in );
X	unuse_data( 0 );
X	return 0;
X    }
X    fclose( fp_in );
X
X    if( !word_same || !long_same ) {
X	wp_bmap( author_cnts, total.author );
X	wp_bmap( subject_cnts, total.subject );
X	for( i = 0; i < total.root; i++ ) {
X	    lp_bmap( &p_roots[i].root_num, 1 );
X	    wp_bmap( &p_roots[i].articles, 3 );
X	}
X	for( i = 0; i < total.article; i++ ) {
X	    lp_bmap( &p_articles[i].num, 2 );
X	    wp_bmap( &p_articles[i].subject, 8 );
X	}
X    }
X
X#ifndef lint
X    author_ptrs = (char **)safemalloc( total.author * sizeof (char **) );
X    subject_ptrs = (char **)safemalloc( total.subject * sizeof (char **) );
X    root_subjects = (WORD *)safemalloc( total.root * sizeof (WORD) );
X    root_article_cnts = (WORD *)safemalloc( total.root * sizeof (WORD) );
X#endif
X    selected_roots = safemalloc( total.root * sizeof (char) );
X
X    bzero( root_article_cnts, total.root * sizeof (WORD) );
X    bzero( selected_roots, total.root * sizeof (char) );
X
X    for( i = 0, ptr = strings; i < total.author; i++ ) {
X	author_ptrs[i] = ptr;
X	ptr += strlen( ptr ) + 1;
X    }
X
X    for( i = 0, j = 0; i < total.root; i++ ) {
X	root_subjects[i] = j;
X	k = p_roots[i].subject_cnt;
X	while( k-- ) {
X	    root_article_cnts[i] += subject_cnts[j];
X	    subject_ptrs[j++] = ptr;
X	    ptr += strlen( ptr ) + 1;
X	}
X	if( saved_selections ) {
X	    for( k = 0; k < selected_root_cnt; k++ ) {
X		if( p_roots[i].root_num == saved_selections[k] ) {
X		    selected_roots[i] = 1;
X		}
X	    }
X	}
X    }
X    count_roots( !saved_selections );
X    Free( &saved_selections );
X    select_page = 0;
X    return 1;
X}
X
X/* A short-hand for reading a chunk of the file into a malloced array.
X*/
Xstatic int
Xread_item( dest, len )
Xchar **dest;
XMEM_SIZE len;
X{
X    int ret;
X
X    *dest = safemalloc( len );
X    ret = fread( *dest, 1, (int)len, fp_in );
X    if( ret != len ) {
X	free( *dest );
X	*dest = Nullch;
X	return 0;
X    }
X    return 1;
X}
X
X/* Free some memory if it hasn't already been freed.
X*/
Xstatic void
XFree( pp )
Xchar **pp;
X{
X    if( *pp ) {
X	free( *pp );
X	*pp = Nullch;
X    }
X}
X
X/* Discard the thread data that we received through the use_data() call.
X** If "save_selections" is non-zero, we'll try to remember which roots
X** are currently selected long enough for the use_data() call to re-use
X** them.  Only do this when you are going to re-open the same data file
X** immediately with use_data() (presumably because the data has been
X** updated while we were using it).
X*/
Xvoid
Xunuse_data( save_selections )
Xbool save_selections;
X{
X    int i, j;
X
X    if( save_selections ) {
X#ifndef lint
X	saved_selections
X	  = (ART_NUM *)safemalloc( selected_root_cnt * sizeof (ART_NUM) );
X#endif
X	for( i = 0, j = 0; i < total.root; i++ ) {
X	    if( selected_roots[i] && root_article_cnts[i] ) {
X		saved_selections[j++] = p_roots[i].root_num;
X	    }
X	}
X    } else {
X	selected_root_cnt = selected_count = 0;
X    }
X    Free( &p_roots );
X    Free( &root_subjects );
X    Free( &author_cnts );
X    Free( &subject_cnts );
X    Free( &author_ptrs );
X    Free( &subject_ptrs );
X    Free( &root_article_cnts );
X    Free( &selected_roots );
X    Free( &p_articles );
X    Free( &strings );
X
X    p_art = curr_p_art = Nullart;
X    init_tree();		/* free any tree lines */
X
X    bzero( &total, sizeof (TOTAL) );
X}
X
X/* Transform each WORD's byte-ordering in a buffer of the designated length.
X*/
Xstatic void
Xwp_bmap( buf, len )
XWORD *buf;
Xint len;
X{
X    union {
X	BYTE b[sizeof (WORD)];
X	WORD w;
X    } in, out;
X    register int i;
X
X    if( word_same ) {
X	return;
X    }
X    while( len-- ) {
X	in.w = *buf;
X	for( i = 0; i < sizeof (WORD); i++ ) {
X	    out.b[my_bmap.w[i]] = in.b[mt_bmap.w[i]];
X	}
X	*buf++ = out.w;
X    }
X}
X
X/* Transform each LONG's byte-ordering in a buffer of the designated length.
X*/
Xstatic void
Xlp_bmap( buf, len )
XLONG *buf;
Xint len;
X{
X    union {
X	BYTE b[sizeof (LONG)];
X	LONG l;
X    } in, out;
X    register int i;
X
X    if( long_same ) {
X	return;
X    }
X    while( len-- ) {
X	in.l = *buf;
X	for( i = 0; i < sizeof (LONG); i++ ) {
X	    out.b[my_bmap.l[i]] = in.b[mt_bmap.l[i]];
X	}
X	*buf++ = out.l;
X    }
X}
X
X#endif /* USETHREADS */
END_OF_FILE
  if test 6961 -ne `wc -c <'rthreads.c'`; then
    echo shar: \"'rthreads.c'\" unpacked with wrong size!
  fi
  # end of 'rthreads.c'
fi
if test -f 'uudecode.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'uudecode.c'\"
else
  echo shar: Extracting \"'uudecode.c'\" \(7963 characters\)
  sed "s/^X//" >'uudecode.c' <<'END_OF_FILE'
X/* $Header: uudecode.c,v 4.3.3.1 90/06/20 22:48:21 davison Trn $
X**
X** $Log:	uudecode.c,v $
X** Revision 4.3.3.1  90/06/20  22:48:21  davison
X** Initial Trn Release
X** 
X** Decode one or more uuencoded articles back to binary form.
X**
X** Trn version created by Wayne Davison.
X** Adapted from the nn version by Kim Storm.
X** From the Berkeley original, modified by MSD, RDR, JPHD & WLS.
X*/
X
X#include "EXTERN.h"
X#include "common.h"
X#include "INTERN.h"
X#include "uudecode.h"
X
X#if 000
Xexport char *decode_header_file = "Decode.Headers";
X#endif
X
X#define MAXCHAR 256
X#define NORMLEN 60	/* allows for 80 encoded chars per line */
X
X#define SEQMAX 'z'
X#define SEQMIN 'a'
X
Xstatic char seqc;
Xstatic int first, secnd, check, numl;
X
Xstatic char *target;
Xstatic char dest[MAXFILENAME];
Xstatic char blank;
Xstatic int chtbl[MAXCHAR], cdlen[NORMLEN + 3];
Xstatic int state;
Xstatic bool Xflag;
X
X#define	NO_ADVANCE		0x10
X
X#define	FIND_BEGIN		0x01
X#define	FIND_BEGIN_AFTER_ERROR	0x02
X#define	DECODE_TEXT		0x03
X#define	SKIP_TRAILING	       (0x04 | NO_ADVANCE)
X#define	SKIP_LEADING		0x05
X#define	FOUND_END	       (0x06 | NO_ADVANCE)
X#define DECODE_ERROR	       (0x07 | NO_ADVANCE)
X#define OTHER_ERROR	       (0x08 | NO_ADVANCE)
X#define NEW_BEGIN	       (0x09 | NO_ADVANCE)
X
Xuud_start(dir)
Xchar *dir;
X{
X    target = dir;
X    uu_out = Nullfp;
X    Xflag = FALSE;
X    seqc = SEQMAX;
X    check = 1;
X    first = 1;
X    secnd = 0;
X    state = FIND_BEGIN;
X}
X
Xuud_end()
X{
X    if (uu_out != Nullfp) {
X	fclose(uu_out);
X	uu_out = Nullfp;
X	printf("\n%s INCOMPLETE -- removed\n", dest);
X	unlink(dest);
X    }
X}
X
X
Xuudecode(in)
XFILE *in;
X{
X    int mode, onedone, lens;
X    char buff[LBUFLEN];
X
X    numl = onedone = 0;
X
X    if (state == FIND_BEGIN)
X	inittbls();
X
X    /*
X     * search for header or translation table line.
X     */
X
X    while ((state & NO_ADVANCE) || fgets(buff, sizeof buff, in) != Nullch) {
X	numl++;
X
X	switch (state) {
X	 case NEW_BEGIN:
X	    if (uu_out != Nullfp) {
X		printf("INCOMPLETE FILE: %s -- removed\n", dest);
X		sleep(2);
X		fclose(uu_out);
X		uu_out = Nullfp;
X		Xflag = FALSE;
X		unlink(dest);
X	    }
X	    /* fall thru */
X
X	 case FIND_BEGIN:
X	 case FIND_BEGIN_AFTER_ERROR:
X	    if (strnEQ(buff, "table ", 6)) {
X		gettable(in);
X		continue;
X	    }
X
X	    if (strnEQ(buff, "begin ", 6)
X	     || strnEQ(buff, "Xbegin ", 7)) {
X		lens = strlen(buff)-1;
X		if (buff[lens] == '\n')
X		    buff[lens] = '\0';
X
X		if(sscanf(buff+6,"%o%s", &mode, uu_fname) != 2)
X		    continue;
X
X		Xflag = (*buff == 'X');
X
X		if (target != Nullch)
X		    sprintf(dest, "%s/%s", target, uu_fname);
X		else
X		    strcpy(dest, uu_fname);
X
X		if ((uu_out = fopen(dest, "w")) == Nullfp) {
X		    printf("Cannot create file: %s\n", dest);
X		    goto err;
X		}
X		chmod(dest, mode);
X
X#if 000
X		if (decode_header_file)
X		    store_header(ah, in, target, decode_header_file);
X#endif
X
X		printf("Decoding: %s\n", uu_fname);
X		state = DECODE_TEXT;
X	    }
X	    continue;
X
X	 case SKIP_LEADING:
X	    state = decode_line(buff);
X	    continue;
X
X	 case DECODE_TEXT:
X	    state = decode_line(buff);
X	    onedone = 1;
X	    continue;
X
X	 case FOUND_END:
X	    fclose(uu_out);
X	    uu_out = Nullfp;
X	    Xflag = FALSE;
X	    state = FIND_BEGIN;
X	    printf("Done.\n");
X	    continue;
X
X	 case SKIP_TRAILING:
X	    printf("(Continued)\n");
X	    state = SKIP_LEADING;
X	    return 0;
X
X	 case DECODE_ERROR:
X	    state = SKIP_TRAILING;
X	    continue;
X
X	 case OTHER_ERROR:
X	    fclose(uu_out);
X	    uu_out = Nullfp;
X	    Xflag = FALSE;
X	    state = FIND_BEGIN_AFTER_ERROR;
X	    goto err;
X	}
X    }
X
X    if (onedone) {
X	if (state == DECODE_TEXT)
X	    state = SKIP_LEADING;
X	return 0;
X    }
X
X    if (state == FIND_BEGIN_AFTER_ERROR)
X	return -1;
X    printf("Couldn't find anything to decode.\n");
X
X err:
X    sleep(2);
X    return -1;
X}
X
X/*
X * decode one line, write on uu_out file
X */
X
Xstatic decode_line(buff)
Xchar *buff;
X{
X    char outl[LBUFLEN];
X    register char *bp, *ut;
X    register int *trtbl = chtbl;
X    register int n;
X    register int blen;		/* binary length (from decoded file) */
X    register int rlen;		/* calculated input line length */
X    register int len;		/* actual input line length */
X
X    if (Xflag) {
X	if (*buff == 'X')
X	    buff++;
X	else
X	    *buff = 'x';	/* force a mis-parse of a non-x'ed line */
X    }
X    len = strlen(buff);
X    if (--len < 0)
X	return state;
X
X    buff[len] = '\0';
X
X    /*
X     * Get the binary line length.
X     */
X    if ((blen = trtbl[buff[0]]) < 0) {
X	if (state == SKIP_LEADING) {
X	    if (strnEQ(buff, "begin ", 6))
X		return NEW_BEGIN;
X
X	    return SKIP_LEADING;
X	}
X	/*
X	 * end of uuencoded file ?
X	 */
X	if (strnEQ(buff, "end", 3))
X	    return FOUND_END;
X
X	/*
X	 * end of current file ? : get next one.
X	 */
X	if (strnEQ(buff, "include", 7)) {
X	    printf("Cannot handle 'include' lines -- unpack with uud\n");
X	    return OTHER_ERROR;
X	}
X
X	/*
X	 * trailing garbage
X	 */
X	return SKIP_TRAILING;
X    }
X
X    rlen = cdlen[blen];
X    if (state == SKIP_LEADING && len != rlen && len != rlen+1)
X	return SKIP_LEADING;
X
X    /*
X     * Is it the empty line before the end line ?
X     */
X    if (blen == 0)
X	return state;
X
X    if (len > rlen + 5)
X	return SKIP_TRAILING;
X
X    /*
X     * Pad with blanks.
X     */
X    for (bp = buff + len, n = rlen - len; --n >= 0; )
X	*bp++ = blank;
X
X    /*
X     * Verify
X     */
X    for (n = rlen, bp = buff; --n >= 0; bp++)
X	if (trtbl[*bp] < 0) {
X	    if (state == SKIP_LEADING)
X		return SKIP_LEADING;
X	    return DECODE_ERROR;
X	}
X
X    /*
X     * Check for uuencodes that append a 'z' to each line....
X     */
X    if (check)
X	if (secnd) {
X	    secnd = 0;
X	    if (buff[rlen] == SEQMAX)
X		check = 0;
X	} else if (first) {
X	    first = 0;
X	    secnd = 1;
X	    if (buff[rlen] != SEQMAX)
X		check = 0;
X	}
X
X    /*
X     * There we check.
X     */
X    if (check) {
X	if (buff[rlen] != seqc) {
X	    if (state == SKIP_LEADING)
X		return SKIP_LEADING;
X	    return DECODE_ERROR;
X	}
X
X	if (--seqc < SEQMIN)
X	    seqc = SEQMAX;
X    }
X
X    /*
X     * output a group of 3 bytes (4 input characters).
X     * the input chars are pointed to by p, they are to
X     * be output to file f. blen is used to tell us not to
X     * output all of them at the end of the file.
X     */
X    ut = outl;
X    n = blen;
X    bp = &buff[1];
X    while (--n >= 0) {
X	*(ut++) = trtbl[*bp] << 2 | trtbl[bp[1]] >> 4;
X	if (n > 0) {
X	    *(ut++) = (trtbl[bp[1]] << 4) | (trtbl[bp[2]] >> 2);
X	    n--;
X	}
X	if (n > 0) {
X	    *(ut++) = trtbl[bp[2]] << 6 | trtbl[bp[3]];
X	    n--;
X	}
X	bp += 4;
X    }
X    if (fwrite(outl, 1, blen, uu_out) <= 0) {
X	printf("Error on writing decoded file\n");
X	return OTHER_ERROR;
X    }
X
X    return DECODE_TEXT;
X}
X
X
X
X/*
X * Install the table in memory for later use.
X */
Xstatic inittbls()
X{
X    register int i, j;
X
X    /*
X     * Set up the default translation table.
X     */
X    for (i = 0; i < ' '; i++)
X	chtbl[i] = -1;
X    for (i = ' ', j = 0; i < ' ' + 64; i++, j++)
X	chtbl[i] = j;
X    for (i = ' ' + 64; i < MAXCHAR; i++)
X	chtbl[i] = -1;
X    chtbl['`'] = chtbl[' '];	/* common mutation */
X    chtbl['~'] = chtbl['^'];	/* another common mutation */
X    blank = ' ';
X    /*
X     * set up the line length table, to avoid computing lotsa * and / ...
X     */
X    cdlen[0] = 1;
X    for (i = 1, j = 5; i <= NORMLEN; i += 3, j += 4)
X	cdlen[i] = (cdlen[i + 1] = (cdlen[i + 2] = j));
X}
X
Xstatic gettable(in)
XFILE *in;
X{
X    char buff[LBUFLEN];
X    register int c, n = 0;
X    register char *cpt;
X
X    for (c = 0; c <= MAXCHAR; c++)
X	chtbl[c] = -1;
X
X    for (;;) {
X	if (fgets(buff, sizeof buff, in) == Nullch) {
X	    printf("EOF while in translation table.\n");
X	    return -1;
X	}
X	numl++;
X	if (strnEQ(buff, "begin", 5)) {
X	    printf("Incomplete translation table.\n");
X	    return -1;
X	}
X	cpt = buff + strlen(buff) - 1;
X	*cpt = ' ';
X	while (*cpt == ' ') {
X	    *cpt = 0;
X	    cpt--;
X	}
X	cpt = buff;
X	while (c = *cpt) {
X	    if (chtbl[c] != -1) {
X		printf("Duplicate char in translation table.\n");
X		return -1;
X	    }
X	    if (n == 0)
X		blank = c;
X	    chtbl[c] = n++;
X	    if (n >= 64)
X		return 0;
X	    cpt++;
X	}
X    }
X}
X
END_OF_FILE
  if test 7963 -ne `wc -c <'uudecode.c'`; then
    echo shar: \"'uudecode.c'\" unpacked with wrong size!
  fi
  # end of 'uudecode.c'
fi
echo shar: End of archive 12 \(of 14\).
cp /dev/null ark12isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 14 archives.
    rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
    echo You still must unpack the following archives:
    echo "        " ${MISSING}
fi
exit 0
exit 0 # Just in case...
-- 
Please send comp.sources.unix-related mail to rsalz at uunet.uu.net.
Use a domain-based address or give alternate paths, or you may lose out.



More information about the Comp.sources.unix mailing list