[comp.os.minix] Vn for Minix, part 1 of 4

nick@ultima.cs.uts.oz (Nick Andrew) (11/26/89)

	Since I've been using this Vn under Minix for over 6 months without
problems, I thought it was time to post it to the net. This is the 4/88
version of Vn, as modified for Minix.

Share and Enjoy ... Nick.


			"Zeta Microcomputer Software"
ACSnet:    nick@ultima.cs.uts.oz
UUCP:      ...!uunet!munnari!ultima.cs.uts.oz!nick
Fidonet:   Nick Andrew on 3:713/602 (Zeta)

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of shell archive."
# Contents:  brk.h config.h config_std.h digest.c envir_set.c getch.c
#   hash.c head.h help.c makefile
# Wrapped by nick@ultima on Sun Nov 26 22:15:38 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'brk.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'brk.h'\"
else
echo shar: Extracting \"'brk.h'\" \(750 characters\)
sed "s/^X//" >'brk.h' <<'END_OF_FILE'
X/*
X** vn news reader.
X**
X** brk.h - codes for sig_set routine
X**
X** see copyright disclaimer / history in vn.c source file
X*/
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 ? "
END_OF_FILE
if test 750 -ne `wc -c <'brk.h'`; then
    echo shar: \"'brk.h'\" unpacked with wrong size!
fi
# end of 'brk.h'
fi
if test -f 'config.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'config.h'\"
else
echo shar: Extracting \"'config.h'\" \(4479 characters\)
sed "s/^X//" >'config.h' <<'END_OF_FILE'
X/*
X** vn news reader.
X**
X** config.h - system configuration parameters
X**
X** see copyright disclaimer / history in vn.c source file
X*/
X
X#define DEF_ED "/bin/mined"	/* editor to use if no EDITOR variable */
X#define DEF_PS1 "$ "		/* ! command prompt if no PS1 */
X#define DEF_SAVE ""		/* save file */
X
X#define DEF_PRINT "/usr/bin/lpr"		/* print command */
X
X#define DEF_CCFILE "author_copy"
X#define DEF_KEYXLN ".vnkey"
X
X/*
X** this is the "pre-typed" string the user will be presented with
X** in answer to the "update" question following the QUIT command.
X** Set to "" if you don't like it answering "yes" for you, or "y"
X** if you only want to have to erase one character to say "no", etc.
X*/
X#define QUIT_ANSWER ""
X
X/*
X** default terminal assumed if TERM variable is unset.  Since TERM has to
X** be set for most UNIX tools, you probably want to make this something
X** which will cause failure, unless EVERYBODY has the same kind of terminal
X** or you don't really use a standard UNIX environment.
X*/
X#define DEF_TERM "minix"
X
X/*
X** foreground flag for messages.  applies only if JOBCONTROL undefined
X** (SYS V). set to 1 to see newsgroup messages, etc. during reading phase,
X** 0 for "silent" operation - be warned that this may suppress some
X** non-fatal diagnostic messages - find all references to fgprintf to
X** see what is suppressed.
X*/
X#define NOJOB_FG 1
X
X/*
X** bit mask for interpreting command characters.  Set it to 0xff, and
X** we should be able to handle 8 bit characters for control keys -
X** leaving it 0x7f protects against possible parity bits in ascii
X** characters.  A lot of the general paranoia about character handling
X** in raw mode comes from one of the earliest versions which was
X** run on an amdahl using an IBM series 1 front end - it had a very
X** brain damaged implementation of ioctl().
X*/
X#define CHMASK 0x7f
X
X/*
X** arrow key treatment.  If PAGEARROW is defined, right and left arrow
X** keys will be synonyms for <return> (next-page) and <backspace> (previous).
X** Otherwise, the right arrow will function as down, and the left as up.
X** Made configurable because while there is no lateral motion on the screen
X** to associate with the right and left arrows, you might not like them
X** changing pages on you.
X*/
X#define PAGEARROW
X
X/*
X** if USEVS is defined, terminal initialization / exit for vn will include the
X** "vs"/"ve" pair as well as "ti"/"te".  This doesn't matter on a lot of
X** terminals, but may make vn display behaviour closer to "vi" since vs/ve
X** is vi's "visual mode" sequence.  For instance, I believe the commonly
X** used definitions for these strings on multi-page concepts allows the
X** program to run in the first page of the terminal, preserving the more
X** recent part of your session on exit
X**
X** #define USEVS
X*/
X
X/*
X** temp file name template for mktemp().  Used in tmpnam.c, does not apply
X** if you use a system library tmpnam().   BE CAREFUL - VNTEMPNAME MUST
X** contain a string of 6 X's for mktemp() (actually, a place where 6 X's
X** are intended to go).  TMP_XOFFSET absolutely MUST point to the first of
X** the X's.  Yes, writing into a literal string is sloppy.  To the best of
X** my knowledge, tmpnam.c is the only place you'll find vn code doing it.
X** We make this configurable in case you want temp files somewhere else.
X*/
X#define VNTEMPNAME "/usr/tmp/vnXXXXXX"
X#define TMP_XOFFSET 11
X
X/*
X** VNLOGFILE and VNSTATFILE.  If these files EXIST, the corresponding data
X** collection will be turned on.  If they don't it will be turned off.
X** To turn it back on again, create the files empty.  Garbage in VNLOGFILE
X** won't hurt collection but VNSTATFILE requires very strict syntax, so
X** make sure its always an empty file or EXACTLY the right syntax.  See stat.c
X**
X** VNLOGFILE logs user sessions.  VNSTATFILE keeps a running breakdown
X** of newsgroup activity.  I add these with some hesitancy, as I find
X** use of things like this for Gestapo-like purposes repugnant in the
X** extreme.  However, they can also be useful for system tuning purposes
X** such as verifying what newsgroups are being read, and when load on
X** the system due to newsreading is occurring.
X**
X** If VNLOGFILE and VNSTATFILE are NOT DEFINED, the code for doing logging
X** and statistical collection will not be compiled in, saving some overhead,
X** and avoiding calls to system functions like ctime() and time() which may
X** have system dependent quirks.
X**
X*/
X#define VNLOGFILE "/usr/tmp/vn.log"
X#define VNSTATFILE "/usr/tmp/vn.stat"
END_OF_FILE
if test 4479 -ne `wc -c <'config.h'`; then
    echo shar: \"'config.h'\" unpacked with wrong size!
