home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Source Code 1992 March
/
Source_Code_CD-ROM_Walnut_Creek_March_1992.iso
/
usenet
/
altsrcs
/
3
/
3895
< prev
next >
Wrap
Internet Message Format
|
1991-08-23
|
50KB
Path: wupost!uunet!mcsun!unido!estevax!norisc!iain
From: iain@norisc.UUCP (Iain Lea)
Newsgroups: alt.sources
Subject: tin v1.00 - YAN (Yet Another Newsreader) Part 01/08
Message-ID: <582@norisc.UUCP>
Date: 23 Aug 91 13:50:34 GMT
Sender: iain@norisc.UUCP (Iain Lea)
Organization: What organization?
Lines: 1985
Submitted-by: iain@estevax.uucp
Archive-name: tin/part01
#!/bin/sh
# This is tin, a shell archive (shar 3.24)
# made 08/23/1991 13:37 UTC by iain@estevax.uucp
# Source directory /piez/iain/.src/tin
#
# existing files WILL be overwritten
#
# This is part 1 of a multipart archive
# do not concatenate these parts, unpack them in order with /bin/sh
#
# This shar contains:
# length mode name
# ------ ---------- ------------------------------------------
# 570 -rw------- MANIFEST
# 8147 -rw------- Makefile
# 4930 -rw------- README
# 1305 -rw------- TODO
# 512 -rwx------ UPDATE_INDEX
# 5457 -rw------- alloca.c
# 23276 -rw------- art.c
# 6075 -rw------- curses.c
# 2276 -rw------- debug.c
# 20085 -rw------- group.c
# 2673 -rw------- hashstr.c
# 4794 -rw------- help.c
# 9014 -rw------- kill.c
# 16340 -rw------- lang.c
# 8856 -rw------- lang.h
# 1260 -rw------- mail.c
# 6852 -rw------- main.c
# 5489 -rw------- memory.c
# 12707 -rw------- misc.c
# 16290 -rw------- newsrc.c
# 3688 -rw------- nntp.h
# 6594 -rw------- open.c
# 34638 -rw------- page.c
# 2328 -rw------- posted.c
# 3061 -rw------- prompt.c
# 16291 -rw------- proto.h
# 15340 -rw------- rcfile.c
# 22644 -rw------- save.c
# 1936 -rw------- screen.c
# 7656 -rw------- search.c
# 17154 -rw------- select.c
# 1611 -rw------- time.c
# 7369 -rw------- tin.h
# 3866 -rw------- wildmat.c
# 18929 -rw------- tin.1
#
if touch 2>&1 | fgrep '[-amc]' > /dev/null
then TOUCH=touch
else TOUCH=true
fi
if test -r shar3_seq_.tmp; then
echo "Must unpack archives in sequence!"
next=`cat shar3_seq_.tmp`; echo "Please unpack part $next next"
exit 1
fi
# ============= MANIFEST ==============
echo "x - extracting MANIFEST (Text)"
sed 's/^X//' << 'SHAR_EOF' > MANIFEST &&
XMANIFEST for tin v1.00
X----------------------
X 567 MANIFEST
X 8187 Makefile
X 4930 README
X 889 TODO
X 512 UPDATE_INDEX
X 5457 alloca.c
X23418 art.c
X 6075 curses.c
X 2272 debug.c
X20085 group.c
X 2673 hashstr.c
X 4734 help.c
X 9014 kill.c
X16120 lang.c
X 8704 lang.h
X 1260 mail.c
X 6852 main.c
X 5452 memory.c
X12197 misc.c
X16281 newsrc.c
X 3688 nntp.h
X 6594 open.c
X34637 page.c
X 2328 posted.c
X 3061 prompt.c
X15901 proto.h
X15340 rcfile.c
X22473 save.c
X 1936 screen.c
X 7648 search.c
X16958 select.c
X 1611 time.c
X18933 tin.1
X 7363 tin.h
X 3866 wildmat.c
SHAR_EOF
$TOUCH -am 0821104491 MANIFEST &&
chmod 0600 MANIFEST ||
echo "restore of MANIFEST failed"
set `wc -c MANIFEST`;Wc_c=$1
if test "$Wc_c" != "570"; then
echo original size 570, current size $Wc_c
fi
# ============= Makefile ==============
echo "x - extracting Makefile (Text)"
sed 's/^X//' << 'SHAR_EOF' > Makefile &&
X# Makefile
X
X# name of executable file
X#
XEXE=tin
X
X# command line compile flags
X#
X# -D DONT_USE_START_LINE
X# stop editor being started with line offset into file
X#
X# -D DONT_USE_REGEX
X# don't match strings using regular expressions
X#
X# -D USE_LONG_FILENAMES
X# include -DUSE_LONG_FILENAMES if filesystem supports filenames
X# longer than 14 chars. (default for BSD type systems)
X#
X# -D USE_CLEARSCREEN
X# define if the you wish screen to use ClearScreen() and not MoveCursor()
X# and CleartoEOLN(). This is perhaps faster on slow terminals but I have
X# not really run any speed tests.
X#
X# -D LIBDIR=\"\"
X# defaults to /usr/lib/news if not defined
X#
X# -D SPOOLDIR=\"\"
X# defaults to /usr/spool/news if not defined
X#
X# -D USE_NNTP
X# include -DUSE_NNTP if you want to allow reading of news locally and
X# also remotely via the -r option over an NNTP server.
X#
X# You only need to worry about the following two defines if you have
X# defined NNTP to build a version to access news locally & remotely
X#
X# NNTPLIB=
X# point NNTPLIB at the nntp clientlib.o support library
X#
X# NETLIBS=
X# NETLIBS should be the networking libraries you need to link with
X# the nntp clientlib.o
X
XBINDIR = /piez/iain/bin
XTROFF=drf
XPRINT=-Pps0
X
XHFILES = tin.h proto.h lang.h nntp.h
X
XCFILES = art.c curses.c debug.c group.c hashstr.c help.c kill.c lang.c mail.c \
X main.c memory.c misc.c newsrc.c open.c page.c prompt.c posted.c \
X rcfile.c save.c screen.c search.c select.c time.c wildmat.c
X
XOBJECTS = art.o curses.o debug.o group.o hashstr.o help.o kill.o lang.o mail.o \
X main.o memory.o misc.o newsrc.o open.o page.o prompt.o posted.o \
X rcfile.o save.o screen.o search.o select.o time.o wildmat.o
X
XLINTFLAGS=-a -c -h -n -x
X
X.c.o :
X $(CC) $(CFLAGS) $*.c
X
Xall :
X @echo "There is no default. Specify one of the following targets."
X @echo " make bsd (BSD/Ultrix)"
X @echo " make sysv (SysV)"
X @echo " make sysvr4 (SysV R4)"
X @echo " make sco (SCO Unix)"
X @echo " make xenix (Xenix 386)"
X @echo " make norisc (Site specific)"
X @echo " make estevax (Site specific)"
X
X# For Berkeley systems:
Xbsd:
X @echo "Compiling for BSD/Ultrix..."
X @$(MAKE) CFLAGS='-c -O -DBSD -DLIBDIR=\"/usr/lib/news\" -DSPOOLDIR=\"/usr/spool/news\"' \
X LIBS="-lcurses -ltermcap" \
X STRIP=strip EXE=tin linkit
X
X# For System V:
Xsysv:
X @echo "Compiling for System V..."
X @$(MAKE) CFLAGS='-c -O -DUSE_NNTP -DLIBDIR="\\"/usr/lib/news\\"" -DSPOOLDIR="\\"/usr/spool/news\\""' \
X NNTPLIB="clientlib.o" \
X NETLIBS="-lnet -lnsl_s" \
X LIBS="-lcurses -ltermcap" \
X STRIP=strip EXE=tin linkit
X
X# For System V Release 4:
Xsysvr4:
X @echo "Compiling for System V Release 4..."
X @$(MAKE) CFLAGS='-c -O -DUSE_NNTP -DLIBDIR=\"/usr/lib/news\" -DSPOOLDIR=\"/usr/spool/news\"' \
X NNTPLIB="./nntp/clientlib.o" \
X NETLIBS="-lnsl -lsocket" \
X LIBS="-lcurses -ltermcap" \
X STRIP=strip EXE=tin linkit
X
X# For Sco Unix:
Xsco:
X @echo "Compiling for Sco Unix..."
X @$(MAKE) CFLAGS='-c -O -UM_XENIX -DLIBDIR=\"/usr/lib/news\" -DSPOOLDIR=\"/usr/spool/news\"' \
X LIBS="-lcurses -lgen -lc_s" \
X STRIP=strip EXE=tin linkit
X
X# For Xenix 386:
Xxenix:
X @echo "Compiling for Xenix 386..."
X @$(MAKE) CFLAGS='-c -Zi -DLIBDIR="\\"/usr/lib/news\\"" -DSPOOLDIR="\\"/usr/spool/news\\""' \
X LIBS="-lcurses -ltinfo -lx" \
X STRIP=echo EXE=tin linkit
X
X# SITE SPECIFIC - IGNORE
Xnorisc:
X @echo "Compiling for NORISC with NNTP..."
X @$(MAKE) CFLAGS='-c -O -DBSD -DUSE_NNTP -DLIBDIR=\"/news/lib\" -DSPOOLDIR=\"/news/spool\"' \
X NNTPLIB=/news/nntp/clientlib.o \
X LIBS="-lcurses -ltermcap" \
X STRIP=strip EXE=tin linkit
X
X# SITE SPECIFIC - IGNORE
Xestevax:
X @echo "Compiling for ESTEVAX with NNTP..."
X @$(MAKE) CFLAGS='-c -O -DBSD -DUSE_NNTP -DLIBDIR=\"/usr/lib/news\" -DSPOOLDIR=\"/usr/spool/news\"' \
X NNTPLIB=/others/mtz/bnews2/NNTP/common/clientlib.o \
X LIBS="-lcurses -ltermcap" \
X STRIP=strip EXE=tin linkit
X
Xlinkit: $(OBJECTS)
X @echo "Linking $(EXE)..."
X# $(CC) -o $(EXE) $(OBJECTS) alloca.o $(NNTPLIB) $(NETLIBS) $(LIBS)
X $(CC) -o $(EXE) $(OBJECTS) $(NNTPLIB) $(NETLIBS) $(LIBS)
X @$(STRIP) $(EXE)
X @ls -l $(EXE)
X
Xcflow:
X @echo "creating cflow for $(EXE)..."
X @cflow $(CFILES) > cflow.$(EXE) &
X
Xproto:
X @echo "generating function prototypes for proto.h..."
X @echo "#ifdef __STDC__" > PROTO.H
X @echo " " >> PROTO.H
X @cproto *.c >> PROTO.H
X @echo " " >> PROTO.H
X @echo "#else" >> PROTO.H
X @echo " " >> PROTO.H
X @cproto -f1 *.c >> PROTO.H
X @echo " " >> PROTO.H
X @echo "#endif" >> PROTO.H
X @-mv PROTO.H proto.h
X
Xinstall: all
X @echo "installing $(EXE)..."
X @-mv $(EXE) $(BINDIR)
X @chmod 755 $(BINDIR)/$(EXE)
X
Xshar:
X @-mv -f ../$(EXE).shar ../$(EXE).shar-
X @shar -a -n $(EXE) -s iain@estevax.uucp -L50 -o ../$(EXE).shar [A-Z]* [A-Za-z0-9]*.[ch] $(EXE).1
X
Xtar:
X @echo "archiving files to $(EXE).tar..."
X @-rm $(EXE).tar $(EXE).tar.Z > /dev/null 2>&1
X @tar cvf $(EXE).tar $(HFILES) $(CFILES) Makefile README TODO UPDATE_INDEX $(EXE).1
X @echo "compressing $(EXE).tar..."
X @compress $(EXE).tar
X @ls -l $(EXE).tar.Z
X
Xzoo:
X @echo "archiving files to $(EXE).zoo..."
X @-rm $(EXE).zoo > /dev/null 2>&1
X @zoo ah $(EXE).zoo $(HFILES) $(CFILES) Makefile README TODO UPDATE_INDEX $(EXE).1
X @ls -l $(EXE).zoo
X
Xtags:
X @echo "generating tags (results in ./tags)..."
X @-rm tags
X @ctags $(HFILES) $(CFILES)
X
Xlint:
X @echo "linting source (results in ./LINT)..."
X @lint $(LINTFLAGS) $(CFILES) > LINT
X
Xclean:
X @echo "cleaning..."
X @-rm -rf *.o #* $(EXE)
X
Xgrind:
X @echo "grinding tags index..."
X @ctags -v *.[ch] | sort -f > $(EXE).index
X
Xman:
X @echo "printing $(EXE) manual to $(PRINT)..."
X @+ $(TROFF) -F Helvetica -man3 $(PRINT) $(EXE).1
X
Xprint:
X @echo "printing to $(PRINT)..."
X @expand -4 art.c | enscript -2r -h -G $(PRINT) -b art.c
X @expand -4 curses.c | enscript -2r -h -G $(PRINT) -b curses.c
X @expand -4 debug.c | enscript -2r -h -G $(PRINT) -b debug.c
X @expand -4 group.c | enscript -2r -h -G $(PRINT) -b group.c
X @expand -4 hashstr.c | enscript -2r -h -G $(PRINT) -b hashstr.c
X @expand -4 help.c | enscript -2r -h -G $(PRINT) -b help.c
X @expand -4 kill.c | enscript -2r -h -G $(PRINT) -b kill.c
X @expand -4 lang.c | enscript -2r -h -G $(PRINT) -b lang.c
X @expand -4 lang.h | enscript -2r -h -G $(PRINT) -b lang.h
X @expand -4 mail.c | enscript -2r -h -G $(PRINT) -b mail.c
X @expand -4 main.c | enscript -2r -h -G $(PRINT) -b main.c
X @expand -4 memory.c | enscript -2r -h -G $(PRINT) -b memory.c
X @expand -4 misc.c | enscript -2r -h -G $(PRINT) -b misc.c
X @expand -4 newsrc.c | enscript -2r -h -G $(PRINT) -b newsrc.c
X @expand -4 nntp.h | enscript -2r -h -G $(PRINT) -b nntp.h
X @expand -4 open.c | enscript -2r -h -G $(PRINT) -b open.c
X @expand -4 page.c | enscript -2r -h -G $(PRINT) -b page.c
X @expand -4 posted.c | enscript -2r -h -G $(PRINT) -b posted.c
X @expand -4 prompt.c | enscript -2r -h -G $(PRINT) -b prompt.c
X @expand -4 rcfile.c | enscript -2r -h -G $(PRINT) -b rcfile.c
X @expand -4 save.c | enscript -2r -h -G $(PRINT) -b save.c
X @expand -4 screen.c | enscript -2r -h -G $(PRINT) -b screen.c
X @expand -4 search.c | enscript -2r -h -G $(PRINT) -b search.c
X @expand -4 select.c | enscript -2r -h -G $(PRINT) -b select.c
X @expand -4 tin.h | enscript -2r -h -G $(PRINT) -b tin.h
X @expand -4 time.c | enscript -2r -h -G $(PRINT) -b time.c
X
Xvaxb:
X @echo "copying to estevax..."
X @rcp $(EXE).tar.Z estevax:.src/tin &
X
Xkommu:
X @echo "copying to kommu..."
X @uncompress $(EXE).tar.Z
X @rcp $(EXE).tar kommu:.src/tin &
X @compress $(EXE).tar
X
Xart.o: art.c $(HFILES)
Xcurses.o: curses.c
Xdebug.o: debug.c $(HFILES)
Xgroup.o: group.c $(HFILES)
Xhashstr.o: hashstr.c $(HFILES)
Xhelp.o: help.c $(HFILES)
Xkill.o: kill.c $(HFILES)
Xlang.o: lang.c $(HFILES)
Xmail.o: mail.c
Xmain.o: main.c $(HFILES)
Xmemory.o: memory.c $(HFILES)
Xmisc.o: misc.c $(HFILES)
Xnewsrc.o: newsrc.c $(HFILES)
Xopen.o: open.c $(HFILES)
Xpage.o: page.c $(HFILES)
Xposted.o: posted.c $(HFILES)
Xprompt.o: prompt.c $(HFILES)
Xrcfile.o: rcfile.c $(HFILES)
Xsave.o: save.c $(HFILES)
Xscreen.o: screen.c $(HFILES)
Xsearch.o: search.c $(HFILES)
Xselect.o: select.c $(HFILES)
Xtime.o: time.c
Xwildmat.o: wildmat.c $(HFILES)
SHAR_EOF
$TOUCH -am 0823153791 Makefile &&
chmod 0600 Makefile ||
echo "restore of Makefile failed"
set `wc -c Makefile`;Wc_c=$1
if test "$Wc_c" != "8147"; then
echo original size 8147, current size $Wc_c
fi
# ============= README ==============
echo "x - extracting README (Text)"
sed 's/^X//' << 'SHAR_EOF' > README &&
XTin is a full screen threaded newsreader that uses the tass newsreader as
Xits base. Tass was developed by Rich Skrenta (skrenta@blekko.commodore.com).
XTin can read news locally and also via an NNTP server (-r option). Tin
Xcontains more features than tass but they are still accessable to the
Xbeginner and expert alike. I tried to follow the tass UI conventions as
Xmuch as possible.
X
XThis is a late beta release (I hope!). I am looking for people to test this
Xand send me ideas/comments & bugs so that I can correct any and then send
Xit off to comp.sources.misc sometime in the near future.
X
XI find myself getting more done using this new reader than rn/vn and the like.
X
XThis is the only newsreader that I know of that threads on the Archive-name:
Xfield as used in comp.sources.* groups as well as on the more normal Subject:
Xfield. Before anyone comments on Subject: threading not being right and I
Xshould look at trn, I have and its threads are neat but I get more done with
Xtin than trn. It is especially good at saving and processing saved articles
X& threads.
X
XI may be off the net for a couple of months at the end of September, but
Xwill be contactable at the following address:
X Iain J. Lea
X BrueckenStr. 12
X 8500 Nuernberg 90
X Germany.
X Phone. +49-911-331963
X Email. iain@estevax.uucp
X
XBugs and new features to be added are described in the file TODO
X
XBuilt & used on the following machines
X--------------------------------------
X 1) Vax 8850 & Ultrix 4.1 (Developed & most tested platform)
X 2) Vax 11/785 & BSD 4.3
X 3) 386 PC & Xenix 386
X 4) 386 PC & ATT Unix SysVR4.0 (strange behaviour with inverse video)
X 5) 386 PC & SCO Unix SysVR3.2 (strange behaviour with inverse video)
X 6) 386 PC & ISC Unix SysVR3.2 with WINTCP (shakey ??)
X
XBuilding Tin
X------------
X 1) type make and a few system types will be displayed
X 2) edit Makefile if you want to add/change -D DEFINES
X 3) type 'make <system type>' for your system
X 4) NOTE. the mmakefile needs rewriting (Any takers?)
X
X Note: the supplied Makefile will not run directly on BSD. It
X requires a little work (Any takers to write a good Makefile?)
X
XInstalling Tin
X--------------
X 1) make install
X
XCredits
X-------
XI wish to give credit to the following people for the routines
Xthat they have written and I have used in tin:
X
XRich Skrenta - tass v3.2 that tin is based upon.
XSyd Weinstein - curses.c is taken from the elm mailreader
XRich Salz - wildmat regex pattern matching routine
XWayne Brandt - multi-part uudecode routine
X
XI wish to thank the following people for comments & ideas:
X
XKlaus Arzig, Reiner Balling, Georg Biehler, Peter Dressler,
XGerhard Ermer, Joachim Feld, Bernhard Gmelch, Joe Johnson,
XCyrill Jung, Clifford Luke, Toni Metz, Klaus Neuberger,
XOtto Niesser, Fredy Schwatz, Bernd Schwerin, Chris Smith
X
XFeatures of tass v3.2
X---------------------
Xo Organizes articles by threads. Displays a really nice article
X selection page.
X
Xo Group selection page makes it easy to scan newsgroups, subscribe,
X unsubscribe, reorder your .newsrc
X
Xo If you've ever used Notes, this is the program for you.
X Tass looks a lot like Notes, but has a few improvements:
X visual group selection page, Notes didn't have one
X rn style unread article detection as opposed to single timeline
X uses standard /usr/spool/news article layout
X
XNewsreading style under Tass tends to be different than with rn. Instead of
Xplowing through each group reading everything unread, you may find yourself
Xreading fewer articles in more groups. It's easier to skip about and only
Xread interesting threads with Tass.
X
XTass keeps an index file for each group. The first time you enter a group,
Xit will be a bit slow creating this file. After that Tass will incrementally
Xupdate the index file and there should be little delay.
X
XYou can also run Tass in "update mode" out of cron to update the indexes.
X
XFeatures New to Tin v1.00
X-------------------------
Xo News can be read locally (ie. /usr/spool/news) or remotely by NNTP (-r option)
X
Xo User can config tin's options dynamically by 'M' command and have them
X saved to ~/.tin/tinrc.
X
Xo Archive-name: mail header is used when saving and post processing
X articles / threads.
X
Xo Adjusts to size of screen for how much of Subject: & From: is displayed.
X
Xo Post processes saved articles/threads. It will handle sh, uudecode,
X zoo, lharc, arc and zip (unzip) formats.
X
Xo Articles can be sorted on Subject:, From:, Date: field or nothing.
X
Xo Killfile support (Not fully debugged). Kill articles at single group
X / all groups on Subject:,From: line or on user entered pattern.
X
Xo Saves articles / threads to elm mailbox by pressing '=' when asked
X for name of saved file.
X
Xo Displays history of user posted articles/replies & followups.
X
Xo Higlighted bar / -> arrow can be used for selecting articles
X
Xo Tagging of articles to save in a particular order
X
XAnd many other small changes.
SHAR_EOF
$TOUCH -am 0820185891 README &&
chmod 0600 README ||
echo "restore of README failed"
set `wc -c README`;Wc_c=$1
if test "$Wc_c" != "4930"; then
echo original size 4930, current size $Wc_c
fi
# ============= TODO ==============
echo "x - extracting TODO (Text)"
sed 's/^X//' << 'SHAR_EOF' > TODO &&
XFIX FEATURES
X------------
Xo Fix Makefile file to be more portable across platforms
X
Xo Rewrite README and finish man page
X
Xo Fix code to sort arts. At page level funny things happen.
X
Xo Fix code to KILL articles. At page level funny things happen.
X
Xo Fix code to KILL articles with 't' command.
X
Xo Fix 'z' so that it stays unread even if a KILL is performed before
X leaving the group.
X
Xo Fix job control? under SysVR4 where a ^Z makes the screen redraw
X itself and does not suspend the process as it should.
X
Xo Fix help screens so that they understand if the terminal has more
X than 25 lines (ie. use LINES).
X
Xo Fix -u -v -c that get malloc error sometimes on SysV machines
X
XADD FEATURES
X------------
Xo Sort .newsrc according to preference.
X
Xo Add 'H' context senstive level help screens
X
Xo Add code to do unpack patches
X
Xo Add '+' for saving in MH mail format
X
Xo Add time period kill article
X
Xo Add -s <dir> option to save new news to specifed spool dir for when
X one goes on holiday so that it can be read later by giving -S <dir>.
X
Xo Add code to allow user to specify routine for post processing
X articles
X
XPIPEDREAMS
X----------
Xo Add Virtual newsgroups (combination of newsgroups ie. virtual.ibm
X consists of comp.sys.ibm.* groups)
X
Xo Add support for german text messages
SHAR_EOF
$TOUCH -am 0822182591 TODO &&
chmod 0600 TODO ||
echo "restore of TODO failed"
set `wc -c TODO`;Wc_c=$1
if test "$Wc_c" != "1305"; then
echo original size 1305, current size $Wc_c
fi
# ============= UPDATE_INDEX ==============
echo "x - extracting UPDATE_INDEX (Text)"
sed 's/^X//' << 'SHAR_EOF' > UPDATE_INDEX &&
X#! /bin/csh -f
X# Iain Lea, 21-08-91
X# Script to update tin indexes from the at queue
X
X# required for at
Xsetenv HOME /piez/iain
Xsetenv NAME 'Iain J. Lea'
Xsetenv GROUP 'piez'
Xsetenv PATH :/usr/ucb:/bin:/usr/bin:/usr/local
X
X# specific for this script
Xsetenv SCRIPT /piez/iain/bin/UPDATE_INDEX
Xsetenv TIME 1000
Xsetenv TINDIR /piez/iain/bin
X
X# hangs update indexes onto system batch queue
X+ $TINDIR/tin -u
X
X# sleeps and then submits this script again for tommorow
X/usr/bin/sleep 120
X/usr/local/at $TIME $SCRIPT
SHAR_EOF
$TOUCH -am 0821093891 UPDATE_INDEX &&
chmod 0700 UPDATE_INDEX ||
echo "restore of UPDATE_INDEX failed"
set `wc -c UPDATE_INDEX`;Wc_c=$1
if test "$Wc_c" != "512"; then
echo original size 512, current size $Wc_c
fi
# ============= alloca.c ==============
echo "x - extracting alloca.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > alloca.c &&
X/*
X alloca -- (mostly) portable public-domain implementation -- D A Gwyn
X
X last edit: 86/05/30 rms
X include config.h, since on VMS it renames some symbols.
X Use xmalloc instead of malloc.
X
X This implementation of the PWB library alloca() function,
X which is used to allocate space off the run-time stack so
X that it is automatically reclaimed upon procedure exit,
X was inspired by discussions with J. Q. Johnson of Cornell.
X
X It should work under any C implementation that uses an
X actual procedure stack (as opposed to a linked list of
X frames). There are some preprocessor constants that can
X be defined when compiling for your specific system, for
X improved efficiency; however, the defaults should be okay.
X
X The general concept of this implementation is to keep
X track of all alloca()-allocated blocks, and reclaim any
X that are found to be deeper in the stack than the current
X invocation. This heuristic does not reclaim storage as
X soon as it becomes invalid, but it will do so eventually.
X
X As a special case, alloca(0) reclaims storage without
X allocating any. It is a good idea to use alloca(0) in
X your main control loop, etc. to force garbage collection.
X*/
X
X#ifndef lint
Xstatic char SCCSid[] = "@(#)alloca.c 1.1"; /* for the "what" utility */
X#endif
X
X#ifdef emacs
X#include "config.h"
X#ifdef static
X/* actually, only want this if static is defined as ""
X -- this is for usg, in which emacs must undefine static
X in order to make unexec workable
X */
X#ifndef STACK_DIRECTION
Xyou
Xlose
X-- must know STACK_DIRECTION at compile-time
X#endif /* STACK_DIRECTION undefined */
X#endif /* static */
X#endif /* emacs */
X
X#ifdef X3J11
Xtypedef void *pointer; /* generic pointer type */
X#else
Xtypedef char *pointer; /* generic pointer type */
X#endif
X
X#define NULL 0 /* null pointer constant */
X
Xextern void free();
Xextern pointer xmalloc();
X
X/*
X Define STACK_DIRECTION if you know the direction of stack
X growth for your system; otherwise it will be automatically
X deduced at run-time.
X
X STACK_DIRECTION > 0 => grows toward higher addresses
X STACK_DIRECTION < 0 => grows toward lower addresses
X STACK_DIRECTION = 0 => direction of growth unknown
X*/
X
X#ifndef STACK_DIRECTION
X#define STACK_DIRECTION 0 /* direction unknown */
X#endif
X
X#if STACK_DIRECTION != 0
X
X#define STACK_DIR STACK_DIRECTION /* known at compile-time */
X
X#else /* STACK_DIRECTION == 0; need run-time code */
X
Xstatic int stack_dir; /* 1 or -1 once known */
X#define STACK_DIR stack_dir
X
Xstatic void
Xfind_stack_direction (/* void */)
X{
X static char *addr = NULL; /* address of first
X `dummy', once known */
X auto char dummy; /* to get stack address */
X
X if (addr == NULL)
X { /* initial entry */
X addr = &dummy;
X
X find_stack_direction (); /* recurse once */
X }
X else /* second entry */
X if (&dummy > addr)
X stack_dir = 1; /* stack grew upward */
X else
X stack_dir = -1; /* stack grew downward */
X}
X
X#endif /* STACK_DIRECTION == 0 */
X
X/*
X An "alloca header" is used to:
X (a) chain together all alloca()ed blocks;
X (b) keep track of stack depth.
X
X It is very important that sizeof(header) agree with malloc()
X alignment chunk size. The following default should work okay.
X*/
X
X#ifndef ALIGN_SIZE
X#define ALIGN_SIZE sizeof(double)
X#endif
X
Xtypedef union hdr
X{
X char align[ALIGN_SIZE]; /* to force sizeof(header) */
X struct
X {
X union hdr *next; /* for chaining headers */
X char *deep; /* for stack depth measure */
X } h;
X} header;
X
X/*
X alloca( size ) returns a pointer to at least `size' bytes of
X storage which will be automatically reclaimed upon exit from
X the procedure that called alloca(). Originally, this space
X was supposed to be taken from the current stack frame of the
X caller, but that method cannot be made to work for some
X implementations of C, for example under Gould's UTX/32.
X*/
X
Xstatic header *last_alloca_header = NULL; /* -> last alloca header */
X
Xpointer
Xalloca (size) /* returns pointer to storage */
X unsigned size; /* # bytes to allocate */
X{
X auto char probe; /* probes stack depth: */
X register char *depth = &probe;
X
X#if STACK_DIRECTION == 0
X if (STACK_DIR == 0) /* unknown growth direction */
X find_stack_direction ();
X#endif
X
X /* Reclaim garbage, defined as all alloca()ed storage that
X was allocated from deeper in the stack than currently. */
X
X {
X register header *hp; /* traverses linked list */
X
X for (hp = last_alloca_header; hp != NULL;)
X if (STACK_DIR > 0 && hp->h.deep > depth
X || STACK_DIR < 0 && hp->h.deep < depth)
X {
X register header *np = hp->h.next;
X
X free ((pointer) hp); /* collect garbage */
X
X hp = np; /* -> next header */
X }
X else
X break; /* rest are not deeper */
X
X last_alloca_header = hp; /* -> last valid storage */
X }
X
X if (size == 0)
X return NULL; /* no allocation required */
X
X /* Allocate combined header + user data storage. */
X
X {
X register pointer new = xmalloc (sizeof (header) + size);
X /* address of header */
X
X ((header *)new)->h.next = last_alloca_header;
X ((header *)new)->h.deep = depth;
X
X last_alloca_header = (header *)new;
X
X /* User storage begins just after header. */
X
X return (pointer)((char *)new + sizeof(header));
X }
X}
X
Xpointer xmalloc(n)
Xunsigned int n;
X{
X extern pointer malloc();
X pointer cp;
X static char mesg[] = "xmalloc: no memory!\n";
X
X cp = malloc(n);
X if (! cp) {
X write (2, mesg, sizeof(mesg) - 1);
X exit(1);
X }
X return cp;
X}
SHAR_EOF
$TOUCH -am 0815172991 alloca.c &&
chmod 0600 alloca.c ||
echo "restore of alloca.c failed"
set `wc -c alloca.c`;Wc_c=$1
if test "$Wc_c" != "5457"; then
echo original size 5457, current size $Wc_c
fi
# ============= art.c ==============
echo "x - extracting art.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > art.c &&
X/*
X * Project : tin - a visual threaded usenet newsreader
X * Module : art.c
X * Author : R.Skrenta / I.Lea
X * Created : 01-04-91
X * Updated : 22-08-91
X * Release : 1.0
X * Notes :
X * Copyright : (c) Copyright 1991 by Rich Skrenta & Iain Lea
X * You may freely copy or redistribute this software,
X * so long as there is no profit made from its use, sale
X * trade or reproduction. You may not change this copy-
X * right notice, and it must be included in any copy made
X */
X
X#include "tin.h"
X
X#define HEADER_LEN 1024
X
Xextern int errno;
X
Xchar index_file[LEN+1];
Xchar *glob_art_group;
Xint index_file_killed = FALSE;
Xlong last_read_article;
X
X#ifdef SIGTSTP
Xvoid art_susp (sig)
X int sig;
X{
X char buf[LEN];
X
X Raw(FALSE);
X putchar('\n');
X signal(SIGTSTP, SIG_DFL);
X#ifdef BSD
X sigsetmask(sigblock(0) & ~(1 << (SIGTSTP -1)));
X#endif
X kill(0, SIGTSTP);
X
X signal(SIGTSTP, art_susp);
X
X if (! update) {
X mail_setup ();
X
X Raw(TRUE);
X
X ClearScreen();
X sprintf (buf, txt_group, glob_art_group);
X wait_message (buf);
X }
X}
X#endif
X
X
X/*
X * Convert a string to a long, only look at first n characters
X */
X
Xlong my_atol (s, n)
X char *s;
X int n;
X{
X long ret = 0;
X
X while (*s && n--) {
X if (*s >= '0' && *s <= '9')
X ret = ret * 10 + (*s - '0');
X else
X return -1;
X s++;
X }
X
X return ret;
X}
X
X
X/*
X * Construct the pointers to the basenotes of each thread
X * arts[] contains every article in the group. inthread is
X * set on each article that is after the first article in the
X * thread. Articles which have been expired have their thread
X * set to -2 (ART_EXPIRED).
X */
X
Xvoid find_base ()
X{
X int i;
X
X top_base = 0;
X
X for (i = 0; i < top; i++)
X if (! arts[i].inthread && arts[i].thread != ART_EXPIRED) {
X if (top_base >= max_art)
X expand_art ();
X base[top_base++] = i;
X }
X}
X
X/*
X * Count the number of non-expired and non-killed articles in arts[]
X */
X
Xint num_of_arts ()
X{
X int sum = 0;
X register int i;
X
X for (i = 0; i < top; i++) {
X if (arts[i].thread != ART_EXPIRED && ! arts[i].tagged) {
X sum++;
X }
X }
X
X return sum;
X}
X
X/*
X * Do we have an entry for article art?
X */
X
Xint valid_artnum (art)
X long art;
X{
X register int i;
X
X for (i = 0; i < top; i++)
X if (arts[i].artnum == art)
X return i;
X
X return -1;
X}
X
X
X/*
X * Return TRUE if arts[] contains any expired articles
X * (articles we have an entry for which don't have a corresponding
X * article file in the spool directory)
X */
X
Xint purge_needed ()
X{
X register int i;
X
X for (i = 0; i < top; i++)
X if (arts[i].thread == ART_EXPIRED)
X return TRUE;
X
X return FALSE;
X}
X
X
X/*
X * Main group indexing routine. Group should be the name of the
X * newsgroup, i.e. "comp.unix.amiga". group_path should be the
X * same but with the .'s turned into /'s: "comp/unix/amiga"
X *
X * Will read any existing index, create or incrementally update
X * the index by looking at the articles in the spool directory,
X * and attempt to write a new index if necessary.
X */
X
Xvoid index_group (group, group_path)
X char *group;
X char *group_path;
X{
X int killed = FALSE;
X int modified = FALSE;
X glob_art_group = group;
X
X#ifdef SIGTSTP
X signal(SIGTSTP, art_susp);
X#endif
X
X if (! update) {
X sprintf (msg, txt_group, group);
X wait_message (msg);
X }
X
X hash_reclaim ();
X free_art_array ();
X
X if (local_index)
X find_local_index (group);
X else
X sprintf (index_file, "%s/%s/%s", spooldir, group_path, INDEXDIR);
X
X /*
X * load articles from index file if it exists
X */
X load_index ();
X
X /*
X * load killed articles into arts[] because kill arts is OFF
X */
X if (! kill_articles && index_file_killed) {
X index_file_killed = FALSE;
X last_read_article = 0L;
X }
X
X /*
X * add any articles to arts[] that are new or were killed
X */
X modified = read_group (group, group_path);
X
X /*
X * compare kill descriptions to arts[] and kill mark any that match
X */
X killed = kill_any_articles (group);
X
X if (modified || killed || purge_needed()) {
X if (local_index) { /* writing index in home directory */
X setuid(real_uid); /* so become them */
X setgid(real_gid);
X }
X
X if (killed) {
X reload_index_file (group, killed);
X } else {
X dump_index (group, FALSE);
X make_threads (FALSE);
X find_base ();
X }
X
X if (local_index) {
X setuid(tin_uid);
X setgid(tin_gid);
X }
X } else {
X make_threads (FALSE);
X find_base ();
X }
X
X if ((modified || killed) && ! update) {
X clear_message();
X }
X}
X
X/*
X * Index a group. Assumes any existing index has already been
X * loaded.
X */
X
Xint read_group (group, group_path)
X char *group;
X char *group_path;
X{
X int fd;
X long art;
X int count;
X int modified = FALSE;
X int respnum;
X register int i;
X
X setup_base (group, group_path); /* load article numbers into base[] */
X count = 0;
X
X for (i = 0; i < top_base; i++) { /* for each article # */
X art = base[i];
X
X/*
X * Do we already have this article in our index? Change thread from
X * -2 (ART_EXPIRED) to -1 (ART_NORMAL) if so and skip the header eating.
X */
X
X if ((respnum = valid_artnum (art)) >= 0 || art <= last_read_article) {
X arts[respnum].thread = ART_NORMAL;
X arts[respnum].unread = ART_UNREAD;
X continue;
X }
X
X if (! modified) {
X modified = TRUE; /* we've modified the index */
X /* it will need to be re-written */
X }
X
X if ((fd = open_header_fd (group_path, art)) < 0) {
X continue;
X }
X
X /*
X * Add article to arts[]
X */
X if (top >= max_art)
X expand_art();
X
X arts[top].artnum = art;
X arts[top].thread = ART_NORMAL;
X
X set_article (&arts[top]);
X
X if (! parse_headers (fd, &arts[top])) {
X continue;
X }
X close (fd);
X last_read_article = arts[top].artnum; /* used if arts are killed */
X top++;
X
X if (++count % 10 == 0 && ! update) {
X sprintf (msg, txt_indexing, count);
X wait_message (msg);
X }
X }
X
X return modified;
X}
X
X
X/*
X * Go through the articles in arts[] and use .thread to snake threads
X * through them. Use the subject line to construct threads. The
X * first article in a thread should have .inthread set to FALSE, the
X * rest TRUE. Only do unexprired articles we haven't visited yet
X * (arts[].thread == -1 ART_NORMAL).
X */
X
Xvoid make_threads (rethread)
X int rethread;
X{
X register int i;
X register int j;
X
X /*
X * .thread & .inthread need to be reset if re-threading arts[]
X */
X if (rethread) {
X for (i=0 ; i < top ; i++) {
X arts[i].thread = ART_NORMAL;
X arts[i].inthread = FALSE;
X }
X }
X
X switch (sort_art_type) {
X case SORT_BY_NONE: /* don't sort at all */
X qsort (arts, top, sizeof (struct header), artnum_comp);
X break;
X case SORT_BY_SUBJ:
X qsort (arts, top, sizeof (struct header), subj_comp);
X break;
X case SORT_BY_FROM:
X qsort (arts, top, sizeof (struct header), from_comp);
X break;
X case SORT_BY_DATE:
X qsort (arts, top, sizeof (struct header), date_comp);
X break;
X default:
X break;
X }
X
X for (i = 0; i < top; i++) {
X if (arts[i].thread == ART_NORMAL) {
X for (j = i+1; j < top; j++) {
X if (arts[j].thread != ART_EXPIRED &&
X ((arts[i].subject == arts[j].subject) ||
X ((arts[i].part || arts[i].patch) &&
X arts[i].archive == arts[j].archive))) {
X arts[i].thread = j;
X arts[j].inthread = TRUE;
X break;
X }
X }
X }
X }
X}
X
X/*
X * Return a pointer into s eliminating any leading Re:'s. Example:
X *
X * Re: Reorganization of misc.jobs
X * ^ ^
X */
X
Xchar *eat_re (s)
X char *s;
X{
X
X while (*s == 'r' || *s == 'R') {
X if ((*(s+1) == 'e' || *(s+1) == 'E')) {
X if (*(s+2) == ':')
X s += 3;
X else if (*(s+2) == '^' && isdigit(*(s+3)) && *(s+4) == ':')
X s += 5; /* hurray nn */
X else
X break;
X } else
X break;
X while (*s == ' ')
X s++;
X }
X
X return s;
X}
X
X/*
X * Hash the subjects (after eating the Re's off) for a quicker
X * thread search later. We store the hashes for subjects in the
X * index file for speed.
X */
X
Xlong hash_s(s)
X char *s;
X{
X char *t;
X long h = 0;
X
X t = s;
X
X while (*t)
X h = h * 64 + *t++;
X
X return h;
X}
X
X
Xint parse_headers (fd, h)
X int fd;
X struct header *h;
X{
X char buf[HEADER_LEN];
X char buf2[HEADER_LEN];
X char *ptr, *ptrline, *s;
X int n = 0, len = 0, lineno = 0;
X int flag;
X int got_subject = FALSE;
X int got_from = FALSE;
X int got_date = FALSE;
X int got_archive = FALSE;
X
X if ((n = read(fd, buf, HEADER_LEN)) <= 0)
X return FALSE;
X
X buf[n-1] = '\0';
X
X ptr = buf;
X
X while (1) {
X for (ptrline = ptr; *ptr && *ptr != '\n'; ptr++) {
X if (((*ptr) & 0x7F) < 32) {
X *ptr = ' ';
X }
X }
X flag = *ptr;
X *ptr++ = '\0';
X lineno++;
X
X if (! got_from && strncmp(ptrline, "From: ", 6) == 0) {
X my_strncpy(buf2, ptrline+6, max_from+1);
X buf2[max_from] = '\0';
X h->from = hash_str (buf2);
X got_from = TRUE;
X } else if (! got_subject && strncmp(ptrline, "Subject: ", 9) == 0) {
X my_strncpy (buf2, ptrline+9, max_subj+max_from+1);
X s = eat_re (buf2);
X s[max_subj+max_from] = '\0';
X h->subject = hash_str (eat_re (s));
X got_subject = TRUE;
X } else if (! got_date && strncmp(ptrline, "Date: ", 6) == 0) {
X my_strncpy (buf2, ptrline+6, 32);
X parse_date (buf2 ,h->date);
X got_date = TRUE;
X } else if (strncmp(ptrline, "Archive-name: ", 14) == 0) {
X if ((s = (char *) strchr (ptrline+14, '/')) != NULL) {
X my_strncpy(buf2, ptrline+14, MAX_ARCH);
X if (strncmp (s+1,"part",4) == 0 ||
X strncmp (s+1,"Part",4) == 0) {
X h->part = str_dup (s+5);
X len = (int) strlen (h->part);
X if (h->part[len-1] == '\n') {
X h->part[len-1] = '\0';
X }
X } else {
X if (strncmp (s+1,"patch",5) == 0 ||
X strncmp (s+1,"Patch",5) == 0) {
X h->patch = str_dup (s+6);
X len = (int) strlen (h->patch);
X if (h->patch[len-1] == '\n') {
X h->patch[len-1] = '\0';
X }
X }
X }
X if (h->part || h->patch) {
X s = buf2;
X while (*s && *s != '/')
X s++;
X *s = '\0';
X s = buf2;
X h->archive = hash_str (s);
X got_archive = TRUE;
X }
X }
X }
X
X if (! flag || lineno > 25 || got_archive) {
X debug_print_header (h);
X return TRUE;
X }
X }
X}
X
X/*
X * Write out an index file. Write the group name first so if
X * local indexing is done we can disambiguate between group name
X * hash collisions by looking at the index file.
X *
X * NOTE: check out the add_string routine in hashstr.c to
X * understand what *iptr is doing in this routine.
X */
X
Xvoid dump_index (group, killed)
X char *group;
X int killed;
X{
X char nam[LEN+1];
X FILE *fp;
X int *iptr;
X int realnum;
X register int i;
X
X sprintf (nam, "%s.%d", index_file, getpid());
X if ((fp = fopen (nam, "w")) == NULL) {
X error_message (txt_cannot_open, nam);
X return;
X }
X
X /*
X * dump group header info.
X */
X if (sort_art_type != SORT_BY_NONE) {
X qsort (arts, top, sizeof (struct header), artnum_comp);
X }
X fprintf(fp, "%s\n", group);
X fprintf(fp, "%d\n", num_of_arts ());
X if (last_read_article > arts[top-1].artnum) {
X fprintf(fp, "%ld\n", last_read_article);
X } else {
X fprintf(fp, "%ld\n", arts[top-1].artnum);
X }
X if (index_file_killed && killed) {
X fprintf (fp, "KILLED\n");
X } else {
X fprintf (fp, "COMPLETE\n");
X }
X
X /*
X * dump articles
X */
X realnum = 0;
X for (i = 0; i < top; i++) {
X if (arts[i].thread != ART_EXPIRED && ! arts[i].tagged) {
X debug_print_header (&arts[i]);
X
X fprintf(fp, "%ld\n", arts[i].artnum);
X
X iptr = (int *) arts[i].subject;
X iptr--;
X
X if (! arts[i].subject) {
X fprintf(fp, " \n");
X } else if (*iptr < 0 || *iptr > top) {
X fprintf(fp, " %s\n", arts[i].subject);
X *iptr = realnum;
X/*
X } else if (arts[*iptr].tagged) {
X fprintf(fp, " %s\n", arts[i].subject);
X *iptr = realnum;
X } else if (killed && *iptr == i) {
X*/
X } else if (killed || *iptr == i) {
X fprintf(fp, " %s\n", arts[i].subject);
X } else {
X fprintf(fp, "%%%d\n", *iptr);
X }
X
X iptr = (int *) arts[i].from;
X iptr--;
X
X if (! arts[i].from) {
X fprintf (fp, " \n");
X } else if (*iptr < 0 || *iptr > top) {
X fprintf (fp, " %s\n", arts[i].from);
X *iptr = realnum;
X/*
X } else if (arts[*iptr].tagged) {
X fprintf(fp, " %s\n", arts[i].from);
X *iptr = realnum;
X } else if (killed && *iptr == i) {
X*/
X } else if (killed || *iptr == i) {
X fprintf(fp, " %s\n", arts[i].from);
X } else {
X fprintf(fp, "%%%d\n", *iptr);
X }
X
X fprintf (fp, "%s\n", arts[i].date);
X
X iptr = (int *) arts[i].archive;
X iptr--;
X
X if (! arts[i].archive) {
X fprintf (fp, "\n");
X } else if (*iptr < 0 || *iptr > top) {
X fprintf (fp, " %s\n", arts[i].archive);
X *iptr = realnum;
X/*
X } else if (arts[*iptr].tagged) {
X fprintf (fp, " %s\n", arts[i].archive);
X *iptr = realnum;
X*/
X } else if (arts[i].part || arts[i].patch) {
X/*
X if (killed && *iptr == i) {
X*/
X if (killed || *iptr == i) {
X fprintf(fp, " %s\n", arts[i].archive);
X } else {
X fprintf (fp, "%%%d\n", *iptr);
X }
X } else {
X fprintf (fp, "\n");
X }
X
X if (! arts[i].part) {
X fprintf (fp, " \n");
X } else {
X fprintf (fp, "%s\n", arts[i].part);
X }
X
X if (! arts[i].patch) {
X fprintf (fp, " \n");
X } else {
X fprintf (fp, "%s\n", arts[i].patch);
X }
X
X realnum++;
X }
X }
X fclose (fp);
X chmod (index_file, 0644);
X rename_file (nam, index_file);
X if (debug) {
X sprintf (msg, "/bin/cp %s INDEX", index_file);
X system (msg);
X }
X}
X
X/*
X * strncpy that stops at a newline and null terminates
X */
X
Xvoid my_strncpy(p, q, n)
X char *p;
X char *q;
X int n;
X{
X while (n--) {
X if (!*q || *q == '\n')
X break;
X *p++ = *q++;
X }
X *p = '\0';
X}
X
X/*
X * Read in an index file.
X *
X * index file header
X * 1. newsgroup name (ie. alt.sources)
X * 2. number of articles (ie. 26)
X * 3. number of last read article (ie. 210)
X * 4. Is this a complete/killed index file (ie. COMPLETE/KILLED)
X * index file record
X * 1. article number (ie. 183) [mandatory]
X * 2. Subject: line (ie. Which newsreader?) [mandatory]
X * 3. From: line (ie. iain@norisc) [mandatory]
X * 4. Date: of posting (ie. 911231125959) [mandatory]
X * 5. Archive: name (ie. compiler) [optional]
X * 6. Part number of Archive: name (ie. 01) [optional]
X * 7. Patch number of Archive: name (ie. 01) [optional]
X */
X
Xint load_index ()
X{
X int error = 0;
X int i, n;
X char buf[LEN+1], *p;
X FILE *fp;
X
X top = 0;
X last_read_article = 0L;
X
X if ((fp = fopen (index_file, "r")) == NULL) {
X return FALSE;
X }
X
X debug_print_comment ("*** LOADING ***");
X
X /*
X * load header - discard group name, num. of arts in index file after any arts were killed
X */
X if (fgets(buf, LEN, fp) == NULL ||
X fgets(buf, LEN, fp) == NULL) {
X error = 0;
X goto corrupt_index;
X }
X i = atoi (buf);
X
X /*
X * num. of last_read_article including any that were killed
X */
X if (fgets(buf, LEN, fp) == NULL) {
X error = 1;
X goto corrupt_index;
X }
X last_read_article = atol (buf);
X
X /*
X * is index file complete or were articles killed when it was dumped
X */
X if (fgets(buf, LEN, fp) == NULL) {
X error = 2;
X goto corrupt_index;
X }
X index_file_killed = (buf[0] == 'K' ? TRUE : FALSE);
X
X /*
X * load articles
X */
X for (; top < i ; top++) {
X if (top >= max_art) {
X expand_art ();
X }
X
X arts[top].thread = ART_EXPIRED;
X set_article (&arts[top]);
X
X /*
X * Article no.
X */
X if (fgets(buf, LEN, fp) == NULL) {
X error = 3;
X goto corrupt_index;
X }
X arts[top].artnum = atol(buf);
X
X /*
X * Subject:
X */
X if (fgets(buf, LEN, fp) == NULL) {
X error = 4;
X goto corrupt_index;
X }
X
X if (buf[0] == '%') {
X n = atoi (&buf[1]);
X if (n >= top || n < 0) {
X error = 5;
X goto corrupt_index;
X }
X arts[top].subject = arts[n].subject;
X } else if (buf[0] == ' ') {
X for (p = &buf[1]; *p && *p != '\n'; p++) ;
X *p = '\0';
X buf[max_subj+max_from] = '\0';
X arts[top].subject = hash_str (&buf[1]);
X } else {
X error = 6;
X goto corrupt_index;
X }
X
X /*
X * From:
X */
X if (fgets(buf, LEN, fp) == NULL) {
X error = 7;
X goto corrupt_index;
X }
X
X if (buf[0] == '%') {
X n = atoi (&buf[1]);
X if (n >= top || n < 0) {
X error = 8;
X goto corrupt_index;
X }
X arts[top].from = arts[n].from;
X } else if (buf[0] == ' ') {
X for (p = &buf[1]; *p && *p != '\n'; p++) ;
X *p = '\0';
X buf[max_from] = '\0';
X arts[top].from = hash_str (&buf[1]);
X } else {
X error = 9;
X goto corrupt_index;
X }
X
X /*
X * Date:
X */
X if (fgets(buf, LEN, fp) == NULL) {
X error = 10;
X goto corrupt_index;
X }
X
X buf[strlen (buf)-1] = '\0';
X my_strncpy (arts[top].date, buf, 12);
X
X /*
X * Archive-name:
X */
X if (fgets(buf, LEN, fp) == NULL) {
X error = 11;
X goto corrupt_index;
X }
X
X if (buf[0] == '\n') {
X arts[top].archive = (char *) 0;
X } else if (buf[0] == '%') {
X n = atoi (&buf[1]);
X if (n > top || n < 0) {
X error = 12;
X goto corrupt_index;
X }
X arts[top].archive = arts[n].archive;
X } else if (buf[0] == ' ') {
X for (p = &buf[1]; *p && *p != '\n'; p++) ;
X *p = '\0';
X buf[MAX_ARCH] = '\0';
X arts[top].archive = hash_str (&buf[1]);
X } else {
X error = 13;
X goto corrupt_index;
X }
X
X /*
X * part no.
X */
X if (fgets(buf, LEN, fp) == NULL) {
X error = 14;
X goto corrupt_index;
X }
X
X if (buf[0] != ' ') {
X buf[strlen (buf)-1] = '\0';
X arts[top].part = str_dup (buf);
X }
X
X /*
X * patch no.
X */
X if (fgets(buf, LEN, fp) == NULL) {
X error = 15;
X goto corrupt_index;
X }
X
X if (buf[0] != ' ') {
X buf[strlen (buf)-1] = '\0';
X arts[top].patch = str_dup (buf);
X }
X
X debug_print_header (&arts[top]);
X }
X
X fclose(fp);
X return TRUE;
X
Xcorrupt_index:
X if (! update) {
X sprintf (msg, txt_corrupt_index, index_file, error, top);
X error_message (msg, NULL);
X }
X
X if (debug) {
X sprintf (msg, "cp %s INDEX.BAD", index_file);
X system (msg);
X }
X
X unlink (index_file);
X top = 0;
X return FALSE;
X}
X
X
X/*
X * Look in the local $HOME/RCDIR/INDEXDIR (or wherever) directory for the
X * index file for the given group. Hashing the group name gets
X * a number. See if that #.1 file exists; if so, read first line.
X * Group we want? If no, try #.2. Repeat until no such file or
X * we find an existing file that matches our group.
X */
X
Xvoid find_local_index (group)
X char *group;
X{
X unsigned long h;
X static char buf[LEN+1];
X int i;
X char *p;
X FILE *fp;
X
X h = hash_groupname (group);
X
X i = 1;
X while (1) {
X sprintf(index_file, "%s/%lu.%d", indexdir, h, i);
X
X if ((fp = fopen(index_file, "r")) == NULL) {
X return;
X }
X
X if (fgets(buf, LEN, fp) == NULL) {
X fclose(fp);
X return;
X }
X fclose(fp);
X
X for (p = buf; *p && *p != '\n'; p++) ;
X *p = '\0';
X
X if (strcmp(buf, group) == 0)
X return;
X
X i++;
X }
X}
X
X
X/*
X * Run the index file updater only for the groups we've loaded.
X */
X
Xvoid do_update()
X{
X int i, j;
X char group_path[LEN+1];
X char *p;
X
X for (i = 0; i < local_top; i++) {
X strcpy(group_path, active[my_group[i]].name);
X for (p = group_path; *p; p++) {
X if (*p == '.') {
X *p = '/';
X }
X }
X if (verbose) {
X printf ("%s %s\n", (catchup ? "catchup" : "updating"),
X active[my_group[i]].name);
X fflush (stdout);
X }
X index_group (active[my_group[i]].name, group_path);
X if (catchup) {
X for (j = 0; j < top; j++) {
X arts[j].unread = ART_READ;
X }
X update_newsrc (active[my_group[i]].name, my_group[i]);
X }
X }
X}
X
X/*
X * reload index after any articles have been killed
X */
X
Xvoid reload_index_file (group, killed)
X char *group;
X int killed;
X{
X char group_path[LEN+1];
X char *p;
X int i, respnum;
X long art;
X
X if (local_index) { /* writing index in home directory */
X setuid (real_uid); /* so become them */
X setgid (real_gid);
X }
X
X strcpy (group_path, group); /* turn comp.unix.amiga into */
X for (p = group_path; *p; p++) /* comp/unix/amiga */
X if (*p == '.')
X *p = '/';
X
X if (killed) {
X if (! update) {
X wait_message ("Killing...");
X }
X index_file_killed = TRUE;
X setup_base (group, group_path);
X dump_index (group, killed);
X load_index ();
X } else {
X if (! update) {
X wait_message ("Unkilling...");
X }
X if (local_index) {
X find_local_index (group);
X } else {
X sprintf (index_file, "%s/%s/%s", spooldir, group_path, INDEXDIR);
X }
X
X unlink (index_file); /* delete index file */
X
X index_file_killed = FALSE;
X last_read_article = 0L;
X
X if (read_group (group, group_path)) {
X dump_index (group, killed);
X }
X }
X
X make_threads (TRUE);
X find_base ();
X
X if (local_index) {
X setuid (tin_uid);
X setgid (tin_gid);
X }
X
X return;
X}
X
X/*
X * convert date from "24 Jul 91 12:59:59" to "910724125959"
X */
X
Xchar *parse_date (date, str)
X char *date;
X char *str;
X{
X char buf[4];
X int i = 3;
X
X if (date[1] == ' ') { /* ie. "2 Aug..." instead of "12 Aug... */
X str[4] = '0'; /* day */
X str[5] = date[0];
X i = 2;
X } else {
X str[4] = date[0]; /* day */
X str[5] = date[1];
X }
X
X buf[0] = date[i++]; /* month in Jan,Feb,.. form */
X buf[1] = date[i++];
X buf[2] = date[i++];
X buf[3] = '\0';
X
X i++;
X
X str[0] = date[i++]; /* year */
X str[1] = date[i++];
X
X i++;
X
X if (strcmp (buf, "Jan") == 0) { /* convert Jan to 01 etc */
X str[2] = '0';
X str[3] = '1';
X } else if (strcmp (buf, "Feb") == 0) {
X str[2] = '0';
X str[3] = '2';
X } else if (strcmp (buf, "Mar") == 0) {
X str[2] = '0';
X str[3] = '3';
X } else if (strcmp (buf, "Apr") == 0) {
X str[2] = '0';
X str[3] = '4';
X } else if (strcmp (buf, "May") == 0) {
X str[2] = '0';
X str[3] = '5';
X } else if (strcmp (buf, "Jun") == 0) {
X str[2] = '0';
X str[3] = '6';
X } else if (strcmp (buf, "Jul") == 0) {
X str[2] = '0';
X str[3] = '7';
X } else if (strcmp (buf, "Aug") == 0) {
X str[2] = '0';
X str[3] = '8';
X } else if (strcmp (buf, "Sep") == 0) {
X str[2] = '0';
X str[3] = '9';
X } else if (strcmp (buf, "Oct") == 0) {
X str[2] = '1';
X str[3] = '0';
X } else if (strcmp (buf, "Nov") == 0) {
X str[2] = '1';
X str[3] = '1';
X } else if (strcmp (buf, "Dec") == 0) {
X str[2] = '1';
X str[3] = '2';
X } else {
X str[2] = '0';
X str[3] = '0';
X }
X
X str[6] = date[i++]; /* hour */
X str[7] = date[i++];
X
X i++;
X
X str[8] = date[i++]; /* minutes */
X str[9] = date[i++];
X
X i++;
X
X str[10] = date[i++]; /* seconds */
X str[11] = date[i++];
X
X str[12] = '\0'; /* terminate string */
X
X return (str);
X}
X
X
Xint artnum_comp (s1, s2)
X struct header *s1;
X struct header *s2;
X{
X /* s1->artnum less than s2->artnum */
X if (s1->artnum < s2->artnum) {
X return -1;
X }
X /* s1->artnum greater than s2->artnum */
X if (s1->artnum > s2->artnum) {
X return 1;
X }
X return 0;
X}
X
X
Xint subj_comp (s1, s2)
X struct header *s1;
X struct header *s2;
X{
X /* s1->subject less than s2->subject */
X if (strcmp (s1->subject, s2->subject) < 0) {
X return -1;
X }
X /* s1->subject greater than s2->subject */
X if (strcmp (s1->subject, s2->subject) > 0) {
X return 1;
X }
X return 0;
X}
X
X
Xint from_comp (s1, s2)
X struct header *s1;
X struct header *s2;
X{
X /* s1->from less than s2->from */
X if (strcmp (s1->from, s2->from) < 0) {
SHAR_EOF
echo "End of tin part 1"
echo "File art.c is continued in part 2"
echo "2" > shar3_seq_.tmp
exit 0
--
NAME Iain Lea
EMAIL norisc!iain@estevax.UUCP ...!unido!estevax!norisc!iain
SNAIL Siemens AG, AUT 922C, Postfach 4848, Nuernberg, Germany
PHONE +49-911-895-3853, +49-911-895-3877, +49-911-331963