#!/bin/sh -
#
# $FreeBSD: ports/sysutils/bsdstats/files/300.statistics,v 1.38 2006/12/05 13:49:45 scrappy Exp $
# $NetBSD: 300.statistics,v 1.1.1.1 2010/03/12 00:13:40 morr Exp $
#

# If there is a global system configuration file, suck it in.
#
if [ -r /etc/defaults/periodic.conf ]
then
    . /etc/defaults/periodic.conf
    source_periodic_confs
    periodic_conf=/etc/periodic.conf
else
    . /etc/rc.conf	# For systems without periodic.conf, use rc.conf
    if [ -r /etc/rc.conf.local ] 
    then
        . /etc/rc.conf.local
    fi
    periodic_conf=/etc/rc.conf.local
fi

oldmask=$(umask)
umask 066

version="5.3"
checkin_server=${monthly_statistics_checkin_server:-"rpt.bsdstats.org"}
bsdstats_log=${monthly_statistics_logfile:-"/var/log/bsdstats"}
id_token_file='/var/db/bsdstats'

PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/pkg/sbin:/usr/pkg/bin
export PATH

unset HTTP_USER_AGENT

IFS="
"

random () {
  jot -r 1 0 900
}

# RFC 2396
uri_escape () {
    echo ${1+$@} | sed -e '
        s/%/%25/g
        s/;/%3b/g
        s,/,%2f,g
        s/?/%3f/g
        s/:/%3a/g
        s/@/%40/g
        s/&/%26/g
        s/=/%3d/g
        s/+/%2b/g
        s/\$/%24/g
        s/,/%2c/g
        s/ /%20/g
        '
}

do_fetch () {
    url="http://$checkin_server/scripts/$1"
    case $(uname) in
	FreeBSD )	
		/usr/bin/fetch -q -o - "$url"
		;;
	* )
		/usr/bin/ftp -V -o - "$url"
		;;
    esac
}

check_dns () {
    if [ `dig bsdstats.org txt | grep TXT | grep UP | wc -l` = 0 ] 
    then
      echo "DNS not reachable, Network Down?"
      exit
    fi
}

send_devices () {
    case $(uname) in
	FreeBSD )
	    for line in `/usr/sbin/pciconf -l`
	    do
	      DRIVER=`echo $line | awk -F\@ '{print $1}'`
	      DEV=`echo $line | awk '{print $4}' | cut -c8-15`
	      CLASS=`echo $line | awk '{print $2}' | cut -c9-14`
	      query_string=$query_string`echo \&dev[]=$DRIVER:$DEV:$CLASS`
	    done

	    report_devices
	    ;;
	* )
	    # Not supported
	    ;;
    esac
}

send_ports () {
    case $(uname) in
	FreeBSD )
	    for line in `/usr/sbin/pkg_info | /usr/bin/awk '{print $1}' `
	    do
              category=`grep "@comment ORIGIN" /var/db/pkg/${line}/+CONTENTS | sed -E 's/^\@comment ORIGIN:(.+)\/.+/\1/g'`
              line=$(uri_escape $line)
              category=$(uri_escape $category)
	      query_string=$query_string`echo \&port[]=${category}:${line}`
	    done

	    report_ports
	    ;;
	NetBSD|DragonFlyBSD )
	    for line in `/usr/sbin/pkg_info | /usr/bin/awk '{print $1}' `
	    do
	      category=`pkg_info -Q PKGPATH ${line}|cut -d/ -f1`
              line=$(uri_escape $line)
              category=$(uri_escape $category)
	      query_string=$query_string`echo \&port[]=${category}:${line}`
	    done

	    report_ports
	    ;;
	* )
	    # Not supported
	    ;;
    esac
}

