home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 January
/
usenetsourcesnewsgroupsinfomagicjanuary1994.iso
/
sources
/
misc
/
volume28
/
tin
/
part03
< prev
next >
Wrap
Text File
|
1992-02-23
|
52KB
|
2,173 lines
Newsgroups: comp.sources.misc
From: iain%estevax.uucp@unido.Informatik.Uni-Dortmund.DE (Iain Lea)
Subject: v28i047: tin - threaded full screen newsreader v1.1, Part03/11
Message-ID: <1992Feb18.043612.12785@sparky.imd.sterling.com>
X-Md4-Signature: f37955312af61c11d30fcf35556b4a19
Date: Tue, 18 Feb 1992 04:36:12 GMT
Approved: kent@sparky.imd.sterling.com
Submitted-by: iain%estevax.uucp@unido.Informatik.Uni-Dortmund.DE (Iain Lea)
Posting-number: Volume 28, Issue 47
Archive-name: tin/part03
Environment: BSD, SCO, ISC, SUNOS, SYSVR3, SYSVR4, ULTRIX, XENIX
Supersedes: tin: Volume 23, Issue 15-23
#!/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 tevax' for csh or 'set ADD_ADDRESS @littevax' and
X '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
X reach _u_s_e_r@_b_i_g_v_a_x. This variable has precedence over
X the file $_H_O_M_E/._t_i_n/_a_d_d__a_d_d_r_e_s_s that may also contain
X
X
X
X
NEWS-OS Release 4.1R 15
X
X
X
X
X
TIN(1) NEWS-OS Programmer's Manual TIN(1)
X
X
X
X an address.
X
X BBUUGG_AADDDDRREESSSS
X If the 'B' command bug report mail address is not
X correct this variable should be set to the correct mail
X address. This variable has precedence over the file
X $_H_O_M_E/._t_i_n/_b_u_g__a_d_d_r_e_s_s that may also contain a mail
X address.
X
X EEDDIITTOORR
X This variable has precedence over the default editor
X (ie. vi) that is used in all editing operations within
X tin (ie. posting 'w', replying 'rR', follow-ups 'fF'
X and bug reports 'B').
X
TTIIPPSS AANNDD TTRRIICCKKSS
X The following newsgroups provide useful information concern-
X ing news 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
X Bnews & Cnews)
X
X Many prompts (ie. 'Mark everything as read? (y/n): y')
X within tin offer a default choice that the cursor is posi-
X tioned on. By pressing <CR> the default value is taken.
X
X When tin is run in an xterm window it will resize itself
X each time the xterm is resized.
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
X bugs found should be reported by the 'B' (bug report) com-
X mand.
X
X
X
X
X
X
16 Release 4.1R NEWS-OS
X
X
X
X
X
TIN(1) NEWS-OS Programmer's Manual TIN(1)
X
X
X
X There is a bug when article killing is switched ON/OFF at
X article page level and the 't' command is used to return to
X group selection index.
X
X When articles have been unkilled, all articles will be
X marked unread even if they have already been read.
X
X Killing articles when tin is setuid causes strange
X behaviour.
X
X Will not uudecode some of the images in
X alt.binaries.pictures because more than one image is in the
X multi-part file to uudecode. Only the first image will be
X uudecoded.
X
X Does not handle Xref: headers for cross-posted articles.
X
X More than one page of responses within a thread cause offset
X problems at thread level.
X
HHIISSTTOORRYY
X Based on the tass newsreader that was developed by Rich
X Skrenta and posted to alt.sources in March 1991. Tass was
X itself heavily infleuenced by NOTES which was developed at
X the University of Illinois in the early 1980's.
X
X Tin v1.00 (full distribution) was posted in 8 parts to
X alt.sources 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
X 30 Sep 1991.
X Tin v1.0 PL4 (patch) was posted in 2 parts to alt.sources on
X 02 Oct 1991.
X Tin v1.0 PL5 (patch) was posted in 4 parts to alt.sources on
X 17 Oct 1991.
X Tin v1.0 PL6 (patch) was posted in 5 parts to alt.sources on
X 27 Nov 1991.
X Tin v1.0 PL7 (patch) was posted in 2 parts to alt.sources on
X 27 Nov 1991.
X Tin v1.1 PL0 (full distribution) was posted in ?? parts to
X alt.sources on ?? Feb 1992.
X
CCRREEDDIITTSS
X Rich Skrenta
X author of tass v3.2 which this newsreader used as its
X base.
X
X Dave Taylor
X author of curses.c from the elm mailreader.
X
X
X
X
NEWS-OS Release 4.1R 17
X
X
X
X
X
TIN(1) NEWS-OS Programmer's Manual TIN(1)
X
X
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 I wish to thank the following people for supplying patchs:
X
X Anton Aylward, Dieter Becker, Marc Boucher, Robert Claeson,
X Ned Danieley, Brent Ermlick, Carl Hage, Ed Hanway, Torsten
X Homeyer, Karl-Koenig Koenigsson, Kris Kugel, Hakan Lenne-
X stal, Clifford Luke, Bill Poitras, Jim Robinson, Nickolay
X Saukh, Rich Salz, John Sauter, Bart Sears, Karl-Olav Ser-
X rander, Doug Sewell, Cliff Stanford, Adri Verhoef, Cary
X Whitney
X
X I wish to thank the following people for bug
X reports/comments:
X
X Klaus Arzig, Scott Babb, Reiner Balling, Dan Berry, Volker
X Beyer, Roger Binns, Georg Biehler, Ian Brown, Andreas Bro-
X sig, Steven Cogswell, Tom Czarnik, David Donovan, Peter
X Dressler, Gerhard Ermer, Hugh Fader, Joachim Feld, Paul Fox,
X Bernhard Gmelch, Viet Hoang, Andy Jackson, Joe Johnson,
X Cyrill Jung, Hans-Juergen Knopp, Per Lindqvist, Bob Lukas,
X Phillip Molloy, Toni Metz, Greg Miller, Klaus Neuberger,
X Otto Niesser, Reiner Oelhaf, Wolf Paul, Andrew Phillips, Ted
X Richards, Fredy Schwatz, Bernd Schwerin, Klamer Schutte,
X Chris Smith, Steve Spearman, Hironobu Takahashi, Sven Werner
X
AAUUTTHHOORR
X Iain Lea
X (iain%estevax.uucp@unido.Informatik.Uni-Dortmund.DE)
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
18 Release 4.1R NEWS-OS
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 41067 -eq "$Wc_c" ||
echo 'tin.nrf: original size 41067, 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 : R.Skrenta / I.Lea
X * Created : 01-04-91
X * Updated : 04-02-92
X * Notes :
X * Copyright : (c) Copyright 1991-92 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
#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
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 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 set_real_uid_gid (); /* so become them */
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 (show_only_unread);
X }
X
X if (local_index) {
X set_tin_uid_gid ();
X }
X } else {
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 display_groupname = TRUE;
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 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 % 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 (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, 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_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) {
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 * 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 ()
{
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 = fopen (index_file, "r")) == 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]);
X } else {
X error = 12;
X goto corrupt_index;
X }
X
X /*
X * Date:
X */
X if (fgets(buf, sizeof buf, fp) == NULL) {
X error = 13;
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, sizeof buf, fp) == NULL) {
X error = 14;
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 = 15;
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 continue;
X *p = '\0';
X arts[top].archive = hash_str (&buf[1]);
X } else {
X error = 16;
X goto corrupt_index;
X }
X
X /*
X * part no.
X */
X if (fgets(buf, sizeof buf, fp) == NULL) {
X error = 17;
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, sizeof buf, fp) == NULL) {
X error = 18;
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
corrupt_index:
X if (! update) {
X sprintf (msg, txt_corrupt_index, index_file, error, top);
X error_message (msg, "");
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 * 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
void find_local_index (group)
X char *group;
{
X unsigned long h;
X static char buf[LEN];
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, sizeof buf, fp) == NULL) {
X fclose(fp);
X return;
X }
X fclose(fp);
X
X for (p = buf; *p && *p != '\n'; p++)
X continue;
X *p = '\0';
X
X if (strcmp(buf, group) == 0)
X return;
X
X i++;
X }
}
X
/*
X * Run the index file updater only for the groups we've loaded.
X */
X
void do_update ()
{
X int i, j;
X char group_path[LEN];
X char *p;
X long epoch;
X
X if (verbose) {
X time (&epoch);
X printf ("%s", ctime (&epoch));
X fflush (stdout);
X }
X
X for (i = 0; i < group_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], FALSE);
X }
X }
X
X if (verbose) {
X time (&epoch);
X printf ("%s", ctime (&epoch));
X fflush (stdout);
X }
}
X
/*
X * reload index after any articles have been killed
X */
X
void reload_index_file (group, killed)
X char *group;
X int killed;
{
X char group_path[LEN];
X char *p;
X
X if (local_index) { /* writing index in home directory */
X set_real_uid_gid (); /* so become them */
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 (txt_killing_arts);
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 (txt_unkilling_arts);
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 (show_only_unread);
X
X if (local_index) {
X set_tin_uid_gid ();
X }
X
X return;
}
X
/*
X * convert date from ctime format to sortable format
X * "24 Jul 91 12:59:59", "Mon, 24 Jul 91 12:59:59" and
X * "Mon, 24 Jul 1991 12:59:59" are parsed and produce
X * output of the form "910724125959"
X */
X
char *parse_date (date, str)
X char *date;
X char *str;
{
X char buf[4];
X int i = 0;
X
X /* Check for extraneous day-of-week at start of date */
X while (isalpha(date[i]) || date[i] == ',' || date[i] == ' ') {
X i++;
X }
X
X if (date[i+1] == ' ') { /* ie. "2 Aug..." instead of "12 Aug... */
X str[4] = '0'; /* day */
X str[5] = date[i++];
X i++;
X } else {
X str[4] = date[i++]; /* day */
X str[5] = date[i++];
X i++;
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 if (isdigit(date[i])) { /* 19xx format */
X str[0] = date[i++];
X str[1] = date[i++];
X }
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
int artnum_comp (p1, p2)
X char *p1;
X char *p2;
{
X struct article_t *s1 = (struct article_t *) p1;
X struct article_t *s2 = (struct article_t *) p2;
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
int subj_comp (p1, p2)
X char *p1;
X char *p2;
{
X struct article_t *s1 = (struct article_t *) p1;
X struct article_t *s2 = (struct article_t *) p2;
X
X /* return result of strcmp (reversed for descending) */
X return (sort_art_type == SORT_BY_SUBJ_ASCEND
X ? strcmp (s1->subject, s2->subject)
X : strcmp (s2->subject, s1->subject));
}
X
X
int from_comp (p1, p2)
X char *p1;
X char *p2;
{
X struct article_t *s1 = (struct article_t *) p1;
X struct article_t *s2 = (struct article_t *) p2;
X
X /* return result of strcmp (reversed for descending) */
X return (sort_art_type == SORT_BY_FROM_ASCEND
X ? strcmp (s1->from, s2->from)
X : strcmp (s2->from, s1->from));
}
X
X
int date_comp (p1, p2)
X char *p1;
X char *p2;
{
X struct article_t *s1 = (struct article_t *) p1;
X struct article_t *s2 = (struct article_t *) p2;
X /* return result of strcmp (reversed for descending) */
X return (sort_art_type == SORT_BY_DATE_ASCEND
X ? strcmp (s1->date, s2->date)
X : strcmp (s2->date, s1->date));
}
X
X
void set_article (art)
X struct article_t *art;
{
X art->subject = (char *) 0;
X art->from = (char *) 0;
X art->name = (char *) 0;
X art->date[0] = '\0';
X art->archive = (char *) 0;
X art->part = (char *) 0;
X art->patch = (char *) 0;
X art->unread = ART_UNREAD;
X art->inthread = FALSE;
X art->killed = FALSE;
X art->tagged = FALSE;
}
SHAR_EOF
chmod 0600 art.c ||
echo 'restore of art.c failed'
Wc_c="`wc -c < 'art.c'`"
test 23976 -eq "$Wc_c" ||
echo 'art.c: original size 23976, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= curses.c ==============
if test -f 'curses.c' -a X"$1" != X"-c"; then
echo 'x - skipping curses.c (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting curses.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'curses.c' &&
/*
X * Project : tin - a threaded Netnews reader
X * Module : curses.c
X * Author : Dave Taylor
X * Created : ??-??-86
X * Updated : 13-12-91
X * Notes : This is a screen management library borrowed with permission
X * from the Elm mail system (a great mailer--I highly recommend
X * it!).This library was hacked to provide what tin needs.
X * Copyright : Copyright (c) 1986 Dave Taylor
X * The Elm Mail System - $Revision: 2.1 $ $State: Exp $
X */
X
#include <stdio.h>
#include <curses.h>
#ifndef MINIX
# include <sys/ioctl.h>
#endif
X
#ifdef TRUE
# undef TRUE
# define TRUE 1
#else
# define TRUE 1
#endif
X
#ifdef FALSE
# undef FALSE
# define FALSE 0
#else
# define FALSE 0
#endif
X
#define BACKSPACE '\b'
#define VERY_LONG_STRING 2500
X
int LINES=23;
int COLS=80;
X
int inverse_okay = TRUE;
X
#ifdef BSD
# ifndef BSD4_1
# include <sgtty.h>
# else
# include <termio.h>
# endif
#else
# ifndef SYSV
# ifndef MINIX
# ifdef SINIX
# include <termios.h>
# else
# include <termio.h>
# endif
# else
# include <sgtty.h>
# endif
# endif
#endif
X
#include <ctype.h>
X
#include "tin.h"
X
#define TTYIN 0
X
#ifdef SHORTNAMES
# define _clearinverse _clrinv
# define _cleartoeoln _clrtoeoln
# define _cleartoeos _clr2eos
#endif
X
#if defined(BSD) || defined(MINIX)
# define TCGETA TIOCGETP
# define TCSETAW TIOCSETP
X
struct sgttyb _raw_tty,
X _original_tty;
#else
# ifdef SINIX
# define TCGETA STCGETA
# define TCSETAW STCSETAW
struct termios _raw_tty,
X _original_tty;
# else
struct termio _raw_tty,
X _original_tty;
# endif
#endif
X
static int _inraw = FALSE; /* are we IN rawmode? */
X
#define DEFAULT_LINES_ON_TERMINAL 24
#define DEFAULT_COLUMNS_ON_TERMINAL 80
X
static char *_clearscreen, *_moveto, *_cleartoeoln, *_cleartoeos,
X *_setinverse, *_clearinverse, *_setunderline, *_clearunderline,
X *_terminalinit, *_terminalend;
X
static int _lines,_columns;
X
static char _terminal[1024]; /* Storage for terminal entry */
static char _capabilities[1024]; /* String for cursor motion */
X
static char *ptr = _capabilities; /* for buffering */
X
int outchar (); /* char output for tputs */
char *tgetstr (), /* Get termcap capability */
X *tgoto (); /* and the goto stuff */
X
int InitScreen ()
{
X int tgetent(); /* get termcap entry */
X char termname[40], *p;
X
X if ((p = (char *) getenv ("TERM")) == NULL) {
X fprintf (stderr, "%s: TERM variable must be set to use screen capabilities\n", progname);
X return (FALSE);
X }
X if (strcpy (termname, p) == NULL) {
X fprintf (stderr,"%s: Can't get TERM variable\n", progname);
X return (FALSE);
X }
X if (tgetent (_terminal, termname) != 1) {
X fprintf (stderr,"%s: Can't get entry for TERM\n", progname);
X return (FALSE);
X }
X
X /* load in all those pesky values */
X _clearscreen = tgetstr ("cl", &ptr);
X _moveto = tgetstr ("cm", &ptr);
X _cleartoeoln = tgetstr ("ce", &ptr);
X _cleartoeos = tgetstr ("cd", &ptr);
X _lines = tgetnum ("li");
X _columns = tgetnum ("co");
X _setinverse = tgetstr ("so", &ptr);
X _clearinverse = tgetstr ("se", &ptr);
X _setunderline = tgetstr ("us", &ptr);
X _clearunderline = tgetstr ("ue", &ptr);
X _terminalinit = tgetstr ("ti", &ptr);
X _terminalend = tgetstr ("te", &ptr);
X
X InitWin ();
X
X if (!_clearscreen) {
X fprintf (stderr,
X "%s: Terminal must have clearscreen (cl) capability\n",progname);
X return (FALSE);
X }
X if (!_moveto) {
X fprintf (stderr,
X "%s: Terminal must have cursor motion (cm)\n", progname);
X return (FALSE);
X }
X if (!_cleartoeoln) {
X fprintf (stderr,
X "%s: Terminal must have clear to end-of-line (ce)\n", progname);
X return (FALSE);
X }
X if (!_cleartoeos) {
/*
X fprintf (stderr,
X "%s: terminal does not have clear to end-of-screen (ce). Simulating\n", progname);
*/
X fprintf (stderr,
X "%s: Terminal must have clear to end-of-screen (cd)\n", progname);
X return (FALSE);
X }
X if (_lines == -1)
X _lines = DEFAULT_LINES_ON_TERMINAL;
X if (_columns == -1)
X _columns = DEFAULT_COLUMNS_ON_TERMINAL;
X return (TRUE);
}
X
/*
X * returns the number of lines and columns on the display.
X */
X
void ScreenSize(num_lines, num_columns)
X int *num_lines, *num_columns;
{
X if (_lines == 0) _lines = DEFAULT_LINES_ON_TERMINAL;
X if (_columns == 0) _columns = DEFAULT_COLUMNS_ON_TERMINAL;
X
X *num_lines = _lines - 1; /* assume index from zero*/
X *num_columns = _columns; /* assume index from one */
}
X
void InitWin ()
{
X if (_terminalinit) {
X tputs (_terminalinit, 1, outchar);
X fflush (stdout);
X }
}
X
void EndWin ()
{
X if (_terminalend) {
X tputs (_terminalend, 1, outchar);
X fflush (stdout);
X }
}
X
/*
X * clear the screen: returns -1 if not capable
X */
X
void ClearScreen()
{
X tputs(_clearscreen, 1, outchar);
X fflush(stdout); /* clear the output buffer */
}
X
/*
X * move cursor to the specified row column on the screen.
X * 0,0 is the top left!
X */
X
void MoveCursor(row, col)
X int row, col;
{
X char *stuff, *tgoto();
X
X stuff = tgoto (_moveto, col, row);
X tputs (stuff, 1, outchar);
X fflush (stdout);
}
X
/*
X * clear to end of line
X */
X
void CleartoEOLN()
{
X tputs(_cleartoeoln, 1, outchar);
X fflush(stdout); /* clear the output buffer */
}
X
/*
X * clear to end of screen
X */
X
void CleartoEOS()
{
X int i;
X
X if (_cleartoeos) {
X tputs(_cleartoeos, 1, outchar);
X } else {
X for (i=_lines ; i < _lines ; i++) {
X MoveCursor (i, 0);
X CleartoEOLN ();
X }
X }
X fflush(stdout); /* clear the output buffer */
}
X
/*
X * set inverse video mode
X */
X
void StartInverse()
{
X if (_setinverse && inverse_okay)
X tputs(_setinverse, 1, outchar);
X fflush(stdout);
}
X
/*
X * compliment of startinverse
X */
X
void EndInverse()
{
X if (_clearinverse && inverse_okay)
X tputs(_clearinverse, 1, outchar);
X fflush(stdout);
}
X
/*
X * returns either 1 or 0, for ON or OFF
X */
X
int RawState()
{
X return (_inraw);
}
X
/*
X * state is either TRUE or FALSE, as indicated by call
X */
X
void Raw(state)
X int state;
{
X if (state == FALSE && _inraw) {
X (void) ioctl(TTYIN, TCSETAW, &_original_tty);
X _inraw = 0;
X }
X else if (state == TRUE && ! _inraw) {
X
X (void) ioctl(TTYIN, TCGETA, &_original_tty); /** current setting **/
X
X (void) ioctl(TTYIN, TCGETA, &_raw_tty); /** again! **/
#if defined(BSD) || defined(MINIX)
X _raw_tty.sg_flags &= ~(ECHO | CRMOD); /* echo off */
X _raw_tty.sg_flags |= CBREAK; /* raw on */
#else
X _raw_tty.c_lflag &= ~(ICANON | ECHO); /* noecho raw mode */
X
X _raw_tty.c_cc[VMIN] = '\01'; /* minimum # of chars to queue */
X _raw_tty.c_cc[VTIME] = '\0'; /* minimum time to wait for input */
#endif
X
X (void) ioctl(TTYIN, TCSETAW, &_raw_tty);
X
X _inraw = 1;
X }
}
X
/*
X * read a character with Raw mode set!
X */
X
int ReadCh()
{
X register int result;
X char ch;
X
#ifdef READ_CHAR_HACK
#undef getc
X ch = getc (stdin);
X return ((ch == EOF) ? EOF : ch & 0xFF);
#else
X result = read(0, &ch, 1);
X return((result <= 0 ) ? EOF : ch & 0xFF);
#endif
}
X
/*
X * output a character. From tputs... (Note: this CANNOT be a macro!)
X */
X
int outchar(c)
X char c;
{
X putc(c, stdout);
}
SHAR_EOF
chmod 0600 curses.c ||
echo 'restore of curses.c failed'
Wc_c="`wc -c < 'curses.c'`"
test 7108 -eq "$Wc_c" ||
echo 'curses.c: original size 7108, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= debug.c ==============
if test -f 'debug.c' -a X"$1" != X"-c"; then
echo 'x - skipping debug.c (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting debug.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'debug.c' &&
/*
X * Project : tin - a threaded Netnews reader
X * Module : debug.c
X * Author : I.Lea
X * Created : 01-04-91
X * Updated : 21-01-92
X * Notes : debug routines
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 debug;
X
X
void debug_print_arts ()
{
#ifdef DEBUG
X int i;
X
X if (! debug)
X return;
X
X for (i = 0; i < top; i++) { /* for each group */
X debug_print_header (&arts[i]);
X }
#endif
}
X
X
void debug_print_header (s)
X struct article_t *s;
{
#ifdef DEBUG
X FILE *fp;
X
X if (! debug)
X return;
X
X if ((fp = fopen ("/tmp/DUMP","a+")) != NULL) {
X fprintf (fp,"art=[%5ld] killed=[%s]\n", s->artnum,
X (s->tagged ? "TRUE" : "FALSE"));
X fprintf (fp,"subj=[%-38s]\n", s->subject);
X fprintf (fp,"from=[%s] name=[%s]\n", s->from, s->name);
X if (s->archive) {
X fprintf (fp, "arch=[%-38s] ", s->archive);
X } else {
X fprintf (fp, "arch=[] ");
X }
X if (s->part) {
X fprintf (fp, "part=[%s] ", s->part);
X } else {
X fprintf (fp, "part=[] ");
X }
X if (s->patch) {
X fprintf (fp, "patch=[%s]\n", s->patch);
X } else {
X fprintf (fp, "patch=[]\n");
X }
X fprintf (fp,"thread=[%d] inthread=[%d] unread=[%d]\n",
X s->thread, s->inthread, s->unread);
/* fprintf (fp,"thread=[%s] inthread=[%s] unread=[%s]\n",
X (s->thread == ART_NORMAL ? "ART_NORMAL" : "ART_EXPIRED"),
X (s->inthread ? "TRUE" : "FALSE"),
X (s->unread ? "TRUE" : "FALSE"));
*/
X fflush (fp);
X fclose (fp);
X chmod ("/tmp/DUMP", 0666);
X }
#endif
}
X
X
void debug_print_comment (comment)
X char *comment;
{
#ifdef DEBUG
X FILE *fp;
X
X if (! debug)
X return;
X
X if ((fp = fopen ("/tmp/BASE","a+")) != NULL) {
X fprintf (fp,"\n%s\n\n", comment);
X fflush (fp);
X fclose (fp);
X chmod ("/tmp/BASE", 0666);
X }
#endif
}
X
X
void debug_print_base ()
{
#ifdef DEBUG
X FILE *fp;
X int i;
X
X if (! debug)
X return;
X
X if ((fp = fopen ("/tmp/BASE","a+")) != NULL) {
X for (i = 0; i < top_base; i++) {
X fprintf (fp, "base[%3d]=[%5ld]\n",i,base[i]);
X }
X fflush (fp);
X fclose (fp);
X chmod ("/tmp/BASE", 0666);
X }
#endif
}
X
X
void debug_print_active ()
{
#ifdef DEBUG
X FILE *fp;
X int i;
X
X if (! debug)
X return;
X
X if ((fp = fopen ("/tmp/ACTIVE","w")) != NULL) {
X for (i = 0; i < num_active; i++) { /* for each group */
X fprintf (fp, "[%4d]=[%-28s] max=[%4ld] min=[%4ld] mod=[%c] nxt=[%4d] flag=[%d] read=[%d] thread=[%d]\n",
X i, active[i].name, active[i].max, active[i].min,
X active[i].moderated, active[i].next, active[i].flag,
X active[i].read, active[i].thread);
X }
X fflush (fp);
X fclose (fp);
X chmod ("/tmp/ACTIVE", 0666);
X }
#endif
}
X
X
void log_user ()
{
#ifdef LOG_USER
X char buf[33];
X FILE *fp;
X long epoch;
X extern struct passwd *myentry;
X
X if ((fp = fopen (LOG_USER_FILE, "a+")) != NULL) {
X time (&epoch);
X my_strncpy (buf, myentry->pw_gecos, 32);
X fprintf (fp, "%s%d: %-32s (%-8s) %s", VERSION, PATCHLEVEL,
X buf, myentry->pw_name, ctime (&epoch));
X fclose (fp);
X chmod (LOG_USER_FILE, 0666);
X }
#endif
}
SHAR_EOF
chmod 0600 debug.c ||
echo 'restore of debug.c failed'
Wc_c="`wc -c < 'debug.c'`"
test 3249 -eq "$Wc_c" ||
echo 'debug.c: original size 3249, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= feed.c ==============
if test -f 'feed.c' -a X"$1" != X"-c"; then
echo 'x - skipping feed.c (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting feed.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'feed.c' &&
/*
X * Project : tin - a threaded Netnews reader
X * Module : feed.c
X * Author : I.Lea
X * Created : 31-08-91
X * Updated : 31-01-92
X * Notes : provides same interface to mail,pipe,print and save commands
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
extern char *glob_group; /* Group name */
extern char note_h_date[LEN]; /* Date: */
extern char note_h_subj[LEN]; /* Subject: */
extern FILE *note_fp; /* the body of the current article */
extern int note_end; /* end of article ? */
extern int note_page; /* what page we're on */
extern long note_mark[MAX_PAGES]; /* ftells on beginnings of pages */
X
char default_mail_address[LEN];
char default_pipe_command[LEN];
char default_save_file[LEN];
char default_regex_pattern[LEN];
char proc_ch_default; /* set in change_rcfile () */
X
X
void feed_articles (function, level, prompt, respnum, group_path)
X int function;
X int level;
X char *prompt;
X int respnum;
X char *group_path;
{
X char address[LEN];
X char command[LEN];
X char file[LEN], *p;
X char mailbox[LEN];
X char pattern[LEN];
X char ch = 'a', ch_default = 'a';
X char proc_ch = proc_ch_default;
X FILE *fp;
X int b, i, j, count = 1;
X int is_mailbox = FALSE;
X int orig_note_end;
X int orig_note_page;
X int patlen;
X int ret1 = FALSE;
X int ret2 = FALSE;
X int redraw_screen = FALSE;
X
X if (level == PAGE_LEVEL) {
X orig_note_end = note_end;
X orig_note_page = note_page;
X }
X
X b = which_thread (respnum);
X
X if (num_of_tagged_files) {
X ch_default = 'T';
X }
X if (! num_of_tagged_files && num_of_responses (b)) {
X ch_default = 't';
X }
X
X if ((save_archive_name == FALSE || arts[respnum].archive == (char *) 0) ||
X (save_archive_name == TRUE && function != FEED_SAVE) ||
X ch_default == 'T') {
X do {
X sprintf (msg, "%s%s%c", prompt, txt_art_thread_regex_tag, ch_default);
X wait_message (msg);
X MoveCursor (LINES, (int) strlen (msg)-1);
X if ((ch = (char) ReadCh ()) == CR)
X ch = ch_default;
X } while (ch != ESC && ch != 'a' && ch != 't' && ch != 'T' && ch != 'r' && ch != 'e');
X } else {
X file[0] = '\0';
X ch = ch_default;
X if (str_str (glob_group, "sources", 7)) {
X proc_ch = 's'; /* *source* group */
X } else if (str_str (glob_group, "binaries", 8)) {
X proc_ch = 'u'; /* *binaries* group */
X } else {
X proc_ch = 's';
X }
X }
X
X if (ch == 'e' || ch == ESC) { /* exit */
X clear_message ();
X return;
X }
X
X if (ch == 'r') {
X sprintf (msg, txt_feed_pattern, default_regex_pattern);
X if (! prompt_string (msg, pattern)) {
X clear_message ();
X return;
X }
X if (strlen (pattern)) {
X my_strncpy (default_regex_pattern, pattern, LEN);
X } else {
X if (default_regex_pattern[0]) {
X my_strncpy (pattern, default_regex_pattern, LEN);
X } else {
X info_message (txt_no_match);
X return;
X }
X }
X }
X
X switch (function) {
X case FEED_MAIL:
X sprintf (msg, txt_mail_art_to, default_mail_address);
X if (! prompt_string (msg, address)) {
X clear_message ();
X return;
X }
X if (strlen (address)) {
X strcpy (default_mail_address, address);
X } else {
X if (default_mail_address[0]) {
X strcpy (address, default_mail_address);
X } else {
X info_message (txt_no_mail_address);
X return;
X }
X }
X break;
X case FEED_PIPE:
X sprintf (msg, txt_pipe_to_command, default_pipe_command);
X if (! prompt_string (msg, command)) {
X clear_message ();
X return;
X }
X if (strlen (command)) {
X strcpy (default_pipe_command, command);
X } else {
X if (default_pipe_command[0]) {
X strcpy (command, default_pipe_command);
X } else {
X info_message (txt_no_command);
X return;
X }
X }
X
X if ((fp = popen (command, "w")) == NULL) {
X error_message (txt_command_failed_s, command);
X return;
X }
X wait_message (txt_piping);
X Raw (FALSE);
X break;
X case FEED_PRINT:
X if (default_printer) {
#ifdef SINIX
X sprintf (command, "%s -dru=%s %s",
X printer, get_val ("PRINTER","ps0"), redirect_output);
#else
X sprintf (command, "%s -P%s %s",
X printer, get_val ("PRINTER","ps0"), redirect_output);
#endif
X } else {
X if (cmd_line_printer[0]) {
X sprintf (command, "%s %s",
X cmd_line_printer, redirect_output);
X } else {
X sprintf (command, "%s %s",
X printer, redirect_output);
X }
X }
X if ((fp = popen (command, "w")) == NULL) {
X error_message (txt_command_failed_s, command);
X return;
X }
X break;
X case FEED_SAVE: /* ask user for filename */
X free_save_array ();
X if ((save_archive_name == FALSE || arts[respnum].archive == (char *) 0)) {
X sprintf (msg, txt_save_filename, default_save_file);
X if (! prompt_string (msg, file)) {
X clear_message ();
X return;
X }
X if (strlen (file)) {
X strcpy (default_save_file, file);
SHAR_EOF
true || echo 'restore of feed.c failed'
fi
echo 'End of tin1.1 part 3'
echo 'File feed.c is continued in part 4'
echo 4 > _shar_seq_.tmp
exit 0
--
NAME Iain Lea
EMAIL iain%estevax.uucp@unido.Informatik.Uni-Dortmund.DE
SNAIL Bruecken Strasse 12, 8500 Nuernberg 90, Germany
PHONE +49-911-331963 (home) +49-911-3089-407 (work)
--
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...