#! /bin/sh -
#
# server_inews 
#
#   Post article read on stdin.  Arguments are ignored. 
#   Meant to be invoked by an NNTP server or by a sendmail/zmailer alias (e.g.
#   feednews: "|/news/bin/server_inews" )
#
#   We assume that the From: line can be trusted and if a Path: line is not
#   present we fake one using the mail path so broken users that rely on it
#   get a reply address that way.
#
#   The message is mailed to moderators of moderated newsgroups mentioned on
#   the Newsgroups: line, unless a proper Approved: line is seen, in which
#   case we post directly.
#
# original code from Geoff Collyer, C news alpha release
# heavily reworked for CSRI/ANT environment by Jean-Francois Lamy
#	(lamy@ai.toronto.edu)

NEWSCTL=${NEWSCTL-/usr/lib/news}
NEWSBIN=${NEWSBIN-/usr/lib/newsbin}
NEWSARTS=${NEWSARTS-/usr/spool/news}
PATH=$NEWSCTL:/usr/lib/news:$NEWSBIN:$NEWSBIN/relay:/bin:/usr/bin:/usr/ucb
export PATH

debug=''		# flags
exclusion=''

hostname=`hostname`

input=/tmp/in$$in      	# uncensored input
from=/tmp/in$$from      # return path extracted from From_ or Return-Path: line
inhdrs=/tmp/in$$hdr	# generated by tear: headers
inbody=/tmp/in$$body	# generated by tear: body
censart=/tmp/in$$cens   # article with censored headers
nglist=/tmp/in$$ngs     # newsgroups: raw list with commas
ngfile=/tmp/in$$ngc	# newsgroups, one per line
rtefile=/tmp/in$$rte    # route chosen for each moderated newsgroup
rmlist="$inhdrs $inbody $input $from\
        $censart $nglist $ngfile $modfile $rtefile"
				       
# articles plainly mailed to moderators
sendnews="/usr/lib/sendmail -t"

umask 2
trap '' 1 2 15         # ignore signals to avoid losing articles

# capture incoming news in case inews fails
   if cat >>$input; then
      : got it.
   else
      echo "$0: lost news; cat status $?" >&2
      exit 1
   fi


# We separate the header from the body.
   >>$inbody; >>$censart
   awk 'BEGIN			 { inbody = 0 }
   inbody != 0			 { print $0 >"'$inbody'"; next}
   inbody == 0 && /^$|^[ ][ \t]*$/ { inbody = 1; print "" >"'$inbody'"; next }
   inbody == 0			 { print $0 >"'$censart'" ; next }
   ' $input

# Extract information from From_ or Return-Path line so that we can give it
# back to the mailer (we want mail to the moderator to look as if it came from
# the originator himself).  We then mutate it into a Path: header.
# if there is a Path: header (e.g. if we are invoked from NNTP, we use that.
   sed -e '1s/^From \([^ ]*\) .*$/Path: \1/' \
       -e 's/^Return-Path: \([^ ]*\).*$/Path: \1/' \
       -e '/^Path: /{
		   s/^Path: \([^ ]*\).*$/\1/
		   s/.*'$hostname'[^!]*!//
		   w '$from'
		   s/^/Path: /
		   }' \
       -e '/^[ 	]*$/q'	<$censart >$inhdrs


# produce list of newsgroups
   sed -n '/^Newsgroups:[ ]/{
      s/^Newsgroups:[ ]*\(.*\)$/\1/p
      q
      }' <$inhdrs >$nglist

# control messages are special: newgroup messages belong to inexistent
# newsgroups (makes sense) and names with .ctl don't appear in the active file
# either.  We force a trailing .ctl on newsgroup names so that downstream
# sites can prevent control articles from getting on mail redistributions
#
# Remove tabs after : so that the rest of the world accepts our postings.
   read ng <$nglist
   if egrep "^Control:|^Subject: cmsg" $inhdrs >/dev/null ; then
       ( server_censor <$inhdrs |
	 sed -e '/^Newsgroups:/{
                  s/.ctl//g
		  s/,/.ctl,/g
		  s/$/.ctl/g
		  }' \
	      -e 's/^\([^:]*:\)[	 ]*/\1 /'
	 tr -d '\1-\7\13\14\16-\37' <$inbody
       ) >$censart
       relaynews -r <$censart
       rm $rmlist
       exit 0
   fi