fi
# end of 'config.h'
fi
if test -f 'config_std.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'config_std.h'\"
else
echo shar: Extracting \"'config_std.h'\" \(2802 characters\)
sed "s/^X//" >'config_std.h' <<'END_OF_FILE'
X/*
X** default news poster
X*/
X#define DEF_POST "/usr/lib/news/inews -h"
X
X/*
X** default user .newsrc file
X*/
X#define DEF_NEWSRC ".newsrc"
X
X/*
X** If INLETTER is defined, the address line will be placed into the
X** file editted by the user, and the mailer is assumed smart enough
X** to understand about header lines in the file.  Otherwise the
X** address is part of the mailer's command line.
X**
X** if MAILSMART is defined, The From: line will be used for mail replies,
X** or overridden by a "Reply-to:" line if present - "Path:" will be used
X** as a last resort.  If MAILSMART is not defined, "Path:" will simply be
X** used.
X**
X** if MAILCHOOSE is defined, the user is prompted before edit with all
X** of the address lines to choose from, or to input a new one.  MAILCHOOSE
X** makes MAILSMART irrelevant, but the two are independent of INLETTER.
X**
X*/
X#define MAILSMART
X#define INLETTER
X
X/*
X** default mail sender.  If INLETTER, will be done as
X** cat <file> | DEF_MAIL,  Otherwise, cat <file> | DEF_MAIL <address>
X** user's MAILER variable will have to conform, too.
X*/
X#ifdef INLETTER
X#define DEF_MAIL "/usr/lib/sendmail -t"
X#else
X#define DEF_MAIL "/bin/mail"
X#endif
X
X/* OLDRC defined for an apparently earlier news version which took unnamed
X** command line options as synonyms for -n, and did not take ranges in
X** the .newsrc file.  Probably useless, but kept in for historical reasons.
X**
X**#define OLDRC
X*/
X
X/*
X** article spool directory
X*/
X#define SPOOLDIR "/usr/spool/news"
X
X/*
X** active file
X*/
X#define ACTFILE "/usr/lib/news/active"
X
X/*
X** maximum number of option lines in .newsrc
X*/
X#define OPTLINES 20
X
X/*
X** maximum number of filter options
X*/
X#define NUMFILTER 30
X
X/*
X** maximum number of file lines to search looking for header lines.
X*/
X#define HDR_LINES 36
X
X/*
X** When a newsgroup is scanned, we ignore articles less than <high spool> -
X** MAXARTRANGE.  This is intended to prevent ridiculous numbers of article
X** opening attempts the first time a user reads a new newsgroup which has a
X** huge difference between the high and low spool numbers, perhaps due to
X** some articles not getting expired.
X*/
X#define MAXARTRANGE 1600	/* about 2 weeks of soc.singles */
X
X/*
X** If we detect that the user has a higher number in .newsrc than the
X** high article number, obviously the active file is out of synch with the
X** .newsrc.  We set the user's number back to the low article number in
X** this case, on the theory that it's better to repeat stuff than miss
X** articles.  On such setbacks, we won't backdate the user by more than
X** SYN_SETBACK articles, preventing floods of articles on large newsgroups
X** if you don't define SYN_CHECK, the user's number won't be adjusted in
X** this case, choosing to lose articles rather than show old ones.
X*/
X#define SYN_CHECK
X#define SYN_SETBACK 60
END_OF_FILE
if test 2802 -ne `wc -c <'config_std.h'`; then
    echo shar: \"'config_std.h'\" unpacked with wrong size!
