#! /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