aboutsummaryrefslogtreecommitdiff
blob: b4f221736775b7cd54f168553f87c411802b069b (plain)
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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
#!/bin/sh
# $Id$
# Author:
#   Matthias Schwarzott <zzam@gmx.de>
#   Various other contributors from gentoo.de
#
# some ideas from ctvdr's shutdownvdr by Tobias Grimm <tg@e-tobi.net>
#

# This script is called by vdr when triggering shutdown
# called from vdr with: vdr -s vdrshutdown-gate.sh

# It calls all shell-scripts located under /usr/share/vdr/shutdown
# for checking if shutdown should be allowed.
# A lot of functions defined in here can be used
# from within these scripts.

#fork to background already done by vdrshutdown-gate.sh for now
#if [ -z "${EXECUTED_BY_VDR_BG}" ]; then
#	exec /usr/share/vdr/bin/vdr-bg.sh "${0}" "${@}"
#	exit
#fi

if [ "$(id  -u)" != "0" ]; then
	echo "This program should be run as root"
	exit 99
fi

# should be default paths on a machine build with vdr ebuilds
NVRAM_WAKEUP=/usr/bin/nvram-wakeup
HOOKDIR=/usr/share/vdr/shutdown

. /usr/share/vdr/inc/functions.sh
include shutdown-functions
read_caps

include svdrpcmd
svdrp_command

VDR_TIMER_NEXT="${1}"
VDR_TIMER_DELTA="${2}"
VDR_TIMER_CHANNEL="${3}"
VDR_TIMER_FILENAME="${4}"
VDR_USERSHUTDOWN="${5}"

: ${SHUTDOWN_DEFAULT_RETRY_TIME:=10}

if [ "${DEBUG}" -ge 1 ]; then
	exec </dev/null >/tmp/vdrshutdown-really.log 2>&1
	echo Started debug output of $0 $@
	nr=0
	for f; do
		nr=$(($nr+1))
		echo "param #${nr} - ${f}"
	done
	set -x
fi

svdrp_send() {
	${SVDRPCMD} "$@"
}

mesg() {
	svdrp_send MESG ${1}
}

is_auto_shutdown() {
	[ "${VDR_USERSHUTDOWN}" = "0" ]
}

is_user_shutdown() {
	[ "${VDR_USERSHUTDOWN}" = "1" ]
}

is_forced_shutdown() {
	[ "${THIS_SHUTDOWN_IS_FORCED}" = "1" ]
}

is_shutdown_aborted() {
	[ "${SHUTDOWN_ABORT}" = "1" ]
}

forced_tests_count_greater_zero() {
	[ "${SHUTDOWN_FORCE_COUNT}" -gt 0 ]
}

set_retry_time() {
	local TIME="${1}"
	if [ "${TRY_AGAIN}" -lt "${TIME}" ]; then
		TRY_AGAIN=${TIME}
	fi
}

shutdown_abort_common() {
	ABORT_MESSAGE="${1}"
	SHUTDOWN_ABORT="1"
	set_retry_time "${SHUTDOWN_DEFAULT_RETRY_TIME}"
}

shutdown_abort() {
	shutdown_abort_common "${1}"
	disable_forced_shutdown
}

shutdown_abort_can_force() {
	if is_forced_shutdown; then
		# this is the forced way, ignore this abort
		echo FORCED: ${1}
		SHUTDOWN_FORCE_COUNT=$(($SHUTDOWN_FORCE_COUNT+1))
	else
		shutdown_abort_common "${1}"
	fi
}

shutdown_abort_exit() {
	local ABORT_MESSAGE="${1}"
	local EXITCODE=1

	mesg "Shutdown aborted: ${ABORT_MESSAGE}"
	exit ${EXITCODE}
}



init_forced_shutdown() {
	SHUTDOWN_CAN_FORCE=0
	THIS_SHUTDOWN_IS_FORCED="0"

	# only continue if user-shutdown
	if ! is_user_shutdown; then
		return 0
	fi



	# detect if this could be a forced shutdown
	local shutdown_force_file=${shutdown_data_dir}/last-shutdown-abort

	local LAST_SHUTDOWN_ABORT=$(read_int_from_file "${shutdown_force_file}")
	NOW=$(date +%s)
	local DISTANCE=$(($NOW-$LAST_SHUTDOWN_ABORT))
	if [ "${DISTANCE}" -lt "${SHUTDOWN_FORCE_DETECT_INTERVALL:-60}" ]; then
		THIS_SHUTDOWN_IS_FORCED="1"
	fi

	[ -f "${shutdown_force_file}" ] && rm "${shutdown_force_file}"
	SHUTDOWN_FORCE_COUNT=0
	SHUTDOWN_CAN_FORCE=1
}

disable_forced_shutdown() {
	SHUTDOWN_CAN_FORCE="0"
}

write_force_file() {
	local shutdown_force_file=${shutdown_data_dir}/last-shutdown-abort
	echo "${NOW}" > "${shutdown_force_file}"
}

check_forced_shutdown_possible_next_time() {
	if [ "${SHUTDOWN_CAN_FORCE}" = "1" ]; then
		write_force_file
		sleep 1s
		mesg "You can force a shutdown with pressing power again"
	fi
}

execute_hooks() {
	local HOOK
	for HOOK in $HOOKDIR/pre-shutdown-*.sh; do
		[ -r "${HOOK}" ] || continue
		sh -n "${HOOK}" || continue
		. "${HOOK}"
	done
}

retry_shutdown() {
	local when=${TRY_AGAIN}

	if [ -n "${CAP_SHUTDOWN_SVDRP}" ]; then
		if [ "${when}" -gt 5 ]; then
			svdrp_send "DOWN $(($when-5))"
		else
			svdrp_send "DOWN"
		fi
		return
	fi

	if [ "${CAP_SHUTDOWN_AUTO_RETRY:-0}" = "1" ]; then
		# vdr itself will retry shutdown in a reasonable time
		return
	fi
	
	# shutdown retry must be simulated by sleep and the power key
	#as vdr itself is not able

	# just do it here without forking as we are already in background wrt vdr
	sleep ${when}m
	svdrp_send "hitk power"
}

check_auto_retry() {
	if [ "${TRY_AGAIN}" -gt 0 -a "${ENABLE_AUTO_RETRY}" = 1 ]; then
		retry_shutdown ${TRY_AGAIN}
	fi
}

disable_auto_retry() {
	ENABLE_AUTO_RETRY=0
}

init() {
	SHUTDOWN_ABORT=0
	TRY_AGAIN=0
	ENABLE_AUTO_RETRY=1
}


init
init_forced_shutdown
execute_hooks

if is_shutdown_aborted; then
	mesg "No Shutdown: ${ABORT_MESSAGE}"
	check_forced_shutdown_possible_next_time
	check_auto_retry
	
	exit 0
fi


# TODO: Integrate code into here (+rewrite)
# Keep VDR_TIMER_NEXT here, instead of $@, as it could have been changed
/usr/share/vdr/bin/vdrshutdown-wakeup-helper.sh "${VDR_TIMER_NEXT}"

if [ $? != 0 ]; then
	mesg "setting wakeup time not successful"
	exit 1
fi

rm "${shutdown_data_dir}/shutdown-time-written"
date +%s > "${shutdown_data_dir}/shutdown-time-written"

if is_forced_shutdown && forced_tests_count_greater_zero; then
	mesg "User enforced shutdown"
else
	mesg "Shutting down"
fi

exit 0