v08i065: The VN news reader, Part02/03
sources-request at mirror.UUCP
sources-request at mirror.UUCP
Wed Feb 18 10:17:07 AEST 1987
Submitted by: rtech!rtech!bobm (Bob Mcqueer)
Mod.sources: Volume 8, Issue 65
Archive-name: vn/Part02
[ I forgot to point out that I repacked the archives because of a patch
Bob sent me. --r$ ]
#! /bin/sh
# This is a shell archive. Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file".
# If all goes well, you will see the message "End of archive 2 (of 3)."
# Contents: reader.c strtok.c term_set.c tty.h tty_set.c tune.h
# userlist.c vn.h vnglob.c
# Wrapped by rs at mirror on Tue Feb 17 12:10:31 1987
PATH=/bin:/usr/bin:/usr/ucb; export PATH
echo shar: extracting "'reader.c'" '(18610 characters)'
if test -f 'reader.c' ; then
echo shar: will not over-write existing file "'reader.c'"
else
sed 's/^X//' >reader.c <<'@//E*O*F reader.c//'
X/*
X** vn news reader.
X**
X** reader.c - article reading interface - "more" like.
X**
X** see copyright disclaimer / history in vn.c source file
X*/
X
X#include <stdio.h>
X#include <sys/types.h>
X#include "tty.h"
X#include "config.h"
X#include "vn.h"
X#include "head.h"
X#include "reader.h"
X
X#define PERTAB 8 /* tab expansion factor */
X#define BACKTRACK 24
X
Xextern char *Printer,*Editor,*Mailer,*Poster,*Orgdir,*Savefile,*Savedir,*Ccfile;
Xextern int L_allow;
Xextern int C_allow;
Xextern int Rot;
Xextern int Headflag;
Xextern int Digest;
Xextern char *No_msg;
Xextern char *Roton_msg;
Xextern char *Rotoff_msg;
Xextern char *Hdon_msg;
Xextern char *Hdoff_msg;
X
Xextern char *T_head, *FT_head, *N_head, *L_head, *RT_head, *DIS_head;
Xextern char *TO_head, *F_head, *P_head, *M_head, *R_head;
X
Xextern char Cxrtoi[], Cxitor[];
X
Xstatic FILE *Fpread;
Xstatic char *Fname;
Xstatic char *Lookahead;
Xstatic int Rlines;
Xstatic int Hlines;
X
X#ifdef ADDRMUNGE
Xstatic int Newaddr;
X#endif
X
X/*
X readstr routine is the "funnel" to the reading state,
X and controls signal setting. Some "session" context is passed
X along to allow jumping back to a different display
X
X WARNING:
X
X NOTHING below readstr should call strtok()
X*/
X
Xreadstr (s,crec,highrec,count)
Xchar *s;
Xint *crec, *highrec;
Xint count;
X{
X char *fnext, *strtok();
X int pc;
X Fname = strtok(s,LIST_SEP);
X if (Fname != NULL)
X {
X term_set (ERASE);
X sig_set (BRK_READ,&Fpread);
X fnext = strtok(NULL,LIST_SEP);
X while (Fname != NULL && readfile(fnext,&pc) >= 0)
X {
X if (Digest)
X unlink (Fname);
X Fname = fnext;
X fnext = strtok (NULL,LIST_SEP);
X }
X if (Digest && Fname != NULL)
X unlink (Fname);
X if (pc != 0)
X forward (pc, crec, highrec);
X else
X {
X *crec += count;
X if (*crec >= *highrec)
X *crec = *highrec - 1;
X }
X sig_set (BRK_RFIN);
X show ();
X term_set (MOVE, 0, *crec);
X }
X else
X {
X preinfo ("%s",No_msg);
X term_set (MOVE, 0, *crec);
X }
X}
X
X/*
X readfile presents article:
X sn - name of next article, NULL if last.
X pages - pages to advance on return, if applicable
X returns 0 for "continue", <0 for "quit"
X*/
Xstatic readfile (sn,pages)
Xchar *sn;
Xint *pages;
X{
X FILE *fopen();
X int lines,percent,artlin;
X long rew_pos, ftell();
X char c, buf[RECLEN], mid[RECLEN], ngrp[RECLEN], dist[RECLEN];
X char from[RECLEN], title[RECLEN], flto[RECLEN], reply[RECLEN];
X char pstr[24], dgname[48], getpgch(), *index(), *digest_extract();
X char *tgetstr();
X
X *pages = 0;
X
X term_set(ERASE);
X
X if (Digest)
X {
X lines = atoi(Fname);
X if ((Fname = digest_extract(dgname,lines)) == NULL)
X {
X printf ("couldn't extract article %d",lines);
X return (0);
X }
X }
X
X if ((Fpread = fopen(Fname,"r")) == NULL)
X {
X printf ("couldn't open article %s",Fname);
X return (0);
X }
X
X Hlines = gethead (mid, from, title, ngrp, flto, reply, dist, &artlin);
X printf (ANFORM,Fname,Cxrtoi[PG_HELP]);
X lines = 1;
X rew_pos = ftell(Fpread);
X if (Headflag)
X {
X rewind(Fpread);
X Rlines = 0;
X }
X else
X {
X /* use do_out to guard against control sequences */
X Rlines = Hlines;
X sprintf (buf,"%s%s\n",T_head,title);
X lines += do_out(buf,1);
X sprintf (buf,"%s%s\n",F_head,from);
X lines += do_out(buf,1);
X if (index(ngrp,',') != NULL)
X {
X sprintf (buf,"%s%s\n",N_head,ngrp);
X lines += do_out(buf,1);
X }
X if (*flto != '\0')
X {
X sprintf (buf,"%s%s\n",FT_head,flto);
X lines += do_out(buf,1);
X }
X printf ("%s%d\n",L_head,artlin); /* no controls */
X ++lines;
X }
X
X /* will return out of outer while loop */
X Lookahead = NULL;
X while (1)
X {
X /*
X ** lines counts folded lines from do_out.
X ** globals Hlines and Rlines refer to records.
X ** If Lookahead is null after this loop, we've
X ** hit EOF.
X */
X lines += do_out(Lookahead,L_allow-lines);
X while (1)
X {
X if (Lookahead == NULL)
X {
X if (fgets(buf,RECLEN-1,Fpread) == NULL)
X break;
X Lookahead = buf;
X if (Rot != 0 && Rlines >= Hlines)
X rot_line(buf);
X ++Rlines;
X }
X if (lines >= L_allow)
X break;
X lines += do_out(buf,L_allow-lines);
X }
X
X if (Lookahead != NULL)
X {
X /*
X ** calculation is truncated rather than rounded,
X ** so we shouldn't get "100%". Subtract 2 for
X ** 1 line lookahead and empty line at beginning
X ** of article.
X */
X if (Headflag)
X percent = ((Rlines-2)*100)/(artlin+Hlines);
X else
X percent = ((Rlines-Hlines-2)*100)/artlin;
X sprintf (pstr,PAGE_MID,percent);
X }
X else
X {
X if (sn == NULL)
X strcpy (pstr,PAGE_END);
X else
X strcpy (pstr,PAGE_NEXT);
X }
X c = getpgch(pstr,mid,from,reply,title,ngrp,flto,dist);
X
X /*
X handle user input:
X CAUTION!! return cases must close Fpread.
X */
X switch (c)
X {
X case PG_NEXT:
X fclose (Fpread);
X return (0);
X case PG_FLIP:
X *pages = 1; /* fall through */
X case PG_QUIT:
X fclose (Fpread);
X return (-1);
X case PG_REWIND:
X if (Headflag)
X {
X Rlines = 0;
X rewind (Fpread);
X }
X else
X {
X fseek (Fpread,rew_pos,0);
X Rlines = Hlines;
X }
X Lookahead = NULL;
X lines = 2 - RECBIAS;
X break;
X case PG_SEARCH:
X searcher(buf);
X lines = 2 - RECBIAS;
X lines += do_out(buf,L_allow-lines);
X break;
X case PG_WIND:
X fseek (Fpread,0L,2);
X lines = 2 - RECBIAS;
X Lookahead = NULL;
X break;
X case PG_STEP:
X if (Lookahead == NULL)
X {
X fclose (Fpread);
X return (0);
X }
X lines = L_allow - 1;
X break;
X default:
X if (Lookahead == NULL)
X {
X fclose (Fpread);
X return (0);
X }
X lines = 2 - RECBIAS;
X break;
X }
X }
X}
X
X/*
X gethead obtains subject, reply, message id, from, lines, newsgroup and
X followup-to lines of article for later use in mailing replies and
X posting followups, does not rewind, but leaves file at end of header
X lines. Returns number of header lines.
X*/
Xstatic gethead (mid, from, title, ngrp, flto, reply, dist, lin)
Xchar *mid, *from, *title, *ngrp, *flto, *reply, *dist;
Xint *lin;
X{
X int count;
X char buf [RECLEN], *index();
X long pos,ftell();
X
X#ifdef ADDRMUNGE
X Newaddr = 1;
X#endif
X
X *lin = 0;
X *dist = *mid = *from = *title = *ngrp = *flto = *reply = '\0';
X
X /* for conditional is abnormal - expected exit is break */
X for (count = 0; count < HDR_LINES && fgets(buf,RECLEN-1,Fpread) != NULL; ++count)
X {
X
X /* reset position and bail out at first non-header line */
X if (index(buf,':') == NULL)
X {
X pos = ftell(Fpread);
X pos -= strlen(buf);
X fseek (Fpread,pos,0);
X break;
X }
X
X#ifdef MAILSMART
X if (strncmp(buf,RT_head,RTHDLEN) == 0)
X {
X buf [strlen(buf)-1] = '\0';
X strcpy (reply,buf+RTHDLEN);
X continue;
X }
X#else
X if (strncmp(buf,P_head,PHDLEN) == 0)
X {
X buf [strlen(buf)-1] = '\0';
X strcpy (reply,buf+PHDLEN);
X continue;
X }
X#endif
X if (strncmp(buf,DIS_head,DISHDLEN) == 0)
X {
X buf [strlen(buf)-1] = '\0';
X strcpy (dist,buf+DISHDLEN);
X continue;
X }
X if (strncmp(buf,M_head,MHDLEN) == 0)
X {
X buf [strlen(buf)-1] = '\0';
X strcpy (mid,buf+MHDLEN);
X continue;
X }
X if (strncmp(buf,F_head,FHDLEN) == 0)
X {
X buf [strlen(buf)-1] = '\0';
X strcpy (from,buf+FHDLEN);
X continue;
X }
X if (strncmp(buf,T_head,THDLEN) == 0)
X {
X buf [strlen(buf)-1] = '\0';
X strcpy (title,buf+THDLEN);
X continue;
X }
X if (strncmp(buf,N_head,NHDLEN) == 0)
X {
X buf [strlen(buf)-1] = '\0';
X strcpy (ngrp,buf+NHDLEN);
X continue;
X }
X if (strncmp(buf,FT_head,FTHDLEN) == 0)
X {
X buf [strlen(buf)-1] = '\0';
X strcpy (flto,buf+FTHDLEN);
X continue;
X }
X if (strncmp(buf,L_head,LHDLEN) == 0)
X {
X buf [strlen(buf)-1] = '\0';
X *lin = atoi(buf+LHDLEN);
X continue;
X }
X }
X#ifdef MAILSMART
X if (*reply == '\0')
X strcpy(reply,from);
X#endif
X return (count);
X}
X
X/*
X getpgch prints prompt and gets command from user
X handles "mail", "save" and "followup" internally
X as well as flag resets.
X*/
Xstatic char getpgch(prompt,mid,from,reply,title,ngrp,flto,dist)
Xchar *prompt, *mid, *from, *reply, *title, *ngrp, *flto, *dist;
X{
X char c;
X int ic;
X term_set (ONREVERSE);
X printf("%s\015",prompt);
X term_set (OFFREVERSE);
X while ((ic=getnoctl()) != EOF)
X {
X switch (c = Cxitor[ic])
X {
X case SETROT:
X term_set (ZAP,0,PPR_MAX);
X if (Rot == 0)
X {
X Rot = 13;
X printf ("%s\n",Roton_msg);
X }
X else
X {
X Rot = 0;
X printf ("%s\n",Rotoff_msg);
X }
X if (Lookahead != NULL && Rlines > Hlines)
X rot_line(Lookahead);
X break;
X case HEADTOG:
X term_set (ZAP,0,PPR_MAX);
X if (Headflag)
X {
X Headflag = FALSE;
X printf ("%s\n",Hdoff_msg);
X }
X else
X {
X Headflag = TRUE;
X printf ("%s\n",Hdon_msg);
X }
X break;
X case PG_HELP:
X term_set (ZAP,0,PPR_MAX);
X help_pg ();
X break;
X case PG_REPLY:
X mail (reply,title,from);
X break;
X case PG_FOLLOW:
X followup (mid,title,ngrp,flto,from,dist);
X break;
X case SAVE:
X saver ();
X break;
X case PRINT:
X printr ();
X break;
X default:
X term_set (ZAP,0,PPR_MAX);
X return (c);
X }
X
X term_set (ONREVERSE);
X printf("%s\015",prompt);
X term_set (OFFREVERSE);
X }
X term_set (ZAP,0,PPR_MAX);
X return (c);
X}
X
X/*
X save article
X Like the savestr routine, it "loses" some storage every time
X the user specifies a new file, but this should not be significant
X*/
Xstatic saver ()
X{
X char *fn,cmd[RECLEN],*str_store(),*rprompt();
X
X tty_set (SAVEMODE);
X sprintf (cmd,SAVFORM,Savefile);
X fn = rprompt(cmd,cmd);
X if (fn != NULL)
X Savefile = str_store(fn);
X if (*Savefile != '/' && *Savefile != '$')
X sprintf (cmd,"cat %s >>%s/%s",Fname,Savedir,Savefile);
X else
X sprintf (cmd,"cat %s >>%s",Fname,Savefile);
X system (cmd);
X tty_set (RESTORE);
X}
X
X/*
X invoke editor on new temp file, mail using reply line,
X possibly first allowing user to overide the reply (not INLETTER)
X*/
Xstatic mail (p, t, f)
Xchar *p, *t, *f;
X{
X char *new, fn[L_tmpnam], cmd [RECLEN+60], *rprompt ();
X FILE *fp, *fopen();
X
X tmpnam (fn);
X if ((fp = fopen(fn,"w")) == NULL)
X printex ("can't open %s\n",fn);
X
X if ((new = index(p, '(')) != NULL)
X *new = '\0'; /* a poor way of deleting comments */
X
X#ifdef ADDRMUNGE
X if (Newaddr)
X {
X Newaddr = 0;
X ADDRMUNGE(p);
X }
X#endif
X
X if (strncmp(t, FPFIX, FPFLEN) == 0)
X t += FPFLEN; /* don't add multiple Re:s */
X#ifdef INLETTER
X fprintf (fp,"%s%s\n%s%s%s\n\n%s:\n", TO_head, p, T_head, FPFIX, t, f);
X#else
X fprintf (fp,"%s%s%s\n\n%s:\n", T_head, FPFIX, t, f);
X#endif
X
X edcopy (fp);
X fclose (fp);
X tty_set (SAVEMODE);
X
X#ifndef INLETTER
X sprintf (cmd,"ADDRESS: %s\nreturn to accept, or input new address: ",p);
X if ((new = rprompt(cmd,cmd)) != NULL)
X strcpy (p,new);
X#endif
X
X sprintf (cmd,"%s %s", Editor, fn);
X chdir (Orgdir);
X system (cmd);
X cd_group ();
X new = rprompt ("still want to mail it ? ",cmd);
X if (new != NULL && (*new == 'y' || *new == 'Y'))
X {
X#ifndef INLETTER
X sprintf (cmd,"%s '%s' <%s", Mailer, p, fn);
X#else
X sprintf (cmd,"%s <%s", Mailer, fn);
X#endif
X system (cmd);
X printf ("given to mailer\n");
X }
X else
X printf ("not mailed\n");
X unlink (fn);
X tty_set (RESTORE);
X term_set (RESTART);
X}
X
X/*
X post a followup article, invoking editor for user after creating
X new temp file. remove after posting. Hack in ".followup" if posting
X newsgroup ends in ".general" - similar hack for preventing mod &
X announce groups - should really be more thorough and parse the
X whole string. User can change, anyway.
X*/
Xstatic followup (m,t,n,ft,oa,dist)
Xchar *m, *t, *n, *ft, *oa, *dist;
X{
X char fn[L_tmpnam], *new, cmd [RECLEN], *rprompt();
X FILE *f, *fopen();
X char *rindex();
X
X if (*ft != '\0')
X strcpy (cmd,ft);
X else
X strcpy (cmd,n);
X new = rindex(cmd,'.');
X if (new != NULL && strcmp(new,".general") == 0)
X strcpy (new,".followup");
X if ( strncmp(cmd, "mod.", 4) == 0 || strcmp(new, ".announce") == 0)
X {
X term_set (ONREVERSE);
X printf("Cannot post a follow-up to \"%s\", reply with mail to moderator\007\n",
X cmd);
X term_set (OFFREVERSE);
X return;
X }
X
X tmpnam (fn);
X if ((f = fopen(fn,"w")) == NULL)
X printex ("can't open %s\n",fn);
X
X if (strncmp(t, FPFIX, FPFLEN) == 0)
X t += FPFLEN; /* don't add multiple Re:s */
X fprintf (f,"%s%s%s\n%s%s\n%s%s\n",T_head,FPFIX,t,N_head,cmd,R_head,m);
X if (*dist != '\0')
X fprintf(f,"%s%s\n",DIS_head,dist);
X fprintf (f,"\nin article %s, %s says:\n",m,oa);
X edcopy (f);
X fclose (f);
X tty_set (SAVEMODE);
X sprintf (cmd,"%s %s", Editor, fn);
X chdir (Orgdir);
X system (cmd);
X cd_group ();
X new = rprompt("still want to post it ? ",cmd);
X if (new != NULL && (*new == 'y' || *new == 'Y'))
X {
X sprintf (cmd,"%s <%s", Poster, fn);
X system (cmd);
X printf ("given to posting program\n");
X save_article (fn);
X }
X else
X printf ("not posted\n");
X unlink (fn);
X tty_set (RESTORE);
X term_set (RESTART);
X}
X
X/*
X get user buffer, return whitespace delimited token
X without using strtok(). buffer is allowed to overwrite
X prompt string.
X*/
Xstatic char *
Xrprompt(s,buf)
Xchar *s,*buf;
X{
X printf("%s",s);
X fgets (buf,RECLEN-1,stdin);
X while (*buf == ' ' || *buf == '\t')
X ++buf;
X if (*buf == '\n' || *buf == '\0')
X return (NULL);
X for (s = buf; *s != ' ' && *s != '\t' && *s != '\n' && *s != '\0'; ++s)
X ;
X *s = '\0';
X return (buf);
X}
X
X/*
X edcopy copies article to file which user is editting for
X a reply or followup, so it may be referenced. It places
X ED_MARK in the left hand margin.
X*/
Xedcopy(fp)
XFILE *fp;
X{
X long current;
X char buf[RECLEN];
X int i;
X
X /* save position, rewind and skip over header lines */
X current = ftell(Fpread);
X rewind (Fpread);
X for (i=0; i < HDR_LINES; ++i)
X {
X if (fgets(buf,RECLEN-1,Fpread) == NULL)
X break;
X if (strncmp(buf,L_head,LHDLEN) == 0)
X break;
X }
X
X /* if line already begins with ED_MARK, forget about the space */
X while (fgets(buf,RECLEN-1,Fpread) != NULL)
X {
X if (buf[0] == ED_MARK)
X fprintf(fp,"%c%s",ED_MARK,buf);
X else
X fprintf(fp,"%c %s",ED_MARK,buf);
X }
X
X /* restore position */
X fseek(Fpread,current,0);
X}
X
X/*
X help menus
X*/
Xstatic help_pg()
X{
X h_print (Cxrtoi[PG_NEXT],HPG_NEXT);
X h_print (Cxrtoi[PG_QUIT],HPG_QUIT);
X h_print (Cxrtoi[PG_FLIP],HPG_FLIP);
X h_print (Cxrtoi[PG_REWIND],HPG_REWIND);
X h_print (Cxrtoi[PG_WIND],HPG_WIND);
X h_print (Cxrtoi[PG_SEARCH],HPG_SEARCH);
X h_print (Cxrtoi[PG_STEP],HPG_STEP);
X h_print (Cxrtoi[PG_REPLY],HPG_REPLY);
X h_print (Cxrtoi[PG_FOLLOW],HPG_FOLLOW);
X h_print (Cxrtoi[SAVE],HPG_SAVE);
X h_print (Cxrtoi[PRINT],HPG_PRINT);
X h_print (Cxrtoi[SETROT],HPG_ROT);
X h_print (Cxrtoi[HEADTOG],HPG_HEAD);
X h_print (Cxrtoi[PG_HELP],HPG_HELP);
X printf ("%s\n",HPG_DEF);
X}
X
Xrot_line (s)
Xunsigned char *s;
X{
X for ( ; *s != '\0'; ++s)
X {
X if (*s >= 'A' && *s <= 'Z')
X {
X *s += Rot;
X if (*s > 'Z')
X *s -= 26;
X continue;
X }
X if (*s >= 'a' && *s <= 'z')
X {
X *s += Rot;
X if (*s > 'z')
X *s -= 26;
X }
X }
X}
X
X/*
X** output record. folds record to terminal width on word boundaries,
X** returning number of lines output. If limit is reached, remainder
X** of buffer waiting to be output is returned. Processes several
X** special characters:
X** form-feed - return "lim" lines so we stop on that line
X** tabs - counts "expanded" width
X** backspace - assumes they work, -1 width unless in first col.
X** bell - pass through with zero width
X** newline - end of record.
X** del - turns into '_'
X** other control - 'A' - 1 added ('01' = ctl-A). Makes escape = "[".
X** (prevents "letter bombs" containing inappropriate control
X** sequences for the terminal).
X**
X** Sets Lookahead pointer to remainder of line or NULL.
X*/
Xstatic do_out(s,lim)
Xchar *s;
Xint lim;
X{
X int len,i;
X char cs,*word,*start;
X
X Lookahead = NULL;
X if (s == NULL)
X return(0);
X len = 0;
X start = word = s;
X
X /*
X ** NOTE: "normal" return is buried inside switch, at newline
X ** ending record
X */
X for (i=0; i < lim; ++i)
X {
X for ( ; len < C_allow; ++s)
X {
X switch (*s)
X {
X case '\n':
X *s = '\0'; /* fall through */
X case '\0':
X printf("%s\n",start);
X return(i+1);
X case '\t':
X len = ((len/PERTAB)+1)*PERTAB;
X word = s;
X break;
X case '\b':
X if (len > 0)
X --len;
X break;
X case '\014':
X *s = ' ';
X i = lim-1; /* fall through */
X case ' ':
X word = s+1;
X ++len;
X break;
X case '\177':
X *s = '_';
X ++len;
X break;
X default:
X if (*s < ' ')
X *s += 'A' - 1;
X ++len; /* fall through */
X case '\07':
X break;
X }
X }
X cs = *s;
X *s = '\0';
X if ((len = strlen(word)) < BACKTRACK)
X {
X *s = cs;
X s = word;
X cs = *s;
X *s = '\0';
X }
X else
X len = 0;
X printf("%s\n",start);
X start = s;
X *s = cs;
X }
X Lookahead = start;
X return(lim);
X}
X
Xsave_article(tempfname)
Xchar *tempfname;
X{
X FILE *in, *out;
X int c;
X time_t timenow, time();
X char *today, *ctime();
X
X
X if ((in = fopen(tempfname, "r")) == NULL)
X return;
X if ((out = fopen(Ccfile, "a")) == NULL)
X {
X fclose(in);
X return;
X }
X timenow = time((time_t)0);
X today = ctime(&timenow);
X fprintf(out,"From vn %s",today);
X while ((c=getc(in)) != EOF)
X putc(c, out);
X putc('\n', out);
X fclose(in);
X fclose(out);
X printf ("a copy has been saved in %s\n", Ccfile);
X}
X
X/*
X send article to printer
X*/
Xstatic printr ()
X{
X char cmd[RECLEN];
X
X tty_set (SAVEMODE);
X printf("Sent to printer\n");
X sprintf (cmd,"%s %s 2>/dev/null",Printer,Fname);
X system (cmd);
X tty_set (RESTORE);
X}
X
X/*
X search article for specified search pattern, returning the line on which
X it is found in buf, a null buffer otherwise. The input file will
X be positioned either after the line on which the pattern is
X found, or unaaltered if match fails.
X*/
Xsearcher (buf)
Xchar *buf;
X{
X static char searchstr[RECLEN] = "";
X char lasave[RECLEN];
X char *s, *reg, *rprompt(), *regcmp(), *regex();
X long current;
X int orlines;
X
X /* save position, then request search pattern */
X current = ftell(Fpread);
X orlines = Rlines;
X
X tty_set (SAVEMODE);
X sprintf (lasave,SEARCHFORM,searchstr);
X s = rprompt(lasave,lasave);
X tty_set (RESTORE);
X if (s != NULL)
X strcpy(searchstr, lasave);
X
X /* Now compile the search string */
X if(( reg = regcmp(searchstr, (char *)0)) == NULL) {
X printf("Invalid search string \"%s\"\n", searchstr);
X *buf = '\0';
X return;
X }
X
X /* try lookahead buffer first */
X if (Lookahead != NULL && regex(reg,Lookahead) != NULL)
X {
X strcpy(buf,Lookahead);
X regfree(reg);
X return;
X }
X
X /* Lookahead can point into buf */
X if (Lookahead != NULL)
X strcpy(lasave,Lookahead);
X
X /* now start reading lines, rotating if necessary and do search */
X while (fgets(buf,RECLEN-1,Fpread) != NULL)
X {
X if (Rot != 0 && Rlines >= Hlines)
X rot_line(buf);
X ++Rlines;
X if( regex(reg, buf) != NULL ){ /* Got it */
X term_set (ONREVERSE);
X printf("\n\tSkipping ....\n\n");
X term_set (OFFREVERSE);
X regfree(reg);
X return;
X }
X }
X
X /* no dice, so restore position */
X regfree(reg);
X term_set (ONREVERSE);
X printf("Cannot find string \"%s\" in remainder of article\007\n",
X searchstr);
X term_set (OFFREVERSE);
X fseek(Fpread,current,0);
X Rlines = orlines;
X if (Lookahead != NULL)
X strcpy(buf,lasave);
X else
X *buf = '\0';
X return(0.0);
X}
@//E*O*F reader.c//
if test 18610 -ne "`wc -c <'reader.c'`"; then
echo shar: error transmitting "'reader.c'" '(should have been 18610 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'strtok.c'" '(1082 characters)'
if test -f 'strtok.c' ; then
echo shar: will not over-write existing file "'strtok.c'"
else
sed 's/^X//' >strtok.c <<'@//E*O*F strtok.c//'
X/*
X** vn news reader.
X**
X** strtok.c - strtok() and strpbrk() string routines using UCB index().
X**
X** see copyright disclaimer / history in vn.c source file
X*/
X
X#include <stdio.h>
X
Xchar *strpbrk (s,del)
Xchar *s, *del;
X{
X char *ptr,*index();
X if (s == NULL)
X return (NULL);
X for (; *del != '\0'; ++del)
X if ((ptr = index(s,*del)) != NULL)
X return (ptr);
X return (NULL);
X}
X
Xchar *strtok(str,delim)
Xchar *str, *delim;
X{
X char *tokstart, *tokend, *first_ch (), *last_ch();
X static char *save=NULL;
X
X if (str != NULL)
X save = str;
X
X if (save == NULL)
X return (NULL);
X
X tokstart = first_ch (save, delim);
X tokend = last_ch (tokstart, delim);
X save = first_ch (tokend, delim);
X *tokend = '\0';
X
X if (*tokstart == '\0')
X return (NULL);
X
X return (tokstart);
X}
X
Xstatic char *first_ch (str,delim)
Xchar *str,*delim;
X{
X char *index ();
X char *f;
X
X for (f = str; *f != '\0' && index(delim,*f) != NULL; ++f)
X ;
X
X return (f);
X}
X
Xstatic char *last_ch (str,delim)
Xchar *str,*delim;
X{
X char *index ();
X char *f;
X
X for (f = str; *f != '\0' && index(delim,*f) == NULL; ++f)
X ;
X
X return (f);
X}
@//E*O*F strtok.c//
if test 1082 -ne "`wc -c <'strtok.c'`"; then
echo shar: error transmitting "'strtok.c'" '(should have been 1082 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'term_set.c'" '(4914 characters)'
if test -f 'term_set.c' ; then
echo shar: will not over-write existing file "'term_set.c'"
else
sed 's/^X//' >term_set.c <<'@//E*O*F term_set.c//'
X/*
X** vn news reader.
X**
X** term_set.c - terminal control, hides termcap interface
X**
X** see copyright disclaimer / history in vn.c source file
X*/
X
X#include <stdio.h>
X#include "tty.h"
X#include "vn.h"
X
Xextern int L_allow, C_allow;
Xextern char *Ku, *Kd, *Kl, *Kr;
X
Xstatic outc (c)
Xchar c;
X{
X putchar (c);
X}
X
X/*
X term_set controls terminal through termcap
X START sets global parameters related to terminal also,
X as well as allocating display buffer which depends on
X terminal lines, and allocating escape strings. RESTART
X simply re-issues the initialization - used following system
X calls that could have goofed up the terminal state.
X*/
X
X/*
X** Escape strings.
X*/
X
Xstatic char *Cm,*Cl,*So,*Se,*Te,*Bc,*Ce,*Ti,*Ks,*Ke;
X#ifdef USEVS
Xstatic char *Vs,*Ve;
X#endif
X
Xstatic int Backspace; /* backspace works */
Xstatic int Overstrike; /* terminal overstrikes */
X
Xstatic t_setup()
X{
X int i;
X char *tgetstr(), *getenv(), *str_store();
X char *c, tc_buf[2048],optstr[2048];
X
X c = optstr;
X if (tgetent(tc_buf,getenv("TERM")) != 1)
X printex ("%s - unknown terminal",getenv("TERM"));
X
X /* get needed capabilities */
X Cm = str_store(tgetstr("cm",&c));
X Cl = str_store(tgetstr("cl",&c));
X So = str_store(tgetstr("so",&c));
X Se = str_store(tgetstr("se",&c));
X Te = str_store(tgetstr("te",&c));
X Ti = str_store(tgetstr("ti",&c));
X Bc = str_store(tgetstr("bc",&c));
X Ce = str_store(tgetstr("ce",&c));
X Kd = str_store(tgetstr("kd",&c));
X Ke = str_store(tgetstr("ke",&c));
X Kl = str_store(tgetstr("kl",&c));
X Kr = str_store(tgetstr("kr",&c));
X Ks = str_store(tgetstr("ks",&c));
X Ku = str_store(tgetstr("ku",&c));
X#ifdef USEVS
X Vs = str_store(tgetstr("vs",&c));
X Ve = str_store(tgetstr("ve",&c));
X#endif
X Backspace = tgetflag("bs");
X Overstrike = tgetflag("os");
X
X if ( *Cm == '\0' || *Cl == '\0')
X {
X printex ("cursor control and erase capability needed");
X }
X
X /*
X ** Checks for arrow keys which don't issue something beginning
X ** with <ESC>. This is more paranoid than we need to be, strictly
X ** speaking - we could get away with any string which didn't
X ** conflict with controls used for commands. However, that would
X ** be a maintenance headache - we will simply reserve <ESC> as the
X ** only char not to be used for commands, and punt on terminals
X ** which don't send reasonable arrow keys. It would be confusing
X ** to have keys work partially, also. I know of no terminal with
X ** one arrow key beginning with an escape, and another beginning
X ** with something else, but let's be safe. This also insists on
X ** definitions for all 4 arrows, which seems reasonable.
X */
X
X if ((*Ku != '\0' && *Ku != '\033') || *Kl != *Ku || *Kr != *Ku || *Kd != *Ku)
X {
X fgprintf("WARNING: arrow keys will not work for this terminal");
X Ku = Kd = Kl = Kr = Kd = Ke = "";
X }
X
X if (Overstrike)
X fgprintf ("WARNING: terminal overstrikes - can't update display without erase\n");
X
X i = RECBIAS+1 < HHLINES+2 ? HHLINES+2 : RECBIAS+1;
X if ((L_allow = tgetnum("li")) < i)
X {
X if (L_allow < 0)
X printex ("can't determine number of lines on terminal");
X printex ("too few lines for display - %d needed", i);
X }
X
X /*
X ** C_allow set so as to not use extreme right column.
X ** Avoids "bad wraparound" problems - we're deciding it's best
X ** to ALWAYS assume no automargin, and take care of it ourselves
X */
X if((C_allow = tgetnum("co")) > MAX_C)
X C_allow = MAX_C;
X else
X --C_allow;
X if (C_allow < MIN_C)
X {
X if (C_allow < 0)
X printex("can't determine number of columns on terminal.");
X printex ("too few columns for display - %d needed",MIN_C);
X }
X
X L_allow -= RECBIAS;
X page_alloc();
X tputs(Ti,1,outc);
X tputs(Ks,1,outc);
X#ifdef USEVS
X tputs(Vs,1,outc);
X#endif
X}
X
X/* VARARGS */
Xterm_set(cmd,x,y)
Xint cmd,x,y;
X{
X char *tgoto();
X int i;
X switch (cmd)
X {
X case MOVE:
X tputs (tgoto(Cm,x,y),1,outc);
X break;
X case ERASE:
X tputs(Cl,1,outc);
X break;
X case ONREVERSE:
X tputs(So,1,outc);
X break;
X case OFFREVERSE:
X tputs(Se,1,outc);
X break;
X case START:
X t_setup();
X break;
X case RESTART:
X tputs(Ti,1,outc);
X tputs(Ks,1,outc);
X#ifdef USEVS
X tputs(Vs,1,outc);
X#endif
X break;
X case STOP:
X term_set (MOVE,0,L_allow+RECBIAS-1);
X printf ("\n");
X tputs(Ke,1,outc);
X tputs(Te,1,outc);
X#ifdef USEVS
X tputs(Ve,1,outc);
X#endif
X break;
X case RUBSEQ:
X if (Overstrike)
X {
X /* space overprint is futile */
X if (Backspace)
X putchar('\010');
X else
X tputs(Bc,1,outc);
X break;
X }
X if (Backspace)
X printf("%c %c",'\010','\010');
X else
X {
X tputs(Bc,1,outc);
X putchar(' ');
X tputs(Bc,1,outc);
X }
X break;
X case ZAP:
X if (Ce != NULL && *Ce != '\0')
X tputs(Ce,1,outc);
X else
X {
X if (Overstrike)
X break; /* punt */
X for (i=x; i < y; ++i)
X putchar(' ');
X if (Backspace)
X {
X for (i=x; i < y; ++i)
X putchar('\010');
X }
X else
X {
X for (i=x; i < y; ++i)
X tputs(Bc,1,outc);
X }
X }
X break;
X default:
X printex ("term_set unknown code (%d)",cmd);
X break;
X }
X return (0);
X}
@//E*O*F term_set.c//
if test 4914 -ne "`wc -c <'term_set.c'`"; then
echo shar: error transmitting "'term_set.c'" '(should have been 4914 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'tty.h'" '(404 characters)'
if test -f 'tty.h' ; then
echo shar: will not over-write existing file "'tty.h'"
else
sed 's/^X//' >tty.h <<'@//E*O*F tty.h//'
X/*
X** vn news reader.
X**
X** tty.h - codes for tty_set and term_set
X**
X** see copyright disclaimer / history in vn.c source file
X*/
X
X#define MOVE 100
X#define ERASE 101
X#define START 102
X#define STOP 103
X#define RUBSEQ 104
X#define ZAP 105
X#define ONREVERSE 106
X#define OFFREVERSE 107
X#define RESTART 108
X
X#define RAWMODE 200
X#define COOKED 201
X#define SAVEMODE 202
X#define RESTORE 203
X#define BACKSTOP 204
@//E*O*F tty.h//
if test 404 -ne "`wc -c <'tty.h'`"; then
echo shar: error transmitting "'tty.h'" '(should have been 404 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'tty_set.c'" '(2552 characters)'
if test -f 'tty_set.c' ; then
echo shar: will not over-write existing file "'tty_set.c'"
else
sed 's/^X//' >tty_set.c <<'@//E*O*F tty_set.c//'
X/*
X** vn news reader.
X**
X** tty_set.c - interface to ioctl (system tty interface)
X**
X** see copyright disclaimer / history in vn.c source file
X*/
X
X#ifdef SYSV
X#include <termio.h>
X#else
X#include <sgtty.h>
X#endif
X
X#include "tty.h"
X
Xextern char Erasekey,Killkey;
X
X#ifdef SYSV
Xstatic struct termio C_tp, O_tp;
X#else
Xstatic struct sgttyb C_tp;
Xstatic unsigned short O_lflag;
X#endif
X
Xstatic unsigned S_flag=0;
Xstatic int R_ignore=0; /* up/down counter of reset calls to ignore */
X
X#define IO_GOT 1 /* have polled for original terminal mode */
X#define IO_RAW 2 /* in RAW (CBREAK actually) mode */
X
X/*
X tty_set handles ioctl calls. SAVEMODE, RESTORE are used around
X system calls and interrupts to assure cooked mode, and restore
X raw if raw on SAVEMODE. The pair results in no calls to ioctl
X if we are cooked already when SAVEMODE is called, and may be nested,
X provided we desire no "restore" of cooked mode after restoring raw.
X
X When we get the original terminal mode, we also save erase and kill.
X
X sig_set makes an ioctl call to get process group leader. Otherwise
X ioctl calls should come through here.
X*/
Xtty_set(cmd)
Xint cmd;
X{
X int rc;
X unsigned mask;
X
X switch (cmd)
X {
X case BACKSTOP:
X#ifdef JOBCONTROL
X if ((rc = ioctl(1,TIOCLGET,&mask)) != 0)
X break;
X mask |= LTOSTOP;
X rc = ioctl(1,TIOCLSET,&mask);
X#else
X rc = 0;
X#endif
X break;
X case RAWMODE:
X if ((S_flag & IO_RAW) != 0)
X {
X rc = 0;
X break;
X }
X if ((S_flag & IO_GOT) == 0)
X {
X /* Save original modes, get erase / kill */
X#ifdef SYSV
X rc = ioctl(0,TCGETA,&C_tp);
X O_tp = C_tp;
X Erasekey = C_tp.c_cc[VERASE];
X Killkey = C_tp.c_cc[VKILL];
X#else
X rc = ioctl(0,TIOCGETP,&C_tp);
X O_lflag = C_tp.sg_flags;
X Erasekey = C_tp.sg_erase;
X Killkey = C_tp.sg_kill;
X#endif
X }
X#ifdef SYSV
X C_tp.c_lflag &= ~(ECHO | ICANON);
X C_tp.c_cc[VMIN] = 1;
X rc = ioctl(0,TCSETAW,&C_tp);
X#else
X C_tp.sg_flags |= CBREAK;
X C_tp.sg_flags &= ~ECHO;
X rc = ioctl(0,TIOCSETP,&C_tp);
X#endif
X S_flag = IO_GOT|IO_RAW;
X break;
X case COOKED:
X if ((S_flag & IO_RAW) != 0)
X {
X#ifdef SYSV
X C_tp = O_tp;
X rc = ioctl(0,TCSETAW,&C_tp);
X#else
X C_tp.sg_flags = O_lflag;
X rc = ioctl(0,TIOCSETP,&C_tp);
X#endif
X S_flag &= ~IO_RAW;
X }
X else
X rc = 0;
X break;
X case SAVEMODE:
X if ((S_flag & IO_RAW) != 0)
X {
X tty_set(COOKED);
X R_ignore = 0;
X }
X else
X ++R_ignore;
X rc = 0;
X break;
X case RESTORE:
X if (R_ignore <= 0)
X {
X tty_set(RAWMODE);
X }
X else
X --R_ignore;
X rc = 0;
X break;
X default:
X rc = -1;
X }
X if (rc < 0)
X printex ("ioctl failure, tty_set: %d",cmd);
X}
@//E*O*F tty_set.c//
if test 2552 -ne "`wc -c <'tty_set.c'`"; then
echo shar: error transmitting "'tty_set.c'" '(should have been 2552 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'tune.h'" '(2613 characters)'
if test -f 'tune.h' ; then
echo shar: will not over-write existing file "'tune.h'"
else
sed 's/^X//' >tune.h <<'@//E*O*F tune.h//'
X/*
X** vn news reader.
X**
X** tune.h - system tuning parameters
X**
X** see copyright disclaimer / history in vn.c source file
X*/
X
X/*
X** buffer size needed for tmpnam()
X*/
X#ifndef L_tmpnam
X#define L_tmpnam 48
X#endif
X
X/*
X** hash table size. linked list type of table which can expand to
X** arbitrary density, including densities > 100%. Number of entries
X** will be number of newsgroups in active list. This should be a prime
X** number ("long division" of string modulo table size hash function).
X*/
X#define HASHSIZE 809
X
X/*
X** maximum number of columns on terminal. If made smaller, there
X** will be a savings in the size of the temporary file used
X** for holding displays, at the penalty of not being able to use
X** the entire screen width on terminals actually possessing more
X** columns than this. A block roughly on the order of this value
X** times the number of lines the terminal has is maintained per page in
X** the temp file, and read / written as displays are interacted
X** with. MIN_C put here because MAX_C > MIN_C. MIN_C is the minumum
X** number of columns for which a "reasonable" display can be produced.
X** before making it smaller, look at all uses of C_allow and variable
X** to see that a setting that small won't screw up array bounds.
X*/
X#define MAX_C 132
X#define MIN_C 36
X
X/*
X** large size for general purpose local buffers. only used in automatic
X** variable declarations. Used with fgets for buffer size when reading
X** file records, to hold pathnames, commands, etc. Reduce if you blow
X** out stack storage. If reduced too far, will eventually show up
X** as syntax errors on reading .newsrc's and the active list, and
X** scrozzled article information arising from truncated header lines.
X** The reply path line will probably be the first thing to cause trouble.
X** Look through the reader to find the worst case chain of declarations
X** (on the order of 12 or so is probably the max).
X*/
X#define RECLEN 1200
X
X/*
X** to protect against reading entire articles to find non-existent header
X** lines if an article should be hosed, only a limited number of records
X** are searched. Should be big enough to get down to the last header
X** entry on legitimate articles.
X*/
X#define HDR_LINES 24 /* records of article to search for header line */
X
X/* these determine some static array sizes */
X#define OPTLINES 60 /* maximum number of option lines in .newsrc */
X#define NUMFILTER 24 /* max number of filters on articles */
X
X/* block sizes for allocation routines */
X#define STRBLKSIZE 1800 /* string storage allocation block */
X#define NDBLKSIZE 50 /* NODE structures to allocate at a time */
@//E*O*F tune.h//
if test 2613 -ne "`wc -c <'tune.h'`"; then
echo shar: error transmitting "'tune.h'" '(should have been 2613 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'userlist.c'" '(1923 characters)'
if test -f 'userlist.c' ; then
echo shar: will not over-write existing file "'userlist.c'"
else
sed 's/^X//' >userlist.c <<'@//E*O*F userlist.c//'
X/*
X** vn news reader.
X**
X** userlist.c - generate user's list of articles
X**
X** see copyright disclaimer / history in vn.c source file
X*/
X
X#include <stdio.h>
X#include "vn.h"
X
Xextern PAGE Page;
X
X/*
X generate user list of articles - either article numbers
X are input directly (numeric list), or input is a search
X string - invoke regular expression library and examine titles
X search string "*" reserved for marked articles. Strings may
X be prefixed with '!' for negation.
X*/
Xuserlist (list)
Xchar *list;
X{
X int i,j,anum[RECLEN/2],acount;
X char neg, *s, sbuf[MAX_C+1], *reg, *regex(), *regcmp(), *index(), *strtok();
X
X user_str (sbuf,"Articles or title search string : ",1);
X if (sbuf[0] == '!')
X {
X neg = '!';
X s = sbuf+1;
X }
X else
X {
X neg = '\0';
X s = sbuf;
X }
X for (i=0; s[i] != '\0'; ++i)
X {
X if (index(LIST_SEP,s[i]) == NULL)
X {
X if (s[i] < '0' || s[i] > '9')
X break;
X }
X }
X acount = 0;
X
X if (s[i] == '\0')
X {
X for (s = strtok(s,LIST_SEP); s != NULL; s = strtok(NULL,LIST_SEP))
X {
X anum[acount] = atoi(s);
X ++acount;
X }
X }
X else
X {
X if (s[0] == ART_MARK)
X {
X for (i=0; i < Page.h.artnum; ++i)
X {
X if (Page.b[i].art_mark == ART_MARK)
X {
X anum[acount] = Page.b[i].art_id;
X ++acount;
X }
X }
X }
X else
X {
X reg = regcmp(s,(char *) 0);
X if (reg != NULL)
X {
X for (i=0; i < Page.h.artnum; ++i)
X {
X if (regex(reg,Page.b[i].art_t) != NULL)
X {
X anum[acount] = Page.b[i].art_id;
X ++acount;
X }
X }
X regfree (reg);
X }
X else
X preinfo ("bad regular expression syntax");
X }
X }
X
X /* algorithm is inefficient, but we're only handling a few numbers */
X *list = '\0';
X for (i=0; i < Page.h.artnum; ++i)
X {
X for (j=0; j < acount && anum[j] != Page.b[i].art_id; ++j)
X ;
X if (neg == '!')
X {
X if (j < acount)
X continue;
X }
X else
X {
X if (j >= acount)
X continue;
X }
X sprintf (list,"%d ",Page.b[i].art_id);
X list += strlen(list);
X }
X}
@//E*O*F userlist.c//
if test 1923 -ne "`wc -c <'userlist.c'`"; then
echo shar: error transmitting "'userlist.c'" '(should have been 1923 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'vn.h'" '(4278 characters)'
if test -f 'vn.h' ; then
echo shar: will not over-write existing file "'vn.h'"
else
sed 's/^X//' >vn.h <<'@//E*O*F vn.h//'
X/*
X** vn news reader.
X**
X** vn.h - general parameters
X**
X** see copyright disclaimer / history in vn.c source file
X*/
X
X#include "tune.h"
X
X#define TRUE 1
X#define FALSE 0
X
X#ifdef OLDRC
X#define NARGOPT "lprxfuMs"
X#else
X#define NARGOPT "lprxfuMsi"
X#endif
X
X#define FIL_AUTHOR 'w'
X#define FIL_TITLE 't'
X
X/*
X newsrc states
X*/
X#define NEWS_ON ':'
X#define NEWS_OFF '!'
X
X/* bit flags for state of newsgroup */
X#define FLG_SCAN 1
X#define FLG_SUB 2
X#define FLG_PAGE 4
X#define FLG_WRIT 8
X#define FLG_SPEC 16
X
X#define LIST_SEP " ,"
X#define ED_MARK '>'
X#define ART_MARK '*'
X#define ART_WRITTEN '_'
X#define ART_UNWRITTEN ' '
X
X#define FPFIX "Re: "
X#define FPFLEN 4
X
X#define ANFORM ":%s - %c for help:\n"
X#define ANFLINES 1
X#define NOFORM "can't open article %s\n"
X#define NEWGFORM "groups not mentioned in %s:\n"
X#define SAVFORM "save file (%s) ? "
X#define UDKFORM "undefined key - %c for help"
X#define HELPFORM "%c for help"
X
X/*
X page display format and dependent parameters
X*/
X#define HFORMAT "\n%s (page %d of %d):"
X#define DHFORMAT "\n%s (DIGEST EXTRACTION):"
X#define TFORMAT "%s ~ %s %s"
X#define AFORMAT "\n%c%c%d) " /* begin with newline - see show routine */
X#define CFORMAT "page %d of %d (%d shown), newsgroup %d of %d"
X#define RECBIAS 2 /* lines before articles - depends on HFORMAT */
X#define AFLEN 5 /* min. char. in article id - depends on AFORMAT */
X#define WRCOL 1 /* column of written mark. depends on AFORMAT */
X#define INFOLINE 0 /* HFORMAT TFORMAT leaves for use */
X
X/*
X command characters - don't use numerics or <ESC>
X ALTSAVE is a hack to avoid having to use ctl-s - XON/XOFF.
X Wanted to preserve "s" pneumonic and lower / control /cap
X convention.
X*/
X#define DIGEST 'd'
X#define UP 'k'
X#define DOWN 'j'
X#define FORWARD '\012'
X#define BACK '\010'
X#define READ 'r'
X#define ALTREAD ' '
X#define READALL 'R'
X#define READSTRING '\022'
X#define SAVE 's'
X#define SAVEALL 'S'
X#define SAVESTRING '\023'
X#define ALTSAVE '\024'
X#define PRINT 'p'
X#define PRINTALL 'P'
X#define PRINTSTRING '\020'
X#define MARK 'x'
X#define UNMARK 'X'
X#define REDRAW '\014'
X#define QUIT 'q'
X#define SSTAT '#'
X#define GRPLIST '%'
X#define ORGGRP 'o'
X#define ORGSTAT 'O'
X#define UPDATE 'w'
X#define UNSUBSCRIBE 'u'
X#define UPALL 'W'
X#define UPSEEN '\027'
X#define UNESC '!'
X#define NEWGROUP 'n'
X#define HEADTOG 'h'
X#define SETROT 'z'
X#define HELP '?'
X#define HELP_HEAD "[...] = effect of optional number preceding command\n\
Xpipes are specified by filenames beginning with |\n\
Xarticles specified as a list of numbers, title search string, or\n\
X * to specify marked articles. ! may be used to negate any\n"
X
X#define HHLINES 5 /* lines (CRs + 1) contained in HELP_HEAD */
X
X/*
X state flags for handling breaks / values for sig_set calls.
X BRK_IN, BRK_SESS, BRK_READ and BRK_OUT are the states. All
X but BRK_INIT are used as calls to sig_set. BRK_RFIN indicates
X a return from BRK_READ to BRK_SESS (no jump location passed),
X*/
X#define BRK_INIT 0 /* initial value, indicating uncaught signals */
X#define BRK_IN 1 /* in NEWSRC / article scanning phase */
X#define BRK_SESS 2 /* in page interactive session */
X#define BRK_READ 3 /* reading articles */
X#define BRK_RFIN 4 /* finished reading, return to old mode */
X#define BRK_OUT 5 /* NEWSRC updating phase */
X
X#define BRK_PR "really quit ? "
X#define BRK_MSG "\nQUIT (signal %d)"
X
X/*
X newsgroup structure (node of hash table)
X next - hashtable link
X nd_name - name of newsgroup (key to reach node by)
X pnum - page number, initially used to establish Newsorder
X pages - number of pages for news display
X rdnum - articles read
X orgrd - original articles read number
X pgshwn - pages shown mask
X pgrd - article number on highest conecutively shown page
X art - articles in group
X state - status
X*/
Xtypedef struct _node
X{
X struct _node *next;
X char *nd_name;
X int pnum,pages,art,rdnum,orgrd,pgrd;
X unsigned long pgshwn;
X unsigned state;
X} NODE;
X
X/*
X newsgroup information for page display
X name - of group
X group - pointer to table entry
X artnum - number of articles
X*/
Xtypedef struct
X{
X char *name;
X NODE *group;
X int artnum;
X} HEAD;
X
X/*
X article information - id (spool) number, title string, mark, written.
X*/
Xtypedef struct
X{
X int art_id;
X char art_mark;
X char art_written;
X char art_t[MAX_C-AFLEN];
X} BODY;
X
Xtypedef struct
X{
X HEAD h;
X BODY *b;
X} PAGE;
@//E*O*F vn.h//
if test 4278 -ne "`wc -c <'vn.h'`"; then
echo shar: error transmitting "'vn.h'" '(should have been 4278 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'vnglob.c'" '(1613 characters)'
if test -f 'vnglob.c' ; then
echo shar: will not over-write existing file "'vnglob.c'"
else
sed 's/^X//' >vnglob.c <<'@//E*O*F vnglob.c//'
X/*
X** vn news reader.
X**
X** vnglob.c - global variables - see string.c also
X**
X** see copyright disclaimer / history in vn.c source file
X*/
X
X#include <stdio.h>
X#include "config.h"
X#include "vn.h"
X#include "head.h"
X
X/*
X global data structure
X*/
XNODE **Newsorder; /* .newsrc file order */
X
Xchar *Editor,*Ps1,*Mailer,*Printer,*Poster;
X
Xchar Erasekey, Killkey; /* user keys from stty */
Xchar *Newsrc, *Orgdir; /* .newsrc file, and original pwd */
Xchar *Onews; /* temp. file for backing up .newsrc */
Xchar *Savefile = DEF_SAVE; /* file in which to save articles */
Xchar *Savedir; /* default directory for saved articles */
Xchar *Ccfile; /* author_copy file, stored /bin/mail fmt */
X
Xint Rot; /* rotation */
Xint Headflag; /* header printing flag */
Xint Digest; /* if non-zero, digest article */
X
Xchar *Ku, *Kd, *Kl, *Kr; /* Cursor movement capabilities */
X
X/* character translation arrays for commands */
Xchar Cxitop[128], Cxitor[128], Cxrtoi[128], Cxptoi[128];
X
X/*
X cur_page - current page displayed;
X lrec - last record
X l_allow - lines allowed for article display
X c_allow - columns allowed
X ncount = newsorder index
X nfltr - number of filters
X*/
Xint Cur_page, Lrec, L_allow, C_allow, Ncount, Nfltr;
X
X/*
X article filtration options.
X*/
Xchar *Wopt[NUMFILTER]; /* regular expressions for -w options */
Xchar *Topt[NUMFILTER]; /* regular expressions for -t options */
Xchar *Negwopt[NUMFILTER]; /* regular expressions for negated -w options */
Xchar *Negtopt[NUMFILTER]; /* regular expressions for negated -t options */
X
Xint Nwopt, Ntopt, Nnwopt, Nntopt;
X
Xint Nounsub, Listfirst;
X/*
X current page
X*/
XPAGE Page;
@//E*O*F vnglob.c//
if test 1613 -ne "`wc -c <'vnglob.c'`"; then
echo shar: error transmitting "'vnglob.c'" '(should have been 1613 characters)'
fi
fi # end of overwriting check
echo shar: "End of archive 2 (of 3)."
cp /dev/null ark2isdone
DONE=true
for I in 1 2 3; do
if test -! f ark${I}isdone; then
echo "You still need to run archive ${I}."
DONE=false
fi
done
case $DONE in
true)
echo "You have run all 3 archives."
echo 'Now read the README'
;;
esac
## End of shell archive.
exit 0
More information about the Mod.sources
mailing list