home *** CD-ROM | disk | FTP | other *** search
/ Unix System Administration Handbook 1997 October / usah_oct97.iso / news / cnews.tar / expire / upact < prev    next >
Text File  |  1995-01-02  |  5KB  |  199 lines

  1. #! /bin/sh
  2. # Update 3rd field (minimum art. #) of a 4-field active file.
  3.  
  4.  
  5.  
  6. # =()<. ${NEWSCONFIG-@<NEWSCONFIG>@}>()=
  7. . ${NEWSCONFIG-/etc/news/bin/config}
  8.  
  9.  
  10.  
  11. PATH=$NEWSCTL/bin:$NEWSBIN/maint:$NEWSBIN:$NEWSPATH ; export PATH
  12. umask $NEWSUMASK
  13.  
  14. maxlen=200            # max length for shell cmd; 200 is pretty safe
  15. replace=yes
  16. what=normal            # update min, make sure max has a 0 on front
  17. lserr=/dev/null
  18. interpose=
  19. for dummy
  20. do
  21.     case "$1" in
  22.     -b)    what=both    ;;    # update both max and min
  23.     -p)    what=plain    ;;    # don't do ANYTHING to max
  24.     -s)    maxlen=0    ;;    # ls is funny, do slow way
  25.     '-#')    replace=no ; lserr=$NEWSCTL/active.errs    ;;    # debugging
  26.     -I)    interpose="$2" ; shift ;;    # interpose pgm for testing
  27.     --)    shift ; break    ;;
  28.     -*)    echo "$0: unknown option \`$1'" >&2 ; exit 2    ;;
  29.     *)    break        ;;
  30.     esac
  31.     shift
  32. done
  33.  
  34. cd $NEWSCTL
  35.  
  36. # lock news system momentarily and grab a copy of the active file
  37. lock LOCK $$ || exit 1
  38. status=1
  39. trap 'unlock LOCK ; trap 0 ; exit $status' 0 1 2 15
  40. sort active >active.upact || exit    # sort brings related dirs together
  41. trap 0 1 2 15
  42. unlock LOCK
  43.  
  44. # check out the active file
  45. checkactive -n -q active.upact >active.eek
  46. if test -s active.eek
  47. then
  48.     echo "$0: problems in active file -- aborting" >&2
  49.     cat active.eek >&2
  50.     rm -f active.eek active.upact
  51.     exit 1
  52. fi
  53.  
  54. # Bernd Felsche of MetaPro Systems came up with this general approach,
  55. # which minimizes the number of processes spawned, although this code is
  56. # rather different from his.  Thanks, Bernd!
  57.  
  58. # first, find minima, efficiently
  59. # translate names to dirs, turn dirs into "ls -f" commands, run them, pick
  60. # the desired data out of the output, turn dirs back into names, sort again,
  61. # and merge in old-max values
  62. tr '.' '/' <active.upact |
  63.     awk 'BEGIN {
  64.         maxlen = '"$maxlen"'
  65.         dirs = ""
  66.         ndirs = 0
  67.         print "cd '"$NEWSARTS"'"
  68.     }
  69.     length($1) + length(dirs) > maxlen && ndirs > 0 {
  70.         if (ndirs == 1)
  71.             print "echo " substr(dirs, 2) ":"
  72.         print "ls -f" dirs
  73.         dirs = ""
  74.         ndirs = 0
  75.     }
  76.     # the /. on the end eliminates problems with names including ":"
  77.     { dirs = dirs " " $1 "/." ; ndirs++ }
  78.     END {
  79.         if (ndirs == 1)
  80.             print "echo " substr(dirs, 2) ":"
  81.         print "ls -f" dirs
  82.         print "echo /.:"        # simplifies later logic
  83.     }' | sh 2>$lserr |
  84.     awk -F' ' 'BEGIN {
  85.         OFMT = "%.12g"
  86.         big = 99999999999
  87.         lowest = big
  88.         small = 0
  89.         highest = small
  90.         dir = ""
  91.     }
  92.     $0 ~ /^[0-9]+$/ {
  93.         # some old awks do not think $0 is numeric, so use $1
  94.         if ($1 < lowest)
  95.             lowest = $1
  96.         if ($1 > highest)
  97.             highest = $1
  98.         next
  99.     }
  100.     $0 ~ /\/\.:$/ {
  101.         if (dir != "") {
  102.             if (highest != small)
  103.                 print dir, highest, lowest
  104.             else
  105.                 print dir, "-", "-"
  106.         }
  107.         dir = substr($0, 1, length($0)-3)    # trim off /.:
  108.         lowest = big
  109.         highest = small
  110.     }' | tr '/' '.' | sort |
  111.     join -o 1.1 2.2 1.2 1.3 - active.upact >active.hilow
  112. # active.hilow now is newsgroup, old max, high file, low file
  113.  
  114. # testing hook
  115. if test " $interpose" != " "
  116. then
  117.     $interpose
  118. fi
  119.  
  120. # lock news system again
  121. lock LOCK $$ || exit 1
  122. status=1
  123. trap 'unlock LOCK ; trap 0 ; exit $status' 0 1 2 15
  124.  
  125. # decide on any extra processing needed
  126. extra=
  127. case "$what" in
  128. both)    extra='$7 != "-" && $7 > $3 {
  129.         # update max from high file
  130.         s = "000000000000000" $7
  131.         len = length($3)
  132.         if (length($7) > len)
  133.             len = length($7) + 1
  134.         s = substr(s, length(s)-len+1)
  135.         if (s !~ /^0/)
  136.             s = "0" s
  137.         $3 = s
  138.     }'
  139.     ;;
  140. normal)    extra='$3 !~ /^0/ { $3 = "0" $3 }'    ;;
  141. esac
  142.  
  143. # build new active file, cautiously
  144. # The result of the join is line number (for the sort -n that restores the
  145. # old order of the active file), newsgroup, active max, active min, active
  146. # flags, old max, high file, low file.
  147. awk '{ print $1, $2, $3, $4, NR }' active | sort |
  148.     join -a1 -e - -o 1.5 1.1 1.2 1.3 1.4 2.2 2.3 2.4 - active.hilow |
  149.     sort -n |
  150.     awk 'BEGIN { OFMT = "%.12g" }
  151.     $1 == "-" { next }        # no longer in active file
  152.     '"$extra"'
  153.     {
  154.         # find a new value for min
  155.         if ($8 != "-" && $8 != "")    # there was a low file
  156.             s = $8            # use it
  157.         else if ($6+0 != $3+0)        # oldmax != newmax, race cond!
  158.             s = $4            # use old value to be safe
  159.         else                # no files and no race
  160.             s = $3 + 1        # use max+1
  161.  
  162.         if (length(s) < 5) {
  163.             s = "00000" s
  164.             s = substr(s, length(s)-5+1)
  165.         }
  166.         print $2, ($3 ""), s, $5    # the "" forces string version
  167.     }' >active.tmp
  168.  
  169. # check that everything looks okay
  170. checkactive -q active.tmp >active.eek
  171. if test -s active.eek
  172. then
  173.     echo "$0: errors in active.tmp -- aborting" >&2
  174.     cat active.eek >&2
  175.     exit            # with status=1
  176. fi
  177. if test `wc -l <active.tmp` -lt `wc -l <active`
  178. then
  179.     echo "$0: active.tmp is bad (short) -- aborting" >&2
  180.     exit            # with status=1
  181. fi
  182. rm -f active.eek active.hilow active.upact    # clean up temporaries
  183.  
  184. # if we weren't asked to install it, don't
  185. case "$replace" in
  186. no)    status=0 ; exit    ;;
  187. esac
  188.  
  189. # replace active, carefully
  190. rm -f active.old
  191. mv active active.old && mv active.tmp active
  192. if test -f active.tmp
  193. then
  194.     echo "$0: replacing active didn't work" >&2
  195.     exit            # with status=1
  196. fi
  197.  
  198. status=0            # trap 0 does the actual exit
  199.