[alt.sources] fixnews

srt@aerospace.aero.org (Scott "TCB" Turner) (03/09/91)

This is a little hack I threw together to run through my .newsrc and
make sure I have no more than 50 articles to read in each newsgroup.
This allows me to dabble in heavily trafficked newsgroups without
going through contortions in rn.  

Fixnews also deletes unsubscribed newsgroups from your .newsrc and
probably tramples over orphaned articles created by rn's "kill"
command.  Fixnews is intended for NNTP-style news only.

Fixnews has been moderately tested and attempts to be safe about your
.newsrc file, but no claims are made about this code.  Use at your
own risk, and enjoy.

						-- Scott Turner

#! /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:  README Makefile config.h server.h fixnews.c
# Wrapped by srt@aerospace on Fri Mar  8 14:37:48 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'README' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'README'\"
else
echo shar: Extracting \"'README'\" \(1180 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
X			       fixnews
X			   Scott R. Turner
X			srt@aerospace.aero.org
X
XUsage: fixnews [-d] [num]
X
XThis is a simple little hack that updates your .newsrc so that you
Xhave no more than <num> articles to read in every newsgroup.  If <num>
Xis omitted, then 50 articles are left.  If you have less than <num>
Xarticles to read in a newsgroup, the .newsrc line passes through
Xunchanged.  If you are unsubscribed to a newsgroup it is removed from
Xyour .newsrc.
X
XNote that the latest version of rn expects you to have every available
Xnewsgroup listed in your .newsrc.  (Which I find silly.)  If you
Xdelete lines from your .newsrc, the next time a checkgroups message
Xrolls around, you'll get asked about every deleted newsgroup.  You can
Xavoid this by using the -q option to rn, but then you won't be
Xinformed about legitimate new newsgroups.
X
XAlternately, you can call fixnews with the -d option to turn off
Xdeletion of unsubscribed newsgroups.
X
XIn case of problems, fixnews saves your old .newsrc into .newsrc.old.
X
XFixnews is intended only for NNTP-style news.  It has been moderately
Xtested, but no claims for correctness, durability, or style of coding
Xare claimed.  Use at your own risk.END_OF_FILE
if test 1180 -ne `wc -c <'README'`; then
    echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
fi
if test -f 'Makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Makefile'\"
else
echo shar: Extracting \"'Makefile'\" \(395 characters\)
sed "s/^X//" >'Makefile' <<'END_OF_FILE'
X#
X#  Makefile for Fixnews
X#  Mon Feb 11 15:37:39 1991 -- Scott "TCB" Turner
X#
X#  Set NNTPDIR correctly, and edit config.h before compiling.
X#
XCC = cc
XCFLAGS =   -O 
XNNTPDIR = /usr/src/new/news2.11/nntp1.5.10
Xlibs =  -ltermlib  
X
Xfixnews.o: config.h fixnews.c server.h
Xfixnews: fixnews.o $(NNTPDIR)/common/clientlib.o
X	$(CC) $(LDFLAGS) fixnews.o $(NNTPDIR)/common/clientlib.o -o fixnews $(libs)
X
END_OF_FILE
if test 395 -ne `wc -c <'Makefile'`; then
    echo shar: \"'Makefile'\" unpacked with wrong size!
fi
# end of 'Makefile'
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'\" \(745 characters\)
sed "s/^X//" >'config.h' <<'END_OF_FILE'
X/*
X *  Configuration File
X *  Mon Feb 11 15:32:40 1991 -- Scott "TCB" Turner
X *
X *  Various configurable definitions.  SERVER_FILE will probably need to
X *  be changed, the others probably not.
X *
X */
X
X/*
X *  Name of server file.  This can be found in the "config.h" file in
X *  the rn distribution (and I would expect in other places as well).
X *
X */
X#define SERVER_FILE "/usr/aero/lib/news/server"
X
X/*
X *  Name of .newsrc file.  Note the leading slash.
X *
X */
X#define NEWSRC "/.newsrc"
X
X/*
X *  Success code for NNTP "GROUP" command.  This can be found
X *  in the "nntp.h" file of the NNTP distribution, but shouldn't change.
X *
X */
X#define GROUP_SUCCESS 211
X
X/*
X *  Default number of articles to save in each newsgroup.
X *
X */
X#define SAVE 50
END_OF_FILE
if test 745 -ne `wc -c <'config.h'`; then
    echo shar: \"'config.h'\" unpacked with wrong size!
