Subject: C News patch CR.G
Newsgroups: news.software.b

This is a patch for the C News Cleanup Release.  The distribution files
on ftp.cs.toronto.edu and zoo.toronto.edu have been updated to match.
See the README.changes diff below for what's been done.

start of patch CR.G
(suggested archive name:  patchCR.G)
apply with   patch -p0 <thisfile

Prereq: CR.F
*** README.mastercopy	Thu Apr 27 21:08:35 1995
--- README	Thu Apr 27 20:52:33 1995
***************
*** 1,4 ****
! Cleanup Release of C News, with patch CR.F			March 1995
  
  The current C News distribution can be retrieved by anonymous FTP from
  ftp.cs.toronto.edu (file pub/c-news/c-news.tar.Z) or ftp.zoo.toronto.edu
--- 1,4 ----
! Cleanup Release of C News, with patch CR.G			April 1995
  
  The current C News distribution can be retrieved by anonymous FTP from
  ftp.cs.toronto.edu (file pub/c-news/c-news.tar.Z) or ftp.zoo.toronto.edu

*** README.changes.mastercopy	Thu Apr 27 21:08:36 1995
--- README.changes	Thu Apr 27 20:55:54 1995
***************
*** 1,3 ****
--- 1,10 ----
+ High points of patch CR.G:
+ This one is basically overflow from CR.F.  Readnews's options and option
+ handling have been revamped substantially to clean them up.  And the main
+ program for dbz has been overhauled somewhat for improved portability,
+ with the addition of one new option (-v for checking whether a database
+ appears to be using dbz).
+ 
  High points of patch CR.F:
  CR.G will follow immediately, but the two should be reasonably independent.
  Another bunch of minor odds and ends.  Small extension to the batchparms

*** conf/versionname.mastercopy	Thu Apr 27 21:08:36 1995
--- conf/versionname	Thu Apr 27 20:52:47 1995
***************
*** 1 ****
! Cleanup Release, with patch CR.F
--- 1 ----
! Cleanup Release, with patch CR.G

*** conf/histsetup.mastercopy	Thu Apr 27 21:08:37 1995
--- conf/histsetup	Thu Apr 27 21:03:11 1995
***************
*** 15,30 ****
  touch history || exit 1
  if test -s history
  then
! 	# if dbz -v history
! 	if test -s history.dir
  	then
  		exit 0
  	fi
! 	echo '*** history file exists but index is not dbz format'
  	exit 1
  fi
  
! lock -o LOCK $$ || { echo '*** cannot get the lock file' ; exit 1 ; }
  status=1
  trap 'unlock LOCK ; trap 0 ; exit $status' 0 1 2 15
  
--- 15,29 ----
  touch history || exit 1
  if test -s history
  then
! 	if dbz -v history
  	then
  		exit 0
  	fi
! 	echo '*** history file exists but index is not dbz format' >&2
  	exit 1
  fi
  
! lock -o LOCK $$ || { echo '*** cannot get the lock file' >&2 ; exit 1 ; }
  status=1
  trap 'unlock LOCK ; trap 0 ; exit $status' 0 1 2 15

*** libdbz/makefile.mastercopy	Thu Apr 27 21:08:38 1995
--- libdbz/makefile	Thu Apr 27 20:53:37 1995
***************
*** 89,95 ****
  	rmdir xx
  	sed '/>	0/d' $(RHIST) >dbase.used
  	test "`cat dbase.used | wc -l`" -eq "`sed -n '2s/ .*//p' dbase.dir`" ;
! 	: ./rdbz -v dbase
  	cp $(RHIST) dbase2
  	./rdbz -E 1000 -0 -p $(RPSIZE) -t '	' dbase2
  	cmp $(RHIST) dbase
--- 89,95 ----
  	rmdir xx
  	sed '/>	0/d' $(RHIST) >dbase.used
  	test "`cat dbase.used | wc -l`" -eq "`sed -n '2s/ .*//p' dbase.dir`" ;
