summaryrefslogtreecommitdiff
path: root/doasedit
blob: add65255f954807c4b331c48be51c10815bd1752 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#!/bin/sh

# Copyright (c) 2022 Thomas Voss <mail@thomasvoss.com>
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
# WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
# AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
# DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
# OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
# TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.

# Copy an existing text file to a temporary location.  Then edit the file.
# Attempt to then transfer the temporary file back to the original location if
# the temprary file has been altered.  Conclude with a little clean-up.  Try to
# avoid deleting any changes.

warn() { echo "$PROG: $1" >&2; }
die()  { warn "$2"; exit $1;   }

get_intr() {
	stty -a | sed -En '
		/^(.* )?intr = / {
			s///
			s/;.*$//
			p
		}'
}

PROG=${0##*/}

[ $# -ne 1 ] && {
	echo "Usage: $PROG file"
	exit 1
}

[ ! -f "$1" ] && die 2 "$1: File does not exist or is a special file/link."
[   -L "$1" ] && die 2 "$1: File is a symbolic link, refusing to edit."
[ ! -r "$1" ] && die 3 "$1: File cannot be read by the current user."

tmp=$(mktemp --tmpdir doasedit.XXXXXXXX --suffix="${1//*./.}") || \
	die 4 "Could not create temporary file."
trap "rm -f $tmp" EXIT HUP INT TERM
cp "$1" "$tmp" || die 5 "$1: Unable to copy file."

"${VISUAL:-${EDITOR:-vi}}" "$tmp" || {
	warn "Could not run visual editor '$VISUAL' or editor '$EDITOR'."
	die 6 "Make sure the VISUAL and/or EDITOR variables are set."
}

cmp -s "$1" "$tmp" && \
	die 0 "File unchanged.  Not writing back to original location."

# At this point the file has been changed.  Make sure it still exists.
[ -f "$tmp" ] && {
	doas cp "$tmp" "$1"
	until cmp -s "$tmp" "$1"; do
		warn "$1: Copying failed.  Press enter to try again,"
		warn "or ($(get_intr)) to cancel."
		read _
		doas cp "$tmp" "$1"
	done
}