~bart-samwel/laptop-mode-tools/main-before-tagging-was-invented

1 by Bart Samwel
Initial import
1
#!/bin/bash
2
3
# Script to start or stop laptop_mode, and to control various settings of the
4
# kernel, hardware etc. that influence power consumption.
5
#
6
# This script is a part of Laptop Mode Tools. If you are running a supported
7
# power management daemon, this script will be automatically called on power
8
# state change.
9
#
10
# Configure laptop mode tools in /etc/laptop-mode/laptop-mode.conf, and in
11
# the broken-out config files in /etc/laptop-mode/conf.d.
12
#
13
# Please consult the manual pages laptop-mode.conf(8) and laptop_mode(8) for
14
# additional information.
15
#
16
# Maintainer:       Bart Samwel (bart@samwel.tk)
3 by Bart Samwel
Fix up laptop mode home page URL in usr/sbin/laptop_mode
17
# Project homepage: http://samwel.tk/laptop_mode
1 by Bart Samwel
Initial import
18
#
19
# Contributors to this script:   Bart Samwel
20
#				 Kiko Piris
21
#				 Micha Feigin
22
#				 Andrew Morton
23
#				 Herve Eychenne
24
#				 Dax Kelson
25
#				 Jan Polacek
26
#				 ... and many others that I've stopped
27
#				 keeping track of.
28
#
29
# Based on a script for Linux 2.4 written by Jens Axboe.
30
31
#############################################################################
32
33
set -a
34
35
# The laptop mode tools version number. Extracted by the installer makefile
36
# as well, so don't change the format!
2 by Bart Samwel
Update version number; remove make dist (bzr export works quite well)
37
LMTVERSION=1.35
1 by Bart Samwel
Initial import
38
39
# This script is loaded from multiple scripts to set the config defaults
40
# and to read the configuration on top of those. Only when the command is
41
# recognized does this script do anything else.
42
VERBOSE_OUTPUT=0
43
ENABLE_LAPTOP_MODE_ON_BATTERY=1
44
ENABLE_LAPTOP_MODE_ON_AC=0
45
ENABLE_LAPTOP_MODE_WHEN_LID_CLOSED=0
46
PARTITIONS="auto /dev/mapper/*"
47
LM_BATT_MAX_LOST_WORK_SECONDS=600
48
LM_AC_MAX_LOST_WORK_SECONDS=360
49
DEF_MAX_AGE=30
50
LM_READAHEAD=3072
51
NOLM_READAHEAD=128
52
CONTROL_READAHEAD=1	
53
CONTROL_NOATIME=0
54
CONTROL_HD_IDLE_TIMEOUT=1
55
LM_AC_HD_IDLE_TIMEOUT=4    # 20 seconds
56
LM_BATT_HD_IDLE_TIMEOUT=4  # 20 seconds
57
NOLM_HD_IDLE_TIMEOUT=244   # 2 hours
58
DEF_UPDATE=5
59
DEF_XFS_AGE_BUFFER=15
60
DEF_XFS_SYNC_INTERVAL=30
61
DEF_XFS_BUFD_INTERVAL=1
62
XFS_HZ=100
63
CONTROL_MOUNT_OPTIONS=1
64
BATT_HD_POWERMGMT=1
4 by Bart Samwel
Change default HD power management values from 255 to 254
65
LM_AC_HD_POWERMGMT=254
66
NOLM_AC_HD_POWERMGMT=254
1 by Bart Samwel
Initial import
67
CONTROL_HD_POWERMGMT=0
68
CONTROL_HD_WRITECACHE=0
69
NOLM_AC_HD_WRITECACHE=1
70
NOLM_BATT_HD_WRITECACHE=0
71
LM_HD_WRITECACHE=0
72
LM_DIRTY_RATIO=60
73
LM_DIRTY_BACKGROUND_RATIO=1
74
NOLM_DIRTY_BACKGROUND_RATIO=10
75
NOLM_DIRTY_RATIO=40
76
LM_SECONDS_BEFORE_SYNC=2	
77
BATT_CPU_MAXFREQ=medium
78
BATT_CPU_MINFREQ=slowest
79
BATT_CPU_GOVERNOR=ondemand
80
BATT_CPU_IGNORE_NICE_LOAD=1
81
LM_AC_CPU_MAXFREQ=fastest
82
LM_AC_CPU_MINFREQ=slowest
83
LM_AC_CPU_GOVERNOR=ondemand
84
LM_AC_CPU_IGNORE_NICE_LOAD=1
85
NOLM_AC_CPU_MAXFREQ=fastest
86
NOLM_AC_CPU_MINFREQ=slowest
87
NOLM_AC_CPU_GOVERNOR=performance
88
NOLM_AC_CPU_IGNORE_NICE_LOAD=0
89
CONTROL_CPU_FREQUENCY=0
90
HD="/dev/[hs]d[abcdefgh]"
91
CONTROL_SYSLOG_CONF=0
92
LM_AC_SYSLOG_CONF=/etc/syslog-on-ac-with-lm.conf
93
NOLM_AC_SYSLOG_CONF=/etc/syslog-on-ac-without-lm.conf
94
BATT_SYSLOG_CONF=/etc/syslog-on-battery.conf
95
SYSLOG_CONF_SIGNAL_PROGRAM=syslogd
96
SYSLOG_CONF=/etc/syslog.conf
97
CONTROL_DPMS_STANDBY=0
98
BATT_DPMS_STANDBY=300
99
LM_AC_DPMS_STANDBY=1200
100
NOLM_AC_DPMS_STANDBY=1200
101
CONTROL_CPU_THROTTLING=0
102
BATT_CPU_THROTTLING=medium
103
LM_AC_CPU_THROTTLING=minimum
104
NOLM_AC_CPU_THROTTLING=minimum
105
CONTROL_START_STOP=1
106
CONTROL_TERMINAL=0
107
TERMINALS="/dev/vc/1 /dev/vcs1"
108
BATT_TERMINAL_BLANK_MINUTES=1
109
BATT_TERMINAL_POWERDOWN_MINUTES=2
110
LM_AC_TERMINAL_BLANK_MINUTES=10
111
LM_AC_TERMINAL_POWERDOWN_MINUTES=10
112
NOLM_AC_TERMINAL_BLANK_MINUTES=10
113
NOLM_AC_TERMINAL_POWERDOWN_MINUTES=50
114
ENABLE_AUTO_HIBERNATION=0
115
HIBERNATE_COMMAND=/usr/sbin/hibernate
116
AUTO_HIBERNATION_ON_CRITICAL_BATTERY_LEVEL=1
117
DISABLE_LAPTOP_MODE_ON_CRITICAL_BATTERY_LEVEL=1
118
AUTO_HIBERNATION_BATTERY_CHARGE_MAH=0
119
AUTO_HIBERNATION_BATTERY_CHARGE_MWH=0
120
MINIMUM_BATTERY_CHARGE_MAH=0
121
MINIMUM_BATTERY_CHARGE_MWH=0
122
ASSUME_SCSI_IS_SATA=1
123
CONTROL_BRIGHTNESS=0
124
BATT_BRIGHTNESS_COMMAND=false
125
LM_AC_BRIGHTNESS_COMMAND=false
126
NOLM_AC_BRIGHTNESS_COMMAND=false
127
128
# No default on these ones -- we need to detect if they have been set, for
129
# backward compatibility with MINIMUM_BATTERY_MINUTES etc.
130
AUTO_HIBERNATION_BATTERY_CHARGE_PERCENT=
131
MINIMUM_BATTERY_CHARGE_PERCENT=
132
133
# Backward compatibility variable that is sometimes
134
# set externally (Debian init system)
135
unset VERBOSE
136
137
# Source config.
138
if [ -r /etc/laptop-mode/laptop-mode.conf ] ; then
139
	. /etc/laptop-mode/laptop-mode.conf
140
else
141
	echo $0: Configuration file /etc/laptop-mode/laptop-mode.conf not present or not readable.
142
	exit 1