! 	./rdbz -v dbase
  	cp $(RHIST) dbase2
  	./rdbz -E 1000 -0 -p $(RPSIZE) -t '	' dbase2
  	cmp $(RHIST) dbase

*** libdbz/dbzmain.c.mastercopy	Thu Apr 27 21:08:38 1995
--- libdbz/dbzmain.c	Wed Apr 26 22:50:52 1995
***************
*** 28,40 ****
  char *inname = "(no file)";		/* filename for messages etc. */
  long lineno;				/* line number for messages etc. */
  
! char *basename;
  char *pagname;
! char *dirname;
  char *str2dup();
  FILE *base;
  
  int op = 'b';			/* what to do, default build a new table */
  int baseinput = 1;		/* is the base file also the input? */
  
  char *from = NULL;		/* old table to use for dbzagain() */
--- 28,41 ----
  char *inname = "(no file)";		/* filename for messages etc. */
  long lineno;				/* line number for messages etc. */
  
! char *base_name;
  char *pagname;
! char *dir_name;
  char *str2dup();
  FILE *base;
  
  int op = 'b';			/* what to do, default build a new table */
+ char *badop = "only one of -a -x -c -m -v can be given";
  int baseinput = 1;		/* is the base file also the input? */
  
  char *from = NULL;		/* old table to use for dbzagain() */
***************
*** 70,79 ****
--- 71,83 ----
  void dofile();
  void runs();
  void dosweep();
+ void verify();
  void mkfiles();
  void crfile();
  void doline();
  void process();
+ datum dofetch();
+ int dostore();
  
  #ifdef HAVERFCIZE
  extern char *rfc822ize();
***************
*** 96,126 ****
  
  	progname = argv[0];
  
! 	while ((c = getopt(argc, argv, "axcmt:l:R0E:SqOiX:Yuf:p:eMUC:T:wd")) != EOF)
  		switch (c) {
  		case 'a':	/* append to existing table */
  			if (op != 'b')
! 				fail("only one of -a -x -c -m can be given", "");
  			op = 'a';
  			baseinput = 0;
  			break;
  		case 'x':	/* extract from existing table */
  			if (op != 'b')
! 				fail("only one of -a -x -c -m can be given", "");
  			op = 'x';
  			baseinput = 0;
  			break;
  		case 'c':	/* check existing table */
  			if (op != 'b')
! 				fail("only one of -a -x -c -m can be given", "");
  			op = 'c';
  			break;
  		case 'm':	/* extract missing (complement of -x) */
  			if (op != 'b')
! 				fail("only one of -a -x -c -m can be given", "");
  			op = 'm';
  			baseinput = 0;
  			break;
  		case 't':	/* set field separator */
  			if (strlen(optarg) > (size_t)1)
  				fail("only one field separator allowed", "");
--- 100,135 ----
  
  	progname = argv[0];
  
! 	while ((c = getopt(argc, argv, "axcmvt:l:R0E:SqOiX:Yuf:p:eMUC:T:wd")) != EOF)
  		switch (c) {
  		case 'a':	/* append to existing table */
  			if (op != 'b')
! 				fail(badop, "");
  			op = 'a';
  			baseinput = 0;
  			break;
  		case 'x':	/* extract from existing table */
  			if (op != 'b')
! 				fail(badop, "");
  			op = 'x';
  			baseinput = 0;
  			break;
  		case 'c':	/* check existing table */
  			if (op != 'b')
! 				fail(badop, "");
  			op = 'c';
  			break;
  		case 'm':	/* extract missing (complement of -x) */
  			if (op != 'b')
! 				fail(badop, "");
  			op = 'm';
  			baseinput = 0;
  			break;
+ 		case 'v':	/* verify that this is a dbz file */
+ 			if (op != 'b')
+ 				fail(badop, "");
+ 			op = 'v';
+ 			break;
  		case 't':	/* set field separator */
  			if (strlen(optarg) > (size_t)1)
  				fail("only one field separator allowed", "");
***************
*** 206,225 ****
  		}
  	if (errflg || optind >= argc || (optind+1 < argc && baseinput)) {
  		fprintf(stderr, "usage: %s ", progname);
! 		fprintf(stderr, "[-a] [-x] [-c] database [file] ...\n");
  		exit(2);
  	}
  
  	(void) dbzincore(useincore);
  	(void) dbzwritethrough(dowt);
! 	basename = argv[optind];
! 	pagname = str2dup(basename, ".pag");
! 	dirname = str2dup(basename, ".dir");
  	mkfiles();
  	optind++;
  
  	if (baseinput)		/* implies no further arguments */
! 		process(base, basename);
  	else if (optind >= argc)
  		process(stdin, "stdin");
  	else
--- 215,240 ----
  		}
  	if (errflg || optind >= argc || (optind+1 < argc && baseinput)) {
  		fprintf(stderr, "usage: %s ", progname);
! 		fprintf(stderr, "[-{axcmv}] database [file] ...\n");
  		exit(2);
  	}
  
  	(void) dbzincore(useincore);
  	(void) dbzwritethrough(dowt);
