Advertisement
Guest User

Untitled

a guest
Jul 15th, 2014
235
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Bash 6.16 KB | None | 0 0
  1. #!/bin/sh
  2. # updatehosts: fetch external hosts files and append to our own
  3.  
  4.  
  5. ## Settings ###################################################################
  6. HOSTS="${1:-/etc/hosts}"
  7. #EXCLUDE='rover.ebay.com'  # separate multiple entries with colons
  8. #HOSTS_URL='http://someonewhocares.org/hosts/zero/hosts'  ## hosts -> 0.0.0.0
  9. #HOSTS_URL='http://someonewhocares.org/hosts/hosts'       ## hosts -> 127.0.0.1
  10. HOSTS_URL='http://winhelp2002.mvps.org/hosts.txt'
  11.  
  12.  
  13. ## Internals; here be dragons #################################################
  14. DELIM='## END STATIC HOSTS ##'
  15. SED_COMMENT_HOST='s/^\(127\|0\)\.0\.0\.\(1\|0\)\( \+\)%s$/#\\0\1# excluded/g'
  16. #SED_REMOVE_LOCAL='/^#<localhost>$/,/^#<\/localhost>$/d'  # someonewhocares
  17. SED_REMOVE_LOCAL='/^\(127\.0\.0\.1\|::1\)  localhost$/d'     # mvps
  18. SED_SCRUB_HOSTS='/^%s$/,$d'
  19. KEEP_EXTERNAL_LOCALHOST=
  20. TMP_PRIMARY=
  21. TMP_SECONDARY=
  22. TMP_SED=
  23. STEP=
  24.  
  25.  
  26. ## Functions ##################################################################
  27.  
  28. err() {
  29.     local pattern msg
  30.  
  31.     case "$1" in
  32.     WRITE_TO_FILE)    msg="Failed to write to file: %s"              ;;
  33.     DOWNLOAD)         msg="Failed to download URL: %s"               ;;
  34.     EXCLUDE)          msg="Failed to comment hosts for exclusion"    ;;
  35.     GET_NUM_ENTRIES)  msg="Failed to parse number of entries in %s"  ;;
  36.     TIMESTAMP)        msg="Failed to timestamp hosts file (%s)"      ;;
  37.     VERIFY_CONSTANTS) msg="Malconfigured script; please edit %s"     ;;
  38.     WRITE_TO_TMP)     msg="Failed to create temporary files in /tmp" ;;
  39.     APPEND_TO_FILE)   msg="Failed to append to file (%s >> %s)"      ;;
  40.     "")               msg="undefined!" ;;
  41.     *)                msg="$1"         ;;
  42.     esac
  43.  
  44.     shift 2>/dev/null
  45.     printf -- "\n[!] ERROR: $msg\n" "$@" 1>&2
  46.     exit 1
  47. }
  48.  
  49.  
  50. clean_up() {
  51.     rm -f "$TMP_PRIMARY" "$TMP_SECONDARY" "$TMP_SED"
  52. }
  53.  
  54. step() {
  55.     STEP=$((${STEP:-0}+1))
  56.     local pattern="$1"
  57.     shift 2>/dev/null
  58.  
  59.     printf -- "\n[%d] $pattern " $STEP "$@"
  60. }
  61.  
  62.  
  63. scrub_old() {
  64.     local regex
  65.     step "Scrubbing hosts file of old additions"
  66.  
  67.     # prepare regex by inserting the delimeter into it
  68.     regex="$(printf -- "$SED_SCRUB_HOSTS" "$DELIM")"
  69.  
  70.     #echo "sed \"$regex\" $TMP_SECONDARY" >&2
  71.     sed_i "$regex" "$TMP_SECONDARY" || err WRITE_TO_FILE "$TMP_SECONDARY"
  72.  
  73.     # restore delim until we figure out a better sed command
  74.     grep -q -- "$DELIM" "$TMP_SECONDARY" || echo "$DELIM" >> "$TMP_SECONDARY"
  75. }
  76.  
  77.  
  78. sed_i() {
  79.     # sed -i is supposedly not portable so let's reinvent it
  80.     local expression="$1"
  81.     local _file="$2"
  82.  
  83.     sed "$expression" "$_file" > "$TMP_SED" || return 1
  84.     mv -f "$TMP_SED" "$_file"
  85.  
  86.     return $?
  87. }
  88.  
  89.  
  90. download_hosts() {
  91.     local num_excluded num_hosts
  92.     step "Downloading external hosts file"
  93.  
  94.     wget -qt3 -O "$TMP_PRIMARY" "$HOSTS_URL" || err DOWNLOAD "$HOSTS_URL"
  95.  
  96.     # remove localhost section in it unless KEEP_EXTERNAL_LOCALHOST is set
  97.     [ "$KEEP_EXTERNAL_LOCALHOST" ] || sed_i "$SED_REMOVE_LOCAL" "$TMP_PRIMARY"
  98.  
  99.     # comment our exclusions and catch returned count
  100.     num_excluded=$(exclude "$TMP_PRIMARY") || err EXCLUDE
  101.  
  102.     # count number of uncommented lines in our temp file
  103.     num_hosts=$(get_num_entries "$TMP_PRIMARY") || err GET_NUM_ENTRIES
  104.  
  105.     printf -- '\n... %d host definitions loaded%s' \
  106.         $num_hosts "${num_excluded:+" ($num_excluded commented out")}"
  107. }
  108.  
  109.  
  110. append() {
  111.     step "Adding loaded hosts"
  112.  
  113.     cat "$TMP_PRIMARY" >> "$TMP_SECONDARY" || \
  114.     err APPEND_TO_FILE "$TMP_PRIMARY" "$TMP_SECONDARY"
  115. }
  116.  
  117.  
  118. get_num_entries() {
  119.     local _file
  120.     _file="${1:-"$TMP_PRIMARY"}"
  121.     cat "$_file" | grep -v '^[ \t]*#\|^$' | wc -l
  122.     return $?
  123. }
  124.  
  125.  
  126. timestamp() {
  127.     cat >> "$TMP_SECONDARY" << _EOF
  128.  
  129. # [${0##*/}] external hosts file as below added on $(date)
  130.  
  131. _EOF
  132.     [ $? -eq 0 ] || err TIMESTAMP "$TMP_SECONDARY"
  133. }
  134.  
  135.  
  136. exclude() {
  137.     [ "$EXCLUDE" ] || return 0
  138.     local host regex before after delta
  139.     local _file="$1"
  140.     local commented=0
  141.     local IFS=':'
  142.  
  143.     for host in $EXCLUDE; do
  144.         unset regex before after delta
  145.         regex="$(printf -- "$SED_COMMENT_HOST" "$host")"
  146.  
  147.         before=$(get_num_entries "$_file")
  148.         sed_i "$regex" "$_file" || return 1
  149.         after=$(get_num_entries "$_file")
  150.  
  151.         delta=$((before-$after))
  152.         commented=$((commented+$delta))
  153.     done
  154.  
  155.     [ $commented -gt 0 ] && echo $commented
  156.     return 0
  157. }
  158.  
  159.  
  160. sanity_check() {
  161.     # constants set?
  162.     ([ "$HOSTS" ]     && [ "$SED_COMMENT_HOST" ]  && \
  163.      [ "$DELIM" ]     && [ "$SED_REMOVE_LOCAL" ]  && \
  164.      [ "$HOSTS_URL" ] && [ "$SED_SCRUB_HOSTS"  ] ) || err VERIFY_CONSTANTS "$0"
  165.  
  166.     # does the hosts file exist to begin with. if not, have our downloaded list
  167.     # retain its basic localhost entries (127.0.0.1 etc)
  168.     [ ! -e "$HOSTS" ] && KEEP_EXTERNAL_LOCALHOST=1
  169.  
  170.     # delimeter present in hosts? else append
  171.     grep -q -- "$DELIM" "$TMP_SECONDARY" || echo "$DELIM" >> "$TMP_SECONDARY"
  172.  
  173.     return 0
  174. }
  175.  
  176.  
  177. create_temp() {
  178.     step "Creating working copy of %s along with temporary files" "$HOSTS"
  179.  
  180.     TMP_PRIMARY="$(  mktemp /tmp/hosts.primary.XXXXXX)" || err WRITE_TO_TMP
  181.     TMP_SECONDARY="$(mktemp /tmp/hosts.secondary.XXXXXX)"
  182.     TMP_SED="$(      mktemp /tmp/hosts.sed.XXXXXX)"
  183.     [ -e "$HOSTS" ] && cp "$HOSTS" "$TMP_SECONDARY"
  184.  
  185.     return $?
  186. }
  187.  
  188.  
  189. commit() {
  190.     step "Committing all changes to %s (may need root)" "$HOSTS"
  191.  
  192.     cp -f "$TMP_SECONDARY" "$HOSTS" 2>/dev/null && return 0
  193.  
  194.     # if we're still here we failed, so try sudo and then su -c
  195.     printf -- '\n... failed; retrying with sudo\n'
  196.     sudo cp -f "$TMP_SECONDARY" "$HOSTS" 2>/dev/null && return 0
  197.  
  198.     printf '\n... failed; retrying with su -c\n'
  199.     su -c "cp -f "$TMP_SECONDARY" "$HOSTS"" 2>/dev/null && return 0
  200.  
  201.     err WRITE_TO_FILE "$HOSTS"
  202. }
  203.  
  204.  
  205. finish_with_flair() {
  206.     step "All done, no errors\n"
  207.     return 0
  208. }
  209.  
  210.  
  211. main() {
  212.     trap 'clean_up' EXIT
  213.  
  214.     create_temp
  215.     sanity_check
  216.  
  217.     download_hosts
  218.     scrub_old
  219.     timestamp
  220.     append
  221.     commit
  222.  
  223.     finish_with_flair
  224.     return $?
  225. }
  226.  
  227.  
  228. ## Execution start ############################################################
  229.  
  230. main
  231. exit $?
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement