#!/bin/csh -f

# "host  -l"  seems  broken  with  the  move to  the  new  DNS  server
# infrastructure (128.6.1.1) Also, previously simulated subdomains are
# now real.

# This script is a replacement for some functions...

# "host-l <subdomain>" gets info on the specified domain from 128.6.1.1.
# The default domain is rutgers.edu.  You can specify more than one domain.

# "host-l -r" gets info for rutgers.edu and any subdomain therein
# which uses the same nameservers as rutgers.edu.

switch (`uname -s``uname -r`)
case SunOS5*:
    set SOLARIS

    set DIG = /usr/local/bin/dig
    set HOST = /usr/local/bin/host
    set WHOAMI = `/usr/ucb/whoami`
	breaksw
case Linux2*:
case Linux3*:
case Linux4*:
    set DIG = /usr/bin/dig
    set HOST = /usr/bin/host
    set WHOAMI = `/usr/bin/whoami`
	breaksw
default:
	exec echo ${0}: does not run on `uname -s` `uname -r`
endsw

set BASE = `basename $0`
set TMP = /tmp/$BASE.$$

while($#argv)
	switch ("$1")
	case -c:
		set CACHE
		shift
		breaksw
	case -cd:
		set CACHEDIR = $2
		shift ; shift
		breaksw
	case -d:
		set DEBUG
#		shift
#		breaksw
# fall through to verbose
	case -v:
		set VERBOSE
		shift
		breaksw
	case -kd:
		set KEEPDIG
		set TEEDIG = "tee -a $TMP.dig"
		shift
		breaksw
	case -ks:
		set KEEPSCRIPT
		shift
		breaksw
	case -ps:
		set PRINTSCRIPT
		shift
		breaksw
	case -q:
		set QUICK	# only use data in cache
		set CACHE	# (implies cache)
		shift
		breaksw
	case -r:
		set RECURSE
		shift
		breaksw
	case -s:
		set GETSERIAL
		set CACHE	# inventing "serial" implies cache
		set RECURSE	#  and recursion
		shift
		breaksw
	case -server:
		set SERVER = $2
		set SERVERDIR = /$SERVER
		shift ; shift
		breaksw
	default:
	    if ( ! $?DOMAINS ) set DOMAINS
	    set DOMAINS = ( $DOMAINS $1 )
	    shift
	    breaksw
#		set DQ = '"'
#		exec echo ${0}: "What do I do with $DQ$1$DQ?"
	endsw
end

if (! $?DOMAINS) set DOMAINS = "rutgers.edu"
if (! $?SERVER) then
    set SERVER = 128.6.1.1
    set SERVERDIR
endif
if (! $?TEEDIG) set TEEDIG = cat

set SKIPDOMAINS = $0.skip
if (! -e $SKIPDOMAINS) set SKIPDOMAINS = `echo $0.skip | sed 's;n\.skip;.skip;'`
if (! -e $SKIPDOMAINS) set SKIPDOMAINS = /dev/null

if ($?QUICK) goto noawk
if ($?VERBOSE) echo `date +%T` Generating awk file
cat > $TMP.awk <<EOF
{

# Skip comments and blank lines
    if(NF==0||substr(\$1,1,1)==";")next;

# \$ORIGIN denotes subdomain name
    if (\$1=="\$ORIGIN"){
	l2m1=length(\$2)-1;
	DOMAIN=substr(\$2,1,l2m1);
	next}

# Process SOA
# possibilities:

    if(\$3=="IN"&&\$4=="SOA"||\$2=="IN"&&\$3=="SOA") {
    if(\$1=="@"){SOA1=DOMAIN;HOST="";SOA2=\$5;SOA3=\$6}
    else if(substr(\$0,1,1)!="	"){DOMAIN=\$1;HOST="";SOA1=DOMAIN;SOA2=\$5;SOA3=\$6}
    else {SOA1=DOMAIN;SOA2=\$4;SOA3=\$5}
    if (substr(DOMAIN,length(DOMAIN))==".")DOMAIN=substr(DOMAIN,1,length(DOMAIN)-1);
    if (substr(SOA1,length(SOA1))==".")SOA1=substr(SOA1,1,length(SOA1)-1);
    if (substr(SOA2,length(SOA2))==".")SOA2=substr(SOA2,1,length(SOA2)-1);
	else SOA2=SOA2 "." DOMAIN;
    if (substr(SOA3,length(SOA3))==".")SOA3=substr(SOA3,1,length(SOA3)-1);
	else SOA3=SOA3 "." DOMAIN;
    if(NF==11){
      print SOA1,"start of authority",SOA2,SOA3,"(",\$7,\$8,\$9,\$10,\$11,")";
      next
    }
#    print SOA1,"start of authority",SOA2,SOA3 "(";
# make this all on one line; 6/20/12
    printf "%s %s %s %s %s",SOA1,"start of authority",SOA2,SOA3,"(";
    INSOA=1;
    next
    }

# Continue SOA
if (INSOA) {
    ARG=\$1;
    RPAREN="";
    if(I=index(ARG,"H"))      N=substr(ARG,1,I-1)*60*60;
    else if(I=index(ARG,"M")) N=substr(ARG,1,I-1)*60;
    else if(I=index(ARG,"W")) N=substr(ARG,1,I-1)*60*60*24*7;
    else                      N=ARG;
    I=index(\$0,";");
    if(I)COMMENT=substr(\$0,I);
    if(index(\$0,")")){
	INSOA=0;
	RPAREN=")"
	}
#    print "    ",N,RPAREN,COMMENT;
# Making this all one line; 6/20/12
    printf " %s",N;
    if(RPAREN!="")print " )"
    next
    }

# Process NS
    if(\$2=="IN"&&\$3=="NS"||\$3=="IN"&&\$4=="NS") {
	if(substr(\$0,1,1)!="	")HOST=\$1;
	NS=\$NF;
	if (substr(NS,length(NS))==".")NS=substr(NS,1,length(NS)-1);
	else if (NS == "@") NS = DOMAIN;
	else NS=NS "." DOMAIN;
	if (HOST=="") print DOMAIN,"name server",NS;
	else if (substr(HOST,length(HOST))==".") print substr(HOST,1,length(HOST)-1),"name server",NS;
	else print HOST "." DOMAIN,"name server",NS;
	next
	}

# Process A
    if(\$2=="IN"&&\$3=="A"||\$3=="IN"&&\$4=="A") {
	if(substr(\$0,1,1)!="	")HOST=\$1;
	A=\$NF;
	if (HOST=="") print DOMAIN,"has address",A;
	else if (substr(HOST,length(HOST))==".") print substr(HOST,1,length(HOST)-1),"has address",A;
	else print HOST "." DOMAIN,"has address",A;
	next
	}

# Process AAAA
    if(\$2=="IN"&&\$3=="AAAA"||\$3=="IN"&&\$4=="AAAA") {
	if(substr(\$0,1,1)!="	")HOST=\$1;
	AAAA=\$NF;
	if (HOST=="") print DOMAIN,"has IPv6 address",AAAA;
	else if (substr(HOST,length(HOST))==".") print substr(HOST,1,length(HOST)-1),"has IPv6 address",AAAA;
	else print HOST "." DOMAIN,"has IPv6 address",AAAA;
	next
	}

# Process MX
    if(\$2=="IN"&&\$3=="MX"||\$3=="IN"&&\$4=="MX") {
	if(substr(\$0,1,1)!="	")HOST=\$1;
	MX=\$NF;
	if (substr(MX,length(MX))==".")MX=substr(MX,1,length(MX)-1);
	else if (MX == "@") MX = DOMAIN;
	else MX=MX "." DOMAIN;
	PRI=NF-1;
	PRI=\$PRI;
	if (HOST=="") print DOMAIN,"mail is handled (pri=" PRI ") by",MX;
	else if (substr(HOST,length(HOST))==".") print substr(HOST,1,length(HOST)-1),"mail is handled (pri=" PRI ") by",MX;
	else print HOST "." DOMAIN,"mail is handled (pri=" PRI ") by",MX;
	next
	}

# Process TXT
    if(\$2=="IN"&&\$3=="TXT"||\$3=="IN"&&\$4=="TXT") {
	if(substr(\$0,1,1)!="	") {
	    HOST=\$1;
	    ITXT=5;
	    }
	else ITXT=4;
	TXT="";
	for(I=ITXT;I<=NF;I++) TXT=TXT " " \$I;
	if (HOST=="") print DOMAIN,"descriptive text" TXT;
	else if (substr(HOST,length(HOST))==".") print substr(HOST,1,length(HOST)-1),"descriptive text" TXT;
	else print HOST "." DOMAIN,"descriptive text" TXT;
	next
	}

# Process CNAME
    if(\$2=="IN"&&\$3=="CNAME"||\$3=="IN"&&\$4=="CNAME") {
	if(substr(\$0,1,1)!="	")HOST=\$1;
	CNAME=\$NF;
	if (substr(CNAME,length(CNAME))==".")CNAME=substr(CNAME,1,length(CNAME)-1);
	else if (CNAME == "@") CNAME = DOMAIN;
	else CNAME=CNAME "." DOMAIN;
	PRI=NF-1;
	PRI=\$PRI;
	if (HOST=="") print DOMAIN,"is a nickname for",CNAME;
	else if (substr(HOST,length(HOST))==".") print substr(HOST,1,length(HOST)-1),"is a nickname for",CNAME;
	else print HOST "." DOMAIN,"is a nickname for",CNAME;
	next
	}

# Process SRV
    if(\$2=="IN"&&\$3=="SRV"||\$3=="IN"&&\$4=="SRV") {
	if(substr(\$0,1,1)!="	")HOST=\$1;
	SRV=\$NF;
	if (substr(SRV,length(SRV))==".")SRV=substr(SRV,1,length(SRV)-1);
	else if (SRV == "@") SRV = DOMAIN;
	else SRV=SRV "." DOMAIN;
	SS=NF-3;
	SS1=\$SS;
	SS+=1;
	SS2=\$SS;
	SS+=1;
	SS3=\$SS;
	if (HOST=="") print DOMAIN,"server selection",SS1,SS2,SS3,SRV;
	else if (substr(HOST,length(HOST))==".") print substr(HOST,1,length(HOST)-1),"server selection",SS1,SS2,SS3,SRV;
	else print HOST "." DOMAIN,"server selection",SS1,SS2,SS3,SRV;
	next
	}

    print ">",\$0
}
EOF

if ($?PRINTSCRIPT) then
    cat $TMP.awk
    echo =======================================
endif

noawk:
if ("$TEEDIG" != "cat") cp /dev/null $TMP.dig

if ($?CACHE) then
#    set CACHEDIR = /var/tmp/$BASE.$WHOAMI
if (! $?CACHEDIR) set CACHEDIR = /tmp/$BASE.$WHOAMI
    if (! -e $CACHEDIR) mkdir $CACHEDIR
    set CACHEDIR = $CACHEDIR$SERVERDIR
    if (! -e $CACHEDIR) mkdir $CACHEDIR
    endif
endif

if ($?RECURSE) then
    if ($?CACHE) then
	if ($?QUICK) goto quickru
	if ($?VERBOSE) echo `date +%T` Getting serial number for rutgers.edu
	if ($?SOLARIS) then
#	    set SERIAL = `$HOST -t soa rutgers.edu 128.6.1.1 |& grep -w serial | awk '{print $1}'`
	    set SERIAL = `$HOST -t soa rutgers.edu $SERVER |& grep -w serial | awk '{print $1}'`
	else
#	    set SERIAL = `$HOST -t soa rutgers.edu 128.6.1.1 |& grep -w SOA | awk '{print $7}'`
	    set SERIAL = `$HOST -t soa rutgers.edu $SERVER |& grep -w SOA | awk '{print $7}'`
	endif
	if (! -e $CACHEDIR/rutgers.edu.$SERIAL) then
	    if ($?VERBOSE) echo `date +%T` Collecting rutgers.edu $SERIAL
# Remove funny quoting of ";" that Linux dig does; 6/26/12
#	    $DIG @dns.rutgers.edu rutgers.edu AXFR | \
# Suddenly failing under Linux -- 2 servers found! 3/22/13
#	    $DIG @128.6.1.1 rutgers.edu AXFR | \
if ($?DEBUG) echo 1: $DIG @$SERVER rutgers.edu AXFR
	    $DIG @$SERVER rutgers.edu AXFR | \
		$TEEDIG | \
		sed 's|\\;|;|g' | \
		awk -f $TMP.awk > $CACHEDIR/rutgers.edu.$SERIAL.new
	    set STATUS = $status
	    if ($STATUS) then
#		exec echo ${0}: $DIG \| awk exited with status $STATUS
		echo ${0}: $DIG \| awk exited with status $STATUS
		exit $STATUS
	    else 
		if (-z $CACHEDIR/rutgers.edu.$SERIAL.new) then
		    echo ${0}: $DIG \| awk produced no output
		    exit 1
		endif
		grep " start of authority " $CACHEDIR/rutgers.edu.$SERIAL.new > /dev/null
		if ($status) then
		    echo ${0}: $DIG \| awk produced no start of authority
		    exit 1
		endif
		set FTRM = `/bin/ls $CACHEDIR/rutgers.edu.* | grep -v $CACHEDIR/rutgers.edu.$SERIAL.new`
		if ("$FTRM" != "") /bin/rm -f $FTRM
		/bin/mv $CACHEDIR/rutgers.edu.$SERIAL{.new,}
	    endif
	endif
quickru:
	if ($?QUICK) then
	    if (! $?GETSERIAL) then
		set CRU = `/bin/ls -t $CACHEDIR/rutgers.edu.* | head -1`
		cat $CRU
	    endif
	else
	    if (! $?GETSERIAL) cat $CACHEDIR/rutgers.edu.$SERIAL
	endif
	if ($?QUICK) then
# just in case there's more than one file there:
	    set CRU = `/bin/ls -t $CACHEDIR/rutgers.edu.* | head -1`
	    set GPAT = `grep "^rutgers.edu name.server" $CRU | awk '{print $NF}'`
	else
	    set GPAT = `grep "^rutgers.edu name.server" $CACHEDIR/rutgers.edu.$SERIAL | awk '{print $NF}'`
	endif
	set GPAT = "`echo $GPAT | sed 's; ;|;g'`"
	if ($?QUICK) then
	    set CRU = `/bin/ls -t $CACHEDIR/rutgers.edu.* | head -1`
	    set DOMAINS = `grep "name server" $CRU | egrep "$GPAT" | awk '{print $1}' | grep -v ^rutgers.edu | sed 's;\.$;;' | sort -u`
	else
	    set DOMAINS = `grep "name server" $CACHEDIR/rutgers.edu.$SERIAL | egrep "$GPAT" | awk '{print $1}' | grep -v ^rutgers.edu | sed 's;\.$;;' | sort -u`
	endif
    else
	if ($?VERBOSE) echo `date +%T` Collecting rutgers.edu
# Remove funny quoting of ";" that Linux dig does; 6/26/12
#	$DIG @dns.rutgers.edu rutgers.edu AXFR | \
#	$DIG @128.6.1.1 rutgers.edu AXFR | \
if ($?DEBUG) echo 2: $DIG @$SERVER rutgers.edu AXFR
	$DIG @$SERVER rutgers.edu AXFR | \
	    $TEEDIG | \
	    sed 's|\\;|;|g' | \
	    awk -f $TMP.awk > $TMP
	if (! $?GETSERIAL) cat $TMP
        set GPAT = `grep "^rutgers.edu name.server" $TMP | awk '{print $NF}'`
	set GPAT = "`echo $GPAT | sed 's; ;|;g'`"
	set DOMAINS = `grep "name server" $TMP | egrep "$GPAT" | awk '{print $1}' | grep -v ^rutgers.edu | sed 's;\.$;;' | sort -u`
	/bin/rm $TMP
    endif
endif

foreach DOMAIN ( $DOMAINS )
    grep "^$DOMAIN"'$' $SKIPDOMAINS > /dev/null
    if (! $status) then
	if ($?VERBOSE) echo `date +%T` Skipping domain $DOMAIN
	continue
    endif
#    $DIG @dns.rutgers.edu $DOMAIN AXFR | \
#	$TEEDIG | \
#	awk -f $TMP.awk
    if ($?CACHE) then
	if ($?QUICK) goto quick
	if ($?VERBOSE) echo `date +%T` Getting serial number for $DOMAIN
	if ($?SOLARIS) then
#	    set SERIAL = `$HOST -t soa $DOMAIN 128.6.1.1 |& grep -w serial | awk '{print $1}'`
	    set SERIAL = `$HOST -t soa $DOMAIN $SERVER |& grep -w serial | awk '{print $1}'`
	else
#	    set SERIAL = `$HOST -t soa $DOMAIN 128.6.1.1 |& grep -w SOA | awk '{print $7}'`
	    set SERIAL = `$HOST -t soa $DOMAIN $SERVER |& grep -w SOA | awk '{print $7}'`
	endif
	if (! -e $CACHEDIR/$DOMAIN.$SERIAL) then
	    if ($?VERBOSE) echo `date +%T` Collecting $DOMAIN $SERIAL
# Remove funny quoting of ";" that Linux dig does; 6/26/12
#	    $DIG @dns.rutgers.edu $DOMAIN AXFR | \
#	    $DIG @128.6.1.1 $DOMAIN AXFR | \
if ($?DEBUG) echo 3: $DIG @$SERVER $DOMAIN AXFR
	    $DIG @$SERVER $DOMAIN AXFR | \
		$TEEDIG | \
		sed 's|\\;|;|g' | \
		awk -f $TMP.awk > $CACHEDIR/$DOMAIN.$SERIAL.new
	    set STATUS = $status
	    if ($STATUS) then
#		exec echo ${0}: $DIG $DOMAIN \| awk exited with status $STATUS
		echo ${0}: $DIG $DOMAIN \| awk exited with status $STATUS
		exit $STATUS
	    else 
		if (-z $CACHEDIR/$DOMAIN.$SERIAL.new) then
		    echo ${0}: $DIG $DOMAIN \| awk produced no output
		    exit 1
		endif
		grep " start of authority " $CACHEDIR/$DOMAIN.$SERIAL.new > /dev/null
		if ($status) then
		    echo ${0}: $DIG $DOMAIN \| awk produced no start of authority
		    exit 1
		endif
		set FTRM = `/bin/ls $CACHEDIR/$DOMAIN.* | grep -v $CACHEDIR/$DOMAIN.$SERIAL.new`
		if ("$FTRM" != "") /bin/rm -f $FTRM
		/bin/mv $CACHEDIR/$DOMAIN.$SERIAL{.new,}
	    endif
	endif
quick:
	if ($?QUICK) then
	    set DRU = `/bin/ls -t $CACHEDIR/$DOMAIN.* | head -1`
	    if (! $?GETSERIAL) cat $DRU
	else
	    if (! $?GETSERIAL) cat $CACHEDIR/$DOMAIN.$SERIAL
	endif
    else
	if ($?VERBOSE) echo `date +%T` Collecting $DOMAIN
# Remove funny quoting of ";" that Linux dig does; 6/26/12
#	$DIG @dns.rutgers.edu $DOMAIN AXFR | \
#	$DIG @128.6.1.1 $DOMAIN AXFR | \
if ($?DEBUG) echo 4: $DIG @$SERVER $DOMAIN AXFR
	$DIG @$SERVER $DOMAIN AXFR | \
	    $TEEDIG | \
	    sed 's|\\;|;|g' | \
	    awk -f $TMP.awk
    endif
end

if ($?GETSERIAL) then
    set DATA = `/bin/ls -lt $CACHEDIR/* | head -1 | awk '{print $6,$7,$8}'`
#    echo $DATA
#    set YEAR = `date +%Y`
# keep length of serial number at 10 digits
    set YEAR = `date +%y`
    switch ($DATA[1])
    case Jan:
	set MONTH = "01"
	breaksw
    case Feb:
	set MONTH = "02"
	breaksw
    case Mar:
	set MONTH = "03"
	breaksw
    case Apr:
	set MONTH = "04"
	breaksw
    case May:
	set MONTH = "05"
	breaksw
    case Jun:
	set MONTH = "06"
	breaksw
    case Jul:
	set MONTH = "07"
	breaksw
    case Aug:
	set MONTH = "08"
	breaksw
    case Sep:
	set MONTH = "09"
	breaksw
    case Oct:
	set MONTH = "10"
	breaksw
    case Nov:
	set MONTH = "11"
	breaksw
    case Dec:
	set MONTH = "12"
	breaksw
    endsw
    set DAY = $DATA[2]
    if ($DAY < 10) set DAY = "0"$DAY
    set TIME = `echo $DATA[3] | sed 's;:;;'`
    echo $YEAR$MONTH$DAY$TIME
endif

if ($?KEEPDIG) then
    echo `date +%T` keeping $TMP.dig
else
    /bin/rm -f $TMP.dig
endif

if ($?KEEPSCRIPT) then
    echo `date +%T` keeping $TMP.awk
else
    /bin/rm -f $TMP.awk
endif
