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