[net.sources] 2.6-2.7.c

ARPAVAX:usenet (06/08/82)

Common subdirectories: 2.6/doc and 2.7/doc
Common subdirectories: 2.6/man and 2.7/man
Common subdirectories: 2.6/misc and 2.7/misc
Only in 2.7: new.2.7
Common subdirectories: 2.6/src and 2.7/src
diff -c -r 2.6/man/checknews.1 2.7/man/checknews.1
*** 2.6/man/checknews.1	Sun Apr  4 20:34:53 1982
--- 2.7/man/checknews.1	Sat Jun  5 19:40:49 1982
***************
*** 2,8
  .SH NAME
  checknews \- check to see if user has news
  .SH SYNOPSIS
! checknews [ynqevv] [readnews options]
  .SH DESCRIPTION
  .I checknews
  reports to the user whether or not he has news.

--- 2,9 -----
  .SH NAME
  checknews \- check to see if user has news
  .SH SYNOPSIS
! .BR checknews " [ " ynqevv " ]  [ "
! .IR "readnews options" " ] "
  .SH DESCRIPTION
  .I checknews
  reports to the user whether or not he has news.
***************
*** 37,43
  .TP 10
  .B e
  Executes
! .I readnews(1)
  if there is news.
  .PP
  If there are no options,

--- 38,44 -----
  .TP 10
  .B e
  Executes
! .IR readnews (1)
  if there is news.
  .PP
  If there are no options,
***************
*** 46,51
  .SH FILES
  .PD 0
  .TP 25
  /usr/lib/news/active
  Active newsgroups
  .TP 25

--- 47,53 -----
  .SH FILES
  .PD 0
  .TP 25
+ ~/.newsrc
  /usr/lib/news/active
  Active newsgroups
  Options and list of previously read articles
***************
*** 48,55
  .TP 25
  /usr/lib/news/active
  Active newsgroups
- .TP 25
- ~/.newsrc
  Options and list of previously read articles
  .SH SEE ALSO
  readnews(1),

--- 50,55 -----
  ~/.newsrc
  /usr/lib/news/active
  Active newsgroups
  Options and list of previously read articles
  .SH SEE ALSO
  inews(1),
***************
*** 52,56
  ~/.newsrc
  Options and list of previously read articles
  .SH SEE ALSO
! readnews(1),
! inews(1)

--- 52,57 -----
  Active newsgroups
  Options and list of previously read articles
  .SH SEE ALSO
! inews(1),
! postnews(1),
! readnews(1)
diff -c -r 2.6/man/expire.8 2.7/man/expire.8
*** 2.6/man/expire.8	Tue Mar 30 18:43:45 1982
--- 2.7/man/expire.8	Sat Jun  5 19:40:52 1982
***************
*** 2,27
  .SH NAME
  expire \- remove outdated news articles
  .SH SYNOPSIS
! /usr/lib/news/expire
! [
! .B \-n
! .I newsgroups
! ]
! [
! .B \-i
! ]
! [
! .B \-I
! ]
! [
! .B \-v
! [
! .I level
! ] ]
! [
! .B \-e
! .I days
! ]
  .SH DESCRIPTION
  .PP
  .I Expire

--- 2,13 -----
  .SH NAME
  expire \- remove outdated news articles
  .SH SYNOPSIS
! .BR /usr/lib/news/expire " [ " \-n
! .IR newsgroups " ] [ "
! .BR \-i " ] [ " \-I " ] [ " \-v " [ "
! .IR level " ] ] [ "
! .BI \-e days
! " ] "
  .SH DESCRIPTION
  .PP
  .I Expire
***************
*** 25,32
  .SH DESCRIPTION
  .PP
  .I Expire
! is normally started up by cron(8) every night
! to remove all expired news.
  If no newsgroups are specified, the default is to expire
  .BI all .
  .PP

--- 11,19 -----
  .SH DESCRIPTION
  .PP
  .I Expire
! is normally started up by
! .IR cron (8)
! every night to remove all expired news.
  If no newsgroups are specified, the default is to expire
  .BR all .
  .PP
***************
*** 28,34
  is normally started up by cron(8) every night
  to remove all expired news.
  If no newsgroups are specified, the default is to expire
! .BI all .
  .PP
  Articles whose specified expiration date has already passed
  are considered expirable.

--- 15,21 -----
  .IR cron (8)
  every night to remove all expired news.
  If no newsgroups are specified, the default is to expire
! .BR all .
  .PP
  Articles whose specified expiration date has already passed
  are considered expirable.
***************
*** 69,74
  If you have articles archived by giving them expiration dates far into the
  future, these options might remove these files anyway.
  .SH "SEE ALSO"
  inews(1),
  uurec(8),
  sendnews(8),

--- 56,62 -----
  If you have articles archived by giving them expiration dates far into the
  future, these options might remove these files anyway.
  .SH "SEE ALSO"
+ checknews(1),
  inews(1),
  readnews(1),
  recnews(8),
***************
*** 70,77
  future, these options might remove these files anyway.
  .SH "SEE ALSO"
  inews(1),
- uurec(8),
- sendnews(8),
  readnews(1),
  checknews(1)
  .SH BUGS

--- 58,63 -----
  .SH "SEE ALSO"
  checknews(1),
  inews(1),
  readnews(1),
  recnews(8),
  sendnews(8),
***************
*** 73,79
  uurec(8),
  sendnews(8),
  readnews(1),
! checknews(1)
  .SH BUGS
  The default expiration date should be applied by expire.
  This would allow different defaults for different newsgroups

--- 59,67 -----
  checknews(1),
  inews(1),
  readnews(1),
! recnews(8),
! sendnews(8),
! uurec(8)
  .SH BUGS
  The default expiration date should be applied by expire.
  This would allow different defaults for different newsgroups
***************
*** 77,83
  .SH BUGS
  The default expiration date should be applied by expire.
  This would allow different defaults for different newsgroups
! (by adding a \-e option to expire and having different invocations)
  and would defer the choice until the time for expiration comes.
  It would also make less demands on disk space since it would be
  possible to do uux \-c.

--- 65,73 -----
  .SH BUGS
  The default expiration date should be applied by expire.
  This would allow different defaults for different newsgroups
! (by adding a
! .B \-e
! option to expire and having different invocations)
  and would defer the choice until the time for expiration comes.
  It would also make less demands on disk space since it would be
  possible to do
***************
*** 80,85
  (by adding a \-e option to expire and having different invocations)
  and would defer the choice until the time for expiration comes.
  It would also make less demands on disk space since it would be
! possible to do uux \-c.
  Currently, the default is applied by inews when the article
  is first seen by the system.

--- 70,76 -----
  option to expire and having different invocations)
  and would defer the choice until the time for expiration comes.
  It would also make less demands on disk space since it would be
! possible to do
! .I "uux \-c".
  Currently, the default is applied by inews when the article
  is first seen by the system.
diff -c -r 2.6/man/inews.1 2.7/man/inews.1
*** 2.6/man/inews.1	Tue Apr 20 10:47:08 1982
--- 2.7/man/inews.1	Sat Jun  5 20:24:19 1982
***************
*** 2,16
  .SH NAME
  inews \- submit news articles
  .SH SYNOPSIS
! .B inews
! .B \-t
! title
! [
! .B \-n
! newsgroups ]
! [
! .B \-e
! expiration date ]
  .PP
  .B inews
  .B \-p

--- 2,13 -----
  .SH NAME
  inews \- submit news articles
  .SH SYNOPSIS
! .B "inews \-t "
! .IR title " [ "
! .B \-n 
! .IR newsgroups " ] [ "
! .B \-e 
! .IR "expiration date" " ]"
  .PP
  .B "inews \-p"
  .RI " [ " filename " ] "
***************
*** 12,21
  .B \-e
  expiration date ]
  .PP
! .B inews
! .B \-p
! [
! filename ]
  .PP
  .B inews
  .B \-C

--- 9,16 -----
  .B \-e 
  .IR "expiration date" " ]"
  .PP
! .B "inews \-p"
! .RI " [ " filename " ] "
  .PP
  .BI "inews \-C " newsgroup
  .SH DESCRIPTION
***************
*** 17,25
  [
  filename ]
  .PP
! .B inews
! .B \-C
! newsgroup
  .SH DESCRIPTION
  .I Inews
  submits news articles to the USENET news

--- 12,18 -----
  .B "inews \-p"
  .RI " [ " filename " ] "
  .PP
! .BI "inews \-C " newsgroup
  .SH DESCRIPTION
  .I Inews
  submits news articles to the USENET news
***************
*** 25,32
  submits news articles to the USENET news
  network.  The first form is for submitting user articles.
  The body will be read from the standard
! input.  A 
! .I title 
  must be specified as there is no default.  Each article
  belongs to a list of newsgroups.  If the 
  .B \-n 

--- 18,25 -----
  submits news articles to the USENET news
  network.  The first form is for submitting user articles.
  The body will be read from the standard
! input.  A
! .I title
  must be specified as there is no default.  Each article
  belongs to a list of newsgroups.  If the
  .B \-n
***************
*** 28,35
  input.  A 
  .I title 
  must be specified as there is no default.  Each article
! belongs to a list of newsgroups.  If the 
! .B \-n 
  flag is omitted, the list
  will default to something like "general".  If you wish to submit
  an article in multiple newsgroups, the

--- 21,28 -----
  input.  A
  .I title
  must be specified as there is no default.  Each article
! belongs to a list of newsgroups.  If the
! .B \-n
  flag is omitted, the list
  will default to something line 
  .IR general .
***************
*** 31,37
  belongs to a list of newsgroups.  If the 
  .B \-n 
  flag is omitted, the list
! will default to something like "general".  If you wish to submit
  an article in multiple newsgroups, the
  .I newsgroups
  must be separated by commas and/or spaces.

--- 24,34 -----
  belongs to a list of newsgroups.  If the
  .B \-n
  flag is omitted, the list
! will default to something line 
! .IR general .
! (On ours, it is 
! .IR general .)
! If you wish to submit
  an article in multiple newsgroups, the
  .I newsgroups
  must be separated by commas and/or spaces.
***************
*** 54,59
  .LP
  The third form is for creating new newsgroups.  On some systems, this may
  be limited to specific users such as the super-user or news administrator.
  .SH FILES
  .PD 0
  .TP 25

--- 51,76 -----
  .LP
  The third form is for creating new newsgroups.  On some systems, this may
  be limited to specific users such as the super-user or news administrator.
+ (This happens on ours.)
+ .LP
+ If the file /usr/lib/news/recording is present, it is taken as a list of
+ "recordings" to be shown to users posting news.
+ (This is by analogy to the recording you hear when you dial information
+ in some parts of the country, asking you if you really wanted to do this.)
+ The file contains lines of the form:
+ .br
+ 	newsgroups <tab> filename
+ .br
+ for example:
+ .br
+ 	net.all	/usr/lib/news/net.recording
+ 	fa.all	/usr/lib/news/fa.recording
+ .br
+ Any user posting an article to a newsgroup matching the pattern on
+ the left will be shown the contents of the file on the right.
+ The user is then told to hit DEL to abort or RETURN to proceed.
+ The intent of this feature is to help companies keep proprietary
+ information from accidently leaking out.
  .SH FILES
  .PD 0
  .TP 25
***************
*** 79,87
  System subscription list
  .PD
  .SH SEE ALSO
! mail(1),
! readnews(1),
! uucp(1),
  getdate(3),
  msgs(1),
  recnews(1),

--- 96,103 -----
  System subscription list
  .PD
  .SH SEE ALSO
! Mail(1),
! binmail(1),
  getdate(3),
  msgs(1),
  news(5),
***************
*** 84,89
  uucp(1),
  getdate(3),
  msgs(1),
  recnews(1),
  sendnews(8),
  uurec(8),

--- 100,108 -----
  binmail(1),
  getdate(3),
  msgs(1),
+ news(5),
+ newsrc(5)
+ readnews(1),
  recnews(1),
  sendnews(8),
  uucp(1),
***************
*** 86,91
  msgs(1),
  recnews(1),
  sendnews(8),
  uurec(8),
  news(5),
  newsrc(5)

--- 105,111 -----
  readnews(1),
  recnews(1),
  sendnews(8),
+ uucp(1),
  uurec(8),
  .SH AUTHORS
  Matt Glickman
***************
*** 87,94
  recnews(1),
  sendnews(8),
  uurec(8),
- news(5),
- newsrc(5)
  .SH AUTHORS
  Matt Glickman
  .br

--- 107,112 -----
  sendnews(8),
  uucp(1),
  uurec(8),
  .SH AUTHORS
  Matt Glickman
  .br
diff -c -r 2.6/man/news.5 2.7/man/news.5
*** 2.6/man/news.5	Tue Apr 20 10:52:39 1982
--- 2.7/man/news.5	Sun May 16 15:33:34 1982
***************
*** 107,116
  .I subscriptions
  is the list of newsgroups to be transmitted to the system.  The
  .I flags
! are a set of keys describing how the article should be transmitted.  Currently,
! only the
! .B A
! flag (transmit in old format) is implemented.  The default is no flags.
  .LP
  The
  .I transmission command

--- 107,114 -----
  .I subscriptions
  is the list of newsgroups to be transmitted to the system.  The
  .I flags
! are a set of keys describing how the article should be transmitted.
! The default is no flags.
  .LP
  The
  .I transmission command
diff -c -r 2.6/man/newsrc.5 2.7/man/newsrc.5
*** 2.6/man/newsrc.5	Tue Apr 20 10:48:05 1982
--- 2.7/man/newsrc.5	Sat Jun  5 20:08:19 1982
***************
*** 23,28
  .B fa.info-cpm: 1-7
  .br
  .B net.news: 1
  .LP
  An options line starts with the word
  .B options

--- 23,34 -----
  .B fa.info-cpm: 1-7
  .br
  .B net.news: 1
+ .br
+ .B fa.info-vax! 1-5
+ .br
+ .LP
+ If the : is replaced with an ! (as in info-vax above) the newsgroup
+ is not subscribed to and will not be shown to the user.
  .LP
  An options line starts with the word
  .B options
diff -c -r 2.6/man/postnews.1 2.7/man/postnews.1
*** 2.6/man/postnews.1	Tue Apr 20 10:45:51 1982
--- 2.7/man/postnews.1	Sat Jun  5 19:40:49 1982
***************
*** 3,13
  .SH NAME
  postnews \- submit news articles
  .SH SYNOPSIS
! .ll +5
! .B postnews
! [
! .I article
! ]
  .SH DESCRIPTION
  .I Postnews
  is a shell script that calls

--- 3,10 -----
  .SH NAME
  postnews \- submit news articles
  .SH SYNOPSIS
! .BR postnews " [ "
! .IR article " ]"
  .SH DESCRIPTION
  .I Postnews
  is a shell script that calls
***************
*** 11,17
  .SH DESCRIPTION
  .I Postnews
  is a shell script that calls