! 	base_name = argv[optind];
! 	pagname = str2dup(base_name, ".pag");
! 	dir_name = str2dup(base_name, ".dir");
! 
! 	if (op == 'v') {
! 		verify(dir_name);
! 		/* NOTREACHED */
! 	}
! 
  	mkfiles();
  	optind++;
  
  	if (baseinput)		/* implies no further arguments */
! 		process(base, base_name);
  	else if (optind >= argc)
  		process(stdin, "stdin");
  	else
***************
*** 233,239 ****
  	if (doruns)
  		runs(pagname);
  	if (sweep)
! 		dosweep(basename, pagname);
  	if (printx)
  		printf("%ld\n", xxx);
  	exit(0);
--- 248,254 ----
  	if (doruns)
  		runs(pagname);
  	if (sweep)
! 		dosweep(base_name, pagname);
  	if (printx)
  		printf("%ld\n", xxx);
  	exit(0);
***************
*** 240,245 ****
--- 255,284 ----
  }
  
  /*
+  - verify - just check whether the .dir file looks right or not
+  */
+ void				/* does not return */
+ verify(dir)
+ char *dir;
+ {
+ 	FILE *f;
+ 	char buf[4];
+ 	size_t n;
+ 
+ 	f = fopen(dir, "r");
+ 	if (f == NULL)
+ 		exit(1);
+ 	n = fread(buf, sizeof(buf), 1, f);
+ 	(void) fclose(f);
+ 
+ 	if (n != 1 || memcmp(buf, "dbz ", (size_t)4) != 0)
+ 		exit(1);
+ 
+ 	exit(0);
+ 	/* NOTREACHED */
+ }
+ 
+ /*
   - dofile - open a file and invoke process()
   */
  void
