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