report_ports () {
	# Handle HTTP proxy services
	#
	# HTTP_PROXY/http_proxy can take the following form:
	#    [http://][username:password@]proxy[:port][/]
	# Authentication details may also be provided via HTTP_PROXY_AUTH:
	#    HTTP_PROXY_AUTH="basic:*:username:password"
	#

	if [ -z "$HTTP_PROXY" -a -n "$http_proxy" ]; then
		HTTP_PROXY=$http_proxy
	fi
	if [ -n "$HTTP_PROXY" ]; then
		# Attempt to resolve any HTTP authentication
		if [ -n "$HTTP_PROXY_AUTH" ]; then
			PROXY_AUTH_USER=`echo $HTTP_PROXY_AUTH | sed -E 's/^.+:\*:(.+):.+$/\1/g'`
			PROXY_AUTH_PASS=`echo $HTTP_PROXY_AUTH | sed -E 's/^.+:\*:.+:(.+)$/\1/g'`
		else
			# Check for authentication within HTTP_PROXY
			HAS_HTTP_AUTH=`echo $HTTP_PROXY | sed -E 's/^(http:\/\/)?(.+:.+@)?.+/\2/'`
			if [ -n "$HAS_HTTP_AUTH" ]; then
				# Found HTTP authentication details
				PROXY_AUTH_USER=`echo $HAS_HTTP_AUTH | cut -d: -f1`
				PROXY_AUTH_PASS=`echo $HAS_HTTP_AUTH | cut -d: -f2`
			fi
		fi

		# Determine the proxy components
		PROXY_HOST=`echo $HTTP_PROXY | sed -E 's/^(http:\/\/)?(.+:.+@)?([^@:]+)(:.+)?/\3/'`
		PROXY_PORT=`echo $HTTP_PROXY | sed -E 's/^(http:\/\/)?(.+:.+@)?(.+):([0-9]+)/\4/' | sed -e 's/[^0-9]//g'`
		if [ -z "$PROXY_PORT" ]; then
			# Use default proxy port
			PROXY_PORT=3128
		fi
	fi

	# Determine the host/port netcat should connect to
	if [ -n "$PROXY_HOST" -a -n "$PROXY_PORT" ]; then
		nc_host=$PROXY_HOST
		nc_port=$PROXY_PORT
		url_prefix="http://${checkin_server}"
	else
		nc_host=$checkin_server
		nc_port=80
	fi

	# Proxy authentication, if required
	if [ -n "$PROXY_AUTH_USER" -a -n "$PROXY_AUTH_PASS" ]; then
		auth_base64=`echo "$PROXY_AUTH_USER:$PROXY_AUTH_PASS" | openssl base64`
		proxy_auth="Proxy-Authorization: Basic $auth_base64
"
	fi


	# Make the request	
	string_length=`echo ${query_string} | wc -m` 
	string_length=`expr ${string_length} - 1`

	echo "POST ${url_prefix}/scripts/report_ports.php HTTP/1.0
Host: ${checkin_server}
User-Agent: bsdstats ${version}
Connection: close
${proxy_auth}Content-Type: application/x-www-form-urlencoded
Content-Length: ${string_length}

token=${TOKEN}&key=${KEY}${query_string}" | \
		nc $nc_host $nc_port  | \
		grep STATUS= | {
          local IFS
          IFS='= 
'

           while read var val
             do  
             case $var in
                 STATUS)
                     if [ $val = "OK" ]
                     then
                       echo "[`date`] System Ports reported"
                     else
                       echo "[`date`] System Ports not reported, exiting"
                       exit
                     fi
                 ;; 
                 *)
                     echo "[`date`] Error with fetch to server"
                     exit
                 ;;
                 esac
           done   
       } >> $bsdstats_log

}

report_devices () {
      do_fetch report_devices.php?token=$TOKEN\&key=$KEY$query_string | { 
          local IFS
          IFS='=
'

           while read var val
             do
             case $var in
                 STATUS)
                     if [ $val = "OK" ]
                     then
                       echo "[`date`] System Devices reported"
                     else
                       echo "[`date`] System Devices not reported, exiting"
                       exit
                     fi
                 ;;
                 *)
                     echo "[`date`] Error with fetch to server"
                     exit
                 ;;
                 esac
           done  
       } >> $bsdstats_log
}

get_id_token () {
    if [ -f $id_token_file ]
    then
      if [ `cat /var/db/bsdstats | wc -l` -lt 3 ] 
      then
        rm $id_token_file
      fi
    fi

    if [ ! -f $id_token_file -o ! -s $id_token_file ] ;
    then
       IDTOKEN=$(uri_escape $( openssl rand -base64 32 ) )
       
       idf=$( mktemp "$id_token_file.XXXXXX" )  && \
       chown root:wheel $idf          && \
       chmod 600 $idf

       do_fetch getid.php?key=$IDTOKEN | {
          local IFS
          IFS='=
'

	   while read var val 
	     do  
	     case $var in
		 KEY)
                     echo "KEY=$val"
		 ;;
		 TOKEN)
                     echo "TOKEN=$val"
		 ;;
		 *)
                 ;;
		 esac
	   done
           echo "VERSION=$version"
       } > $idf                                  && \

       mv $idf $id_token_file
       if [ ! -s $id_token_file ] ;
       then
    	  echo "Nothing returned from $checkin_server"
	  exit 1
       fi
    fi
    . $id_token_file
    KEY=$( uri_escape $KEY )
    TOKEN=$( uri_escape $TOKEN )
}