fi
# end of 'config_std.h'
fi
if test -f 'digest.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'digest.c'\"
else
echo shar: Extracting \"'digest.c'\" \(5681 characters\)
sed "s/^X//" >'digest.c' <<'END_OF_FILE'
X/*
X** vn news reader.
X**
X** digest.c - digest unpacking routines
X**
X** see copyright disclaimer / history in vn.c source file
X*/
X
X#include <stdio.h>
X#include "config.h"
X#include "head.h"
X#include "tune.h"
X#include "node.h"
X#include "page.h"
X
Xextern int Digest;
Xextern int L_allow;
Xextern int C_allow;
Xextern PAGE Page;
X
Xextern FILE *vns_aopen();
X
Xstatic char *Ext_pool = NULL;
Xstatic char *Show[3];
X
Xstatic char *Dhead = "Date: ";
Xstatic char *Fhead = "From: ";
Xstatic char *Lhead = "Lines: ";
Xstatic char *Thead = "Subject: ";
X
X#define THDLEN 9
X#define LHDLEN 7
X#define FHDLEN 6
X#define DHDLEN 6
X
Xdige_page (idx,skip)
Xint idx;
X{
X	char name[24];
X	FILE *fp;
X	int i,len,hl;
X	char subj[RECLEN],date[RECLEN],from[RECLEN],junk[RECLEN],*str_store();
X	long pos;
X	ARTHEADER hdr;
X
X	Digest = Page.b[idx].art_id;
X
X	if ((fp = vns_aopen(Digest,&hdr)) == NULL)
X		return (-1);
X
X	subj[0] = date[0] = from[0] = junk[0] = '\0';
X
X	/* skip over some articles if requested to */
X	for (i=skip; i > 0; --i)
X	{
X		if (dig_advance(fp,from,subj,date,junk,&pos,&hl) < 0)
X			return (-1);
X	}
X
X	for (i=0; i < L_allow &&
X			(len = dig_advance(fp,from,subj,date,junk,&pos,&hl)) >= 0; ++i)
X	{
X		Page.b[i].art_id = i+1+skip;
X		Page.b[i].art_mark = ' ';
X		subj [C_allow] = '\0';
X		from [C_allow] = '\0';
X		sprintf (name,"%d",len);
X		form_title (date,subj,name,from,100);
X		strcpy (Page.b[i].art_t,date);
X	}
X
X	vns_aclose (fp);
X
X	if (i == 0)
X		return (-1);
X
X	Page.h.artnum = i;
X	return (i);
X}
X
X/*
X	returns name of file containing "article", NULL for failure
X*/
Xchar * dige_extract (s,art,hdr,start)
Xchar *s;
Xint art;
XARTHEADER *hdr;
Xlong *start;
X{
X	FILE *fout,*fin;
X	long pos;
X	int lines,hl;
X	char subj[RECLEN],date[RECLEN],from[RECLEN],bufr[RECLEN];
X	char extra[RECLEN];
X	char *index();
X	long ftell();
X	char *str_tpool(), *str_tstore();
X
X	if (Ext_pool != NULL)
X		str_tfree(Ext_pool);
X	Ext_pool = str_tpool(3);
X
X	if ((fin = vns_aopen(Digest,hdr)) == NULL)
X		return (NULL);
X
X	for ( ; art > 0; --art)
X	{
X		from[0] = subj[0] = date[0] = '\0';
X		if ((lines = dig_advance(fin,from,subj,date,extra,&pos,&hl)) < 0)
X		{
X			vns_aclose(fin);
X			return (NULL);
X		}
X	}
X
X	tmpnam(s);
X
X	if ((fout = fopen(s,"w")) == NULL)
X	{
X		vns_aclose(fin);
X		unlink (s);
X		return (NULL);
X	}
X
X	fseek(fin,0L,0);
X
X	hdr->show_num = 0;
X	hdr->show = Show;
X	hdr->lines = lines;
X	hdr->hlines = hl;
X	if (subj[0] != '\0')
X	{
X		sprintf (bufr,"%s%s",Thead,subj);
X		Show[hdr->show_num] = str_tstore(Ext_pool,bufr);
X		++(hdr->show_num);
X	}
X	if (from[0] != '\0')
X	{
X		sprintf (bufr,"%s%s",Fhead,from);
X		Show[hdr->show_num] = str_tstore(Ext_pool,bufr);
X		++(hdr->show_num);
X	}
X	if (date[0] != '\0')
X	{
X		sprintf (bufr,"%s%s",Dhead,date);
X		Show[hdr->show_num] = str_tstore(Ext_pool,bufr);
X		++(hdr->show_num);
X	}
X
X	while (fgets(bufr,RECLEN-1,fin) != NULL && bufr[0] != '\n')
X	{
X		if (strncmp(bufr,Fhead,FHDLEN) == 0)
X		{
X			fprintf (fout,"%s%s\n",Fhead,from);
X			continue;
X		}
X		if (strncmp(bufr,Thead,THDLEN) == 0)
X		{
X			fprintf (fout,"%s%s\n",Thead,subj);
X			continue;
X		}
X		if (strncmp(bufr,Dhead,DHDLEN) == 0)
X		{
X			fprintf (fout,"%s%s\n",Dhead,date);
X			continue;
X		}
X		/* defer line count header - it comes last */
X		if (strncmp(bufr,Lhead,LHDLEN) == 0)
X			continue;
X		fprintf (fout,"%s",bufr);
X	}
X
X	/* toss in extra header lines, line count header, extra newline */
X	fprintf (fout,"%s%s%d\n\n",extra,Lhead,lines);
X	*start = ftell(fout);
X
X	fseek (fin,pos,0);
X
X	while (fgets(bufr,RECLEN-1,fin) != NULL && strncmp(bufr,"--------",8) != 0)
X		fprintf(fout,"%s",bufr);
X
X	vns_aclose (fin);
X	fclose (fout);
X	return (s);
X}
X
Xdig_list (s)
Xchar *s;
X{
X	char *ptr,*out,*new,ns[L_tmpnam],tmp[RECLEN],*strtok();
X	ARTHEADER hdr;
X	long pos;
X	int i;
X
X	prinfo ("Extracting articles .....");
X	strcpy (tmp,s);
X	out = s;
X
X	for (ptr = strtok(tmp," "); ptr != NULL; ptr = strtok(NULL," "))
X	{
X		i = atoi(ptr);
X		if ((new = dige_extract(ns,i,&hdr,&pos)) != NULL)
X		{
X			sprintf (out,"%s ",new);
X			out += strlen(new) + 1;
X		}
X	}
X
X	*out = '\0';
X
X	if (*s == '\0')
X		strcpy (s,"NULLDIGEST");
X}
X
Xdig_ulist (s)
Xchar *s;
X{
X	char *strtok();
X	for (s = strtok(s," "); s != NULL; s = strtok(NULL," "))
X		unlink (s);
X}
X
X/*
X	returns # lines in article, -1 for failure
X	scans past article, returns position of start.
X	also returns "extra" header lines encountered, WITH newlines.
X	and counts total header lines.
X*/
Xstatic dig_advance (fp,from,subj,date,extra,pos,hcount)
XFILE *fp;
Xchar *from,*subj,*date,*extra;
Xlong *pos;
Xint *hcount;
X{
X	char buf[RECLEN];
X	char *ptr, *index();
X	int len,state,lcount;
X
X	*hcount = lcount = state = 0;
X	*extra = '\0';
X
X	while (fgets(buf,RECLEN-1,fp) != NULL)
X	{
X		buf[(len = strlen(buf) - 1)] = '\0';
X		for (--len ; len >= 0 && buf[len] == ' ' || buf[len] == '\t'; --len)
X			buf[len] = '\0';
X		++len;
X
X		switch(state)
X		{
X		case 0:
X			/* skip blank lines before header */
X			if (len == 0)
X				break;
X			state = 1;	/* fall through */
X		case 1:
X			++(*hcount);
X			if (strncmp(buf,Fhead,FHDLEN) == 0)
X			{
X				strcpy (from,buf+FHDLEN);
X				break;
X			}
X			if (strncmp(buf,Thead,THDLEN) == 0)
X			{
X				strcpy (subj,buf+THDLEN);
X				break;
X			}
X			if (strncmp(buf,Dhead,DHDLEN) == 0)
X			{
X				strcpy (date,buf+DHDLEN);
X				break;
X			}
X			/* put wierd header lines in extra */
X			if ((ptr = index(buf,':')) != NULL)
X			{
X				*ptr = '\0';
X				if (index(buf, ' ') == NULL)
X				{
X					*ptr = ':';
X					sprintf(extra,"%s\n",buf);
X					extra += strlen(extra);
X					break;
X				}
X				*ptr = ':';
X			}
X			state = 2;
X			--(*hcount);
X
X			/* remember the newline we lopped off */
X			*pos = ftell(fp)-strlen(buf)-1;	/* fall through */
X		case 2:
X			++lcount;
X			if (strncmp("--------",buf,8) == 0)
X			{
X				--lcount;
X				return (lcount);
X			}
X			break;
X		}
X	}
X
X	return (-1);
X}
END_OF_FILE
if test 5681 -ne `wc -c <'digest.c'`; then
    echo shar: \"'digest.c'\" unpacked with wrong size!