fi
# end of 'config.h'
fi
if test -f 'server.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'server.h'\"
else
echo shar: Extracting \"'server.h'\" \(198 characters\)
sed "s/^X//" >'server.h' <<'END_OF_FILE'
X/*
X *  External definitions for client NNTP routines.
X *
X */
Xextern	char	*getserverbyfile();
Xextern	int	server_init();
Xextern	void	put_server();
Xextern	int	get_server();
Xextern	void	close_server();
END_OF_FILE
if test 198 -ne `wc -c <'server.h'`; then
    echo shar: \"'server.h'\" unpacked with wrong size!
fi
# end of 'server.h'
fi
if test -f 'fixnews.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'fixnews.c'\"
else
echo shar: Extracting \"'fixnews.c'\" \(5546 characters\)
sed "s/^X//" >'fixnews.c' <<'END_OF_FILE'
X/*
X *  Fixnews
X *  Mon Feb 26 12:25:27 1990 -- Scott "TCB" Turner
X *
X *  This is a simple little hack that updates your .newsrc so that you
X *  have no more than <arg> articles to read in every newsgroup.  If
X *  <arg> is omitted, then 50 articles are left.  If you have less
X *  than <arg> articles to read in a newsgroup, the .newsrc line
X *  passes through unchanged.  If you are unsubscribed to a newsgroup
X *  it is removed from your .newsrc.
X *
X *  Note that the latest version of rn expects you to have every
X *  available newsgroup listed in your .newsrc.  (Which I find silly.)
X *  If you delete lines from your .newsrc, the next time a checkgroups
X *  message rolls around, you'll get asked about every deleted newsgroup.
X *  You can avoid this by using the -q option to rn, but then you
X *  won't be informed about legitimate new newsgroups.
X *
X *  Alternately, you can call fixnews with the -d option to turn off
X *  deletion of unsubscribed newsgroups.
X *
X */
X#include <sys/types.h>
X#include <stdio.h>
X#include <sys/file.h>
X#include "server.h"
X#include "config.h"
X
X/*
X *  Globals
X *
X *    save -- number of articles to save.
X *    delete -- whether to delete unsubscribed newsgroups.
X */
Xint save = SAVE;
Xint delete = 1;
X
Xvoid filternewsrc()
X{
X  FILE *in, *out;
X  char *home;
X  char newsrc[256],newsrcold[256],newsrc_line[256],
X       name[256],command[256],ser_line[256];
X  int i,j;
X  long lastread,num,first,last;
X  char *getenv();
X
X  /*
X   *  Determine user's home directory and location of ~/.newsrc
X   *
X   */
X  home = getenv("HOME");
X  if (home == NULL) {
X    fprintf(stderr,"Unable to determine home directory.\n");
X    exit(1);
X  };
X  (void) strcpy(newsrc,home);
X  (void) strcat(newsrc,NEWSRC);
X  in = fopen(newsrc, "r");
X
X  if ( in == NULL ) {
X    fprintf(stderr,"Unable to open %s.\n",newsrc);
X    exit(1);
X  };
X
X  /*
X   *   Rename .newsrc to .newsrc.old
X   *
X   */
X  (void) strcpy(newsrcold,newsrc);
X  (void) strcat(newsrcold,".old");
X  (void) rename(newsrc,newsrcold);
X  
X  /*
X   *  Open the new version.
X   *
X   */
X  out = fopen(newsrc, "w");
X
X  if ( out == NULL ) {
X    fprintf(stderr,"Unable to open %s for output.\n",newsrc);
X    exit(1);
X  };
X
X  /*
X   *  Read and process.
X   *
X   */
X  while(fgets(newsrc_line,80,in) != NULL) {
X
X    /*
X     *  This might possibly be an "options" line, in which case it
X     *  should be written out unchanged.
X     *
X     */
X    if (strncmp("option",newsrc_line,6) == 0) {
X      fprintf(out,"%s",newsrc_line);
X      continue;
X    };
X    
X    /*
X     *  Copy the name from the beginning of the .newsrc line to a
X     *  colon or a bang.  If a bang, drop it from the .newsrc.
X     *
X     */
X    for(i = 0;newsrc_line[i] != ':' && newsrc_line[i] != '!';i++)
X      name[i] = newsrc_line[i];
X    if (newsrc_line[i] == '!') {
X      if (!delete) fprintf(out,"%s",newsrc_line);
X      continue;
X    };
X    name[i] = '\0';
X    
X    /*
X     *  Get the last read article.  Search backwards for the start
X     *  of the number.  Skip over the individually marked articles.
X     *  If you think about it, this isn't quite correct (well, it
X     *  it isn't quite correct even if you don't think about it) but
X     *  it is easy and behaves reasonably.
X     *
X     */
X    for(i=strlen(newsrc_line);
X	newsrc_line[i] != '-' && newsrc_line[i] != ':';
X	i--);
X    i++;
X    lastread = atol(&(newsrc_line[i]));
X    
X    /*
X     *   Get the last article from the NNTP server.  The command for
X     *   this is "GROUP <groupname>" and the response is either:
X     *
X     *     211 <number> <first> <last> <name>
X     *
X     *                   or
X     *
X     *     411 No such newsgroup
X     *
X     */
X    sprintf(command,"GROUP %s",name);
X    put_server(command);
X    (void) get_server(ser_line, sizeof(ser_line));
X    
X    /*
X     *  Were we successful?
X     *
X     */
X    i = atoi(ser_line);
X    if (i != GROUP_SUCCESS) {
X      fprintf(stderr,"No response from NNTP for newsgroup: %s.\n",name);
X      continue;
X    };
X
X    /*
X     *  Else get the last article number available.
X     *
X     */
X    sscanf(ser_line,"%ld %ld %ld %ld",&i, &num,&first,&last);
X    if (lastread < (last - save)) {
X      fprintf(out,"%s: 1-%d\n",name,(last-save));
X    } else {
X      fprintf(out,"%s",newsrc_line);
X    };
X  };
X};
X
Xmain(argc,argv)
Xregister int argc; char **argv;
X{
X  int		response;
X  register char	*server;
X
X  /*
X   *  If there's a single argument, it's the number of articles to
X   *  save in each newsgroup.
X   *
X   */
X  while (argc > 1) {
X    /*
X     *  -d turns off line deletion.
X     *
X     */
X    if (!strcmp(argv[argc],"-d")) {
X      delete = 0;
X    } else {
X    /*
X     *  Otherwise, a number that indicates how many articles to save.
X     *
X     */
X      sscanf(argv[argc],"%d",&save);
X      if (save == 0) {
X	fprintf(stderr,"Unexpected argument to fixnews: %s.\n",argv[argc]);
X	exit(1);
X      };
X    };
X    argc--;
X  };
X
X  /*
X   *  Find the NNTP server.
X   *
X   */
X  server = getserverbyfile(SERVER_FILE);
X  if (server == NULL) {
X    fprintf(stderr, "Couldn't get name of news server from %s\n",
X	    SERVER_FILE);
X    fprintf(stderr,
X	    "Either fix this file, or put NNTPSERVER in your environment.\n");
X    exit(1);
X  }
X
X  /*
X   *  Initialize the server.
X   *
X   */
X  response = server_init(server);
X  if (response < 0) {
X    fprintf(stderr, "getactive: Can't get active file from server %s.\n",
X	    server);
X    exit(1);
X  }
X
X  /*
X   *  Set up the server handler.
X   *
X   */
X  if (handle_server_response(response, server) < 0)
X    exit(1);
X  
X  filternewsrc();
X  close_server();
X  exit(0);
X};
X
END_OF_FILE
if test 5546 -ne `wc -c <'fixnews.c'`; then
    echo shar: \"'fixnews.c'\" unpacked with wrong size!
fi
# end of 'fixnews.c'
fi
echo shar: End of shell archive.
exit 0