home *** CD-ROM | disk | FTP | other *** search
Text File | 1991-09-25 | 49.7 KB | 2,035 lines |
- Newsgroups: comp.sources.misc
- From: iain@estevax.uucp (Iain J. Lea)
- Subject: v23i016: tin - threaded full screen newsreader v1.0 PL2, Part02/09
- Message-ID: <1991Sep25.205034.1844@sparky.imd.sterling.com>
- X-Md4-Signature: 1216384cf791ab26c63268a1db335011
- Date: Wed, 25 Sep 1991 20:50:34 GMT
- Approved: kent@sparky.imd.sterling.com
-
- Submitted-by: iain@estevax.uucp (Iain J. Lea)
- Posting-number: Volume 23, Issue 16
- Archive-name: tin/part02
- Environment: BSD, SCO, ISC, SUNOS, SYSVR3, SYSVR4, ULTRIX, XENIX
-
- #!/bin/sh
- # this is tin.shar.02 (part 2 of tin1.02)
- # do not concatenate these parts, unpack them in order with /bin/sh
- # file tin.1 continued
- #
- if touch 2>&1 | fgrep '[-amc]' > /dev/null
- then TOUCH=touch
- else TOUCH=true
- fi
- if test ! -r shar3_seq_.tmp; then
- echo "Please unpack part 1 first!"
- exit 1
- fi
- (read Scheck
- if test "$Scheck" != 2; then
- echo "Please unpack part $Scheck next!"
- exit 1
- else
- exit 0
- fi
- ) < shar3_seq_.tmp || exit 1
- echo "x - Continuing file tin.1"
- sed 's/^X//' << 'SHAR_EOF' >> tin.1 &&
- X.TP
- X\fBz\fP
- XMark article as unread.
- X.TP
- X\fB/\fP
- XArticle forward search.
- X.TP
- X\fB?\fP
- XArticle backward search
- X.TP
- X\fB|\fP
- XPipe current article / thread / articles matching pattern / tagged articles
- Xinto command.
- X.TP
- X\fB<\fP
- XGoto the first article in the current thread.
- X.TP
- X\fB>\fP
- XGoto the last article in the current thread.
- X.SH "OPTIONS MENU"
- XThis menu is accessed by pressing 'M' at all levels. It allows the user
- Xto customize the behaviour of tin. The options are saved to the file
- X\fI$HOME/.tin/tinrc\fP. The following options are settable:
- X.TP 4
- X\fBAuto save\fP
- XAutomatically save articles/threads by Archive-name: line in article
- Xheader. This is useful to set ON in conjunction with 'Save separate'.
- XUse <SPACE> to toggle ON/OFF and <CR> to set.
- X.TP
- X\fBSave separate\fP
- XSave articles/threads to separate files. Set ON if saving source code.
- XSet OFF if saving a coversational thread. Use <SPACE> to toggle ON/OFF
- Xand <CR> to set.
- X.TP
- X\fBMark saved read\fP
- XThis allows saved articles/threads to be automatically marked as
- Xhaving been read. Use <SPACE> to toggle ON/OFF and <CR> to set.
- X.TP
- X\fBKill articles\fP
- XThis allows the user to kill articles that match entries in the kill
- Xfile \fI$HOME/.tin/kill\fP. Use <SPACE> to toggle ON/OFF and <CR>
- Xto set.
- X.TP
- X\fBShow Author\fP
- XIf set ON the Subject: & From: (author) lines from the articles header
- Xare displayed. If set OFF longer Subject: lines are displayed. Use
- X<SPACE> to toggle ON/OFF and <CR> to set.
- X.TP
- X\fBDraw arrow\fP
- XAllows groups/articles to be selected by an arrow '->' if set ON or
- Xby an highlighted bar if set OFF. Use <SPACE> to toggle ON/OFF and
- X<CR> to set.
- X.TP
- X\fBPrint header\fP
- XThis allows the complete mail header or only the Siubject: and From:
- Xfields to be output when printing articles. Use <SPACE> to toggle
- XON/OFF and <CR> to set.
- X.TP
- X\fBGoto 1st unread\fP
- XThis allows the cursor to be placed at the first / last unread article
- Xupon entering a newsgroup with unread news. Use <SPACE> to toggle
- XON/OFF and <CR> to set.
- X.TP
- X\fBProcess type\fP
- XThis specifies the default type of post processing to perform on saved
- Xarticles. The following types of processing are allowed:
- X.in +.5i
- X.ti -\w'\(em'u
- X\(emnone.
- X.ti -\w'\(em'u
- X\(emunpacking of multi-part shell archives.
- X.ti -\w'\(em'u
- X\(emunpacking of multi-part uuencoded files.
- X.ti -\w'\(em'u
- X\(emunpacking of multi-part uuencoded files that produce a *.zoo archive
- Xwhose contents is listed.
- X.ti -\w'\(em'u
- X\(emunpacking of multi-part uuencoded files that produce a *.zoo archive
- Xwhose contents is extracted.
- X.ti -\w'\(em'u
- X\(emunpacking of multi-part patches for use by \fIpatch\fP and applying
- Xthem to specified source files.
- X.in -.5i
- XUse <SPACE> to toggle the required type and <CR> to set.
- X.TP
- X\fBSort articles by\fP
- XThis specifies how articles should be sorted. The following sort
- Xtypes are allowed:
- X.in +.5i
- X.ti -\w'\(em'u
- X\(emdon't sort articles (default).
- X.ti -\w'\(em'u
- X\(emsort articles by Subject: field (ascending & descending).
- X.ti -\w'\(em'u
- X\(emsort articles by From: field (ascending & descending).
- X.ti -\w'\(em'u
- X\(emsort articles by Date: field (ascending & descending).
- X.in -.5i
- XUse <SPACE> to set the required type.
- X.TP
- X\fBSave directory\fP
- XThe directory where articles/threads are to be saved. Default is
- X\fI$HOME/News\fP.
- X.TP
- X\fBMail directory\fP
- XThe directory where articles/threads are to be saved in mailbox format.
- XThis feature is mainly for use with the Elm mail program. It allows
- Xthe user to save articles/threads/groups simply by giving '=' as
- Xthe filename to save to.
- X.TP
- X\fBPrinter\fP
- XThe printer program with options that is to be used to print
- Xarticles. Default is lpr for BSD machines and lp for SysV machines.
- X.SH "KILL ARTICLE MENU"
- XThis menu is accessed by pressing '^K' at the group and page levels. It
- Xallows the user to kill an article that matches the current Subject:
- Xline, From: line or a string entered by the user. The user entered string
- Xcan be applied to the Subject: or From: lines of an article. The kill
- Xdescription can be limited to the current newsgroup or it can apply to all newsgroups.
- XOnce entered the user can abort the command and not save the kill
- Xdescription, edit the kill file or save the kill description.
- X.PP
- XOn starting tin the users killfile \fI$HOME/.tin/kill\fP is read and
- Xon entering a newsgroup any kill descriptions are applied. Articles
- Xthat match a kill description are marked killed and are not displayed.
- X.PP
- XThe 'Kill articles' option needs to be set ON in the Options Menu
- X(selected by 'M' at any level) to activate this command.
- X.SH "POSTING ARTICLES"
- XTin allows posting of articles, follow-up to already posted articles
- Xand replying direct through mail to the author of an article.
- X.PP
- XUse the 'w' command to post an article to a newsgroup. After entering
- Xthe post subject the default editor (ie. vi) or the editor specified
- Xby the $EDITOR enviroment variable will be started and the article can
- Xbe entered. To crosspost articles simply add a comma and the name of
- Xthe newsgroup(s) to the end of the Newsgroups: line at the beginning of
- Xthe article. After saving and exiting the editor you are asked if you
- Xwish to a)bort posting the article, e)dit the article again or p)ost
- Xthe article to the specified newsgroup(s).
- X.PP
- XUse the 'W' command to display a history of the articles you have posted.
- XThe date the article was posted, which newsgroups the article was
- Xposted to and the articles subject line are displayed.
- X.PP
- XUse the 'f' / 'F' command to post a follow-up article to an already
- Xposted article. The 'F' command will copy the text of the original
- Xarticle into the editor. The editing procedure is the same as when
- Xposting an article with the 'w' command.
- X.PP
- XUse the 'r' / 'R' command to reply direct through mail to the author
- Xof an already posted article. The 'R' command will copy the text of
- Xthe original article into the editor. The editing procedure is the
- Xsame as when posting an article with the 'w' command. After saving
- Xand exiting the editor you are asked if you wish to a)bort sending
- Xthe article, e)dit the article again or s)end the article to the
- Xauthor.
- X.SH "MAILING PIPING PRINTING AND SAVING ARTICLES"
- XThe command interface to mail ('m'), pipe ('|'), print ('o') and save
- X('s') articles is the same for ease of use.
- X.PP
- XThe initial command will ask you to select which a)rticle, t)hread,
- Xr)egex pattern, t)agged articles you wish to mail, pipe etc.
- X.PP
- XTagged articles must have already been tagged with the 'T' command.
- XAll tagged articles can be untagged by the 'U' untag command.
- X.PP
- XIf regex pattern matching is selected you are asked to enter a regular
- Xexpression (ie. to match all articles subject lines containing 'net News'
- Xyou must enter '*net News*'). Any articles that match the
- Xentered expression will be mailed, piped etc.
- X.PP
- XTo save articles to a mailbox with the name of the current newsgroup
- X(ie. Alt.sources) enter '=' or '=<mailbox name>' when asked for the
- Xsave filename.
- X.PP
- XTo save articles in <newsgroup name>/<filename> format enter '+<filename>'.
- X.PP
- XWhen saving articles you can specify whether the saved files should be
- Xpost processed (ie. unshar shell archive, uudecode multiple parts etc).
- XA default process type can be set by the 'Process type:' in the 'M'
- Xoptions menu.
- X.SH SIGNATURES
- XTin will recognize a signature in either \fI$HOME/.signature\fP or
- X\fI$HOME/.Sig\fP. If \fI$HOME/.signature\fP exists, then the signature
- Xwill be pulled into the editor for Tin mail commands. A signature in
- X\fI$HOME/.signature\fP will not be pulled into the editor for posting
- Xcommands since the inews program will append the signature itself.
- X.PP
- XA signature in \fI$HOME/.Sig\fP will be pulled into the editor for both
- Xposting and mailing commands.
- X.PP
- XThe following is an example of a \fI$HOME/.Sig\fP file:
- X.RS
- X.nf
- XNAME Iain Lea
- XEMAIL iain@estevax.uucp ...!unido!estevax!iain
- XSNAIL Siemens AG, ANL 433SZ, 8510 Fuerth-Bislohe, Germany
- XPHONE +49-911-331963 (home) +49-911-895-3853 (work)
- X.fi
- X.RE
- X.SH "ENVIROMENT VARIABLES"
- X.TP
- X\fBTINDIR\fP
- XDefine this variable if you do not want tin's .tin directory in $HOME/.tin.
- X(ie. if you want all tin's private files in /tmp/.tin you would set
- XTINDIR to contain /tmp.
- X.TP
- X\fBNNTPSERVER\fP
- XThe default NNTP server to remotely read news from. This variable only
- Xneeds to be set if the -r command line option is specified and the file
- X\fI/etc/nntpserver\fP does not exist.
- X.TP
- X\fBORGANIZATION\fP
- XSet the mail header field Organization: to the contents of the
- Xvariable instead of the system default. This variable has precedence
- Xover the file \fI$HOME/.tin/organization\fP that may also contain an
- Xorganization string.
- X.TP
- X\fBREPLYTO\fP
- XSet the mail header field Reply-To: to the return address specified
- Xby the variable.
- XThis is useful if the machine is not registered in the UUCP mail maps
- Xor if you wish to recieve replies at a different machine.
- XThis variable has precedence over the file \fI$HOME/.tin/reply_to\fP
- Xthat may also contain a return address.
- X.TP
- X\fBADD_ADDRESS\fP
- XThis can contain an address to append to the return address when replying
- Xdirectly through mail to somebody whose mail address is not directly
- Xrecognized by the local host. For example say the return address is
- X\fIuser@bigvax\fP, but \fIbigvax\fP is not recognized by your host, so
- Xtherfore the mail will not reach \fIuser\fP. But the host \fIlittevax\fP
- Xis known to recognize your host and \fIbigvax\fP, so if ADD_ADDRESS is set
- X(ie. 'setenv ADD_ADDRESS @littevax' for csh or 'set ADD_ADDRESS @littevax'
- Xand 'export ADD_ADDRESS' for sh) the address \fIuser@bigvax@littlevax\fP will
- Xbe used and the mail will reach \fIuser@bigvax\fP.
- XThis variable has precedence over the file \fI$HOME/.tin/add_address\fP
- Xthat may also contain an address.
- X.TP
- X\fBBUG_ADDRESS\fP
- XIf the 'B' command bug report mail address is not correct this variable should be
- Xset to the correct mail address. This variable has precedence over the file
- X\fI$HOME/.tin/bug_address\fP that may also contain a mail address.
- X.TP
- X\fBEDITOR\fP
- XThis variable has precedence over the default editor (ie. vi) that is
- Xused in all editing operations within tin (ie. posting 'w', replying 'rR',
- Xfollow-ups 'fF' and bug reports 'B').
- X.SH TIPS AND TRICKS
- XThe following newsgroups provide useful information concerning news software:
- X.in +.5i
- X.ti -\w'\(em'u
- X\(emnews.software.readers (info. about news user agents tin,rn,nn,vn etc.)
- X.ti -\w'\(em'u
- X\(emnews.software.nntp (info. about NNTP)
- X.ti -\w'\(em'u
- X\(emnews.software.b (info. about news transport agents Bnews & Cnews)
- X.PP
- XMany prompts (ie. 'Mark everything as read? (y/n): y') within tin
- Xoffer a default choice that the cursor is positioned on. By pressing
- X<CR> the default value is taken.
- X.PP
- XWhen tin is run in an xterm window it will resize itself each time the xterm
- Xis resized.
- X.SH FILES
- X.nf
- X.ta \w'\fI$HOME/.tin/organization\fP 'u
- X\fI$HOME/.newsrc\fP newgroups subscribed to.
- X\fI$HOME/.tin/tinrc\fP options.
- X\fI$HOME/.tin/.index\fP newsgroup index files directory.
- X\fI$HOME/.tin/kill\fP kill file.
- X\fI$HOME/.tin/posted\fP history of articles posted by user.
- X\fI$HOME/.tin/active\fP used by -n option for notifying user of new groups.
- X\fI$HOME/.tin/organization\fP string to replace default organization.
- X\fI$HOME/.tin/reply_to\fP host address to use in Reply-To: mail header.
- X\fI$HOME/.tin/add_address\fP address to add to when replying through mail.
- X\fI$HOME/.tin/bug_address\fP address to send bug reports to.
- X\fI$HOME/.signature\fP signature.
- X\fI$HOME/.Sig\fP signature.
- X.fi
- X.SH BUGS
- XThere are bugs somewhere among the creeping featurism. Any bugs found
- Xshould be reported by the 'B' (bug report) command.
- X.PP
- XThere is a bug when article killing is switched ON/OFF at article
- Xpage level and the 't' command is used to return to group selection
- Xindex.
- X.PP
- XWhen articles have been unkilled, all articles will be marked
- Xunread even if they have already been read.
- X.PP
- XKilling articles when tin is setuid causes strange behaviour.
- X.PP
- XWill not uudecode some of the images in alt.binaries.pictures because
- Xmore than one image is in the multi-part file to uudecode. Only the
- Xfirst image will be uudecoded.
- X.PP
- XDoes not handle Xref: headers for cross-posted articles.
- X.SH HISTORY
- XBased on the tass newsreader that was developed by Rich Skrenta and posted
- Xto alt.sources in March 1991. Tass was itself heavily infleuenced by NOTES
- Xwhich was developed at the University of Illinois in the 1970's.
- X.SH CREDITS
- X.TP
- XRich Skrenta
- Xauthor of tass v3.2 which this newsreader used as its base.
- X.TP
- XSyd Weinstein
- Xcurses.c is taken from the elm mailreader
- X.TP
- XRich Salz
- Xauthor of wildmat.c pattern matching routines.
- X.TP
- XChris Smith
- Xauthor of multi-part uudecode routine.
- X.SH AUTHOR
- X.TP
- XIain Lea
- X(iain@estevax.uucp or ...!unido!estevax!iain)
- SHAR_EOF
- echo "File tin.1 is complete" &&
- $TOUCH -am 0924085491 tin.1 &&
- chmod 0600 tin.1 ||
- echo "restore of tin.1 failed"
- set `wc -c tin.1`;Wc_c=$1
- if test "$Wc_c" != "26331"; then
- echo original size 26331, current size $Wc_c
- fi
- # ============= wildmat.3 ==============
- echo "x - extracting wildmat.3 (Text)"
- sed 's/^X//' << 'SHAR_EOF' > wildmat.3 &&
- X.TH WILDMAT 3
- X.SH NAME
- Xwildmat \- perform shell-style wildcard matching
- X.SH SYNOPSIS
- X.nf
- X.B "int"
- X.B "wildmat(text, pattern)"
- X.B " char *text;"
- X.B " char *pattern;"
- X.fi
- X.SH DESCRIPTION
- X.I Wildmat
- Xcompares the
- X.I text
- Xagainst the
- X.I pattern
- Xand
- Xreturns non-zero if the pattern matches the text.
- XThe pattern is interpreted similar to shell filename wildcards, and not
- Xas a full regular expression such as those handled by the
- X.IR grep (1)
- Xfamily of programs or the
- X.IR regex (3)
- Xor
- X.IR regexp (3)
- Xset of routines.
- X.PP
- XThe pattern is interpreted according to the following rules:
- X.TP
- X.BI \e x
- XTurns off the special meaning of
- X.I x
- Xand matches it directly; this is used mostly before a question mark or
- Xasterisk, and is not valid inside square brackets.
- X.TP
- X.B ?
- XMatches any single character.
- X.TP
- X.B *
- XMatches any sequence of zero or more characters.
- X.TP
- X.BI [ x...y ]
- XMatches any single character specified by the set
- X.IR x...y .
- XA minus sign may be used to indicate a range of characters.
- XThat is,
- X.I [0\-5abc]
- Xis a shorthand for
- X.IR [012345abc] .
- XMore than one range may appear inside a character set;
- X.I [0-9a-zA-Z._]
- Xmatches almost all of the legal characters for a host name.
- XThe close bracket,
- X.IR ] ,
- Xmay be used if it is the first character in the set.
- XThe minus sign,
- X.IR \- ,
- Xmay be used if it is either the first or last character in the set.
- X.TP
- X.BI [^ x...y ]
- XThis matches any character
- X.I not
- Xin the set
- X.IR x...y ,
- Xwhich is interpreted as described above.
- XFor example,
- X.I [^]\-]
- Xmatches any character other than a close bracket or minus sign.
- X.SH "BUGS AND LIMITATIONS"
- XThere is no way to end a range with a close bracket.
- X.SH HISTORY
- XWritten by Rich $alz <rsalz@bbn.com> in 1986, and posted to Usenet
- Xseveral times since then, most notably in comp.sources.misc in
- XMarch, 1991.
- X.PP
- XLars Mathiesen <thorinn@diku.dk> enhanced the multi-asterisk failure
- Xmode in early 1991.
- X.PP
- XRich and Lars increased the efficiency of star patterns and reposted it
- Xto comp.sources.misc in April, 1991.
- X.PP
- XRobert Elz <kre@munnari.oz.au> added minus sign and close bracket handling
- Xin June, 1991.
- X.PP
- X.de R$
- XThis is revision \\$3, dated \\$4.
- X..
- X.R$ $Id: wildmat.3,v 1.7 91/07/05 17:50:16 rsalz Exp $
- X.SH "SEE ALSO"
- Xgrep(1), regex(3), regexp(3).
- SHAR_EOF
- $TOUCH -am 0923175591 wildmat.3 &&
- chmod 0600 wildmat.3 ||
- echo "restore of wildmat.3 failed"
- set `wc -c wildmat.3`;Wc_c=$1
- if test "$Wc_c" != "2247"; then
- echo original size 2247, current size $Wc_c
- fi
- # ============= art.c ==============
- echo "x - extracting art.c (Text)"
- sed 's/^X//' << 'SHAR_EOF' > art.c &&
- X/*
- X * Project : tin - a visual threaded usenet newsreader
- X * Module : art.c
- X * Author : R.Skrenta / I.Lea
- X * Created : 01-04-91
- X * Updated : 24-09-91
- X * Release : 1.0
- X * Notes :
- X * Copyright : (c) Copyright 1991 by Rich Skrenta & Iain Lea
- X * You may freely copy or redistribute this software,
- X * so long as there is no profit made from its use, sale
- X * trade or reproduction. You may not change this copy-
- X * right notice, and it must be included in any copy made
- X */
- X
- X#include "tin.h"
- X
- X#define HEADER_LEN 1024
- X
- Xextern int errno;
- X
- Xchar index_file[LEN+1];
- Xchar *glob_art_group;
- Xint index_file_killed = FALSE;
- Xlong last_read_article;
- X
- X
- X/*
- X * Convert a string to a long, only look at first n characters
- X */
- X
- Xlong my_atol (s, n)
- X char *s;
- X int n;
- X{
- X long ret = 0;
- X
- X while (*s && n--) {
- X if (*s >= '0' && *s <= '9')
- X ret = ret * 10 + (*s - '0');
- X else
- X return -1;
- X s++;
- X }
- X
- X return ret;
- X}
- X
- X
- X/*
- X * Construct the pointers to the basenotes of each thread
- X * arts[] contains every article in the group. inthread is
- X * set on each article that is after the first article in the
- X * thread. Articles which have been expired have their thread
- X * set to -2 (ART_EXPIRED).
- X */
- X
- Xvoid find_base ()
- X{
- X int i;
- X
- X top_base = 0;
- X
- X for (i = 0; i < top; i++)
- X if (! arts[i].inthread && arts[i].thread != ART_EXPIRED) {
- X if (top_base >= max_art)
- X expand_art ();
- X base[top_base++] = i;
- X }
- X}
- X
- X/*
- X * Count the number of non-expired and non-killed articles in arts[]
- X */
- X
- Xint num_of_arts ()
- X{
- X int sum = 0;
- X register int i;
- X
- X for (i = 0; i < top; i++) {
- X if (arts[i].thread != ART_EXPIRED && ! arts[i].tagged) {
- X sum++;
- X }
- X }
- X
- X return sum;
- X}
- X
- X/*
- X * Do we have an entry for article art?
- X */
- X
- Xint valid_artnum (art)
- X long art;
- X{
- X register int i;
- X
- X for (i = 0; i < top; i++)
- X if (arts[i].artnum == art)
- X return i;
- X
- X return -1;
- X}
- X
- X
- X/*
- X * Return TRUE if arts[] contains any expired articles
- X * (articles we have an entry for which don't have a corresponding
- X * article file in the spool directory)
- X */
- X
- Xint purge_needed ()
- X{
- X register int i;
- X
- X for (i = 0; i < top; i++)
- X if (arts[i].thread == ART_EXPIRED)
- X return TRUE;
- X
- X return FALSE;
- X}
- X
- X
- X/*
- X * Main group indexing routine. Group should be the name of the
- X * newsgroup, i.e. "comp.unix.amiga". group_path should be the
- X * same but with the .'s turned into /'s: "comp/unix/amiga"
- X *
- X * Will read any existing index, create or incrementally update
- X * the index by looking at the articles in the spool directory,
- X * and attempt to write a new index if necessary.
- X */
- X
- Xvoid index_group (group, group_path)
- X char *group;
- X char *group_path;
- X{
- X int killed = FALSE;
- X int modified = FALSE;
- X glob_art_group = group;
- X
- X#ifdef SIGTSTP
- X if (do_sigtstp) {
- X#ifdef POSIX_JOB_CONTROL
- X sigemptyset (&art_act.sa_mask);
- X art_act.sa_flags = SA_RESTART | SA_RESETHAND;
- X art_act.sa_handler = art_suspend;
- X sigaction (SIGTSTP, &art_act, 0L);
- X#else
- X signal (SIGTSTP, art_suspend);
- X#endif
- X }
- X#endif
- X
- X#ifdef SIGWINCH
- X signal (SIGWINCH, art_resize);
- X#endif
- X
- X if (! update) {
- X sprintf (msg, txt_group, group);
- X wait_message (msg);
- X }
- X
- X hash_reclaim ();
- X free_art_array ();
- X
- X if (local_index)
- X find_local_index (group);
- X else
- X sprintf (index_file, "%s/%s/%s", spooldir, group_path, INDEXDIR);
- X
- X /*
- X * load articles from index file if it exists
- X */
- X load_index ();
- X
- X /*
- X * load killed articles into arts[] because kill arts is OFF
- X */
- X if (! kill_articles && index_file_killed) {
- X index_file_killed = FALSE;
- X last_read_article = 0L;
- X }
- X
- X /*
- X * add any articles to arts[] that are new or were killed
- X */
- X modified = read_group (group, group_path);
- X
- X /*
- X * compare kill descriptions to arts[] and kill mark any that match
- X */
- X killed = kill_any_articles (group);
- X
- X if (modified || killed || purge_needed()) {
- X if (local_index) { /* writing index in home directory */
- X 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 ();
- X }
- X
- X if (local_index) {
- X set_tin_uid_gid ();
- X }
- X } else {
- X make_threads (FALSE);
- X find_base ();
- X }
- X
- X if ((modified || killed) && ! update) {
- X clear_message();
- X }
- X}
- X
- X/*
- X * Index a group. Assumes any existing index has already been
- X * loaded.
- X */
- X
- Xint read_group (group, group_path)
- X char *group;
- X char *group_path;
- X{
- X int fd;
- X long art;
- X int count;
- X int 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 count = 0;
- X
- X for (i = 0; i < top_base; i++) { /* for each article # */
- X art = base[i];
- X
- X/*
- X * Do we already have this article in our index? Change thread from
- X * -2 (ART_EXPIRED) to -1 (ART_NORMAL) if so and skip the header eating.
- X */
- X
- X if ((respnum = valid_artnum (art)) >= 0 || art <= last_read_article) {
- X arts[respnum].thread = ART_NORMAL;
- X arts[respnum].unread = ART_UNREAD;
- X continue;
- X }
- X
- X if (! modified) {
- X modified = TRUE; /* we've modified the index */
- X /* it will need to be re-written */
- X }
- X
- X if ((fd = open_header_fd (group_path, art)) < 0) {
- X continue;
- X }
- X
- X /*
- X * Add article to arts[]
- X */
- X if (top >= max_art)
- X expand_art();
- X
- X arts[top].artnum = art;
- X arts[top].thread = ART_NORMAL;
- X
- X set_article (&arts[top]);
- X
- X if (! parse_headers (fd, &arts[top])) {
- X continue;
- X }
- X close (fd);
- X last_read_article = arts[top].artnum; /* used if arts are killed */
- X top++;
- X
- X if (++count % 10 == 0 && ! update) {
- X if (display_groupname) {
- X MoveCursor (0, 0);
- X CleartoEOLN ();
- X center_line (0, TRUE, group);
- X display_groupname = FALSE;
- X }
- X sprintf (msg, txt_indexing, count);
- X wait_message (msg);
- X }
- X }
- X
- X return modified;
- X}
- X
- X
- X/*
- X * Go through the articles in arts[] and use .thread to snake threads
- X * through them. Use the subject line to construct threads. The
- X * first article in a thread should have .inthread set to FALSE, the
- X * rest TRUE. Only do unexprired articles we haven't visited yet
- X * (arts[].thread == -1 ART_NORMAL).
- X */
- X
- Xvoid make_threads (rethread)
- X int rethread;
- X{
- X register int i;
- X register int j;
- X
- X /*
- X * .thread & .inthread need to be reset if re-threading arts[]
- X */
- X if (rethread) {
- X for (i=0 ; i < top ; i++) {
- X arts[i].thread = ART_NORMAL;
- X arts[i].inthread = FALSE;
- X }
- X }
- X
- X switch (sort_art_type) {
- X case SORT_BY_NOTHING: /* don't sort at all */
- X qsort (arts, top, sizeof (struct header), artnum_comp);
- X break;
- X case SORT_BY_SUBJ_DESCEND:
- X case SORT_BY_SUBJ_ASCEND:
- X qsort (arts, top, sizeof (struct header), subj_comp);
- X break;
- X case SORT_BY_FROM_DESCEND:
- X case SORT_BY_FROM_ASCEND:
- X qsort (arts, top, sizeof (struct header), from_comp);
- X break;
- X case SORT_BY_DATE_DESCEND:
- X case SORT_BY_DATE_ASCEND:
- X qsort (arts, top, sizeof (struct header), date_comp);
- X break;
- X default:
- X break;
- X }
- X
- X for (i = 0; i < top; i++) {
- X if (arts[i].thread == ART_NORMAL) {
- X for (j = i+1; j < top; j++) {
- X if (arts[j].thread != ART_EXPIRED &&
- X ((arts[i].subject == arts[j].subject) ||
- X ((arts[i].part || arts[i].patch) &&
- X arts[i].archive == arts[j].archive))) {
- X arts[i].thread = j;
- X arts[j].inthread = TRUE;
- X break;
- X }
- X }
- X }
- X }
- X}
- X
- X/*
- X * Return a pointer into s eliminating any leading Re:'s. Example:
- X *
- X * Re: Reorganization of misc.jobs
- X * ^ ^
- X */
- X
- Xchar *eat_re (s)
- X char *s;
- X{
- X
- X while (*s == 'r' || *s == 'R') {
- X if ((*(s+1) == 'e' || *(s+1) == 'E')) {
- X if (*(s+2) == ':')
- X s += 3;
- X else if (*(s+2) == '^' && isdigit(*(s+3)) && *(s+4) == ':')
- X s += 5; /* hurray nn */
- X else
- X break;
- X } else
- X break;
- X while (*s == ' ')
- X s++;
- X }
- X
- X return s;
- X}
- X
- X/*
- X * Hash the subjects (after eating the Re's off) for a quicker
- X * thread search later. We store the hashes for subjects in the
- X * index file for speed.
- X */
- X
- Xlong hash_s (s)
- X char *s;
- X{
- X long h = 0;
- X unsigned char *t = (unsigned char *) s;
- X
- X while (*t)
- X h = h * 64 + *t++;
- X
- X return h;
- X}
- X
- X
- Xint parse_headers (fd, h)
- X int fd;
- X struct header *h;
- X{
- X char buf[HEADER_LEN];
- X char buf2[HEADER_LEN];
- X char *ptr, *ptrline, *s;
- X int n = 0, len = 0, lineno = 0;
- X int flag;
- X int got_subject = FALSE;
- X int got_from = FALSE;
- X int got_date = FALSE;
- X int got_archive = FALSE;
- X
- X if ((n = read (fd, buf, HEADER_LEN)) <= 0) {
- X return FALSE;
- X }
- X
- X buf[n-1] = '\0';
- X
- X ptr = buf;
- X
- X while (1) {
- X for (ptrline = ptr; *ptr && *ptr != '\n'; ptr++) {
- X if (((*ptr) & 0x7F) < 32) {
- X *ptr = ' ';
- X }
- X }
- X flag = *ptr;
- X *ptr++ = '\0';
- X lineno++;
- X
- X if (! got_from && strncmp(ptrline, "From: ", 6) == 0) {
- X my_strncpy(buf2, ptrline+6, HEADER_LEN);
- X h->from = hash_str (buf2);
- X got_from = TRUE;
- X } else if (! got_subject && strncmp(ptrline, "Subject: ", 9) == 0) {
- X my_strncpy (buf2, ptrline+9, HEADER_LEN);
- X s = eat_re (buf2);
- X h->subject = hash_str (eat_re (s));
- X got_subject = TRUE;
- X } else if (! got_date && strncmp(ptrline, "Date: ", 6) == 0) {
- X my_strncpy (buf2, ptrline+6, HEADER_LEN);
- X parse_date (buf2 ,h->date);
- X got_date = TRUE;
- X } else if (strncmp(ptrline, "Archive-name: ", 14) == 0) {
- X if ((s = (char *) strchr (ptrline+14, '/')) != NULL) {
- X my_strncpy(buf2, ptrline+14, HEADER_LEN);
- 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
- X/*
- X * Write out an index file. Write the group name first so if
- X * local indexing is done we can disambiguate between group name
- X * hash collisions by looking at the index file.
- X *
- X * NOTE: check out the add_string routine in hashstr.c to
- X * understand what *iptr is doing in this routine.
- X */
- X
- Xvoid dump_index (group, killed)
- X char *group;
- X int killed;
- X{
- X char nam[LEN+1];
- X FILE *fp;
- X int *iptr;
- X int realnum;
- X register int i;
- X
- X sprintf (nam, "%s.%d", index_file, getpid());
- X if ((fp = fopen (nam, "w")) == NULL) {
- X error_message (txt_cannot_open, nam);
- X return;
- X }
- X
- X /*
- X * dump group header info.
- X */
- X if (sort_art_type != SORT_BY_NOTHING) {
- X qsort (arts, top, sizeof (struct header), artnum_comp);
- X }
- X fprintf(fp, "%s\n", group);
- X fprintf(fp, "%d\n", num_of_arts ());
- X if (last_read_article > arts[top-1].artnum) {
- X fprintf(fp, "%ld\n", last_read_article);
- X } else {
- X fprintf(fp, "%ld\n", arts[top-1].artnum);
- X }
- X if (index_file_killed && killed) {
- X fprintf (fp, "KILLED\n");
- X } else {
- X fprintf (fp, "COMPLETE\n");
- X }
- X
- X /*
- X * dump articles
- X */
- X realnum = 0;
- X for (i = 0; i < top; i++) {
- X if (arts[i].thread != ART_EXPIRED && ! arts[i].tagged) {
- X debug_print_header (&arts[i]);
- X
- X fprintf(fp, "%ld\n", arts[i].artnum);
- X
- X iptr = (int *) arts[i].subject;
- X iptr--;
- X
- X if (! arts[i].subject) {
- X fprintf(fp, " \n");
- X } else if (*iptr < 0 || *iptr > top) {
- X fprintf(fp, " %s\n", arts[i].subject);
- X *iptr = realnum;
- X/*
- X } else if (arts[*iptr].tagged) {
- X fprintf(fp, " %s\n", arts[i].subject);
- X *iptr = realnum;
- X } else if (killed && *iptr == i) {
- X*/
- X } else if (killed || *iptr == i) {
- X fprintf(fp, " %s\n", arts[i].subject);
- X } else {
- X fprintf(fp, "%%%d\n", *iptr);
- X }
- X
- X iptr = (int *) arts[i].from;
- X iptr--;
- X
- X if (! arts[i].from) {
- X fprintf (fp, " \n");
- X } else if (*iptr < 0 || *iptr > top) {
- X fprintf (fp, " %s\n", arts[i].from);
- X *iptr = realnum;
- X/*
- X } else if (arts[*iptr].tagged) {
- X fprintf(fp, " %s\n", arts[i].from);
- X *iptr = realnum;
- X } else if (killed && *iptr == i) {
- X*/
- X } else if (killed || *iptr == i) {
- X fprintf(fp, " %s\n", arts[i].from);
- X } else {
- X fprintf(fp, "%%%d\n", *iptr);
- X }
- X
- X fprintf (fp, "%s\n", arts[i].date);
- X
- X iptr = (int *) arts[i].archive;
- X iptr--;
- X
- X if (! arts[i].archive) {
- X fprintf (fp, "\n");
- X } else if (*iptr < 0 || *iptr > top) {
- X fprintf (fp, " %s\n", arts[i].archive);
- X *iptr = realnum;
- X/*
- X } else if (arts[*iptr].tagged) {
- X fprintf (fp, " %s\n", arts[i].archive);
- X *iptr = realnum;
- X*/
- X } else if (arts[i].part || arts[i].patch) {
- X/*
- X if (killed && *iptr == i) {
- X*/
- X if (killed || *iptr == i) {
- X fprintf(fp, " %s\n", arts[i].archive);
- X } else {
- X fprintf (fp, "%%%d\n", *iptr);
- X }
- X } else {
- X fprintf (fp, "\n");
- X }
- X
- X if (! arts[i].part) {
- X fprintf (fp, " \n");
- X } else {
- X fprintf (fp, "%s\n", arts[i].part);
- X }
- X
- X if (! arts[i].patch) {
- X fprintf (fp, " \n");
- X } else {
- X fprintf (fp, "%s\n", arts[i].patch);
- X }
- X
- X realnum++;
- X }
- X }
- X fclose (fp);
- X chmod (index_file, 0644);
- X rename_file (nam, index_file);
- X if (debug) {
- X sprintf (msg, "/bin/cp %s INDEX", index_file);
- X system (msg);
- X }
- X}
- X
- X/*
- X * strncpy that stops at a newline and null terminates
- X */
- X
- Xvoid my_strncpy(p, q, n)
- X char *p;
- X char *q;
- X int n;
- X{
- X while (n--) {
- X if (! *q || *q == '\n')
- X break;
- X *p++ = *q++;
- X }
- X *p = '\0';
- X}
- X
- X/*
- X * Read in an index file.
- X *
- X * index file header
- X * 1. newsgroup name (ie. alt.sources)
- X * 2. number of articles (ie. 26)
- X * 3. number of last read article (ie. 210)
- X * 4. Is this a complete/killed index file (ie. COMPLETE/KILLED)
- X * index file record
- X * 1. article number (ie. 183) [mandatory]
- X * 2. Subject: line (ie. Which newsreader?) [mandatory]
- X * 3. From: line (ie. iain@norisc) [mandatory]
- X * 4. Date: of posting (ie. 911231125959) [mandatory]
- X * 5. Archive: name (ie. compiler) [optional]
- X * 6. Part number of Archive: name (ie. 01) [optional]
- X * 7. Patch number of Archive: name (ie. 01) [optional]
- X */
- X
- Xint load_index ()
- X{
- X int error = 0;
- X int i, n;
- X char buf[LEN+1], *p;
- X FILE *fp;
- X
- X top = 0;
- X last_read_article = 0L;
- X
- X if ((fp = fopen (index_file, "r")) == NULL) {
- X return FALSE;
- X }
- X
- X debug_print_comment ("*** LOADING ***");
- X
- X /*
- X * load header - discard group name, num. of arts in index file after any arts were killed
- X */
- X if (fgets(buf, 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:
- 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 * Date:
- X */
- X if (fgets(buf, sizeof buf, fp) == NULL) {
- X error = 10;
- X goto corrupt_index;
- X }
- X
- X buf[strlen (buf)-1] = '\0';
- X my_strncpy (arts[top].date, buf, 12);
- X
- X /*
- X * Archive-name:
- X */
- X if (fgets(buf, sizeof buf, fp) == NULL) {
- X error = 11;
- X goto corrupt_index;
- X }
- X
- X if (buf[0] == '\n') {
- X arts[top].archive = (char *) 0;
- X } else if (buf[0] == '%') {
- X n = atoi (&buf[1]);
- X if (n > top || n < 0) {
- X error = 12;
- X goto corrupt_index;
- X }
- X arts[top].archive = arts[n].archive;
- X } else if (buf[0] == ' ') {
- X for (p = &buf[1]; *p && *p != '\n' ; p++)
- X continue;
- X *p = '\0';
- X arts[top].archive = hash_str (&buf[1]);
- X } else {
- X error = 13;
- X goto corrupt_index;
- X }
- X
- X /*
- X * part no.
- X */
- X if (fgets(buf, sizeof buf, fp) == NULL) {
- X error = 14;
- X goto corrupt_index;
- X }
- X
- X if (buf[0] != ' ') {
- X buf[strlen (buf)-1] = '\0';
- X arts[top].part = str_dup (buf);
- X }
- X
- X /*
- X * patch no.
- X */
- X if (fgets(buf, sizeof buf, fp) == NULL) {
- X error = 15;
- X goto corrupt_index;
- X }
- X
- X if (buf[0] != ' ') {
- X buf[strlen (buf)-1] = '\0';
- X arts[top].patch = str_dup (buf);
- X }
- X
- X debug_print_header (&arts[top]);
- X }
- X
- X fclose(fp);
- X return TRUE;
- X
- Xcorrupt_index:
- X if (! update) {
- X sprintf (msg, txt_corrupt_index, index_file, error, top);
- X error_message (msg, "");
- X }
- X
- X if (debug) {
- X sprintf (msg, "cp %s INDEX.BAD", index_file);
- X system (msg);
- X }
- X
- X unlink (index_file);
- X top = 0;
- X return FALSE;
- X}
- X
- X
- X/*
- X * Look in the local $HOME/RCDIR/INDEXDIR (or wherever) directory for the
- X * index file for the given group. Hashing the group name gets
- X * a number. See if that #.1 file exists; if so, read first line.
- X * Group we want? If no, try #.2. Repeat until no such file or
- X * we find an existing file that matches our group.
- X */
- X
- Xvoid find_local_index (group)
- X char *group;
- X{
- X unsigned long h;
- X static char buf[LEN+1];
- X int i;
- X char *p;
- X FILE *fp;
- X
- X h = hash_groupname (group);
- X
- X i = 1;
- X while (1) {
- X sprintf(index_file, "%s/%lu.%d", indexdir, h, i);
- X
- X if ((fp = fopen(index_file, "r")) == NULL) {
- X return;
- X }
- X
- X if (fgets(buf, 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
- X/*
- X * Run the index file updater only for the groups we've loaded.
- X */
- X
- Xvoid do_update()
- X{
- X int i, j;
- X char group_path[LEN+1];
- X char *p;
- X long epoch;
- X
- X if (verbose) {
- X time (&epoch);
- X printf ("%s", ctime (&epoch));
- X fflush (stdout);
- X }
- X
- X for (i = 0; i < local_top; i++) {
- X strcpy(group_path, active[my_group[i]].name);
- X for (p = group_path; *p; p++) {
- X if (*p == '.') {
- X *p = '/';
- X }
- X }
- X if (verbose) {
- X printf ("%s %s\n", (catchup ? "Catchup" : "Updating"),
- X active[my_group[i]].name);
- X fflush (stdout);
- X }
- X index_group (active[my_group[i]].name, group_path);
- X if (catchup) {
- X for (j = 0; j < top; j++) {
- X arts[j].unread = ART_READ;
- X }
- X update_newsrc (active[my_group[i]].name, my_group[i], FALSE);
- X }
- X }
- X
- X if (verbose) {
- X time (&epoch);
- X printf ("%s", ctime (&epoch));
- X fflush (stdout);
- X }
- X}
- X
- X/*
- X * Save any new articles to savedir and mark arts read and mail user
- X * and inform how many arts in which groups were saved.
- X */
- X
- Xvoid save_any_news ()
- X{
- X char buf[LEN], log[LEN], *p;
- X char group_path[LEN];
- X extern FILE *note_fp;
- X FILE *fp, *fp_log;
- X int i, j, print_group;
- X int log_opened = TRUE;
- X int saved_arts = 0;
- X int saved_groups = 0;
- X long epoch;
- X
- X sprintf (log, "%s/log", rcdir);
- X if ((fp_log = fopen (log, "w")) == NULL) {
- X error_message (txt_cannot_open, log);
- X fp_log = stdout;
- X verbose = FALSE;
- X log_opened = FALSE;
- X }
- X
- X time (&epoch);
- X fprintf (fp_log, "To: %s\r\n", userid);
- X fprintf (fp_log, "Subject: NEWS LOG %s\r\n", ctime (&epoch));
- X
- X for (i = 0; i < local_top; i++) {
- X strcpy (group_path, active[my_group[i]].name);
- X for (p = group_path; *p; p++) {
- X if (*p == '.') {
- X *p = '/';
- X }
- X }
- X
- X index_group (active[my_group[i]].name, group_path);
- X read_newsrc_line (active[my_group[i]].name);
- X print_group = TRUE;
- X
- X for (j = 0; j < top; j++) {
- X if (arts[j].unread == ART_UNREAD) {
- X if (print_group) {
- X sprintf (msg, "Saving %s...\r\n", active[my_group[i]].name);
- X fprintf (fp_log, "%s", msg);
- X if (verbose) {
- X printf ("%s", msg);
- X }
- X print_group = FALSE;
- X saved_groups++;
- X sprintf (buf, "%s/dummy", group_path);
- X create_path (buf);
- X }
- X sprintf (msg, "[%5ld] %s\r\n", arts[j].artnum, arts[j].subject);
- X fprintf (fp_log, "%s", msg);
- X if (verbose) {
- X printf ("%s", msg);
- X }
- X saved_arts++;
- X
- X sprintf (buf, "%s/%s/%ld", savedir, group_path, arts[j].artnum);
- X if ((fp = fopen (buf, "w")) == NULL) {
- X fprintf (fp_log, txt_cannot_open, buf);
- X error_message (txt_cannot_open, buf);
- X continue;
- X }
- X
- X open_note (arts[j].artnum, group_path);
- X
- X fseek (note_fp, 0L, 0);
- X
- X copy_fp (note_fp, fp, (char *) 0);
- X
- X note_cleanup ();
- X
- X fclose (fp);
- X }
- X }
- 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 sprintf (msg, "\r\nSaved %d articles from %d groups\r\n", saved_arts, saved_groups);
- X fprintf (fp_log, "%s", msg);
- X if (verbose) {
- X printf ("%s", msg);
- X }
- X
- X if (log_opened) {
- X fclose (fp_log);
- X if (verbose) {
- X printf ("Mailing log to %s\r\n", userid);
- X }
- X sprintf (buf, "%s \"%s\" < %s", mailer, userid, log);
- X if (! invoke_cmd (buf)) {
- X error_message (txt_command_failed_s, buf);
- X }
- X }
- X}
- X
- X/*
- X * reload index after any articles have been killed
- X */
- X
- Xvoid reload_index_file (group, killed)
- X char *group;
- X int killed;
- X{
- X char group_path[LEN+1];
- X char *p;
- X
- 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 ("Killing...");
- X }
- X index_file_killed = TRUE;
- X setup_base (group, group_path);
- X dump_index (group, killed);
- X load_index ();
- X } else {
- X if (! update) {
- X wait_message ("Unkilling...");
- X }
- X if (local_index) {
- X find_local_index (group);
- X } else {
- X sprintf (index_file, "%s/%s/%s", spooldir, group_path, INDEXDIR);
- X }
- X
- X unlink (index_file); /* delete index file */
- X
- X index_file_killed = FALSE;
- X last_read_article = 0L;
- X
- X if (read_group (group, group_path)) {
- X dump_index (group, killed);
- X }
- X }
- X
- X make_threads (TRUE);
- X find_base ();
- X
- X if (local_index) {
- X set_tin_uid_gid ();
- X }
- X
- X return;
- X}
- X
- X/*
- X * convert date from "24 Jul 91 12:59:59" to "910724125959"
- X */
- X
- Xchar *parse_date (date, str)
- X char *date;
- X char *str;
- X{
- X char buf[4];
- X int i = 3;
- X
- X if (date[1] == ' ') { /* ie. "2 Aug..." instead of "12 Aug... */
- X str[4] = '0'; /* day */
- X str[5] = date[0];
- X i = 2;
- X } else {
- X str[4] = date[0]; /* day */
- X str[5] = date[1];
- X }
- X
- X buf[0] = date[i++]; /* month in Jan,Feb,.. form */
- X buf[1] = date[i++];
- X buf[2] = date[i++];
- X buf[3] = '\0';
- X
- X i++;
- X
- X str[0] = date[i++]; /* year */
- X str[1] = date[i++];
- X
- X i++;
- X
- X if (strcmp (buf, "Jan") == 0) { /* convert Jan to 01 etc */
- X str[2] = '0';
- X str[3] = '1';
- X } else if (strcmp (buf, "Feb") == 0) {
- X str[2] = '0';
- X str[3] = '2';
- X } else if (strcmp (buf, "Mar") == 0) {
- X str[2] = '0';
- X str[3] = '3';
- X } else if (strcmp (buf, "Apr") == 0) {
- X str[2] = '0';
- X str[3] = '4';
- X } else if (strcmp (buf, "May") == 0) {
- X str[2] = '0';
- X str[3] = '5';
- X } else if (strcmp (buf, "Jun") == 0) {
- X str[2] = '0';
- X str[3] = '6';
- X } else if (strcmp (buf, "Jul") == 0) {
- X str[2] = '0';
- X str[3] = '7';
- X } else if (strcmp (buf, "Aug") == 0) {
- X str[2] = '0';
- X str[3] = '8';
- X } else if (strcmp (buf, "Sep") == 0) {
- X str[2] = '0';
- X str[3] = '9';
- X } else if (strcmp (buf, "Oct") == 0) {
- X str[2] = '1';
- X str[3] = '0';
- X } else if (strcmp (buf, "Nov") == 0) {
- X str[2] = '1';
- X str[3] = '1';
- X } else if (strcmp (buf, "Dec") == 0) {
- X str[2] = '1';
- X str[3] = '2';
- X } else {
- X str[2] = '0';
- X str[3] = '0';
- X }
- X
- X str[6] = date[i++]; /* hour */
- X str[7] = date[i++];
- X
- X i++;
- X
- X str[8] = date[i++]; /* minutes */
- X str[9] = date[i++];
- X
- X i++;
- X
- X str[10] = date[i++]; /* seconds */
- X str[11] = date[i++];
- X
- X str[12] = '\0'; /* terminate string */
- X
- X return (str);
- X}
- X
- X
- Xint artnum_comp (p1, p2)
- X char *p1;
- X char *p2;
- X{
- X struct header *s1 = (struct header *) p1;
- X struct header *s2 = (struct header *) 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
- X
- Xint subj_comp (p1, p2)
- X char *p1;
- X char *p2;
- X{
- X struct header *s1 = (struct header *) p1;
- X struct header *s2 = (struct header *) p2;
- X
- X /* s1->subject less than s2->subject */
- X if (strcmp (s1->subject, s2->subject) < 0) {
- X return (sort_art_type == SORT_BY_SUBJ_DESCEND ? -1 : 1);
- X }
- X /* s1->subject greater than s2->subject */
- X if (strcmp (s1->subject, s2->subject) > 0) {
- X return (sort_art_type == SORT_BY_SUBJ_DESCEND ? 1 : -1);
- X }
- X return 0;
- X}
- X
- X
- Xint from_comp (p1, p2)
- X char *p1;
- X char *p2;
- X{
- X struct header *s1 = (struct header *) p1;
- X struct header *s2 = (struct header *) p2;
- X
- X /* s1->from less than s2->from */
- X if (strcmp (s1->from, s2->from) < 0) {
- X return (sort_art_type == SORT_BY_FROM_DESCEND ? -1 : 1);
- X }
- X /* s1->from greater than s2->from */
- X if (strcmp (s1->from, s2->from) > 0) {
- X return (sort_art_type == SORT_BY_FROM_DESCEND ? 1 : -1);
- X }
- X return 0;
- X}
- X
- X
- Xint date_comp (p1, p2)
- X char *p1;
- X char *p2;
- X{
- X struct header *s1 = (struct header *) p1;
- X struct header *s2 = (struct header *) p2;
- X
- X /* s1->date less than s2->date */
- X if (strcmp (s1->date, s2->date) < 0) {
- X return (sort_art_type == SORT_BY_DATE_DESCEND ? -1 : 1);
- X }
- X /* s1->date greater than s2->date */
- X if (strcmp (s1->date, s2->date) > 0) {
- X return (sort_art_type == SORT_BY_DATE_DESCEND ? 1 : -1);
- X }
- X return 0;
- X}
- X
- X
- Xvoid set_article (art)
- X struct header *art;
- X{
- X art->subject = (char *) 0;
- X art->from = (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->tagged = FALSE;
- X}
- SHAR_EOF
- $TOUCH -am 0924081391 art.c &&
- chmod 0600 art.c ||
- echo "restore of art.c failed"
- set `wc -c art.c`;Wc_c=$1
- if test "$Wc_c" != "26620"; then
- echo original size 26620, current size $Wc_c
- fi
- # ============= curses.c ==============
- echo "x - extracting curses.c (Text)"
- sed 's/^X//' << 'SHAR_EOF' > curses.c &&
- X/*
- X * curses.c
- X */
- X
- X/*
- X * This is a screen management library borrowed with permission from the
- X * Elm mail system (a great mailer--I highly recommend it!).
- X *
- X * I've hacked this library to only provide what Tass needs.
- X *
- X * Original copyright follows:
- X */
- X
- X/*******************************************************************************
- X * The Elm Mail System - $Revision: 2.1 $ $State: Exp $
- X *
- X * Copyright (c) 1986 Dave Taylor
- X ******************************************************************************/
- X
- X#include <stdio.h>
- X#include <curses.h>
- X#include <sys/ioctl.h>
- X
- X#ifdef TRUE
- X#undef TRUE
- X#define TRUE 1
- X#endif
- X
- X#ifdef FALSE
- X#undef FALSE
- X#define FALSE 0
- X#endif
- X
- X#define BACKSPACE '\b'
- X#define VERY_LONG_STRING 2500
- X
- Xint LINES=23;
- Xint COLS=80;
- X
- Xint inverse_okay = TRUE;
- X
- X#ifdef BSD
- X# ifndef BSD4_1
- X# include <sgtty.h>
- X# else
- X# include <termio.h>
- X# endif
- X#else
- X# ifndef SYSV
- X# include <termio.h>
- X# endif
- X#endif
- X
- X
- X#include <ctype.h>
- X
- X/*
- X#ifdef BSD
- X#undef tolower
- X#endif
- X*/
- X
- X#define TTYIN 0
- X
- X#ifdef SHORTNAMES
- X# define _clearinverse _clrinv
- X# define _cleartoeoln _clrtoeoln
- X# define _cleartoeos _clr2eos
- X#endif
- X
- X#ifndef BSD
- Xstruct termio _raw_tty,
- X _original_tty;
- X#else
- X#define TCGETA TIOCGETP
- X#define TCSETAW TIOCSETP
- X
- Xstruct sgttyb _raw_tty,
- X _original_tty;
- X#endif
- X
- Xstatic int _inraw = 0; /* are we IN rawmode? */
- X
- X#define DEFAULT_LINES_ON_TERMINAL 24
- X#define DEFAULT_COLUMNS_ON_TERMINAL 80
- X
- Xstatic
- Xchar *_clearscreen, *_moveto, *_cleartoeoln, *_cleartoeos,
- X *_setinverse, *_clearinverse, *_setunderline, *_clearunderline;
- X
- Xstatic
- Xint _lines,_columns;
- X
- Xstatic char _terminal[1024]; /* Storage for terminal entry */
- Xstatic char _capabilities[1024]; /* String for cursor motion */
- X
- Xstatic char *ptr = _capabilities; /* for buffering */
- X
- Xint outchar(); /* char output for tputs */
- Xchar *tgetstr(), /* Get termcap capability */
- X *tgoto(); /* and the goto stuff */
- X
- Xint InitScreen()
- X{
- X int tgetent(); /* get termcap entry */
- X char termname[40], *p;
- X char *strcpy(), *getenv();
- X
- X if ((p = getenv("TERM")) == NULL) {
- X fprintf(stderr,
- X "TERM variable not set; Tass requires screen capabilities\n");
- X return(FALSE);
- X }
- X if (strcpy(termname, p) == NULL) {
- X fprintf(stderr,"Can't get TERM variable\n");
- X return(FALSE);
- X }
- X if (tgetent(_terminal, termname) != 1) {
- X fprintf(stderr,"Can't get entry for TERM\n");
- 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
- X if (!_clearscreen) {
- X fprintf(stderr,
- X "Terminal must have clearscreen (cl) capability\n");
- X return(FALSE);
- X }
- X if (!_moveto) {
- X fprintf(stderr,
- X "Terminal must have cursor motion (cm)\n");
- X return(FALSE);
- X }
- X if (!_cleartoeoln) {
- X fprintf(stderr,
- X "Terminal must have clear to end-of-line (ce)\n");
- X return(FALSE);
- X }
- X if (!_cleartoeos) {
- X fprintf(stderr,
- X "Terminal must have clear to end-of-screen (cd)\n");
- 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
- Xvoid ScreenSize(num_lines, num_columns)
- X int *num_lines, *num_columns;
- X{
- X /** returns the number of lines and columns on the display. **/
- X
- 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}
- X
- Xvoid ClearScreen()
- X{
- X /* clear the screen: returns -1 if not capable */
- X
- X tputs(_clearscreen, 1, outchar);
- X fflush(stdout); /* clear the output buffer */
- X}
- X
- Xvoid MoveCursor(row, col)
- Xint row, col;
- X{
- X /** move cursor to the specified row column on the screen.
- X 0,0 is the top left! **/
- X
- X char *stuff, *tgoto();
- X
- X stuff = tgoto(_moveto, col, row);
- X tputs(stuff, 1, outchar);
- X fflush(stdout);
- X}
- X
- Xvoid CleartoEOLN()
- X{
- X /** clear to end of line **/
- X
- X tputs(_cleartoeoln, 1, outchar);
- X fflush(stdout); /* clear the output buffer */
- X}
- X
- Xvoid CleartoEOS()
- X{
- X /** clear to end of screen **/
- X
- X tputs(_cleartoeos, 1, outchar);
- X fflush(stdout); /* clear the output buffer */
- X}
- X
- X
- Xvoid StartInverse()
- X{
- X /** set inverse video mode **/
- X
- X if (_setinverse && inverse_okay)
- X tputs(_setinverse, 1, outchar);
- X fflush(stdout);
- X}
- X
- X
- Xvoid EndInverse()
- X{
- X /** compliment of startinverse **/
- X
- X if (_clearinverse && inverse_okay)
- X tputs(_clearinverse, 1, outchar);
- X fflush(stdout);
- X}
- X
- X
- Xint RawState()
- X{
- X /** returns either 1 or 0, for ON or OFF **/
- X
- X return( _inraw );
- X}
- X
- SHAR_EOF
- echo "End of tin1.02 part 2"
- echo "File curses.c is continued in part 3"
- echo "3" > shar3_seq_.tmp
- exit 0
-
- exit 0 # Just in case...
- --
- Kent Landfield INTERNET: kent@sparky.IMD.Sterling.COM
- Sterling Software, IMD UUCP: uunet!sparky!kent
- Phone: (402) 291-8300 FAX: (402) 291-4362
- Please send comp.sources.misc-related mail to kent@uunet.uu.net.
-