fi
# end of 'digest.c'
fi
if test -f 'envir_set.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'envir_set.c'\"
else
echo shar: Extracting \"'envir_set.c'\" \(2900 characters\)
sed "s/^X//" >'envir_set.c' <<'END_OF_FILE'
X/*
X** vn news reader.
X**
X** envir_set.c - routine to obtain pertinent environment variable settings
X**		and set up file / directory names
X**
X** see copyright disclaimer / history in vn.c source file
X*/
X
X#include <stdio.h>
X#include <pwd.h>
X
X#ifndef MINIX
X/* minix does not have this */
X#include <sys/param.h>
X#endif
X
X#include "tune.h"
X#include "config.h"
X#include "vn.h"
X
Xextern char *Editor, *Ps1, *Printer;
Xextern char *Orgdir, *Savedir, *Ccfile;	/* path names */
Xextern char Cxitop[], Cxitor[], Cxrtoi[], Cxptoi[];
Xextern char *Home;
Xextern int More;
X
X#ifdef SYSV
Xextern char *getcwd();
X#define getwd(a) getcwd(a,sizeof(a))
X#define	MAXPATHLEN 240
X#else
Xextern char *getwd();
X#endif
X
X/*
X	environment variable, original directory string setup.
X*/
X
Xenvir_set ()
X{
X	char dbuf [MAXPATHLEN], *ccname, *keyxln;
X	char *vn_env(), *getcwd(), *str_store();
X	struct passwd *ptr, *getpwuid();
X
X	vns_envir();
X	More = 0;
X
X	Ps1 = vn_env("PS1",DEF_PS1);
X	Editor = vn_env("EDITOR",DEF_ED);
X	Printer = vn_env("PRINTER",DEF_PRINT);
X	ccname = vn_env("CCFILE",DEF_CCFILE);
X	keyxln = vn_env("VNKEY",DEF_KEYXLN);
X	Savedir = vn_env("VNSAVE",NULL);
X	More = (strcmp(vn_env("MORE",""), "-c") == 0 ? TRUE : FALSE);
X
X	/*
X		set original directory strings.
X	*/
X
X	if ((ptr = getpwuid(getuid())) == NULL)
X		printex("Cannot obtain /etc/passwd entry");
X	Home = str_store(ptr->pw_dir);
X	if ((Orgdir = getwd(dbuf)) == NULL)
X		printex ("cannot stat pwd");
X	Orgdir = str_store (Orgdir);
X	if (Savedir == NULL)
X		Savedir = Orgdir;
X	if (*ccname != '/')
X	{
X		sprintf (dbuf, "%s/%s",Home,ccname);
X		Ccfile = str_store (dbuf);
X	}
X	else
X		Ccfile = str_store (ccname);
X	sprintf (dbuf, "%s/%s%s",Home,".vn","XXXXXX");
X
X	if (*keyxln != '/')
X	{
X		sprintf(dbuf, "%s/%s",Home,keyxln);
X		set_kxln(dbuf);
X	}
X	else
X		set_kxln(keyxln);
X}
X
Xchar *
Xvn_env(var,def)
Xchar *var;
Xchar *def;
X{
X	char pfx[RECLEN];
X	char *res;
X	char *getenv();
X
X	if (var[0] != 'V' || var[1] != 'N')
X	{
X		sprintf(pfx,"VN%s",var);
X		if ((res = getenv(pfx)) != NULL)
X			return(res);
X	}
X
X	if ((res = getenv(var)) != NULL)
X		return(res);
X
X	return(def);
X}
X
Xstatic
Xset_kxln(fname)
Xchar *fname;
X{
X	FILE *fp;
X	int i;
X	char bufr[80];
X	char in,out,*ptr;
X	char *index(), xln_str();
X
X	for (i=0; i < CHMASK+1; ++i)
X		Cxitop[i] = Cxitor[i] = Cxptoi[i] = Cxrtoi[i] = i;
X
X	if ((fp = fopen(fname,"r")) != NULL)
X	{
X		while(fgets(bufr,79,fp) != NULL)
X		{
X			if (strncmp(bufr+1,"==",2) == 0)
X				ptr = bufr+2;
X			else
X				ptr = index(bufr+1,'=');
X			if (ptr == NULL)
X				continue;
X			*ptr = '\0';
X			++ptr;
X			in = xln_str(bufr+1);
X			out = xln_str(ptr);
X			switch(bufr[0])
X			{
X			case 'r':
X			case 'R':
X				Cxrtoi[out] = in;
X				Cxitor[in] = out;
X				break;
X			case 'p':
X			case 'P':
X				Cxptoi[out] = in;
X				Cxitop[in] = out;
X			default:
X				break;
X			}
X		}
X		fclose(fp);
X	}
X}
X
Xstatic char
Xxln_str(s)
Xchar *s;
X{
X	if (*s < '0' || *s > '9')
X		return(*s & CHMASK);
X	return((char)(atoi(s) & CHMASK));
X}
END_OF_FILE
if test 2900 -ne `wc -c <'envir_set.c'`; then
    echo shar: \"'envir_set.c'\" unpacked with wrong size!
fi
# end of 'envir_set.c'
fi
if test -f 'getch.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'getch.c'\"
else
echo shar: Extracting \"'getch.c'\" \(2004 characters\)
sed "s/^X//" >'getch.c' <<'END_OF_FILE'
X/*
X** vn news reader.
X**
X** getch.c - character i/o routines
X**
X** see copyright disclaimer / history in vn.c source file
X*/
X#include <stdio.h>
X#include <setjmp.h>
X#include <ctype.h>
X#include "config.h"
X#include "vn.h"
X
Xextern char Cxitop[];
Xextern char *Ku, *Kd, *Kr, *Kl;
X
X/*
X	getkey obtains user keystroke with count from leading
X	numerics, if any.  Picks up arrow key sequences and maps
X	them to other keys.  Also translates character through
X	Cxitop array since this routine is only used in session
X	loop.  Saves untranslating arrow keys.
X*/
Xgetkey (c)
Xchar *c;
X{
X	int i, j;
X	static char	ckseq[32];
X
X#ifdef	MINIX
X	fflush(stdout);
X#endif
X
X	/* Check for leading count */
X	for (i = 0; isdigit(*c = getc(stdin) & CHMASK); i = i * 10 + *c - '0')
X		;
X
X	/* @#$!!! flakey front ends that won't map newlines in raw mode */
X	if (*c == '\012' || *c == '\015')
X		*c = '\n';
X
X	/* @#$!!! flakey terminals which send control sequences for cursors! */
X	if( *c == '\033' )
X	{
X		/*
X		** Check if part of cursor key input sequence
X		** (pitch unknown escape sequences)
X		*/
X		j = 0;
X		ckseq[j] = *c; ckseq[j+1] = '\0';
X		while(*c == Ku[j] || *c == Kd[j] || *c == Kl[j] || *c == Kr[j])
X		{
X			if( strcmp(ckseq, Ku) == 0 ) { *c = UP; break; }
X			if( strcmp(ckseq, Kd) == 0 ) { *c = DOWN; break; }
X#ifdef PAGEARROW
X			if( strcmp(ckseq, Kl) == 0 ) { *c = BACK; break; }
X			if( strcmp(ckseq, Kr) == 0 ) { *c = FORWARD; break; }
X#else
X			if( strcmp(ckseq, Kl) == 0 ) { *c = UP; break; }
X			if( strcmp(ckseq, Kr) == 0 ) { *c = DOWN; break; }
X#endif
X			*c = (getc(stdin) & CHMASK);
X			ckseq[++j] = *c; ckseq[j+1] = '\0';
X		}
X	}
X	else
X		*c = Cxitop[*c];
X
X	if (i <= 0)
X		i = 1;
X	return (i);
X}
X
X/*
X	get user key ignoring most controls.  Used from reader and other
X	non-screen interactions.
X*/
Xgetnoctl ()
X{
X	char c;
X
X#ifdef	MINIX
X	fflush(stdout);
X#endif
X	while (iscntrl(c = getc(stdin) & CHMASK))
X	{
X		if (c == '\015' || c == '\012')
X			c = '\n';
X		if (c == '\n' || c == '\b' || c == '\t')
X			return (c);
X	}
X	return ((int) c);
X}
END_OF_FILE
if test 2004 -ne `wc -c <'getch.c'`; then
    echo shar: \"'getch.c'\" unpacked with wrong size!