***************
*** 266,294 ****
  mkfiles()
  {
  	if (op == 'b' && !dbzint) {
! 		crfile(dirname);
  		crfile(pagname);
  	}
  
! 	base = fopen(basename, (op == 'a') ? "a" : "r");
  	if (base == NULL)
! 		fail("cannot open `%s'", basename);
  	if (unopen)
! 		(void) chmod(basename, 0);
  	if (from != NULL) {
! 		if (dbzagain(basename, from) < 0)
! 			fail("dbzagain(`%s'...) failed", basename);
  	} else if (op == 'b' && dbzint) {
  		if (!exact)
  			siz = dbzsize(siz);
  		if (tagsize != 0)
  			tag = dbztagmask(tagsize);
! 		if (dbzfresh(basename, siz, (int)fs, map, tag) < 0)
! 			fail("dbzfresh(`%s'...) failed", basename);
! 	} else if (dbminit(basename) < 0)
! 		fail("dbminit(`%s') failed", basename);
  	if (unopen)
! 		(void) chmod(basename, 0600);	/* hard to restore original */
  }
  
  /*
--- 305,333 ----
  mkfiles()
  {
  	if (op == 'b' && !dbzint) {
! 		crfile(dir_name);
  		crfile(pagname);
  	}
  
! 	base = fopen(base_name, (op == 'a') ? "a" : "r");
  	if (base == NULL)
! 		fail("cannot open `%s'", base_name);
  	if (unopen)
! 		(void) chmod(base_name, 0);
  	if (from != NULL) {
! 		if (dbzagain(base_name, from) < 0)
! 			fail("dbzagain(`%s'...) failed", base_name);
  	} else if (op == 'b' && dbzint) {
  		if (!exact)
  			siz = dbzsize(siz);
  		if (tagsize != 0)
  			tag = dbztagmask(tagsize);
! 		if (dbzfresh(base_name, siz, (int)fs, map, tag) < 0)
! 			fail("dbzfresh(`%s'...) failed", base_name);
! 	} else if (dbminit(base_name) < 0)
! 		fail("dbminit(`%s') failed", base_name);
  	if (unopen)
! 		(void) chmod(base_name, 0600);	/* hard to restore original */
  }
  
  /*
***************
*** 371,393 ****
  		place = ftell(base);
  		llen = strlen(lp);
  		if (fwrite(lp, 1, llen, base) != llen)
! 			fail("write error in `%s'", basename);
  		/* FALLTHROUGH */
  	case 'b':
  		if (omitzero && p != NULL && *(p+1) == '0')
  			return;
  		if (unique) {
! 			value = (dbzint) ? dbzfetch(key) : fetch(key);
  			if (value.dptr != NULL)
  				fail("`%s' already present", lp);
  		}
  		value.dptr = (char *)&place;
  		value.dsize = (int)sizeof(place);
! 		if (((dbzint) ? dbzstore(key, value) : store(key, value)) < 0)
  			fail("store failed on `%s'", lp);
  		break;
  	case 'c':
! 		value = (dbzint) ? dbzfetch(key) : fetch(key);
  		shouldfind = (omitzero && p != NULL && *(p+1) == '0') ? 0 : 1;
  		if (!shouldfind && (value.dptr != NULL || value.dsize != 0))
  			fail("`%s' found, shouldn't be", lp);
--- 410,432 ----
  		place = ftell(base);
  		llen = strlen(lp);
  		if (fwrite(lp, 1, llen, base) != llen)
! 			fail("write error in `%s'", base_name);
  		/* FALLTHROUGH */
  	case 'b':
  		if (omitzero && p != NULL && *(p+1) == '0')
  			return;
  		if (unique) {
! 			value = dofetch(key);
  			if (value.dptr != NULL)
  				fail("`%s' already present", lp);
  		}
  		value.dptr = (char *)&place;
  		value.dsize = (int)sizeof(place);
! 		if (dostore(key, value) < 0)
  			fail("store failed on `%s'", lp);
  		break;
  	case 'c':
! 		value = dofetch(key);
  		shouldfind = (omitzero && p != NULL && *(p+1) == '0') ? 0 : 1;
  		if (!shouldfind && (value.dptr != NULL || value.dsize != 0))
  			fail("`%s' found, shouldn't be", lp);
***************
*** 407,413 ****
  		}
  		break;
  	case 'x':
! 		value = (dbzint) ? dbzfetch(key) : fetch(key);
  		if (value.dptr != NULL && !quick) {
  			(void) memcpy((char *)&place, value.dptr, sizeof(place));
  			if (fseek(base, place, SEEK_SET) != 0)
--- 446,452 ----
  		}
  		break;
  	case 'x':