! .BR inews (1)
  to submit news articles to USENET.
  It will prompt the user for the title of the article
  (which should be a phrase suggesting the subject,

--- 8,14 -----
  .SH DESCRIPTION
  .I Postnews
  is a shell script that calls
! .IR inews (1)
  to submit news articles to USENET.
  It will prompt the user for the title of the article
  (which should be a phrase suggesting the subject,
***************
*** 20,26
  and for the newsgroup.
  An omitted newsgroup (from hitting return)
  will default to
! .BR general .
  .PP
  .B general
  is read by everyone on the local machine.

--- 17,23 -----
  and for the newsgroup.
  An omitted newsgroup (from hitting return)
  will default to
! .IR general .
  .PP
  .I general
  is read by everyone on the local machine.
***************
*** 22,28
  will default to
  .BR general .
  .PP
! .B general
  is read by everyone on the local machine.
  Other possible newsgroups include, but are not limited to,
  .BR btl.general ,

--- 19,25 -----
  will default to
  .IR general .
  .PP
! .I general
  is read by everyone on the local machine.
  Other possible newsgroups include, but are not limited to,
  .IR btl.general ,
***************
*** 25,31
  .B general
  is read by everyone on the local machine.
  Other possible newsgroups include, but are not limited to,
! .BR btl.general ,
  which is read by all users at all Bell Labs sites on USENET,
  .BR net.general ,
  which is read by all users at all sites on USENET,

--- 22,28 -----
  .I general
  is read by everyone on the local machine.
  Other possible newsgroups include, but are not limited to,
! .IR btl.general ,
  which is read by all users at all Bell Labs sites on USENET,
  .IR net.general ,
  which is read by all users at all sites on USENET,
***************
*** 27,33
  Other possible newsgroups include, but are not limited to,
  .BR btl.general ,
  which is read by all users at all Bell Labs sites on USENET,
! .BR net.general ,
  which is read by all users at all sites on USENET,
  and
  .BR net.news ,

--- 24,30 -----
  Other possible newsgroups include, but are not limited to,
  .IR btl.general ,
  which is read by all users at all Bell Labs sites  section lists the commands you can type to the msgs and /bin/mail

--- 135,143 -----
  a `%', as in the
  .B \-c
  option.  If no `%' is present, the article will be piped to the program.
! Paging may be disabled by setting
! .B PAGER
! to a null value.
  .SH "Commands"
  .PP
  This section lists the commands you can type to the msgs and /bin/mail
***************
*** 148,154
  Just hitting return is the same as typing the first command.
  For example, ``[ynq]'' means that the commands ``y'' (yes), ``n'' (no),
  and ``q'' (quit) are common responses, and that ``y'' is the default.
! .ta 1.5i
  Command		Meaning
  .IP y
  Yes.  Prints current article and goes on to next.

--- 146,152 -----
  Just hitting return is the same as typing the first command.
  For example, ``[ynq]'' means that the commands ``y'' (yes), ``n'' (no),
  and ``q'' (quit) are common responses, and that ``y'' is the default.
! .ta 2.5i
  Command		Meaning
  .IP y
  Yes.  Prints current article and goes on to next.
***************
*** 157,163
  In the /bin/mail interface, this means ``go on to the next article'',
  which will have the same effect as ``y'' or just hitting return.
  .IP q
! Quit.  The .newsrc 
  file will be updated if \-l or \-x were not on the command line.
  .IP c
  Cancel the article.

--- 155,161 -----
  In the /bin/mail interface, this means ``go on to the next article'',
  which will have the same effect as ``y'' or just hitting return.
  .IP q
! Quit.  The .newsrc
  file will be updated if \-l or \-x were not on the command line.
  .IP c
  Cancel the article.  Only the author or the super user can do this.
***************
*** 160,166
  Quit.  The .newsrc 
  file will be updated if \-l or \-x were not on the command line.
  .IP c
! Cancel the article.
  .IP r
  Reply.  Reply to article's author via mail.
  .IP "f [\fItitle\fP]"

--- 158,164 -----
  Quit.  The .newsrc
  file will be updated if \-l or \-x were not on the command line.
  .IP c
! Cancel the article.  Only the author or the super user can do this.
  .IP r
  Reply.  Reply to article's author via mail.
  .IP "f [\fItitle\fP]"
***************
*** 184,189
  Erase.  Forget that this article was read.
  .IP h
  Print verbose header.
  .IP !
  Shell escape.
  .IP \fInumber\fP

--- 182,192 -----
  Erase.  Forget that this article was read.
  .IP h
  Print verbose header.
+ .IP u
+ Unsubscribe from this newsgroup.
+ Also goes on to the next newsgroup.
+ .IP v
+ Print the current version of the news software.
  .IP !
  Shell escape.
  .IP \fInumber\fP
***************
*** 209,215
  .TP 10
  .B readnews
  Read all unread articles using the
! .I msgs(1)
  interface.  The
  .I .newsrc
  file is updated at the end of the session.

--- 212,218 -----
  .TP 10
  .B readnews
  Read all unread articles using the
! .IR msgs (1)
  interface.  The
  .I .newsrc
  file is updated at the end of the session.
***************
*** 216,222
  .TP 10
  .B readnews \-c ``ed %'' \-l
  Invoke the
! .I ed(1)
  text editor on a file containing the titles of all unread articles.  The
  .I .newsrc
  file is

--- 219,225 -----
  .TP 10
  .B readnews \-c ``ed %'' \-l
  Invoke the
! .IR ed (1)
  text editor on a file containing the titles of all unread articles.  The
  .I .newsrc
  file is
***************
*** 226,232
  .B readnews \-n all !fa.all \-M \-r
  Read all unread articles except articles whose newsgroups begin with
  "fa." via
! .I Mail(1)
  in reverse order.  The
  .I .newsrc
  file is updated at the end of the session.

--- 229,235 -----
  .B readnews \-n all !fa.all \-M \-r
  Read all unread articles except articles whose newsgroups begin with
  "fa." via
! .IR Mail (1)
  in reverse order.  The
  .I .newsrc
  file is updated at the end of the session.
***************
*** 245,253
  /usr/lib/news/active
  Active newsgroups
  .TP 25
- /usr/lib/news/sys
- System subscriptions
- .TP 25
  /usr/lib/news/help
  Help file for
  .I msgs(1)

--- 248,253 -----
  /usr/lib/news/active
  Active newsgroups
  .TP 25
  /usr/lib/news/help
  Help file for
  .IR msgs (1)
***************
*** 250,256
  .TP 25
  /usr/lib/news/help
  Help file for
! .I msgs(1)
  interface
  .TP 25
  ~/.newsrc

--- 250,256 -----
  .TP 25
  /usr/lib/news/help
  Help file for
! .IR msgs (1)
  interface
  .TP 25
  ~/.newsrc
***************
*** 265,271
  msgs(1),
  Mail(1),
  mail(1),
- getdate(3),
  news(5),
  newsrc(5)
  .SH AUTHORS

--- 265,270 -----
  msgs(1),
  Mail(1),
  mail(1),
  news(5),
  newsrc(5)
  .SH AUTHORS
Only in 2.7/man: recnews.8
Only in 2.7/misc: fa.recording
Only in 2.7/misc: net.recording
diff -c -r 2.6/misc/spool 2.7/misc/spool
*** 2.6/misc/spool	Tue Apr 20 10:30:04 1982
--- 2.7/misc/spool	Sun May 16 16:02:56 1982
***************
*** 43,49
  for sys in *
  do
  	cd $sys
! 	for file in *
  	do
  		uux -z -r - $sys!rnews < $file
  		rm -f $file

--- 43,49 -----
  for sys in *
  do
  	cd $sys
! 	for file in `ls -rt`
  	do
  		uux -z -r - $sys!rnews < $file
  		rm -f $file
Only in 2.7/misc: trimlib
diff -c -r 2.6/src/Makefile.usg 2.7/src/Makefile.usg
*** 2.6/src/Makefile.usg	Sun Apr 18 18:01:56 1982
--- 2.7/src/Makefile.usg	Tue Jun  1 08:25:37 1982
***************
*** 1,4
! # @(#) Makefile.usg	2.3	4/18/82
  
  # definitions
  SPOOLDIR = /usr/spool/news

--- 1,4 -----
! # @(#) Makefile.usg	2.4	6/1/82
  
  # definitions
  SPOOLDIR = /usr/spool/news
***************
*** 38,44
  
  clean:
  	rm -f $(COMMANDS) *.o
! 	rm -f core index all
  
  vgrind:
  	cp /dev/null index

--- 38,44 -----
  
  clean:
  	rm -f $(COMMANDS) *.o
! 	rm -f core index all errs getdate.c
  
  vgrind:
  	cp /dev/null index
diff -c -r 2.6/src/Makefile.v7 2.7/src/Makefile.v7
*** 2.6/src/Makefile.v7	Sun Apr 18 18:01:57 1982
--- 2.7/src/Makefile.v7	Tue Jun  1 08:25:36 1982
***************
*** 1,4
! # @(#) Makefile.v7	2.3	4/18/82
  
  # definitions
  SPOOLDIR = /usr/spool/news

--- 1,4 -----
! # @(#) Makefile.v7	2.4	6/1/82
  
  # definitions
  SPOOLDIR = /usr/spool/news
***************
*** 37,43
  
  clean:
  	rm -f $(COMMANDS) *.o
! 	rm -f core index
  
  vgrind:
  	cp /dev/null index

--- 37,43 -----
  
  clean:
  	rm -f $(COMMANDS) *.o
! 	rm -f core index errs getdate.c
  
  vgrind:
  	cp /dev/null index
diff -c -r 2.6/src/checknews.c 2.7/src/checknews.c
*** 2.6/src/checknews.c	Sun Apr  4 20:33:36 1982
--- 2.7/src/checknews.c	Tue Jun  1 08:25:12 1982
***************
*** 2,8
   * checknews - news checking program
   */
  
! static char *SccsId = "@(#) checknews.c	2.7	4/4/82";
  
  #include <stdio.h>
  #include <sys/types.h>

--- 2,8 -----
   * checknews - news checking program
   */
  
! static char *SccsId = "@(#) checknews.c	2.8	6/1/82";
  
  #include <stdio.h>
  #include <sys/types.h>
***************
*** 152,158
  #endif
  	sprintf(newsrc, "%s/%s", userhome, NEWSRC);
  	if ((rcfp = fopen(newsrc, "r")) != NULL) {
! 		while (fgets(rcbuf, BUFSIZ, rcfp) != NULL) {
  			if (!(space = isspace(*rcbuf)))
  				optflag = FALSE;
  			if (!strncmp(rcbuf, "options ", 8))

--- 152,158 -----
  #endif
  	sprintf(newsrc, "%s/%s", userhome, NEWSRC);
  	if ((rcfp = fopen(newsrc, "r")) != NULL) {
! 		while (fgets(rcbuf, LBUFLEN, rcfp) != NULL) {
  			if (!(space = isspace(*rcbuf)))
  				optflag = FALSE;
  			if (!strncmp(rcbuf, "options ", 8))
***************
*** 218,224
  	}
  	if ((rcfp = fopen(newsrc, "r")) == NULL)
  		xerror("Cannot open .newsrc file");
! 	while (fgets(rcbuf, BUFSIZ, rcfp) != NULL) {
  		if (!nstrip(rcbuf))
  			xerror(".newsrc line too long");
  		if (++line >= LINES)

--- 218,224 -----
  	}
  	if ((rcfp = fopen(newsrc, "r")) == NULL)
  		xerror("Cannot open .newsrc file");
! 	while (fgets(rcbuf, LBUFLEN, rcfp) != NULL) {
  		if (!nstrip(rcbuf))
  			xerror(".newsrc line too long");
  		if (++line >= LINES)
***************
*** 243,248
  	register int i;
  	register char *ptr;
  	int l;
  
  #ifdef DEBUG
  	fprintf(stderr, "nchk()\n");

--- 243,249 -----
  	register int i;
  	register char *ptr;
  	int l;
+ 	char saveptr;
  
  #ifdef DEBUG
  	fprintf(stderr, "nchk()\n");
***************
*** 263,269
  		for (i = 0; i <= line; i++) {
  			strcpy(rcbuf, rcline[i]);
  			ptr = rcbuf;
! 			while (*ptr != ':' && *ptr)
  				ptr++;
  			if (*ptr) {
  				*ptr = '\0';

--- 264,270 -----
  		for (i = 0; i <= line; i++) {
  			strcpy(rcbuf, rcline[i]);
  			ptr = rcbuf;
! 			while (*ptr != ':' && *ptr != '!' && *ptr)
  				ptr++;
  			if (*ptr) {
  				saveptr = *ptr;
***************
*** 266,271
  			while (*ptr != ':' && *ptr)
  				ptr++;
  			if (*ptr) {
  				*ptr = '\0';
  				if (!strcmp(rcbuf, bfr)) {
  					strcpy(rcbuf, ++ptr);

--- 267,273 -----
  			while (*ptr != ':' && *ptr != '!' && *ptr)
  				ptr++;
  			if (*ptr) {
+ 				saveptr = *ptr;
  				*ptr = '\0';
  				if (!strcmp(rcbuf, bfr)) {
  					if (saveptr == '!')
***************
*** 268,273
  			if (*ptr) {
  				*ptr = '\0';
  				if (!strcmp(rcbuf, bfr)) {
  					strcpy(rcbuf, ++ptr);
  					goto skip;
  				}

--- 270,277 -----
  				saveptr = *ptr;
  				*ptr = '\0';
  				if (!strcmp(rcbuf, bfr)) {
+ 					if (saveptr == '!')
+ 						goto contin;
  					strcpy(rcbuf, ++ptr);
  					goto skip;
  				}
***************
*** 304,309
  			}
  			yep(argv);
  		}
  	}
  	if (n)
  		printf("No news is good news.\n");

--- 308,314 -----
  			}
  			yep(argv);
  		}
+ contin:;
  	}
  	if (n)
  		printf("No news is good news.\n");
diff -c -r 2.6/src/control.c 2.7/src/control.c
*** 2.6/src/control.c	Sun Apr 18 18:02:01 1982
--- 2.7/src/control.c	Sat Jun  5 19:43:40 1982
***************
*** 1,6
  /*
   * Control message handling code.  Deal with messages which are to be
   * acted on by netnews itself rather than by people.
   */
  
  static char *SccsId = "@(#) control.c	2.6	4/18/82";

--- 1,8 -----
  /*
   * Control message handling code.  Deal with messages which are to be
   * acted on by netnews itself rather than by people.
+  *
+  * See defs.h "news_version" for the real version of netnews.
   */
  
  static char *SccsId = "@(#) control.c	2.8	6/5/82 (this is NOT the netnews version!)";
***************
*** 3,9
   * acted on by netnews itself rather than by people.
   */
  
! static char *SccsId = "@(#) control.c	2.6	4/18/82";
  
  #include "iparams.h"
  

--- 5,11 -----
   * See defs.h "news_version" for the real version of netnews.
   */
  
! static char *SccsId = "@(#) control.c	2.8	6/5/82 (this is NOT the netnews version!)";
  
  #include "iparams.h"
  
***************
*** 51,56
  		c_sendsys(cargc, cargv);
  	else if (eq("senduuname"))
  		c_senduuname(cargc, cargv);
  	else
  		c_unknown(h, ctlmsgtext);
  }

--- 53,60 -----
  		c_sendsys(cargc, cargv);
  	else if (eq("senduuname"))
  		c_senduuname(cargc, cargv);
+ 	else if (eq("version"))
+ 		c_version(cargc, cargv);
  	else
  		c_unknown(h, ctlmsgtext);
  }
***************
*** 213,219
  
  	groupname = argv[1];
  	verifyname(groupname);
! 	if (groupname[0] == '.')
  		xerror("Illegal group name in rmgroup");
  	sprintf(groupdir, "%s/%s", SPOOL, groupname);
  	if (access(groupdir, 0)) {

--- 217,223 -----
  
  	groupname = argv[1];
  	verifyname(groupname);
! 	if (groupname[0] == '.' || groupname[0] <= ' ')
  		xerror("Illegal group name in rmgroup");
  	sprintf(groupdir, "%s/%s", SPOOL, groupname);
  	if (access(groupdir, 0)) {
***************
*** 244,250
  c_cancel(argc, argv)
  char **argv;
  {
! 	char *line, *p, *q, *r, *s;
  	char *findhist();
  	register FILE *fp;
  	char whatsisname[150];

--- 248,254 -----
  c_cancel(argc, argv)
  char **argv;
  {
! 	char *line, *p, *q, *r, *s, *rr, *ss;
  	char *findhist();
  	register FILE *fp;
  	char whatsisname[150];
***************
*** 257,263
  	line = findhist(argv[1]);
  	if (line)
  		log("Cancelling %s", line);
! 	else
  		log("Can't cancel %s:  non-existent", argv[1]);
  
  	p = index(line, '\t');

--- 261,267 -----
  	line = findhist(argv[1]);
  	if (line)
  		log("Cancelling %s", line);
! 	else {
  		log("Can't cancel %s:  non-existent", argv[1]);
  		return;
  	}
***************
*** 259,264
  		log("Cancelling %s", line);
  	else
  		log("Can't cancel %s:  non-existent", argv[1]);
  
  	p = index(line, '\t');
  	p = index(p+1, '\t');

--- 263,270 -----
  		log("Cancelling %s", line);
  	else {
  		log("Can't cancel %s:  non-existent", argv[1]);
+ 		return;
+ 	}
  
  	p = index(line, '\t');
  	p = index(p+1, '\t');
***************
*** 284,289
  			if (r > header.path)
  				r++;
  		}
  		s = rindex(whatsisname, '!');
  		if (s == 0)
  			s = whatsisname;

--- 290,298 -----
  			if (r > header.path)
  				r++;
  		}
+ 		rr = index(r, ' ');
+ 		if (rr)
+ 			*rr = 0;
  		s = rindex(whatsisname, '!');
  		if (s == 0)
  			s = whatsisname;
***************
*** 293,298
  			if (s > whatsisname)
  				s++;
  		}
  		if (!su && strcmp(r, s)) {
  			sprintf(msgbuf, "Not contributor: %s and %s", header.path, whatsisname);
  			xerror(msgbuf);

--- 302,310 -----
  			if (s > whatsisname)
  				s++;
  		}
+ 		ss = index(s, ' ');
+ 		if (ss)
+ 			*ss = 0;
  		if (!su && strcmp(r, s)) {
  			sprintf(msgbuf, "Not contributor: %s and %s", header.path, whatsisname);
  			xerror(msgbuf);
***************
*** 388,393
  }
  
  /*
   * An unknown control message has been received.
   */
  c_unknown(h, ctlmsgtext)

--- 400,424 -----
  }
  
  /*
+  * Send the version number to the right person.
+  */
+ c_version(h, ctlmsgtext)
+ struct hbuf *h;
+ char *ctlmsgtext;
+ {
+ 	FILE *f;
+ 
+ 	f = mailhdr(h->path, "Our news version");
+ 	if (f == NULL)
+ 		xerror("Cannot send back error message");
+ 	fprintf(f, "Sent-by: USENET Site %s\n\n", SYSNAME);
+ 	fprintf(f, "Currently running news B version %s.\n\n", news_version);
+ 	fprintf(f, "The header of the message follows:\n");
+ 	hwrite(h, f);
+ 	mclose(f);
+ }
+ 
+ /*
   * An unknown control message has been received.
   */
  c_unknown(h, ctlmsgtext)
***************
*** 401,407
  	if (f == NULL)
  		xerror("Cannot send back error message");
  	fprintf(f, "Sent-by: USENET Site %s\n\n", SYSNAME);
! 	fprintf(f, "Currently running news B version %s.\n\n", SccsId);
  	fprintf(f, "The header of the message follows:\n");
  	hwrite(h, f);
  	mclose(f);

--- 432,438 -----
  	if (f == NULL)
  		xerror("Cannot send back error message");
  	fprintf(f, "Sent-by: USENET Site %s\n\n", SYSNAME);
! 	fprintf(f, "Currently running news B version %s.\n\n", news_version);
  	fprintf(f, "The header of the message follows:\n");
  	hwrite(h, f);
  	mclose(f);
***************
*** 417,423
  	if (f == NULL)
  		xerror("Cannot send back error message");
  	fprintf(f, "Sent-by: USENET Site %s\n\n", SYSNAME);
! 	fprintf(f, "Currently running news B version %s.\n\n", SccsId);
  	fprintf(f, "The header of the message follows:\n");
  	hwrite(&header, f);
  	mclose(f);

--- 448,454 -----
  	if (f == NULL)
  		xerror("Cannot send back error message");
  	fprintf(f, "Sent-by: USENET Site %s\n\n", SYSNAME);
! 	fprintf(f, "Currently running news B version %s.\n\n", news_version);
  	fprintf(f, "The header of the message follows:\n");
  	hwrite(&header, f);
  	mclose(f);
***************
*** 626,631
  	/* Be sure we DO allow alphabetics, !, :, ., -, @. *. */
  	char *nasty = "\"'\\`^|;& <>/~";
  
  	while (*nasty) {
  		if (index(sendto, *nasty++)) {
  			log("nasty mail name %s from %s", sendto, header.path);

--- 657,666 -----
  	/* Be sure we DO allow alphabetics, !, :, ., -, @. *. */
  	char *nasty = "\"'\\`^|;& <>/~";
  
+ 	if (sendto[0] <= ' ') {
+ 		log("nasty mail name %s from %s", sendto, header.path);
+ 		xxit(1);
+ 	}
  	while (*nasty) {
  		if (index(sendto, *nasty++)) {
  			log("nasty mail name %s from %s", sendto, header.path);
diff -c -r 2.6/src/defs.h 2.7/src/defs.h
*** 2.6/src/defs.h	Sun Apr 18 18:02:04 1982
--- 2.7/src/defs.h	Mon Jun  7 19:14:09 1982
***************
*** 7,13
   * If TMAIL is undefined, the -M option will be disabled.
   *
   * By convention, the version of the software you are running is taken
!  * to be the version of control.c.
   */
  
  static char *Defs = "@(#) defs.h	2.6	4/18/82";

--- 7,13 -----
   * If TMAIL is undefined, the -M option will be disabled.
   *
   * By convention, the version of the software you are running is taken
!  * to be news_version below.
   */
  
  static char *news_version = "@(#) defs.h	2.7	6/7/82";
***************
*** 10,16
   * to be the version of control.c.
   */
  
! static char *Defs = "@(#) defs.h	2.6	4/18/82";
  
  #define DAYS	(60L*60L*24L)
  #define WEEKS	(7*DAYS)

--- 10,16 -----
   * to be news_version below.
   */
  
! static char *news_version = "@(#) defs.h	2.7	6/7/82";
  
  #define DAYS	(60L*60L*24L)
  #define WEEKS	(7*DAYS)
***************
*** 25,31
  #define RNEWS	"/usr/bin/rnews"	/* rnews for uurec to fork	*/
  				/* If you change rnews, see Makefile too*/
  #define NOTIFY	"usenet"	/* Tell him about certain ctl messages	*/
! #define UUXZ			/* insert if your uux supports -z	*/
  /* #define UUNAME "euuname"	/* omit for uuname, put in LIBDIR	*/
  /* #define MANUALLY		/* Don't execute rmgroups, just notify.	*/
  /* #define BERKNAME "ARPAVAX"	/* name of local host on Berknet	*/

--- 25,32 -----
  #define RNEWS	"/usr/bin/rnews"	/* rnews for uurec to fork	*/
  				/* If you change rnews, see Makefile too*/
  #define NOTIFY	"usenet"	/* Tell him about certain ctl messages	*/
! 				/* Default xmit command - remove -z if	*/
! #define DFTXMIT	"uux - -z -r %s\\!rnews < %s" /* your uux can't do it	*/
  /* #define UUNAME "euuname"	/* omit for uuname, put in LIBDIR	*/
  /* #define MANUALLY		/* Don't execute rmgroups, just notify.	*/
  /* #define BERKNAME "ARPAVAX"	/* name of local host on Berknet	*/
diff -c -r 2.6/src/expire.c 2.7/src/expire.c
*** 2.6/src/expire.c	Tue Apr 20 10:36:27 1982
--- 2.7/src/expire.c	Tue Jun  1 08:25:38 1982
***************
*** 3,9
   *		 have expired.
   */
  
! static char *SccsId = "@(#) expire.c	2.8	4/20/82";
  
  #include "params.h"
  

--- 3,9 -----
   *		 have expired.
   */
  
! static char *SccsId = "@(#) expire.c	2.9	6/1/82";
  
  #include "params.h"
  
***************
*** 12,18
  extern char	*SPOOL;
  extern char	*CAND;
  char	ARTFILE[BUFSIZ], NARTFILE[BUFSIZ], OARTFILE[BUFSIZ];
! char	filename[BUFSIZ];
  char	*OLDNEWS = "/usr/spool/oldnews";
  int	verbose = 0;
  int	ignorexp = 0;

--- 12,18 -----
  extern char	*SPOOL;
  extern char	*CAND;
  char	ARTFILE[BUFSIZ], NARTFILE[BUFSIZ], OARTFILE[BUFSIZ];
! extern char	filename[];
  char	*OLDNEWS = "/usr/spool/oldnews";
  int	verbose = 0;
  int	ignorexp = 0;
***************
*** 18,23
  int	ignorexp = 0;
  long	expincr;
  long	atol();
  
  main(argc, argv)
  int argc;

--- 18,24 -----
  int	ignorexp = 0;
  long	expincr;
  long	atol();
+ time_t	cgtdate(), time();
  
  main(argc, argv)
  int argc;
***************
*** 61,67
  			if (argc > 2) {
  				argv++;
  				argc--;
! 				while (argv[1][0] != '-' && argc) {
  					strcat(ngpat, argv[1]);
  					ngcat(ngpat);
  					argv++;

--- 62,68 -----
  			if (argc > 2) {
  				argv++;
  				argc--;
! 				while (argc > 1 && argv[1][0] != '-') {
  					strcat(ngpat, argv[1]);
  					ngcat(ngpat);
  					argv++;
***************
*** 80,86
  	if (ngpat[0] == 0)
  		strcpy(ngpat, "all,");
  	now = time(0);
- 	newtime = now + expincr;
  	if (chdir(SPOOL))
  		xerror("Cannot chdir %s", SPOOL);
  

--- 81,86 -----
  	if (ngpat[0] == 0)
  		strcpy(ngpat, "all,");
  	now = time(0);
  	if (chdir(SPOOL))
  		xerror("Cannot chdir %s", SPOOL);
  
***************
*** 91,97
  	nhfd = xfopen(NARTFILE, "w");
  
  	while (fgets(afline, BUFLEN, ohfd) != NULL) {
! 		if (verbose > 1)
  			printf("article: %s", afline);
  		p1 = index(afline, '\t');
  		if (p1)

--- 91,97 -----
  	nhfd = xfopen(NARTFILE, "w");
  
  	while (fgets(afline, BUFLEN, ohfd) != NULL) {
! 		if (verbose > 2)
  			printf("article: %s", afline);
  		p1 = index(afline, '\t');
  		if (p1)
***************
*** 107,114
  			*p1 = 0;
  		else
  			continue;
- 		if (verbose > 1)
- 			printf("newsgroup %s\n", groupdir);
  		ngcat(groupdir);
  		if (!ngmatch(groupdir, ngpat)) {
  			fputs(afline, nhfd);

--- 107,112 -----
  			*p1 = 0;
  		else
  			continue;
  		ngcat(groupdir);
  		if (!ngmatch(groupdir, ngpat)) {
  			fputs(afline, nhfd);
***************
*** 132,138
  			fclose(fp);
  			continue;
  		}
! 		h.exptime = cgtdate(h.expdate);
  		if (!h.expdate[0] || ignorexp==2 ||
  		    (ignorexp==1 && newtime < h.exptime))
  			h.exptime = newtime;

--- 130,138 -----
  			fclose(fp);
  			continue;
  		}
! 		if (h.expdate[0])
! 			h.exptime = cgtdate(h.expdate);
! 		newtime = cgtdate(h.recdate) + expincr;
  		if (!h.expdate[0] || ignorexp==2 ||
  		    (ignorexp==1 && newtime < h.exptime))
  			h.exptime = newtime;
***************
*** 167,173
  	int last = 0;
  	char newname[BUFLEN];
  
! 	while (*artlist == ' ' || *artlist == '\n')
  		artlist++;
  	if (*artlist == 0)
  		return;

--- 167,173 -----
  	int last = 0;
  	char newname[BUFLEN];
  
! 	while (*artlist == ' ' || *artlist == '\n' || *artlist == ',')
  		artlist++;
  	if (*artlist == 0)
  		return;
***************
*** 178,183
  	}
  	if (p == 0) {
  		last = 1;
  		unlink(artlist);
  		return;
  	}

--- 178,187 -----
  	}
  	if (p == 0) {
  		last = 1;
+ 		p = index(artlist, ',');
+ 	}
+ 	if (p == 0) {
+ 		last = 1;
  		unlink(artlist);
  		return;
  	}
***************
*** 185,191
  		*p = 0;
  	if (access(OLDNEWS, 0) == 0) {
  		sprintf(newname, "%s/%s", OLDNEWS, artlist);
! 		printf("link %s to %s\n", newname, filename);
  		if (link(artlist, newname) == -1) {
  			if (mkdir(groupdir) == 0)
  				link(artlist, newname);

--- 189,196 -----
  		*p = 0;
  	if (access(OLDNEWS, 0) == 0) {
  		sprintf(newname, "%s/%s", OLDNEWS, artlist);
! 		if (verbose > 1)
! 			printf("link %s to %s\n", newname, filename);
  		if (link(artlist, newname) == -1) {
  			if (mkdir(groupdir) == 0)
  				link(artlist, newname);
diff -c -r 2.6/src/funcs.c 2.7/src/funcs.c
*** 2.6/src/funcs.c	Sat Apr  3 11:53:24 1982
--- 2.7/src/funcs.c	Tue Jun  1 08:25:15 1982
***************
*** 2,8
   * funcs - functions used by both inews and readnews.
   */
  
! static char *SccsId = "@(#) funcs.c	2.4	4/3/82";
  
  #include "params.h"
  

--- 2,8 -----
   * funcs - functions used by both inews and readnews.
   */
  
! static char *SccsId = "@(#) funcs.c	2.5	6/1/82";
  
  #include "params.h"
  
***************
*** 39,91
  }
  
  /*
-  * Check if header.nbuf contains only valid newsgroup names;
-  * exit with error if not valid.
-  *
-  * a == TRUE means header.nbuf is subscription list
-  * a == FALSE means header.nbuf is newsgroup list
-  */
- 
- ngfcheck(a)
- int a;
- {
- 	char ngcheck[NGFSIZ];	/* Hold NGFILE newsgroups */
- 	char tbuf[BUFLEN];	/* hold single header.nbuf news group */
- 	register char *s1, *s2;
- 	register FILE *f;
- 
- 	s1 = ngcheck;
- 	f = xfopen(NGFILE, "r");
- 	while (fgets(bfr, BUFLEN, f) != NULL) {
- 		for (s2 = bfr; *s2 != '\0' &&
- 		    *s2 != ' ' && *s2 != '\t' &&
- 		    *s2 != ':' && *s2 != '\n';) {
- 			if (s1 >= &ngcheck[NGFSIZ-2])
- 				xerror("NGFILE too long");
- 			*s1++ = *s2++;
- 		}
- 		*s1++ = NGDELIM;
- 	}
- 	*s1 = '\0';
- 	fclose(f);
- 	for (s1 = header.nbuf; *s1 != '\0';) {
- 		if (*s1 == NEGCHAR)
- 			s1++;
- 		s2 = tbuf;
- 		while ((*s2++ = *s1++) != NGDELIM)
- 			if (s1[-1] == ':')
- 				xerror("Newsgroup cannot contain ':'");
- 		*s2 = '\0';
- 		s2 = tbuf;
- 		if (!ngmatch(s2, ngcheck) && (!a || !ngmatch(ngcheck, s2))) {
- 			ngdel(s2);
- 			sprintf(bfr, "Bad news group \"%s\"", s2);
- 			xerror(bfr);
- 		}
- 	}
- }
- 
- /*
   * News group matching.
   *
   * nglist is a list of newsgroups.

--- 39,44 -----
  }
  
  /*
   * News group matching.
   *
   * nglist is a list of newsgroups.
***************
*** 370,376
  
  again:
  	p = bfr;
! 	if (fgets(p, BUFLEN, sysfile) == NULL)
  		return(FALSE);
  	if (!nstrip(p))
  		xerror("SUBFILE line too long.");

--- 323,329 -----
  
  again:
  	p = bfr;
! 	if (fgets(p, LBUFLEN, sysfile) == NULL)
  		return(FALSE);
  	if (!nstrip(p))
  		xerror("SUBFILE line too long.");
***************
*** 484,487
  {
  	ngdel(strcpy(bfr, hp->nbuf));
  	fprintf(fp, "A%s\n%s\n%s!%s\n%s\n%s\n", hp->ident, bfr, SYSNAME, hp->path, hp->subdate, hp->title);
  }

--- 437,491 -----
  {
  	ngdel(strcpy(bfr, hp->nbuf));
  	fprintf(fp, "A%s\n%s\n%s!%s\n%s\n%s\n", hp->ident, bfr, SYSNAME, hp->path, hp->subdate, hp->title);
+ }
+ 
+ static int hascaught = 0;
+ static catchintr()
+ {
+ 	hascaught = 1;
+ 	printf("\n");
+ 	fflush(stdout);
+ }
+ 
+ /*
+  * Print a recorded message warning the poor luser what he is doing
+  * and demand that he understands it before proceeding.  Only do
+  * this for newsgroups listed in LIBDIR/recording.
+  */
+ recording(ngrps)
+ char *ngrps;
+ {
+ 	char recbuf[100];
+ 	FILE *fd;
+ 	char nglist[100], fname[100];
+ 	char lngrps[100];
+ 	char *oldsig;
+ 	int  c, n, yes;
+ 
+ 	sprintf(recbuf, "%s/%s", LIB, "recording");
+ 	fd = fopen(recbuf, "r");
+ 	if (fd == NULL)
+ 		return 0;
+ 	strcpy(lngrps, ngrps);
+ 	ngcat(lngrps);
+ 	while ((fgets(recbuf, sizeof recbuf, fd)) != NULL) {
+ 		sscanf(recbuf, "%s %s", nglist, fname);
+ 		ngcat(nglist);
+ 		if (ngmatch(lngrps, nglist)) {
+ 			fclose(fd);
+ 			fd = fopen(fname, "r");
+ 			while ((c = getc(fd)) != EOF)
+ 				putc(c, stderr);
+ 			hascaught = 0;
+ 			oldsig = (char *) signal(SIGINT, catchintr);
+ 			fprintf(stderr, "Do you understand this?  Hit <return> to proceed, <DEL> to abort: ");
+ 			n = read(2, recbuf, 100);
+ 			c = recbuf[0];
+ 			yes = (c=='y' || c=='Y' || c=='\n' || c=='\n' || c==0);
+ 			signal(SIGINT, oldsig);
+ 			if (hascaught || n <= 0 || !yes)
+ 				return -1;
+ 		}
+ 	}
+ 	return 0;
  }
diff -c -r 2.6/src/header.c 2.7/src/header.c
*** 2.6/src/header.c	Sun Apr 18 18:02:11 1982
--- 2.7/src/header.c	Sat Jun  5 21:44:17 1982
***************
*** 2,8
   * header.c - header functions plus some other goodies
   */
  
! static char *SccsId = "@(#) header.c	2.6	4/18/82";
  
  #include <stdio.h>
  #include <sys/types.h>

--- 2,8 -----
   * header.c - header functions plus some other goodies
   */
  
! static char *SccsId = "@(#) header.c	2.9	6/5/82";
  
  #include <stdio.h>
  #include <sys/types.h>
***************
*** 24,30
  	register int len;
  
  	bclear((char *) hp, sizeof (*hp));
! 	if (((fgets(bfr, BUFLEN, fp) != NULL && *bfr >= 'A' && *bfr <= 'Z') && index(bfr, ':')) || !strncmp(bfr, "From ", 5))
  		if (frmread(fp, hp))
  				goto strip;
  	if (*bfr != PROTO)

--- 24,32 -----
  	register int len;
  
  	bclear((char *) hp, sizeof (*hp));
! 	if (((fgets(bfr, PATHLEN, fp) != NULL &&
! 		*bfr >= 'A' && *bfr <= 'Z') && index(bfr, ':')) ||
! 		!strncmp(bfr, "From ", 5))
  		if (frmread(fp, hp))
  				goto strip;
  	if (*bfr != PROTO)
***************
*** 32,38
  	strncpy(hp->ident, &(bfr[1]), NAMELEN);	/* file name */
  	if (!nstrip(hp->ident))
  		return(NULL);
! 	fgets(hp->nbuf, BUFLEN, fp);	/* newsgroup list */
  	if (!nstrip(hp->nbuf))
  		return(NULL);
  	ngcat(hp->nbuf);

--- 34,40 -----
  	strncpy(hp->ident, &(bfr[1]), NAMELEN);	/* file name */
  	if (!nstrip(hp->ident))
  		return(NULL);
! 	fgets(hp->nbuf, BUFLEN, fp);		/* newsgroup list */
  	if (!nstrip(hp->nbuf))
  		return(NULL);
  	ngcat(hp->nbuf);
***************
*** 36,42
  	if (!nstrip(hp->nbuf))
  		return(NULL);
  	ngcat(hp->nbuf);
! 	fgets(hp->path, BUFLEN, fp);	/* source path */
  	if (!nstrip(hp->path))
  		return(NULL);
  	fgets(hp->subdate, DATELEN, fp);	/* date */

--- 38,44 -----
  	if (!nstrip(hp->nbuf))
  		return(NULL);
  	ngcat(hp->nbuf);
! 	fgets(hp->path, BUFLEN, fp);		/* source path */
  	if (!nstrip(hp->path))
  		return(NULL);
  	fgets(hp->subdate, DATELEN, fp);	/* date */
***************
*** 42,48
  	fgets(hp->subdate, DATELEN, fp);	/* date */
  	if (!nstrip(hp->subdate))
  		return(NULL);
! 	fgets(hp->title, BUFLEN, fp);	/* title */
  	if (!nstrip(hp->title))
  		return(NULL);
  strip:	/* strip off sys! from front of path. */

--- 44,50 -----
  	fgets(hp->subdate, DATELEN, fp);	/* date */
  	if (!nstrip(hp->subdate))
  		return(NULL);
! 	fgets(hp->title, BUFLEN, fp);		/* title */
  	if (!nstrip(hp->title))
  		return(NULL);
  strip:	/* strip off sys! from front of path. */
***************
*** 78,83
  	int titleflag = FALSE, fileflag = FALSE, recflag = FALSE, i;
  	int exprflag = FALSE, replyflag = FALSE, followflag = FALSE;
  	int ctlflag = FALSE;
  	long curpos;
  	char wordfrom[100], uname[100], at[100], site[100];
  

--- 80,86 -----
  	int titleflag = FALSE, fileflag = FALSE, recflag = FALSE, i;
  	int exprflag = FALSE, replyflag = FALSE, followflag = FALSE;
  	int ctlflag = FALSE;
+ 	int unreccnt = 0;
  	long curpos;
  	char wordfrom[100], uname[100], at[100], site[100];
  
***************
*** 83,89
  
  	i = type(bfr);
  	do {
! 			curpos = ftell(fp);
  		switch (i) {
  			case FROM:
  				if (!fromflag) {

--- 86,92 -----
  
  	i = type(bfr);
  	do {
! 		curpos = ftell(fp);
  		switch (i) {
  			case FROM:
  				if (!fromflag) {
***************
*** 87,93
  		switch (i) {
  			case FROM:
  				if (!fromflag) {
! 					sscanf(bfr, "%s %s %s %s", wordfrom, uname, at, site);
  					if (isat(at))
  						sprintf(hp->path, "%s@%s", uname, site);
  					else

--- 90,104 -----
  		switch (i) {
  			case FROM:
  				if (!fromflag) {
! #ifdef ATSIGN
! 				/*
! 				 * This old code understood the "user at site"
! 				 * notation but threw away all but the first
! 				 * word of names (like your full name) so has
! 				 * been taken out.
! 				 */
! 					sscanf(bfr, "%s %s %s %s",
! 						wordfrom, uname, at, site);
  					if (isat(at))
  						sprintf(hp->path, "%s@%s",
  							uname, site);
***************
*** 89,95
  				if (!fromflag) {
  					sscanf(bfr, "%s %s %s %s", wordfrom, uname, at, site);
  					if (isat(at))
! 						sprintf(hp->path, "%s@%s", uname, site);
  					else
  						strcpy(hp->path, uname);
  					fromflag = TRUE;

--- 100,107 -----
  					sscanf(bfr, "%s %s %s %s",
  						wordfrom, uname, at, site);
  					if (isat(at))
! 						sprintf(hp->path, "%s@%s",
! 							uname, site);
  					else
  						strcpy(hp->path, uname);
  #else
***************
*** 92,97
  						sprintf(hp->path, "%s@%s", uname, site);
  					else
  						strcpy(hp->path, uname);
  					fromflag = TRUE;
  				}
  				break;

--- 104,112 -----
  							uname, site);
  					else
  						strcpy(hp->path, uname);
+ #else
+ 					getfield(&fromflag, hp->path);
+ #endif
  					fromflag = TRUE;
  				}
  				break;
***************
*** 132,137
  					getfield(&ctlflag, hp->ctlmsg);
  				break;
  			case OTHER:
  				break;
  		}
  	} while ((i=type(fgets(bfr, BUFLEN, fp))) > 0);

--- 147,156 -----
  					getfield(&ctlflag, hp->ctlmsg);
  				break;
  			case OTHER:
+ 				if (unreccnt < NUNREC) {
+ 					strcpy(&hp->unrec[unreccnt][0], bfr);
+ 					unreccnt++;
+ 				}
  				break;
  		}
  	} while ((i=type(fgets(bfr, BUFLEN, fp))) > 0);
***************
*** 196,202
  		return REPLYTO;
  	if (!strncmp(ptr, "References: ", 12))
  		return FOLLOWID;
! 	if (!strncmp(ptr, "Control: ", 12))
  		return CONTROL;
  	return OTHER;
  }

--- 215,221 -----
  		return REPLYTO;
  	if (!strncmp(ptr, "References: ", 12))
  		return FOLLOWID;
! 	if (!strncmp(ptr, "Control: ", 9))
  		return CONTROL;
  	return OTHER;
  }
***************
*** 231,236
  register FILE *fp;
  int wr;
  {
  	ngdel(strcpy(bfr, hp->nbuf));
  	if (wr == 2)
  		fprintf(fp, "From: %s\nNewsgroups: %s\n", hp->path, bfr);

--- 250,257 -----
  register FILE *fp;
  int wr;
  {
+ 	int iu;
+ 
  	ngdel(strcpy(bfr, hp->nbuf));
  	if (wr == 2)
  		fprintf(fp, "From: %s\nNewsgroups: %s\n", hp->path, bfr);
***************
*** 248,253
  		fprintf(fp, "References: %s\n", hp->followid); 
  	if (*hp->ctlmsg)
  		fprintf(fp, "Control: %s\n", hp->ctlmsg);
  	putc('\n', fp);
  }
  

--- 269,278 -----
  		fprintf(fp, "References: %s\n", hp->followid); 
  	if (*hp->ctlmsg)
  		fprintf(fp, "Control: %s\n", hp->ctlmsg);
+ 	for (iu=0; iu<NUNREC; iu++) {
+ 		if (hp->unrec[iu][0])
+ 			fprintf(fp, "%s", &hp->unrec[iu][0]);
+ 	}
  	putc('\n', fp);
  }
  
diff -c -r 2.6/src/header.h 2.7/src/header.h
*** 2.6/src/header.h	Sun Apr 18 18:02:13 1982
--- 2.7/src/header.h	Sat Jun  5 19:54:17 1982
***************
*** 2,8
   * header.h - Article header format
   */
  
! static char *Header = "@(#) header.h	2.4	4/18/82";
  
  /* article header */
  struct	hbuf {

--- 2,8 -----
   * header.h - Article header format
   */
  
! static char *Header = "@(#) header.h	2.5	6/5/82";
  
  #define NUNREC 10
  
***************
*** 4,9
  
  static char *Header = "@(#) header.h	2.4	4/18/82";
  
  /* article header */
  struct	hbuf {
  	char	path[PATHLEN];		/* source string	*/

--- 4,11 -----
  
  static char *Header = "@(#) header.h	2.5	6/5/82";
  
+ #define NUNREC 10
+ 
  /* article header */
  struct	hbuf {
  	char	path[PATHLEN];		/* source string	*/
***************
*** 19,22
  	char	expdate[DATELEN];	/* expiration date	*/
  	time_t	exptime;		/* expdate in secs	*/
  	char	ctlmsg[PATHLEN];	/* control message	*/
  };

--- 21,25 -----
  	char	expdate[DATELEN];	/* expiration date	*/
  	time_t	exptime;		/* expdate in secs	*/
  	char	ctlmsg[PATHLEN];	/* control message	*/
+ 	char	unrec[NUNREC][BUFLEN];	/* unrecognized lines	*/
  };
diff -c -r 2.6/src/iextern.c 2.7/src/iextern.c
*** 2.6/src/iextern.c	Mon Mar 22 20:23:16 1982
--- 2.7/src/iextern.c	Tue Jun  1 08:25:17 1982
***************
*** 2,8
   * iextern - external definitions for inews.
   */
  
! static char *SccsId = "@(#) iextern.c	2.1	2/23/82";
  
  #include "iparams.h"
  

--- 2,8 -----
   * iextern - external definitions for inews.
   */
  
! static char *SccsId = "@(#) iextern.c	2.2	6/1/82";
  
  #include "iparams.h"
  
***************
*** 36,42
  int	mode;				/* mode of news program */
  int	lockcount = 0;			/* no. of times we've called lock */
  struct hbuf header;			/* general-use header structure */
! char	bfr[BUFLEN];			/* general-use scratch area */
  char	filename[NAMELEN];		/* general-use file name */
  char	username[BUFLEN];		/* user's login name */
  char	userhome[BUFLEN];		/* user's home directory */

--- 36,42 -----
  int	mode;				/* mode of news program */
  int	lockcount = 0;			/* no. of times we've called lock */
  struct hbuf header;			/* general-use header structure */
! char	bfr[LBUFLEN];			/* general-use scratch area */
  char	filename[NAMELEN];		/* general-use file name */
  char	username[BUFLEN];		/* user's login name */
  char	userhome[BUFLEN];		/* user's home directory */
diff -c -r 2.6/src/ifuncs.c 2.7/src/ifuncs.c
*** 2.6/src/ifuncs.c	Mon Apr 19 19:50:09 1982
--- 2.7/src/ifuncs.c	Tue Jun  8 08:35:08 1982
***************
*** 2,8
   * ifuncs - functions used by inews.
   */
  
! static char *SccsId = "@(#) ifuncs.c	2.7	4/19/82";
  
  #include "iparams.h"
  

--- 2,8 -----
   * ifuncs - functions used by inews.
   */
  
! static char *SccsId = "@(#) ifuncs.c	2.10	6/8/82";
  
  #include "iparams.h"
  
***************
*** 107,113
  
  	ofp = xfopen(mktemp(TRANS), "w");
  #ifdef BERKNAME
- 	gobbledygook;
  	if (berknet) {
  		ptr = index(h.path, '!');
  		sprintf(bfr, "%s:%s", BERKNAME, ++ptr);

--- 107,112 -----
  
  	ofp = xfopen(mktemp(TRANS), "w");
  #ifdef BERKNAME
  	if (berknet) {
  		ptr = index(h.path, '!');
  		if (ptr == 0)
***************
*** 110,115
  	gobbledygook;
  	if (berknet) {
  		ptr = index(h.path, '!');
  		sprintf(bfr, "%s:%s", BERKNAME, ++ptr);
  		strcpy(h.path, bfr);
  	}

--- 109,116 -----
  #ifdef BERKNAME
  	if (berknet) {
  		ptr = index(h.path, '!');
+ 		if (ptr == 0)
+ 			ptr = h.path-1;
  		sprintf(bfr, "%s:%s", BERKNAME, ++ptr);
  		strcpy(h.path, bfr);
  	}
***************
*** 127,137
  	fclose(ifp);
  	fclose(ofp);
  	if (*sp->s_xmit == '\0')
! #ifdef UUXZ
! 		sprintf(bfr, "uux - -z -r %s\\!rnews < %s", sp->s_name, TRANS);
! #else
! 		sprintf(bfr, "uux - -r %s\\!rnews < %s", sp->s_name, TRANS);
! #endif
  	else
  		sprintf(bfr, "(%s) < %s", sp->s_xmit, TRANS);
  	if (noshell) {

--- 128,134 -----
  	fclose(ifp);
  	fclose(ofp);
  	if (*sp->s_xmit == '\0')
! 		sprintf(bfr, DFTXMIT, sp->s_name, TRANS);
  	else
  		sprintf(bfr, "(%s) < %s", sp->s_xmit, TRANS);
  	if (noshell) {
***************
*** 188,193
  		}
  	}
  	fclose(hfp);
  	addhist(file);
  	addhist("\t");
  	return(FALSE);

--- 185,191 -----
  		}
  	}
  	fclose(hfp);
+ 	idlock(file);
  	addhist(file);
  	addhist("\t");
  	return(FALSE);
***************
*** 209,214
  	fprintf(hfp, "%s\n", histline);
  	fclose(hfp);
  	histline[0] = 0;
  }
  
  /*

--- 207,213 -----
  	fprintf(hfp, "%s\n", histline);
  	fclose(hfp);
  	histline[0] = 0;
+ 	idunlock();
  }
  
  /*
***************
*** 214,221
  /*
   * Save partial news.
   */
! newssave(dummy1, dummy2)
! char *dummy1, *dummy2;
  {
  	register FILE *to, *from;
  	char sfname[BUFLEN];

--- 213,220 -----
  /*
   * Save partial news.
   */
! newssave(fd, dummy)
! FILE *fd, *dummy;
  {
  	register FILE *to, *from;
  	char sfname[BUFLEN];
***************
*** 223,229
  	struct hbuf h;
  	time_t tim;
  
! 	from = xfopen(INFILE, "r");
  	umask(savmask);
  	setgid(gid);
  	setuid(uid);

--- 222,231 -----
  	struct hbuf h;
  	time_t tim;
  
! 	if (fd == NULL)
! 		from = xfopen(INFILE, "r");
! 	else
! 		from = fd;
  	umask(savmask);
  	setgid(gid);
  	setuid(uid);
***************
*** 319,324
  		unlink(LOCKFILE);
  }
  
  /*
   * Put a unique name into header.ident.
   */

--- 321,362 -----
  		unlink(LOCKFILE);
  }
  
+ char lockname[80];
+ idlock(str)
+ char *str;
+ {
+ 	register int i;
+ 	char tempname[80];
+ 	long now;
+ 	struct stat sbuf;
+ 
+ 	sprintf(tempname, "/tmp/LTMP.%d", getpid());
+ 	sprintf(lockname, "/tmp/L%s", str);
+ 	close(creat(tempname, 0666));
+ 	i = 10*60;	/* Keep trying for 10 minutes */
+ 	while (link(tempname, lockname)) {
+ 		if (--i < 0) {
+ 			unlink(tempname);
+ 			sprintf(tempname, "Article %s locked up", str);
+ 			xerror(tempname);
+ 		}
+ 		time(&now);
+ 		i = stat(lockname, &sbuf);
+ 		if (i < 0) {
+ 			xerror("Directory permission problem in /tmp");
+ 		}
+ 		if (sbuf.st_mtime + 10*60 < now)
+ 			unlink(lockname);
+ 		sleep((unsigned)60);
+ 	}
+ 	unlink(tempname);
+ }
+ 
+ idunlock()
+ {
+ 	unlink(lockname);
+ }
+ 
  /*
   * Put a unique name into header.ident.
   */
***************
*** 378,383
  	sprintf(msg, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9);
  
  	lock();
  	logfile = fopen(logfname, "a");
  	if (logfile == NULL) {
  		unlock(0);

--- 416,425 -----
  	sprintf(msg, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9);
  
  	lock();
+ 	if (access(logfname, 0)) {
+ 		unlock(0);
+ 		return;
+ 	}
  	logfile = fopen(logfname, "a");
  	if (logfile == NULL) {
  		unlock(0);
***************
*** 386,389
  	fprintf(logfile, "%s %s\t%s\n", logtime, rmtsys, msg);
  	fclose(logfile);
  	unlock();
  }

--- 428,548 -----
  	fprintf(logfile, "%s %s\t%s\n", logtime, rmtsys, msg);
  	fclose(logfile);
  	unlock();
+ }
+ 
+ /*
+  * Figure out who is sending the message and sign it.
+  * We attempt to look up the user in the gecos field of /etc/passwd.
+  * The Berkeley conventions (name first, & expands to login name) are
+  * assumed.  If a site stores weird stuff in gecos, like some account
+  * number, too bad - local mods may be in order.
+  */
+ char *
+ gensender(un)
+ char *un;
+ {
+ 	static char outbuf[100];
+ 	char inbuf[100];
+ 	struct passwd *pw;
+ 
+ 	pw = getpwnam(un);
+ 	if (pw == NULL)
+ 		return un;
+ 	buildfname(pw->pw_gecos, un, inbuf);
+ 	if (inbuf[0] == 0)
+ 		return un;
+ 	sprintf(outbuf, "%s (%s)", un, inbuf);
+ 	return outbuf;
+ }
+ 
+ /*
+ **  BUILDFNAME -- build full name from gecos style entry.
+ **	(routine lifted from sendmail)
+ **
+ **	This routine interprets the strange entry that would appear
+ **	in the GECOS field of the password file.
+ **
+ **	Parameters:
+ **		p -- name to build.
+ **		login -- the login name of this user (for &).
+ **		buf -- place to put the result.
+ **
+ **	Returns:
+ **		none.
+ **
+ **	Side Effects:
+ **		none.
+ */
+ 
+ buildfname(p, login, buf)
+ 	register char *p;
+ 	char *login;
+ 	char *buf;
+ {
+ 	register char *bp = buf;
+ 
+ 	if (*p == '*')
+ 		p++;
+ 	while (*p != '\0' && *p != ',' && *p != ';' && *p != ':')
+ 	{
+ 		if (*p == '&')
+ 		{
+ 			strcpy(bp, login);
+ 			*bp = toupper(*bp);
+ 			while (*bp != '\0')
+ 				bp++;
+ 			p++;
+ 		}
+ 		else
+ 			*bp++ = *p++;
+ 	}
+ 	*bp = '\0';
+ }
+ 
+ /*
+  * Check if header.nbuf contains only valid newsgroup names;
+  * exit with error if not valid.
+  *
+  * a == TRUE means header.nbuf is subscription list
+  * a == FALSE means header.nbuf is newsgroup list
+  */
+ 
+ ngfcheck(a)
+ int a;
+ {
+ 	char ngcheck[NGFSIZ];	/* Hold NGFILE newsgroups */
+ 	char tbuf[BUFLEN];	/* hold single header.nbuf news group */
+ 	register char *s1, *s2;
+ 	register FILE *f;
+ 
+ 	s1 = ngcheck;
+ 	f = xfopen(NGFILE, "r");
+ 	while (fgets(bfr, BUFLEN, f) != NULL) {
+ 		for (s2 = bfr; *s2 != '\0' &&
+ 		    *s2 != ' ' && *s2 != '\t' &&
+ 		    *s2 != ':' && *s2 != '\n';) {
+ 			if (s1 >= &ngcheck[NGFSIZ-2])
+ 				xerror("NGFILE too long");
+ 			*s1++ = *s2++;
+ 		}
+ 		*s1++ = NGDELIM;
+ 	}
+ 	*s1 = '\0';
+ 	fclose(f);
+ 	for (s1 = header.nbuf; *s1 != '\0';) {
+ 		if (*s1 == NEGCHAR)
+ 			s1++;
+ 		s2 = tbuf;
+ 		while ((*s2++ = *s1++) != NGDELIM)
+ 			if (s1[-1] == ':')
+ 				xerror("Newsgroup cannot contain ':'");
+ 		*s2 = '\0';
+ 		s2 = tbuf;
+ 		if (!ngmatch(s2, ngcheck) && (!a || !ngmatch(ngcheck, s2))) {
+ 			ngdel(s2);
+ 			sprintf(bfr, "Bad news group \"%s\"", s2);
+ 			newssave(stdin, NULL);
+ 			xerror(bfr);
+ 		}
+ 	}
  }
diff -c -r 2.6/src/inews.c 2.7/src/inews.c
*** 2.6/src/inews.c	Tue Apr 20 11:09:05 1982
--- 2.7/src/inews.c	Tue Jun  1 08:25:21 1982
***************
*** 2,8
   * inews - insert, receive, and transmit news articles.
   */
  
! static char *SccsId = "@(#) inews.c	2.8	4/20/82";
  
  #include "iparams.h"
  

--- 2,8 -----
   * inews - insert, receive, and transmit news articles.
   */
  
! static char *SccsId = "@(#) inews.c	2.9	6/1/82";
  
  #include "iparams.h"
  
***************
*** 38,43
  'F',	' ',		FALSE,	UNPROC,	UNKNOWN,	header.followid,
  'c',	'\0',		FALSE,	UNKNOWN,CANCEL,		filename,
  'C',	'\0',		FALSE,	UNKNOWN,CREATENG,	header.nbuf,
  '\0',	'\0',		0,	0,	0,		(char *)NULL
  };
  

--- 38,45 -----
  'F',	' ',		FALSE,	UNPROC,	UNKNOWN,	header.followid,
  'c',	'\0',		FALSE,	UNKNOWN,CANCEL,		filename,
  'C',	'\0',		FALSE,	UNKNOWN,CREATENG,	header.nbuf,
+ #define Dflag	options[8].flag
+ 'D',	'\0',		FALSE,	UNPROC,	UNKNOWN,	filename,
  '\0',	'\0',		0,	0,	0,		(char *)NULL
  };
  
***************
*** 196,201
  	 * ALL of the command line has now been processed. (!)
  	 */
  
  	if (mode == CANCEL) {
  		if (strcmp(whatever, header.path) && uid != ROOTID && uid != geteuid() && uid)
  			xerror("Not contributor");

--- 198,217 -----
  	 * ALL of the command line has now been processed. (!)
  	 */
  
+ 	if (!Dflag) {
+ 		if (recording(header.nbuf)) {
+ 			if (!tty)
+ 				fwait(fsubr(newssave, stdin, NULL));
+ 			xerror("aborted due to recording");
+ 		}
+ 	}
+ 
+ 	if (!tty && mode != PROC) {
+ 		i = fork();
+ 		if (i == 0)
+ 			exit(0);
+ 	}
+ 
  	if (mode == CANCEL) {
  		if (strncmp(whatever, header.path, strlen(whatever)) && uid != ROOTID && uid != geteuid() && uid)
  			xerror("Not contributor");
***************
*** 197,203
  	 */
  
  	if (mode == CANCEL) {
! 		if (strcmp(whatever, header.path) && uid != ROOTID && uid != geteuid() && uid)
  			xerror("Not contributor");
  		cancel();
  		xxit(0);

--- 213,219 -----
  	}
  
  	if (mode == CANCEL) {
! 		if (strncmp(whatever, header.path, strlen(whatever)) && uid != ROOTID && uid != geteuid() && uid)
  			xerror("Not contributor");
  		cancel();
  		xxit(0);
***************
*** 205,211
  
  	if (*header.nbuf)
  		lcase(header.nbuf);
! 	strcpy(header.path, username);
  	tty = isatty(fileno(stdin));
  	if (mode == PROC) {
  		signal(SIGHUP, SIG_IGN);

--- 221,227 -----
  
  	if (*header.nbuf)
  		lcase(header.nbuf);
! 	strcpy(header.path, gensender(username));
  	tty = isatty(fileno(stdin));
  	if (mode == PROC) {
  		signal(SIGHUP, SIG_IGN);
***************
*** 286,292
  	if (mode != PROC)
  		input();
  
- 	/* Do the actual insertion. */
  	if (tty) {
  		i = fork();
  		if (i <= 0)

--- 302,307 -----
  	if (mode != PROC)
  		input();
  
  	if (tty) {
  		i = fork();
  		if (i == 0)
***************
*** 289,299
  	/* Do the actual insertion. */
  	if (tty) {
  		i = fork();
! 		if (i <= 0)
! 			insert();
! 		exit(0);
! 	} else
! 		insert();
  }
  
  /* Camel, R.O.H. */

--- 304,315 -----
  
  	if (tty) {
  		i = fork();
! 		if (i == 0)
! 			exit(0);
! 	}
! 
! 	/* Do the actual insertion. */
! 	insert();
  }
  
  /* Camel, R.O.H. */
***************
*** 432,438
  			if (!strcmp(bfr, ".\n"))
  				break;
  			for (cp=bfr; *cp; cp++) {
! 				if (isprint(*cp) || isspace(*cp))
  					putc(*cp, infp);
  				if (isprint(*cp))
  					chcount++;

--- 448,454 -----
  			if (!strcmp(bfr, ".\n"))
  				break;
  			for (cp=bfr; *cp; cp++) {
! 				if (isprint(*cp) || isspace(*cp) || *cp=='\b')
  					putc(*cp, infp);
  				if (isprint(*cp))
  					chcount++;
***************
*** 496,501
  		xerror(locbuf);
  	}
  
  	/*
  	 * Give away the files we just created, which were assigned to our
  	 * REAL uid.  This only works on USG systems.  It is an alternative

--- 512,518 -----
  		xerror(locbuf);
  	}
  
+ #ifdef USG
  	/*
  	 * Give away the files we just created, which were assigned to our
  	 * REAL uid.  This only works on USG systems.  It is an alternative
***************
*** 499,505
  	/*
  	 * Give away the files we just created, which were assigned to our
  	 * REAL uid.  This only works on USG systems.  It is an alternative
! 	 * to the setuid call above.
  	 */
  	chown(ngname, duid, dgid);
  	chown(locbuf, duid, dgid);

--- 516,524 -----
  	/*
  	 * Give away the files we just created, which were assigned to our
  	 * REAL uid.  This only works on USG systems.  It is an alternative
! 	 * to the setuid call above.  The directories we just made are owned
! 	 * by our real uid, so we have to temporarily set our effective uid
! 	 * the same to allow the chown.  Fortunately, USG lets us setuid back.
  	 */
  	setuid(getuid());
  	chown(ngname, duid, dgid);
***************
*** 501,506
  	 * REAL uid.  This only works on USG systems.  It is an alternative
  	 * to the setuid call above.
  	 */
  	chown(ngname, duid, dgid);
  	chown(locbuf, duid, dgid);
  

--- 520,526 -----
  	 * by our real uid, so we have to temporarily set our effective uid
  	 * the same to allow the chown.  Fortunately, USG lets us setuid back.
  	 */
+ 	setuid(getuid());
  	chown(ngname, duid, dgid);
  	chown(locbuf, duid, dgid);
  	setuid(duid);
***************
*** 503,508
  	 */
  	chown(ngname, duid, dgid);
  	chown(locbuf, duid, dgid);
  
  	/* Update the "active newsgroup" file. */
  	actfp = xfopen(ACTIVE, "a");

--- 523,530 -----
  	setuid(getuid());
  	chown(ngname, duid, dgid);
  	chown(locbuf, duid, dgid);
+ 	setuid(duid);
+ #endif
  
  	/* Update the "active newsgroup" file. */
  	actfp = xfopen(ACTIVE, "a");
Only in 2.7/src: install.usg
Only in 2.7/src: install.v7
Only in 2.6/src: newsinstall.sh
diff -c -r 2.6/src/params.h 2.7/src/params.h
*** 2.6/src/params.h	Mon Mar 22 20:23:34 1982
--- 2.7/src/params.h	Tue Jun  1 08:25:22 1982
***************
*** 2,8
   * params.h - parameters for everyone.
   */
  
! static char *Params = "@(#) params.h	2.1	2/23/82";
  
  #include <stdio.h>
  #include <signal.h>

--- 2,8 -----
   * params.h - parameters for everyone.
   */
  
! static char *Params = "@(#) params.h	2.2	6/1/82";
  
  #include <stdio.h>
  #include <signal.h>
***************
*** 45,51
  extern	unsigned uid, gid, duid, dgid;
  extern	int	savmask,sigtrap,mode,lockcount,defexp;
  extern	struct	hbuf header;
! extern	char	bfr[BUFLEN],username[BUFLEN],userhome[BUFLEN];
  extern	char	*SPOOL,*LIB,*CAND;
  extern	char	*SUBFILE,*NGFILE,*ACTIVE;
  extern	char	SYSNAME[],*NEWSU,*NEWSG;

--- 45,51 -----
  extern	unsigned uid, gid, duid, dgid;
  extern	int	savmask,sigtrap,mode,lockcount,defexp;
  extern	struct	hbuf header;
! extern	char	bfr[LBUFLEN],username[BUFLEN],userhome[BUFLEN];
  extern	char	*SPOOL,*LIB,*CAND;
  extern	char	*SUBFILE,*NGFILE,*ACTIVE;
  extern	char	SYSNAME[],*NEWSU,*NEWSG;
Only in 2.6/src: postnews
diff -c -r 2.6/src/postnews.usg 2.7/src/postnews.usg
*** 2.6/src/postnews.usg	Sun Apr 18 18:02:17 1982
--- 2.7/src/postnews.usg	Tue Jun  1 08:25:34 1982
***************
*** 1,5
! : '@(#) postnews.usg	2.3	4/18/82'
! if [ $# -gt 1 ]; then
  	echo "$0: Too many args"
  	exit 1
  fi

--- 1,5 -----
! : '@(#) postnews.usg	2.4	6/1/82'
! if test $# -gt 1 ; then
  	echo "$0: Too many args"
  	exit 1
  fi
***************
*** 3,9
  	echo "$0: Too many args"
  	exit 1
  fi
! if [ $# -eq 1 -a ! -r "$1" ]; then
  	echo "$0: Can't read $1"
  	exit 1
  fi

--- 3,9 -----
  	echo "$0: Too many args"
  	exit 1
  fi
! if test $# -eq 1 -a ! -r "$1" ; then
  	echo "$0: Can't read $1"
  	exit 1
  fi
***************
*** 11,17
  read title
  echo "Newsgroups (general): " \\c
  read ng
! if [ x$ng = x ]; then
  	ng=general
  fi
  case $# in

--- 11,17 -----
  read title
  echo "Newsgroups (general): " \\c
  read ng
! if test x$ng = x ; then
  	ng=general
  fi
  case $# in
***************
*** 16,22
  fi
  case $# in
  0)
! 	if [ x$EDITOR = x ]
  	then
  		echo "Type news, end with control D"
  		inews -t "$title" -n $ng

--- 16,22 -----
  fi
  case $# in
  0)
! 	if test x$EDITOR = x 
  	then
  		echo "Type news, end with control D"
  		inews -t "$title" -n $ng
***************
*** 22,28
  		inews -t "$title" -n $ng
  	else
  		t=/tmp/pn$$
! 		trap "rm -f $t; exit" 0 1 2
  		$EDITOR $t
  		inews -t "$title" -n $ng <$t &
  	fi

--- 22,28 -----
  		inews -t "$title" -n $ng
  	else
  		t=/tmp/pn$$
! 		trap "sleep 1; rm -f $t; exit" 0 1 2
  		$EDITOR $t
  		inews -t "$title" -n $ng <$t &
  	fi
diff -c -r 2.6/src/postnews.v7 2.7/src/postnews.v7
*** 2.6/src/postnews.v7	Sun Apr 18 18:02:19 1982
--- 2.7/src/postnews.v7	Tue Jun  1 08:25:16 1982
***************
*** 1,5
! : '@(#) postnews.v7	2.3	4/18/82'
! if [ $# -gt 1 ]; then
  	echo "$0: Too many args"
  	exit 1
  fi

--- 1,5 -----
! : '@(#) postnews.v7	2.4	6/1/82'
! if test $# -gt 1 ; then
  	echo "$0: Too many args"
  	exit 1
  fi
***************
*** 3,9
  	echo "$0: Too many args"
  	exit 1
  fi
! if [ $# -eq 1 -a ! -r "$1" ]; then
  	echo "$0: Can't read $1"
  	exit 1
  fi

--- 3,9 -----
  	echo "$0: Too many args"
  	exit 1
  fi
! if test $# -eq 1 -a ! -r "$1" ; then
  	echo "$0: Can't read $1"
  	exit 1
  fi
***************
*** 11,17
  read title
  echo -n "Newsgroups (general): "
  read ng
! if [ x$ng = x ]; then
  	ng=general
  fi
  case $# in

--- 11,17 -----
  read title
  echo -n "Newsgroups (general): "
  read ng
! if test x$ng = x ; then
  	ng=general
  fi
  case $# in
***************
*** 16,22
  fi
  case $# in
  0)
! 	if [ x$EDITOR = x ]
  	then
  		echo "Type news, end with control D"
  		inews -t "$title" -n $ng

--- 16,22 -----
  fi
  case $# in
  0)
! 	if test x$EDITOR = x 
  	then
  		echo "Type news, end with control D"
  		inews -t "$title" -n $ng
***************
*** 22,28
  		inews -t "$title" -n $ng
  	else
  		t=/tmp/pn$$
! 		trap "rm -f $t; exit" 0 1 2
  		$EDITOR $t
  		inews -t "$title" -n $ng <$t &
  	fi

--- 22,28 -----
  		inews -t "$title" -n $ng
  	else
  		t=/tmp/pn$$
! 		trap "sleep 1; rm -f $t; exit" 0 1 2
  		$EDITOR $t
  		inews -t "$title" -n $ng <$t
  	fi
***************
*** 24,30
  		t=/tmp/pn$$
  		trap "rm -f $t; exit" 0 1 2
  		$EDITOR $t
! 		inews -t "$title" -n $ng <$t &
  	fi
  	;;
  1)

--- 24,30 -----
  		t=/tmp/pn$$
  		trap "sleep 1; rm -f $t; exit" 0 1 2
  		$EDITOR $t
! 		inews -t "$title" -n $ng <$t
  	fi
  	;;
  1)
***************
*** 28,33
  	fi
  	;;
  1)
! 	inews -t "$title" -n $ng < $1 &
  	;;
  esac

--- 28,33 -----
  	fi
  	;;
  1)
! 	inews -t "$title" -n $ng < $1
  	;;
  esac
diff -c -r 2.6/src/process.c 2.7/src/process.c
*** 2.6/src/process.c	Mon Mar 22 20:23:37 1982
--- 2.7/src/process.c	Mon Jun  7 19:14:10 1982
***************
*** 2,8
   * process - process options for readnews
   */
  
! static char *SccsId = "@(#) process.c	2.2	3/14/82";
  
  #include "rparams.h"
  

--- 2,8 -----
   * process - process options for readnews
   */
  
! static char *SccsId = "@(#) process.c	2.4	6/7/82";
  
  #include "rparams.h"
  
***************
*** 21,27
  's',   NGDELIM,	FALSE,	STRING,	ANY,		UNKNOWN,header.nbuf,
  'x',	'\0',	FALSE,	OPTION,	ANY,		UNKNOWN,(char *)NULL,
  'h',	'\0',	FALSE,	OPTION,	ANY,		UNKNOWN,(char *)NULL,
- #ifdef TMAIL
  'M',	'\0',	FALSE,	OPTION,	UNKNOWN,	MAIL,	(char *)NULL,
  #endif
  '\0',	'\0',	0,	0,	0,		0,	(char *)NULL

--- 21,26 -----
  's',   NGDELIM,	FALSE,	STRING,	ANY,		UNKNOWN,header.nbuf,
  'x',	'\0',	FALSE,	OPTION,	ANY,		UNKNOWN,(char *)NULL,
  'h',	'\0',	FALSE,	OPTION,	ANY,		UNKNOWN,(char *)NULL,
  'M',	'\0',	FALSE,	OPTION,	UNKNOWN,	MAIL,	(char *)NULL,
  'f',	'\0',	FALSE,	OPTION,	ANY,		UNKNOWN,(char *)NULL,
  '\0',	'\0',	0,	0,	0,		0,	(char *)NULL
***************
*** 23,29
  'h',	'\0',	FALSE,	OPTION,	ANY,		UNKNOWN,(char *)NULL,
  #ifdef TMAIL
  'M',	'\0',	FALSE,	OPTION,	UNKNOWN,	MAIL,	(char *)NULL,
! #endif
  '\0',	'\0',	0,	0,	0,		0,	(char *)NULL
  };
  

--- 22,28 -----
  'x',	'\0',	FALSE,	OPTION,	ANY,		UNKNOWN,(char *)NULL,
  'h',	'\0',	FALSE,	OPTION,	ANY,		UNKNOWN,(char *)NULL,
  'M',	'\0',	FALSE,	OPTION,	UNKNOWN,	MAIL,	(char *)NULL,
! 'f',	'\0',	FALSE,	OPTION,	ANY,		UNKNOWN,(char *)NULL,
  '\0',	'\0',	0,	0,	0,		0,	(char *)NULL
  };
  
***************
*** 50,56
  					goto found;
  			}
  			/* unknown option letter */
! 			fprintf(stderr, "usage: readnews [ -a [ date ]] [ -n newsgroups ] [ -t titles ] [ -lprxhM ]\n");
  			fprintf(stderr, "\t[ -c [ ``mailer'' ]]\n\n");
  			fprintf(stderr, "       readnews -s\n");
  			exit(1);

--- 49,55 -----
  					goto found;
  			}
  			/* unknown option letter */
! 			fprintf(stderr, "Usage: readnews [ -a [ date ]] [ -n newsgroups ] [ -t titles ] [ -lprxhfM ]\n");
  			fprintf(stderr, "\t[ -c [ ``mailer'' ]]\n\n");
  			fprintf(stderr, "       readnews -s\n");
  			exit(1);
***************
*** 66,72
  			optpt->flag = TRUE;
  			state = optpt->newstate;
  			ptr = optpt->buf;
! 			len = BUFSIZ;
  		}
  
  		argv++;		/* done with this option arg. */

--- 65,71 -----
  			optpt->flag = TRUE;
  			state = optpt->newstate;
  			ptr = optpt->buf;
! 			len = LBUFLEN;
  		}
  
  		argv++;		/* done with this option arg. */
diff -c -r 2.6/src/readnews.c 2.7/src/readnews.c
*** 2.6/src/readnews.c	Sat Apr  3 10:22:09 1982
--- 2.7/src/readnews.c	Tue Jun  1 08:25:24 1982
***************
*** 2,8
   * readnews - read news articles.
   */
  
! static char *SccsId = "@(#) readnews.c	2.4	4/3/82";
  
  #include "rparams.h"
  

--- 2,8 -----
   * readnews - read news articles.
   */
  
! static char *SccsId = "@(#) readnews.c	2.5	6/1/82";
  
  #include "rparams.h"
  
***************
*** 35,40
  	struct group *gp;
  	int i, optflag = FALSE, space = FALSE;
  	struct utsname ubuf;
  
  
  	/* set up defaults and initialize. */

--- 35,41 -----
  	struct group *gp;
  	int i, optflag = FALSE, space = FALSE;
  	struct utsname ubuf;
+ 	char *myrc;
  
  
  	/* set up defaults and initialize. */
***************
*** 112,118
  #else
  	getuser();
  #endif
! 	sprintf(newsrc, "%s/%s", userhome, NEWSRC);
  	if ((rcfp = fopen(newsrc, "r")) != NULL) {
  		while (fgets(rcbuf, BUFSIZ, rcfp) != NULL) {
  			if (!(space = isspace(*rcbuf)))

--- 113,122 -----
  #else
  	getuser();
  #endif
! 	myrc = getenv("NEWSRC");
! 	if (myrc == NULL)
! 		myrc = NEWSRC;
! 	sprintf(newsrc, "%s/%s", userhome, myrc);
  	if ((rcfp = fopen(newsrc, "r")) != NULL) {
  		rcreadok = FALSE;
  		while (fgets(rcbuf, LBUFLEN, rcfp) != NULL) {
***************
*** 114,120
  #endif
  	sprintf(newsrc, "%s/%s", userhome, NEWSRC);
  	if ((rcfp = fopen(newsrc, "r")) != NULL) {
! 		while (fgets(rcbuf, BUFSIZ, rcfp) != NULL) {
  			if (!(space = isspace(*rcbuf)))
  				optflag = FALSE;
  			if (!strncmp(rcbuf, "options ", 8))

--- 118,125 -----
  		myrc = NEWSRC;
  	sprintf(newsrc, "%s/%s", userhome, myrc);
  	if ((rcfp = fopen(newsrc, "r")) != NULL) {
! 		rcreadok = FALSE;
! 		while (fgets(rcbuf, LBUFLEN, rcfp) != NULL) {
  			if (!(space = isspace(*rcbuf)))
  				optflag = FALSE;
  			if (!strncmp(rcbuf, "options ", 8))
***************
*** 149,154
  			}
  		}
  		fclose(rcfp);
  	}
  	if (line != -1) {
  #ifdef DEBUG

--- 154,160 -----
  			}
  		}
  		fclose(rcfp);
+ 		rcreadok = TRUE;
  	}
  	if (line != -1) {
  #ifdef DEBUG
***************
*** 191,197
  		xxit(0);
  	}
  	if (!xflag && (rcfp = xfopen(newsrc, "r"))) {
! 		while (!sigtrap && fgets(rcbuf, BUFSIZ, rcfp) != NULL) {
  			if (!nstrip(rcbuf))
  				xerror(".newsrc line too long");
  			if (++line >= LINES)

--- 197,203 -----
  		xxit(0);
  	}
  	if (!xflag && (rcfp = xfopen(newsrc, "r"))) {
! 		while (!sigtrap && fgets(rcbuf, LBUFLEN, rcfp) != NULL) {
  			if (!nstrip(rcbuf))
  				xerror(".newsrc line too long");
  			if (++line >= LINES)
diff -c -r 2.6/src/readr.c 2.7/src/readr.c
*** 2.6/src/readr.c	Sun Apr 18 18:02:23 1982
--- 2.7/src/readr.c	Tue Jun  8 08:35:14 1982
***************
*** 2,8
   * readr - /bin/mail and msgs interface and associated functions.
   */
  
! static char *SccsId = "@(#) readr.c	2.8	4/18/82";
  
  #include "rparams.h"
  

--- 2,8 -----
   * readr - /bin/mail and msgs interface and associated functions.
   */
  
! static char *SccsId = "@(#) readr.c	2.10	6/8/82";
  
  #include "rparams.h"
  
***************
*** 33,39
  	int  news = 0;
  	char *ed, *tf = "/tmp/folXXXXXX";
  	char edcmdbuf[128];
! 
  	FILE *ofp;		/* for output of Readr			*/
  	FILE *fp;		/* for use with hread interface		*/
  	struct hbuf h;		/* ditto.				*/

--- 33,39 -----
  	int  news = 0;
  	char *ed, *tf = "/tmp/folXXXXXX";
  	char edcmdbuf[128];
! 	char folbuf[160];
  	FILE *ofp;		/* for output of Readr			*/
  	FILE *fp;		/* for use with hread interface		*/
  	struct hbuf h;		/* ditto.				*/
***************
*** 39,44
  	struct hbuf h;		/* ditto.				*/
  	int i;
  	int oobit;		/* last bit, really			*/
  
  #ifdef DEBUG
  	fprintf(stderr, "readr()\n");

--- 39,45 -----
  	struct hbuf h;		/* ditto.				*/
  	int i;
  	int oobit;		/* last bit, really			*/
+ 	char *oldsig;
  
  #ifdef DEBUG
  	fprintf(stderr, "readr()\n");
***************
*** 130,135
  			if (sigtrap) {
  				if (sigtrap == SIGHUP)
  					return;
  				fprintf(ofp, "Abort (n)?  ");
  				fflush(ofp);
  				gets(bfr);

--- 131,138 -----
  			if (sigtrap) {
  				if (sigtrap == SIGHUP)
  					return;
+ 				if (!rcreadok)
+ 					xxit(0);
  				fprintf(ofp, "Abort (n)?  ");
  				fflush(ofp);
  				gets(bfr);
***************
*** 140,146
  #ifdef DEBUG
  			fprintf(stderr, "filename = '%s'\n", filename);
  #endif
! 			if (access(filename, 4) || ((fp = fopen(filename, "r")) == NULL) || (hread(&h, fp) == NULL) || !select(&h)) {
  #ifdef DEBUG
  				fprintf(stderr, "Bad article '%s'\n", filename);
  #endif

--- 143,149 -----
  #ifdef DEBUG
  			fprintf(stderr, "filename = '%s'\n", filename);
  #endif
! 			if (access(filename, 4) || ((fp = fopen(filename, "r")) == NULL) || (hread(&h, fp) == NULL) || (!rfq && !select(&h))) {
  #ifdef DEBUG
  				fprintf(stderr, "Bad article '%s'\n", filename);
  #endif
***************
*** 248,254
  			clear(bit);
  			saveart;
  			nextbit();
! 			if (hflag)
  				fprintf(ofp, "From: %s\n", h.path);
  			break;
  

--- 251,257 -----
  			clear(bit);
  			saveart;
  			nextbit();
! 			if (hflag) {
  				fprintf(ofp, "From: %s\n", h.path);
  				fflush(ofp);
  			}
***************
*** 250,255
  			nextbit();
  			if (hflag)
  				fprintf(ofp, "From: %s\n", h.path);
  			break;
  
  		/* reprint the article */

--- 253,260 -----
  			nextbit();
  			if (hflag) {
  				fprintf(ofp, "From: %s\n", h.path);
+ 				fflush(ofp);
+ 			}
  			break;
  
  		/*
***************
*** 252,257
  				fprintf(ofp, "From: %s\n", h.path);
  			break;
  
  		/* reprint the article */
  		case 'p':
  			if (*bptr != '\0') goto badropt;

--- 257,291 -----
  			}
  			break;
  
+ 		/*
+ 		 * Unsubscribe to the newsgroup and go on to next group
+ 		 */
+ 		case 'u':
+ 			obit = -1;
+ 			if (fp != NULL) {
+ 				fclose(fp);
+ 				fp = NULL;
+ 			}
+ 			if (cflag)
+ 				clear(bit);
+ 			else
+ 				putc('\n', ofp);
+ 			rfq = 0;
+ 			zapng = TRUE;
+ 			saveart;
+ 			if (nextng()) {
+ 				if (actdirect == BACKWARD)
+ 					fprintf(ofp, "Can't back up.\n");
+ 				else
+ 					goto getout;
+ 			}
+ 			break;
+ 
+ 		/* Print the current version of news */
+ 		case 'v':
+ 			fprintf(ofp, "News version: %s\n", news_version);
+ 			break;
+ 
  		/* reprint the article */
  		case 'p':
  			if (*bptr != '\0') goto badropt;
***************
*** 377,383
  			}
  			if (*bptr != '\0') goto badropt;
  			readmode = SPEC;
! 			i = strcmp(username, hptr->path);
  			if (i && uid != ROOTID && uid) {
  				fprintf(ofp, "Can't cancel what you didn't write.\n");
  				break;

--- 411,421 -----
  			}
  			if (*bptr != '\0') goto badropt;
  			readmode = SPEC;
! 			strcpy(rcbuf, hptr->path);
! 			ptr1 = index(rcbuf, ' ');
! 			if (ptr1)
! 				*ptr1 = 0;
! 			i = strcmp(username, rcbuf);
  			if (i && uid != ROOTID && uid) {
  				fprintf(ofp, "Can't cancel what you didn't write.\n");
  				break;
***************
*** 402,408
  
  		/* mail reply */
  		case 'r':
! 			tfilename = h.path;
  			if (*bptr == '-') {
  				bptr++;
  				if (*hbuf1.path)

--- 440,446 -----
  
  		/* mail reply */
  		case 'r':
! 			hptr = &h;
  			if (*bptr == '-') {
  				hptr = &hbuf1;
  				bptr++;
***************
*** 404,409
  		case 'r':
  			tfilename = h.path;
  			if (*bptr == '-') {
  				bptr++;
  				if (*hbuf1.path)
  					tfilename = hbuf1.path;

--- 442,448 -----
  		case 'r':
  			hptr = &h;
  			if (*bptr == '-') {
+ 				hptr = &hbuf1;
  				bptr++;
  			}
  			tfilename = hptr->path;
***************
*** 405,412
  			tfilename = h.path;
  			if (*bptr == '-') {
  				bptr++;
- 				if (*hbuf1.path)
- 					tfilename = hbuf1.path;
  			}
  			if (*bptr != '\0') goto badropt;
  			{

--- 444,449 -----
  			if (*bptr == '-') {
  				hptr = &hbuf1;
  				bptr++;
  			}
  			tfilename = hptr->path;
  			if (*bptr != '\0') goto badropt;
***************
*** 408,413
  				if (*hbuf1.path)
  					tfilename = hbuf1.path;
  			}
  			if (*bptr != '\0') goto badropt;
  			{
  				register char *pathptr, *ptr;

--- 445,451 -----
  				hptr = &hbuf1;
  				bptr++;
  			}
+ 			tfilename = hptr->path;
  			if (*bptr != '\0') goto badropt;
  			{
  				register char *pathptr, *ptr;
***************
*** 414,419
  				char curberk[BUFLEN];
  
  				*rcbuf = '\0';
  				pathptr = tfilename;
  				ptr = pathptr - 1;
  				i = 0;

--- 452,458 -----
  				char curberk[BUFLEN];
  
  				*rcbuf = '\0';
+ 				*curberk = '\0';
  				pathptr = tfilename;
  				ptr = pathptr - 1;
  				i = 0;
***************
*** 418,423
  				ptr = pathptr - 1;
  				i = 0;
  again:
  				for (; *++ptr && !index(NETCHRS, *ptr); i++)
  					;
  				if (*ptr)

--- 457,469 -----
  				ptr = pathptr - 1;
  				i = 0;
  again:
+ 				/*
+ 				 * Play games stripping off multiple berknet
+ 				 * addresses (: or .) here.  Should also strip
+ 				 * off multiple @ arpanet addresses, but I
+ 				 * think we should just wait for the sane world
+ 				 * of internet absolute addreses.
+ 				 */
  				for (; *++ptr && !index(NETCHRS, *ptr); i++)
  					;
  				if (*ptr)
***************
*** 437,442
  					i = 1;
  					goto again;
  				}
  			}
  			fprintf(ofp, "To: %s\n", rcbuf);
  			fflush(ofp);

--- 483,493 -----
  					i = 1;
  					goto again;
  				}
+ 				/* Strip off all but first word, to avoid
+ 				 * the full name (Joe Blow). */
+ 				ptr = index(rcbuf, ' ');
+ 				if (ptr)
+ 					*ptr = 0;
  			}
  			fprintf(ofp, "To: %s\n", rcbuf);
  			fflush(ofp);
***************
*** 446,452
  				*ptr1 = *ptr2;
  			}
  			*ptr1 = '\0';
! 			sprintf(bfr, "%s %s", MAILER, address);
  			system(bfr);
  			break;
  

--- 497,504 -----
  				*ptr1 = *ptr2;
  			}
  			*ptr1 = '\0';
! 			sprintf(rcbuf, MAILER, hptr->title);
! 			sprintf(bfr, "%s %s", rcbuf, address);
  			system(bfr);
  			break;
  
***************
*** 557,565
  
  		/* follow-up article */
  		case 'f':
! 			tfilename = h.title;
! 			ptr2 = h.nbuf;
! 			ptr3 = h.ident;
  			if (*bptr == '-') {
  				if (*hbuf1.title && *hbuf1.nbuf) {
  					tfilename = hbuf1.title;

--- 609,615 -----
  
  		/* follow-up article */
  		case 'f':
! 			hptr = &h;
  			if (*bptr == '-') {
  				hptr = &hbuf1;
  				bptr++;
***************
*** 561,571
  			ptr2 = h.nbuf;
  			ptr3 = h.ident;
  			if (*bptr == '-') {
! 				if (*hbuf1.title && *hbuf1.nbuf) {
! 					tfilename = hbuf1.title;
! 					ptr2 = hbuf1.nbuf;
! 					ptr3 = hbuf1.ident;
! 				}
  				bptr++;
  			}
  			fprintf(ofp, "Posting followup article to network.  (To abort press DEL.)\n");

--- 611,617 -----
  		case 'f':
  			hptr = &h;
  			if (*bptr == '-') {
! 				hptr = &hbuf1;
  				bptr++;
  			}
  			tfilename = hptr->title;
***************
*** 568,573
  				}
  				bptr++;
  			}
  			fprintf(ofp, "Posting followup article to network.  (To abort press DEL.)\n");
  			fprintf(ofp, "Please use reply ('r') instead unless your article is of general interest.\n");
  			launder(ptr2);

--- 614,627 -----
  				hptr = &hbuf1;
  				bptr++;
  			}
+ 			tfilename = hptr->title;
+ 			ptr2 = hptr->nbuf;
+ 			folbuf[0] = 0;
+ 			if (hptr->followid) {
+ 				strcpy(folbuf, hptr->followid);
+ 				strcat(folbuf, " ");
+ 			}
+ 			strcat(folbuf, hptr->ident);
  			fprintf(ofp, "Posting followup article to network.  (To abort press DEL.)\n");
  			fprintf(ofp, "Please use reply ('r') instead unless your article is of general interest.\n");
  			launder(ptr2);
***************
*** 575,581
  				bptr++;
  			fprintf(ofp, "Title: ");
  			if (*bptr == '\0') {
! 				sprintf(bfr, "%s -F %s -n %s -t \'", INEWS, ptr3, ptr2);
  				if (strncmp(tfilename, "Re: ", 4)) {
  					strcat(bfr, "Re: ");
  					fprintf(ofp, "Re: ");

--- 629,635 -----
  				bptr++;
  			fprintf(ofp, "Title: ");
  			if (*bptr == '\0') {
! 				sprintf(bfr, "%s -D -F '%s' -n %s -t \'", INEWS, folbuf, ptr2);
  				if (strncmp(tfilename, "Re: ", 4)) {
  					strcat(bfr, "Re: ");
  					fprintf(ofp, "Re: ");
***************
*** 597,603
  			}
  			*ptr1 = '\0';
  			hascaught = 0;
! 			signal(SIGINT, catchintr);
  			fprintf(ofp, "Hit <return> to continue, DEL to abort: ");
  			fflush(ofp);
  			gets(edcmdbuf);

--- 651,657 -----
  			}
  			*ptr1 = '\0';
  			hascaught = 0;
! 			oldsig = (char *) signal(SIGINT, catchintr);
  			fprintf(ofp, "Hit <return> to continue, DEL to abort: ");
  			fflush(ofp);
  			gets(edcmdbuf);
***************
*** 601,607
  			fprintf(ofp, "Hit <return> to continue, DEL to abort: ");
  			fflush(ofp);
  			gets(edcmdbuf);
! 			signal(SIGINT, SIG_IGN);
  			if (hascaught)
  				break;
  

--- 655,661 -----
  			fprintf(ofp, "Hit <return> to continue, DEL to abort: ");
  			fflush(ofp);
  			gets(edcmdbuf);
! 			signal(SIGINT, oldsig);
  			if (hascaught)
  				break;
  			if (recording(hptr->nbuf, 0))
***************
*** 604,609
  			signal(SIGINT, SIG_IGN);
  			if (hascaught)
  				break;
  
  			ed = getenv("EDITOR");
  			if (ed) {

--- 658,665 -----
  			signal(SIGINT, oldsig);
  			if (hascaught)
  				break;
+ 			if (recording(hptr->nbuf, 0))
+ 				break;
  
  			ed = getenv("EDITOR");
  			if (ed) {
***************
*** 676,682
  				break;
  			}
  			fprintf(ofp, "(n)ext re(p)rint (w)rite (q)uit (r)eply\
!  (c)ancel -[n] +[n] (f)ollowup (N)ext\n");
  			break;
  		}
  	}

--- 732,738 -----
  				break;
  			}
  			fprintf(ofp, "(n)ext re(p)rint (w)rite (q)uit (r)eply\
!  (c)ancel -[n] +[n] (f)ollowup (N)ext (u)nsubscribe (v)ersion\n");
  			break;
  		}
  	}
***************
*** 793,799
  		pclose (ufp);
  	else
  		fclose(ufp);
! 	if (isnew && !isprogram)
  		printf("%s: %s\n", to, isnew ? "New file": "Appended");
  }
  

--- 849,855 -----
  		pclose (ufp);
  	else
  		fclose(ufp);
! 	if (!isprogram)
  		printf("%s: %s\n", to, isnew ? "New file": "Appended");
  }
  
***************
*** 925,931
  	fclose(ifp);
  	fclose(ofp);
  	if (*sp->s_xmit == '\0')
! 		sprintf(bfr, "uux - -r %s\\!rnews < %s", sp->s_name, TRANS);
  	else
  		sprintf(bfr, "(%s) < %s", sp->s_xmit, TRANS);
  	fwait(fsubr(pshell, bfr, (char *)NULL));

--- 981,987 -----
  	fclose(ifp);
  	fclose(ofp);
  	if (*sp->s_xmit == '\0')
! 		sprintf(bfr, DFTXMIT, sp->s_name, TRANS);
  	else
  		sprintf(bfr, "(%s) < %s", sp->s_xmit, TRANS);
  	fwait(fsubr(pshell, bfr, (char *)NULL));
diff -c -r 2.6/src/rextern.c 2.7/src/rextern.c
*** 2.6/src/rextern.c	Mon Mar 22 20:23:46 1982
--- 2.7/src/rextern.c	Tue Jun  1 08:25:29 1982
***************
*** 2,8
   * rextern - external definitions for readnews
   */
  
! static char *SccsId = "@(#) rextern.c	2.1	2/23/82";
  
  #include "rparams.h"
  

--- 2,8 -----
   * rextern - external definitions for readnews
   */
  
! static char *SccsId = "@(#) rextern.c	2.2	6/1/82";
  
  #include "rparams.h"
  
***************
*** 35,41
  int	savmask;			/* old umask			*/
  int	mode;				/* mode of news program		*/
  struct hbuf header;			/* general-use header structure	*/
! char	bfr[BUFLEN];			/* general-use scratch area	*/
  char	username[BUFLEN];		/* user's login name		*/
  char	userhome[BUFLEN];		/* user's home directory	*/
  char	*SPOOL = SPOOLDIR";		/* spool directory		*/

--- 35,41 -----
  int	savmask;			/* old umask			*/
  int	mode;				/* mode of news program		*/
  struct hbuf header;			/* general-use header structure	*/
! char	bfr[LBUFLEN];			/* general-use scratch area	*/
  char	username[BUFLEN];		/* user's login name		*/
  char	userhome[BUFLEN];		/* user's home directory	*/
  char	*SPOOL = SPOOLDIR";		/* spool directory		*/
***************
*** 63,68
  int	bit, obit, readmode = NEXT;
  int	defexp = FALSE;		/* set if def. expiration date used */
  int	actdirect = FORWARD;	/* read direction in ACTIVE file */
  struct stat statbuf;
  #ifndef SHELL
  char	*SHELL;

--- 63,70 -----
  int	bit, obit, readmode = NEXT;
  int	defexp = FALSE;		/* set if def. expiration date used */
  int	actdirect = FORWARD;	/* read direction in ACTIVE file */
+ int	rcreadok = FALSE;	/* NEWSRC has been read OK */
+ int	zapng = FALSE;		/* ! out this newsgroup on next updaterc */
  struct stat statbuf;
  #ifndef SHELL
  char	*SHELL;
diff -c -r 2.6/src/rfuncs.c 2.7/src/rfuncs.c
*** 2.6/src/rfuncs.c	Sun Apr 18 18:02:25 1982
--- 2.7/src/rfuncs.c	Tue Jun  1 08:25:30 1982
***************
*** 2,8
   * rfuncs - functions for readnews.
   */
  
! static char *SccsId = "@(#) rfuncs.c	2.5	4/18/82";
  
  #include "rparams.h"
  

--- 2,8 -----
   * rfuncs - functions for readnews.
   */
  
! static char *SccsId = "@(#) rfuncs.c	2.6	6/1/82";
  
  #include "rparams.h"
  
***************
*** 54,59
  	register char *ptr, punct = ',';
  	register int cur = 0, i;
  	int next = 0;
  
  	if (*groupdir)
  		updaterc();

--- 54,60 -----
  	register char *ptr, punct = ',';
  	register int cur = 0, i;
  	int next = 0;
+ 	char oldptr;
  
  	if (*groupdir)
  		updaterc();
***************
*** 58,64
  	if (*groupdir)
  		updaterc();
  	sprintf(groupdir, "%s/.%s", SPOOL, name);
! 	if (stat(groupdir, &statbuf))
  		return 1;
  	last = 1;
  	strcpy(groupdir, name);

--- 59,66 -----
  	if (*groupdir)
  		updaterc();
  	sprintf(groupdir, "%s/.%s", SPOOL, name);
! 	if (stat(groupdir, &statbuf)) {
! 		groupdir[0] = 0;
  		return 1;
  	}
  	last = 1;
***************
*** 60,65
  	sprintf(groupdir, "%s/.%s", SPOOL, name);
  	if (stat(groupdir, &statbuf))
  		return 1;
  	last = 1;
  	strcpy(groupdir, name);
  	for (i = 0; i <= line; i++) {

--- 62,68 -----
  	if (stat(groupdir, &statbuf)) {
  		groupdir[0] = 0;
  		return 1;
+ 	}
  	last = 1;
  	strcpy(groupdir, name);
  	for (i = 0; i <= line; i++) {
***************
*** 65,71
  	for (i = 0; i <= line; i++) {
  		strcpy(rcbuf, rcline[i]);
  		ptr = rcbuf;
! 		while (*ptr != ':' && *ptr)
  			ptr++;
  		if (*ptr) {
  			*ptr = '\0';

--- 68,74 -----
  	for (i = 0; i <= line; i++) {
  		strcpy(rcbuf, rcline[i]);
  		ptr = rcbuf;
! 		while (*ptr != ':' && *ptr != '!' && *ptr)
  			ptr++;
  		if (*ptr) {
  			oldptr = *ptr;
***************
*** 68,73
  		while (*ptr != ':' && *ptr)
  			ptr++;
  		if (*ptr) {
  			*ptr = '\0';
  			if (!strcmp(rcbuf, name)) {
  				sprintf(rcbuf, "%s,%ld", ++ptr, statbuf.st_size+1L);

--- 71,77 -----
  		while (*ptr != ':' && *ptr != '!' && *ptr)
  			ptr++;
  		if (*ptr) {
+ 			oldptr = *ptr;
  			*ptr = '\0';
  			if (!strcmp(rcbuf, name)) {
  				if (oldptr == '!') {
***************
*** 70,75
  		if (*ptr) {
  			*ptr = '\0';
  			if (!strcmp(rcbuf, name)) {
  				sprintf(rcbuf, "%s,%ld", ++ptr, statbuf.st_size+1L);
  				goto skip;
  			}

--- 74,83 -----
  			oldptr = *ptr;
  			*ptr = '\0';
  			if (!strcmp(rcbuf, name)) {
+ 				if (oldptr == '!') {
+ 					groupdir[0] = 0;
+ 					return 1;
+ 				}
  				sprintf(rcbuf, "%s,%ld", ++ptr, statbuf.st_size+1L);
  				goto skip;
  			}
***************
*** 113,119
  	xxit(0);
  }
  
! Mail() {
  	register FILE *fp = NULL, *ofp;
  	struct hbuf h;
  	register char *ptr;

--- 121,128 -----
  	xxit(0);
  }
  
! Mail()
! {
  	register FILE *fp = NULL, *ofp;
  	struct hbuf h;
  	register char *ptr;
***************
*** 191,197
  }
  #endif
  
! updaterc() {
  	register int cur = 1,next = 1, i;
  	register char *ptr;
  

--- 200,207 -----
  }
  #endif
  
! updaterc()
! {
  	register int cur = 1,next = 1, i;
  	register char *ptr;
  	char oldptr;
***************
*** 194,199
  updaterc() {
  	register int cur = 1,next = 1, i;
  	register char *ptr;
  
  	sprintf(rcbuf, "%s: ", groupdir);
  again:

--- 204,210 -----
  {
  	register int cur = 1,next = 1, i;
  	register char *ptr;
+ 	char oldptr;
  
  	sprintf(rcbuf, "%s%c ", groupdir, zapng ? '!' : ':');
  
***************
*** 195,201
  	register int cur = 1,next = 1, i;
  	register char *ptr;
  
! 	sprintf(rcbuf, "%s: ", groupdir);
  again:
  	ptr = &rcbuf[strlen(rcbuf)];
  	while (get(next))

--- 206,214 -----
  	register char *ptr;
  	char oldptr;
  
! 	sprintf(rcbuf, "%s%c ", groupdir, zapng ? '!' : ':');
! 
! 	zapng = FALSE;
  again:
  	ptr = &rcbuf[strlen(rcbuf)];
  	while (get(next))
***************
*** 213,219
  		sprintf(ptr, "%d-%d,", cur, next-1);
  skip:
  	if ((long) next > statbuf.st_size) {
! 		if (index(rcbuf, ',') == NULL)
  			return;
  		ngdel(rcbuf);
  		ptr = index(rcbuf, ' ');

--- 226,234 -----
  		sprintf(ptr, "%d-%d,", cur, next-1);
  skip:
  	if ((long) next > statbuf.st_size) {
! 		if (index(rcbuf, ',') != NULL)
! 			ngdel(rcbuf);
! 		else if (index(rcbuf, '!') == NULL)
  			return;
  		ptr = index(rcbuf, ' ');
  		ptr--;
***************
*** 215,221
  	if ((long) next > statbuf.st_size) {
  		if (index(rcbuf, ',') == NULL)
  			return;
- 		ngdel(rcbuf);
  		ptr = index(rcbuf, ' ');
  		*ptr = '\0';
  		for (i = 0; i <= line; i++)

--- 230,235 -----
  			ngdel(rcbuf);
  		else if (index(rcbuf, '!') == NULL)
  			return;
  		ptr = index(rcbuf, ' ');
  		ptr--;
  		oldptr = *ptr;
***************
*** 217,223
  			return;
  		ngdel(rcbuf);
  		ptr = index(rcbuf, ' ');
! 		*ptr = '\0';
  		for (i = 0; i <= line; i++)
  			if (!strncmp(rcbuf, rcline[i], strlen(rcbuf))) {
  				*ptr = ' ';

--- 231,240 -----
  		else if (index(rcbuf, '!') == NULL)
  			return;
  		ptr = index(rcbuf, ' ');
! 		ptr--;
! 		oldptr = *ptr;
! 		ptr[0] = ':';
! 		ptr[1] = '\0';
  		for (i = 0; i <= line; i++)
  			if (!strncmp(rcbuf, rcline[i], strlen(rcbuf))) {
  				ptr[0] = oldptr;
***************
*** 220,226
  		*ptr = '\0';
  		for (i = 0; i <= line; i++)
  			if (!strncmp(rcbuf, rcline[i], strlen(rcbuf))) {
! 				*ptr = ' ';
  				rcline[i] = realloc(rcline[i], strlen(rcbuf) + 1);
  				if (rcline[i] == NULL)
  					xerror("Cannot realloc");

--- 237,244 -----
  		ptr[1] = '\0';
  		for (i = 0; i <= line; i++)
  			if (!strncmp(rcbuf, rcline[i], strlen(rcbuf))) {
! 				ptr[0] = oldptr;
! 				ptr[1] = ' ';
  				rcline[i] = realloc(rcline[i], strlen(rcbuf) + 1);
  				if (rcline[i] == NULL)
  					xerror("Cannot realloc");
***************
*** 229,235
  			}
  		if (++line > LINES)
  			xerror("Too many newsgroups\n");
! 		*ptr = ' ';
  		if ((rcline[line] = malloc(strlen(rcbuf) + 1)) == NULL)
  			xerror("Not enough memory");
  		strcpy(rcline[line], rcbuf);

--- 247,254 -----
  			}
  		if (++line > LINES)
  			xerror("Too many newsgroups\n");
! 		ptr[0] = oldptr;
! 		ptr[1] = ' ';
  		if ((rcline[line] = malloc(strlen(rcbuf) + 1)) == NULL)
  			xerror("Not enough memory");
  		strcpy(rcline[line], rcbuf);
***************
*** 294,299
  	exit(status);
  }
  
  select(hp)
  register struct hbuf *hp;
  {

--- 313,321 -----
  	exit(status);
  }
  
+ /*
+  * Return TRUE if the user has not ruled out this article.
+  */
  select(hp)
  register struct hbuf *hp;
  {
***************
*** 303,308
  		return FALSE;
  	if (index(hp->nbuf, ',') && seenbefore(hp->ident))
  		return FALSE;
  	return TRUE;
  }
  

--- 325,332 -----
  		return FALSE;
  	if (index(hp->nbuf, ',') && seenbefore(hp->ident))
  		return FALSE;
+ 	if (fflag && isfol(hp))
+ 		return FALSE;
  	return TRUE;
  }
  
***************
*** 304,309
  	if (index(hp->nbuf, ',') && seenbefore(hp->ident))
  		return FALSE;
  	return TRUE;
  }
  
  /*

--- 328,346 -----
  	if (fflag && isfol(hp))
  		return FALSE;
  	return TRUE;
+ }
+ 
+ /*
+  * Return TRUE if this article is a followup to something.
+  */
+ isfol(hp)
+ register struct hbuf *hp;
+ {
+ 	if (hp->followid[0])
+ 		return TRUE;
+ 	if (strncmp(hp->title, "Re:", 3) == 0)
+ 		return TRUE;
+ 	return FALSE;
  }
  
  /*
diff -c -r 2.6/src/rparams.h 2.7/src/rparams.h
*** 2.6/src/rparams.h	Mon Mar 22 20:23:49 1982
--- 2.7/src/rparams.h	Tue Jun  1 08:25:33 1982
***************
*** 2,8
   * rparams.h - parameters for readnews, rfuncs, and readr.
   */
  
! static char *Rparams = "@(#) rparams.h	2.1	2/23/82";
  
  #include "params.h"
  

--- 2,8 -----
   * rparams.h - parameters for readnews, rfuncs, and readr.
   */
  
! static char *Rparams = "@(#) rparams.h	2.2	6/1/82";
  
  #include "params.h"
  
***************
*** 18,23
  #define xflag	options[8].flag
  #define hflag	options[9].flag
  #define Mflag	options[10].flag
  
  #define	NEXT	0
  #define SPEC	1

--- 18,24 -----
  #define xflag	options[8].flag
  #define hflag	options[9].flag
  #define Mflag	options[10].flag
+ #define fflag	options[11].flag
  
  #define	NEXT	0
  #define SPEC	1
***************
*** 49,55
  extern time_t	atime;
  extern struct stat statbuf;
  extern struct optable *optpt, options[];
! extern int	actdirect;
  
  /* macros */
  #define get(i)	(bitmap[(i-1) >> 3] & (1 << (i-1) % 8))

--- 50,56 -----
  extern time_t	atime;
  extern struct stat statbuf;
  extern struct optable *optpt, options[];
! extern int	actdirect, rcreadok, zapng;
  
  /* macros */
  #define get(i)	(bitmap[(i-1) >> 3] & (1 << (i-1) % 8))