#!/bin/csh -f
## adcomplain 3.104 29-Aug-97
## Bill McFadden
## billmc@rdrop.com
##
## The latest version of this file is available at:
## http://www.rdrop.com/users/billmc
## Please mail ideas and bug reports to billmc@rdrop.com.
##
## SYNOPSIS
##
## adcomplain [-c] [-f filename] [-m] [-q] [-v] [newsgroup]
##
## DESCRIPTION
## Composes and mails a complaint about inappropriate commercial use of
## Usenet/e-mail. Sends complaint to the offender and his/her provider
## by default, but destination is configurable. Can be used with as few
## as three keystrokes.
##
## A third-party forwarding service called Abuse.net is used for
## complaints to the offender's provider. This ensures that the best
## known complaint address is used. The first time you use Abuse.net,
## you will receive a message asking you to register. See www.abuse.net.
##
## This was created in the belief that a single, concise message is the
## most appropriate way to complain. Mail bombing (e-mailing megabytes
## of useless data) and public flaming (replying on Usenet, causing your
## complaint to be duplicated on every machine in the network) are
## discouraged.
##
## USAGE
## Pipe the Usenet posting or e-mail (use the -m option for e-mail)
## through this script. It will compose the message and display it for
## approval before mailing.
##
## You may supply a newsgroup name (or comma separated newsgroups list)
## as the last argument. If not supplied, the contents of the
## 'Newsgroups' header, if present, will be used. Note: Very long
## newsgroup lists can cause errors. The newsgroup name is not needed
## when using the -f and -m options.
##
## OPTIONS
## Any combination of options may be used together. For example, -c and
## -m may be used together to complain about a chain letter received via
## e-mail.
## -c
## Chain letter mode. Composes and mails a complaint about chain
## letters, such as Make Money Fast.
## -f filename
## Use the contents of the specified file as the complaint text.
## -m
## Mail mode. Composes and mails a complaint about junk e-mail.
## -q
## Quiet mode. Doesn't ask any questions except whether to send the
## message.
## -v
## Verbose mode. Diagnostic messages will be printed.
##
## INSTALLATION
## Must be installed on a Unix system.
##
## Type "echo $PATH" to list the directories in your search path.
##
## Go to one of those directories and save this script in a file named
## "adcomplain".
##
## Type "chmod +x adcomplain" to make it executable.
##
## Type "rehash" to add it to the search path.
##
## To test, send an e-mail message to yourself, save the message in a
## file, and type "adcomplain -m < file", where "file" is the file in
## which you saved the message.
##
## NEWSREADER CONFIGURATION
## rn (as well as trn and strn) users can put the following in their
## .rnmac file to map adcomplain to the 'a' key:
##
## a %(%m=[pa]?|adcomplain %C\n:a)
##
## In addition, rn users can complain about chain letters by mapping the
## 'A' key as follows:
##
## A %(%m=[pa]?|adcomplain -c\n:A)
##
## rn users can also customize the message based on the current newsgroup
## by using adcomplain's -f mode as shown in the following example:
##
## Z %(%m=[pa]?%(%C=aaa.forsale?|adcomplain -f aaa_complaint\n:%(%C=bbb.forsale?|adcomplain -f bbb_complaint\n:%(%C=ccc.forsale?|adcomplain -f ccc_complaint\n:%(%C=ddd.forsale?|adcomplain -f ddd_complaint\n:Z)))))
##
## When 'Z' is pressed, the above macro checks the newsgroup name, and if
## it matches one of four choices (aaa.forsale, bbb.forsale, ccc.forsale,
## ddd.forsale), uses a complaint message specific to that newsgroup.
## You can use it to complain about foreign postings in local newsgroups,
## for example (e.g., "aaa.forsale is for items for sale in the Podunk
## area.")
##
## nn users can put the following in their .nn/init file to map adcomplain
## to ctrl-A:
##
## map both ^A (
## :!! cat /dev/null > /tmp/junk$(USER)
## save-full "//tmp/junk$(USER)"
## :! echo; adcomplain $G < /tmp/junk$(USER)
## :!! rm -rf /tmp/junk$(USER)
## )
##
## tin users can type "|" at the article level to pipe the article into
## adcomplain. Type "adcomplain" when it asks for the command name.
##
set cc = $user
## CONFIGURATION SECTION ##
## this section lets you choose the default recipient(s) of the complaint
## 1 = poster only, 2 = provider only, 3 = both
set recipient = 2
## remove this section if you want a copy of the complaint sent to you
set cc
## remove this section to include a copy of the posting every time
## (ordinarily this is not done unless you choose to notify provider)
set noinclude
## remove this section if your mailer automatically adds your .signature
set addsig
## remove this section if you don't want to reject addresses from your domain
## this feature is intended to deal with messages forged to look as though
## they came from your system
set checkdomain
## this is the domain name of your system (e.g., "compuserve.com")
## if empty, the DOMAINNAME environment variable will be used, if defined
set mydomain = ""
## remove this section if your system uses the BSDI version of 'fmt'
## (this is indicated by the message text being incorrectly formatted)
set nobsdi
## this is the default name of the file to use for the complaint text
## if the file name is empty, the default text will be used
set textfile = ""
## this is the name of the mail utility (see sendmail(8) man page)
## type "which sendmail" to find out where sendmail is on your system
set mailcmd = "/usr/lib/sendmail -t"
## END OF CONFIGURATION SECTION ##
##
## THEORY OF OPERATION
## The program used to display the message prior to mailing is:
## $PAGER, if defined,
## otherwise, use more.
##
## The editor is:
## $VISUAL, if defined,
## otherwise, use $EDITOR, if defined,
## otherwise, use vi.
##
## The header parsing algorithm is described below:
##
## $subject
## Use contents of "Subject" header.
##
## $newsgroup
## Use command line argument, if present,
## otherwise, use contents of "Newsgroups" header.
## Insert spaces after commas, if any, separating newsgroup names.
##
## $poster
## Use contents of "NNTP-Posting-User" header, if present,
## otherwise, use contents of "Return-Path" header, if present,
## otherwise, use contents of "Reply-To" header, if present,
## otherwise, use contents of "From" header.
## Reject any $poster that does not contain a '.' and a '@' (i.e.,
## incomplete).
## Reject any $poster whose last field does not match any known
## top-level domain name.
## Reject any $poster whose domain matches user's domain, if enabled.
##
## $poster1
## Set to $poster.
## If $poster1 is of form "Name
", set to "address".
## If $poster1 is of form "(address)", set to "address".
## If $poster1 is of form "address(Name)", set to "address".
## Remove extra words, in case header is of form "address (Name)"
##
## $host
## Use last field of "Path" header, if present,
## otherwise, use next-to-last field of "Path" header, if present,
## otherwise, use second field of "Received: from" header, if present,
## otherwise, use first field of "Received: from" header, if present,
## otherwise, use contents of "NNTP-Posting-Host" header, if present,
## otherwise, use contents of "Message-ID" header, if present,
## otherwise, use contents of "Sender" header, if present,
## otherwise, use $poster.
## If $host is of form "", set to "id@host".
## If $host is of form "(id@host)", set to "id@host".
## If $host is of form "host(inet_address)", set to "host".
## If $host is of form "id@host", remove "id@" portion.
## Remove extra words, in case header is of form "address (Name)"
## Reject any $host that doesn't begin with a letter (e.g., an IP
## address).
## Reject any $host that does not contain a '.' (i.e., incomplete).
## Reject any $host whose last field does not match any known top-level
## domain name.
## Reject any $host whose domain matches user's domain, if enabled.
##
## $site
## If last field of $host >= 3 characters long (e.g., "com edu"),
## set $site to last two fields (e.g., "company.com" or "college.edu")
## unless three field version found in exceptions list,
## otherwise, set $site to last three fields (e.g., "canadian.site.ca")
## unless two field version found in exceptions list.
##
## $redirect
## Use redirection list entry, if present, that matches $site.
##
## $postmaster
## Use postmaster@$site.
##
## $complain_to
## Use contents of "X-Complain-To" header, if present,
## otherwise set to $site@abuse.net.
## Reject any $complain_to that does not contain a '.' and a '@' (i.e.,
## incomplete).
##
## If $poster is of form "user,id ",
## message will be addressed to $poster1 (i.e., "user.id@site"),
## otherwise, message will be addressed to $poster.
##
## parse command line options
while ( 1 )
switch( $1 )
case -c:
set chainmode
shift
breaksw
case -f:
shift
set textfile = "$1"
shift
breaksw
case -m:
set mailmode
shift
breaksw
case -q:
set quiet
shift
breaksw
case -v:
set verb
shift
breaksw
default:
break
endsw
end
## determine user's domain name
if ( $?checkdomain ) then
if ( "$mydomain" == "" && $?DOMAINNAME ) then
set mydomain = "$DOMAINNAME"
set site2 = `echo "$mydomain" | sed 's/.*\.\(.*\..*\)/\1/'`
set site3 = `echo "$mydomain" | sed 's/.*\.\(.*\..*\..*\)/\1/'`
if ( `echo "$mydomain" | sed 's/.*\.\(.*\)/\1/' | wc -c` > 3 ) then
if ( $?0 ) then
if ( `grep -ci "^# $site3" $0` == 0 ) then
set mydomain = "$site2"
else
set mydomain = "$site3"
endif
else
set mydomain = "$site2"
endif
else
if ( $?0 ) then
if ( `grep -ci "^# $site2" $0` == 0 ) then
set mydomain = "$site3"
else
set mydomain = "$site2"
endif
else
set mydomain = "$site3"
endif
endif
endif
if ( $?verb ) echo "adcomplain: your domain is '$mydomain'"
endif
if ( "$mydomain" == "" ) then
set mydomain = "#%"
endif
## copy original Usenet posting from stdin
set noglob
set dest = /tmp/$user-$$
cat >$dest-1
#sed '/^$/q' $dest-1 >$dest
awk 'length>0,length==0' $dest-1 >$dest
## parse headers
if ( $?verb ) echo "adcomplain: subject: checking 'Subject' header..."
set subject = `grep -i "Subject: " $dest | head -1`
set subject = "$subject[2-]"
if ( "$subject" == "" ) then
echo ""
echo "adcomplain: warning: subject not found"
echo ""
else
if ( $?verb ) echo "adcomplain: found, subject is '$subject'"
endif
if ( ! $?mailmode && "$textfile" == "" ) then
if ( $?verb ) echo "adcomplain: newsgroup: checking command line argument..."
set newsgroup = "$argv"
if ( "$newsgroup" == "" ) then
if ( $?verb ) echo "adcomplain: newsgroup: checking 'Newsgroups' header..."
set newsgroup = `grep -i "Newsgroups: " $dest | head -1`
set newsgroup = "$newsgroup[2-]"
endif
set newsgroup = `echo "$newsgroup" | sed 's/,/, /g'`
if ( "$newsgroup" == "" ) then
echo ""
echo "adcomplain: warning: no valid newsgroup name was found"
echo ""
set newsgroup = "(INSERT NEWSGROUP NAME HERE)"
echo -n "Was this a mail message instead of a Usenet posting? [y] "
set ans = "`head -1 .*/\1/'`
set poster1 = `echo "$poster1" | sed 's/^(\(.*\)).*/\1/'`
set poster1 = `echo "$poster1" | sed 's/(.*)//'`
set poster1 = "$poster1[1]"
set domain = `echo "$poster1" | sed 's/.*\.\(.*\)/\1/'`
if ( `echo "$poster1" | grep -c '\.'` != 0 && \
`echo "$poster1" | grep -c '@'` != 0 && \
`echo "$poster1" | grep -ci $mydomain\$` == 0 && \
`grep -ci "^###.* $domain" $0` != 0 ) break
endif
else
echo ""
echo "adcomplain: warning: no valid return address was found"
echo ""
set poster
set poster1
endif
end
if ( $?verb && "$poster" != "" ) \
echo "adcomplain: found, poster is '$poster'"
set complain_to
set host
set postmaster
if ( ! $?quiet || "$recipient" != "1" ) then
set search_patterns = ( path1 path2 rcvd NNTP-Posting-Host\
Message-ID Sender poster stop )
foreach pat ( $search_patterns )
if ( "$pat" != "stop" ) then
Try_Again:
switch ( "$pat" )
case "path1":
if ( $?mailmode ) breaksw
if ( $?verb ) echo "adcomplain: host: checking 'Path' header..."
set host1 = `grep -i "^Path: " $dest | head -1`
set host1 = "$host1[2-]"
set host = `echo "$host1" | sed 's/.*\!\(.*\)/\1/'`
breaksw
case "path2":
if ( $?mailmode ) breaksw
if ( $?verb ) echo "adcomplain: host: checking 'Path' header..."
set host = `echo "$host1" | sed 's/.*\!\(.*\)\!\(.*\)/\1/'`
set host = `echo "$host" | sed 's/\(.*\)\!\(.*\)/\1/'`
breaksw
case "rcvd":
set rcvd = `grep -i "^Received: from " $dest | tr [A-Z] [a-z]`
@ i = ( $#rcvd - 2 )
set host = ""
breaksw
case "rcvd1":
if ( $i < 1 ) then
set pat = ""
breaksw
endif
if ( $?verb ) echo "adcomplain: host: checking 'Received: from' header..."
set host1 = ( $rcvd[$i-] )
while ( $i && "$host1[1-2]" != "received: from" )
set host1 = ( $rcvd[$i-] )
@ i = ( $i - 1 )
end
if ( $#host1 >= 5 ) then
set host = "$host1[4-5]"
endif
breaksw
case "rcvd2":
if ( $?verb ) echo "adcomplain: host: checking 'Received: from' header..."
if ( $#host1 >= 3 ) then
set host = "$host1[3]"
endif
breaksw
case "rcvd3":
if ( $?verb ) echo "adcomplain: host: checking 'Received: ... by' header..."
set j = 4
while ( $j < $#host1 && "$host1[$j]" != "by" )
@ j = ( $j + 1 )
end
@ j = ( $j + 1 )
if ( $j <= $#host1 ) then
set host = "$host1[$j]"
endif
@ i = ( $i - 1 )
breaksw
case "poster":
if ( $?verb ) echo "adcomplain: host: trying poster..."
set host = "$poster"
breaksw
default:
if ( $?verb ) echo "adcomplain: host: checking '$pat' header..."
set host = `grep -i "$pat\: " $dest | head -1`
set host = "$host[2-]"
breaksw
endsw
if ( "$host" != "" ) then
set host = `echo "$host" | sed 's/.*<\(.*\)>.*/\1/'`
set host = `echo "$host" | sed 's/^(\(.*\)).*/\1/'`
set host = `echo "$host" | sed 's/(.*)//'`
set host = `echo "$host" | sed 's/.*@\(.*\)/\1/'`
if ( "$host" != "" ) then
set host = "$host[1]"
set domain = `echo "$host" | sed 's/.*\.\(.*\)/\1/'`
if ( `echo "$host" | grep -c '\.'` != 0 && \
`echo "$host" | grep -ci '^[a-z]'` != 0 && \
`echo "$host" | grep -ci $mydomain\$` == 0 && \
`grep -ci "^###.* $domain" $0` != 0 ) break
endif
endif
switch ( "$pat" )
case "rcvd":
case "rcvd3":
set pat = "rcvd1"
goto Try_Again
case "rcvd1":
set pat = "rcvd2"
goto Try_Again
case "rcvd2":
set pat = "rcvd3"
goto Try_Again
default:
breaksw
endsw
else
echo ""
echo "adcomplain: warning: no valid host name was found"
echo ""
set host
endif
end
Find_Site:
if ( $?verb && "$host" != "" ) echo "adcomplain: found, host is '$host'"
set site2 = `echo "$host" | sed 's/.*\.\(.*\..*\)/\1/'`
set site3 = `echo "$host" | sed 's/.*\.\(.*\..*\..*\)/\1/'`
if ( `echo "$host" | sed 's/.*\.\(.*\)/\1/' | wc -c` > 3 ) then
if ( $?0 ) then
if ( `grep -ci "^# $site3" $0` == 0 ) then
set site = "$site2"
else
set site = "$site3"
endif
else
set site = "$site2"
endif
else
if ( $?0 ) then
if ( `grep -ci "^# $site2" $0` == 0 ) then
set site = "$site3"
else
set site = "$site2"
endif
else
set site = "$site3"
endif
endif
if ( $?verb && "$site" != "" ) echo "adcomplain: site is '$site'"
if ( "$site" != "" ) then
if ( $?0 ) then
if ( $?verb ) \
echo "adcomplain: checking redirection list..."
set redirect = `grep -i "^# $site" $0 | head -1`
if ( $#redirect > 2 ) then
set host = `grep -i "$redirect[3]\: " $dest | head -1`
set host = "$host[2-]"
set host = `echo "$host" | sed 's/.*<\(.*\)>.*/\1/'`
set host = `echo "$host" | sed 's/^(\(.*\)).*/\1/'`
set host = `echo "$host" | sed 's/(.*)//'`
set host = `echo "$host" | sed 's/.*@\(.*\)/\1/'`
if ( "$host" != "" ) then
if ( $?verb ) echo "adcomplain: found, checking '$redirect[3]' header..."
set host = "$host[1]"
goto Find_Site
endif
endif
if ( $?verb ) echo "adcomplain: no redirection found, continuing..."
else
echo ""
echo "adcomplain: error: can't find adcomplain source file, unable to read redirection list"
echo ""
endif
endif
if ( "$site" != "" ) then
set postmaster = "postmaster@$site"
if ( $?verb ) \
echo "adcomplain: postmaster is '$postmaster'"
endif
set search_patterns = ( Complain-To stop )
foreach pat ( $search_patterns )
if ( "$pat" != "stop" ) then
if ( $?verb ) echo "adcomplain: complain_to: checking '$pat' header..."
set complain_to = `grep -i "$pat\: " $dest | head -1`
set complain_to = "$complain_to[2-]"
if ( `echo "$complain_to" | grep -c '\.'` != 0 && \
`echo "$complain_to" | grep -c '@'` != 0 ) break
else
if ( $?verb ) echo "adcomplain: complain_to: trying site name..."
if ( "$site" != "" ) then
set complain_to = "$site@abuse.net"
else
echo ""
echo "adcomplain: warning: no valid complaint address was found"
echo ""
set complain_to
endif
endif
end
set complain_to = `echo "$complain_to" | sed 's/ /, /g'`
if ( $?verb && "$complain_to" != "" ) \
echo "adcomplain: found, complain_to is '$complain_to'"
endif
rm -f $dest
## find out where to send message
if ( "$complain_to" == "" ) then
set recipient = 1
else
if ( "$poster" == "" ) then
set recipient = 2
else
if ( ! $?quiet ) then
echo "Send to:"
echo " 1 = $poster"
echo " 2 = $complain_to"
echo " 3 = both"
echo -n "Send to whom? [$recipient] "
set ans = "`head -1 $dest
if ( "$recipient" == "2" ) then
echo "advise this user to" >>$dest
endif
echo "discontinue posting unsolicited" >>$dest
echo "commercial advertisements to $newsgroup." >>$dest
echo "My site must pay to receive" >>$dest
echo "and store them." >>$dest
if ( ! $?quiet ) then
echo -n "Is '$subject' relevant to $newsgroup? [y] "
set ans = "`head -1 >$dest
echo "has nothing to do with" >>$dest
echo "$newsgroup." >>$dest
endif
endif
if ( "$recipient" != "2" ) then
echo "" >>$dest
echo "The biz.marketplace and ads" >>$dest
echo "newsgroup hierarchies" >>$dest
echo "are the correct places for" >>$dest
echo "commercial ads." >>$dest
echo "(Ads may be inappropriate in" >>$dest
echo "some biz newsgroups, so please" >>$dest
echo "check first.)" >>$dest
echo "For more information about" >>$dest
echo "Usenet etiquette," >>$dest
echo "see news.announce.newusers." >>$dest
endif
else
echo "Please" >$dest
if ( "$recipient" != "2" ) then
echo "don't" >>$dest
else
echo "advise this user not to" >>$dest
endif
echo "post these illegal chain letters." >>$dest
endif
if ( "$recipient" != "2" ) then
echo "" >>$dest
echo "Most text-based newsreaders will allow" >>$dest
echo "you to cancel a posting by finding your" >>$dest
echo "article and pressing 'C' or 'D'." >>$dest
echo "(Netscape users can select 'Cancel" >>$dest
echo "Message' in the Edit menu)." >>$dest
echo "If you need help, contact your" >>$dest
if ( "$postmaster" != "" ) then
echo "postmaster at <$postmaster>." >>$dest
else
echo "postmaster." >>$dest
endif
endif
else
if ( ! $?chainmode ) then
echo "Please" >$dest
if ( "$recipient" == "2" ) then
echo "advise this user to" >>$dest
endif
echo "discontinue sending unsolicited" >>$dest
echo "commercial advertisements to my e-mail" >>$dest
echo "address." >>$dest
echo "My site must pay to receive and store" >>$dest
echo "them." >>$dest
else
echo "Please" >$dest
if ( "$recipient" != "2" ) then
echo "don't" >>$dest
else
echo "advise this user not to" >>$dest
endif
echo "mail these illegal chain letters." >>$dest
endif
endif
echo "Thanks." >>$dest
if ( "$recipient" == "2" ) then
echo "" >>$dest
echo "Note: I have not contacted this user directly," >>$dest
echo "because I do not wish to be mailbombed," >>$dest
echo "threatened, or have my my e-mail address" >>$dest
echo "collected for commercial use." >>$dest
endif
else
if ( -e $textfile ) then
cat $textfile >$dest
else
echo "adcomplain: ${textfile}: no such file"
echo "adcomplain: (current directory is $cwd)"
endif
endif
echo "" >>$dest
## reformat message text
if ( $?nobsdi ) then
fmt -76 $dest >$dest-2
else
fmt 75 76 $dest >$dest-2
endif
rm -f $dest
mv $dest-2 $dest
## include copy of posting if needed
if ( ! $?noinclude || "$recipient" != "1" ) then
echo "--------forwarded message--------" >>$dest
cat $dest-1 >>$dest
echo "-----end of forwarded message-----" >>$dest
echo "" >>$dest
endif
rm -f $dest-1
## append signature if needed
if ( $?addsig && -e $HOME/.signature ) then
echo "-- " >>$dest
cat $HOME/.signature >>$dest
endif
## prepend message header
if ( "$recipient" == "2" ) then
echo "To: $complain_to" >$dest-1
else
if ( `echo "$poster" | grep -c ','` == 0 ) then
echo "To: $poster" >$dest-1
else
echo "To: $poster1" >$dest-1
endif
endif
if ( "$recipient" == "3" ) then
if ( "$cc" != "" ) set cc = ", $cc"
set cc = "$complain_to$cc"
endif
if ( "$cc" != "" ) echo "Cc: $cc" >>$dest-1
if ( "$recipient" == "2" ) then
echo "Subject: Abuse report ($subject)" >>$dest-1
else
echo "Subject: Re: $subject" >>$dest-1
endif
echo "" >>$dest-1
cat $dest >>$dest-1
rm -f $dest
mv $dest-1 $dest
## print copy of message on terminal
echo ""
if ( ! $?PAGER ) set PAGER = "more"
$PAGER $dest