! 		value = dofetch(key);
  		if (value.dptr != NULL && !quick) {
  			(void) memcpy((char *)&place, value.dptr, sizeof(place));
  			if (fseek(base, place, SEEK_SET) != 0)
***************
*** 419,425 ****
  			fputs(lp, stdout);
  		break;
  	case 'm':
! 		value = (dbzint) ? dbzfetch(key) : fetch(key);
  		if (value.dptr == NULL) {
  			fputs(keytext, stdout);
  			putchar('\n');
--- 458,464 ----
  			fputs(lp, stdout);
  		break;
  	case 'm':
! 		value = dofetch(key);
  		if (value.dptr == NULL) {
  			fputs(keytext, stdout);
  			putchar('\n');
***************
*** 529,532 ****
--- 568,598 ----
  	(void) strcpy(p, s1);
  	(void) strcat(p, s2);
  	return(p);
+ }
+ 
+ /*
+  - dofetch - do a fetch or dbzfetch
+  */
+ datum
+ dofetch(key)
+ datum key;
+ {
+ 	if (dbzint)
+ 		return(dbzfetch(key));
+ 	else
+ 		return(fetch(key));
+ }
+ 
+ /*
+  - dostore - do a store or dbzstore
+  */
+ int
+ dostore(key, value)
+ datum key;
+ datum value;
+ {
+ 	if (dbzint)
+ 		return(dbzstore(key, value));
+ 	else
+ 		return(store(key, value));
  }

*** man/readnews.1cn.mastercopy	Thu Apr 27 21:08:39 1995
--- man/readnews.1cn	Sun Apr 16 22:31:42 1995
***************
*** 4,23 ****
  .ds b /usr/libexec/news
  .\" =()<.ds c @<NEWSCTL>@>()=
  .ds c /etc/news
! .TH READNEWS 1CN "8 July 1993"
  .BY "C News"
  .SH NAME
  readnews \- read news articles
  .SH SYNOPSIS
  .B readnews
! .RB [ -n
! newsgroups]
! .RB [ -d
! commands]
! .RB [ -i ]
! .RB [ -clpC ]
! .RB [ -s [ -+?
! .RI [ group ]]]
  .SH DESCRIPTION
  .I Readnews
  without arguments enters command mode,
--- 4,41 ----
  .ds b /usr/libexec/news
  .\" =()<.ds c @<NEWSCTL>@>()=
  .ds c /etc/news
! .\"
! .\"
! .\"
! .TH READNEWS 1CN "16 April 1995"
  .BY "C News"
  .SH NAME
  readnews \- read news articles
  .SH SYNOPSIS
  .B readnews
! [
! .B \-n
! newsgroups ]
! [
! .B \-d
! commands ]
! [
! .B \-i
! ] [
! .B \-c
! ] [
! .B \-l
! ] [
! .B \-p
! ] [
! .B \-C
! ] [
! .B \-L
! ] [
! .BR \-A group
! ] [
! .BR \-D group
! ]
  .SH DESCRIPTION
  .I Readnews
  without arguments enters command mode,
***************
*** 35,70 ****
  Some useful functions are available which don't use command mode.
  The flags for these are:
  .TP
! .B -c
  Check if there is news, and if so print `You have news.'.
  .TP
! .B -C
  Check if there is news, and print the groups and number of
  articles in each group to be read.
  .TP
! .B -l
  List the titles of available news articles.
  .TP
! .B -p
  Print all articles on standard output,
  and update
  .IR newsrc .
  .TP
! .B -s
  Print the newsgroup subscription list.
  .TP
! .BI -s+ " group"
  Add
  .I group
  to the subscription list.
  .TP
! .BI -s- " group"
! Subtract
  .I group
  from the subscription list.
- .TP
- .B -s?
- List currently active newsgroups.
  .P
  The remaining flags mostly determine article selection,
  and may also appear in the
--- 53,85 ----
  Some useful functions are available which don't use command mode.
  The flags for these are:
  .TP
! .B \-c
  Check if there is news, and if so print `You have news.'.
  .TP
! .B \-C
  Check if there is news, and print the groups and number of
  articles in each group to be read.
  .TP
! .B \-l
  List the titles of available news articles.
  .TP
! .B \-p
  Print all articles on standard output,
  and update
  .IR newsrc .
  .TP
! .B \-L
  Print the newsgroup subscription list.
  .TP
! .BI \-A group
  Add
  .I group
  to the subscription list.
  .TP
! .BI \-D group
! Delete
  .I group
  from the subscription list.
  .P
  The remaining flags mostly determine article selection,
  and may also appear in the
***************
*** 75,102 ****
  file by entering lines prefixed with the word `options',
  followed by the options arguments.
  This is most useful with the
! .B -n
  flag, specifying the usual groups one wishes to subscribe to.
  .TP
! \fB-n \fInewsgroups\fR
  Select all articles belonging to
  .IR newsgroups .
! .I newsgroups
  is a comma separated list of newsgroup names.
  The character `!' may be used to exclude certain groups,
  and the word `all' can be used to match any group.
  e.g. `-n all,!net.jokes'
  .TP
! .B -i
  Ignore
  .I .newsrc
  file. It is not read or updated.
  This allows selection of articles that have already been read.
  .TP
! \fB-d \fIcommands\fR
  Disable the
  .IR commands .
! .I commands
  is a string of command characters (see the next section);
  entering any command beginning with any of them will result in 
  an error message.
--- 90,117 ----
  file by entering lines prefixed with the word `options',
  followed by the options arguments.
  This is most useful with the
! .B \-n
  flag, specifying the usual groups one wishes to subscribe to.
  .TP
! \fB\-n \fInewsgroups\fR
  Select all articles belonging to
  .IR newsgroups .
! .I Newsgroups
  is a comma separated list of newsgroup names.
  The character `!' may be used to exclude certain groups,
  and the word `all' can be used to match any group.
  e.g. `-n all,!net.jokes'
  .TP
! .B \-i
  Ignore
  .I .newsrc
  file. It is not read or updated.
  This allows selection of articles that have already been read.
  .TP
! \fB\-d \fIcommands\fR
  Disable the
  .IR commands .
! .I Commands
  is a string of command characters (see the next section);
  entering any command beginning with any of them will result in 
  an error message.
***************
*** 129,135 ****
  This section details the commands available when
  .I readnews
  is in command mode (no
! .B -clpsC
  arguments).
  The simplest way of using this mode, is to enter RETURN after every
  prompt.
--- 144,150 ----
  This section details the commands available when
  .I readnews
  is in command mode (no
! .B \-clpsC
  arguments).
  The simplest way of using this mode, is to enter RETURN after every
  prompt.
***************
*** 157,163 ****
  .B .
  Print the current article.
  .TP
! .B -
  Go back to the previous article. This is a toggle, typing it
  twice returns you to the original article.
  .TP
--- 172,178 ----
  .B .
  Print the current article.
  .TP
! .B \-
  Go back to the previous article. This is a toggle, typing it
  twice returns you to the original article.
  .TP
***************
*** 203,209 ****
  The
  .I .newsrc
  file will be updated provided the flag
! .B -i
  was not specified.
  .TP
  .B x
--- 218,224 ----
  The
  .I .newsrc
  file will be updated provided the flag
! .B \-i
  was not specified.
  .TP
  .B x
***************
*** 309,314 ****
--- 324,346 ----
  when displaying article bodies.
  This heads off letter bombs at the price of interfering with use of
  non-ASCII character sets.
+ .PP
+ Cleanup of command-line syntax has eliminated the old
+ .B \-s
+ option in favor of
+ .BR \-L ,
+ .BR \-A ,
+ and
+ .BR \-D .
+ This is a change for the better, but an incompatible one.
+ .PP
+ The
+ .B \-A
+ and
+ .B \-D
+ options
+ have a nasty tendency to dump core;
+ they should be fixed or deleted.
  .PP
  This program is about as simple as they come.
  Almost any seasoned news user will want something more complex.

*** readnews/newsrc.c.mastercopy	Thu Apr 27 21:08:40 1995
--- readnews/newsrc.c	Sun Apr 16 22:09:06 1995
***************
*** 103,110 ****
  	if (!*cp)
  		return;
  
! 	argc = 1;
! 	argv = (char **) myalloc(sizeof(char *));
  	argv[argc - 1] = cp;
  	while (*cp && (cp = strpbrk(cp, " \t")) != NULL) {
  		while (*cp == ' ' || *cp == '\t')
--- 103,111 ----
  	if (!*cp)
  		return;
  
! 	argc = 2;
! 	argv = (char **) myalloc(2 * sizeof(char *));
! 	argv[0] = "options";
  	argv[argc - 1] = cp;
  	while (*cp && (cp = strpbrk(cp, " \t")) != NULL) {
  		while (*cp == ' ' || *cp == '\t')
***************
*** 116,122 ****
  			argv[argc - 1] = cp;
  		}
  	}
! 	if (options(argc, argv, false))
  		error("Bad options: %s line %d: %s", rcname, rclineno, s);
  	free((char *) argv);
  }
--- 117,123 ----
  			argv[argc - 1] = cp;
  		}
  	}
