rsalz@bbn.com (Rich Salz) (12/01/90)
Submitted-by: Wayne Davison <davison@dri.com> Posting-number: Volume 23, Issue 64 Archive-name: trn/part05 ---- Cut Here and unpack ---- #!/bin/sh # this is part 5 of a multipart archive # do not concatenate these parts, unpack them in order with /bin/sh # file art.c continued # CurArch=5 if test ! -r s2_seq_.tmp then echo "Please unpack part 1 first!" exit 1; fi ( read Scheck if test "$Scheck" != $CurArch then echo "Please unpack part $Scheck next!" exit 1; else exit 0; fi ) < s2_seq_.tmp || exit 1 echo "x - Continuing file art.c" sed 's/^X//' << 'SHAR_EOF' >> art.c X FLUSH; X#endif X return TRUE; X } X if (artpos == innersearch) { /* just got onto page? */ X isrchline = artline; /* remember first line after */ X highlight = artline - 1; X#ifdef DEBUGGING X if (debug & DEB_INNERSRCH) X printf("There it is %ld = %ld, %d @ %d\n",(long)artpos, X (long)innersearch,hide_everything,highlight) FLUSH; X#endif X if (hide_everything) { /* forced refresh? */ X topline = highlight - gline; X if (topline < -1) X topline = -1; X return FALSE; /* let refresh do it all */ X } X } X#ifdef DEBUGGING X if (debug & DEB_INNERSRCH) X printf("Not far enough? %d <? %d + %d\n",artline,isrchline,gline) X FLUSH; X#endif X if (artline < isrchline + gline) { X return TRUE; X } X return FALSE; X} X#endif SHAR_EOF echo "File art.c is complete" chmod 0660 art.c || echo "restore of art.c fails" echo "x - extracting art.h (Text)" sed 's/^X//' << 'SHAR_EOF' > art.h && X/* $Header: art.h,v 4.3 85/05/01 11:35:29 lwall Exp $ X * X * $Log: art.h,v $ X * Revision 4.3 85/05/01 11:35:29 lwall X * Baseline for release with 4.3bsd. X * X */ X X/* do_article() return values */ X X#define DA_NORM 0 X#define DA_RAISE 1 X#define DA_CLEAN 2 X#define DA_TOEND 3 X Xvoid art_init(); Xint do_article(); Xint page_switch(); Xbool innermore(); SHAR_EOF chmod 0660 art.h || echo "restore of art.h fails" echo "x - extracting artio.c (Text)" sed 's/^X//' << 'SHAR_EOF' > artio.c && X/* $Header: artio.c,v 4.3.3.1 90/07/21 20:11:03 davison Trn $ X * X * $Log: artio.c,v $ X * Revision 4.3.3.1 90/07/21 20:11:03 davison X * Initial Trn Release X * X * Revision 4.3.2.5 90/03/22 23:04:04 sob X * Fixes provided by Wayne Davison <drivax!davison> X * X * Revision 4.3.2.4 89/11/27 01:29:57 sob X * Altered NNTP code per ideas suggested by Bela Lubkin X * <filbo@gorn.santa-cruz.ca.us> X * X * Revision 4.3.2.3 89/11/26 22:55:31 sob X * Add nntpopen() and nntpclose() routines to cut down on size of rrn X * X * Revision 4.3.2.2 89/11/08 01:17:12 sob X * Added changes to insure that this will compile for RN or RRN with no X * changes to the source code. X * X * Revision 4.3.2.1 89/11/06 00:07:25 sob X * Added RRN support from NNTP 1.5 X * X * Revision 4.3 85/05/01 11:35:39 lwall X * Baseline for release with 4.3bsd. X * X */ X X#include "EXTERN.h" X#include "common.h" X#ifdef SERVER X#include "server.h" X#endif X#include "INTERN.h" X#include "artio.h" X Xvoid Xartio_init() X{ X ; X} X X/* open an article, unless it's already open */ X XFILE * Xartopen(artnum) XART_NUM artnum; X{ X#ifdef SERVER X nntpopen(artnum,GET_ARTICLE); X#else X char artname[32]; /* filename of current article */ X X if (artnum < 1) X return Nullfp; X if (openart == artnum) { /* this article is already open? */ X fseek(artfp,0L,0); /* just get to the beginning */ X return artfp; /* and say we succeeded */ X } X if (artfp != Nullfp) { /* it was somebody else? */ X fclose(artfp); /* put them out of their misery */ X openart = 0; /* and remember them no more */ X } X sprintf(artname,"%ld",(long)artnum); X /* produce the name of the article */ X if (artfp = fopen(artname,"r")) /* if we can open it */ X openart = artnum; /* remember what we did here */ X#endif /* SERVER */ X#ifdef LINKART X { X char tmpbuf[256]; X char *s; X X if (fstat(artfp->_file,&filestat)) X return artfp; X if (filestat.st_size < (sizeof tmpbuf)) { X fgets(tmpbuf,(sizeof tmpbuf),artfp); X if (*tmpbuf == '/') { /* is a "link" to another article */ X fclose(artfp); X if (s=index(tmpbuf,'\n')) X *s = '\0'; X if (!(artfp = fopen(tmpbuf,"r"))) X openart = 0; X else { X if (*linkartname) X free(linkartname); X linkartname = savestr(tmpbuf); X } X } X else X fseek(artfp,0L,0); /* get back to the beginning */ X } X } X#endif X return artfp; /* and return either fp or NULL */ X} X X#ifdef SERVER Xstatic long our_pid; X XFILE * Xnntpopen(artnum,function) XART_NUM artnum; XART_PART function; X{ X char ser_line[256]; X char artname[32]; /* filename of current article */ X if (our_pid == 0) X our_pid = getpid(); X if (artnum < 1) X return Nullfp; X if ((openart == artnum) && (openpart >= function)) X { /* this article is already open? */ X fseek(artfp,0L,0); /* just get to the beginning */ X return artfp; /* and say we succeeded */ X } X if (artfp != Nullfp) { /* it was somebody else? */ X fclose(artfp); /* put them out of their misery */ X nntpclose(); X openart = 0; /* and remember them no more */ X } X sprintf(artname,"/tmp/rrn%ld.%ld", (long) artnum, our_pid); X artfp = fopen(artname, "w+"); /* create the temporary article */ X if (artfp == Nullfp) { X UNLINK(artname); X return Nullfp; X } X switch (function){ X case GET_STATUS: X function = GET_HEADER; /* fall through */ X case GET_HEADER: X sprintf(ser_line, "HEAD %ld", (long)artnum); X break; X case GET_ARTICLE: X sprintf(ser_line, "ARTICLE %ld", (long)artnum); X break; X } X put_server(ser_line); /* ask the server for the article */ X if (get_server(ser_line, sizeof(ser_line)) < 0) { X fprintf(stderr, "rrn: Unexpected close of server socket.\n"); X finalize(1); X } X if (*ser_line != CHAR_OK) { /* and get it's reaction */ X fclose(artfp); X artfp = Nullfp; X UNLINK(artname); X errno = ENOENT; /* Simulate file-not-found */ X return Nullfp; X } X X for (;;) { X if (get_server(ser_line, sizeof(ser_line)) < 0) { X fprintf(stderr, "rrn: Unexpected close of server socket.\n"); X finalize(1); X } X if (ser_line[0] == '.' && ser_line[1] == '\0') X break; X fputs((ser_line[0] == '.' ? ser_line + 1 : ser_line), artfp); X putc('\n', artfp); X } X openpart = function; X if (function == GET_HEADER) X putc('\n', artfp); /* req'd blank line after header */ X fseek(artfp, 0L, 0); /* Then get back to the start */ X openart = artnum; X return artfp; /* and return either fp or NULL */ X} X Xvoid Xnntpclose() X{ X char artname[32]; /* filename of current article */ X if (our_pid == 0) X our_pid = getpid(); X sprintf(artname, "/tmp/rrn%ld.%ld", (long) openart, our_pid); X UNLINK(artname); X} X#endif SHAR_EOF chmod 0660 artio.c || echo "restore of artio.c fails" echo "x - extracting artio.h (Text)" sed 's/^X//' << 'SHAR_EOF' > artio.h && X/* $Header: artio.h,v 4.3.3.1 90/07/21 20:12:10 davison Trn $ X * X * $Log: artio.h,v $ X * Revision 4.3.3.1 90/07/21 20:12:10 davison X * Initial Trn Release X * X * Revision 4.3.2.2 89/11/27 01:27:53 sob X * Altered NNTP code per ideas suggested by Bela Lubkin X * <filbo@gorn.santa-cruz.ca.us> X * X * Revision 4.3.2.1 89/11/26 22:41:24 sob X * Added RRN support X * X * Revision 4.3 85/05/01 11:35:43 lwall X * Baseline for release with 4.3bsd. X * X */ X XEXT ART_POS artpos INIT(0); /* byte position in article file */ X XEXT ART_LINE artline INIT(0); /* current line number in article file */ XEXT FILE *artfp INIT(Nullfp); /* current article file pointer */ XEXT ART_NUM openart INIT(0); /* what is the currently open article number? */ X#ifdef LINKART X EXT char *linkartname INIT(nullstr);/* real name of article for Eunice */ X#endif X#ifdef SERVER XEXT ART_PART openpart INIT(0); /* how much of that article do we have? */ XFILE *nntpopen(); /* get an article unless already retrieved */ X Xvoid nntpclose(); X/* MUST be in increasing order of completeness! */ X#define GET_STATUS 1 /* test for existence only */ X#define GET_HEADER 2 /* if only header items are desired */ X#define GET_ARTICLE 3 /* retreive full article */ X#endif X Xvoid artio_init(); XFILE *artopen(); /* open an article unless already opened */ SHAR_EOF chmod 0660 artio.h || echo "restore of artio.h fails" echo "x - extracting artsrch.c (Text)" sed 's/^X//' << 'SHAR_EOF' > artsrch.c && X/* $Header: artsrch.c,v 4.3.3.1 90/07/21 20:13:13 davison Trn $ X * X * $Log: artsrch.c,v $ X * Revision 4.3.3.1 90/07/21 20:13:13 davison X * Initial Trn Release X * X * Revision 4.3.2.4 89/11/27 01:30:00 sob X * Altered NNTP code per ideas suggested by Bela Lubkin X * <filbo@gorn.santa-cruz.ca.us> X * X * Revision 4.3.2.3 89/11/26 22:54:37 sob X * Added new patches to make rrn faster. X * X * Revision 4.3.2.2 89/11/26 22:20:57 sob X * Added better NNTP support. X * X * Revision 4.3.2.1 89/11/26 22:13:10 sob X * Added support for NNTP X * X * Revision 4.3 85/05/01 11:35:47 lwall X * Baseline for release with 4.3bsd. X * X */ X X#include "EXTERN.h" X#include "common.h" X#include "search.h" X#include "term.h" X#include "util.h" X#include "intrp.h" X#include "bits.h" X#include "kfile.h" X#include "head.h" X#include "final.h" X#include "cheat.h" X#ifdef SERVER X#include "server.h" X#endif X#include "ng.h" X#include "artio.h" X#ifdef USETHREADS X#include "rthreads.h" X#include "ngdata.h" X#endif X#include "INTERN.h" X#include "artsrch.h" X Xvoid Xartsrch_init() X{ X#ifdef ARTSEARCH X#ifdef ZEROGLOB X init_compex(&sub_compex); X init_compex(&art_compex); X#endif X#endif X} X X/* search for an article containing some pattern */ X X#ifdef ARTSEARCH Xint Xart_search(patbuf,patbufsiz,get_cmd) Xchar *patbuf; /* if patbuf != buf, get_cmd must */ Xint patbufsiz; Xint get_cmd; /* be set to FALSE!!! */ X{ X char *pattern; /* unparsed pattern */ X register char cmdchr = *patbuf; /* what kind of search? */ X register char *s; X bool backward = cmdchr == '?' || cmdchr == Ctl('p'); X /* direction of search */ X COMPEX *compex; /* which compiled expression */ X char *cmdlst = Nullch; /* list of commands to do */ X int normal_return = SRCH_NOTFOUND; /* assume no commands */ X bool saltaway = FALSE; /* store in KILL file? */ X char howmuch; /* search just the subjects */ X bool doread; /* search read articles? */ X bool foldcase = TRUE; /* fold upper and lower case? */ X X int_count = 0; X if (cmdchr == '/' || cmdchr == '?') { /* normal search? */ X if (get_cmd && buf == patbuf) X if (!finish_command(FALSE)) /* get rest of command */ X return SRCH_ABORT; X compex = &art_compex; X if (patbuf[1]) { X howmuch = 0; X doread = FALSE; X } X else { X howmuch = art_howmuch; X doread = art_doread; X } X s = cpytill(buf,patbuf+1,cmdchr);/* ok to cpy buf+1 to buf */ X pattern = buf; X if (*pattern) { X if (*lastpat) X free(lastpat); X lastpat = savestr(pattern); X } X if (*s) { /* modifiers or commands? */ X for (s++; *s && index("Kharc",*s); s++) { X if (*s == 'h') /* scan header */ X howmuch = 1; X else if (*s == 'a') /* scan article */ X howmuch = 2; X else if (*s == 'r') /* scan read articles */ X doread = TRUE; X else if (*s == 'K') /* put into KILL file */ X saltaway = TRUE; X else if (*s == 'c') /* make search case sensitive */ X foldcase = FALSE; X } X } X while (isspace(*s) || *s == ':') X s++; X if (*s) { X if (*s == 'm' || *s == 'M') X doread = TRUE; X if (*s == 'k') /* grandfather clause */ X *s = 'j'; X cmdlst = savestr(s); X normal_return = SRCH_DONE; X } X art_howmuch = howmuch; X art_doread = doread; X if (srchahead) X srchahead = -1; X } X else { X register char *h; X X howmuch = 0; /* just search subjects */ X doread = (cmdchr == Ctl('p')); X if (cmdchr == Ctl('n')) X normal_return = SRCH_SUBJDONE; X compex = &sub_compex; X pattern = patbuf+1; X strcpy(pattern,": *"); X h = pattern + strlen(pattern); X interp(h,patbufsiz - (h-patbuf),"%s"); /* fetch current subject */ X if (cmdchr == 'K') { X saltaway = TRUE; X cmdchr = 'k'; X } X if (cmdchr == 'k') { X normal_return = SRCH_DONE; X cmdlst = savestr("j"); X mark_as_read(); /* this article has this subject */ X if (!*h) { X#ifdef VERBOSE X IF(verbose) X fputs("\nCannot delete null subject.\n",stdout) FLUSH; X ELSE X#endif X#ifdef TERSE X fputs("\nNull subject.\n",stdout) FLUSH; X#endif X return SRCH_ABORT; X } X#ifdef VERBOSE X else if (verbose) X printf("\nMarking subject \"%s\" as read.\n",h) FLUSH; X#endif X } X else if (!srchahead) X srchahead = -1; X h[24] = '\0'; /* compensate for notesfiles */ X while (*h) { X if (index("/\\[.^*$'\"",*h) != Nullch) X *h++ = '.'; X else X h++; X } X#ifdef DEBUGGING X if (debug) { X printf("\npattern = %s\n",pattern) FLUSH; X } X#endif X } X if ((s = compile(compex,pattern,TRUE,foldcase)) != Nullch) { X /* compile regular expression */ X printf("\n%s\n",s) FLUSH; X return SRCH_ABORT; X } X#ifdef KILLFILES X if (saltaway) { X char saltbuf[LBUFLEN]; X X s = saltbuf; X sprintf(s,"/%s/",pattern); X s += strlen(s); X if (doread) X *s++ = 'r'; X if (howmuch==1) X *s++ = 'h'; X else if (howmuch==2) X *s++ = 'a'; X *s++ = ':'; X if (!cmdlst) X cmdlst = savestr("j"); X safecpy(s,cmdlst,LBUFLEN-(s-saltbuf)); X kf_append(saltbuf); X } X#endif X if (cmdlst && index(cmdlst,'=')) X normal_return = SRCH_ERROR; /* listing subjects is an error? */ X if (get_cmd) { X fputs("\nSearching...\n",stdout) FLUSH; X /* give them something to read */ X } X#ifdef USETHREADS X if (mode == 't') { X if (!cmdlst) X cmdlst = savestr("+"); /* thread selector's default command */ X if (unread_selector) X doread = TRUE; X normal_return = SRCH_DONE; X } X#endif X if (backward) { X if (cmdlst && art <= lastart) X art++; /* include current article */ X if (doread) X check_first(absfirst); X } X else { X if (art > lastart) { X art = (doread ? absfirst : firstart); X check_first(art--); X } X else if (cmdlst && art >= absfirst) X art--; /* include current article */ X } X if (srchahead > 0) { X if (!backward) X art = srchahead - 1; X srchahead = -1; X } X assert(!cmdlst || *cmdlst); X perform_cnt = 0; X for (;;) { X if (backward ? X (--art < absfirst || (!doread && art < firstart)) : X (++art > lastart) X ) { /* out of articles? */ X if (cmdlst) X free(cmdlst); X return normal_return; X } X if (int_count) { X int_count = 0; X if (cmdlst) X free(cmdlst); X return SRCH_INTR; X } X /*NOSTRICT*/ X if (doread || !was_read(art)) { X if (wanted(compex,art,howmuch)) { X /* does the shoe fit? */ X if (cmdlst) { X if (perform(cmdlst,TRUE)) { X if (cmdlst) X free(cmdlst); X return SRCH_INTR; X } X } X else { X if (cmdlst) X free(cmdlst); X return SRCH_FOUND; X } X } X else if (!cmdlst && ! (art%50)) { X printf("...%ld",(long)art); X fflush(stdout); X } X } X } X} X X/* determine if article fits pattern */ X/* returns TRUE if it exists and fits pattern, FALSE otherwise */ X Xbool Xwanted(compex, artnum, scope) XCOMPEX *compex; XART_NUM artnum; Xchar scope; X{ X if (!scope) { X char subj_buf[266]; X X#ifdef USETHREADS X if (ThreadedGroup) X find_article(art); X if (p_art) { X if (mode != 't') X strcpy(subj_buf, "Subject: "); X else X *subj_buf = '\0'; X if (p_art->subject != -1) X strcat(subj_buf,subject_ptrs[p_art->subject]); X } X else X#endif X { X strcpy(subj_buf, "Subject: "); X strncpy(subj_buf+9,fetchsubj(artnum,FALSE,FALSE),256); X } X#ifdef DEBUGGING X if (debug & DEB_SEARCH_AHEAD) X printf("%s\n",subj_buf) FLUSH; X#endif X return execute(compex,subj_buf) != Nullch; X } X#ifdef CACHESUBJ X else X fetchsubj(artnum,FALSE,FALSE);/* might as well get subject handy */ X#endif X X#ifdef SERVER X if (scope == 1){ X if (nntpopen(artnum,GET_HEADER) == Nullfp) /* we only need the header */ X return FALSE; X } X else X#endif X if (artopen(artnum) == Nullfp) /* ensure that article is open */ X X return FALSE; /* if not, return NO MATCH */ X scope--; X while (fgets(buf,LBUFLEN,artfp) != Nullch) { X /* for each line of article */ X if (!scope && index(buf,':') == Nullch && *buf != ' ' && *buf != '\t') X /* if headers only and out of header */ X return FALSE; /* say no go */ X if (execute(compex,buf) != Nullch) { X /* does pattern matcher match? */ X return TRUE; /* say Eureka */ X } X } X return FALSE; /* out of article, so no match */ X} X#endif X SHAR_EOF chmod 0660 artsrch.c || echo "restore of artsrch.c fails" echo "x - extracting artsrch.h (Text)" sed 's/^X//' << 'SHAR_EOF' > artsrch.h && X/* $Header: artsrch.h,v 4.3 85/05/01 11:35:55 lwall Exp $ X * X * $Log: artsrch.h,v $ X * Revision 4.3 85/05/01 11:35:55 lwall X * Baseline for release with 4.3bsd. X * X */ X X#ifndef NBRA X#include "search.h" X#endif X X#ifdef ARTSEARCH X X#define SRCH_ABORT 0 X#define SRCH_INTR 1 X#define SRCH_FOUND 2 X#define SRCH_NOTFOUND 3 X#define SRCH_DONE 4 X#define SRCH_SUBJDONE 5 X#define SRCH_ERROR 6 X#endif X XEXT char *lastpat INIT(nullstr); /* last search pattern */ X#ifdef ARTSEARCH X EXT COMPEX sub_compex; /* last compiled subject search */ X EXT COMPEX art_compex; /* last compiled normal search */ X# ifdef CONDSUB X EXT COMPEX *bra_compex INIT(&art_compex); X /* current compex with brackets */ X# endif X EXT char art_howmuch; /* search just the subjects */ X EXT bool art_doread; /* search read articles? */ X#endif X Xvoid artsrch_init(); X#ifdef ARTSEARCH X int art_search(); X bool wanted(); /* return TRUE if current article matches pattern */ X#endif SHAR_EOF chmod 0660 artsrch.h || echo "restore of artsrch.h fails" echo "x - extracting artstate.h (Text)" sed 's/^X//' << 'SHAR_EOF' > artstate.h && X/* $Header: artstate.h,v 4.3.1.2 85/05/13 09:30:30 lwall Exp $ X * X * $Log: artstate.h,v $ X * Revision 4.3.1.2 85/05/13 09:30:30 lwall X * Added CUSTOMLINES option. X * X * Revision 4.3.1.1 85/05/10 11:31:32 lwall X * Branch for patches. X * X * Revision 4.3 85/05/01 11:35:59 lwall X * Baseline for release with 4.3bsd. X * X */ X XEXT bool reread INIT(FALSE); /* consider current art temporarily */ X /* unread? */ XEXT bool do_fseek INIT(FALSE); /* should we back up in article file? */ X XEXT bool oldsubject INIT(FALSE); /* not 1st art in subject thread */ XEXT ART_LINE topline INIT(-1); /* top line of current screen */ XEXT bool do_hiding INIT(TRUE); /* hide header lines with -h? */ X#ifdef ROTATION XEXT bool rotate INIT(FALSE); /* has rotation been requested? */ X#endif XEXT char *prompt; /* pointer to current prompt */ X XEXT char *firstline INIT(Nullch); /* special first line? */ X#ifdef CUSTOMLINES XEXT char *hideline INIT(Nullch); /* custom line hiding? */ XEXT char *pagestop INIT(Nullch); /* custom page terminator? */ XEXT COMPEX hide_compex; XEXT COMPEX page_compex; X#endif SHAR_EOF chmod 0660 artstate.h || echo "restore of artstate.h fails" echo "x - extracting backpage.c (Text)" sed 's/^X//' << 'SHAR_EOF' > backpage.c && X/* $Header: backpage.c,v 4.3.3.1 90/06/20 22:36:17 davison Trn $ X * X * $Log: backpage.c,v $ X * Revision 4.3.3.1 90/06/20 22:36:17 davison X * Initial Trn Release X * X * Revision 4.3 85/05/01 11:36:03 lwall X * Baseline for release with 4.3bsd. X * X */ X X#include "EXTERN.h" X#include "common.h" X#include "intrp.h" X#include "final.h" X#include "INTERN.h" X#include "backpage.h" X XART_LINE maxindx = -1; Xlong lseek(); X Xvoid Xbackpage_init() X{ X char *varyname; X X varyname = filexp(VARYNAME); X close(creat(varyname,0600)); X varyfd = open(varyname,2); X UNLINK(varyname); X if (varyfd < 0) { X printf(cantopen,varyname) FLUSH; X sig_catcher(0); X } X X} X X/* virtual array read */ X XART_POS Xvrdary(indx) XART_LINE indx; X{ X int subindx; X long offset; X X#ifdef DEBUGGING X if (indx > maxindx) { X printf("vrdary(%ld) > %ld\n",(long)indx, (long)maxindx) FLUSH; X return 0; X } X#endif X if (indx < 0) X return 0; X subindx = indx % VARYSIZE; X offset = (indx - subindx) * sizeof(varybuf[0]); X if (offset != oldoffset) { X if (oldoffset >= 0) { X#ifndef lint X (void)lseek(varyfd,oldoffset,0); X write(varyfd, (char *)varybuf,sizeof(varybuf)); X#endif /* lint */ X } X#ifndef lint X (void)lseek(varyfd,offset,0); X read(varyfd,(char *)varybuf,sizeof(varybuf)); X#endif /* lint */ X oldoffset = offset; X } X return varybuf[subindx]; X} X X/* write to virtual array */ X Xvoid Xvwtary(indx,newvalue) XART_LINE indx; XART_POS newvalue; X{ X int subindx; X long offset; X X#ifdef DEBUGGING X if (indx < 0) X printf("vwtary(%ld)\n",(long)indx) FLUSH; X if (!indx) X maxindx = 0; X if (indx > maxindx) { X if (indx != maxindx + 1) X printf("indx skipped %d-%d\n",maxindx+1,indx-1) FLUSH; X maxindx = indx; X } X#endif X subindx = indx % VARYSIZE; X offset = (indx - subindx) * sizeof(varybuf[0]); X if (offset != oldoffset) { X if (oldoffset >= 0) { X#ifndef lint X (void)lseek(varyfd,oldoffset,0); X write(varyfd,(char *)varybuf,sizeof(varybuf)); X#endif /* lint */ X } X#ifndef lint X (void)lseek(varyfd,offset,0); X read(varyfd,(char *)varybuf,sizeof(varybuf)); X#endif /* lint */ X oldoffset = offset; X } X varybuf[subindx] = newvalue; X} X SHAR_EOF chmod 0660 backpage.c || echo "restore of backpage.c fails" echo "x - extracting backpage.h (Text)" sed 's/^X//' << 'SHAR_EOF' > backpage.h && X/* $Header: backpage.h,v 4.3 85/05/01 11:36:11 lwall Exp $ X * X * $Log: backpage.h,v $ X * Revision 4.3 85/05/01 11:36:11 lwall X * Baseline for release with 4.3bsd. X * X */ X X/* things for doing the 'back page' command */ X XEXT int varyfd INIT(0); /* virtual array file for storing */ X /* file offsets */ XEXT ART_POS varybuf[VARYSIZE]; /* current window onto virtual array */ X XEXT long oldoffset INIT(-1); /* offset to block currently in window */ X Xvoid backpage_init(); XART_POS vrdary(); Xvoid vwtary(); SHAR_EOF chmod 0660 backpage.h || echo "restore of backpage.h fails" echo "x - extracting bits.c (Text)" sed 's/^X//' << 'SHAR_EOF' > bits.c && X/* $Header: bits.c,v 4.3.3.1 90/06/20 22:36:24 davison Trn $ X * X * $Log: bits.c,v $ X * Revision 4.3.3.1 90/06/20 22:36:24 davison X * Initial Trn Release X * X * Revision 4.3.2.3 89/11/28 01:52:02 sob X * Removed some lint. X * X * Revision 4.3.2.2 89/11/27 01:30:04 sob X * Altered NNTP code per ideas suggested by Bela Lubkin X * <filbo@gorn.santa-cruz.ca.us> X * X * Revision 4.3.1.4 86/10/31 15:23:53 lwall X * Separated firstart into two variables so KILL on new articles won't X * accidentally mark articles read. X * X * Revision 4.3.1.3 86/09/09 16:01:43 lwall X * Fixed 'n more articles' bug. X * X * Revision 4.3.1.2 86/07/24 14:40:23 lwall X * Gets host name from path instead of relay-version for news 2.10.3. X * X * Revision 4.3.1.1 85/05/10 11:31:41 lwall X * Branch for patches. X * X * Revision 4.3 85/05/01 11:36:15 lwall X * Baseline for release with 4.3bsd. X * X */ X X#include "EXTERN.h" X#include "common.h" X#include "rcstuff.h" X#include "head.h" X#include "util.h" X#include "final.h" X#include "rn.h" X#include "cheat.h" X#include "ng.h" X#include "artio.h" X#include "intrp.h" X#include "ngdata.h" X#include "rcln.h" X#include "kfile.h" X#ifdef USETHREADS X#include "rthreads.h" X#endif X#include "INTERN.h" X#include "bits.h" X X#ifdef DBM X# ifdef NULL X# undef NULL X# endif X# include <dbm.h> X#endif XMEM_SIZE ctlsize; /* size of bitmap in bytes */ X Xvoid Xbits_init() X{ X#ifdef DELAYMARK X dmname = savestr(filexp(RNDELNAME)); X#else X ; X#endif X} X X/* checkpoint the .newsrc */ X Xvoid Xcheckpoint_rc() X{ X#ifdef DEBUGGING X if (debug & DEB_CHECKPOINTING) { X fputs("(ckpt)",stdout); X fflush(stdout); X } X#endif X if (doing_ng) X restore_ng(); /* do not restore M articles */ X if (rc_changed) X write_rc(); X#ifdef DEBUGGING X if (debug & DEB_CHECKPOINTING) { X fputs("(done)",stdout); X fflush(stdout); X } X#endif X} X X/* reconstruct the .newsrc line in a human readable form */ X Xvoid Xrestore_ng() X{ X register char *s, *mybuf = buf; X register ART_NUM i; X ART_NUM count=0; X int safelen = LBUFLEN - 16; X X strcpy(buf,rcline[ng]); /* start with the newsgroup name */ X s = buf + rcnums[ng] - 1; /* use s for buffer pointer */ X *s++ = rcchar[ng]; /* put the requisite : or !*/ X *s++ = ' '; /* put the not-so-requisite space */ X for (i=1; i<=lastart; i++) { /* for each article in newsgroup */ X if (s-mybuf > safelen) { /* running out of room? */ X safelen *= 2; X if (mybuf == buf) { /* currently static? */ X *s = '\0'; X mybuf = safemalloc((MEM_SIZE)safelen + 16); X strcpy(mybuf,buf); /* so we must copy it */ X s = mybuf + (s-buf); X /* fix the pointer, too */ X } X else { /* just grow in place, if possible */ X char *newbuf; X X newbuf = saferealloc(mybuf,(MEM_SIZE)safelen + 16); X s = newbuf + (s-mybuf); X mybuf = newbuf; X } X } X if (!was_read(i)) /* still unread? */ X count++; /* then count it */ X else { /* article was read */ X ART_NUM oldi; X X sprintf(s,"%ld",(long)i); /* put out the min of the range */ X s += strlen(s); /* keeping house */ X oldi = i; /* remember this spot */ X do i++; while (i <= lastart && was_read(i)); X /* find 1st unread article or end */ X i--; /* backup to last read article */ X if (i > oldi) { /* range of more than 1? */ X sprintf(s,"-%ld,",(long)i); X /* then it out as a range */ X s += strlen(s); /* and housekeep */ X } X else X *s++ = ','; /* otherwise, just a comma will do */ X } X } X if (*(s-1) == ',') /* is there a final ','? */ X s--; /* take it back */ X *s++ = '\0'; /* and terminate string */ X#ifdef DEBUGGING X if (debug & DEB_NEWSRC_LINE && !panic) { X printf("%s: %s\n",rcline[ng],rcline[ng]+rcnums[ng]) FLUSH; X printf("%s\n",mybuf) FLUSH; X } X#endif X free(rcline[ng]); /* return old rc line */ X if (mybuf == buf) { X rcline[ng] = safemalloc((MEM_SIZE)(s-buf)+1); X /* grab a new rc line */ X strcpy(rcline[ng], buf); /* and load it */ X } X else { X mybuf = saferealloc(mybuf,(MEM_SIZE)(s-mybuf)+1); X /* be nice to the heap */ X rcline[ng] = mybuf; X } X *(rcline[ng] + rcnums[ng] - 1) = '\0'; X if (rcchar[ng] == NEGCHAR) { /* did they unsubscribe? */ X printf(unsubto,ngname) FLUSH; X toread[ng] = TR_UNSUB; /* make line invisible */ X } X else X /*NOSTRICT*/ X toread[ng] = (ART_UNREAD)count; /* remember how many unread there are */ X} X X/* mark an article unread, keeping track of toread[] */ X Xvoid Xonemore(artnum) XART_NUM artnum; X{ X#ifdef DEBUGGING X if (debug && artnum < firstbit) { X printf("onemore: %d < %d\n",artnum,firstbit) FLUSH; X return; X } X#endif X if (ctl_read(artnum)) { X ctl_clear(artnum); X ++toread[ng]; X } X} X X/* mark an article read, keeping track of toread[] */ X Xvoid Xoneless(artnum) XART_NUM artnum; X{ X#ifdef DEBUGGING X if (debug && artnum < firstbit) { X printf("oneless: %d < %d\n",artnum,firstbit) FLUSH; X return; X } X#endif X if (!ctl_read(artnum)) { X ctl_set(artnum); X if (toread[ng] > TR_NONE) X --toread[ng]; X } X} X X/* mark an article as unread, making sure that firstbit is properly handled */ X/* cross-references are left as read in the other newsgroups */ X Xvoid Xunmark_as_read() X{ X check_first(art); X#ifdef USETHREADS X /* Keep selected_count accurate */ X if (ctl_read(art)) { X find_article(art); X if (p_art) { X if (selected_roots[p_art->root]) { X selected_count++; X } X root_article_cnts[p_art->root] = 1; X } else X unthreaded++; X } X scan_all_roots = FALSE; X#endif X onemore(art); X#ifdef MCHASE X if (!parse_maybe(art)) X chase_xrefs(art,FALSE); X#endif X} X X#ifdef USETHREADS X/* mark an article as read in this newsgroup only */ X Xvoid Xset_read(artnum,sel) XART_NUM artnum; Xint sel; X{ X if (!ctl_read(artnum)) { X oneless(artnum); X if( p_art->subject != -1 ) X selected_count -= sel; X } X} X X/* mark an article as unread in this newsgroup only */ X Xvoid Xset_unread(artnum,sel) XART_NUM artnum; Xint sel; X{ X if (artnum >= absfirst) { X check_first(artnum); X if (ctl_read(artnum)) { X onemore(artnum); X selected_count += sel; X root_article_cnts[p_art->root] = 1; X scan_all_roots = FALSE; X } X } X} X#endif X X#ifdef DELAYMARK X/* temporarily mark article as read. When newsgroup is exited, articles */ X/* will be marked as unread. Called via M command */ X Xvoid Xdelay_unmark(artnum) XART_NUM artnum; X{ X if (dmfp == Nullfp) { X dmfp = fopen(dmname,"w+"); X if (dmfp == Nullfp) { X printf(cantcreate,dmname) FLUSH; X sig_catcher(0); X } X } X#ifdef USETHREADS X /* Keep selected_count accurate */ X if (!ctl_read(artnum)) { X find_article(artnum); X if (p_art) { X if (selected_roots[p_art->root]) X selected_count--; X } else X unthreaded--; X } X#endif X oneless(artnum); /* set the correct bit */ X dmcount++; X fprintf(dmfp,"%ld\n",(long)artnum); X} X#endif X X/* mark article as read. If article is cross referenced to other */ X/* newsgroups, mark them read there also. */ X Xvoid Xmark_as_read() X{ X#ifdef USETHREADS X /* Keep selected_count accurate */ X if (!ctl_read(art)) { X find_article(art); X if (p_art) { X if (selected_roots[p_art->root]) X selected_count--; X } else X unthreaded--; X } X#endif X oneless(art); /* set the correct bit */ X checkcount++; /* get more worried about crashes */ X chase_xrefs(art,TRUE); X} X X/* make sure we have bits set correctly down to firstbit */ X Xvoid Xcheck_first(min) XART_NUM min; X{ X register ART_NUM i = firstbit; X X if (min < absfirst) X min = absfirst; X if (min < i) { X for (i--; i>=min; i--) X ctl_set(i); /* mark as read */ X firstart = firstbit = min; X } X} X X/* bring back articles marked with M */ X X#ifdef DELAYMARK Xvoid Xyankback() X{ X if (dmfp) { /* delayed unmarks pending? */ X#ifdef VERBOSE X printf("\nReturning %ld Marked article%s...\n",(long)dmcount, X dmcount == 1 ? nullstr : "s") FLUSH; X#endif X rewind(dmfp); X while (fgets(buf,sizeof buf,dmfp) != Nullch) { X art = (ART_NUM)atol(buf); X unmark_as_read(); X } X fclose(dmfp); X dmfp = Nullfp; X UNLINK(dmname); /* and be tidy */ X } X dmcount = 0; X} X#endif X X/* run down xref list and mark as read or unread */ X Xint Xchase_xrefs(artnum,markread) XART_NUM artnum; Xint markread; X{ X#ifdef ASYNC_PARSE X if (parse_maybe(artnum)) /* make sure we have right header */ X return -1; X#endif X#ifdef DBM X { X datum lhs, rhs; X datum fetch(); X register char *idp; X char *ident_buf; X static FILE * hist_file = Nullfp; X#else X if ( X#ifdef DEBUGGING X debug & DEB_FEED_XREF || X#endif X htype[XREF_LINE].ht_minpos >= 0) { X /* are there article# xrefs? */ X#endif /* DBM */ X char *xref_buf, *curxref; X register char *xartnum; X char *rver_buf = Nullch; X static char *inews_site = Nullch; X register ART_NUM x; X char tmpbuf[128]; X X#ifdef DBM X rver_buf = fetchlines(artnum,NGS_LINE); X /* get Newsgroups */ X if (!index(rver_buf,',')) /* if no comma, no Xref! */ X return 0; X if (hist_file == Nullfp) { /* Init. file accesses */ X#ifdef DEBUGGING X if (debug) X printf ("chase_xref: opening files\n"); X#endif X dbminit(filexp(ARTFILE)); X if ((hist_file = fopen (filexp(ARTFILE), "r")) == Nullfp) X return 0; X } X xref_buf = safemalloc((MEM_SIZE)BUFSIZ); X ident_buf = fetchlines(artnum,MESSID_LINE); X /* get Message-ID */ X#ifdef DEBUGGING X if (debug) X printf ("chase_xref: Message-ID: %s\n", ident_buf); X#endif X idp = ident_buf; X while (*++idp) /* make message-id case insensitive */ X if (isupper(*idp)) X *idp = tolower (*idp); X lhs.dptr = ident_buf; /* look up article by id */ X lhs.dsize = strlen(lhs.dptr) + 1; X rhs = fetch(lhs); /* fetch the record */ X if (rhs.dptr == NULL) /* if null, nothing there */ X goto wild_goose; X fseek (hist_file, *((long *)rhs.dptr), 0); X /* datum returned is position in hist file */ X fgets (xref_buf, BUFSIZ, hist_file); X#ifdef DEBUGGING X if (debug) X printf ("Xref from history: %s\n", xref_buf); X#endif X curxref = cpytill(tmpbuf, xref_buf, '\t') + 1; X curxref = cpytill(tmpbuf, curxref, '\t') + 1; X#ifdef DEBUGGING X if (debug) X printf ("chase_xref: curxref: %s\n", curxref); X#endif X#else /* !DBM */ X#ifdef DEBUGGING X if (htype[XREF_LINE].ht_minpos >= 0) X#endif X xref_buf = fetchlines(artnum,XREF_LINE); X /* get xrefs list */ X#ifdef DEBUGGING X else { X xref_buf = safemalloc((MEM_SIZE)100); X printf("Give Xref: ") FLUSH; X gets(xref_buf); X } X#endif X#ifdef DEBUGGING X if (debug & DEB_XREF_MARKER) X printf("Xref: %s\n",xref_buf) FLUSH; X#endif X curxref = cpytill(tmpbuf,xref_buf,' ') + 1; X X /* Make sure site name on Xref matches what inews thinks site is. X * Check first against last inews_site. If it matches, fine. X * If not, fetch inews_site from current Relay-Version line and X * check again. This is so that if the new administrator decides X * to change the system name as known to inews, rn will still do X * Xrefs correctly--each article need only match itself to be valid. X */ X if (inews_site == Nullch || strNE(tmpbuf,inews_site)) { X#ifndef NORELAY X char *t; X#endif X if (inews_site != Nullch) X free(inews_site); X#ifndef NORELAY X rver_buf = fetchlines(artnum,RVER_LINE); X if ((t = instr(rver_buf,"; site ")) == Nullch) X#else /* NORELAY */ X /* In version 2.10.3 of news or afterwards, the Relay-Version X * and Posting-Version header lines have been removed. For X * the code below to work as intended, I have modified it to X * extract the first component of the Path header line. This X * should give the same effect as did the old code with respect X * to the use of the Relay-Version site name. X */ X rver_buf = fetchlines(artnum,PATH_LINE); X if (instr(rver_buf,"!") == Nullch) X#endif /* NORELAY */ X inews_site = savestr(nullstr); X else { X char new_site[128]; X X#ifndef NORELAY X cpytill(new_site,t + 7,'.'); X#else /* NORELAY */ X cpytill(new_site,rver_buf,'!'); X#endif /* NORELAY */ X inews_site = savestr(new_site); X } X if (strNE(tmpbuf,inews_site)) { X#ifdef DEBUGGING X if (debug) X printf("Xref not from %s--ignoring\n",inews_site) FLUSH; X#endif X goto wild_goose; X } X } X#endif /* DBM */ X while (*curxref) { X /* for each newsgroup */ X curxref = cpytill(tmpbuf,curxref,' '); X#ifdef DBM X xartnum = index(tmpbuf,'/'); X#else X xartnum = index(tmpbuf,':'); X#endif /* DBM */ X if (!xartnum) /* probably an old-style Xref */ X break; X *xartnum++ = '\0'; X if (strNE(tmpbuf,ngname)) {/* not the current newsgroup? */ X x = atol(xartnum); X if (x) X if (markread) { X if (addartnum(x,tmpbuf)) X goto wild_goose; X } X#ifdef MCHASE X else X subartnum(x,tmpbuf); X#endif X } X while (*curxref && isspace(*curxref)) X curxref++; X } X wild_goose: X free(xref_buf); X#ifdef DBM X free(ident_buf); X#endif /* DBM */ X if (rver_buf != Nullch) X free(rver_buf); X } X return 0; X} X Xint Xinitctl() X{ X char *mybuf = buf; /* place to decode rc line */ X register char *s, *c, *h; X register long i; X register ART_NUM unread; X X#ifdef DELAYMARK X dmcount = 0; X#endif X if ((lastart = getngsize(ng)) < 0) /* this cannot happen (laugh here) */ X return -1; X X absfirst = getabsfirst(ng,lastart); /* remember first existing article */ X if (!absfirst) /* no articles at all? */ X absfirst = 1; /* pretend there is one */ X#ifndef lint X ctlsize = (MEM_SIZE)(OFFSET(lastart)/BITSPERBYTE+20); X#endif /* lint */ X ctlarea = safemalloc(ctlsize); /* allocate control area */ X X /* now modify ctlarea to reflect what has already been read */ X X for (s = rcline[ng] + rcnums[ng]; *s == ' '; s++) ; X /* find numbers in rc line */ X i = strlen(s); X#ifndef lint X if (i >= LBUFLEN-2) /* bigger than buf? */ X mybuf = safemalloc((MEM_SIZE)(i+2)); X#endif /* lint */ X strcpy(mybuf,s); /* make scratch copy of line */ X mybuf[i++] = ','; /* put extra comma on the end */ X mybuf[i] = '\0'; X s = mybuf; /* initialize the for loop below */ X if (strnEQ(s,"1-",2)) { /* can we save some time here? */ X firstbit = atol(s+2)+1; /* ignore first range thusly */ X s=index(s,',') + 1; X } X else X firstbit = 1; /* all the bits are valid for now */ X if (absfirst > firstbit) { /* do we know already? */ X firstbit = absfirst; /* no point calling getngmin again */ X } X else if (artopen(firstbit) == Nullfp) { X /* first unread article missing? */ X i = getngmin(".",firstbit); /* see if expire has been busy */ X if (i) { /* avoid a bunch of extra opens */ X firstbit = i; X } X } X firstart = firstbit; /* firstart > firstbit in KILL */ X#ifdef PENDING X# ifdef CACHESUBJ X subj_to_get = firstbit; X# endif X#endif X unread = lastart - firstbit + 1; /* assume this range unread */ X for (i=OFFSET(firstbit)/BITSPERBYTE; i<ctlsize; i++) X ctlarea[i] = 0; /* assume unread */ X#ifdef DEBUGGING X if (debug & DEB_CTLAREA_BITMAP) { X printf("\n%s\n",mybuf) FLUSH; X for (i=1; i <= lastart; i++) X if (! was_read(i)) X printf("%ld ",(long)i) FLUSH; X } X#endif X for ( ; (c = index(s,',')) != Nullch; s = ++c) { X /* for each range */ X ART_NUM min, max; X X *c = '\0'; /* do not let index see past comma */ X if ((h = index(s,'-')) != Nullch) { /* is there a -? */ X min = atol(s); X max = atol(h+1); X if (min < firstbit) /* make sure range is in range */ X min = firstbit; X if (max > lastart) X max = lastart; X if (min <= max) /* non-null range? */ X unread -= max - min + 1;/* adjust unread count */ X for (i=min; i<=max; i++) /* for all articles in range */ X ctl_set(i); /* mark them read */ X } X else if ((i = atol(s)) >= firstbit && i <= lastart) { X /* is single number reasonable? */ X ctl_set(i); /* mark it read */ X unread--; /* decrement articles to read */ X } X#ifdef DEBUGGING X if (debug & DEB_CTLAREA_BITMAP) { X printf("\n%s\n",s) FLUSH; X for (i=1; i <= lastart; i++) X if (! was_read(i)) X printf("%ld ",(long)i) FLUSH; X } X#endif X } X#ifdef DEBUGGING X if (debug & DEB_CTLAREA_BITMAP) { X fputs("\n(hit CR)",stdout) FLUSH; X gets(cmd_buf); X } X#endif X if (mybuf != buf) X free(mybuf); X toread[ng] = unread; X return 0; X} X Xvoid Xgrow_ctl(newlast) XART_NUM newlast; X{ X ART_NUM tmpfirst; X MEM_SIZE newsize; X register ART_NUM i; X X forcegrow = FALSE; X if (newlast > lastart) { X ART_NUM tmpart = art; X#ifndef lint X newsize = (MEM_SIZE)(OFFSET(newlast)/BITSPERBYTE+2); X#else X newsize = Null(MEM_SIZE); X#endif /* lint */ X if (newsize > ctlsize) { X newsize += 20; X ctlarea = saferealloc(ctlarea,newsize); X ctlsize = newsize; X } X toread[ng] += (ART_UNREAD)(newlast-lastart); X for (i=lastart+1; i<=newlast; i++) X ctl_clear(i); /* these articles are unread */ X#ifdef CACHESUBJ X if (subj_list != Null(char**)) { X#ifndef lint X subj_list = (char**)saferealloc((char*)subj_list, X (MEM_SIZE)((OFFSET(newlast)+2)*sizeof(char *)) ); X#endif /* lint */ X for (i=lastart+1; i<=newlast; i++) X subj_list[OFFSET(i)] = Nullch; X } X#endif X tmpfirst = lastart+1; X lastart = newlast; X#ifdef KILLFILES X#ifdef VERBOSE X IF(verbose) X sprintf(buf, X "%ld more article%s arrived--looking for more to kill...\n\n", X (long)(lastart - tmpfirst + 1), X (lastart > tmpfirst ? "s have" : " has" ) ); X ELSE /* my, my, how clever we are */ X#endif X#ifdef TERSE X strcpy(buf, "More news--killing...\n\n"); X#endif X kill_unwanted(tmpfirst,buf,TRUE); X#endif X art = tmpart; X } X} X SHAR_EOF chmod 0660 bits.c || echo "restore of bits.c fails" echo "x - extracting bits.h (Text)" sed 's/^X//' << 'SHAR_EOF' > bits.h && X/* $Header: bits.h,v 4.3.3.1 90/06/20 22:36:35 davison Trn $ X * X * $Log: bits.h,v $ X * Revision 4.3.3.1 90/06/20 22:36:35 davison X * Initial Trn Release X * X * Revision 4.3.1.2 86/11/03 09:49:58 lwall X * Added firstbit variable. X * X * Revision 4.3.1.1 85/05/10 11:31:52 lwall X * Branch for patches. X * X * Revision 4.3 85/05/01 11:36:39 lwall X * Baseline for release with 4.3bsd. X * X */ X XEXT char *ctlarea INIT(Nullch); /* one bit for each article in current newsgroup */ X /* with the following interpretation: */ X /* 0 => unread */ X /* 1 => read */ X X/* if subscripting is faster than shifting on your machine, define this */ X#undef USESUBSCRIPT X#ifdef USESUBSCRIPT XEXT char powerof2[] INIT({1,2,4,8,16,32,64,128}); X#define pow2(x) powerof2[x] X#else X#define pow2(x) (1 << (x)) X#endif X X#ifdef lint XEXT bool nonesuch INIT(FALSE); X#define ctl_set(a) X#define ctl_clear(a) X#define ctl_read(a) nonesuch X#define was_read(a) nonesuch X#else X#define ctl_set(a) (ctlarea[(OFFSET(a)) / BITSPERBYTE] |= pow2((OFFSET(a)) % BITSPERBYTE)) X#define ctl_clear(a) (ctlarea[(OFFSET(a)) / BITSPERBYTE] &= ~pow2((OFFSET(a)) % BITSPERBYTE)) X#define ctl_read(a) ((ctlarea[(OFFSET(a)) / BITSPERBYTE] & pow2((OFFSET(a)) % BITSPERBYTE)) != 0) X X#define was_read(a) ((a)<firstbit || ctl_read(a)) X#endif /* lint */ X XEXT ART_NUM absfirst INIT(0); /* 1st real article in current newsgroup */ XEXT ART_NUM firstart INIT(0); /* minimum unread article number in newsgroup */ XEXT ART_NUM firstbit INIT(0); /* minimum valid bit, usually == firstart */ XEXT ART_NUM lastart INIT(0); /* maximum article number in newsgroup */ X X#ifdef DELAYMARK XEXT FILE *dmfp INIT(Nullfp); XEXT char *dmname INIT(Nullch); XEXT int dmcount INIT(0); X#endif X Xvoid bits_init(); Xvoid checkpoint_rc(); Xvoid restore_ng(); Xvoid onemore(); Xvoid oneless(); Xvoid unmark_as_read(); X#ifdef USETHREADS Xvoid set_read(); Xvoid set_unread(); X#endif Xvoid delay_unmark(); Xvoid mark_as_read(); Xvoid check_first(); X#ifdef DELAYMARK X void yankback(); X#endif Xint chase_xrefs(); Xint initctl(); Xvoid grow_ctl(); SHAR_EOF chmod 0660 bits.h || echo "restore of bits.h fails" echo "x - extracting cheat.c (Text)" sed 's/^X//' << 'SHAR_EOF' > cheat.c && X/* $Header: cheat.c,v 4.3.3.1 90/07/21 20:14:01 davison Trn $ X * X * $Log: cheat.c,v $ X * Revision 4.3.3.1 90/07/21 20:14:01 davison X * Initial Trn Release X * X * Revision 4.3.2.2 89/11/27 01:30:18 sob X * Altered NNTP code per ideas suggested by Bela Lubkin X * <filbo@gorn.santa-cruz.ca.us> X * X * Revision 4.3.2.1 89/11/26 22:54:21 sob X * Added RRN support X * X * Revision 4.3 85/05/01 11:36:46 lwall X * Baseline for release with 4.3bsd. X * X */ X X#include "EXTERN.h" X#include "common.h" X#include "intrp.h" X#include "search.h" X#include "ng.h" X#include "bits.h" X#include "artio.h" X#include "term.h" X#include "artsrch.h" X#include "head.h" X#include "INTERN.h" X#include "cheat.h" X X/* see what we can do while they are reading */ X X#ifdef PENDING X# ifdef ARTSEARCH X COMPEX srchcompex; /* compiled regex for searchahead */ X# endif X#endif X Xvoid Xcheat_init() X{ X ; X} X X#ifdef PENDING Xvoid Xlook_ahead() X{ X#ifdef ARTSEARCH X register char *h, *s; X X#ifdef DEBUGGING X if (debug && srchahead) { X printf("(%ld)",(long)srchahead); X fflush(stdout); X } X#endif X if (srchahead && srchahead < art) { /* in ^N mode? */ X char *pattern; X X pattern = buf+1; X strcpy(pattern,": *"); X h = pattern + strlen(pattern); X interp(h,(sizeof buf) - (h-buf),"%s"); X h[24] = '\0'; /* compensate for notesfiles */ X while (*h) { X if (index("\\[.^*$'\"",*h) != Nullch) X *h++ = '.'; X else X h++; X } X#ifdef DEBUGGING X if (debug & DEB_SEARCH_AHEAD) { X fputs("(hit CR)",stdout); X fflush(stdout); X gets(buf+128); X printf("\npattern = %s\n",pattern); X } X#endif X if ((s = compile(&srchcompex,pattern,TRUE,TRUE)) != Nullch) { X /* compile regular expression */ X printf("\n%s\n",s); X srchahead = 0; X } X if (srchahead) { X srchahead = art; X for (;;) { X srchahead++; /* go forward one article */ X if (srchahead > lastart) { /* out of articles? */ X#ifdef DEBUGGING X if (debug) X fputs("(not found)",stdout); X#endif X break; X } X if (!was_read(srchahead) && X wanted(&srchcompex,srchahead,0)) { X /* does the shoe fit? */ X#ifdef DEBUGGING X if (debug) X printf("(%ld)",(long)srchahead); X#endif X#ifdef SERVER X nntpopen(srchahead,GET_HEADER); X#else X artopen(srchahead); X#endif X break; X } X if (input_pending()) X break; X } X fflush(stdout); X } X } X else X#endif X { X if (art+1 <= lastart)/* how about a pre-fetch? */ X#ifdef SERVER X nntpopen(art+1,GET_HEADER); /* look for the next article */ X#else X artopen(art+1); /* look for the next article */ X#endif X } X} X#endif X X/* see what else we can do while they are reading */ X Xvoid Xcollect_subjects() X{ X#ifdef PENDING X# ifdef CACHESUBJ X ART_NUM oldart = openart; X ART_POS oldartpos; X X if (!in_ng || !srchahead) X return; X if (oldart) /* remember where we were in art */ X oldartpos = ftell(artfp); X if (srchahead >= subj_to_get) X subj_to_get = srchahead+1; X while (!input_pending() && subj_to_get <= lastart) X fetchsubj(subj_to_get++,FALSE,FALSE); X if (oldart) { X artopen(oldart); X fseek(artfp,oldartpos,0); /* do not screw the pager */ X } X# endif X#endif X} X SHAR_EOF chmod 0660 cheat.c || echo "restore of cheat.c fails" echo "x - extracting cheat.h (Text)" sed 's/^X//' << 'SHAR_EOF' > cheat.h && X/* $Header: cheat.h,v 4.3 85/05/01 11:36:58 lwall Exp $ X * X * $Log: cheat.h,v $ X * Revision 4.3 85/05/01 11:36:58 lwall X * Baseline for release with 4.3bsd. X * X */ X X#ifdef ARTSEARCH XEXT ART_NUM srchahead INIT(0); /* are we in subject scan mode? */ X /* (if so, contains art # found or -1) */ X#endif X X#ifdef PENDING X# ifdef CACHESUBJ X EXT ART_NUM subj_to_get; X# endif X#endif X Xvoid cheat_init(); Xvoid look_ahead(); Xvoid collect_subjects(); SHAR_EOF chmod 0660 cheat.h || echo "restore of cheat.h fails" echo "x - extracting common.h (Text)" sed 's/^X//' << 'SHAR_EOF' > common.h && X/* $Header: common.h,v 4.3.3.1 90/07/21 20:15:23 davison Trn $ X * X * $Log: common.h,v $ X * Revision 4.3.3.1 90/07/21 20:15:23 davison X * Initial Trn Release X * X * Revision 4.3.2.13 90/05/08 22:05:37 sob X * Added quick startup (-q) flag. X * X * Revision 4.3.2.12 90/04/23 00:32:04 sob X * More cleanup. X * X * Revision 4.3.2.11 90/04/14 19:37:07 sob X * Added better support for the NeXT. X * X * Revision 4.3.2.10 90/04/06 20:54:12 sob X * Corrected forward definition of fseek() X * X * Revision 4.3.2.9 90/03/17 21:19:04 sob X * Removed the incorrect forward definition of sprintf(). X * X * Revision 4.3.2.8 89/12/20 20:40:03 sob X * Changed ACT_POS from short to long per suggestion from eps@cd.SFSU.EDU. X * X * Revision 4.3.2.7 89/12/08 22:43:12 sob X * Corrected typo pointed out by weening@gang-of-four.stanford.edu X * X * Revision 4.3.2.6 89/11/28 01:57:31 sob X * Added initlines_specified variable for use with SIGWINCH support. X * X * Revision 4.3.2.5 89/11/28 00:30:56 sob X * Reversed the CANCELHEADER definitions. X * X * Revision 4.3.2.4 89/11/27 01:29:23 sob X * Altered NNTP code per ideas suggested by Bela Lubkin X * <filbo@gorn.santa-cruz.ca.us> X * X * Revision 4.3.2.3 89/11/26 19:32:06 sob X * Increased the size of MAXRCLINE from 1000 to 1500 X * Increated HASHSIZ from 1103 to 1693 X * X * Revision 4.3.2.2 89/11/07 23:18:49 sob X * Repaired NEWSHEADER and CANCEL to work correctly with NNTP and INTERNET. X * X * Revision 4.3.2.1 89/11/06 00:12:33 sob X * Added RRN support from NNTP 1.5 X * X * Revision 4.3.1.4 86/10/31 15:46:09 lwall X * Expanded maximum number of .newsrc lines for net reorganization. X * X * Revision 4.3.1.3 85/05/23 17:19:32 lwall X * Now allows 'r' and 'f' on null articles. X * X * Revision 4.3.1.2 85/05/13 09:30:39 lwall X * Added CUSTOMLINES option. X * X * Revision 4.3.1.1 85/05/10 11:32:04 lwall X * Branch for patches. X * X * Revision 4.3 85/05/01 11:37:11 lwall X * Baseline for release with 4.3bsd. X * X */ X X#include "config.h" /* generated by installation script */ X#ifdef WHOAMI X# include <whoami.h> X#endif X X#include <stdio.h> X#include <sys/types.h> X#include <sys/stat.h> X#include <ctype.h> X X#ifndef isalnum X# define isalnum(c) (isalpha(c) || isdigit(c)) X#endif X X#include <errno.h> X#include <signal.h> X#ifdef IOCTL X#include <sys/ioctl.h> X#endif X X#ifdef FCNTL X# include <fcntl.h> X#endif X X#ifdef TERMIO X# include <termio.h> X#else X# include <sgtty.h> X#endif X X#ifdef GETPWENT X# include <pwd.h> X#endif X X#define BITSPERBYTE 8 X#define LBUFLEN 512 /* line buffer length */ X /* (don't worry, .newsrc lines can exceed this) */ X#ifdef pdp11 X# define CBUFLEN 256 /* command buffer length */ X# define PUSHSIZE 128 X#else X# define CBUFLEN 512 /* command buffer length */ X# define PUSHSIZE 256 X#endif X#ifdef pdp11 X# define MAXFILENAME 128 X#else X# define MAXFILENAME 512 X#endif X#define LONGKEY 15 /* longest keyword: currently "posting-version" */ X#define FINISHCMD 0177 X X/* some handy defs */ X X#define bool char X#define TRUE (1) X#define FALSE (0) X#define Null(t) ((t)0) X#define Nullch Null(char *) X#define Nullfp Null(FILE *) X X#define Ctl(ch) (ch & 037) X X#define strNE(s1,s2) (strcmp(s1,s2)) X#define strEQ(s1,s2) (!strcmp(s1,s2)) X#define strnNE(s1,s2,l) (strncmp(s1,s2,l)) X#define strnEQ(s1,s2,l) (!strncmp(s1,s2,l)) X X/* Things we can figure out ourselves */ X X#ifdef SIGTSTP X# define BERKELEY /* include job control signals? */ X#endif X X#ifdef FIONREAD X# define PENDING X#else X# ifdef O_NDELAY X# define PENDING X# endif X#endif X X#ifdef EUNICE X# define LINKART /* add 1 level of possible indirection */ X# define UNLINK(victim) while (!unlink(victim)) X#else X# define UNLINK(victim) unlink(victim) X#endif X X/* Valid substitutions for strings marked with % comment are: X * %a Current article number X * %A Full name of current article (%P/%c/%a) X * (if LINKART defined, is the name of the real article) X * %b Destination of a save command, a mailbox or command X * %B The byte offset to the beginning of the article for saves X * with or without the header X * %c Current newsgroup, directory form X * %C Current newsgroup, dot form X * %d %P/%c X * %D Old Distribution: line X * %f Old From: line or Reply-To: line X * %F Newsgroups to followup to from Newsgroups: and Followup-To: X * %h Name of header file to pass to mail or news poster X * %H Host name (yours) X * %i Old Message-I.D.: line, with <> X * %I Inclusion indicator X * %l News administrator login name X * %L Login name (yours) X * %M Number of articles markd with M X * %n Newsgroups from source article X * %N Full name (yours) X * %o Organization (yours) X * %O Original working directory (where you ran rn from) X * %p Your private news directory (-d switch) X * %P Public news spool directory (SPOOLDIR) X * %r Last reference (parent article id) X * %R New references list X * %s Subject, with all Re's and (nf)'s stripped off X * %S Subject, with one Re stripped off X * %t New To: line derived from From: and Reply-To (Internet always) X * %T New To: line derived from Path: X * %u Number of unread articles X * %U Number of unread articles disregarding current article X * %x News library directory, usually /usr/lib/news X * %X Rn library directory, usually %x/rn X * %z Size of current article in bytes. X * %~ Home directory X * %. Directory containing . files X * %$ current process number X * %{name} Environment variable "name". %{name-default} form allowed. X * %[name] Header line beginning with "Name: ", without "Name: " X * %"prompt" X * Print prompt and insert what is typed. X * %`command` X * Insert output of command. X * %(test_text=pattern?if_text:else_text) X * Substitute if_text if test_text matches pattern, otherwise X * substitute else_text. Use != for negated match. X * % substitutions are done on test_text, if_text, and else_text. X * (Note: %() only works if CONDSUB defined.) X * %digit Substitute the text matched by the nth bracket in the last X * pattern that had brackets. %0 matches the last bracket X * matched, in case you had alternatives. X * X * Put ^ in the middle to capitalize the first letter: %^C = Net.jokes X * Put _ in the middle to capitalize last component: %_c = net/Jokes X * X * ~ interpretation in filename expansion happens after % expansion, so X * you could put ~%{NEWSLOGNAME-news} and it will expand correctly. X */ X X/* *** System Dependent Stuff *** */ X X/* NOTE: many of these are defined in the config.h file */ X X/* name of organization */ X#ifndef ORGNAME X# define ORGNAME "ACME Widget Company, Widget Falls, Southern North Dakota" X#endif X X#ifndef MBOXCHAR X# define MBOXCHAR 'F' /* how to recognize a mailbox by 1st char */ X#endif X X#ifndef ROOTID X# define ROOTID 0 /* uid of superuser */ X#endif X X#ifdef NORMSIG X# define sigset signal X# define sigignore(sig) signal(sig,SIG_IGN) X#endif X X#ifndef LOGDIRFIELD X# define LOGDIRFIELD 6 /* Which field (origin 1) is the */ X /* login directory in /etc/passwd? */ X /* (If it is not kept in passwd, */ X /* but getpwnam() returns it, */ X /* define the symbol GETPWENT) */ X#endif X#ifndef GCOSFIELD X# define GCOSFIELD 5 X#endif X X#ifndef NEGCHAR X# define NEGCHAR '!' X#endif X X/* Space conservation section */ X X/* To save D space, cut down size of MAXRCLINE, NGMAX, VARYSIZE. */ X#define MAXRCLINE 1500 /* number of lines allowed in .newsrc */ X /* several parallel arrays affected. */ X /* (You can have more lines in the active file, */ X /* just not in the .newsrc) */ X#define HASHSIZ 1693 /* should be prime, and at least MAXRCLINE + 10% */ X#define NGMAX 100 /* number of newsgroups allowed on command line */ X /* undefine ONLY symbol to disable "only" feature */ X#define VARYSIZE 256 /* this makes a block 1024 bytes long in DECville */ X /* (used by virtual array routines) */ X X/* Undefine any of the following features to save both I and D space */ X/* In general, earlier ones are easier to get along without */ X/* Pdp11's without split I and D may have to undefine them all */ X#define DEBUGGING /* include debugging code */ X#define USETHREADS /* Add article-thread following */ X#define CUSTOMLINES /* include code for HIDELINE and PAGESTOP */ X#define PUSHBACK /* macros and keymaps using pushback buffer */ X#define SPEEDOVERMEM /* use more memory to run faster */ X#define WORDERASE /* enable ^W to erase a word */ X#define MAILCALL /* check periodically for mail */ X#define CLEAREOL /* use clear to end-of-line instead of clear screen */ X#define NOFIREWORKS /* keep whole screen from flashing on certain */ X /* terminals such as older Televideos */ X#define VERIFY /* echo the command they just typed */ X#define HASHNG /* hash newsgroup lines for fast lookup-- */ X /* linear search used if not defined */ X#define CONDSUB /* allow %(cond?text:text) */ X#define BACKTICK /* allow %`command` */ X#define PROMPTTTY /* allow %"prompt" */ X#define ULSMARTS /* catch _^H in text and do underlining */ X#define TERMMOD /* allow terminal type modifier on switches */ X#define BAUDMOD /* allow baudrate modifier on switches */ X#define GETLOGIN /* use getlogin() routine as backup to environment */ X /* variables USER or LOGNAME */ X#define ORGFILE /* if organization begins with /, look up in file */ X#define TILDENAME /* allow ~logname expansion */ X#define SETENV /* allow command line environment variable setting */ X#define GETWD /* use our getwd() instead of piped in pwd */ X#define MAKEDIR /* use our makedir() instead of shell script */ X#define MEMHELP /* keep help messages in memory */ X#define VERBOSE /* compile in more informative messages */ X#define TERSE /* compile in shorter messages */ X /* (Note: both VERBOSE and TERSE can be defined; -t X * sets terse mode. One or the other MUST be defined. X */ X#ifndef pdp11 X# define CACHESUBJ /* cache subject lines in memory */ X /* without this ^N still works but runs really slow */ X /* but you save lots and lots of D space */ X# define CACHEFIRST /* keep absolute first article numbers in memory */ X /* cost: about 2k */ X#endif X#define ROTATION /* enable x, X and ^X commands to work */ X#define DELBOGUS /* ask if bogus newsgroups should be deleted */ X#define RELOCATE /* allow newsgroup rearranging */ X#define ESCSUBS /* escape substitutions in multi-character commands */ X#define DELAYMARK /* allow articles to be temporarily marked as read */ X /* until exit from current newsgroup or Y command */ X#define MCHASE /* unmark xrefed articles on m or M */ X#define MUNGHEADER /* allow alternate header formatting via */ X /* environment variable ALTHEADER (not impl) */ X#define ASYNC_PARSE /* allow parsing headers asyncronously to reading */ X /* used by MCHASE and MUNGHEADER */ X#define FINDNEWNG /* check for new newsgroups on startup */ X#define FASTNEW /* do optimizations on FINDNEWNG for faster startup */ X /* (this optimization can make occasional mistakes */ X /* if a group is removed and another group of the */ X /* same length is added, and if no softpointers are */ X /* affected by said change.) */ X#define INNERSEARCH /* search command 'g' with article */ X#define CATCHUP /* catchup command at newsgroup level */ X#define NGSEARCH /* newsgroup pattern matching */ X#define ONLY /* newsgroup restrictions by pattern */ X#define KILLFILES /* automatic article killer files */ X#define ARTSEARCH /* pattern searches among articles */ X /* /, ?, ^N, ^P, k, K */ X X/* some dependencies among options */ X X#ifndef ARTSEARCH X# undef KILLFILES X# undef INNERSEARCH X# undef CACHESUBJ X#endif X X#ifndef DELAYMARK X# ifndef MCHASE X# ifndef MUNGHEADER X# undef ASYNC_PARSE X# endif X# endif X#endif X X#ifndef SETUIDGID X# define eaccess access X#endif X X#ifdef ONLY /* idiot lint doesn't grok #if */ X# define NGSORONLY X#else X# ifdef NGSEARCH X# define NGSORONLY X# endif X#endif X X#ifdef VERBOSE X# ifdef TERSE X# define IF(c) if (c) X# define ELSE else X# else X# define IF(c) X# define ELSE X# endif X#else /* !VERBOSE */ X# ifndef TERSE X# define TERSE X# endif X# define IF(c) "IF" outside of VERBOSE??? X# define ELSE "ELSE" outside of VERBOSE??? X#endif X X#ifdef DEBUGGING X# define assert(ex) {if (!(ex)){fprintf(stderr,"Assertion failed: file %s, line %d\n", __FILE__, __LINE__);sig_catcher(0);}} X#else X# define assert(ex) ; X#endif X X#ifdef SPEEDOVERMEM X# define OFFSET(x) (x) X#else X# define OFFSET(x) ((x)-absfirst) X#endif X X/* If you're strapped for space use the help messages in shell scripts */ X/* if {NG,ART,PAGER,SUBS}HELP is undefined, help messages are in memory */ X#ifdef MEMHELP /* undef MEMHELP above to get them all as sh scripts */ X# undef NGHELP X# undef ARTHELP X# undef PAGERHELP X# undef SUBSHELP X#else X# ifndef NGHELP /* % and ~ */ X# define NGHELP "%X/ng.help" SHAR_EOF echo "End of part 5" echo "File common.h is continued in part 6" echo "6" > s2_seq_.tmp exit 0 exit 0 # Just in case... -- Please send comp.sources.unix-related mail to rsalz@uunet.uu.net. Use a domain-based address or give alternate paths, or you may lose out.