home *** CD-ROM | disk | FTP | other *** search
/ PC Welt 2006 November (DVD) / PCWELT_11_2006.ISO / casper / filesystem.squashfs / usr / sbin / laptop_mode < prev    next >
Encoding:
Text File  |  2006-07-10  |  50.0 KB  |  1,540 lines

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