fi
# end of 'getch.c'
fi
if test -f 'hash.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'hash.c'\"
else
echo shar: Extracting \"'hash.c'\" \(1874 characters\)
sed "s/^X//" >'hash.c' <<'END_OF_FILE'
X/*
X** vn news reader.
X**
X** hash.c - hash table routines
X**
X** see copyright disclaimer / history in vn.c source file
X*/
X
X#include <stdio.h>
X#include "config.h"
X#include "tune.h"
X#include "node.h"
X
X/*
X** hash table manipulation routines:
X*/
X
Xextern int Ncount;
Xextern NODE **Newsorder;
X
Xstatic NODE *Tab [HASHSIZE];	/* hash Table */
X
Xhashinit ()
X{
X	int i;
X	for (i=0; i < HASHSIZE; ++i)
X		Tab[i] = NULL;
X	Ncount = 0;
X}
X
X/*
X	enter new node (name s, articles n, low l) in hash Table, 
X	initial flags = 0.  Set order to -1.
X*/
XNODE *hashenter(s,n,l)
Xchar *s;
Xint n;
Xint l;
X{
X	char *str_store();
X	NODE *ptr,*node_store();
X	NODE *hashfind();
X	int i;
X
X	if ((ptr = hashfind(s)) != NULL)
X	{
X		fgprintf ("Warning: group %s encountered twice",s);
X		return (ptr);
X	}
X
X	i=hash(s);
X	ptr = node_store();
X	ptr->next = Tab[i];
X	Tab[i] = ptr;
X	if (l > n)
X		l = n;
X	++Ncount;
X	ptr->lownum = l;
X	ptr->state = 0;
X	ptr->data = NULL;
X	ptr->flags = 0;
X	ptr->highnum = n;
X	ptr->nd_name = str_store(s);
X	ptr->pgshwn = 0;
X	ptr->order = -1;
X	return (ptr);
X}
X
XNODE *hashfind(s)
Xchar *s;
X{
X	NODE *ptr;
X
X	for (ptr = Tab[hash(s)]; ptr != NULL && strcmp(ptr->nd_name,s) != 0;
X					ptr = ptr->next)
X		    ;
X	return (ptr);
X}
X
Xmake_newsorder()
X{
X	char *malloc();
X	int i;
X	NODE *ptr;
X
X	if ((Newsorder = (NODE **) malloc(Ncount * sizeof(NODE *))) == NULL)
X		printex("Memory allocation failure - newsorder array");
X	for (i=0; i < Ncount; ++i)
X		Newsorder[i] = NULL;
X	for (i=0; i < HASHSIZE; ++i)
X	{
X		for (ptr = Tab[i]; ptr != NULL; ptr = ptr->next)
X		{
X			if (ptr->order < 0 || ptr->order >= Ncount)
X				printex("News order range error");
X			Newsorder[ptr->order] = ptr;
X		}
X	}
X	for (i=0; i < Ncount; ++i)
X		if (Newsorder[i] == NULL)
X			printex("News order duplication error");
X}
X
Xstatic hash (s)
Xchar *s;
X{
X	unsigned rem;
X	for (rem=0; *s != '\0'; ++s)
X		rem = (rem*128 + (*s&0x7f)) % HASHSIZE;
X	return (rem);
X}
END_OF_FILE
if test 1874 -ne `wc -c <'hash.c'`; then
    echo shar: \"'hash.c'\" unpacked with wrong size!
fi
# end of 'hash.c'
fi
if test -f 'head.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'head.h'\"
else
echo shar: Extracting \"'head.h'\" \(2530 characters\)
sed "s/^X//" >'head.h' <<'END_OF_FILE'
X/*
X** vn news reader.
X**
X** head.h - header line structure
X**
X** see copyright disclaimer / history in vn.c source file
X*/
X
X/*
X** How this thing works:
X**
X** this structure is filled in by vns_aopen when opening an article.
X** lines & hlines items will be used in providing percentage read prompts
X**
X** show_num & show are the article information lines presented for the user
X** when the "show headers" flag is turned off.
X**
X** from and artid are used for mail salutations, etc.
X**
X** The items used for mail replies, FOLLOWING the call to the mail massager
X** if there is one, are mailcmd, mail_num, and mail.  These are the items
X** the massager should fill in.  If no massager exists, vns_aopen will
X** fill these in directly.  If mail_err is non-null, the user won't be
X** able to mail a reply to the article, and the item should be an error
X** message explaining why.  If there is a mailer function, the mailcmd
X** item is not used.
X**
X** The priv and priv_num items are for sole use of the server layer in
X** the mail massager, mailer and poster functions.
X**
X** The postcmd, post_num, and post arguments are used in treatment of
X** followups.  If post_err is non-null, followup won't be allowed, for
X** the reason described therein.  If there is a poster function, the
X** postcmd item isn't used.
X**
X** The header lines for inclusion in mail / followup files will open
X** the file, and will be followed by one blank line.  The lines are literal -
X** all appropriate headers should be prepended, etc.
X**
X** postcmd / mailcmd are used as format strings which are assumed to have a
X** single %s in them some place for the placement of the users editted file.
X** The result will be spawned as a command.
X*/
X
Xtypedef struct
X{
X	int lines;		/* number of lines in article */
X	int hlines;		/* number of header lines in article */
X	char *from;		/* authors name */
X	char *artid;		/* article id */
X	int show_num;		/* number of extra lines for reader display */
X	char **show;		/* extra header lines */
X	int priv_num;		/* number of private arguments */
X	char **priv;		/* private server arguments */
X	char *mail_err;		/* mail reply error message */
X	char *mailcmd;		/* command line for mailer */
X	int mail_num;		/* number of header lines in mail reply file */
X	char **mail;		/* mail reply header lines */
X	char *post_err;		/* follow-up posting error message */
X	char *postcmd;		/* command line for followup poster */
X	int post_num;		/* number of header lines for followup file */
X	char **post;		/* followup header lines */
X} ARTHEADER;
END_OF_FILE
if test 2530 -ne `wc -c <'head.h'`; then
    echo shar: \"'head.h'\" unpacked with wrong size!