# handle non control messages.  Unknown newsgroups are dropped, as per RFC1036
# Too bad if Pnews, postnews or the Zmailer router did not complain
egrep "^(` sed -e 's/\./\\\\./g' \
	       -e 's/+/\\\\+/g'  \
               -e 's/,/ |/g'     \
               -e 's/$/ /' <$nglist`)" \
   $NEWSCTL/active >$ngfile
exec <$ngfile
while read ng high low flag   # look at next group's active entry
do
   case "$flag" in
   n)
      echo "$0: $ng may not be posted to." >&2
      echo "$0: message not sent anywhere." >&2
      exit 64   # sendmail/Zmailer "bad usage" message
      ;;
   m)
      if grep -s '^Approved:[    ]' $inhdrs; then # just post normally
         approved=1
	 newsgroups=${newsgroups+$newsgroups,}$ng
      else # un-Approved: add moderator to list of recipients
	 # look for route for this group
	 while read ngpat route
	 do
	    # a dreadful B 2.11 hack: backbone|internet == all
	       case "$ngpat" in
	       backbone|internet) ngpat="all" ;;
	       esac
	    # we assume that mailpath file has proper wildcards at the
	    # end, i.e. we always exit via this break.
	       if (echo $ng $route| gngp -a "$ngpat" >/dev/null) ; then
		     echo $route >$rtefile
		     break
	       fi
	 done <$NEWSCTL/mailpaths

	 # add to list of moderators unless no moderator is found
	 # (local newsgroups are assumed to have a catch-all pattern
	 # to provoke errors)
         route=`cat $rtefile`
	 if [ "$route" = "error" ] ; then
	    echo "$0: no moderator found for news group '$ng'" >&2
	    echo "$0: message not sent anywhere." >&2
	    exit 64 # bad usage message.
	 else
	    modroute=${modroute+$modroute,}$route
	 fi
      fi
      ;;
   y)
      newsgroups=${newsgroups+$newsgroups,}$ng
      ;;
   esac
done

# $censart is used rather than a pipe to work around a bug in the 4.2
# sh which makes it sometimes return the wrong exit status

if [ "$modroute" ] ; then
   # mail article to the moderator(s)
   # Remove headers that may break mailers or cause loops.
   # strip invisible chars from body, a la B news
      ( sed -e '/^Newsgroups:/d' -e '/^Path:/d' \
	    -e '/^To:/d' -e '/^Cc:/d' < $inhdrs
	echo "To: ${modroute}"
	tr -d '\1-\7\13\14\16-\37' <$inbody
      ) >$censart
      $sendnews -f"`cat $from`" <$censart
fi

if [ "$newsgroups" ] ; then
   # feed article to news.  Put in cleaned-up newsgroups line (no remote
   # moderated newsgroups appear).  If a local user posts to a newsgroup with
   # a local moderator then the approved article does not get posted because
   # the news server is already in the path.  We fix that with a chain-saw,
   # pending resolution of the bug in the news relaying software...
   # strip invisible chars from body, a la B news
      ( server.censor <$inhdrs |
	sed ${approved+-e} ${approved+"s/^Path:.*$hostname!/Path: /"} \
	    -e "s/^Newsgroups:.*\$/Newsgroups: $newsgroups/" \
   	    -e 's/^\([^:]*:\)[	 ]*/\1 /'
	tr -d '\1-\7\13\14\16-\37' <$inbody
      ) >$censart

   if relaynews -r <$censart
   then
      rm -f $rmlist      # far out, it worked
      if [ -s $NEWSCTL/dig.twimc ]; then
	 $NEWSBIN/digestify $NEWSCTL/dig.twimc
      fi
      exit 0
   else
      status=$?
      echo "$0: article could not be posted (relaynews status $status)" >&2
      echo "$0: failed news in `hostname`:$input " >&2
      exit $status
   fi
else
   rm -f $rmlist
   exit 0
fi
