home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
misc
/
volume29
/
tin
/
part03
< prev
next >
Wrap
Text File
|
1992-03-28
|
52KB
|
1,839 lines
Newsgroups: comp.sources.misc
From: iain%anl433.uucp@germany.eu.net (Iain J. Lea)
Subject: v29i021: tin - threaded full screen newsreader v1.1P1, Part03/12
Message-ID: <1992Mar27.033012.2189@sparky.imd.sterling.com>
X-Md4-Signature: 7ac252288dcd0d07398f2b1d1636718c
Date: Fri, 27 Mar 1992 03:30:12 GMT
Approved: kent@sparky.imd.sterling.com
Submitted-by: iain%anl433.uucp@germany.eu.net (Iain J. Lea)
Posting-number: Volume 29, Issue 21
Archive-name: tin/part03
Environment: BSD, SCO, ISC, SUNOS, SYSVR3, SYSVR4, ULTRIX, XENIX
Supersedes: tin: Volume 28, Issue 45-55
#!/bin/sh
# this is tin.shar.03 (part 3 of tin1.1)
# do not concatenate these parts, unpack them in order with /bin/sh
# file tin.nrf continued
#
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck
if test "$Scheck" != 3; then
echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping tin.nrf'
else
echo 'x - continuing file tin.nrf'
sed 's/^X//' << 'SHAR_EOF' >> 'tin.nrf' &&
X
X KK Mark thread as read and advance to next unread thread.
X
X mm Mail current article / thread / articles matching pattern
X / tagged articles to someone.
X
X MM User configurable options menu (for more information see
X section Options Menu).
X
X nn Go to the next article.
X
X NN Go to the next unread article.
X
X oo Output current article / thread / articles matching
X pattern / tagged articles to printer.
X
X oo Output article/thread/tagged articles to printer.
X
X pp Go to the previous article.
X
X PP Go to the previous unread article.
X
X qq Quit tin.
X
X rr Reply through mail to author.
X
X RR Reply through mail to author with a copy of the current
X
X
X
X
10 Release 4.1R NEWS-OS
X
X
X
X
X
TIN(1) LOCAL TIN(1)
X
X
X
X article included.
X
X ss Save current article / thread / articles matching pattern
X / tagged articles to file / files / mailbox. To save to a
X mailbox enter '=' or '=mailbox' when asked for filename
X to save to. To save in <newsgroup name>/<filename> format
X enter '+filename'. Environment variables are allowed
X within a filename (ie. $SOURCES/dir/filename).
X
X tt Return to group selection index.
X
X vv Print tin version number.
X
X ww Post an article to current group.
X
X WW List articles posted by user. The date posted, the
X newsgroup and the subject are listed.
X
X zz Mark article as unread.
X
X // Article forward search.
X
X ?? Article backward search
X
X || Pipe current article / thread / articles matching pattern
X / tagged articles into command.
X
X << Goto the first article in the current thread.
X
X >> Goto the last article in the current thread.
X
OOPPTTIIOONNSS MMEENNUU
X This menu is accessed by pressing 'M' at all levels. It allows the
X user to customize the behaviour of tin. The options are saved to
X the file $_H_O_M_E/._t_i_n/_t_i_n_r_c. Use <SPACE> to toggle the required
X option and <CR> to set.
X
X AAuuttoo ssaavvee
X Automatically save articles/threads by Archive-name: line in
X article header. This is useful to set ON in conjunction with
X 'Save separate'.
X
X SSaavvee sseeppaarraattee
X Save articles/threads to separate files. Set ON if saving
X source code. Set OFF if saving a conversational thread.
X
X MMaarrkk ssaavveedd rreeaadd
X This allows saved articles/threads to be automatically marked
X as having been read.
X
X KKiillll aarrttiicclleess
X This allows the user to kill articles that match entries in the
X
X
X
X
NEWS-OS Release 4.1R 11
X
X
X
X
X
TIN(1) LOCAL TIN(1)
X
X
X
X kill file $_H_O_M_E/._t_i_n/_k_i_l_l.
X
X DDrraaww aarrrrooww
X Allows groups/articles to be selected by an arrow '->' if set
X ON or by an highlighted bar if set OFF.
X
X PPrriinntt hheeaaddeerr
X This allows the complete mail header or only the Siubject: and
X From: fields to be output when printing articles.
X
X GGoottoo 11sstt uunnrreeaadd
X This allows the cursor to be placed at the first / last unread
X article upon entering a newsgroup with unread news.
X
X SSccrroollll ffuullll ppaaggee
X If set ON scrolling of groups/articles will be a full page at a
X time, otherwise half a page at a time.
X
X CCaattcchhuupp oonn qquuiitt
X If set ON the user is asked when quitting if all groups read
X during the current session should be marked read.
X
X TThhrreeaadd aarrttiicclleess
X If set ON articles will be threaded in all groups (default),
X otherwise articles will be shown unthreaded. If set ON but
X certain user specified groups are in $_H_O_M_E/._t_i_n/_u_n_t_h_r_e_a_d, the
X specified groups will be unthreaded and the rest will be
X threaded.
X
X SShhooww oonnllyy uunnrreeaadd
X If set ON show only new/unread articles, otherwise show all
X articles.
X
X SShhooww AAuutthhoorr
X If set 'None' only the Subject: line will be displayed. If set
X 'Addr' Subject: line & the address part of the From: line are
X displayed. If set 'Name' Subject: line & the authors full name
X part of the From: line are displayed. If set 'Both' Subject:
X line & all of the From: line are displayed.
X
X PPrroocceessss ttyyppee
X This specifies the default type of post processing to perform
X on saved articles. The following types of processing are
X allowed:
X -none.
X -unpacking of multi-part shell archives.
X -unpacking of multi-part uuencoded files.
X -unpacking of multi-part uuencoded files that produce a
X *.zoo archive whose contents is listed.
X -unpacking of multi-part uuencoded files that produce a
X *.zoo archive whose contents is extracted.
X
X
X
X
X
12 Release 4.1R NEWS-OS
X
X
X
X
X
TIN(1) LOCAL TIN(1)
X
X
X
X SSoorrtt aarrttiicclleess bbyy
X This specifies how articles should be sorted. The following
X sort types are allowed:
X -don't sort articles (default).
X -sort articles by Subject: field (ascending & descending).
X -sort articles by From: field (ascending & descending).
X -sort articles by Date: field (ascending & descending).
X
X SSaavvee ddiirreeccttoorryy
X The directory where articles/threads are to be saved. Default
X is $_H_O_M_E/_N_e_w_s.
X
X MMaaiill ddiirreeccttoorryy
X The directory where articles/threads are to be saved in mailbox
X format. This feature is mainly for use with the Elm mail
X program. It allows the user to save articles/threads/groups
X simply by giving '=' as the filename to save to.
X
X PPrriinntteerr
X The printer program with options that is to be used to print
X articles. Default is lpr for BSD machines and lp for SysV
X machines.
X
KKIILLLL AARRTTIICCLLEE MMEENNUU
X This menu is accessed by pressing '^K' at the group and page
X levels. It allows the user to kill an article that matches the
X current Subject: line, From: line or a string entered by the user.
X The user entered string can be applied to the Subject: or From:
X lines of an article. The kill description can be limited to the
X current newsgroup or it can apply to all newsgroups. Once entered
X the user can abort the command and not save the kill description,
X edit the kill file or save the kill description.
X
X On starting tin the users killfile $_H_O_M_E/._t_i_n/_k_i_l_l is read and on
X entering a newsgroup any kill descriptions are applied. Articles
X that match a kill description are marked killed and are not
X displayed.
X
X The 'Kill articles' option needs to be set ON in the Options Menu
X (selected by 'M' at any level) to activate this command.
X
PPOOSSTTIINNGG AARRTTIICCLLEESS
X Tin allows posting of articles, follow-up to already posted
X articles and replying direct through mail to the author of an
X article.
X
X Use the 'w' command to post an article to a newsgroup. After
X entering the post subject the default editor (ie. vi) or the editor
X specified by the $VISUAL environment variable will be started and
X the article can be entered. To crosspost articles simply add a
X comma and the name of the newsgroup(s) to the end of the
X Newsgroups: line at the beginning of the article. After saving and
X
X
X
X
NEWS-OS Release 4.1R 13
X
X
X
X
X
TIN(1) LOCAL TIN(1)
X
X
X
X exiting the editor you are asked if you wish to a)bort posting the
X article, e)dit the article again or p)ost the article to the
X specified newsgroup(s).
X
X Use the 'W' command to display a history of the articles you have
X posted. The date the article was posted, which newsgroups the
X article was posted to and the articles subject line are displayed.
X
X Use the 'f' / 'F' command to post a follow-up article to an already
X posted article. The 'F' command will copy the text of the original
X article into the editor. The editing procedure is the same as when
X posting an article with the 'w' command.
X
X Use the 'r' / 'R' command to reply direct through mail to the
X author of an already posted article. The 'R' command will copy the
X text of the original article into the editor. The editing procedure
X is the same as when posting an article with the 'w' command. After
X saving and exiting the editor you are asked if you wish to a)bort
X sending the article, e)dit the article again or s)end the article
X to the author.
X
MMAAIILLIINNGG PPIIPPIINNGG PPRRIINNTTIINNGG AANNDD SSAAVVIINNGG AARRTTIICCLLEESS
X The command interface to mail ('m'), pipe ('|'), print ('o') and
X save ('s') articles is the same for ease of use.
X
X The initial command will ask you to select which a)rticle, t)hread,
X r)egex pattern, t)agged articles you wish to mail, pipe etc.
X
X Tagged articles must have already been tagged with the 'T' command.
X All tagged articles can be untagged by the 'U' untag command.
X
X If regex pattern matching is selected you are asked to enter a
X regular expression (ie. to match all articles subject lines
X containing 'net News' you must enter '*net News*'). Any articles
X that match the entered expression will be mailed, piped etc.
X
X To save articles to a mailbox with the name of the current
X newsgroup (ie. Alt.sources) enter '=' or '=<mailbox name>' when
X asked for the save filename.
X
X To save articles in <newsgroup name>/<filename> format enter
X '+<filename>'.
X
X When saving articles you can specify whether the saved files should
X be post processed (ie. unshar shell archive, uudecode multiple
X parts etc). A default process type can be set by the 'Process
X type:' in the 'M' options menu.
X
AAUUTTOOMMAATTIICC MMAAIILLIINNGG AANNDD SSAAVVIINNGG NNEEWW NNEEWWSS
X Tin allows new/unread news articles to be mailed (-M option)/saved
X (-S option) in batch mode for later reading. Useful when going on
X holiday and you don't want to return and find that expire has
X
X
X
X
14 Release 4.1R NEWS-OS
X
X
X
X
X
TIN(1) LOCAL TIN(1)
X
X
X
X removed a whole load of unread articles. Best to run from crontab
X everyday while away, after which you will be mailed a report of
X which articles were mailed/saved from which newsgroups and the
X total number of articles mailed/saved. Articles are saved in a
X private news structure under your <savedir> directory (default is
X $_H_O_M_E/_N_e_w_s). Be careful of using this option if you read a lot of
X groups because you could overflow your filesystem. If you only want
X to save a few groups it would be best to backup your full
X $_H_O_M_E/._n_e_w_s_r_c and create a new one that only contains the
X newsgroups you want to mail/save. Saved news can be read later by
X starting tin with the -R option.
X
X tin -M iain -f newsrc.mail (mail any unread articles in newgroups
X specified in file newsrc.mail)
X
X tin -S -f newsrc.save (save any unread articles in newgroups
X specified in file newsrc.save)
X
X tin -R (read any unread articles saved by tin -S option)
X
SSIIGGNNAATTUURREESS
X Tin will recognize a signature in either $_H_O_M_E/._s_i_g_n_a_t_u_r_e or
X $_H_O_M_E/._S_i_g. If $_H_O_M_E/._s_i_g_n_a_t_u_r_e exists, then the signature will be
X pulled into the editor for Tin mail commands. A signature in
X $_H_O_M_E/._s_i_g_n_a_t_u_r_e will not be pulled into the editor for posting
X commands since the inews program will append the signature itself.
X
X A signature in $_H_O_M_E/._S_i_g will be pulled into the editor for both
X posting and mailing commands.
X
X The following is an example of a $_H_O_M_E/._S_i_g file:
X NAME Iain Lea
X EMAIL iain%anl433.uucp@germany.eu.net
X SNAIL Bruecken Strasse 12, 8500 Nuernberg 90, Germany
X PHONE +49-911-331963 (home) +49-911-3089-407 (work)
X
EENNVVIIRROOMMEENNTT VVAARRIIAABBLLEESS
X TTIINNDDIIRR
X Define this variable if you do not want tin's .tin directory
X in $HOME/.tin. (ie. if you want all tin's private files in
X /tmp/.tin you would set TINDIR to contain /tmp.
X
X NNNNTTPPSSEERRVVEERR
X The default NNTP server to remotely read news from. This
X variable only needs to be set if the -r command line option is
X specified and the file /_e_t_c/_n_n_t_p_s_e_r_v_e_r does not exist.
X
X OORRGGAANNIIZZAATTIIOONN
X Set the mail header field Organization: to the contents of the
X variable instead of the system default. This variable has
X precedence over the file $_H_O_M_E/._t_i_n/_o_r_g_a_n_i_z_a_t_i_o_n that may also
X contain an organization string.
X
X
X
X
NEWS-OS Release 4.1R 15
X
X
X
X
X
TIN(1) LOCAL TIN(1)
X
X
X
X RREEPPLLYYTTOO
X Set the mail header field Reply-To: to the return address
X specified by the variable. This is useful if the machine is
X not registered in the UUCP mail maps or if you wish to recieve
X replies at a different machine. This variable has precedence
X over the file $_H_O_M_E/._t_i_n/_r_e_p_l_y_t_o that may also contain a
X return address.
X
X AADDDD_AADDDDRREESSSS
X This can contain an address to append to the return address
X when replying directly through mail to somebody whose mail
X address is not directly recognized by the local host. For
X example say the return address is _u_s_e_r@_b_i_g_v_a_x, but _b_i_g_v_a_x is
X not recognized by your host, so therfore the mail will not
X reach _u_s_e_r. But the host _l_i_t_t_e_v_a_x is known to recognize your
X host and _b_i_g_v_a_x, so if ADD_ADDRESS is set (ie. 'setenv
X ADD_ADDRESS @littevax' for csh or 'set ADD_ADDRESS @littevax'
X and 'export ADD_ADDRESS' for sh) the address
X _u_s_e_r@_b_i_g_v_a_x@_l_i_t_t_l_e_v_a_x will be used and the mail will reach
X _u_s_e_r@_b_i_g_v_a_x. This variable has precedence over the file
X $_H_O_M_E/._t_i_n/_a_d_d__a_d_d_r_e_s_s that may also contain an address.
X
X BBUUGG_AADDDDRREESSSS
X If the 'B' command bug report mail address is not correct this
X variable should be set to the correct mail address. This
X variable has precedence over the file $_H_O_M_E/._t_i_n/_b_u_g__a_d_d_r_e_s_s
X that may also contain a mail address.
X
X VVIISSUUAALL
X This variable has precedence over the default editor (ie. vi)
X that is used in all editing operations within tin (ie. posting
X 'w', replying 'rR', follow-ups 'fF' and bug reports 'B').
X
TTIIPPSS AANNDD TTRRIICCKKSS
X The following newsgroups provide useful information concerning news
X software:
X -news.software.readers (info. about news user agents
X tin,rn,nn,vn etc.)
X -news.software.nntp (info. about NNTP)
X -news.software.b (info. about news transport agents Bnews &
X Cnews)
X
X Many prompts (ie. 'Mark everything as read? (y/n): y') within tin
X offer a default choice that the cursor is positioned on. By
X pressing <CR> the default value is taken.
X
X When tin is run in an xterm window it will resize itself each time
X the xterm is resized.
X
X Tin will reread the active file at set intervals to show any new
X news.
X
X
X
X
X
16 Release 4.1R NEWS-OS
X
X
X
X
X
TIN(1) LOCAL TIN(1)
X
X
X
FFIILLEESS
X $_H_O_M_E/._n_e_w_s_r_c subscribed to newgroups.
X $_H_O_M_E/._t_i_n/_t_i_n_r_c options.
X $_H_O_M_E/._t_i_n/._i_n_d_e_x newsgroup index files directory.
X $_H_O_M_E/._t_i_n/_a_d_d__a_d_d_r_e_s_s address to add to when replying through mail.
X $_H_O_M_E/._t_i_n/_a_c_t_i_v_e used by -n option for notifying user of new groups.
X $_H_O_M_E/._t_i_n/_b_u_g__a_d_d_r_e_s_s address to send bug reports to.
X $_H_O_M_E/._t_i_n/_k_i_l_l kill file.
X $_H_O_M_E/._t_i_n/_o_r_g_a_n_i_z_a_t_i_o_n string to replace default organization.
X $_H_O_M_E/._t_i_n/_p_o_s_t_e_d history of articles posted by user.
X $_H_O_M_E/._t_i_n/_r_e_p_l_y_t_o host address to use in Reply-To: mail header.
X $_H_O_M_E/._t_i_n/_u_n_t_h_r_e_a_d contains groups that are not to be threaded.
X $_H_O_M_E/._s_i_g_n_a_t_u_r_e signature.
X $_H_O_M_E/._S_i_g signature.
X
BBUUGGSS
X There are bugs somewhere among the creeping featurism. Any bugs
X found should be reported by the 'B' (bug report) command.
X
X There is a bug when article killing is switched ON/OFF at article
X page level and the 't' command is used to return to group selection
X index.
X
X When articles have been unkilled, all articles will be marked
X unread even if they have already been read.
X
X Killing articles when tin is setuid causes strange behaviour.
X
X Will not uudecode some of the images in alt.binaries.pictures
X because more than one image is in the multi-part file to uudecode.
X Only the first image will be uudecoded.
X
X Does not yet handle Xref: headers for cross-posted articles.
X
HHIISSTTOORRYY
X Based on the tass newsreader that was developed by Rich Skrenta and
X posted to alt.sources in March 1991. Tass was itself heavily
X infleuenced by NOTES which was developed at the University of
X Illinois in the early 1980's.
X
X Tin v1.00 (full distribution) was posted in 8 parts to alt.sources
X on 23 Aug 1991.
X Tin v1.0 PL1 (full distribution) was posted in 8 parts to
X alt.sources on 03 Sep 1991.
X Tin v1.0 PL2 (full distribution) was posted in 9 parts to
X alt.sources on 24 Sep 1991.
X Tin v1.0 PL3 (patch) was posted in 4 parts to alt.sources on 30 Sep
X 1991.
X Tin v1.0 PL4 (patch) was posted in 2 parts to alt.sources on 02 Oct
X 1991.
X Tin v1.0 PL5 (patch) was posted in 4 parts to alt.sources on 17 Oct
X 1991.
X
X
X
X
NEWS-OS Release 4.1R 17
X
X
X
X
X
TIN(1) LOCAL TIN(1)
X
X
X
X Tin v1.0 PL6 (patch) was posted in 5 parts to alt.sources on 27 Nov
X 1991.
X Tin v1.0 PL7 (patch) was posted in 2 parts to alt.sources on 27 Nov
X 1991.
X Tin v1.1 PL0 (full distribution) was posted in 11 parts to
X alt.sources on 13 Feb 1992.
X Tin v1.1 PL1 (full distribution) was posted in 12 parts to
X alt.sources on 24 Mar 1992.
X
CCRREEDDIITTSS
X Rich Skrenta
X author of tass v3.2 which this newsreader used as its base.
X
X Dave Taylor
X author of curses.c from the elm mailreader.
X
X Rich Salz
X author of wildmat.c pattern matching routine.
X
X Chris Thewalt
X author of getline.c emacs style editing routine.
X
X Dieter Becker
X for generously posting certain versions and patches for me
X when my net connection was removed by a group of very short
X sighted people.
X
X I wish to thank the following people for supplying patchs:
X
X Anton Aylward, Dieter Becker, Dan Berry, Marc Boucher, Robert
X Claeson, Steven Cogswell, Ned Danieley, Brent Ermlick, Carl Hage,
X Ed Hanway, Torsten Homeyer, Nelson Kading, Fritz Kleeman, Karl-
X Koenig Koenigsson, Kris Kugel, Hakan Lennestal, Clifford Luke,
X Michael Faurot, David MacKenzie, Bill Poitras, Jim Robinson,
X Nickolay Saukh, Rich Salz, John Sauter, Bart Sears, Karl-Olav
X Serrander, Doug Sewell, Cliff Stanford, Adri Verhoef, Cary Whitney
X
X I wish to thank the following people for bug reports/comments:
X
X Klaus Arzig, Scott Babb, Reiner Balling, Volker Beyer, Roger Binns,
X Georg Biehler, Ian Brown, Andreas Brosig, Leila Burrell-Davis, Tom
X Czarnik, David Donovan, Peter Dressler, Gerhard Ermer, Hugh Fader,
X Joachim Feld, Paul Fox, Bernhard Gmelch, Viet Hoang, Andy Jackson,
X Joe Johnson, Cyrill Jung, Hans-Juergen Knopp, Per Lindqvist, Bob
X Lukas, Phillip Molloy, Toni Metz, Greg Miller, Klaus Neuberger,
X Otto Niesser, Reiner Oelhaf, Wolf Paul, John Palkovic, Andrew
X Phillips, Ted Richards, Fredy Schwatz, Bernd Schwerin, Klamer
X Schutte, Chris Smith, Daniel Smith, Steve Spearman, Hironobu
X Takahashi, Sven Werner
X
AAUUTTHHOORR
X Iain Lea
X
X
X
X
18 Release 4.1R NEWS-OS
X
X
X
X
X
TIN(1) LOCAL TIN(1)
X
X
X
X (iain%anl433.uucp@germany.eu.net)
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
NEWS-OS Release 4.1R 19
X
X
SHAR_EOF
echo 'File tin.nrf is complete' &&
chmod 0600 tin.nrf ||
echo 'restore of tin.nrf failed'
Wc_c="`wc -c < 'tin.nrf'`"
test 44431 -eq "$Wc_c" ||
echo 'tin.nrf: original size 44431, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= active.c ==============
if test -f 'active.c' -a X"$1" != X"-c"; then
echo 'x - skipping active.c (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting active.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'active.c' &&
/*
X * Project : tin - a threaded Netnews reader
X * Module : active.c
X * Author : I.Lea
X * Created : 16-02-92
X * Updated : 01-03-92
X * Notes :
X * Copyright : (c) Copyright 1991-92 by 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
#include "tin.h"
X
int group_hash[TABLE_SIZE]; /* group name --> active[] */
int reread_active_file = FALSE;
X
X
int test_reread = 0;
X
X
/*
X * Resync active file when SIGALRM signal reeived that
X * is triggered by alarm (RESYNC_ACTIVE_SECS) call.
X */
X
void resync_active_file ()
{
#ifndef NO_RESYNC_ACTIVE_FILE
X if (reread_active_file) {
X wait_message (txt_reading_active_file);
X free_active_arrays ();
X max_active = DEFAULT_ACTIVE_NUM;
X expand_active ();
X read_active_file ();
X read_newsrc (TRUE);
X reread_active_file = FALSE;
X alarm (RESYNC_ACTIVE_SECS); /* reset alarm clock */
X group_selection_page ();
X test_reread++;
X }
#endif
}
X
/*
X * Load the active file into active[] and create copy of active ~/.tin/active
X */
X
int read_active_file ()
{
X FILE *fp;
X char *p, *q, *r;
X char buf[LEN];
X char moderated;
X int created, i;
X long h;
X
X num_active = 0;
X
X if ((fp = open_active_fp ()) == NULL) {
X if (compiled_with_nntp) {
X sprintf (msg, txt_cannot_open_active_file, active_file, progname);
X wait_message (msg);
X } else {
X printf (txt_cannot_open, active_file);
X putchar ('\n');
X fflush (stdout);
X }
X exit (1);
X }
X
X if (reread_active_file == FALSE && (read_news_via_nntp && update == FALSE)) {
X wait_message (txt_reading_active_file);
X }
X
X for (i = 0; i < TABLE_SIZE; i++) {
X group_hash[i] = -1;
X }
X
X while (fgets (buf, sizeof (buf), fp) != NULL) {
X for (p = buf; *p && *p != ' '; p++)
X continue;
X if (*p != ' ') {
X error_message (txt_bad_active_file, buf);
X continue;
X }
X *p++ = '\0';
X
X if (num_active >= max_active) {
X expand_active ();
X }
X
X h = hash_groupname (buf);
X
X if (group_hash[h] == -1) {
X group_hash[h] = num_active;
X } else { /* hash linked list chaining */
X for (i=group_hash[h]; active[i].next >= 0; i=active[i].next) {
X if (strcmp(active[i].name, buf) == 0) {
X goto read_active_continue; /* kill dups */
X }
X }
X if (strcmp(active[i].name, buf) == 0)
X goto read_active_continue;
X active[i].next = num_active;
X }
X
X for (q = p; *q && *q != ' '; q++)
X continue;
X if (*q != ' ') {
X error_message (txt_bad_active_file, buf);
X continue;
X }
X *q++ = '\0';
X
X for (r = q; *r && *r != '\n'; r++) {
X if (*r == 'y' || *r == 'm') {
X moderated = *r;
X break;
X }
X }
X
X active[num_active].name = str_dup (buf);
X active[num_active].max = (long) atol (p);
X active[num_active].min = (long) atol (q);
X active[num_active].moderated = moderated;
X active[num_active].next = -1; /* hash chaining */
X active[num_active].flag = UNSUBSCRIBED; /* not in my_group[] yet */
X active[num_active].read = FALSE; /* read/unread */
X active[num_active].thread = TRUE; /* thread articles */
X
X num_active++;
X
read_active_continue:;
X
X }
X fclose (fp);
X
X /*
X * exit if active file is empty
X */
X if (! num_active) {
X error_message (txt_active_file_is_empty, active_file);
X exit (1);
X }
X
X /*
X * create backup of LIBDIR/active for use by -n option to notify new groups
X */
X created = backup_active (TRUE);
X
X debug_print_active ();
X
X if (cmd_line || (read_news_via_nntp && update == FALSE)) {
X wait_message ("\n");
X }
X
X return (created);
}
X
/*
X * create ~/.tin/active from LIBDIR/active if it does not exist
X */
X
int backup_active (create)
X int create;
{
X char buf[LEN];
X FILE *fp;
X int created = FALSE;
X int i;
X struct stat sb;
X
X set_real_uid_gid ();
X
X sprintf (buf, "%s/active", rcdir);
X
X if (create) {
X if (stat (buf, &sb) != -1) {
X goto backup_active_done;
X }
X }
X
X if ((fp = fopen (buf, "w")) != NULL) {
X for (i = 0; i < num_active ; i++) { /* for each group */
X fprintf (fp, "%s\n", active[i].name);
X }
X fclose (fp);
X chmod (buf, 0644);
X created = TRUE;
X }
X
backup_active_done:
X set_tin_uid_gid ();
X return (created);
}
X
/*
X * Option -n to check for any newly created newsgroups.
X */
X
#if 0 /* MY VERSION IAIN LEA */
void notify_groups ()
{
X char buf[LEN];
X FILE *fp;
X int group_not_found;
X int i, j, index;
X int num = 0;
X int update_old_active = FALSE;
X struct notify_t {
X char name[LEN];
X int len;
X } *old_active;
X
X set_real_uid_gid ();
X
X sprintf (buf, "%s/active", rcdir);
X
X if ((fp = fopen (buf, "r")) == NULL) {
X error_message (txt_cannot_open, buf);
X goto notify_groups_done;
X }
X
X Raw (FALSE);
X
X wait_message (txt_checking_active_file);
X
X old_active = (struct notify_t *) my_malloc ((unsigned) sizeof (struct notify_t) * num_active);
X if (old_active == (struct notify_t *) 0) {
X error_message (txt_out_of_memory, progname);
X goto notify_groups_done;
X }
X
X while (fgets (old_active[num].name, sizeof (old_active[num].name), fp) != NULL) {
X old_active[num].len = strlen (old_active[num].name)-1;
X old_active[num].name[old_active[num].len] = '\0';
X num++;
X if (num == num_active) {
X break;
X }
X }
X
X for (i = 0 ; i < num_active ; i++) {
X group_not_found = TRUE;
X for (j=0; j < num ; j++) {
X if (strncmp (old_active[j].name, active[i].name, old_active[j].len) == 0) {
X group_not_found = FALSE; /* found it so read in next group */
X break;
X }
X }
X
X if (group_not_found) {
X update_old_active = TRUE;
X sprintf (msg, txt_subscribe_to_new_group, active[i].name);
X wait_message (msg);
X scanf ("%s", buf);
X if (buf[0] == 'y') {
X index = add_group (active[i].name, TRUE);
X subscribe (active[my_group[index]].name, ':',
X my_group[index], FALSE);
X }
X wait_message (txt_checking);
X }
X }
X fclose (fp);
X
X if (old_active != (struct notify_t *) 0) {
X free ((char *) old_active);
X old_active = (struct notify_t *) 0;
X }
X
X Raw (TRUE);
X
X /*
X * write active[] to ~/.tin/active
X */
X if (update_old_active) {
X backup_active (FALSE);
X }
X
notify_groups_done:
X set_tin_uid_gid ();
}
X
#endif
X
void notify_groups ()
{
X char buf[LEN];
X FILE *fp;
X int group_not_found;
X int i, j, index;
X int num = 0;
X int update_old_active = FALSE;
X int max_old_active;
X struct notify_t {
X char name[LEN];
X int len;
X int visited;
X } *old_active;
X
X set_real_uid_gid ();
X
X sprintf (buf, "%s/active", rcdir);
X
X if ((fp = fopen (buf, "r")) == NULL) {
X error_message (txt_cannot_open, buf);
X goto notify_groups_done;
X }
X
X Raw (FALSE);
X
X wait_message (txt_checking_active_file);
X
X max_old_active = num_active;
X
X old_active = (struct notify_t *) my_malloc ((unsigned) sizeof (struct notify_t) * max_old_active);
X if (old_active == (struct notify_t *) 0) {
X error_message (txt_out_of_memory, progname);
X goto notify_groups_done;
X }
X
X while (fgets (old_active[num].name, sizeof (old_active[num].name), fp) != NULL) {
X old_active[num].len = strlen (old_active[num].name)-1;
X old_active[num].name[old_active[num].len] = '\0';
X old_active[num].visited = FALSE;
X num++;
X if (num >= max_old_active) {
X max_old_active= max_old_active + (max_old_active / 2);
X old_active= (struct notify_t*) my_realloc(
X (struct notify_t*) old_active,
X (unsigned) sizeof(struct notify_t) * max_old_active);
X if (old_active == (struct notify_t *) 0) {
X error_message (txt_out_of_memory, progname);
X goto notify_groups_done;
X }
X }
X }
X
X for (i = 0 ; i < num_active ; i++) {
X group_not_found = TRUE;
X for (j=0; j < num ; j++) {
X if (strcmp (old_active[j].name, active[i].name) == 0) {
X group_not_found = FALSE; /* found it so read in next group */
X old_active[j].visited = TRUE;
X break;
X }
X }
X
X if (group_not_found) {
X update_old_active = TRUE;
X printf ("\r\nSubscribe to %s (y/n): ", active[i].name);
X fflush (stdout);
X scanf ("%s", buf);
X if (buf[0] == 'y') {
X index = add_group (active[i].name, TRUE);
X subscribe (active[my_group[index]].name, ':',
X my_group[index], FALSE);
X }
X printf ("Checking...");
X fflush (stdout);
X }
X }
X fclose (fp);
X
X /*
X * Look for bogus groups
X */
X for (j = 0 ; j < num ; j++) {
X if (! old_active[j].visited) {
X update_old_active= 1;
X printf ("\nRemove bogus group %s (y/n): ", old_active[j].name);
X fflush (stdout);
X scanf ("%s", buf);
X if (buf[0] == 'y')
X delete_group (old_active[j].name);
X }
X }
X
X if (old_active != (struct notify_t *) 0) {
X free ((char *) old_active);
X old_active = (struct notify_t *) 0;
X }
X
X Raw (TRUE);
X
X /*
X * write active[] to ~/.tin/active
X */
X if (update_old_active) {
X backup_active (FALSE);
X }
X
notify_groups_done:
X set_tin_uid_gid ();
}
SHAR_EOF
chmod 0600 active.c ||
echo 'restore of active.c failed'
Wc_c="`wc -c < 'active.c'`"
test 8707 -eq "$Wc_c" ||
echo 'active.c: original size 8707, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= art.c ==============
if test -f 'art.c' -a X"$1" != X"-c"; then
echo 'x - skipping art.c (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting art.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'art.c' &&
/*
X * Project : tin - a threaded Netnews reader
X * Module : art.c
X * Author : I.Lea & R.Skrenta
X * Created : 01-04-91
X * Updated : 21-03-92
X * Notes :
X * Copyright : (c) Copyright 1991-92 by Iain Lea & Rich Skrenta
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
#include "tin.h"
X
char index_file[LEN];
char *glob_art_group;
int index_file_killed = FALSE;
long last_read_article;
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
void find_base (only_unread)
X int only_unread;
{
X register int i;
X register int j;
X
X top_base = 0;
X
X debug_print_arts ();
X
X if (only_unread) {
X for (i = 0; i < top; i++) {
X if (arts[i].thread != ART_EXPIRED && arts[i].inthread == FALSE) {
X if (top_base >= max_art) {
X expand_art ();
X }
X if (arts[i].unread == ART_UNREAD) {
X base[top_base++] = i;
X } else {
X for (j = i ; j >= 0 ; j = arts[j].thread) {
X if (arts[j].unread) {
X base[top_base++] = i;
X break;
X }
X }
X }
X }
X }
X } else {
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 }
X base[top_base++] = i;
X }
X }
X }
}
X
/*
X * Count the number of non-expired and non-killed articles in arts[]
X */
X
int num_of_arts ()
{
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].killed == FALSE) {
X sum++;
X }
X }
X
X return sum;
}
X
/*
X * Do we have an entry for article art?
X */
X
int valid_artnum (art)
X long art;
{
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 * 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
int purge_needed ()
{
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 * 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
void index_group (group, group_path)
X char *group;
X char *group_path;
{
X int killed = FALSE;
X int modified = FALSE;
X glob_art_group = group;
X
X set_signals_art ();
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 /*
X * load articles from index file if it exists
X */
X load_index_file (group);
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 set_real_uid_gid (); /* so become them */
X }
X
X if (killed) {
X reload_index_file (group, killed);
X } else {
X dump_index_file (group, FALSE);
X read_newsrc_line (group);
X make_threads (FALSE);
X find_base (show_only_unread);
X }
X
X if (local_index) {
X set_tin_uid_gid ();
X }
X } else {
X read_newsrc_line (group);
X make_threads (FALSE);
X find_base (show_only_unread);
X }
X
X if ((modified || killed) && ! update) {
X clear_message ();
X }
}
X
/*
X * Index a group. Assumes any existing index has already been
X * loaded.
X */
X
int read_group (group, group_path)
X char *group;
X char *group_path;
{
X int fd;
X long art;
X int count = 0;
X int modified = FALSE;
X int respnum;
X register int i;
X
X setup_base (group, group_path); /* load article numbers into base[] */
X
X for (i = 0; i < top_base; i++) { /* for each article # */
X art = base[i];
X
/*
X * Do we already have this article in our index? Change thread from
X * (ART_EXPIRED) to (ART_NORMAL) if so and skip the header eating.
X */
X
X if ((respnum = valid_artnum (art)) >= 0 || art <= last_read_article) {
X if (respnum >= 0) {
X arts[respnum].thread = ART_NORMAL;
X arts[respnum].unread = ART_UNREAD;
X }
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 % MODULO_COUNT_NUM == 0 && ! update) {
#ifndef SLOW_SCREEN_UPDATE
X sprintf (msg, txt_indexing_num, group, count);
#else
X sprintf (msg, txt_indexing, group);
#endif
X wait_message (msg);
X }
X }
X
X return modified;
}
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
void make_threads (rethread)
X int rethread;
{
X extern int cur_groupnum;
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 && active[my_group[cur_groupnum]].thread) {
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_NOTHING: /* don't sort at all */
X qsort ((char *) arts, top, sizeof (struct article_t), artnum_comp);
X break;
X case SORT_BY_SUBJ_DESCEND:
X case SORT_BY_SUBJ_ASCEND:
X qsort ((char *) arts, top, sizeof (struct article_t), subj_comp);
X break;
X case SORT_BY_FROM_DESCEND:
X case SORT_BY_FROM_ASCEND:
X qsort ((char *) arts, top, sizeof (struct article_t), from_comp);
X break;
X case SORT_BY_DATE_DESCEND:
X case SORT_BY_DATE_ASCEND:
X qsort ((char *) arts, top, sizeof (struct article_t), date_comp);
X break;
X default:
X break;
X }
X
X if (thread_arts && active[my_group[cur_groupnum]].thread) {
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
int parse_headers (fd, h)
X int fd;
X struct article_t *h;
{
X char buf[HEADER_LEN];
X char buf2[HEADER_LEN];
X char art_from_addr[LEN];
X char art_full_name[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
X buf[n-1] = '\0';
X
X ptr = buf;
X
X while (1) {
X for (ptrline = ptr; *ptr && *ptr != '\n'; ptr++) {
X if (((*ptr) & 0xFF) < ' ') {
X *ptr = ' ';
X }
X }
X flag = *ptr;
X *ptr++ = '\0';
X lineno++;
X
X if (! got_from && match_header (ptrline, "From", buf2, HEADER_LEN)) {
X parse_from (buf2, art_from_addr, art_full_name);
X h->from = hash_str (art_from_addr);
X h->name = hash_str (art_full_name);
X got_from = TRUE;
X } else if (! got_subject && match_header (ptrline, "Subject", buf2, HEADER_LEN)) {
X s = eat_re (buf2);
X h->subject = hash_str (eat_re (s));
X got_subject = TRUE;
X } else if (! got_date && match_header (ptrline, "Date", buf2, HEADER_LEN)) {
X parse_date (buf2, h->date);
X got_date = TRUE;
X } else if (match_header (ptrline, "Archive-name", buf2, HEADER_LEN) ||
X match_header (ptrline, "Archive-Name", buf2, HEADER_LEN)) {
X if ((s = (char *) strchr (buf2, '/')) != NULL) {
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 /* NOTREACHED */
}
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
void dump_index_file (group, killed)
X char *group;
X int killed;
{
X char nam[LEN];
X FILE *fp;
X int *iptr;
X int realnum;
X register int i;
X
X sprintf (nam, "%s.%d", index_file, process_id);
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_NOTHING) {
X qsort ((char *) arts, top, sizeof (struct article_t), artnum_comp);
X }
X fprintf (fp, "%s\n", group);
X fprintf (fp, "%d\n", num_of_arts ());
X if (top <= 0) {
X fprintf (fp, "0\n");
X } else {
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 }
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].killed == FALSE) {
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 } 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 } else if (killed || *iptr == i) {
X fprintf(fp, " %s\n", arts[i].from);
X } else {
X fprintf(fp, "%%%d\n", *iptr);
X }
X
X iptr = (int *) arts[i].name;
X iptr--;
X
X if (! arts[i].name) {
X fprintf (fp, " \n");
X } else if (*iptr < 0 || *iptr > top) {
X fprintf (fp, " %s\n", arts[i].name);
X *iptr = realnum;
X } else if (killed || *iptr == i) {
X fprintf(fp, " %s\n", arts[i].name);
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 } else if (arts[i].part || arts[i].patch) {
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 == 2) {
X sprintf (msg, "cp %s INDEX", index_file);
X system (msg);
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 *
X * index file record
X * 1. article number (ie. 183) [mandatory]
X * 2. Subject: line (ie. Which newsreader?) [mandatory]
X * 3. From: line (addr) (ie. iain@norisc) [mandatory]
X * 4. From: line (name) (ie. Iain Lea) [mandatory]
X * 5. Date: of posting (ie. 911231125959) [mandatory]
X * 6. Archive: name (ie. compiler) [optional]
X * 7. Part number of Archive: name (ie. 01) [optional]
X * 8. Patch number of Archive: name (ie. 01) [optional]
X */
X
int load_index_file (group_name)
X char *group_name;
{
X int error = 0;
X int i, n;
X char buf[LEN], *p;
X FILE *fp;
X
X top = 0;
X last_read_article = 0L;
X
X if ((fp = open_index_fp (group_name)) == NULL) {
X return FALSE;
X }
X
X /*
X * load header - discard group name, num. of arts in index file after any arts were killed
X */
X if (fgets(buf, sizeof buf, fp) == NULL ||
X fgets(buf, sizeof buf, 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, sizeof buf, fp) == NULL) {
X error = 1;
X goto corrupt_index;
X }
X last_read_article = (long) atol (buf);
X
X /*
X * is index file complete or were articles killed when it was dumped
X */
X if (fgets(buf, sizeof buf, 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, sizeof buf, fp) == NULL) {
X error = 3;
X goto corrupt_index;
X }
X arts[top].artnum = (long) atol (buf);
X
X /*
X * Subject:
X */
X if (fgets(buf, sizeof buf, 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 continue;
X *p = '\0';
X arts[top].subject = hash_str (&buf[1]);
X } else {
X error = 6;
X goto corrupt_index;
X }
X
X /*
X * From: (addr part)
X */
X if (fgets(buf, sizeof buf, 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 continue;
X *p = '\0';
X arts[top].from = hash_str (&buf[1]);
X } else {
X error = 9;
X goto corrupt_index;
X }
X
X /*
X * From: (full name)
X */
X if (fgets(buf, sizeof buf, fp) == NULL) {
X error = 10;
X goto corrupt_index;
X }
X
X if (buf[0] == '%') {
X n = atoi (&buf[1]);
X if (n > top || n < 0) {
X error = 11;
X goto corrupt_index;
X }
X if (n == top) { /* no full name so .name = .from */
X arts[top].name = arts[top].from;
X } else {
X arts[top].name = arts[n].name;
X }
X } else if (buf[0] == ' ') {
X for (p = &buf[1]; *p && *p != '\n'; p++)
X continue;
X *p = '\0';
X arts[top].name = hash_str (&buf[1]);
SHAR_EOF
true || echo 'restore of art.c failed'
fi
echo 'End of tin1.1 part 3'
echo 'File art.c is continued in part 4'
echo 4 > _shar_seq_.tmp
exit 0
--
NAME Iain Lea
EMAIL iain%anl433.uucp@germany.eu.net
SNAIL Siemens AG, ANL A433SZ, Gruendlacher Str. 248, 8510 Fuerth, Germany.
PHONE +49-911-3089-407 (work) +49-911-331963 (home) +49-911-3089-290 (FAX)
--
Dr. med. dipl.-math Dieter Becker Tel.: (0 / +49) 6841 - 16 3046
Medizinische Universitaets- und Poliklinik Fax.: (0 / +49) 6841 - 16 3369
Innere Medizin III
D - 6650 Homburg / Saar Email: becker@med-in.uni-sb.de
exit 0 # Just in case...