fi
# end of 'head.h'
fi
if test -f 'help.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'help.c'\"
else
echo shar: Extracting \"'help.c'\" \(6850 characters\)
sed "s/^X//" >'help.c' <<'END_OF_FILE'
X/*
X** vn news reader.
X**
X** help.c - print help
X**
X** see copyright disclaimer / history in vn.c source file
X*/
X#include <stdio.h>
X#include <setjmp.h>
X#include "config.h"
X#include "tty.h"
X#include "tune.h"
X#include "node.h"
X#include "page.h"
X#include "reader.h"
X#include "vn.h"
X
Xextern int L_allow;
Xextern int C_allow;
Xextern int Digest;
Xextern char *Contstr;
Xextern char Cxptoi[], Cxrtoi[];
X
Xextern int (*Hookfunc)();
Xextern char *(*Hookhelp)();
X
X/*
X	Help message table.  Character for command, plus its help
X	message.  Table order is order of presentation to user.
X*/
Xstatic struct HELPTAB
X{
X	char cmd, *msg;
X	int dig;
X	char *amsg;
X} 
XHelptab [] =
X{
X	{ QUIT, "quit", 1, NULL},
X	{ UP, "(or up arrow) move up [number of lines]", 1, NULL},
X	{ DOWN, "(or down arrow) move down [number of lines]", 1, NULL},
X#ifdef PAGEARROW
X	{ BACK, "(or left arrow) previous page [number of pages]", 1, NULL},
X	{ FORWARD, "(or right arrow) next page [number of pages]", 1, NULL},
X#else
X	{ BACK, "previous page [number of pages]", 1, NULL},
X	{ FORWARD, "next page [number of pages]", 1, NULL},
X#endif
X	{ GRPBACK, "previous newsgroup [number of newsgroups]", 0, NULL },
X	{ GRPFORWARD, "next newsgroup [number of newsgroups]", 0, NULL },
X	{ TOPMOVE, "move to top of page", 1, NULL},
X	{ BOTMOVE, "move to bottom of page", 1, NULL},
X	{ ALTBOTTOM, "move to bottom of page (alternate L)", 1, NULL},
X	{ MIDMOVE, "move to middle of page", 1, NULL},
X	{ DIGEST, "unpack digest", 1, "exit digest"},
X	{ READ, "read article [number of articles]", 1, NULL},
X	{ ALTREAD, "read article (alternate 'r')", 1, NULL},
X	{ READALL, "read all articles on page", 1, NULL},
X	{ READSTRING, "specify articles to read", 1, NULL},
X	{ SAVE, "save or pipe article [number of articles]", 1, NULL},
X	{ SAVEALL, "save or pipe all articles on page", 1, NULL},
X	{ SAVESTRING, "specify articles to save", 1, NULL},
X	{ ALTSAVE, "specify articles to save (alternate ctl-s)", 1, NULL},
X	{ PRINT, "print article [number of articles]", 1, NULL},
X	{ PRINTALL, "print all article on page", 1, NULL},
X	{ PRINTSTRING, "specify articles to print", 1, NULL},
X	{ UPDATE, "update .newsrc status to cursor", 0, NULL},
X	{ UPALL, "update .newsrc status for whole newsgroup", 0, NULL},
X	{ UPSEEN, "update .newsrc status for all pages displayed", 0, NULL},
X	{ ORGGRP, "recover original .newsrc status for newsgroup", 0, NULL},
X	{ ORGSTAT, "recover all original .newsrc status", 0, NULL},
X	{ SSTAT, "display count of groups and pages - shown and total", 0, NULL},
X	{ GRPLIST, "list newsgroups with new article, updated counts", 0, NULL},
X	{ NEWGROUP, "specify newsgroup to display and/or resubscribe to", 1, NULL},
X	{ UNSUBSCRIBE, "unsubscribe from group", 0, NULL},
X	{ MARK, "mark/unmark article [number of articles]", 1, NULL},
X	{ ART_MARK, "mark/unmark article [number of articles]", 1, NULL},
X	{ UNMARK, "erase marks on articles", 1, NULL},
X	{ MARKSTRING, "specify articles to mark/unmark", 1, NULL},
X	{ HEADTOG, "toggle flag for display of headers when reading", 1, NULL},
X	{ SETROT, "toggle rotation for reading", 1, NULL},
X	{ REDRAW, "redraw screen", 1, NULL},
X	{ UNESC, "escape to UNIX to execute a command", 1, NULL},
X	{ PRTVERSION, "show vn version", 1, NULL},
X	{ HELP, "show this help menu", 1, NULL}
X};
X
X#define HTSIZE (sizeof(Helptab)/sizeof(struct HELPTAB))
X
X
X#define HHLINES 5	/* lines (CRs + 1) contained in HELP_HEAD */
X/*
X	help from main screen
X*/
Xhelp ()
X{
X	int i,lcount,lim;
X	char *hs;
X	char c;
X
X	term_set (ERASE);
X	lim = L_allow + RECBIAS - 2;
X	printf("%s\n","[...] = effect of optional number preceding command\n");
X	printf("%s\n","pipes are specified by filenames beginning with |\n");
X	printf("%s\n","articles specified as a list of numbers, title search string, or\n");
X	printf("%s\n","	* to specify marked articles.  ! may be used to negate any\n");
X	lcount = HHLINES;
X	for (i=0; i < HTSIZE; ++i)
X	{
X		if (Digest && !(Helptab[i].dig))
X			continue;
X		if (Hookfunc != NULL && (*Hookfunc)(Helptab[i].cmd,0,0) >= 0)
X			continue;
X		++lcount;
X		if (Digest && Helptab[i].amsg != NULL)
X			h_print (Cxptoi[Helptab[i].cmd],Helptab[i].amsg);
X		else
X			h_print (Cxptoi[Helptab[i].cmd],Helptab[i].msg);
X		if (lcount >= lim)
X		{
X			printf ("\n%s",Contstr);
X			getnoctl ();
X			term_set (MOVE,0,lim+1);
X			term_set (ZAP,0,strlen(Contstr));
X			term_set (MOVE,0,lim-1);
X			putchar ('\n');
X			lcount = 0;
X		}
X	}
X	if (Hookhelp != NULL)
X	{
X		for (hs=(*Hookhelp)(0,1,&c);
X				hs != NULL; hs = (*Hookhelp)(0,0,&c))
X		{
X			++lcount;
X			h_print (Cxptoi[c],hs);
X			if (lcount >= lim)
X			{
X				printf ("\n%s",Contstr);
X				getnoctl ();
X				term_set (MOVE,0,lim+1);
X				term_set (ZAP,0,strlen(Contstr));
X				term_set (MOVE,0,lim-1);
X				putchar ('\n');
X				lcount = 0;
X			}
X		}
X	}
X	if (lcount > 0)
X	{
X		printf ("\n%s",Contstr);
X		getnoctl ();
X	}
X}
X
X/*
X	help from reader
X*/
Xhelp_rd()
X{
X	char *hs;
X	char c;
X
X	printf("\n");	/* "confused" tab expansion on first line */
X
X	hr_print (Cxrtoi[PG_NEXT],HPG_NEXT);
X	hr_print (Cxrtoi[PG_QUIT],HPG_QUIT);
X	hr_print (Cxrtoi[PG_FLIP],HPG_FLIP);
X	hr_print (Cxrtoi[PG_REWIND],HPG_REWIND);
X	hr_print (Cxrtoi[PG_WIND],HPG_WIND);
X	hr_print (Cxrtoi[PG_SEARCH],HPG_SEARCH);
X	hr_print (Cxrtoi[PG_STEP],HPG_STEP);
X	hr_print (Cxrtoi[PG_REPLY],HPG_REPLY);
X	hr_print (Cxrtoi[PG_FOLLOW],HPG_FOLLOW);
X	hr_print (Cxrtoi[SAVE],HPG_SAVE);
X	hr_print (Cxrtoi[PRINT],HPG_PRINT);
X	hr_print (Cxrtoi[SETROT],HPG_ROT);
X	hr_print (Cxrtoi[HEADTOG],HPG_HEAD);
X	hr_print (Cxrtoi[PG_HELP],HPG_HELP);
X	if (Hookhelp != NULL)
X	{
X		for (hs=(*Hookhelp)(1,1,&c);
X				hs != NULL; hs = (*Hookhelp)(1,0,&c))
X			h_print (Cxrtoi[c],hs);
X	}
X	printf ("%s\n",HPG_DEF);
X}
X
Xhr_print(c,msg)
Xchar c;
Xchar *msg;
X{
X	if (Hookfunc == NULL || (*Hookfunc)(c,1,0) < 0)
X		h_print(c,msg);
X}
X
Xsrch_help(c,dig)
Xchar c;
Xint *dig;
X{
X	int i;
X
X	for (i=0; i < HTSIZE; ++i)
X		if (Helptab[i].cmd == c)
X			break;
X	if (i < HTSIZE)
X	{
X		*dig = Helptab[i].dig;
X		return (0);
X	}
X	return(-1);
X}
X
X/*
X	h_print prints a character and a legend for a help menu.
X*/
Xstatic
Xh_print(c,s)
Xchar c,*s;
X{
X	if (strlen(s) > (C_allow - 14))
X		s [C_allow - 14] = '\0';
X	if (c > ' ' && c != '\177')
X		printf ("	 %c - %s\n",c,s);
X	else
X	{
X		switch (c)
X		{
X		case '\177':
X			printf ("  <delete> - %s\n",s);  
X			break;
X		case '\040':
X			printf ("   <space> - %s\n",s);  
X			break;
X		case '\033':
X			printf ("  <escape> - %s\n",s);  
X			break;
X		case '\n':
X			printf ("  <return> - %s\n",s);  
X			break;
X		case '\t':
X			printf ("     <tab> - %s\n",s);  
X			break;
X		case '\b':
X			printf (" <back sp> - %s\n",s);  
X			break;
X		case '\f':
X			printf ("<formfeed> - %s\n",s);  
X			break;
X		case '\07':
X			printf ("    <bell> - %s\n",s);  
X			break;
X		case '\0':
X			printf ("    <null> - %s\n",s);  
X			break;
X		default:
X			if (c < '\033')
X			{
X				c += 'a' - 1;
X				printf(" control-%c - %s\n",c,s);
X			}
X			else
X				printf("       %c0%o - %s\n",'\\',(int) c,s);
X			break;
X		}
X	}
X}
END_OF_FILE
if test 6850 -ne `wc -c <'help.c'`; then
    echo shar: \"'help.c'\" unpacked with wrong size!