143
fi
144
if [ -d /etc/laptop-mode/conf.d ] ; then
15 by Bart Samwel
Centralize exports to modules; only read *.conf files from split-up config file conf.d
145
	for CONF in /etc/laptop-mode/conf.d/*.conf ; do
1 by Bart Samwel
Initial import
146
		if [ -r "$CONF" ] ; then
147
			. "$CONF"
148
		else
149
			echo "Warning: Configuration file $CONF is not readable, skipping."
150
		fi
151
	done
152
fi
153
154
# Support for old config settings
155
if [ "$AC_HD" != "" ] ; then
156
	AC_HD_WITHOUT_LM="$AC_HD"
157
	AC_HD_WITH_LM="$AC_HD"
158
fi
159
if [ "$VERBOSE" != "" ] ; then
160
	VERBOSE_OUTPUT="$VERBOSE"
161
fi
162
if [ "$CPU_MAXFREQ" != "" ] ; then
163
	BATT_CPU_MAXFREQ="$CPU_MAXFREQ"
164
fi
165
if [ "$MAX_AGE" != "" ] ; then
166
	LM_BATT_MAX_LOST_WORK_SECONDS="$MAX_AGE"
167
	LM_AC_MAX_LOST_WORK_SECONDS="$MAX_AGE"
168
fi
169
if [ "$DEF_AGE" != "" ] ; then
170
	DEF_MAX_AGE="$DEF_AGE"
171
fi
172
if [ "$LAPTOP_MODE_ALWAYS_ON" != "" ] ; then
173
	ENABLE_LAPTOP_MODE_ALWAYS="$LAPTOP_MODE_ALWAYS_ON"
174
fi
175
if [ "$LM_WHEN_LID_CLOSED" != "" ] ; then
176
	ENABLE_LAPTOP_MODE_WHEN_LID_CLOSED="$LM_WHEN_LID_CLOSED"
177
fi
178
if [ "$REMOUNT_PARTITIONS" != "" ] ; then
179
	PARTITIONS="$REMOUNT_PARTITIONS"
180
fi
181
if [ "$READAHEAD" != "" ] ; then
182
	LM_READAHEAD="$READAHEAD"
183
fi
184
if [ "$DO_REMOUNT_NOATIME" != "" ] ; then
185
	CONTROL_NOATIME="$DO_REMOUNT_NOATIME"
186
fi
187
if [ "$DO_HD" != "" ] ; then
188
	CONTROL_HD_IDLE_TIMEOUT="$DO_HD"
189
fi
190
if [ "$AC_HD_WITH_LM" != "" ] ; then
191
	LM_AC_HD_IDLE_TIMEOUT="$AC_HD_WITH_LM"
192
fi
193
if [ "$AC_HD_WITHOUT_LM" != "" ] ; then
194
	NOLM_HD_IDLE_TIMEOUT="$AC_HD_WITHOUT_LM"
195
fi
196
if [ "$BATT_HD" != "" ] ; then
197
	LM_BATT_HD_IDLE_TIMEOUT="$BATT_HD"
198
fi		
199
if [ "$DO_REMOUNTS" != "" ] ; then
200
	CONTROL_MOUNT_OPTIONS="$DO_REMOUNTS"
201
fi	
202
if [ "$DO_HD_POWERMGMT" != "" ] ; then
203
	CONTROL_HD_POWERMGMT="$DO_HD_POWERMGMT"
204
fi
205
if [ "$AC_HDPARM_POWERMGMT_WITH_LM" != "" ] ; then
206
	LM_AC_HD_POWERMGMT="$AC_HDPARM_POWERMGMT_WITH_LM"
207
fi
208
if [ "$AC_HDPARM_POWERMGMT_WITHOUT_LM" != "" ] ; then
209
	NOLM_AC_HD_POWERMGMT="$AC_HDPARM_POWERMGMT_WITHOUT_LM"
210
fi
211
if [ "$BATT_HDPARM_POWERMGMT" != "" ] ; then
212
	BATT_HD_POWERMGMT="$BATT_HDPARM_POWERMGMT"
213
fi
214
if [ "$DO_WRITECACHE" != "" ] ; then
215
	CONTROL_HD_WRITECACHE="$DO_WRITECACHE"
216
fi
217
if [ "$AC_WRITECACHE_WITHOUT_LM" != "" ] ; then
218
	NOLM_AC_HD_WRITECACHE="$AC_WRITECACHE_WITHOUT_LM"
219
fi
220
if [ "$BATT_WRITECACHE" != "" ] ; then
221
	LM_HD_WRITECACHE="$BATT_WRITECACHE"
222
fi
223
if [ "$DIRTY_RATIO" != "" ]; then
224
	LM_DIRTY_RATIO="$DIRTY_RATIO"
225
fi
226
if [ "$DIRTY_BACKGROUND_RATIO" != "" ] ; then
227
	LM_DIRTY_BACKGROUND_RATIO="$DIRTY_BACKGROUND_RATIO"
228
fi
229
if [ "$DEF_DIRTY_RATIO" != "" ]; then
230
	NOLM_DIRTY_RATIO="$DEF_DIRTY_RATIO"
231
fi
232
if [ "$DEF_DIRTY_BACKGROUND_RATIO" != "" ] ; then
233
	NOLM_DIRTY_BACKGROUND_RATIO="$DEF_DIRTY_BACKGROUND_RATIO"
234
fi
235
if [ "$DO_CPU" != "" ] ; then
236
	CONTROL_CPU_FREQUENCY="$DO_CPU"
237
fi
238
if [ "$CONTROL_CPU_MAXFREQ" != "" ] ; then
239
	CONTROL_CPU_FREQUENCY="$CONTROL_CPU_MAXFREQ"
240
fi
241
if [ "$AC_CPU_MAXFREQ_WITH_LM" != "" ] ; then
242
	LM_AC_CPU_MAXFREQ="$AC_CPU_MAXFREQ_WITH_LM"
243
fi
244
if [ "$AC_CPU_MAXFREQ_WITHOUT_LM" != "" ] ; then
245
	NOLM_AC_CPU_MAXFREQ="$AC_CPU_MAXFREQ_WITHOUT_LM"
246
fi
247
if [ "$DO_SYSLOG" != "" ] ; then
248
	CONTROL_SYSLOG_CONF="$DO_SYSLOG"
249
fi
250
if [ "$SYSLOG_SIGNAL_PROGRAM" != "" ] ;then
251
	SYSLOG_CONF_SIGNAL_PROGRAM="$SYSLOG_SIGNAL_PROGRAM"
252
fi
253
if [ "$AC_SYSLOG_WITH_LM" != "" ] ; then
254
	LM_AC_SYSLOG_CONF="$AC_SYSLOG_WITH_LM"
255
fi
256
if [ "$AC_SYSLOG_WITHOUT_LM" != "" ] ; then
257
	NOLM_AC_SYSLOG_CONF="$AC_SYSLOG_WITHOUT_LM"
258
fi
259
if [ "$BATT_SYSLOG" != "" ] ; then
260
	BATT_SYSLOG_CONF="$BATT_SYSLOG"
261
fi
262
if [ "$ENABLE_LAPTOP_MODE_ALWAYS" != "" ] ; then
263
	ENABLE_LAPTOP_MODE_ON_AC="$ENABLE_LAPTOP_MODE_ALWAYS"
264
fi
265
if [ "$MINIMUM_BATTERY_MINUTES" != "" -a "$MINIMUM_BATTERY_CHARGE_PERCENT" == "" ] ; then
266
	# Use a very conservative estimate (1% = 1 battery minute, 100 minutes in a battery)
267
	# for backward compatibility.
268
	MINIMUM_BATTERY_CHARGE_PERCENT="$MINIMUM_BATTERY_MINUTES"
269
fi
270
if [ -z "$MINIMUM_BATTERY_CHARGE_PERCENT" ] ; then
271
	# Apply the default, now that we've determined that this is the minimum.
272
	MINIMUM_BATTERY_CHARGE_PERCENT=3
273
fi
274
if [ "$AUTO_HIBERNATION_BATTERY_MINUTES" != "" -a "$AUTO_HIBERNATION_BATTERY_CHARGE_PERCENT" == "" ] ; then
275
	# Use a very conservative estimate (1% = 1 battery minute, 100 minutes in a battery)
276
	# for backward compatibility.
277
	AUTO_HIBERNATION_BATTERY_CHARGE_PERCENT="$AUTO_HIBERNATION_BATTERY_MINUTES"
278
fi
279
if [ -z "$AUTO_HIBERNATION_BATTERY_CHARGE_PERCENT" ] ; then
280
	# Apply the default, now that we've determined that this is the minimum.
281
	AUTO_HIBERNATION_BATTERY_CHARGE_PERCENT=2
282
fi
283
284
285
# Postprocessing
286
if [ "$VERBOSE_OUTPUT" -ne 0 ] ; then
287
	OUTPUT="/dev/stdout"
288
else
289
	OUTPUT="/dev/null"
290
fi
291
292
if [ "$PARTITIONS" == "" ] ; then
293
	PARTITIONS="auto /dev/mapper/*"
294
fi
295
296
297
# Expand shell wild cards immediately.
298
PARTITIONS=$( echo $PARTITIONS )
299
TERMINALS=$( echo $TERMINALS )
300
301
# Convert seconds to hdparm -S format
302
# Everything over 20 minutes is interpreted as 2 hours.
303
seconds_to_hdparm_S() {
304
  if [ "$1" -eq 0 ] ; then
305
	# disable.
306
	echo 0
307
 elif [ "$1" -gt 0 -a "$1" -lt 5 ] ; then
308
	# 5 seconds minimum
309
	echo 1 	
310
  elif [ "$1" -le $((240*5)) ] ; then
311
	# Values between 1 and 240 signify increments of 5 seconds
312
	echo $(($1 / 5))
313
  elif [ "$1" -lt $((30*60)) ] ; then
314
	# Values between 20 and 30 minutes are rounded up to 30 minutes.
315
	echo 241
316
  elif [ "$1" -lt $((12*30*60)) ] ; then
317
	# Values between 30 minutes and 6 hours (exclusive) yield values between
318
	# 241 and 251, in 30-minute increments.
319
	echo $(( 240 + ($1 / (30*60)) ))
320
  else
321
	# Larger values effectively indicate no timeout at all.
322
	echo 0
323
  fi
324
}
325
326
# Convert configured idle timeouts to hdparm -S format.
327
if [ "$LM_AC_HD_IDLE_TIMEOUT_SECONDS" != "" ] ; then
328
	LM_AC_HD_IDLE_TIMEOUT=$(seconds_to_hdparm_S $LM_AC_HD_IDLE_TIMEOUT_SECONDS)
329
fi
330
if [ "$LM_BATT_HD_IDLE_TIMEOUT_SECONDS" != "" ] ; then
331
	LM_BATT_HD_IDLE_TIMEOUT=$(seconds_to_hdparm_S $LM_BATT_HD_IDLE_TIMEOUT_SECONDS)
332
fi
333
if [ "$NOLM_HD_IDLE_TIMEOUT_SECONDS" != "" ] ; then
334
	NOLM_HD_IDLE_TIMEOUT=$(seconds_to_hdparm_S $NOLM_HD_IDLE_TIMEOUT_SECONDS)
335
fi
336
337
if [ "$1" == "status" ] ; then
338
	# Display a status report.
339
	echo Mounts:
340
	mount | sed "s/^/   /"
341
	echo
342
	echo Drive power status:
6 by Bart Samwel
laptop-mode.conf world-readable by default; better error messages when laptop_mode status is called by a non-root user.
343
	for disk in $HD; do
344
		if [ -r $disk ]; then
345
			hdparm -C $disk 2>/dev/null | sed "s/^/   /"
346
		else
347
			echo "   Cannot read $disk, permission denied - $0 needs to be run as root"
348
		fi
349
	done
1 by Bart Samwel
Initial import
350
	echo
351
	echo "(NOTE: drive settings affected by Laptop Mode cannot be retrieved.)"
352
	echo
353
	echo Readahead states:
354
	cat /etc/mtab | while read DEV MP FST OPTS DUMP PASS ; do
355
		if [ -b $DEV ] ; then
6 by Bart Samwel
laptop-mode.conf world-readable by default; better error messages when laptop_mode status is called by a non-root user.
356
			if [ -r $DEV ] ; then
357
				echo "   $DEV: $((`blockdev --getra $DEV` / 2)) kB"
358
			else
359
				echo "   Cannot read $DEV, permission denied - $0 needs to be run as root"
360
			fi
1 by Bart Samwel
Initial import
361
		fi
362
	done
363
	echo
9 by Bart Samwel
Move /var/run/laptop-mode-* to /var/run/laptop-mode-tools/*
364
	if [ -e /var/run/laptop-mode-tools/enabled ] ; then
365
		echo Laptop Mode Tools is allowed to run: /var/run/laptop-mode-tools/enabled exists.
1 by Bart Samwel
Initial import
366
	else
9 by Bart Samwel
Move /var/run/laptop-mode-* to /var/run/laptop-mode-tools/*
367
		echo Laptop Mode Tools is NOT allowed to run: /var/run/laptop-mode-tools/enabled does not exist.
1 by Bart Samwel
Initial import
368
	fi
369
	echo
370
	STATFILES="/proc/sys/vm/laptop_mode /proc/apm /proc/pmu/info /proc/sys/vm/bdflush /proc/sys/vm/dirty_ratio /proc/sys/fs/xfs/age_buffer /proc/sys/fs/xfs/sync_interval /proc/sys/fs/xfs/lm_age_buffer /proc/sys/fs/xfs/lm_sync_interval /proc/sys/vm/pagebuf/lm_flush_age /proc/sys/fs/xfs/xfsbufd_centisecs /proc/sys/fs/xfs/xfssyncd_centisecs /proc/sys/vm/dirty_background_ratio /proc/sys/vm/dirty_expire_centisecs /proc/sys/fs/xfs/age_buffer/centisecs /proc/sys/vm/dirty_writeback_centisecs /sys/devices/system/cpu/*/cpufreq/cpuinfo_*_freq /sys/devices/system/cpu/*/cpufreq/scaling_governor /proc/acpi/button/lid/*/state /proc/acpi/ac_adapter/*/state /proc/acpi/battery/*/state"
371
	for THISFILE in $STATFILES ; do
372
		if [ -e $THISFILE ] ; then
373
			echo $THISFILE:
374
			if [ -r $THISFILE ] ; then
375
				cat $THISFILE | sed "s/^/   /"
376
			else
6 by Bart Samwel
laptop-mode.conf world-readable by default; better error messages when laptop_mode status is called by a non-root user.
377
				echo "   Not accessible, permission denied - $0 needs to be run as root."
1 by Bart Samwel
Initial import
378
			fi
379
			echo
380
		fi
381
	done
382
383
elif [ "$1" != "readconfig" -a "$1" != "defaults" ] ; then
384
385
#############################################################################
386
387
KLEVEL="$(uname -r |
388
			 {
389
				 IFS='.-' read a b c
390
				 echo $a.$b
391
			 }
392
)"
393
KMINOR="$(uname -r |
394
			{
395
				IFS='.-' read a b c d
396
				echo $c
397
			}
398
)"
399
400
case "$KLEVEL" in
401
	"2.4" ) ;;
402
	"2.6" ) ;;
403
	*)
404
		echo "Unhandled kernel version: $KLEVEL ('uname -r' = '$(uname -r)')" >&2
405
		exit 1
406
		;;
407
esac
408
409
410
411
# Stop exporting everything -- what we do from here is private.
412
set +a
413
414
if [ "$1" == "--version" ] ; then
415
	echo "Laptop Mode Tools $LMTVERSION"
416
	exit 0
417
fi
418
echo "Laptop Mode Tools $LMTVERSION" >> $OUTPUT
419
420
if [ ! -e /proc/sys/vm/laptop_mode ] ; then
421
	echo "Kernel does not have support for laptop mode. Please apply the laptop mode" >&2
