home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-02-22 | 50.4 KB | 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...
-