xref: /freebsd/contrib/file/install-sh (revision d1d50c78ab5592e27e6f1dc9657dc4c8eb8fdc9e)
175a6cdb3SDavid E. O'Brien#!/bin/sh
275a6cdb3SDavid E. O'Brien# install - install a program, script, or datafile
3d1d50c78SDavid E. O'Brien
4d1d50c78SDavid E. O'Brienscriptversion=2005-05-14.22
5d1d50c78SDavid E. O'Brien
6d1d50c78SDavid E. O'Brien# This originates from X11R5 (mit/util/scripts/install.sh), which was
7d1d50c78SDavid E. O'Brien# later released in X11R6 (xc/config/util/install.sh) with the
8d1d50c78SDavid E. O'Brien# following copyright and license.
9a2e8fb4cSDavid E. O'Brien#
10d1d50c78SDavid E. O'Brien# Copyright (C) 1994 X Consortium
11a2e8fb4cSDavid E. O'Brien#
12d1d50c78SDavid E. O'Brien# Permission is hereby granted, free of charge, to any person obtaining a copy
13d1d50c78SDavid E. O'Brien# of this software and associated documentation files (the "Software"), to
14d1d50c78SDavid E. O'Brien# deal in the Software without restriction, including without limitation the
15d1d50c78SDavid E. O'Brien# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
16d1d50c78SDavid E. O'Brien# sell copies of the Software, and to permit persons to whom the Software is
17d1d50c78SDavid E. O'Brien# furnished to do so, subject to the following conditions:
18d1d50c78SDavid E. O'Brien#
19d1d50c78SDavid E. O'Brien# The above copyright notice and this permission notice shall be included in
20d1d50c78SDavid E. O'Brien# all copies or substantial portions of the Software.
21d1d50c78SDavid E. O'Brien#
22d1d50c78SDavid E. O'Brien# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23d1d50c78SDavid E. O'Brien# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24d1d50c78SDavid E. O'Brien# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
25d1d50c78SDavid E. O'Brien# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
26d1d50c78SDavid E. O'Brien# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
27d1d50c78SDavid E. O'Brien# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28d1d50c78SDavid E. O'Brien#
29d1d50c78SDavid E. O'Brien# Except as contained in this notice, the name of the X Consortium shall not
30d1d50c78SDavid E. O'Brien# be used in advertising or otherwise to promote the sale, use or other deal-
31d1d50c78SDavid E. O'Brien# ings in this Software without prior written authorization from the X Consor-
32d1d50c78SDavid E. O'Brien# tium.
33d1d50c78SDavid E. O'Brien#
34d1d50c78SDavid E. O'Brien#
35d1d50c78SDavid E. O'Brien# FSF changes to this file are in the public domain.
3675a6cdb3SDavid E. O'Brien#
3775a6cdb3SDavid E. O'Brien# Calling this script install-sh is preferred over install.sh, to prevent
3875a6cdb3SDavid E. O'Brien# `make' implicit rules from creating a file called install from it
3975a6cdb3SDavid E. O'Brien# when there is no Makefile.
4075a6cdb3SDavid E. O'Brien#
4175a6cdb3SDavid E. O'Brien# This script is compatible with the BSD install script, but was written
42a2e8fb4cSDavid E. O'Brien# from scratch.  It can only install one file at a time, a restriction
43a2e8fb4cSDavid E. O'Brien# shared with many OS's install programs.
4475a6cdb3SDavid E. O'Brien
4575a6cdb3SDavid E. O'Brien# set DOITPROG to echo to test this script
4675a6cdb3SDavid E. O'Brien
4775a6cdb3SDavid E. O'Brien# Don't use :- since 4.3BSD and earlier shells don't like it.
4875a6cdb3SDavid E. O'Briendoit="${DOITPROG-}"
4975a6cdb3SDavid E. O'Brien
5075a6cdb3SDavid E. O'Brien# put in absolute paths if you don't have them in your path; or use env. vars.
5175a6cdb3SDavid E. O'Brien
5275a6cdb3SDavid E. O'Brienmvprog="${MVPROG-mv}"
5375a6cdb3SDavid E. O'Briencpprog="${CPPROG-cp}"
5475a6cdb3SDavid E. O'Brienchmodprog="${CHMODPROG-chmod}"
5575a6cdb3SDavid E. O'Brienchownprog="${CHOWNPROG-chown}"
5675a6cdb3SDavid E. O'Brienchgrpprog="${CHGRPPROG-chgrp}"
5775a6cdb3SDavid E. O'Brienstripprog="${STRIPPROG-strip}"
5875a6cdb3SDavid E. O'Brienrmprog="${RMPROG-rm}"
5975a6cdb3SDavid E. O'Brienmkdirprog="${MKDIRPROG-mkdir}"
6075a6cdb3SDavid E. O'Brien
6175a6cdb3SDavid E. O'Brienchmodcmd="$chmodprog 0755"
62d1d50c78SDavid E. O'Brienchowncmd=
63d1d50c78SDavid E. O'Brienchgrpcmd=
64d1d50c78SDavid E. O'Brienstripcmd=
6575a6cdb3SDavid E. O'Brienrmcmd="$rmprog -f"
6675a6cdb3SDavid E. O'Brienmvcmd="$mvprog"
67d1d50c78SDavid E. O'Briensrc=
68d1d50c78SDavid E. O'Briendst=
69d1d50c78SDavid E. O'Briendir_arg=
70d1d50c78SDavid E. O'Briendstarg=
71d1d50c78SDavid E. O'Brienno_target_directory=
7275a6cdb3SDavid E. O'Brien
73d1d50c78SDavid E. O'Brienusage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
74d1d50c78SDavid E. O'Brien   or: $0 [OPTION]... SRCFILES... DIRECTORY
75d1d50c78SDavid E. O'Brien   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
76d1d50c78SDavid E. O'Brien   or: $0 [OPTION]... -d DIRECTORIES...
77d1d50c78SDavid E. O'Brien
78d1d50c78SDavid E. O'BrienIn the 1st form, copy SRCFILE to DSTFILE.
79d1d50c78SDavid E. O'BrienIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
80d1d50c78SDavid E. O'BrienIn the 4th, create DIRECTORIES.
81d1d50c78SDavid E. O'Brien
82d1d50c78SDavid E. O'BrienOptions:
83d1d50c78SDavid E. O'Brien-c         (ignored)
84d1d50c78SDavid E. O'Brien-d         create directories instead of installing files.
85d1d50c78SDavid E. O'Brien-g GROUP   $chgrpprog installed files to GROUP.
86d1d50c78SDavid E. O'Brien-m MODE    $chmodprog installed files to MODE.
87d1d50c78SDavid E. O'Brien-o USER    $chownprog installed files to USER.
88d1d50c78SDavid E. O'Brien-s         $stripprog installed files.
89d1d50c78SDavid E. O'Brien-t DIRECTORY  install into DIRECTORY.
90d1d50c78SDavid E. O'Brien-T         report an error if DSTFILE is a directory.
91d1d50c78SDavid E. O'Brien--help     display this help and exit.
92d1d50c78SDavid E. O'Brien--version  display version info and exit.
93d1d50c78SDavid E. O'Brien
94d1d50c78SDavid E. O'BrienEnvironment variables override the default commands:
95d1d50c78SDavid E. O'Brien  CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG
96d1d50c78SDavid E. O'Brien"
97d1d50c78SDavid E. O'Brien
98d1d50c78SDavid E. O'Brienwhile test -n "$1"; do
9975a6cdb3SDavid E. O'Brien  case $1 in
100d1d50c78SDavid E. O'Brien    -c) shift
10175a6cdb3SDavid E. O'Brien        continue;;
10275a6cdb3SDavid E. O'Brien
10375a6cdb3SDavid E. O'Brien    -d) dir_arg=true
10475a6cdb3SDavid E. O'Brien        shift
10575a6cdb3SDavid E. O'Brien        continue;;
10675a6cdb3SDavid E. O'Brien
107d1d50c78SDavid E. O'Brien    -g) chgrpcmd="$chgrpprog $2"
108d1d50c78SDavid E. O'Brien        shift
109d1d50c78SDavid E. O'Brien        shift
110d1d50c78SDavid E. O'Brien        continue;;
111d1d50c78SDavid E. O'Brien
112d1d50c78SDavid E. O'Brien    --help) echo "$usage"; exit $?;;
113d1d50c78SDavid E. O'Brien
11475a6cdb3SDavid E. O'Brien    -m) chmodcmd="$chmodprog $2"
11575a6cdb3SDavid E. O'Brien        shift
11675a6cdb3SDavid E. O'Brien        shift
11775a6cdb3SDavid E. O'Brien        continue;;
11875a6cdb3SDavid E. O'Brien
11975a6cdb3SDavid E. O'Brien    -o) chowncmd="$chownprog $2"
12075a6cdb3SDavid E. O'Brien        shift
12175a6cdb3SDavid E. O'Brien        shift
12275a6cdb3SDavid E. O'Brien        continue;;
12375a6cdb3SDavid E. O'Brien
124d1d50c78SDavid E. O'Brien    -s) stripcmd=$stripprog
125d1d50c78SDavid E. O'Brien        shift
126d1d50c78SDavid E. O'Brien        continue;;
127d1d50c78SDavid E. O'Brien
128d1d50c78SDavid E. O'Brien    -t) dstarg=$2
12975a6cdb3SDavid E. O'Brien	shift
13075a6cdb3SDavid E. O'Brien	shift
13175a6cdb3SDavid E. O'Brien	continue;;
13275a6cdb3SDavid E. O'Brien
133d1d50c78SDavid E. O'Brien    -T) no_target_directory=true
13475a6cdb3SDavid E. O'Brien	shift
13575a6cdb3SDavid E. O'Brien	continue;;
13675a6cdb3SDavid E. O'Brien
137d1d50c78SDavid E. O'Brien    --version) echo "$0 $scriptversion"; exit $?;;
13875a6cdb3SDavid E. O'Brien
139d1d50c78SDavid E. O'Brien    *)  # When -d is used, all remaining arguments are directories to create.
140d1d50c78SDavid E. O'Brien	# When -t is used, the destination is already specified.
141d1d50c78SDavid E. O'Brien	test -n "$dir_arg$dstarg" && break
142d1d50c78SDavid E. O'Brien        # Otherwise, the last argument is the destination.  Remove it from $@.
143d1d50c78SDavid E. O'Brien	for arg
144d1d50c78SDavid E. O'Brien	do
145d1d50c78SDavid E. O'Brien          if test -n "$dstarg"; then
146d1d50c78SDavid E. O'Brien	    # $@ is not empty: it contains at least $arg.
147d1d50c78SDavid E. O'Brien	    set fnord "$@" "$dstarg"
148d1d50c78SDavid E. O'Brien	    shift # fnord
14975a6cdb3SDavid E. O'Brien	  fi
150d1d50c78SDavid E. O'Brien	  shift # arg
151d1d50c78SDavid E. O'Brien	  dstarg=$arg
152d1d50c78SDavid E. O'Brien	done
153d1d50c78SDavid E. O'Brien	break;;
15475a6cdb3SDavid E. O'Brien  esac
15575a6cdb3SDavid E. O'Briendone
15675a6cdb3SDavid E. O'Brien
157d1d50c78SDavid E. O'Brienif test -z "$1"; then
158d1d50c78SDavid E. O'Brien  if test -z "$dir_arg"; then
159d1d50c78SDavid E. O'Brien    echo "$0: no input file specified." >&2
16075a6cdb3SDavid E. O'Brien    exit 1
161d1d50c78SDavid E. O'Brien  fi
162d1d50c78SDavid E. O'Brien  # It's OK to call `install-sh -d' without argument.
163d1d50c78SDavid E. O'Brien  # This can happen when creating conditional directories.
164d1d50c78SDavid E. O'Brien  exit 0
16575a6cdb3SDavid E. O'Brienfi
16675a6cdb3SDavid E. O'Brien
167d1d50c78SDavid E. O'Brienfor src
168d1d50c78SDavid E. O'Briendo
169d1d50c78SDavid E. O'Brien  # Protect names starting with `-'.
170d1d50c78SDavid E. O'Brien  case $src in
171d1d50c78SDavid E. O'Brien    -*) src=./$src ;;
172d1d50c78SDavid E. O'Brien  esac
173d1d50c78SDavid E. O'Brien
174d1d50c78SDavid E. O'Brien  if test -n "$dir_arg"; then
17575a6cdb3SDavid E. O'Brien    dst=$src
176d1d50c78SDavid E. O'Brien    src=
17775a6cdb3SDavid E. O'Brien
178d1d50c78SDavid E. O'Brien    if test -d "$dst"; then
179d1d50c78SDavid E. O'Brien      mkdircmd=:
180d1d50c78SDavid E. O'Brien      chmodcmd=
18175a6cdb3SDavid E. O'Brien    else
182d1d50c78SDavid E. O'Brien      mkdircmd=$mkdirprog
18375a6cdb3SDavid E. O'Brien    fi
18475a6cdb3SDavid E. O'Brien  else
185d1d50c78SDavid E. O'Brien    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
18675a6cdb3SDavid E. O'Brien    # might cause directories to be created, which would be especially bad
18775a6cdb3SDavid E. O'Brien    # if $src (and thus $dsttmp) contains '*'.
188d1d50c78SDavid E. O'Brien    if test ! -f "$src" && test ! -d "$src"; then
189d1d50c78SDavid E. O'Brien      echo "$0: $src does not exist." >&2
19075a6cdb3SDavid E. O'Brien      exit 1
19175a6cdb3SDavid E. O'Brien    fi
19275a6cdb3SDavid E. O'Brien
193d1d50c78SDavid E. O'Brien    if test -z "$dstarg"; then
194d1d50c78SDavid E. O'Brien      echo "$0: no destination specified." >&2
19575a6cdb3SDavid E. O'Brien      exit 1
19675a6cdb3SDavid E. O'Brien    fi
19775a6cdb3SDavid E. O'Brien
198d1d50c78SDavid E. O'Brien    dst=$dstarg
199d1d50c78SDavid E. O'Brien    # Protect names starting with `-'.
200d1d50c78SDavid E. O'Brien    case $dst in
201d1d50c78SDavid E. O'Brien      -*) dst=./$dst ;;
202d1d50c78SDavid E. O'Brien    esac
20375a6cdb3SDavid E. O'Brien
204d1d50c78SDavid E. O'Brien    # If destination is a directory, append the input filename; won't work
205d1d50c78SDavid E. O'Brien    # if double slashes aren't ignored.
206d1d50c78SDavid E. O'Brien    if test -d "$dst"; then
207d1d50c78SDavid E. O'Brien      if test -n "$no_target_directory"; then
208d1d50c78SDavid E. O'Brien	echo "$0: $dstarg: Is a directory" >&2
209d1d50c78SDavid E. O'Brien	exit 1
210d1d50c78SDavid E. O'Brien      fi
211d1d50c78SDavid E. O'Brien      dst=$dst/`basename "$src"`
21275a6cdb3SDavid E. O'Brien    fi
21375a6cdb3SDavid E. O'Brien  fi
21475a6cdb3SDavid E. O'Brien
215d1d50c78SDavid E. O'Brien  # This sed command emulates the dirname command.
216d1d50c78SDavid E. O'Brien  dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'`
21775a6cdb3SDavid E. O'Brien
21875a6cdb3SDavid E. O'Brien  # Make sure that the destination directory exists.
21975a6cdb3SDavid E. O'Brien
22075a6cdb3SDavid E. O'Brien  # Skip lots of stat calls in the usual case.
221d1d50c78SDavid E. O'Brien  if test ! -d "$dstdir"; then
22275a6cdb3SDavid E. O'Brien    defaultIFS='
22375a6cdb3SDavid E. O'Brien	 '
224d1d50c78SDavid E. O'Brien    IFS="${IFS-$defaultIFS}"
22575a6cdb3SDavid E. O'Brien
226d1d50c78SDavid E. O'Brien    oIFS=$IFS
22775a6cdb3SDavid E. O'Brien    # Some sh's can't handle IFS=/ for some reason.
22875a6cdb3SDavid E. O'Brien    IFS='%'
229d1d50c78SDavid E. O'Brien    set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
23075a6cdb3SDavid E. O'Brien    shift
231d1d50c78SDavid E. O'Brien    IFS=$oIFS
23275a6cdb3SDavid E. O'Brien
233d1d50c78SDavid E. O'Brien    pathcomp=
234d1d50c78SDavid E. O'Brien
235d1d50c78SDavid E. O'Brien    while test $# -ne 0 ; do
236d1d50c78SDavid E. O'Brien      pathcomp=$pathcomp$1
237d1d50c78SDavid E. O'Brien      shift
238d1d50c78SDavid E. O'Brien      if test ! -d "$pathcomp"; then
239d1d50c78SDavid E. O'Brien        $mkdirprog "$pathcomp"
240d1d50c78SDavid E. O'Brien	# mkdir can fail with a `File exist' error in case several
241d1d50c78SDavid E. O'Brien	# install-sh are creating the directory concurrently.  This
242d1d50c78SDavid E. O'Brien	# is OK.
243d1d50c78SDavid E. O'Brien	test -d "$pathcomp" || exit
24475a6cdb3SDavid E. O'Brien      fi
245d1d50c78SDavid E. O'Brien      pathcomp=$pathcomp/
24675a6cdb3SDavid E. O'Brien    done
24775a6cdb3SDavid E. O'Brien  fi
24875a6cdb3SDavid E. O'Brien
249d1d50c78SDavid E. O'Brien  if test -n "$dir_arg"; then
250d1d50c78SDavid E. O'Brien    $doit $mkdircmd "$dst" \
251d1d50c78SDavid E. O'Brien      && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \
252d1d50c78SDavid E. O'Brien      && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \
253d1d50c78SDavid E. O'Brien      && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \
254d1d50c78SDavid E. O'Brien      && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; }
25575a6cdb3SDavid E. O'Brien
25675a6cdb3SDavid E. O'Brien  else
257d1d50c78SDavid E. O'Brien    dstfile=`basename "$dst"`
25875a6cdb3SDavid E. O'Brien
259d1d50c78SDavid E. O'Brien    # Make a couple of temp file names in the proper directory.
260d1d50c78SDavid E. O'Brien    dsttmp=$dstdir/_inst.$$_
261d1d50c78SDavid E. O'Brien    rmtmp=$dstdir/_rm.$$_
26275a6cdb3SDavid E. O'Brien
263d1d50c78SDavid E. O'Brien    # Trap to clean up those temp files at exit.
264d1d50c78SDavid E. O'Brien    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
265d1d50c78SDavid E. O'Brien    trap '(exit $?); exit' 1 2 13 15
26675a6cdb3SDavid E. O'Brien
267d1d50c78SDavid E. O'Brien    # Copy the file name to the temp name.
268d1d50c78SDavid E. O'Brien    $doit $cpprog "$src" "$dsttmp" &&
26975a6cdb3SDavid E. O'Brien
270d1d50c78SDavid E. O'Brien    # and set any options; do chmod last to preserve setuid bits.
271d1d50c78SDavid E. O'Brien    #
272d1d50c78SDavid E. O'Brien    # If any of these fail, we abort the whole thing.  If we want to
273d1d50c78SDavid E. O'Brien    # ignore errors from any of these, just make sure not to ignore
274d1d50c78SDavid E. O'Brien    # errors from the above "$doit $cpprog $src $dsttmp" command.
275d1d50c78SDavid E. O'Brien    #
276d1d50c78SDavid E. O'Brien    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \
277d1d50c78SDavid E. O'Brien      && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \
278d1d50c78SDavid E. O'Brien      && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \
279d1d50c78SDavid E. O'Brien      && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } &&
280d1d50c78SDavid E. O'Brien
281d1d50c78SDavid E. O'Brien    # Now rename the file to the real destination.
282d1d50c78SDavid E. O'Brien    { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \
283d1d50c78SDavid E. O'Brien      || {
284d1d50c78SDavid E. O'Brien	   # The rename failed, perhaps because mv can't rename something else
285d1d50c78SDavid E. O'Brien	   # to itself, or perhaps because mv is so ancient that it does not
286d1d50c78SDavid E. O'Brien	   # support -f.
287d1d50c78SDavid E. O'Brien
288d1d50c78SDavid E. O'Brien	   # Now remove or move aside any old file at destination location.
289d1d50c78SDavid E. O'Brien	   # We try this two ways since rm can't unlink itself on some
290d1d50c78SDavid E. O'Brien	   # systems and the destination file might be busy for other
291d1d50c78SDavid E. O'Brien	   # reasons.  In this case, the final cleanup might fail but the new
292d1d50c78SDavid E. O'Brien	   # file should still install successfully.
293d1d50c78SDavid E. O'Brien	   {
294d1d50c78SDavid E. O'Brien	     if test -f "$dstdir/$dstfile"; then
295d1d50c78SDavid E. O'Brien	       $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \
296d1d50c78SDavid E. O'Brien	       || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \
297d1d50c78SDavid E. O'Brien	       || {
298d1d50c78SDavid E. O'Brien		 echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2
299d1d50c78SDavid E. O'Brien		 (exit 1); exit 1
300d1d50c78SDavid E. O'Brien	       }
30175a6cdb3SDavid E. O'Brien	     else
302a2e8fb4cSDavid E. O'Brien	       :
30375a6cdb3SDavid E. O'Brien	     fi
304d1d50c78SDavid E. O'Brien	   } &&
30575a6cdb3SDavid E. O'Brien
30675a6cdb3SDavid E. O'Brien	   # Now rename the file to the real destination.
307d1d50c78SDavid E. O'Brien	   $doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
308d1d50c78SDavid E. O'Brien	 }
309d1d50c78SDavid E. O'Brien    }
310d1d50c78SDavid E. O'Brien  fi || { (exit 1); exit 1; }
311d1d50c78SDavid E. O'Briendone
31275a6cdb3SDavid E. O'Brien
313d1d50c78SDavid E. O'Brien# The final little trick to "correctly" pass the exit status to the exit trap.
314d1d50c78SDavid E. O'Brien{
315d1d50c78SDavid E. O'Brien  (exit 0); exit 0
316d1d50c78SDavid E. O'Brien}
31775a6cdb3SDavid E. O'Brien
318d1d50c78SDavid E. O'Brien# Local variables:
319d1d50c78SDavid E. O'Brien# eval: (add-hook 'write-file-hooks 'time-stamp)
320d1d50c78SDavid E. O'Brien# time-stamp-start: "scriptversion="
321d1d50c78SDavid E. O'Brien# time-stamp-format: "%:y-%02m-%02d.%02H"
322d1d50c78SDavid E. O'Brien# time-stamp-end: "$"
323d1d50c78SDavid E. O'Brien# End:
324