422
	echo "patch or install a newer kernel." >&2
423
	exit 1
424
fi
425
426
if [ ! -w /proc/sys/vm/laptop_mode ] ; then
427
	echo "You do not have enough privileges to enable laptop_mode." >&2
428
	exit 1
429
fi
430
431
# Remove an option (the first parameter) of the form option=<number> from
432
# a mount options string (the rest of the parameters).
433
remove_numeric_mount_option () {
434
	OPT="$1"
435
	shift
436
	echo ",$*," | sed		\
437
	 -e 's|,'"$OPT"'=[0-9]*,|,|g'	\
438
	 -e 's/,,*/,/g'			\
439
	 -e 's/^,//'			\
440
	 -e 's/,$//'
441
}
442
443
# Remove an option (the first parameter) without any arguments from
444
# a mount option string (the rest of the parameters).
445
remove_yesno_mount_option () {
446
	OPT="$1"
447
	shift
448
	echo ",$*," | sed		\
449
	 -e 's|,'"$OPT"',|,|g'		\
450
	 -e 's/,,*/,/g'			\
451
	 -e 's/^,//'			\
452
	 -e 's/,$//'
453
}
454
455
# Find out the state of a yes/no option (e.g. "atime"/"noatime") in
456
# a set of mount options, and use this state to replace the
457
# value of the option in another mount options string.
458
#
459
# Example:
460
# replace_yesno_mount_option atime atime defaults,user=1000,atime defaults,noatime
461
#
462
# This yields "defaults,atime".
463
replace_yesno_mount_option () {
464
	OPT="$1"
465
	DEF_OPT="$2"
466
	REPLACEMENT_OPTS="$3"
467
	OPTS="$4"
468
	PARSEDOPTS="$(remove_yesno_mount_option $OPT $OPTS)"
469
	PARSEDOPTS="$(remove_yesno_mount_option no$OPT $PARSEDOPTS)"
470
471
	if echo ",$REPLACEMENT_OPTS," | grep ",no$OPT," > /dev/null ; then
472
		echo "$PARSEDOPTS,no$OPT"
473
	elif echo ",$REPLACEMENT_OPTS," | grep ",$OPT," > /dev/null ; then
474
		echo "$PARSEDOPTS,$OPT"
475
	else
476
		echo "$PARSEDOPTS,$DEF_OPT"
477
	fi
478
}
479
480
# Find out the state of a numbered option (e.g. "commit=NNN") in
481
# a set of options, and use this state to replace the
482
# value of the option in another mount options string. 
483
#
484
# Example:
485
# replace_numeric_mount_option commit defaults,user=1000,commit=3 defaults,commit=7
486
#
487
# This example yields "defaults,commit=3".
488
replace_numeric_mount_option () {
489
	OPT="$1"
490
	DEF_OPT="$2"
491
	REPLACEMENT_OPTS="$3"
492
	OPTS="$4"	
493
	PARSEDOPTS="$(remove_numeric_mount_option $OPT $OPTS)"
494
	
495
	if echo ",$REPLACEMENT_OPTS," | grep ",$OPT=[0123456789]+," > /dev/null ; then
496
		echo -n "$PARSEDOPTS,$OPT="
497
		echo ",$REPLACEMENT_OPTS," | sed \
498
		 -e 's/.*,'"$OPT"'=//'	\
499
		 -e 's/,.*//'
500
	else
501
		# Option not present in REPLACEMENT_OPTS: use the default.
502
		echo "$PARSEDOPTS,$DEF_OPT"
503
	fi
504
}
505
506
deduce_fstype () {
507
	MP="$1"
508
	# My root filesystem unfortunately has type "unknown" in
509
	# /etc/mtab. If we encounter "unknown", we try to get the
510
	# type from fstab. This still might be wrong, in which
511
	# case the code further down will issue a big warning.
512
	cat /etc/fstab |
513
	sed 's/[[:space:]]*#.*$//' |
514
	while read FSTAB_DEV FSTAB_MP FSTAB_FST FSTAB_OPTS FSTAB_DUMP FSTAB_DUMP ; do
515
		if [ "$FSTAB_MP" = "$MP" ]; then
516
			echo $FSTAB_FST
517
			exit 0
518
		fi
519
	done
520
}
521
522
if [ $CONTROL_NOATIME -eq 1 ] ; then
523
	NOATIME_OPT=",noatime"
524
fi
525
526
INIT=0          # Display info in init script format?
527
FORCE=0         # Force reapplying the current state?
528
while [ "$1" != "" ] ; do
529
	case "$1" in 
530
		init) INIT=1 ;;
531
		force) FORCE=1 ;;
532
		# Old options. We always do "auto" for any option now, but
533
		# we still have to accept the options.
534
		start) ;;
535
		stop) ;;
536
		auto) ;;
537
		*) echo "Unrecognized option $1."
538
		   exit 1 ;;
539
	esac
540
	shift
541
done
542
9 by Bart Samwel
Move /var/run/laptop-mode-* to /var/run/laptop-mode-tools/*
543
mkdir -p /var/run/laptop-mode-tools
544
1 by Bart Samwel
Initial import
545
# Used to display laptop mode state later on. This is the enabled/disabled 
546
# state for laptop mode processing, it tells us nothing about whether laptop
547
# mode is actually _active_.
15 by Bart Samwel
Centralize exports to modules; only read *.conf files from split-up config file conf.d
548
STATE=enabled
1 by Bart Samwel
Initial import
549
if [ "$ENABLE_LAPTOP_MODE_ON_BATTERY" -eq 0 -a "$ENABLE_LAPTOP_MODE_ON_AC" -eq 0 -a "$ENABLE_LAPTOP_MODE_WHEN_LID_CLOSED" -eq 0 ] ; then
550
	STATE=disabled
551
fi
552
553
# Determine the power state.
15 by Bart Samwel
Centralize exports to modules; only read *.conf files from split-up config file conf.d
554
ON_AC=1
1 by Bart Samwel
Initial import
555
556
if [ -d /proc/acpi/ac_adapter ] ; then
557
	ADAPTERS_FOUND=0
558
	ON_AC=0
559
	for ADAPTER in /proc/acpi/ac_adapter/* ; do
560
		if [ -f $ADAPTER/state ] ; then
561
			ADAPTERS_FOUND=1
562
			STATUS=`awk '/^state: / { print $2 }' $ADAPTER/state`
563
			if [ "$STATUS" = "on-line" ] ; then
564
				ON_AC=1
565
			fi
566
		fi
567
	done
568
	if [ "$ADAPTERS_FOUND" -eq 0 ] ; then
569
		ON_AC=1
570
	fi
571
elif [ -f /proc/apm ] ; then
572
	read D1 D2 D3 APM_AC_STATE D0 </proc/apm
573
	if [ "$APM_AC_STATE" = "0x00" ] ; then
574
		ON_AC=0
575
	else
576
		ON_AC=1
577
	fi
578
elif [ -f /proc/pmu/info ] ; then
579
	if ( grep "^AC Power.*0$" /proc/pmu/info ) ; then
580
		echo "/proc/pmu/info indicates absence of AC power." >> $OUTPUT
581
		ON_AC=0
582
	else
583
		# It is possible that there is no AC Power = 1 in the file,
584
		# but we always assume AC power when we're not sure.
585
		ON_AC=1
586
		echo "/proc/pmu/info indicates presence of AC power." >> $OUTPUT
587
	fi
588
else
589
	echo "No ACPI, APM or PMU power management information found -- assuming AC power is present." >> $OUTPUT
590
fi
591
592
593
594
# Determine whether to activate or deactivate laptop mode.
15 by Bart Samwel
Centralize exports to modules; only read *.conf files from split-up config file conf.d
595
ACTIVATE=0
1 by Bart Samwel
Initial import
596
597
if [ "$ON_AC" -eq 1 ] ; then
598
	if [ "$ENABLE_LAPTOP_MODE_ON_AC" -ne 0 ] ; then
599
		echo "On AC power: Activating, because ENABLE_LAPTOP_MODE_ON_AC is set." >> $OUTPUT
600
		ACTIVATE=1
601
	else
602
		echo "On AC power: Deactivating, because ENABLE_LAPTOP_MODE_ON_AC is not set." >> $OUTPUT
603
		ACTIVATE=0
604
	fi
605
else
606
	if [ "$ENABLE_LAPTOP_MODE_ON_BATTERY" -ne 0 ] ; then
607
		echo "On battery power: Activating, because ENABLE_LAPTOP_MODE_ON_BATTERY is set." >> $OUTPUT
608
		ACTIVATE=1
609
	else
610
		echo "On battery power: Deactivating, because ENABLE_LAPTOP_MODE_ON_BATTERY is not set." >> $OUTPUT
611
		ACTIVATE=0
612
	fi
613
fi
614
615
if [ "$ENABLE_LAPTOP_MODE_WHEN_LID_CLOSED" -ne 0 ] ; then
616
	if [ -f /proc/acpi/button/lid/*/state ] ; then
