Path: utzoo!utstat!helios.physics.utoronto.ca!jarvis.csri.toronto.edu!neat.cs.toronto.edu!lamy Newsgroups: news.software.b From: lamy@ai.utoronto.ca (Jean-Francois Lamy) Subject: Re: Cnews remote execution Message-ID: <89Dec7.102844est.2236@neat.cs.toronto.edu> References: <4719@sater.cs.vu.nl> <1989Dec6.165959.985@utzoo.uucp> Date: 7 Dec 89 15:29:16 GMT sater@cs.vu.nl (Hans van Staveren) writes: > If you NFS mount >your /usr/spool/news from a machine where people are not allowed to >execute commands, it would be much nicer if you could easily set it >up to use NNTP to post articles... henry@utzoo.uucp (Henry Spencer) writes: >gotten too involved with it. Possibly the simplest method would be to >arrange a mailing address on the forbidden machine which feeds into >the news system. We are exactly in that position here (the news partition is mounted by 140 machines in 7 (closely knit but independent) subdomains. The following script is what we use as both the "inews" invoked by the NNTP server and as the script invoked by a "feednews" mail alias. The inews on the clients is the NNTP inews (modified to make sure that a Path: header is added if missing). All postings actually take place on the news server and the script tries to handle moderated newsgroups properly wrt return addresses and the like. Jean-Francois Lamy lamy@ai.utoronto.ca, uunet!ai.utoronto.ca!lamy AI Group, Department of Computer Science, University of Toronto, Canada M5S 1A4 ------------------------------------------------------------------------------ #! /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" ). Mail headers inappropriate for # news will be stripped/transformed appropriately. # # 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. We post to non-moderated newsgroups, and deal with # Control: messages appropriately. # # We assume that the From: line can be trusted. A Path: line will be # trusted if present. If not, one will be made up from mail information # if available, and used unless posting an approved message to a moderated # newsgroup (since that would prevent the posting site from seeing it). # The path data will also set the error-return address of the message, # for better or for worse. # # remotely derived from code by Geoff Collyer, C news alpha release # heavily(!) reworked for CSRI/ANT environment by Jean-Francois Lamy # (lamy@ai.utoronto.ca) #exec >> /tmp/jfl 2>&1 #echo '' #date # =()<. ${NEWSCONFIG-@@}>()= . ${NEWSCONFIG-/news/bin/config} PATH=/local/bin:$NEWSCTL/bin:$NEWSBIN:$NEWSBIN/relay:$NEWSPATH export PATH umask $NEWSUMASK # fix according to your site. hostname=`hostname` # the usenet name of your site host="$hostname.toronto.edu" # if $hostname is not absolute date=`date` defdate="`set \`date -u\`; echo $3 $2 \`echo $6 | sed 's/^..//'\` $4 $5`" defmsgid="`set $date; echo \<$6$2$3.\`echo $4 | tr -d :\`.$$@$host\>`" input=/tmp/in$$in # uncensored input inhdrs=/tmp/in$$hdr # headers after censoring inbody=/tmp/in$$body # body after message censart=/tmp/in$$cens # article with censored headers nglist=/tmp/in$$act # active file entries for newsgroups indefs=/tmp/in$$defs # shell variable definitions, extracted from message. logfile=/news/log/inews.log rmlist='/tmp/in'$$'*' # programs relaynews="relaynews -r" sendmail='/usr/lib/sendmail -t' # articles plainly mailed to moderators grep=ngrep modgrep=egrep # use look if $NEWSCTL/mailpaths file is kept sorted. # (remove blank and tab in regular expression used below) trap 'rm -f $rmlist; echo '.' >>$logfile' 0 1 2 3 15 # don't leave a mess. echo -n $date \[$$\] \(`whoami`\) >> $logfile # capture incoming news in case inews fails if cat >>$input; then : got it. else echo "$0: lost news; cat returned status $?" >&2 exit 1 fi echo -n "; " >>$logfile # Separate header from body, mangling headers as we go. awk ' # pass 1 - note presence | absence of certain headers, store body. BEGIN { body = 0 ; skipping = 0 ; received = 0 } body == 1 { print > "'$inbody'" ; next } /^[ \t]*$/ { body = 1 ; print > "'$inbody'" ; next } # don-t bother with various mail headers /^To:|^X-To:|^Cc:|^Bcc:|^Apparently-To:|^Original-To:/ {skipping = 1 ; next } /^Resent-*:/ { skipping = 1; next } # Normally only one of the following would be present (Path: if coming via # NNTP, From_ via mail. Return-Path is unlikely). /^From / { hdrval["Path:"] = $2 ; next } /^Return-Path:/ { hdrval["Path:"] = $2 ; next } /^Path:/ { hdrval["Path:"] = $2 ; next } /^Message-Id:/ { $1 = "Message-ID:" } # a header keyword: remember it and its value. /^[^\t ]*:/ { skipping = 0; received = 0 ; keyword=$1 ; if ( hdrval[$1] == "" ) hdrval[$1] = $0 else # some headers can be repeated hdrval[keyword] = hdrval[keyword] "\n" $0 } # a continuation: concatenate this line to the value !/^[^\t ]*:/ { if ( ! skipping ) hdrval[keyword] = hdrval[keyword] "\n" $0 } # pass 2 - deduce & omit & emit headers END { subj = "Subject:"; path = "Path:" ctl = "Control:"; date = "Date:" ng = "Newsgroups:"; from = "From:" msgid = "Message-ID:"; org = "Organization:" typo = "Message-Id:"; distr = "Distribution:" rcvd = "Received:"; appr = "Approved:" # fill-in some headers if (hdrval[msgid] == "") hdrval[msgid] = msgid " " "'"$defmsgid"'" # force GMT format hdrval[date] = date " " "'"$defdate"'" # nuke others distworld = distr " world" if (hdrval[distr] == distworld) hdrval[distr] = "" # turn Subject: cmsg into a proper Control: header. if (substr(hdrval[subj],1,14) == "Subject: cmsg ") { hdrval[ctl] = ctl " " substr(hdrval[subj],15) hdrval[subj] = substr(hdrval[subj],1,9) substr(hdrval[subj],15) } # warn if no Newsgroups: if (hdrval[ng] == "") print "'$0': no Newsgroups: header." | "cat >&2" else { print "allngs=" q hdrval[ng] q > "'$indefs'" hdrval[ng] = "" } # write out various header values so the shell can read them if (hdrval[ctl] != "") { print "ctrl=" q hdrval[ctl] q > "'$indefs'" hdrval[ctl] = "" } if (hdrval[path] != "") { print "path=" q hdrval[path] q > "'$indefs'" hdrval[path] = "" } if (hdrval[appr] != "") { print "appr=" q hdrval[appr] q > "'$indefs'" } if (hdrval[rcvd] != "") { print "rcvd=" q hdrval[rcvd] q > "'$indefs'" hdrval[rcvd] = "" } # Output headers common to news and mail, starting with From: if (hdrval[from] != "") { print hdrval[from] hdrval[from] = "" } # have pity on readers: put Subject: next if (hdrval[subj] != "") { print hdrval[subj] hdrval[subj] = "" } # print misc. headers in random order, unless they are empty. for (i in hdrval) if (hdrval[i] != "" && hdrval[i] != i " ") print hdrval[i] } ' q=\' $input > $inhdrs # swallow what we've just learned in the awk script . $indefs echo -n $path: $allngs >> $logfile # produce list of newsgroups for validation purposes if test "$ctrl" ; then echo "control" > $nglist # a dreadful hack around all.all.ctl else # keep only newsgroups in active; something else ought to have # complained about that by now. egrep "^(` echo $allngs | sed \ -e 's/^Newsgroups:[ ]*//' \ -e 's/ //' \ -e 's/\./\\\\./g' \ -e 's/+/\\\\+/g' \ -e 's/,/ |/g' \ -e 's/$/ /'`)" $NEWSCTL/active >$nglist fi # sift through newsgroups, gathering moderators # Whether cross-posting to several mailing lists is allowed # is a matter of local policy; uncomment code near end of loop to prevent. exec < $nglist while read ng high low flag ; do ngbak=$ng case "$flag" in y) newsgroups=${newsgroups+$newsgroups,}$ng ;; m) if test "$appr" ; then # just post normally newsgroups=${newsgroups+$newsgroups,}$ng else # no Approved: add moderator to list of mail recipients while true ; do r=`$modgrep "$ng[ ]" $NEWSCTL/mailpaths` if test "$r" ; then set $r moderator=$2 break elif test "$ng" != "internet" ; then # people should just have "all %s@sitename", but since # the docs posted to news.admin talk about backbone and # internet, we suffer through that too. ng=`echo $ng|sed -e 's/.*\..*/&all/' \ -e 's/^all$/backbone/' \ -e 's/^backbone$/internet/'` else echo "$0: no moderator found for '$ng'" >&2 exit 64 # bad usage message. fi done # field the %s feature ngbak=`echo $ngbak | tr '.' '-'` moderator=`echo $moderator | sed -e "s/%s/$ngbak/"` modroute=${modroute+$modroute,}$moderator # enforce restricted usage (mail to first moderator, don't post # article to normal newsgroups). Uncomment next two lines to use. # newsgroups="" # break fi ;; n|*) if test "$ctrl" ; then newsgroups=`echo $allngs|sed -e 's/Newsgroups:[ ]*//'` else echo "$0: Posting to $ng is not allowed." >&2 exit 64 # sendmail/Zmailer "bad usage" message fi ;; esac done if [ "$newsgroups" ] ; then # cook-up the news-specific headers. Path: is omitted if we are # posting to a moderated newsgroup, as this would prevent the site # it was mailed from from seeing the message in the newsgroup. if test "$appr" ; then if test "$ctrl" ; then : else path="devnull" fi fi cat - $inhdrs </From: \2 \(\1\)/' \ -e 's/:[ ]*/: /' \ -e "\$r $inbody" | tr -d '\1-\7\13\14\16-\37' >$censart if $relaynews <$censart then echo -n " relaynews ok" >> $logfile else status=$? echo "$0: article could not be posted (relaynews status $status)" >&2 echo "$0: failed news in `hostname`:$input " >&2 echo " relaynews status $status" >> $logfile exit $status fi fi if [ "$modroute" ] ; then # mail article to the moderator(s). cat - $inhdrs </From: \2 \(\1\)/' \ -e 's/:[ ]*/: /' \ -e '/^Message-ID:/d' \ -e "\$r $inbody" | tr -d '\1-\7\13\14\16-\37' >$censart $sendmail -f$path <$censart echo -n " resent to '$modroute'" >>$logfile fi