! 	if (options(argc, argv, false) < 0)
  		error("Bad options: %s line %d: %s", rcname, rclineno, s);
  	free((char *) argv);
  }

*** readnews/readnews.c.mastercopy	Thu Apr 27 21:08:40 1995
--- readnews/readnews.c	Sun Apr 16 22:26:21 1995
***************
*** 22,28 ****
  bool Cflag;		/* -C verbose -c */
  bool sflag;		/* -s print newsgroup subscription list */
  bool splus;		/* -s+ */
- bool slistall;		/* -s? */
  bool sminus;		/* -s- */
  char *sarg;		/* arg to -s[+-] */
  char *nflag;		/* -n newsgroups */
--- 22,27 ----
***************
*** 53,61 ****
  
  	progname = argv[0];
  	setbuf(stdout, buf);
! 	if (options(--argc, ++argv, true)) {
  		(void) fprintf(stderr,
! 	"Usage: readnews [-n newsgroups] [-i] [-clpC] [-s[-+? [group]]]\n");
  		exit(1);
  	}
  	now = time(&now);
--- 52,60 ----
  
  	progname = argv[0];
  	setbuf(stdout, buf);
! 	if (options(argc, argv, true) < 0) {
  		(void) fprintf(stderr,
! 	"Usage: readnews [-n newsgroups] [-i] [-clpCL] [-Agroup] [-Dgroup]\n");
  		exit(1);
  	}
  	now = time(&now);