617
		if ( cat /proc/acpi/button/lid/*/state | grep "closed" ) ; then
618
			echo "Setting action to \"start\" because the lid is closed." >> $OUTPUT
619
			ACTIVATE=1
620
		fi
621
	else
622
		echo "Warning: ENABLE_LAPTOP_MODE_WHEN_LID_CLOSED is set, but there is no file"
623
		echo "/proc/acpi/button/lid/.../state!"
624
	fi
625
fi
626
627
# If the init script has not been run or has been run with the "stop"
628
# argument, then we should never start laptop mode.
9 by Bart Samwel
Move /var/run/laptop-mode-* to /var/run/laptop-mode-tools/*
629
if [ ! -f /var/run/laptop-mode-tools/enabled ] ; then
630
	echo "Laptop mode disabled because /var/run/laptop-mode-tools/enabled is missing." >> $OUTPUT
1 by Bart Samwel
Initial import
631
	STATE=disabled
632
fi
633
634
if [ "$ACTIVATE" -eq 1 -a -f /etc/default/laptop-mode ] ; then
635
	. /etc/default/laptop-mode
636
	if ! ( echo "$ENABLE_LAPTOP_MODE" |grep y ) ; then
637
		echo "Not starting laptop mode because it is disabled in /etc/default/laptop-mode." >> $OUTPUT
638
		STATE=disabled
639
	fi
640
fi
641
642
if [ "$STATE" == "disabled" ] ; then
643
	ACTIVATE=0
644
fi
645
646
# Check whether we are allowed to activate the data-loss-sensitive stuff.
647
# If the battery charge is too low, we want to disable this, but not the
648
# other power-saving stuff.
649
650
if [ "$ACTIVATE" -eq 0 ] ; then
651
	ACTIVATE_WITH_POSSIBLE_DATA_LOSS=0
652
else
653
	ACTIVATE_WITH_POSSIBLE_DATA_LOSS=1
654
	if [ ! -d /proc/acpi ] ; then
655
		echo "Not ACPI -> no support for minimum battery charge checking." >> $OUTPUT
656
	elif [ "$ON_AC" -eq 0 ] ; then
657
		echo "On ACPI and not on AC -- checking minimum battery charge." >> $OUTPUT
658
		ENOUGH_CHARGE=0
659
		ENOUGH_CHARGE_TO_PREVENT_HIBERNATION=0
660
		for BATT in /proc/acpi/battery/* ; do
661
			PREV_ENOUGH_CHARGE=$ENOUGH_CHARGE
662
			PREV_ENOUGH_CHARGE_TO_PREVENT_HIBERNATION=$ENOUGH_CHARGE_TO_PREVENT_HIBERNATION
663
664
			BATT_STATE=$BATT/state
665
			BATT_INFO=$BATT/info
666
			echo "Checking info and state for $BATT." >> $OUTPUT
667
668
			# Only do if the battery is present
669
			if ( cat $BATT_INFO | grep "present:.*yes" > /dev/null ) ; then
670
				FOUND_AN_ENABLED_CHECK=0
671
				FOUND_AN_ENABLED_HIBERNATION_CHECK=0
672
				
673
				# Get the remaining capacity.
674
				REMAINING=`cat $BATT_STATE | grep "remaining capacity:" | sed  "s/.* \([0-9][0-9]* \).*/\1/" `
675
				if [ -z "$REMAINING" ] ; then
676
					echo "Battery does not report remaining capacity. Perhaps it is not present?" >> $OUTPUT
677
					REMAINING=0
678
				fi
679
				echo "Remaining charge: $REMAINING" >> $OUTPUT
680
	
681
				CAPACITY=`cat $BATT_INFO | grep "design capacity:" | sed  "s/.* \([0-9][0-9]* \).*/\1/" `
682
				if [ -z "$CAPACITY" ] ; then
683
					CAPACITY=0
684
				fi
685
				echo "Design capacity: $CAPACITY" >> $OUTPUT
686
	
687
				# Check the charge percentage
688
				if [ "$MINIMUM_BATTERY_CHARGE_PERCENT" -ne 0 ] ; then
689
					FOUND_AN_ENABLED_CHECK=1
690
					if [ "$CAPACITY" -eq 0 ] ; then
691
						echo "WARNING: Battery does not report a design capacity. Minimum battery"
692
						echo "charge checking does not work without a design capacity."
693
					elif [ "$(($REMAINING * 100 / $CAPACITY))" -ge "$MINIMUM_BATTERY_CHARGE_PERCENT" ] ; then
694
						ENOUGH_CHARGE=1
695
					fi
696
				fi
697
				if [ "$AUTO_HIBERNATION_BATTERY_CHARGE_PERCENT" -ne 0 ] ; then
698
					FOUND_AN_ENABLED_HIBERNATION_CHECK=1
699
					if [ "$CAPACITY" -eq 0 ] ; then
700
						echo "WARNING: Battery does not report a design capacity. Auto hibernation"
701
						echo "does not work without a design capacity."
702
					elif [ "$(($REMAINING * 100 / $CAPACITY))" -ge "$AUTO_HIBERNATION_BATTERY_CHARGE_PERCENT" ] ; then
703
						ENOUGH_CHARGE_TO_PREVENT_HIBERNATION=1
704
					fi
705
				fi
706
	
707
				#
708
				# Fallback: hard values.
709
				#
710
				# Determine the reporting unit.
711
				IN_MAH=0
712
				IN_MWH=0
713
				if ( cat $BATT_INFO | grep mWh > /dev/null ) ; then
714
					IN_MWH=1
715
				elif ( cat $BATT_INFO | grep mAh > /dev/null ) ; then
716
					IN_MAH=1
717
				fi
718
				
719
				if [ "$IN_MAH" -ne 0 ] ; then
720
					if [ "$MINIMUM_BATTERY_CHARGE_MAH" -ne 0 ] ; then
721
						FOUND_AN_ENABLED_CHECK=1
722
						if [ "$REMAINING" -ge "$MINIMUM_BATTERY_CHARGE_MAH" ] ; then
723
							ENOUGH_CHARGE=1
724
						fi
725
					fi
726
					if [ "$AUTO_HIBERNATION_BATTERY_CHARGE_MAH" -ne 0 ] ; then
727
						FOUND_AN_ENABLED_HIBERNATION_CHECK=1
728
						if [ "$REMAINING" -ge "$AUTO_HIBERNATION_BATTERY_CHARGE_MAH" ] ; then
729
							ENOUGH_CHARGE_TO_PREVENT_HIBERNATION=1
730
						fi
731
					fi
732
				elif [ "$IN_MWH" -ne 0 ] ; then
733
					if [ "$MINIMUM_BATTERY_CHARGE_MWH" -ne 0 ] ; then
734
						FOUND_AN_ENABLED_CHECK=1
735
						if [ "$REMAINING" -ge "$MINIMUM_BATTERY_CHARGE_MWH" ] ; then
736
							ENOUGH_CHARGE=1
737
						fi
738
					fi
739
					if [ "$AUTO_HIBERNATION_BATTERY_CHARGE_MWH" -ne 0 ] ; then
740
						FOUND_AN_ENABLED_HIBERNATION_CHECK=1
741
						if [ "$REMAINING" -ge "$AUTO_HIBERNATION_BATTERY_CHARGE_MWH" ] ; then
742
							ENOUGH_CHARGE_TO_PREVENT_HIBERNATION=1
743
						fi
744
					fi
745
				else
746
					echo "Failed to determine battery charge. Battery charge units are not in"
747
					echo "mWh or mAh."
748
				fi
749
				
750
				CAP_STATE=`cat "$BATT_STATE" | sed -r 's/^capacity state:\s*(.*)\s*$/\1/;t;d'`
751
				if [ "$DISABLE_LAPTOP_MODE_ON_CRITICAL_BATTERY_LEVEL" -ne 0 ] ; then
752
					if [ "$CAP_STATE" == "critical" ] ; then				
753
						# Restore the state we had before checking this battery, so that
754
						# this battery does not count as having enough charge.
755
						ENOUGH_CHARGE=$PREV_ENOUGH_CHARGE
756
					elif [ "$FOUND_AN_ENABLED_CHECK" -eq 0 ] ; then
757
						# This is the only check that is enabled. In that case a non-critical
758
						# battery level counts as "enough". (If we would count non-critical
759
						# battery levels as enough *always*, then the other settings would
760
						# have no effect; this is only a final fallback.)
761
						ENOUGH_CHARGE=1
762
					fi
763
				fi
764
				if [ "$AUTO_HIBERNATION_ON_CRITICAL_BATTERY_LEVEL" -ne 0 ] ; then
765
					if [ "$CAP_STATE" == "critical" ] ; then				
766
						ENOUGH_CHARGE_TO_PREVENT_HIBERNATION=$PREV_ENOUGH_CHARGE_TO_PREVENT_HIBERNATION
767
					elif [ "$FOUND_AN_ENABLED_HIBERNATION_CHECK" -eq 0 ] ; then
768
						ENOUGH_CHARGE_TO_PREVENT_HIBERNATION=1
769
					fi
770
				fi
771
			else
772
				echo "Battery is not present." >> $OUTPUT
773
			fi
774
		done
775
		if [ "$ENABLE_AUTO_HIBERNATION" -ne 0 -a "$ENOUGH_CHARGE_TO_PREVENT_HIBERNATION" -eq 0 ] ; then
776
			echo "None of the batteries have a charge above the auto-hibernation level." >> $OUTPUT
777
			echo "Starting hibernation." >> $OUTPUT
778
			$HIBERNATE_COMMAND
779
			# Don't continue -- if things are configured correctly, then we
780
			# will be called on resume.
781
			exit 0			
782
		fi
783
		if [ "$ENOUGH_CHARGE" -eq 0 ] ; then
784
			echo "None of the batteries have a charge above the minimum level." >> $OUTPUT
785
			echo "Deactivating data loss sensitive features." >> $OUTPUT
786
			ACTIVATE_WITH_POSSIBLE_DATA_LOSS=0
787
		fi
788
	fi
789
fi
790
791
if [ "$INIT" -eq 0 ] ; then
792
	echo -n "Laptop mode "
793
fi
794
9 by Bart Samwel
Move /var/run/laptop-mode-* to /var/run/laptop-mode-tools/*
795
# WAS_ACTIVE is used later on. If there is no /var/run/laptop-mode-tools/state, then
1 by Bart Samwel
Initial import
796
# we know that laptop mode wasn't active before.
797
WAS_ACTIVE=0
798
echo Checking if desired state is different from current state. >> $OUTPUT
9 by Bart Samwel
Move /var/run/laptop-mode-* to /var/run/laptop-mode-tools/*
799
if [ -f /var/run/laptop-mode-tools/state ] ; then
800
	read WAS_ACTIVE WAS_ON_AC WAS_ACTIVATE_WITH_POSSIBLE_DATA_LOSS < /var/run/laptop-mode-tools/state
1 by Bart Samwel
Initial import
801
	if [ "$WAS_ON_AC" != "" ] ; then
802
		if [ "$WAS_ACTIVE" -eq "$ACTIVATE" -a "$WAS_ON_AC" -eq "$ON_AC" -a "$WAS_ACTIVATE_WITH_POSSIBLE_DATA_LOSS" -eq "$ACTIVATE_WITH_POSSIBLE_DATA_LOSS" -a "$FORCE" -eq 0 ] ; then
803
			echo -n "$STATE, "
804
			if [ "$WAS_ACTIVE" -eq 1 ] ; then
805
				echo -n "active [unchanged]"
806
				if [ "$ACTIVATE_WITH_POSSIBLE_DATA_LOSS" -eq 0 ] ; then
807
					echo -n ' (Data-loss sensitive features disabled.)'
808
				fi
809
				echo
810
			else
811
				echo "not active [unchanged]"
812
			fi
813
			exit 0
814
		fi
815
	fi
816
else
9 by Bart Samwel
Move /var/run/laptop-mode-* to /var/run/laptop-mode-tools/*
817
	echo "/var/run/laptop-mode-tools/state does not exist, no previous state." >> $OUTPUT
1 by Bart Samwel
Initial import
818
fi
9 by Bart Samwel
Move /var/run/laptop-mode-* to /var/run/laptop-mode-tools/*
819
echo $ACTIVATE $ON_AC $ACTIVATE_WITH_POSSIBLE_DATA_LOSS > /var/run/laptop-mode-tools/state
1 by Bart Samwel
Initial import
820
821
if [ "$ACTIVATE" -eq 1 ] ; then
822
	echo -n "$STATE, active."
823
	if [ "$ACTIVATE_WITH_POSSIBLE_DATA_LOSS" -eq 0 ] ; then
824
		echo -n ' (Data-loss sensitive features disabled.)'
825
	fi
826
	echo
827
else
828
	echo "$STATE, not active."
829
fi
830
831
832
833
# Adjust CPU speed first -- that way, response to a switch to AC power will be faster,
834
# while switching to battery will take place while we're taking less power on the whole.
835
836
#
837
# get_medium_value
838
#
839
#   Get the medium value from a list of numerical values.
840
#   $1 = file containing the list of values
841
#
842
get_medium_value() {
843
	cat "$1" | sed 's/ /\n/g' | sort -n | awk -v RS="" '{n=split($0,a); print a[int((n+1)/2)]}'
844
}
845
846
# Set kernel setting, showing an error if this fails.
847
# Parameter 1: sysctl/proc path
848
# Parameter 2: the value
849
set_sysctl() {
850
	echo "Executing: echo $2 > $1" >> $OUTPUT
851
	if ! echo "$2" > "$1" ; then
852
		echo "SETTING OF KERNEL PARAMETER FAILED: echo $2 \> $1"
853
	fi
854
}
855
export set_sysctl
856
857
if [ $CONTROL_CPU_FREQUENCY -eq 1 ] ; then
858
	if [ $ON_AC -eq 1 ] ; then
859
		if [ "$ACTIVATE" -eq 1 ] ; then
860
			CPU_MAXFREQ="$LM_AC_CPU_MAXFREQ"
861
			CPU_MINFREQ="$LM_AC_CPU_MINFREQ"
862
			CPU_GOVERNOR="$LM_AC_CPU_GOVERNOR"
863
			CPU_IGNORE_NICE_LOAD="$LM_AC_CPU_IGNORE_NICE_LOAD"
864
		else
865
			CPU_MAXFREQ="$NOLM_AC_CPU_MAXFREQ"
866
			CPU_MINFREQ="$NOLM_AC_CPU_MINFREQ"
867
			CPU_GOVERNOR="$NOLM_AC_CPU_GOVERNOR"
868
			CPU_IGNORE_NICE_LOAD="$NOLM_AC_CPU_IGNORE_NICE_LOAD"
869
		fi
870
	else
871
		CPU_MAXFREQ="$BATT_CPU_MAXFREQ"
872
		CPU_MINFREQ="$BATT_CPU_MINFREQ"
873
		CPU_GOVERNOR="$BATT_CPU_GOVERNOR"
874
		CPU_IGNORE_NICE_LOAD="$BATT_CPU_IGNORE_NICE_LOAD"
875
	fi
876
	for THISCPU in /sys/devices/system/cpu/* ; do
877
		if [ -e $THISCPU/cpufreq/cpuinfo_min_freq ]; then
878
			THIS_CPU_MAXFREQ="$CPU_MAXFREQ"
879
			THIS_CPU_MINFREQ="$CPU_MINFREQ"
880
			THIS_CPU_GOVERNOR="$CPU_GOVERNOR"
881
			THIS_CPU_IGNORE_NICE_LOAD="$CPU_IGNORE_NICE_LOAD"
882
			if [ "$CPU_MAXFREQ" = "slowest" ]; then
883
				THIS_CPU_MAXFREQ=`cat $THISCPU/cpufreq/cpuinfo_min_freq`
884
			fi
885
			if [ "$CPU_MINFREQ" = 'slowest' ]; then
886
				THIS_CPU_MINFREQ=`cat $THISCPU/cpufreq/cpuinfo_min_freq`
887
			fi
888
			if [ "$CPU_MAXFREQ" = "medium" ] ; then
889
				THIS_CPU_MAXFREQ=$(get_medium_value $THISCPU/cpufreq/scaling_available_frequencies)
890
			fi
891
			if [ "$CPU_MINFREQ" = "medium" ] ; then
892
				THIS_CPU_MINFREQ=$(get_medium_value $THISCPU/cpufreq/scaling_available_frequencies)
893
			fi
894
			if [ "$CPU_MAXFREQ" = "fastest" ] ; then
895
				THIS_CPU_MAXFREQ=`cat $THISCPU/cpufreq/cpuinfo_max_freq`
896
			fi
897
			if [ "$CPU_MINFREQ" = "fastest" ] ; then
898
				THIS_CPU_MINFREQ=`cat $THISCPU/cpufreq/cpuinfo_max_freq`
899
			fi
900
			echo "Setting CPU maximum frequency for cpu $THISCPU to $THIS_CPU_MAXFREQ." >> $OUTPUT
901
			set_sysctl $THISCPU/cpufreq/scaling_max_freq $THIS_CPU_MAXFREQ
902
			echo "Setting CPU minimum frequency for cpu $THISCPU to $THIS_CPU_MINFREQ." >> $OUTPUT
903
			set_sysctl $THISCPU/cpufreq/scaling_min_freq $THIS_CPU_MINFREQ
904
			echo "Setting CPU frequency governor for cpu $THISCPU to $THIS_CPU_GOVERNOR." >> $OUTPUT
905
			/sbin/modprobe -q cpufreq_$THIS_CPU_GOVERNOR >> $OUTPUT 2>&1
906
			set_sysctl $THISCPU/cpufreq/scaling_governor $THIS_CPU_GOVERNOR
907
			if [ -f "$THISCPU/cpufreq/$THIS_CPU_GOVERNOR/ignore_nice_load" ] ; then
908
				echo "Setting CPU ignore_nice_load for cpu $THISCPU to $THIS_CPU_IGNORE_NICE_LOAD." >> $OUTPUT
909
				set_sysctl $THISCPU/cpufreq/$THIS_CPU_GOVERNOR/ignore_nice_load $THIS_CPU_IGNORE_NICE_LOAD
910
			else
911
				echo "Not setting CPU ignore_nice_load for cpu $THISCPU." >> $OUTPUT
912
				echo "File $THISCPU/cpufreq/$THIS_CPU_GOVERNOR/ignore_nice_load does not exist." >> $OUTPUT
913
			fi
914
		fi
915
	done
916
fi
917
918
if [ $CONTROL_CPU_THROTTLING -eq 1 ] ; then
919
	if [ $ON_AC -eq 1 ] ; then
920
		if [ "$ACTIVATE" -eq 1 ] ; then
921
			CPU_THROTTLING="$LM_AC_CPU_THROTTLING"
922
		else
923
			CPU_THROTTLING="$NOLM_AC_CPU_THROTTLING"
924
		fi
925
	else
926
		CPU_THROTTLING="$BATT_CPU_THROTTLING"
927
	fi
928
	for THISCPU in /proc/acpi/processor/* ; do
929
		if [ -e $THISCPU/throttling ]; then
930
			NUM_LEVELS=`cat $THISCPU/throttling | grep "T[0123456789]*\:" | wc -l`
931
			if [ "$CPU_THROTTLING" = "minimum" ]; then
932
				THIS_CPU_THROTTLING=0
933
			elif [ "$CPU_THROTTLING" = "maximum" ] ; then				
934
				THIS_CPU_THROTTLING=$(($NUM_LEVELS - 1))
935
			elif [ "$CPU_THROTTLING" = "medium" ] ; then
936
				# Divide but round up: that way, "medium" on a two-level system will
937
				# lead to full throttling -- which is 50% on my system, quite reasonable.
938
				THIS_CPU_THROTTLING=$(( ($NUM_LEVELS / 2 ) ))
939
			else
940
				THIS_CPU_THROTTLING="$CPU_THROTTLING"
941
			fi
942
			echo "Setting throttling level for cpu $THISCPU to $THIS_CPU_THROTTLING." >> $OUTPUT
943
			set_sysctl $THISCPU/throttling $THIS_CPU_THROTTLING
944
		fi
945
	done
946
fi
947
9 by Bart Samwel
Move /var/run/laptop-mode-* to /var/run/laptop-mode-tools/*
948
if [ "$CONTROL_START_STOP" -ne 0 -a -f /var/run/laptop-mode-tools/start-stop-undo-actions ] ; then
949
	cat /var/run/laptop-mode-tools/start-stop-undo-actions | \
1 by Bart Samwel
Initial import
950
		while read SCRIPT STARTSTOPACTION ; do
951
			$SCRIPT $STARTSTOPACTION
952
		done
953
	   
954
fi
955
956
957
958
# Adjust kernel settings and mount options (but only if data loss 
959
# sensitive features are active)
960
if [ "$ACTIVATE_WITH_POSSIBLE_DATA_LOSS" -eq 1 ] ; then
961
	# Take MAX_LOST_WORK_SECONDS from LM_BATT_MAX_LOST_WORK_SECONDS or LM_AC_MAX_LOST_WORK_SECONDS_WITH_LM, depending on power state.
962
	MAX_LOST_WORK_SECONDS=$LM_BATT_MAX_LOST_WORK_SECONDS
963
	if [ $ON_AC -eq 1 ] ; then
964
		MAX_LOST_WORK_SECONDS=$LM_AC_MAX_LOST_WORK_SECONDS
965
	fi
966
967
	AGE=$((100*$MAX_LOST_WORK_SECONDS))
968
	XFS_AGE=$(($XFS_HZ*$MAX_LOST_WORK_SECONDS))
969
970
	if [ -d /proc/sys/vm/pagebuf ] ; then
971
		# (For 2.4 and early 2.6.)
972
		# This only needs to be set, not reset -- it is only used when
973
		# laptop mode is enabled.
974
		echo "Adjusting XFS kernel parameters for 2.4 and early 2.6 kernels." >> $OUTPUT
975
		set_sysctl /proc/sys/vm/pagebuf/lm_flush_age  $XFS_AGE
976
		set_sysctl /proc/sys/fs/xfs/lm_sync_interval  $XFS_AGE
977
	elif [ -f /proc/sys/fs/xfs/lm_age_buffer ] ; then
978
		# (A couple of early 2.6 laptop mode patches had these.)
979
		# This only needs to be set, not reset -- it is only used when
980
		# laptop mode is enabled.
981
		echo "Adjusting XFS kernel parameters for early patched 2.6 kernels." >> $OUTPUT
982
		set_sysctl /proc/sys/fs/xfs/lm_age_buffer    $XFS_AGE
983
		set_sysctl /proc/sys/fs/xfs/lm_sync_interval $XFS_AGE
984
	elif [ -f /proc/sys/fs/xfs/age_buffer ] ; then
985
		# (2.6.6)
986
		# But not for these -- they are also used in normal
987
		# operation.
988
		echo "Adjusting XFS kernel parameters for 2.6.6 kernel." >> $OUTPUT
989
		set_sysctl /proc/sys/fs/xfs/age_buffer       $XFS_AGE 
990
		set_sysctl /proc/sys/fs/xfs/sync_interval    $XFS_AGE
991
	elif [ -f /proc/sys/fs/xfs/age_buffer_centisecs ] ; then
992
		# (2.6.7 upwards)
993
		# And not for these either. These are in centisecs,
994
		# not USER_HZ, so we have to use $AGE, not $XFS_AGE.
995
		echo "Adjusting XFS kernel parameters for >2.6.7 kernel." >> $OUTPUT
996
		set_sysctl /proc/sys/fs/xfs/age_buffer_centisecs  $AGE
997
		set_sysctl /proc/sys/fs/xfs/xfssyncd_centisecs    $AGE
998
		set_sysctl /proc/sys/fs/xfs/xfsbufd_centisecs     3000
999
	fi
1000
1001
	case "$KLEVEL" in
1002
		"2.4")
1003
			echo "Adjusting 2.4 kernel parameters to enable laptop mode." >> $OUTPUT
1004
			set_sysctl /proc/sys/vm/laptop_mode   1
1005
			set_sysctl /proc/sys/vm/bdflush       "30 500 0 0 $AGE $AGE 60 20 0"
1006
			;;
1007
		"2.6")
1008
			echo "Adjusting 2.6 kernel parameters to enable laptop mode." >> $OUTPUT
1009
			set_sysctl /proc/sys/vm/laptop_mode		  "$LM_SECONDS_BEFORE_SYNC"
1010
			set_sysctl /proc/sys/vm/dirty_writeback_centisecs "$AGE"
1011
			set_sysctl /proc/sys/vm/dirty_expire_centisecs    "$AGE"
1012
			set_sysctl /proc/sys/vm/dirty_ratio		  "$LM_DIRTY_RATIO"
1013
			set_sysctl /proc/sys/vm/dirty_background_ratio    "$LM_DIRTY_BACKGROUND_RATIO"
1014
			;;
1015
	esac
1016
	if [ $CONTROL_MOUNT_OPTIONS -eq 1 ]; then
1017
		echo "Remounting filesystems." >> $OUTPUT
1018
		cat /etc/mtab | while read DEV MP FST OPTS DUMP PASS ; do
1019
			DO=0
1020
			if ( echo " $PARTITIONS " | grep " $DEV " > /dev/null ) ; then
1021
				DO=1
1022
				echo "$DEV found in PARTITIONS." >> $OUTPUT
1023
			else
1024
				echo "$DEV not found in PARTITIONS." >> $OUTPUT
1025
			fi
1026
			if ( echo " $PARTITIONS " | grep " $MP " > /dev/null ) ; then
1027
				DO=1
1028
				echo "$MP found in PARTITIONS." >> $OUTPUT
1029
			else
1030
				echo "$MP not found in PARTITIONS." >> $OUTPUT
1031
			fi
1032
			if ( echo " $PARTITIONS " | grep " auto " > /dev/null ) ; then
1033
				echo "Checking $DEV against HD because PARTITIONS contains \"auto\"." >> $OUTPUT
1034
				for THISHD in $HD ; do
1035
					echo "   Considering $THISHD." >> $OUTPUT
1036
					if ( echo " $DEV" | grep "$THISHD" > /dev/null ) ; then
1037
						DO=1
1038
						echo "   $DEV contains $THISHD, which is in HD, so we will remount it." >> $OUTPUT
1039
					fi
1040
				done
1041
			fi
1042
			if [ "$DO" -ne 0 ] ; then
1043
				echo "Original options: $OPTS" >> $OUTPUT
1044
				if [ "$WAS_ACTIVE" -eq 0 ] ; then
1045
					# Coming from inactive state: save last known mount options for the device.
9 by Bart Samwel
Move /var/run/laptop-mode-* to /var/run/laptop-mode-tools/*
1046
					echo Updating /var/run/laptop-mode-tools/nolm-mountopts.  >> $OUTPUT
1047
					if [ -f /var/run/laptop-mode-tools/nolm-mountopts ] ; then 
1048
						sed -i "s|^$DEV .*$||" /var/run/laptop-mode-tools/nolm-mountopts
1 by Bart Samwel
Initial import
1049
					fi
9 by Bart Samwel
Move /var/run/laptop-mode-* to /var/run/laptop-mode-tools/*
1050
					echo $DEV $OPTS >> /var/run/laptop-mode-tools/nolm-mountopts
1 by Bart Samwel
Initial import
1051
				else
9 by Bart Samwel
Move /var/run/laptop-mode-* to /var/run/laptop-mode-tools/*
1052
					echo Not updating /var/run/laptop-mode-tools/nolm-mountopts because laptop mode was already active. >> $OUTPUT
1 by Bart Samwel
Initial import
1053
				fi
1054
				if [ "$FST" = 'unknown' ]; then
1055
					echo "Deducing fstype for $MP." >> $OUTPUT
1056
					FST=$(deduce_fstype $MP)
1057
					echo "Deduced fstype for $MP as $FST." >> $OUTPUT
1058
				fi
1059
				# Strip stuff like ext3,ext2 into just ext3.
1060
				echo Reducing file system type.  >> $OUTPUT
1061
				FST=`echo $FST | sed s/,.*//`
1062
				case "$FST" in
1063
					"ext3"|"reiserfs")
1064
						echo Removing commit mount option from original options.  >> $OUTPUT
1065
						PARSEDOPTS="$(remove_numeric_mount_option commit "$OPTS")"
1066
						echo "Executing: mount $DEV -t $FST $MP -o remount,$PARSEDOPTS,commit=$MAX_LOST_WORK_SECONDS$NOATIME_OPT" >> $OUTPUT
1067
						if (! mount $DEV -t $FST $MP -o remount,$PARSEDOPTS,commit=$MAX_LOST_WORK_SECONDS$NOATIME_OPT) ; then
1068
							if [ "$FST" == "ext3" -a "$MP" == "/" ] ; then
1069
								echo "BIG FAT WARNING: Your root filesystem mounted as ext3 seems to lack support for"
1070
								echo "the commit mount option. This usually means that your root filesystem is"
1071
								echo "mounted as ext2 because there is no ext3 support in the kernel at boot time,"
1072
								echo "usually because you compiled ext3 as a module and don't load it in an initrd."
1073
								echo "Note that on recent 2.6 kernels, /proc/mounts shows the correct fs type for"
1074
								echo "the device /dev/root. You can check your actual root filesystem mount type"
1075
								echo "there. To fix the problem, either make ext3 available at boot time by compiling"
1076
								echo "it statically into the kernel, or configure the correct filesystem type in"
1077
								echo "/etc/fstab."
1078
							fi
1079
						fi
1080
						;;
1081
					*)
1082
						echo "Executing: mount $DEV -t $FST $MP -o remount,$OPTS$NOATIME_OPT" >> $OUTPUT
1083
						mount $DEV -t $FST $MP -o remount,$OPTS$NOATIME_OPT
1084
						;;
1085
				esac
1086
				if [ -b $DEV -a "$CONTROL_READAHEAD" -ne 0 ] ; then
11 by Bart Samwel
Use blockdev --setfra instead of --setra (adds dependency on util-linux-ng >= 2.13).
1087
					echo "Executing: /sbin/blockdev --setfra $(($LM_READAHEAD * 2)) $DEV" >> $OUTPUT
1088
					/sbin/blockdev --setfra $(($LM_READAHEAD * 2)) $DEV >> $OUTPUT 2>&1
1 by Bart Samwel
Initial import
1089
				fi
1090
			fi
1091
		done
1092
	fi
1093
else
1094
	# DEACTIVATE w.r.t. kernel options and mount point settings
1095
	U_AGE=$((100*$DEF_UPDATE))
1096
	B_AGE=$((100*$DEF_MAX_AGE))
1097
	set_sysctl /proc/sys/vm/laptop_mode 0
1098
	if [ -f /proc/sys/fs/xfs/age_buffer -a ! -f /proc/sys/fs/xfs/lm_age_buffer ] ; then
1099
		# These need to be restored, if there are no lm_*.
1100
		echo "Restoring default XFS settings (pre-centisecs version)." >> $OUTPUT
1101
		set_sysctl /proc/sys/fs/xfs/age_buffer    $(($XFS_HZ*$DEF_XFS_AGE_BUFFER))
1102
		set_sysctl /proc/sys/fs/xfs/sync_interval $(($XFS_HZ*$DEF_XFS_SYNC_INTERVAL))
1103
	elif [ -f /proc/sys/fs/xfs/age_buffer_centisecs ] ; then
1104
		# These need to be restored as well.
1105
		echo "Restoring default XFS settings." >> $OUTPUT
1106
		set_sysctl /proc/sys/fs/xfs/age_buffer_centisecs  $((100*$DEF_XFS_AGE_BUFFER))
1107
		set_sysctl /proc/sys/fs/xfs/xfssyncd_centisecs    $((100*$DEF_XFS_SYNC_INTERVAL))
1108
		set_sysctl /proc/sys/fs/xfs/xfsbufd_centisecs     $((100*$DEF_XFS_BUFD_INTERVAL))
1109
	fi
1110
	case "$KLEVEL" in
1111
		"2.4")
1112
			echo "Adjusting 2.4 kernel parameters to disable laptop mode." >> $OUTPUT
1113
			set_sysctl /proc/sys/vm/bdflush "30 500 0 0 $U_AGE $B_AGE 60 20 0"
1114
			;;
1115
		"2.6")
1116
			echo "Adjusting 2.6 kernel parameters to disable laptop mode." >> $OUTPUT
1117
			set_sysctl /proc/sys/vm/dirty_writeback_centisecs   "$U_AGE"
1118
			set_sysctl /proc/sys/vm/dirty_expire_centisecs      "$B_AGE"
1119
			set_sysctl /proc/sys/vm/dirty_ratio		    "$NOLM_DIRTY_RATIO"
1120
			set_sysctl /proc/sys/vm/dirty_background_ratio	    "$NOLM_DIRTY_BACKGROUND_RATIO"
1121
			;;
1122
	esac
1123
	if [ $CONTROL_MOUNT_OPTIONS -eq 1 ] ; then
1124
		echo "Remounting filesystems." >> $OUTPUT
1125
		cat /etc/mtab | while read DEV MP FST OPTS DUMP PASS ; do
1126
			DO=0
1127
			if ( echo " $PARTITIONS " | grep " $DEV " > /dev/null ) ; then
1128
				DO=1
1129
				echo "$DEV found in PARTITIONS." >> $OUTPUT
1130
			else
1131
				echo "$DEV not found in PARTITIONS." >> $OUTPUT
1132
			fi
1133
			if ( echo " $PARTITIONS " | grep " $MP " > /dev/null ) ; then
1134
				DO=1
1135
				echo "$MP found in PARTITIONS." >> $OUTPUT
1136
			else
1137
				echo "$MP not found in PARTITIONS." >> $OUTPUT
1138
			fi
1139
			if ( echo " $PARTITIONS " | grep " auto " > /dev/null ) ; then
1140
				echo "Checking $DEV against HD because PARTITIONS contains \"auto\"." >> $OUTPUT
1141
				for THISHD in $HD ; do
1142
					echo "   Considering $THISHD." >> $OUTPUT
1143
					if ( echo " $DEV" | grep "$THISHD" > /dev/null ) ; then
1144
						DO=1
1145
						echo "   $DEV contains $THISHD, which is in HD, so we will remount it." >> $OUTPUT
1146
					fi
1147
				done
1148
			fi
1149
			if [ "$DO" -ne 0 ] ; then
1150
				# Reset commit and atime options to defaults.
1151
				echo "Original options: $OPTS" >> $OUTPUT
1152
				if [ "$FST" = 'unknown' ]; then
1153
					echo "Deducing fstype for $MP." >> $OUTPUT
1154
					FST=$(deduce_fstype $MP)
1155
					echo "Deduced fstype for $MP as $FST." >> $OUTPUT
1156
				fi
1157
				
1158
				# Strip stuff like ext3,ext2 into just ext3.
1159
				echo Reducing file system type.  >> $OUTPUT
1160
				FST=`echo $FST | sed s/,.*//`
1161
				
1162
				# Retrieve original non-laptop mode mount options and restore them.
1163
				# If the file that stores them doesn't exist, then laptop mode
1164
				# has never been started.
9 by Bart Samwel
Move /var/run/laptop-mode-* to /var/run/laptop-mode-tools/*
1165
				if [ "$WAS_ACTIVE" -ne 0 -a -f /var/run/laptop-mode-tools/nolm-mountopts ] ; then						
1166
					SAVED_OPTS=`grep "^$DEV " /var/run/laptop-mode-tools/nolm-mountopts`
1 by Bart Samwel
Initial import
1167
					SAVED_OPTS=${SAVED_OPTS#* } # trim device name
1168
				
1169
					case "$FST" in
1170
						"ext3"|"reiserfs")								
1171
							PARSEDOPTS="$(replace_numeric_mount_option commit commit=0 $SAVED_OPTS $OPTS)"
1172
							PARSEDOPTS="$(replace_yesno_mount_option atime atime $SAVED_OPTS $PARSEDOPTS)"
1173
							echo Executing: mount $DEV -t $FST $MP -o remount,$PARSEDOPTS >> $OUTPUT
1174
							mount $DEV -t $FST $MP -o remount,$PARSEDOPTS
1175
							;;
1176
						*)
1177
							PARSEDOPTS="$(replace_yesno_mount_option atime atime $SAVED_OPTS $OPTS)"
1178
							echo Executing: mount $DEV -t $FST $MP -o remount,$PARSEDOPTS >> $OUTPUT
1179
							mount $DEV -t $FST $MP -o remount,$PARSEDOPTS
1180
							;;
1181
					esac
1182
				else
1183
					echo "No saved mount options, so apparently we never remounted this filesystem during this session." >> $OUTPUT
1184
					echo "Not remounting." >> $OUTPUT
1185
				fi
1186
				if [ -b $DEV -a "$CONTROL_READAHEAD" -ne 0 ] ; then
11 by Bart Samwel
Use blockdev --setfra instead of --setra (adds dependency on util-linux-ng >= 2.13).
1187
					echo "Executing: /sbin/blockdev --setfra $(($NOLM_READAHEAD * 2)) $DEV" >> $OUTPUT
1188
					/sbin/blockdev --setfra $(($NOLM_READAHEAD * 2)) $DEV >> $OUTPUT 2>&1
1 by Bart Samwel
Initial import
1189
				fi
1190
			fi
1191
		done
1192
	fi
1193
fi
1194
1195
1196
1197
# Adjust hard drive powermanagement
1198
1199
# Function for drive capability check. This prevents ugly errors in
1200
# the kernel output about unsupported commands.
1201
#
1202
# $1 = drive name
1203
# $2 = capability (SDPARM/HDPARM or IDLE_TIMEOUT/POWERMGMT/WRITECACHE)
1204
is_capable() {
1205
	local dev=${1#/dev/}
1206
	local MEDIA=
1207
	local BUS=
1208
1209
	HAVE_UDEVINFO=0
1210
	if [ -x "$(which udevinfo 2> /dev/null)" ] ; then
1211
		UDEVVERSION=$(udevinfo -V | awk '{ print $3; }')
1212
		if [ "$UDEVVERSION" -gt 70 ] ; then
1213
			HAVE_UDEVINFO=1
1214
		else
1215
			echo "udevinfo present but version not > 070, not using udev" >> $OUTPUT
1216
		fi
1217
	fi
1218
	
1219
	# If we are running udev, this is the most portable way
1220
	# It assumes more or less recent udev (> 070)
1221
	if [ $HAVE_UDEVINFO -ne 0 ] ; then
1222
		echo -n "Querying $1 media type using udevinfo: " >> $OUTPUT
1223
		eval "$(udevinfo -q env -n $1 2> $OUTPUT | egrep '(ID_TYPE=|ID_BUS=)' >> $OUTPUT 2>&1)"
1224
		if [ -n "$ID_TYPE" -a -n "$ID_BUS" ] ; then
1225
			echo "type '$ID_TYPE on bus '$ID_BUS' detected" >> $OUTPUT
1226
			MEDIA=$ID_TYPE
1227
			BUS=$ID_BUS
1228
		else
1229
			echo "failed - udev not active?" >> $OUTPUT
1230
		fi
1231
	fi
1232
1233
	if [ -z "$MEDIA" ] ; then
1234
		echo -n "Querying $1 media type using device name: " >> $OUTPUT
1235
		case $dev in
1236
			hd*)	# IDE device
1237
				if [ -r /proc/ide/$dev/media ]; then
1238
					MEDIA="$(cat /proc/ide/$dev/media)"
1239
					BUS=ata
1240
					if [ "$MEDIA" = cdrom ] ; then
1241
						MEDIA=cd
1242
					fi
1243
				fi
1244
			;;
1245
			sd*)	# SCSI disk
1246
				# No need to check, sd is always SCSI disk
1247
				MEDIA=disk
1248
				BUS=scsi
1249
			;;
1250
			sr* | scd* )
1251
				# No need to check, sr or scd is always SCSI CD-ROM
1252
				MEDIA=cd
1253
				BUS=scsi
1254
			;;
1255
1256
		esac
1257
		if [ -n "$MEDIA" ] ; then
1258
			echo "type '$MEDIA' on bus '$BUS' detected" >> $OUTPUT
1259
		else
1260
			echo "failed - unknown name" >> $OUTPUT
1261
		fi
1262
	fi
1263
1264
	if [ -z "$MEDIA" ] ; then
1265
		if [ -x "$(which hdparm 2> /dev/null)" ]; then
1266
			echo -n "Querying $1 type using hdparm: " >> $OUTPUT
1267
			if hdparm -I $1 2> $OUTPUT | grep -q CD-ROM >> $OUTPUT 2>&1 ; then
1268
				MEDIA=cd
1269
			else
1270
				MEDIA=disk
1271
			fi
1272
			BUS=ata # or acts like it anyway, because hdparm supports it.
1273
			echo "type '$MEDIA' on bus '$BUS' detected" >> $OUTPUT
1274
		fi
1275
	fi
1276
1277
	# Sanity check
1278
	if [ -z "$MEDIA" -o -z "$BUS" ] ; then
1279
		echo "Querying $1 type - unknown type or bus, disabling hdparm/sdparm" >> $OUTPUT
1280
		return 1
1281
	fi
1282
1283
	if [ "$BUS" == "scsi" -a "$ASSUME_SCSI_IS_SATA" -ne 0 ] ;then
1284
		# Treat scsi disks as SATA devices. Unfortunately they are hard
1285
		# to recognize -- if anybody has a drive and cares to find out
1286
		# how to recognize them, please enlighten me!
1287
		BUS=ata
1288
	fi
1289
1290
	# Now check what capabilities we support for the
1291
	# various media and bus types.
1292
	case "$MEDIA:$BUS:$2" in
1293
		# Although CD-ROM drives usually support
1294
		# idle timeout settings, they don't usually
1295
		# support very low values, and we don't want
1296
		# to mess with that. We simply ignore anything
1297
		# that is a CD player.
1298
		cd:*:* ) return 1;;
1299
1300
		# ATA drives support the "hdparm" command but
1301
		# not normally the "sdparm" command.
1302
		*:ata:HDPARM ) return 0 ;;
1303
		*:ata:SDPARM ) return 1 ;;
1304
		
1305
		# SCSI drives support the "sdparm" command, but
1306
		# not normally the "hdparm" command.
1307
		*:scsi:SDPARM ) return 0 ;;
1308
		*:scsi:HDPARM ) return 1 ;;
1309
1310
		# On ATA disks everything is supported.
1311
		disk:ata:* ) return 0 ;;
1312
1313
		# For sdparm we only know how to set the idle
1314
		# timeout, nothing else at the moment.
1315
		*:scsi:IDLE_TIMEOUT ) return 0 ;;
1316
1317
		# No other capabilities are supported.
1318
		* ) return 1 ;;
1319
	esac
1320
}
1321
1322
if [ $CONTROL_HD_POWERMGMT -eq 1 ] ; then
1323
	if [ $ON_AC -eq 1 ] ; then
1324
		if [ "$ACTIVATE" -eq 1 ] ; then
1325
			HD_POWERMGMT=$LM_AC_HD_POWERMGMT
1326
		else
1327
			HD_POWERMGMT=$NOLM_AC_HD_POWERMGMT
1328
		fi
1329
	else
1330
		HD_POWERMGMT=$BATT_HD_POWERMGMT
1331
	fi
1332
1333
	echo "Setting powermanagement on drives to $HD_POWERMGMT." >> $OUTPUT
1334
	for THISHD in $HD ; do
1335
		if is_capable $THISHD POWERMGMT ; then
1336
			if is_capable $THISHD HDPARM ; then
1337
				if [ ! -e `which hdparm 2> /dev/null` ] ; then
1338
					echo "ERROR: hdparm not installed."
1339
				else
1340
					echo "Executing: hdparm -B $HD_POWERMGMT $THISHD" >> $OUTPUT
1341
					hdparm -B $HD_POWERMGMT $THISHD >> $OUTPUT 2>&1
1342
				fi
1343
			else
1344
				echo "Skipping $THISHD: powermgmt only possible with hdparm but drive does not" >> $OUTPUT
1345
				echo "support hdparm." >> $OUTPUT
1346
			fi
1347
		else
1348
			echo "Skipping $THISHD: powermanagement control not supported." >> $OUTPUT
1349
		fi
1350
	done
1351
fi
1352
1353
if [ $CONTROL_HD_IDLE_TIMEOUT -eq 1 ] ; then
1354
	# Spindown timeouts may only be set when data-loss sensitive
1355
	# features are active.
1356
	if [ "$ACTIVATE_WITH_POSSIBLE_DATA_LOSS" -eq 1 ] ; then
1357
		if [ $ON_AC -eq 1 ] ; then
1358
			HD_IDLE_TIMEOUT=$LM_AC_HD_IDLE_TIMEOUT
1359
			HD_IDLE_TIMEOUT_SECONDS=$LM_AC_HD_IDLE_TIMEOUT_SECONDS
1360
		else
1361
			HD_IDLE_TIMEOUT=$LM_BATT_HD_IDLE_TIMEOUT
1362
			HD_IDLE_TIMEOUT_SECONDS=$LM_BATT_HD_IDLE_TIMEOUT_SECONDS
1363
		fi
1364
	else
1365
		HD_IDLE_TIMEOUT=$NOLM_HD_IDLE_TIMEOUT
1366
		HD_IDLE_TIMEOUT_SECONDS=$NOLM_HD_IDLE_TIMEOUT_SECONDS
1367
	fi
1368
	echo "Setting spindown timeout on drives to $HD_IDLE_TIMEOUT_SECONDS seconds." >> $OUTPUT
1369
	echo "(hdparm configuration value = $HD_IDLE_TIMEOUT.)" >> $OUTPUT
1370
	for THISHD in $HD ; do
1371
		if is_capable $THISHD IDLE_TIMEOUT ; then
1372
			if is_capable $THISHD HDPARM ; then
1373
				if [ ! -e `which hdparm 2> /dev/null` ] ; then
1374
					echo "ERROR: hdparm not installed."
1375
				else
1376
					echo "Executing: hdparm -S $HD_IDLE_TIMEOUT $THISHD" >> $OUTPUT
1377
					hdparm -S $HD_IDLE_TIMEOUT $THISHD >> $OUTPUT 2>&1
1378
				fi
1379
			elif is_capable $THISHD SDPARM ; then
1380
				if [ ! -e `which sdparm 2> /dev/null` ] ; then
1381
					echo "ERROR: sdparm not installed."
1382
				else
1383
					HD_IDLE_TIMEOUT_DECISECONDS=$(($HD_IDLE_TIMEOUT_SECONDS*10))
1384
					echo "Executing: sdparm -q -s SCT=$HD_IDLE_TIMEOUT_DECISECONDS $THISHD" >> $OUTPUT
1385
					sdparm -q -s SCT=$HD_IDLE_TIMEOUT_DECISECONDS $THISHD >> $OUTPUT 2>&1
1386
				fi
1387
			else
1388
				echo "Skipping $THISHD: drive supports neither hdparm nor sdparm." >> $OUTPUT
1389
			fi
1390
		else
1391
			echo "Skipping $THISHD: idle timeout control not supported." >> $OUTPUT
1392
		fi
1393
	done
1394
fi
1395
1396
if [ $CONTROL_HD_WRITECACHE -eq 1 ] ; then
1397
	# The writecache may only be enabled when data-loss sensitive
1398
	# features are active.
1399
1400
	if [ "$ACTIVATE" -eq 1 ] ; then
1401
		if [ "$ACTIVATE_WITH_POSSIBLE_DATA_LOSS" -eq 0 ] ; then
1402
			HD_WRITECACHE=0
1403
		else
1404
			HD_WRITECACHE=$LM_HD_WRITECACHE
1405
		fi
1406
	else
1407
		if [ $ON_AC -eq 1 ] ; then
1408
			HD_WRITECACHE=$NOLM_AC_HD_WRITECACHE
1409
		else
1410
			HD_WRITECACHE=$NOLM_BATT_HD_WRITECACHE
1411
		fi
1412
	fi
1413
	echo "Setting write cache on drives to $HD_WRITECACHE." >> $OUTPUT
1414
	for THISHD in $HD ; do
1415
		if is_capable $THISHD WRITECACHE ; then
1416
			if is_capable $THISHD HDPARM ; then
1417
				if [ ! -e `which hdparm 2> /dev/null` ] ; then
1418
					echo "ERROR: hdparm not installed."
1419
				else
1420
					echo "Executing: hdparm -W $HD_WRITECACHE $THISHD" >> $OUTPUT
1421
					hdparm -W $HD_WRITECACHE $THISHD >> $OUTPUT 2>&1
1422
				fi
1423
			else
1424
				echo "Skipping $THISHD: writecache only possible with hdparm but drive does not" >> $OUTPUT
1425
				echo "support hdparm." >> $OUTPUT
1426
			fi
1427
		else
1428
			echo "Skipping $THISHD: writecache control not supported." >> $OUTPUT
1429
		fi
1430
	done
1431
fi
1432
1433
if [ $CONTROL_SYSLOG_CONF -eq 1 ] ; then
1434
	echo "Adjusting syslog configuration." >> $OUTPUT
1435
	if [ "`readlink -f $SYSLOG_CONF`" != "$SYSLOG_CONF" ] ; then
1436
		echo "$SYSLOG_CONF is a symlink." >> $OUTPUT
1437
		if [ ! -f "$SYSLOG_CONF.no-lm" ] ; then
1438
			echo "But there is no $SYSLOG_CONF.no-lm. This must have been done by an earlier" >> $OUTPUT
1439
			echo "version of laptop-mode-tools." >> $OUTPUT
1440
			echo "Creating it now from $NOLM_AC_SYSLOG_CONF."
1441
			cp "$NOLM_AC_SYSLOG_CONF" "$SYSLOG_CONF.no-lm"
1442
		fi
1443
	else
1444
		echo "$SYSLOG_CONF is not a symlink." >> $OUTPUT
1445
		if [ "$STATE" == "enabled" ] ; then
1446
			echo "Saving it to $SYSLOG_CONF.no-lm." >> $OUTPUT
1447
			cp --backup=numbered "$SYSLOG_CONF" "$SYSLOG_CONF.no-lm"
1448
		fi
1449
	fi
1450
1451
	if [ "$STATE" != "enabled" ] ; then
1452
		echo "Laptop mode is not enabled. Restoring $SYSLOG_CONF." >> $OUTPUT
1453
		if [ -f "$SYSLOG_CONF.no-lm" ] ; then
1454
			mv "$SYSLOG_CONF.no-lm" "$SYSLOG_CONF"
1455
		elif [ "`readlink -f $SYSLOG_CONF`" != "$SYSLOG_CONF" ] ; then
1456
			echo "ERROR: $SYSLOG_CONF is a symlink but $SYSLOG_CONF.no-lm is not present."
1457
		fi
1458
	elif [ $ON_AC -eq 1 ] ; then
1459
		if [ "$ACTIVATE" -eq 1 ] ; then
1460
			echo "Setting syslog config to $LM_AC_SYSLOG_CONF." >> $OUTPUT
1461
			ln -fs "$LM_AC_SYSLOG_CONF" "$SYSLOG_CONF"
1462
		else
1463
			echo "Setting syslog config to $NOLM_AC_SYSLOG_CONF." >> $OUTPUT
1464
			ln -fs "$NOLM_AC_SYSLOG_CONF" "$SYSLOG_CONF"
1465
		fi
1466
	else
1467
		echo "Setting syslog config to $BATT_SYSLOG_CONF." >> $OUTPUT
1468
		ln -fs "$BATT_SYSLOG_CONF" "$SYSLOG_CONF"
1469
	fi
1470
	# Notify syslogd of configuration change.
1471
	if [ "$SYSLOG_CONF_SIGNAL_PROGRAM" != "" ] ; then
1472
		echo "Sending SIGHUP to all $SYSLOG_CONF_SIGNAL_PROGRAM processes." >> $OUTPUT
1473
		killall -q -HUP $SYSLOG_CONF_SIGNAL_PROGRAM
1474
	fi
1475
fi
1476
1477
# Setting X screen standby/suspend/powerdown timing
1478
if [ $CONTROL_DPMS_STANDBY -eq 1 ] ; then
1479
	if [ $ON_AC -eq 1 ]; then
1480
		if [ "$ACTIVATE" -eq 1 ]; then
1481
			STANDBY="$LM_AC_DPMS_STANDBY"
1482
			SUSPEND=$(($STANDBY+30))
1483
			OFF=$(($STANDBY+60))
1484
		else
1485
			STANDBY="$NOLM_AC_DPMS_STANDBY"
1486
			SUSPEND=$(($STANDBY+300))
1487
			OFF=$(($STANDBY+600))
1488
		fi
1489
	else
1490
		STANDBY="$BATT_DPMS_STANDBY"
1491
		SUSPEND=$(($STANDBY+30))
1492
		OFF=$(($STANDBY+60))
1493
	fi
1494
1495
	who | while read -r DPMS_USER DPMS_SCREEN REMAINDER; do	        
1496
	        if su $DPMS_USER -c "xset -d $DPMS_SCREEN dpms $STANDBY $SUSPEND $OFF" 2>> $OUTPUT | grep -q display >> $OUTPUT 2>&1 ; then
1497
		        echo "Unable to set DPMS timeouts: X is not running on $DPMS_SCREEN" >> $OUTPUT
1498
	        else 
1499
		        echo "Set screen $DPMS_SCREEN for the user $DPMS_USER to standby in $STANDBY s, suspend in $SUSPEND s, powerdown in $OFF s" >> $OUTPUT
1500
		fi	
1501
        done
1502
else
1503
	echo "CONTROL_DPMS_STANDBY is disabled, skipping..." >> $OUTPUT
1504
fi
1505
1506
# Set terminal blanking/powerdown timeouts
1507
if [ $CONTROL_TERMINAL -ne 0 ] ; then
1508
	if [ $ON_AC -eq 1 ]; then
1509
		if [ "$ACTIVATE" -eq 1 ]; then
1510
			BLANK_MINUTES="$LM_AC_TERMINAL_BLANK_MINUTES"
1511
			POWERDOWN_MINUTES="$LM_AC_TERMINAL_POWERDOWN_MINUTES"
1512
		else
1513
			BLANK_MINUTES="$NOLM_AC_TERMINAL_BLANK_MINUTES"
1514
			POWERDOWN_MINUTES="$NOLM_AC_TERMINAL_POWERDOWN_MINUTES"
1515
		fi
1516
	else
1517
		BLANK_MINUTES="$BATT_TERMINAL_BLANK_MINUTES"
1518
		POWERDOWN_MINUTES="$BATT_TERMINAL_POWERDOWN_MINUTES"
1519
	fi
1520
	echo "Set terminal blanking timeout to $BLANK_MINUTES min, powerdown timeout to $POWERDOWN_MINUTES min." >> $OUTPUT
1521
	for THISTERMINAL in $TERMINALS ; do
1522
		if [ -e $THISTERMINAL ] ; then
1523
			echo "Terminal $THISTERMINAL found, adjusting." >> $OUTPUT
1524
			TERM=linux setterm -blank "$BLANK_MINUTES" -powerdown "$POWERDOWN_MINUTES" > $THISTERMINAL
1525
		else
1526
			echo "Terminal $THISTERMINAL does not exist." >> $OUTPUT
1527
		fi
1528
	done
1529
else
1530
	echo "CONTROL_TERMINAL is disabled, skipping..." >> $OUTPUT
1531
fi
1532
1533
1534
# Control LCD brightness
1535
if [ $CONTROL_BRIGHTNESS -eq 1 ] ; then
1536
	if [ $ON_AC -eq 1 ]; then
1537
		if [ "$ACTIVATE" -eq 1 ]; then
1538
			BRIGHTNESS_COMMAND="$LM_AC_BRIGHTNESS_COMMAND"
1539
		else
1540
			BRIGHTNESS_COMMAND="$NOLM_AC_BRIGHTNESS_COMMAND"
1541
		fi
1542
	else
1543
		BRIGHTNESS_COMMAND="$BATT_BRIGHTNESS_COMMAND"
1544
	fi
10 by Bart Samwel
Don't touch LCD brightness if the preceding setting is equal to the new setting
1545
	if [ -f /var/run/laptop-mode-tools/state-brightness-command ] ; then
1546
		OLD_BRIGHTNESS_COMMAND="$( cat /var/run/laptop-mode-tools/state-brightness-command )"
1547
	fi
1 by Bart Samwel
Initial import
1548
	
10 by Bart Samwel
Don't touch LCD brightness if the preceding setting is equal to the new setting
1549
	if [ "$FORCE" -ne 0 -o "$BRIGHTNESS_COMMAND" != "$OLD_BRIGHTNESS_COMMAND" ] ; then
1550
		echo "Set LCD brightness using command $BRIGHTNESS_COMMAND \> $BRIGHTNESS_OUTPUT." >> $OUTPUT
1551
		if ( $BRIGHTNESS_COMMAND > $BRIGHTNESS_OUTPUT ) ; then
1552
			echo "Command succeeded." >> $OUTPUT
1553
		else
1554
			echo "Command failed." >> $OUTPUT
1555
		fi
1556
		echo -n $BRIGHTNESS_COMMAND > /var/run/laptop-mode-tools/state-brightness-command
1 by Bart Samwel
Initial import
1557
	else
10 by Bart Samwel
Don't touch LCD brightness if the preceding setting is equal to the new setting
1558
		echo "Not setting LCD brightness -- command was the same as last time." >> $OUTPUT
1 by Bart Samwel
Initial import
1559
	fi
1560
fi
1561
1562
1563
# Start/stop programs 
1564
if [ $CONTROL_START_STOP -eq 1 -a "$STATE" == "enabled" ]; then
1565
	# Empty undo file first. We write the actions we take
1566
	# into this file, so that we can undo them at the
1567
	# next state change. Note: we actually
1568
	# write the actions to the file in reverse order,
1569
	# so we can execute the commands easily afterwards.
9 by Bart Samwel
Move /var/run/laptop-mode-* to /var/run/laptop-mode-tools/*
1570
	echo > /var/run/laptop-mode-tools/start-stop-undo-actions 
1 by Bart Samwel
Initial import
1571
		
1572
	   
1573
	if [ $ON_AC -eq 1 ] ; then
1574
		if [ "$ACTIVATE" -eq 1 ] ; then		
1575
			START_STOP_DIR_PREFIX=/etc/laptop-mode/lm-ac
1576
		else
1577
			START_STOP_DIR_PREFIX=/etc/laptop-mode/nolm-ac
1578
		fi
1579
	else
1580
		START_STOP_DIR_PREFIX=/etc/laptop-mode/batt
1581
	fi
1582
	START_DIR="$START_STOP_DIR_PREFIX"-start
1583
	STOP_DIR="$START_STOP_DIR_PREFIX"-stop
1584
	if [ -d "$STOP_DIR" ] ; then
1585
		for SCRIPT in "$STOP_DIR"/* ; do
1586
			if [ -e "$SCRIPT" ] ; then
1587
				"$SCRIPT" stop
1588
				# Dereference any links. When people configure
1589
				# the directories with links and then they remove
1590
				# links while laptop mode is active, the "undo"
1591
				# will fail if we don't dereference the links
1592
				# before storing them.
1593
				LINKTARGET=`readlink -f "$SCRIPT"`
9 by Bart Samwel
Move /var/run/laptop-mode-* to /var/run/laptop-mode-tools/*
1594
				sed -i "1i $LINKTARGET start" /var/run/laptop-mode-tools/start-stop-undo-actions
1 by Bart Samwel
Initial import
1595
			fi
1596
		done
1597
	fi
1598
	if [ -d "$START_DIR" ] ; then
1599
		for SCRIPT in "$START_DIR"/* ; do
1600
			if [ -e "$SCRIPT" ] ; then
1601
				"$SCRIPT" start
1602
				LINKTARGET=`readlink -f "$SCRIPT"`
9 by Bart Samwel
Move /var/run/laptop-mode-* to /var/run/laptop-mode-tools/*
1603
				sed -i "1i $LINKTARGET stop" /var/run/laptop-mode-tools/start-stop-undo-actions
1 by Bart Samwel
Initial import
1604
			fi
1605
		done
1606
	fi
1607
fi
1608
1609
# Finally, call laptop-mode-tools modules. The modules can use the settings
20 by Bart Samwel
Move modules to /usr/share instead of /usr/lib to improve FHS compliance
1610
# from the config files, but they may NOT assume the settings actually exist,
1 by Bart Samwel
Initial import
1611
# as no defaults have been given for them.
20 by Bart Samwel
Move modules to /usr/share instead of /usr/lib to improve FHS compliance
1612
1613
# Note that the /usr/local/lib path is deprecated.
15 by Bart Samwel
Centralize exports to modules; only read *.conf files from split-up config file conf.d
1614
export FORCE STATE ON_AC ACTIVATE
20 by Bart Samwel
Move modules to /usr/share instead of /usr/lib to improve FHS compliance
1615
for SCRIPT in /usr/share/laptop-mode-tools/modules/* /usr/local/lib/laptop-mode-tools/modules/* /usr/local/share/laptop-mode-tools/modules/* /etc/laptop-mode/modules/*; do
15 by Bart Samwel
Centralize exports to modules; only read *.conf files from split-up config file conf.d
1616
	if [ -x "$SCRIPT" ] ; then
1 by Bart Samwel
Initial import
1617
		"$SCRIPT" >> $OUTPUT
1618
	else
1619
		echo "Module $SCRIPT is not executable." >> $OUTPUT
1620
	fi
1621
done
1622
1623
1624
exit 0
1625
1626
# This fi closes the if for "readconfig". If I would have indented this one
1627
# I would have indented the whole file. :)
1628
fi