xref: /freebsd-src/contrib/ntp/scripts/update-leap/update-leap.sh (revision a466cc55373fc3cf86837f09da729535b57e69a1)
1*276da39aSCy Schubert#!/bin/bash
2*276da39aSCy Schubert
3*276da39aSCy Schubert# Copyright (C) 2014 Timothe Litt litt at acm dot org
4*276da39aSCy Schubert
5*276da39aSCy Schubert# This script may be freely copied, used and modified providing that
6*276da39aSCy Schubert# this notice and the copyright statement are included in all copies
7*276da39aSCy Schubert# and derivative works.  No warranty is offered, and use is entirely at
8*276da39aSCy Schubert# your own risk.  Bugfixes and improvements would be appreciated by the
9*276da39aSCy Schubert# author.
10*276da39aSCy Schubert
11*276da39aSCy SchubertVERSION="1.003"
12*276da39aSCy Schubert
13*276da39aSCy Schubert# leap-seconds file manager/updater
14*276da39aSCy Schubert
15*276da39aSCy Schubert# Depends on:
16*276da39aSCy Schubert#  wget sed, tr, shasum, logger
17*276da39aSCy Schubert
18*276da39aSCy Schubert# ########## Default configuration ##########
19*276da39aSCy Schubert#
20*276da39aSCy Schubert# Where to get the file
21*276da39aSCy SchubertLEAPSRC="ftp://time.nist.gov/pub/leap-seconds.list"
22*276da39aSCy Schubert
23*276da39aSCy Schubert# How many times to try to download new file
24*276da39aSCy SchubertMAXTRIES=6
25*276da39aSCy SchubertINTERVAL=10
26*276da39aSCy Schubert
27*276da39aSCy Schubert# Where to find ntp config file
28*276da39aSCy SchubertNTPCONF=/etc/ntp.conf
29*276da39aSCy Schubert
30*276da39aSCy Schubert# How long before expiration to get updated file
31*276da39aSCy SchubertPREFETCH="60 days"
32*276da39aSCy Schubert
33*276da39aSCy Schubert# How to restart NTP - older NTP: service ntpd? try-restart | condrestart
34*276da39aSCy Schubert# Recent NTP checks for new file daily, so there's nothing to do
35*276da39aSCy SchubertRESTART=
36*276da39aSCy Schubert
37*276da39aSCy Schubert# Where to put temporary copy before it's validated
38*276da39aSCy SchubertTMPFILE="/tmp/leap-seconds.$$.tmp"
39*276da39aSCy Schubert
40*276da39aSCy Schubert# Syslog facility
41*276da39aSCy SchubertLOGFAC=daemon
42*276da39aSCy Schubert# ###########################################
43*276da39aSCy Schubert
44*276da39aSCy Schubert# Places to look for commands.  Allows for CRON having path to
45*276da39aSCy Schubert# old utilities on embedded systems
46*276da39aSCy Schubert
47*276da39aSCy SchubertPATHLIST="/opt/sbin:/opt/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:"
48*276da39aSCy Schubert
49*276da39aSCy SchubertREQUIREDCMDS=" wget logger tr sed shasum"
50*276da39aSCy Schubert
51*276da39aSCy SchubertSELF="`basename $0`"
52*276da39aSCy Schubert
53*276da39aSCy Schubertfunction displayHelp {
54*276da39aSCy Schubert            cat <<EOF
55*276da39aSCy SchubertUsage: $SELF [options] [leapfile]
56*276da39aSCy Schubert
57*276da39aSCy SchubertVerifies and if necessary, updates leap-second definition file
58*276da39aSCy Schubert
59*276da39aSCy SchubertAll arguments are optional:  Default (or current value) shown:
60*276da39aSCy Schubert    -s    Specify the URL of the master copy to download
61*276da39aSCy Schubert          $LEAPSRC
62*276da39aSCy Schubert    -4    Use only IPv4
63*276da39aSCy Schubert    -6    Use only IPv6
64*276da39aSCy Schubert    -p 4|6
65*276da39aSCy Schubert          Prefer IPv4 or IPv6 (as specified) addresses, but use either
66*276da39aSCy Schubert    -d    Specify the filename on the local system
67*276da39aSCy Schubert          $LEAPFILE
68*276da39aSCy Schubert    -e    Specify how long before expiration the file is to be refreshed
69*276da39aSCy Schubert          Units are required, e.g. "-e 60 days"  Note that larger values
70*276da39aSCy Schubert          imply more frequent refreshes.
71*276da39aSCy Schubert          "$PREFETCH"
72*276da39aSCy Schubert    -f    Specify location of ntp.conf (used to make sure leapfile directive is
73*276da39aSCy Schubert          present and to default  leapfile)
74*276da39aSCy Schubert          $NTPCONF
75*276da39aSCy Schubert    -F    Force update even if current file is OK and not close to expiring.
76*276da39aSCy Schubert    -c    Command to restart NTP after installing a new file
77*276da39aSCy Schubert          <none> - ntpd checks file daily
78*276da39aSCy Schubert    -r    Specify number of times to retry on get failure
79*276da39aSCy Schubert          $MAXTRIES
80*276da39aSCy Schubert    -i    Specify number of minutes between retries
81*276da39aSCy Schubert          $INTERVAL
82*276da39aSCy Schubert    -l    Use syslog for output (Implied if CRONJOB is set)
83*276da39aSCy Schubert    -L    Don't use syslog for output
84*276da39aSCy Schubert    -P    Specify the syslog facility for logging
85*276da39aSCy Schubert          $LOGFAC
86*276da39aSCy Schubert    -t    Name of temporary file used in validation
87*276da39aSCy Schubert          $TMPFILE
88*276da39aSCy Schubert    -q    Only report errors to stdout
89*276da39aSCy Schubert    -v    Verbose output
90*276da39aSCy Schubert    -z    Specify path for utilities
91*276da39aSCy Schubert          $PATHLIST
92*276da39aSCy Schubert    -Z    Only use system path
93*276da39aSCy Schubert
94*276da39aSCy Schubert$SELF will validate the file currently on the local system
95*276da39aSCy Schubert
96*276da39aSCy SchubertOrdinarily, the file is found using the "leapfile" directive in $NTPCONF.
97*276da39aSCy SchubertHowever, an alternate location can be specified on the command line.
98*276da39aSCy Schubert
99*276da39aSCy SchubertIf the file does not exist, is not valid, has expired, or is expiring soon,
100*276da39aSCy Schuberta new copy will be downloaded.  If the new copy validates, it is installed and
101*276da39aSCy SchubertNTP is (optionally) restarted.
102*276da39aSCy Schubert
103*276da39aSCy SchubertIf the current file is acceptable, no download or restart occurs.
104*276da39aSCy Schubert
105*276da39aSCy Schubert-c can also be used to invoke another script to perform administrative
106*276da39aSCy Schubertfunctions, e.g. to copy the file to other local systems.
107*276da39aSCy Schubert
108*276da39aSCy SchubertThis can be run as a cron job.  As the file is rarely updated, and leap
109*276da39aSCy Schubertseconds are announced at least one month in advance (usually longer), it
110*276da39aSCy Schubertneed not be run more frequently than about once every three weeks.
111*276da39aSCy Schubert
112*276da39aSCy SchubertFor cron-friendly behavior, define CRONJOB=1 in the crontab.
113*276da39aSCy Schubert
114*276da39aSCy SchubertThis script depends on$REQUIREDCMDS
115*276da39aSCy Schubert
116*276da39aSCy SchubertVersion $VERSION
117*276da39aSCy SchubertEOF
118*276da39aSCy Schubert   return 0
119*276da39aSCy Schubert}
120*276da39aSCy Schubert
121*276da39aSCy Schubert# Default: Use syslog for logging if running under cron
122*276da39aSCy Schubert
123*276da39aSCy SchubertSYSLOG="$CRONJOB"
124*276da39aSCy Schubert
125*276da39aSCy Schubertif [ "$1" = "--help" ]; then
126*276da39aSCy Schubert    displayHelp
127*276da39aSCy Schubert    exit 0
128*276da39aSCy Schubertfi
129*276da39aSCy Schubert
130*276da39aSCy Schubert# Parse options
131*276da39aSCy Schubert
132*276da39aSCy Schubertwhile getopts 46p:P:s:e:f:Fc:r:i:lLt:hqvz:Z opt; do
133*276da39aSCy Schubert    case $opt in
134*276da39aSCy Schubert        4)
135*276da39aSCy Schubert            PROTO="-4"
136*276da39aSCy Schubert            ;;
137*276da39aSCy Schubert        6)
138*276da39aSCy Schubert            PROTO="-6"
139*276da39aSCy Schubert            ;;
140*276da39aSCy Schubert        p)
141*276da39aSCy Schubert            if [ "$OPTARG" = '4' -o "$OPTARG" = '6' ]; then
142*276da39aSCy Schubert                PREFER="--prefer-family=IPv$OPTARG"
143*276da39aSCy Schubert            else
144*276da39aSCy Schubert                echo "Invalid -p $OPTARG" >&2
145*276da39aSCy Schubert                exit 1;
146*276da39aSCy Schubert            fi
147*276da39aSCy Schubert            ;;
148*276da39aSCy Schubert	P)
149*276da39aSCy Schubert	    LOGFAC="$OPTARG"
150*276da39aSCy Schubert	    ;;
151*276da39aSCy Schubert        s)
152*276da39aSCy Schubert            LEAPSRC="$OPTARG"
153*276da39aSCy Schubert            ;;
154*276da39aSCy Schubert        e)
155*276da39aSCy Schubert            PREFETCH="$OPTARG"
156*276da39aSCy Schubert            ;;
157*276da39aSCy Schubert	f)
158*276da39aSCy Schubert	    NTPCONF="$OPTARG"
159*276da39aSCy Schubert	    ;;
160*276da39aSCy Schubert        F)
161*276da39aSCy Schubert            FORCE="Y"
162*276da39aSCy Schubert            ;;
163*276da39aSCy Schubert        c)
164*276da39aSCy Schubert            RESTART="$OPTARG"
165*276da39aSCy Schubert            ;;
166*276da39aSCy Schubert        r)
167*276da39aSCy Schubert            MAXTRIES="$OPTARG"
168*276da39aSCy Schubert            ;;
169*276da39aSCy Schubert        i)
170*276da39aSCy Schubert            INTERVAL="$OPTARG"
171*276da39aSCy Schubert            ;;
172*276da39aSCy Schubert        t)
173*276da39aSCy Schubert            TMPFILE="$OPTARG"
174*276da39aSCy Schubert            ;;
175*276da39aSCy Schubert	l)
176*276da39aSCy Schubert	    SYSLOG="y"
177*276da39aSCy Schubert	    ;;
178*276da39aSCy Schubert	L)
179*276da39aSCy Schubert	    SYSLOG=
180*276da39aSCy Schubert	    ;;
181*276da39aSCy Schubert        h)
182*276da39aSCy Schubert            displayHelp
183*276da39aSCy Schubert            exit 0
184*276da39aSCy Schubert            ;;
185*276da39aSCy Schubert	q)
186*276da39aSCy Schubert	    QUIET="Y"
187*276da39aSCy Schubert	    ;;
188*276da39aSCy Schubert        v)
189*276da39aSCy Schubert            VERBOSE="Y"
190*276da39aSCy Schubert            ;;
191*276da39aSCy Schubert	z)
192*276da39aSCy Schubert	    PATHLIST="$OPTARG:"
193*276da39aSCy Schubert	    ;;
194*276da39aSCy Schubert	Z)
195*276da39aSCy Schubert	    PATHLIST=
196*276da39aSCy Schubert	    ;;
197*276da39aSCy Schubert        *)
198*276da39aSCy Schubert            echo "$SELF -h for usage" >&2
199*276da39aSCy Schubert            exit 1
200*276da39aSCy Schubert            ;;
201*276da39aSCy Schubert    esac
202*276da39aSCy Schubertdone
203*276da39aSCy Schubertshift $((OPTIND-1))
204*276da39aSCy Schubert
205*276da39aSCy Schubertexport PATH="$PATHLIST$PATH"
206*276da39aSCy Schubert
207*276da39aSCy Schubert# Add to path to deal with embedded systems
208*276da39aSCy Schubert#
209*276da39aSCy Schubertfor P in $REQUIREDCMDS ; do
210*276da39aSCy Schubert    if >/dev/null 2>&1 which "$P" ; then
211*276da39aSCy Schubert	continue
212*276da39aSCy Schubert    fi
213*276da39aSCy Schubert    [ "$P" = "logger" ] && continue
214*276da39aSCy Schubert    echo "FATAL: missing $P command, please install"
215*276da39aSCy Schubert    exit 1
216*276da39aSCy Schubertdone
217*276da39aSCy Schubert
218*276da39aSCy Schubert# Handle logging
219*276da39aSCy Schubert
220*276da39aSCy Schubertif ! LOGGER="`2>/dev/null which logger`" ; then
221*276da39aSCy Schubert    LOGGER=
222*276da39aSCy Schubertfi
223*276da39aSCy Schubert
224*276da39aSCy Schubertfunction log {
225*276da39aSCy Schubert    # "priority" "message"
226*276da39aSCy Schubert    #
227*276da39aSCy Schubert    # Stdout unless syslog specified or logger isn't available
228*276da39aSCy Schubert    #
229*276da39aSCy Schubert    if [ -z "$SYSLOG" -o -z "$LOGGER" ]; then
230*276da39aSCy Schubert	if [ -n "$QUIET" -a \( "$1" = "info" -o "$1" = "notice" -o "$1" = "debug" \) ]; then
231*276da39aSCy Schubert	    return 0
232*276da39aSCy Schubert	fi
233*276da39aSCy Schubert	echo "`echo \"$1\" | tr a-z A-Z`: $2"
234*276da39aSCy Schubert	return 0
235*276da39aSCy Schubert    fi
236*276da39aSCy Schubert
237*276da39aSCy Schubert    # Also log to stdout if cron job && notice or higher
238*276da39aSCy Schubert    local S
239*276da39aSCy Schubert    if [ -n "$CRONJOB" -a \( "$1" != "info" \) -a \( "$1" != "debug" \) ] || [ -n "$VERBOSE" ]; then
240*276da39aSCy Schubert	S="-s"
241*276da39aSCy Schubert    fi
242*276da39aSCy Schubert    $LOGGER $S -t "$SELF[$$]" -p "$LOGFAC.$1" "$2"
243*276da39aSCy Schubert}
244*276da39aSCy Schubert
245*276da39aSCy Schubert# Verify interval
246*276da39aSCy SchubertINTERVAL=$(( $INTERVAL *1 ))
247*276da39aSCy Schubert
248*276da39aSCy Schubert# Validate a leap-seconds file checksum
249*276da39aSCy Schubert#
250*276da39aSCy Schubert# File format: (full description in files)
251*276da39aSCy Schubert# # marks comments, except:
252*276da39aSCy Schubert# #$ number : the NTP date of the last update
253*276da39aSCy Schubert# #@ number : the NTP date that the file expires
254*276da39aSCy Schubert# Date (seconds since 1900) leaps : leaps is the # of seconds to add for times >= Date
255*276da39aSCy Schubert# Date lines have comments.
256*276da39aSCy Schubert# #h hex hex hex hex hex is the SHA-1 checksum of the data & dates, excluding whitespace w/o leading zeroes
257*276da39aSCy Schubert
258*276da39aSCy Schubertfunction verifySHA {
259*276da39aSCy Schubert
260*276da39aSCy Schubert    if [ ! -f "$1" ]; then
261*276da39aSCy Schubert        return 1
262*276da39aSCy Schubert    fi
263*276da39aSCy Schubert
264*276da39aSCy Schubert    # Remove comments, except those that are markers for last update, expires and hash
265*276da39aSCy Schubert
266*276da39aSCy Schubert    local RAW="`sed $1 -e'/^\\([0-9]\\|#[\$@h]\)/!d' -e'/^#[\$@h]/!s/#.*\$//g'`"
267*276da39aSCy Schubert
268*276da39aSCy Schubert    # Extract just the data, removing all whitespace
269*276da39aSCy Schubert
270*276da39aSCy Schubert    local DATA="`echo \"$RAW\" | sed -e'/^#h/d' -e's/^#[\$@]//g' | tr -d '[:space:]'`"
271*276da39aSCy Schubert
272*276da39aSCy Schubert    # Compute the SHA hash of the data, removing the marker and filename
273*276da39aSCy Schubert    # Computed in binary mode, which shouldn't matter since whitespace has been removed
274*276da39aSCy Schubert    # shasum comes in several flavors; a portable one is available in Perl (with Digest::SHA)
275*276da39aSCy Schubert
276*276da39aSCy Schubert    local DSHA="`echo -n \"$DATA\" | shasum | sed -e's/[? *].*$//'`"
277*276da39aSCy Schubert
278*276da39aSCy Schubert    # Extract the file's hash. Restore any leading zeroes in hash segments.
279*276da39aSCy Schubert
280*276da39aSCy Schubert    # The sed [] includes a tab (\t) and space; #h is followed by a tab and space
281*276da39aSCy Schubert    local FSHA="`echo \"$RAW\" | sed -e'/^#h/!d' -e's/^#h//' -e's/[ 	] */ 0x/g'`"
282*276da39aSCy Schubert    FSHA=`printf '%08x%08x%08x%08x%08x' $FSHA`
283*276da39aSCy Schubert
284*276da39aSCy Schubert    if [ -n "$FSHA" -a \( "$FSHA" = "$DSHA" \) ]; then
285*276da39aSCy Schubert        if [ -n "$2" ]; then
286*276da39aSCy Schubert            log "info" "Checksum of $1 validated"
287*276da39aSCy Schubert        fi
288*276da39aSCy Schubert    else
289*276da39aSCy Schubert        log "error" "Checksum of $1 is invalid:"
290*276da39aSCy Schubert	[ -z "$FSHA" ] && FSHA="(no checksum record found in file)"
291*276da39aSCy Schubert        log "error" "EXPECTED: $FSHA"
292*276da39aSCy Schubert        log "error" "COMPUTED: $DSHA"
293*276da39aSCy Schubert        return 1
294*276da39aSCy Schubert    fi
295*276da39aSCy Schubert
296*276da39aSCy Schubert    # Check the expiration date, converting NTP epoch to Unix epoch used by date
297*276da39aSCy Schubert
298*276da39aSCy Schubert    EXPIRES="`echo \"$RAW\" | sed -e'/^#@/!d' -e's/^#@//' | tr -d '[:space:]'`"
299*276da39aSCy Schubert    EXPIRES="$(($EXPIRES - 2208988800 ))"
300*276da39aSCy Schubert
301*276da39aSCy Schubert    if [ $EXPIRES -lt `date -u +%s` ]; then
302*276da39aSCy Schubert        log "notice" "File expired on `date -u -d \"Jan 1, 1970 00:00:00 +0000 + $EXPIRES seconds\"`"
303*276da39aSCy Schubert        return 2
304*276da39aSCy Schubert    fi
305*276da39aSCy Schubert
306*276da39aSCy Schubert}
307*276da39aSCy Schubert
308*276da39aSCy Schubert# Verify ntp.conf
309*276da39aSCy Schubert
310*276da39aSCy Schubertif ! [ -f "$NTPCONF" ]; then
311*276da39aSCy Schubert    log "critical" "Missing ntp configuration $NTPCONF"
312*276da39aSCy Schubert    exit 1
313*276da39aSCy Schubertfi
314*276da39aSCy Schubert
315*276da39aSCy Schubert# Parse ntp.conf for leapfile directive
316*276da39aSCy Schubert
317*276da39aSCy SchubertLEAPFILE="`sed $NTPCONF -e'/^ *leapfile  *.*$/!d' -e's/^ *leapfile  *//'`"
318*276da39aSCy Schubertif [ -z "$LEAPFILE" ]; then
319*276da39aSCy Schubert    log "error" "$NTPCONF does not specify a leapfile"
320*276da39aSCy Schubertfi
321*276da39aSCy Schubert
322*276da39aSCy Schubert# Allow placing the file someplace else - testing
323*276da39aSCy Schubert
324*276da39aSCy Schubertif [ -n "$1" ]; then
325*276da39aSCy Schubert    if [ "$1" != "$LEAPFILE" ]; then
326*276da39aSCy Schubert	log "notice" "Requested install to $1, but $NTPCONF specifies $LEAPFILE"
327*276da39aSCy Schubert    fi
328*276da39aSCy Schubert    LEAPFILE="$1"
329*276da39aSCy Schubertfi
330*276da39aSCy Schubert
331*276da39aSCy Schubert# Verify the current file
332*276da39aSCy Schubert# If it is missing, doesn't validate or expired
333*276da39aSCy Schubert# Or is expiring soon
334*276da39aSCy Schubert#  Download a new one
335*276da39aSCy Schubert
336*276da39aSCy Schubertif [ -n "$FORCE" ] || ! verifySHA $LEAPFILE "$VERBOSE" || [ $EXPIRES -lt `date -d "NOW + $PREFETCH" +%s` ] ; then
337*276da39aSCy Schubert    TRY=0
338*276da39aSCy Schubert    while true; do
339*276da39aSCy Schubert        TRY=$(( $TRY + 1 ))
340*276da39aSCy Schubert        if [ -n "$VERBOSE" ]; then
341*276da39aSCy Schubert            log "info" "Attempting download from $LEAPSRC, try $TRY.."
342*276da39aSCy Schubert        fi
343*276da39aSCy Schubert        if wget $PROTO $PREFER -o ${TMPFILE}.log $LEAPSRC -O $TMPFILE ; then
344*276da39aSCy Schubert            log "info" "Download of $LEAPSRC succeeded"
345*276da39aSCy Schubert            if [ -n "$VERBOSE" ]; then
346*276da39aSCy Schubert                cat ${TMPFILE}.log
347*276da39aSCy Schubert            fi
348*276da39aSCy Schubert
349*276da39aSCy Schubert            if ! verifySHA $TMPFILE "$VERBOSE" ; then
350*276da39aSCy Schubert		# There is no point in retrying, as the file on the server is almost
351*276da39aSCy Schubert		# certainly corrupt.
352*276da39aSCy Schubert
353*276da39aSCy Schubert                log "warning" "Downloaded file $TMPFILE rejected -- saved for diagnosis"
354*276da39aSCy Schubert                cat ${TMPFILE}.log
355*276da39aSCy Schubert                rm -f ${TMPFILE}.log
356*276da39aSCy Schubert                exit 1
357*276da39aSCy Schubert            fi
358*276da39aSCy Schubert            rm -f ${TMPFILE}.log
359*276da39aSCy Schubert
360*276da39aSCy Schubert	    # Set correct permissions on temporary file
361*276da39aSCy Schubert
362*276da39aSCy Schubert	    REFFILE="$LEAPFILE"
363*276da39aSCy Schubert            if [ ! -f $LEAPFILE ]; then
364*276da39aSCy Schubert		log "notice" "$LEAPFILE was missing, creating new copy - check permissions"
365*276da39aSCy Schubert                touch $LEAPFILE
366*276da39aSCy Schubert		# Can't copy permissions from old file, copy from NTPCONF instead
367*276da39aSCy Schubert		REFFILE="$NTPCONF"
368*276da39aSCy Schubert            fi
369*276da39aSCy Schubert            chmod --reference $REFFILE $TMPFILE
370*276da39aSCy Schubert            chown --reference $REFFILE $TMPFILE
371*276da39aSCy Schubert	    ( which selinuxenabled && selinuxenabled && which chcon ) >/dev/null 2>&1
372*276da39aSCy Schubert            if  [ $? == 0 ] ; then
373*276da39aSCy Schubert                chcon --reference $REFFILE $TMPFILE
374*276da39aSCy Schubert            fi
375*276da39aSCy Schubert
376*276da39aSCy Schubert	    # Replace current file with validated new one
377*276da39aSCy Schubert
378*276da39aSCy Schubert            if mv -f $TMPFILE $LEAPFILE ; then
379*276da39aSCy Schubert                log "notice" "Installed new $LEAPFILE from $LEAPSRC"
380*276da39aSCy Schubert            else
381*276da39aSCy Schubert                log "error" "Install $TMPFILE => $LEAPFILE failed -- saved for diagnosis"
382*276da39aSCy Schubert                exit 1
383*276da39aSCy Schubert            fi
384*276da39aSCy Schubert
385*276da39aSCy Schubert	    # Restart NTP (or whatever else is specified)
386*276da39aSCy Schubert
387*276da39aSCy Schubert	    if [ -n "$RESTART" ]; then
388*276da39aSCy Schubert		if [ -n "$VERBOSE" ]; then
389*276da39aSCy Schubert		    log "info" "Attempting restart action: $RESTART"
390*276da39aSCy Schubert		fi
391*276da39aSCy Schubert		R="$( 2>&1 $RESTART )"
392*276da39aSCy Schubert		if [ $? -eq 0 ]; then
393*276da39aSCy Schubert		    log "notice" "Restart action succeeded"
394*276da39aSCy Schubert		    if [ -n "$VERBOSE" -a -n "$R" ]; then
395*276da39aSCy Schubert			log "info" "$R"
396*276da39aSCy Schubert		    fi
397*276da39aSCy Schubert		else
398*276da39aSCy Schubert		    log "error" "Restart action failed"
399*276da39aSCy Schubert		    if [ -n "$R" ]; then
400*276da39aSCy Schubert			log "error" "$R"
401*276da39aSCy Schubert		    fi
402*276da39aSCy Schubert		    exit 2
403*276da39aSCy Schubert		fi
404*276da39aSCy Schubert	    fi
405*276da39aSCy Schubert            exit 0
406*276da39aSCy Schubert	fi
407*276da39aSCy Schubert
408*276da39aSCy Schubert	# Failed to download.  See about trying again
409*276da39aSCy Schubert
410*276da39aSCy Schubert        rm -f $TMPFILE
411*276da39aSCy Schubert        if [ $TRY -ge $MAXTRIES ]; then
412*276da39aSCy Schubert            break;
413*276da39aSCy Schubert        fi
414*276da39aSCy Schubert        if [ -n "$VERBOSE" ]; then
415*276da39aSCy Schubert            cat ${TMPFILE}.log
416*276da39aSCy Schubert            log "info" "Waiting $INTERVAL minutes before retrying..."
417*276da39aSCy Schubert        fi
418*276da39aSCy Schubert        sleep $(( $INTERVAL * 60))
419*276da39aSCy Schubert    done
420*276da39aSCy Schubert
421*276da39aSCy Schubert    # Failed and out of retries
422*276da39aSCy Schubert
423*276da39aSCy Schubert    log "warning" "Download from $LEAPSRC failed after $TRY attempts"
424*276da39aSCy Schubert    if [ -f ${TMPFILE}.log ]; then
425*276da39aSCy Schubert        cat ${TMPFILE}.log
426*276da39aSCy Schubert        rm -f ${TMPFILE}.log $TMPFILE
427*276da39aSCy Schubert    fi
428*276da39aSCy Schubert    exit 1
429*276da39aSCy Schubertfi
430*276da39aSCy Schubertlog "info" "Not time to replace $LEAPFILE"
431*276da39aSCy Schubert
432*276da39aSCy Schubertexit 0
433*276da39aSCy Schubert
434*276da39aSCy Schubert# EOF