***************
*** 134,219 ****
   * process options
   * can be called from readnewsrc()
   */
  options(argc, argv, cline)
  int argc;
  char *argv[];
  bool cline;
  {
! 	register char c;
! 
! 	/* should use getopt(3)... but the -s syntax can't */
! 	while (argc > 0) {
! 		if (argv[0][0] != '-')
! 			break;
! 		while (c = *(++(argv[0]))) {
! 			switch (c) {
! 			case 'n':
! 				if (cline)
! 					nflag = argv[1], n_on_cline = true;
! 				else {
! 					if (!n_on_cline)
! 						nflag = (nflag?
! 							catstr2(nflag, NGSEPS, argv[1]):
! 							newstr(argv[1]));
! 					rcgrps = (rcgrps?
! 						catstr2(rcgrps, NGSEPS, argv[1]):
! 						newstr(argv[1]));
! 				}
! 				argc--, argv++; 
! 				break;
! 			case 'd':
! 				disable = (disable?
! 						catstr2(disable, "", argv[1]):
! 						newstr(argv[1]));
! 				argc--, argv++;
! 				break;
! 			case 'i':
! 				iflag = true; 
! 				continue;
! 			case 's':
! 				sflag = true;
! 				switch (argv[0][1]) {
! 				case '\0':
! 					continue;
! 				case '+':
! 					splus = true; 
! 					break;
! 				case '?':
! 					slistall = true, ++(argv[0]); 
! 					continue;
! 				case '-':
! 					sminus = true; 
! 					break;
! 				default:
! 					argc = -1; 
! 					break;
! 				}
! 				if (argc > 0) {
! 					sarg = newstr(argv[1]);
! 					argc--, argv++;
! 				}
! 				break;
! 			case 'p':
! 				pflag = true; 
! 				continue;
! 			case 'l':
! 				lflag = true; 
! 				continue;
! 			case 'c':
! 				cflag = true; 
! 				continue;
! 			case 'C':
! 				cflag = Cflag = true; 
! 				continue;
! 			default:
! 				argc = -1; 
! 				break;
  			}
  			break;
  		}
! 		argc--, argv++;
! 	}
! 	return argc != 0;
  }
  
  /*
--- 133,204 ----
   * process options
   * can be called from readnewsrc()
   */