fi
# end of 'help.c'
fi
if test -f 'makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'makefile'\"
else
echo shar: Extracting \"'makefile'\" \(4377 characters\)
sed "s/^X//" >'makefile' <<'END_OF_FILE'
X# CFLAGS:
X#	set -DJOBCONTROL if you have job control (BSD).
X#	set -DSYSV -Dindex=strchr -Drindex=strrchr on Sytem V systems
X#	set -Dregfree=free if you DON'T include reg.s (SYSV + some BSD)
X#
X# JOBCONTROL could be done as #ifndef SYSV, I suppose, but this clearly
X# marks that particular difference.
X#
X# LIBS:
X# should point to any extra libraries needed, such as termcap.  You
X# may want to change this to use the curses termcap cover.  If you need
X# to pull in another library to get regex / regcmp or strtok on non-SYSV
X# systems, you may want to put that here
X#
X# EXTRAOBJS:
X# may be used to include tmpnam.s, strtok.s, reg.s in the list.
X#
X# These objects implement SYSV utilities for BSD machines.
X#
X# strtok.s implements strtok() / strpbrk().  reg.s implements regex()/regcmp()
X# on top of the BSD regular expression library (regex() allows multiple
X# regular expressions).  tmpnam.s implements tmpnam() of course.
X#
X# If you have them, use your own regex/regcmp, because:
X#
X#	i) They should be faster than the reg.c code, which
X#	recompiles the "current" ucb string every time you
X#	switch regular expressions.
X#
X#	ii) I briefly checked out reg.c once, and it seemed to
X#	work.  Our system has the "real" calls available, so I
X#	run with those.  reg.c hasn't been used much by me, although
X#	I've had nobody tell me it doesn't work.
X#
X# if you DON'T include reg.s, be sure you set -Dregfree=free in CFLAGS.
X#
X# As with regex, if you have a system strtok(), it is likely more efficient -
X# string routines will often be done in assembler on a given machine.
X#
X# Even if you have it, you can use tmpnam.s anyhow.  This version will tailor
X# the temp file name to vnXXXXXX, instead of a generic tmpXXXXXX.
X#
X# "vanilla" BSD:
X#LIBS = -ltermcap
X#EXTRAOBJS = tmpnam.s strtok.s reg.s
X#CFLAGS = -O -DJOBCONTROL
X#
X# "vanilla" SYSV:
X#LIBS = -ltermcap
X#EXTRAOBJS = tmpnam.s
X#CFLAGS = -O -DSYSV -Dregfree=free -Dindex=strchr -Drindex=strrchr
X#
X# BSD with strtok() / regex(), such as ULTRIX.  These are the rules
X# used for our installation (rtech is a microvax running ULTRIX):
X#LIBS = -ltermcap
X#EXTRAOBJS = tmpnam.s
X#CFLAGS = -O -DJOBCONTROL -Dregfree=free
X
X#
X# Minix!!!
X#	Regular expressions: Use reg.c to turn regcmp into re_comp
X#	and regex into re_exec. Use regcompat.c to turn re_comp into
X#	regcomp and re_exec into regexec. Wow! What a load of old
X#	cobblers.
XLIBS =
X#EXTRAOBJS = tmpnam.s strtok.s reg.s
XEXTRAOBJS = tmpnam.s reg.s regcompat.s
XCFLAGS = -F -O -DMINIX -DSYSV
X
X# SERVEROBJS defines the object(s) for the vns_xxxx "server" interface.
X#
X#	std.s is the version for "standard" news, making use of the
X#	users .newsrc file, and  resident articles / active file.
X#
XSERVEROBJS = std.s
X
X# normal vn objects
X#
XVNOBJS=	hash.s envir_set.s pagefile.s reader.s storage.s sig_set.s \
Xterm_set.s tty_set.s userlist.s vn.s vnglob.s digest.s strings.s \
Xsession.s printex.s getch.s help.s newdisp.s stat.s svart.s
X
X# This is to force you to read the makefile.  Once you have, comment this rule,
X# and uncomment the "real" rule.  At the minimum, you will also have to
X# uncomment one of the three sets of LIBS / EXTRAOBJS & CFLAGS definitions
X# above.
X#
X#vn:
X#	@echo "PLEASE READ THE MAKEFILE"
Xvn:	$(VNOBJS) $(EXTRAOBJS) $(SERVEROBJS)
X	cc -i -o vn $(VNOBJS) $(EXTRAOBJS) $(SERVEROBJS) $(LIBS)
X
Xdigest.s:	digest.c config.h head.h node.h page.h tune.h
Xenvir_set.s:	envir_set.c config.h tune.h vn.h
Xgetch.s:	getch.c config.h vn.h
Xhash.s:		hash.c config.h node.h tune.h
Xhelp.s:		help.c config.h node.h page.h reader.h tty.h tune.h vn.h
Xnewdisp.s:	newdisp.c config.h node.h tty.h
Xpagefile.s:	pagefile.c node.h page.h tune.h
Xprintex.s:	printex.c config.h tty.h
Xreader.s:	reader.c config.h brk.h head.h node.h page.h reader.h  \
X		tty.h tune.h vn.h
Xregcompat.s:	regcompat.c
Xsession.s:	session.c config.h brk.h head.h node.h page.h tty.h tune.h \
X		vn.h
Xsig_set.s:	sig_set.c config.h node.h page.h tty.h tune.h
Xstat.s:		stat.c config.h node.h
Xstd.s:		std.c config_std.h brk.h head.h server.h std.h
Xstorage.s:	storage.c node.h page.h tune.h
Xstrings.s:	strings.c node.h page.h tune.h
Xsvart.s:	svart.c config.h node.h page.h tty.h tune.h
Xterm_set.s:	term_set.c config.h node.h page.h tty.h tune.h
Xtty_set.s:	tty_set.c tty.h
Xtmpnam.s:	tmpnam.c config.h
Xuserlist.s:	userlist.c node.h page.h tune.h vn.h
Xvn.s:		vn.c node.h tty.h
Xvnglob.s:	vnglob.c config.h brk.h head.h node.h page.h tune.h
END_OF_FILE
if test 4377 -ne `wc -c <'makefile'`; then
    echo shar: \"'makefile'\" unpacked with wrong size!