enable_token () {
      do_fetch enable_token.php?key=$TOKEN\&token=$KEY | {
          local IFS
          IFS='=
'

           while read var val
             do
             case $var in
                 STATUS)
                     if [ $val = "OK" ]
                     then
                       echo "[`date`] System enabled"
                     else
                       echo "[`date`] System not enabled, exiting"
                       exit
                     fi
                 ;;
                 *)
                     echo "[`date`] Error with fetch to server"
                     exit
                 ;;
                 esac
           done  
       } >> $bsdstats_log
}

disable_token () {
      do_fetch disable_token.php?key=$TOKEN\&token=$KEY | {
          local IFS
          IFS='=
'

           while read var val
             do
             case $var in
                 STATUS)
                     if [ $val = "OK" ]
                     then
                       echo "[`date`] System disabled"
                     else
                       echo "[`date`] System not disabled, exiting"
                       exit
                     fi
                 ;;
                 *)
                     echo "[`date`] Error with fetch to server"
                     exit
                 ;;
                 esac
           done  
       } >> $bsdstats_log
}

report_system () {
      do_fetch report_system.php?token=$TOKEN\&key=$KEY\&rel=$REL\&arch=$ARCH\&opsys=$OS | {
          local IFS
          IFS='=
'

           while read var val
             do
             case $var in
                 STATUS)
                     if [ $val = "OK" ]
                     then
                       echo "[`date`] System reported"
                     else
                       echo "[`date`] System report failed, exiting"
                       exit
                     fi
                 ;;
                 *)
                     echo "[`date`] Error with fetch to server"
                     exit
                 ;;
                 esac
           done  
       } >> $bsdstats_log
}

report_cpu () {
    do_fetch report_cpu.php?token=$TOKEN\&key=$KEY\&cpus=$count\&vendor=$VEN\&cpu_type=$DEV | {
          local IFS
          IFS='=
'

           while read var val
             do
             case $var in
                 STATUS)
                     if [ $val = "OK" ]
                     then
                       echo "[`date`] System CPU reported"
                     else
                       echo "[`date`] System CPU report failed, exiting"
                       exit
                     fi
                 ;;
                 *)
                     echo "[`date`] Error with fetch to server"
                     exit
                 ;;
                 esac
           done  
       } >> $bsdstats_log
}
case "$monthly_statistics_enable" in
    [Yy][Ee][Ss])
      check_dns
      HN=`/bin/hostname`
      REL=`/usr/bin/uname -r`
      ARCH=`/usr/bin/uname -m`
      OS=`/usr/bin/uname -s`
      get_id_token
      test X"$1" = X-nodelay || sleep `random`
      enable_token
      report_system
      echo "Posting monthly OS statistics to $checkin_server"
      case "$monthly_statistics_report_devices" in
          [Yy][Ee][Ss])
              send_devices
              echo "Posting monthly device statistics to $checkin_server"
              line=$( sysctl -n hw.model )
              VEN=$( echo $line | cut -d ' ' -f 1 )
              DEV=$( uri_escape $( echo $line | cut -d ' ' -f 2- ) )
              count=$( sysctl -n hw.ncpu )
              report_cpu
              echo "Posting monthly CPU statistics to $checkin_server"
             ;;
          *) 
             echo "Posting monthly device/CPU statistics disabled"
             echo "    set monthly_statistics_report_devices=\"YES\" in $periodic_conf"
             ;;
      esac
      case "$monthly_statistics_report_ports" in
          [Yy][Ee][Ss])
              send_ports
              echo "Posting monthly ports statistics to $checkin_server"
             ;;
          *) 
             echo "Posting monthly ports statistics disabled"
             echo "    set monthly_statistics_report_ports=\"YES\" in $periodic_conf"
             ;;
      esac
      disable_token
      ;;
    *) 
      echo "Posting monthly OS statistics disabled"
      echo "    set monthly_statistics_enable=\"YES\" in $periodic_conf"
    ;;
esac

umask $oldmask
exit $rc