+ int				/* < 0 failure, otherwise success */
  options(argc, argv, cline)
  int argc;
  char *argv[];
  bool cline;
  {
! 	int c;
! 	extern int optind;
! 	extern char *optarg;
! 
! 	optind = 1;			/* reset scan, if necessary */
! 	while ((c = getopt(argc, argv, "n:d:iLA:D:plcC")) != EOF)
! 		switch (c) {
! 		case 'n':
! 			if (cline)
! 				nflag = optarg, n_on_cline = true;
! 			else {
! 				if (!n_on_cline)
! 					nflag = (nflag?
! 						catstr2(nflag, NGSEPS, optarg):
! 						newstr(optarg));
! 				rcgrps = (rcgrps?
! 					catstr2(rcgrps, NGSEPS, optarg):
! 					newstr(optarg));
  			}
  			break;
+ 		case 'd':
+ 			disable = (disable?
+ 					catstr2(disable, "", optarg):
+ 					newstr(optarg));
+ 			break;
+ 		case 'i':
+ 			iflag = true; 
+ 			break;
+ 		case 'L':
+ 			sflag = true;
+ 			break;
+ 		case 'A':
+ 			sflag = true;
+ 			splus = true;
+ 			sarg = optarg;
+ 			break;
+ 		case 'D':
+ 			sflag = true;
+ 			sminus = true;
+ 			sarg = optarg;
+ 			break;
+ 		case 'p':
+ 			pflag = true; 
+ 			break;
+ 		case 'l':
+ 			lflag = true; 
+ 			break;
+ 		case 'c':
+ 			cflag = true; 
+ 			break;
+ 		case 'C':
+ 			cflag = Cflag = true; 
+ 			break;
+ 		case '?':
+ 		default:
+ 			return(-1);
+ 			break;
  		}
! 
! 	return(0);
  }
  
  /*
***************
*** 228,244 ****
  	register char *tmp, *com;
  	register FILE *f;
  
! 	if (slistall) {
! 		(void) printf("Active newsgroups:\n");
! 		(void) fflush(stdout);
! 		/* possibly vestigial code here, old #ifdefs deleted */
! 		f = stdout;
! 		com = 0;		/* for lint */
! 		com = com;		/* for lint */
! 		for (ap = alist; ap; ap = ap->a_next)
! 			(void) fprintf(f, "%s\n", ap->a_name);
! 		return false;
! 	} else if (splus || sminus) {
  		if (strpbrk(sarg, BADGRPCHARS)) {
  			(void) printf("%s: Illegal char in newsgroup.\n", sarg);
  			return false;
--- 213,219 ----
  	register char *tmp, *com;
  	register FILE *f;
  
! 	if (splus || sminus) {
  		if (strpbrk(sarg, BADGRPCHARS)) {
  			(void) printf("%s: Illegal char in newsgroup.\n", sarg);
  			return false;