home *** CD-ROM | disk | FTP | other *** search
- 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
-