fi
# end of 'makefile'
fi
echo shar: End of shell archive.
exit 0
-- 
			"Zeta Microcomputer Software"
ACSnet:    nick@nswitgould.cs.uts.oz	nick@ultima.cs.uts.oz
UUCP:      ...!uunet!munnari!ultima.cs.uts.oz!nick
Fidonet:   Nick Andrew on 3:713/602 (Zeta)

nick@ultima.cs.uts.oz (Nick Andrew) (11/29/89)

From article <699@ccadfa.adfa.oz.au>, by wkt@csadfa.cs.adfa.oz.au (Warren Toomey):
> In article <16666@ultima.cs.uts.oz>, nick@ultima.cs.uts.oz (Nick Andrew) writes:
>> 
>> 	Since I've been using this Vn under Minix for over 6 months without
...
> Just one question, how do you get news items onto your PC/ST??

	Very messily. I have an entry in the sys file, which looks like:

minix:world,aus,syd,sci,to.zeta:F:

(note that Minix can't handle that many groups ... aus.* and sci.* give
the unbatcher a fair strapping!)

from cron, this command is executed daily:

0 0 * * * /system/news/LIB/sendbatch -s35000 -b12 -c minix

the /system/news/BATCH/minix.cmd file contains:

#!/bin/csh
#  batching file for Nick's Minix news system ...
#  basically, what I want to happen is this:
#	inews updates the batch file /system/news/BATCH/minix
#	only once per day root runs "sendbatch -b12 -c minix"
# (I would have fido do it, but it seems to need news +fido permissions)
#	this script puts the batch into a unique filename and
#	does a "putfile" to 713.777 which is the id of the Minix
#	every so often, my Minix calls up and downloads those files using
#	fidonet (or some other) protocol (such as Zmodem).

	set da=`date`
	set m=$da[2]
	set d=$da[3]
	set seq=`cat /system/fido/filesout/713.777.seq`
	@ seq = $seq + 1
	echo $seq >/system/fido/filesout/713.777.seq
	cat > /system/fido/Newslog/bn$seq.bat.Z
	~fido/bin/putfile /system/fido/Newslog/bn$seq.bat.Z 713.777
	rm -f /system/fido/Newslog/bn$seq.bat.Z
	echo `id` sendbatch minix done `date` >>/system/fido/gather.log
	exit 0


... which is fairly self explanatory. The files bn*.bat.Z are collected,
every so often I call and transfer a whack of them via Zmodem.

Once I receive the files I run the news 2.11 unbatcher on them, which runs
inews etc... and they're done.  I said earlier that the unbatcher was
pretty strapped for capacity ... the average batch ends up about 40k
long, and it takes my Minix 40 minutes on average to unbatch 10 of these
batches.

	Hope this clarifies things somewhat ...  Nick.

-- 
		"Zeta Microcomputer Software"
ACSnet:    nick@ultima.cs.uts.oz
UUCP:      ...!uunet!munnari!ultima.cs.uts.oz!nick
Fidonet:   Nick Andrew on 3:713/602 (Zeta)