home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2007 September / PCWSEP07.iso / Software / Linux / Linux Mint 3.0 Light / LinuxMint-3.0-Light.iso / casper / filesystem.squashfs / usr / sbin / laptop_mode < prev    next >
Encoding:
Text File  |  2006-12-06  |  49.1 KB  |  1,519 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.32
  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=4    # 20 seconds
  51. LM_BATT_HD_IDLE_TIMEOUT=4  # 20 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=1
  100. BATT_TERMINAL_POWERDOWN_MINUTES=2
  101. LM_AC_TERMINAL_BLANK_MINUTES=10
  102. LM_AC_TERMINAL_POWERDOWN_MINUTES=10
  103. NOLM_AC_TERMINAL_BLANK_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: $((`/sbin/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.  
  508. # Determine the power state.
  509. ON_AC=1
  510.  
  511. if [ -d /proc/acpi/ac_adapter ] ; then
  512.     ADAPTERS_FOUND=0
  513.     ON_AC=0
  514.     for ADAPTER in /proc/acpi/ac_adapter/* ; do
  515.         if [ -f $ADAPTER/state ] ; then
  516.             ADAPTERS_FOUND=1
  517.             STATUS=`awk '/^state: / { print $2 }' $ADAPTER/state`
  518.             if [ "$STATUS" = "on-line" ] ; then
  519.                 ON_AC=1
  520.             fi
  521.         fi
  522.     done
  523.     if [ "$ADAPTERS_FOUND" -eq 0 ] ; then
  524.         ON_AC=1
  525.     fi
  526. elif [ -f /proc/apm ] ; then
  527.     read D1 D2 D3 APM_AC_STATE D0 </proc/apm
  528.     if [ "$APM_AC_STATE" = "0x00" ] ; then
  529.         ON_AC=0
  530.     else
  531.         ON_AC=1
  532.     fi
  533. elif [ -f /proc/pmu/info ] ; then
  534.     if ( grep "^AC Power.*0$" /proc/pmu/info ) ; then
  535.         echo "/proc/pmu/info indicates absence of AC power." >> $OUTPUT
  536.         ON_AC=0
  537.     else
  538.         # It is possible that there is no AC Power = 1 in the file,
  539.         # but we always assume AC power when we're not sure.
  540.         ON_AC=1
  541.         echo "/proc/pmu/info indicates presence of AC power." >> $OUTPUT
  542.     fi
  543. else
  544.     echo "No ACPI, APM or PMU power management information found -- assuming AC power is present." >> $OUTPUT
  545. fi
  546.  
  547.  
  548.  
  549. # Determine whether to activate or deactivate laptop mode.
  550. ACTIVATE=0
  551.  
  552. if [ "$ON_AC" -eq 1 ] ; then
  553.     if [ "$ENABLE_LAPTOP_MODE_ON_AC" -ne 0 ] ; then
  554.         echo "On AC power: Activating, because ENABLE_LAPTOP_MODE_ON_AC is set." >> $OUTPUT
  555.         ACTIVATE=1
  556.     else
  557.         echo "On AC power: Deactivating, because ENABLE_LAPTOP_MODE_ON_AC is not set." >> $OUTPUT
  558.         ACTIVATE=0
  559.     fi
  560. else
  561.     if [ "$ENABLE_LAPTOP_MODE_ON_BATTERY" -ne 0 ] ; then
  562.         echo "On battery power: Activating, because ENABLE_LAPTOP_MODE_ON_BATTERY is set." >> $OUTPUT
  563.         ACTIVATE=1
  564.     else
  565.         echo "On battery power: Deactivating, because ENABLE_LAPTOP_MODE_ON_BATTERY is not set." >> $OUTPUT
  566.         ACTIVATE=0
  567.     fi
  568. fi
  569.  
  570. if [ "$ENABLE_LAPTOP_MODE_WHEN_LID_CLOSED" -ne 0 ] ; then
  571.     if [ -f /proc/acpi/button/lid/*/state ] ; then
  572.         if ( cat /proc/acpi/button/lid/*/state | grep "closed" ) ; then
  573.             echo "Setting action to \"start\" because the lid is closed." >> $OUTPUT
  574.             ACTIVATE=1
  575.         fi
  576.     else
  577.         echo "Warning: ENABLE_LAPTOP_MODE_WHEN_LID_CLOSED is set, but there is no file"
  578.         echo "/proc/acpi/button/lid/.../state!"
  579.     fi
  580. fi
  581.  
  582. # If the init script has not been run or has been run with the "stop"
  583. # argument, then we should never start laptop mode.
  584. if [ ! -f /var/run/laptop-mode-enabled ] ; then
  585.     echo "Laptop mode disabled because /var/run/laptop-mode-enabled is missing." >> $OUTPUT
  586.     STATE=disabled
  587. fi
  588.  
  589. if [ "$ACTIVATE" -eq 1 -a -f /etc/default/laptop-mode ] ; then
  590.     . /etc/default/laptop-mode
  591.     if ! ( echo "$ENABLE_LAPTOP_MODE" |grep y ) ; then
  592.         echo "Not starting laptop mode because it is disabled in /etc/default/laptop-mode." >> $OUTPUT
  593.         STATE=disabled
  594.     fi
  595. fi
  596.  
  597. if [ $1 == "start" ]; then
  598.     STATE=enabled
  599.     ACTIVATE=1;
  600. elif [ $1 == "stop" ]; then
  601.     STATE=disabled
  602.     ACTIVATE=0;
  603. fi
  604.  
  605. # Check whether we are allowed to activate the data-loss-sensitive stuff.
  606. # If the battery charge is too low, we want to disable this, but not the
  607. # other power-saving stuff.
  608.  
  609. if [ "$ACTIVATE" -eq 0 ] ; then
  610.     ACTIVATE_WITH_POSSIBLE_DATA_LOSS=0
  611. else
  612.     ACTIVATE_WITH_POSSIBLE_DATA_LOSS=1
  613.     if [ ! -d /proc/acpi ] ; then
  614.         echo "Not ACPI -> no support for minimum battery charge checking." >> $OUTPUT
  615.     elif [ "$ON_AC" -eq 0 ] ; then
  616.         echo "On ACPI and not on AC -- checking minimum battery charge." >> $OUTPUT
  617.         ENOUGH_CHARGE=0
  618.         ENOUGH_CHARGE_TO_PREVENT_HIBERNATION=0
  619.         for BATT in /proc/acpi/battery/* ; do
  620.             PREV_ENOUGH_CHARGE=$ENOUGH_CHARGE
  621.             PREV_ENOUGH_CHARGE_TO_PREVENT_HIBERNATION=$ENOUGH_CHARGE_TO_PREVENT_HIBERNATION
  622.  
  623.             BATT_STATE=$BATT/state
  624.             BATT_INFO=$BATT/info
  625.             echo "Checking info and state for $BATT." >> $OUTPUT
  626.  
  627.             # Only do if the battery is present
  628.             if ( cat $BATT_INFO | grep "present:.*yes" > /dev/null ) ; then
  629.                 FOUND_AN_ENABLED_CHECK=0
  630.                 FOUND_AN_ENABLED_HIBERNATION_CHECK=0
  631.                 
  632.                 # Get the remaining capacity.
  633.                 REMAINING=`cat $BATT_STATE | grep "remaining capacity:" | sed  "s/.* \([0-9][0-9]* \).*/\1/" `
  634.                 if [ -z "$REMAINING" ] ; then
  635.                     echo "Battery does not report remaining capacity. Perhaps it is not present?" >> $OUTPUT
  636.                     REMAINING=0
  637.                 fi
  638.                 echo "Remaining charge: $REMAINING" >> $OUTPUT
  639.     
  640.                 CAPACITY=`cat $BATT_INFO | grep "design capacity:" | sed  "s/.* \([0-9][0-9]* \).*/\1/" `
  641.                 if [ -z "$CAPACITY" ] ; then
  642.                     CAPACITY=0
  643.                 fi
  644.                 echo "Design capacity: $CAPACITY" >> $OUTPUT
  645.     
  646.                 # Check the charge percentage
  647.                 if [ "$MINIMUM_BATTERY_CHARGE_PERCENT" -ne 0 ] ; then
  648.                     FOUND_AN_ENABLED_CHECK=1
  649.                     if [ "$CAPACITY" -eq 0 ] ; then
  650.                         echo "WARNING: Battery does not report a design capacity. Minimum battery"
  651.                         echo "charge checking does not work without a design capacity."
  652.                     elif [ "$(($REMAINING * 100 / $CAPACITY))" -ge "$MINIMUM_BATTERY_CHARGE_PERCENT" ] ; then
  653.                         ENOUGH_CHARGE=1
  654.                     fi
  655.                 fi
  656.                 if [ "$AUTO_HIBERNATION_BATTERY_CHARGE_PERCENT" -ne 0 ] ; then
  657.                     FOUND_AN_ENABLED_HIBERNATION_CHECK=1
  658.                     if [ "$CAPACITY" -eq 0 ] ; then
  659.                         echo "WARNING: Battery does not report a design capacity. Auto hibernation"
  660.                         echo "does not work without a design capacity."
  661.                     elif [ "$(($REMAINING * 100 / $CAPACITY))" -ge "$AUTO_HIBERNATION_BATTERY_CHARGE_PERCENT" ] ; then
  662.                         ENOUGH_CHARGE_TO_PREVENT_HIBERNATION=1
  663.                     fi
  664.                 fi
  665.     
  666.                 #
  667.                 # Fallback: hard values.
  668.                 #
  669.                 # Determine the reporting unit.
  670.                 IN_MAH=0
  671.                 IN_MWH=0
  672.                 if ( cat $BATT_INFO | grep mWh > /dev/null ) ; then
  673.                     IN_MWH=1
  674.                 elif ( cat $BATT_INFO | grep mAh > /dev/null ) ; then
  675.                     IN_MAH=1
  676.                 fi
  677.                 
  678.                 if [ "$IN_MAH" -ne 0 ] ; then
  679.                     if [ "$MINIMUM_BATTERY_CHARGE_MAH" -ne 0 ] ; then
  680.                         FOUND_AN_ENABLED_CHECK=1
  681.                         if [ "$REMAINING" -ge "$MINIMUM_BATTERY_CHARGE_MAH" ] ; then
  682.                             ENOUGH_CHARGE=1
  683.                         fi
  684.                     fi
  685.                     if [ "$AUTO_HIBERNATION_BATTERY_CHARGE_MAH" -ne 0 ] ; then
  686.                         FOUND_AN_ENABLED_HIBERNATION_CHECK=1
  687.                         if [ "$REMAINING" -ge "$AUTO_HIBERNATION_BATTERY_CHARGE_MAH" ] ; then
  688.                             ENOUGH_CHARGE_TO_PREVENT_HIBERNATION=1
  689.                         fi
  690.                     fi
  691.                 elif [ "$IN_MWH" -ne 0 ] ; then
  692.                     if [ "$MINIMUM_BATTERY_CHARGE_MWH" -ne 0 ] ; then
  693.                         FOUND_AN_ENABLED_CHECK=1
  694.                         if [ "$REMAINING" -ge "$MINIMUM_BATTERY_CHARGE_MWH" ] ; then
  695.                             ENOUGH_CHARGE=1
  696.                         fi
  697.                     fi
  698.                     if [ "$AUTO_HIBERNATION_BATTERY_CHARGE_MWH" -ne 0 ] ; then
  699.                         FOUND_AN_ENABLED_HIBERNATION_CHECK=1
  700.                         if [ "$REMAINING" -ge "$AUTO_HIBERNATION_BATTERY_CHARGE_MWH" ] ; then
  701.                             ENOUGH_CHARGE_TO_PREVENT_HIBERNATION=1
  702.                         fi
  703.                     fi
  704.                 else
  705.                     echo "Failed to determine battery charge. Battery charge units are not in"
  706.                     echo "mWh or mAh."
  707.                 fi
  708.                 
  709.                 CAP_STATE=`cat "$BATT_STATE" | sed -r 's/^capacity state:\s*(.*)\s*$/\1/;t;d'`
  710.                 if [ "$DISABLE_LAPTOP_MODE_ON_CRITICAL_BATTERY_LEVEL" -ne 0 ] ; then
  711.                     if [ "$CAP_STATE" == "critical" ] ; then                
  712.                         # Restore the state we had before checking this battery, so that
  713.                         # this battery does not count as having enough charge.
  714.                         ENOUGH_CHARGE=$PREV_ENOUGH_CHARGE
  715.                     elif [ "$FOUND_AN_ENABLED_CHECK" -eq 0 ] ; then
  716.                         # This is the only check that is enabled. In that case a non-critical
  717.                         # battery level counts as "enough". (If we would count non-critical
  718.                         # battery levels as enough *always*, then the other settings would
  719.                         # have no effect; this is only a final fallback.)
  720.                         ENOUGH_CHARGE=1
  721.                     fi
  722.                 fi
  723.                 if [ "$AUTO_HIBERNATION_ON_CRITICAL_BATTERY_LEVEL" -ne 0 ] ; then
  724.                     if [ "$CAP_STATE" == "critical" ] ; then                
  725.                         ENOUGH_CHARGE_TO_PREVENT_HIBERNATION=$PREV_ENOUGH_CHARGE_TO_PREVENT_HIBERNATION
  726.                     elif [ "$FOUND_AN_ENABLED_HIBERNATION_CHECK" -eq 0 ] ; then
  727.                         ENOUGH_CHARGE_TO_PREVENT_HIBERNATION=1
  728.                     fi
  729.                 fi
  730.             else
  731.                 echo "Battery is not present." >> $OUTPUT
  732.             fi
  733.         done
  734.         if [ "$ENABLE_AUTO_HIBERNATION" -ne 0 -a "$ENOUGH_CHARGE_TO_PREVENT_HIBERNATION" -eq 0 ] ; then
  735.             echo "None of the batteries have a charge above the auto-hibernation level." >> $OUTPUT
  736.             echo "Starting hibernation." >> $OUTPUT
  737.             $HIBERNATE_COMMAND
  738.             # Don't continue -- if things are configured correctly, then we
  739.             # will be called on resume.
  740.             exit 0            
  741.         fi
  742.         if [ "$ENOUGH_CHARGE" -eq 0 ] ; then
  743.             echo "None of the batteries have a charge above the minimum level." >> $OUTPUT
  744.             echo "Deactivating data loss sensitive features." >> $OUTPUT
  745.             ACTIVATE_WITH_POSSIBLE_DATA_LOSS=0
  746.         fi
  747.     fi
  748. fi
  749.  
  750. if [ "$INIT" -eq 0 ] ; then
  751.     echo -n "Laptop mode "
  752. fi
  753.  
  754. # WAS_ACTIVE is used later on. If there is no /var/run/laptop-mode-state, then
  755. # we know that laptop mode wasn't active before.
  756. WAS_ACTIVE=0
  757.  
  758. if [ "$ACTIVATE" -eq 1 ] ; then
  759.     echo -n "$STATE, active."
  760.     if [ "$ACTIVATE_WITH_POSSIBLE_DATA_LOSS" -eq 0 ] ; then
  761.         echo -n ' (Data-loss sensitive features disabled.)'
  762.     fi
  763.     echo
  764. else
  765.     echo "$STATE, not active."
  766. fi
  767.  
  768.  
  769.  
  770. # Adjust CPU speed first -- that way, response to a switch to AC power will be faster,
  771. # while switching to battery will take place while we're taking less power on the whole.
  772.  
  773. #
  774. # get_medium_value
  775. #
  776. #   Get the medium value from a list of numerical values.
  777. #   $1 = file containing the list of values
  778. #
  779. get_medium_value() {
  780.     cat "$1" | sed 's/ /\n/g' | sort -n | awk -v RS="" '{n=split($0,a); print a[int((n+1)/2)]}'
  781. }
  782.  
  783. # Set kernel setting, showing an error if this fails.
  784. # Parameter 1: sysctl/proc path
  785. # Parameter 2: the value
  786. set_sysctl() {
  787.     echo "Executing: echo $2 > $1" >> $OUTPUT
  788.     if ! echo "$2" > "$1" ; then
  789.         echo "SETTING OF KERNEL PARAMETER FAILED: echo $2 \> $1"
  790.     fi
  791. }
  792.  
  793. if [ $CONTROL_CPU_FREQUENCY -eq 1 ] ; then
  794.     if [ $ON_AC -eq 1 ] ; then
  795.         if [ "$ACTIVATE" -eq 1 ] ; then
  796.             CPU_MAXFREQ="$LM_AC_CPU_MAXFREQ"
  797.             CPU_MINFREQ="$LM_AC_CPU_MINFREQ"
  798.             CPU_GOVERNOR="$LM_AC_CPU_GOVERNOR"
  799.         else
  800.             CPU_MAXFREQ="$NOLM_AC_CPU_MAXFREQ"
  801.             CPU_MINFREQ="$NOLM_AC_CPU_MINFREQ"
  802.             CPU_GOVERNOR="$NOLM_AC_CPU_GOVERNOR"
  803.         fi
  804.     else
  805.         CPU_MAXFREQ="$BATT_CPU_MAXFREQ"
  806.         CPU_MINFREQ="$BATT_CPU_MINFREQ"
  807.         CPU_GOVERNOR="$BATT_CPU_GOVERNOR"
  808.     fi
  809.     for THISCPU in /sys/devices/system/cpu/* ; do
  810.         if [ -e $THISCPU/cpufreq/cpuinfo_min_freq ]; then
  811.             THIS_CPU_MAXFREQ="$CPU_MAXFREQ"
  812.             THIS_CPU_MINFREQ="$CPU_MINFREQ"
  813.             THIS_CPU_GOVERNOR="$CPU_GOVERNOR"
  814.             if [ "$CPU_MAXFREQ" = "slowest" ]; then
  815.                 THIS_CPU_MAXFREQ=`cat $THISCPU/cpufreq/cpuinfo_min_freq`
  816.             fi
  817.             if [ "$CPU_MINFREQ" = 'slowest' ]; then
  818.                 THIS_CPU_MINFREQ=`cat $THISCPU/cpufreq/cpuinfo_min_freq`
  819.             fi
  820.             if [ "$CPU_MAXFREQ" = "medium" ] ; then
  821.                 THIS_CPU_MAXFREQ=$(get_medium_value $THISCPU/cpufreq/scaling_available_frequencies)
  822.             fi
  823.             if [ "$CPU_MINFREQ" = "medium" ] ; then
  824.                 THIS_CPU_MINFREQ=$(get_medium_value $THISCPU/cpufreq/scaling_available_frequencies)
  825.             fi
  826.             if [ "$CPU_MAXFREQ" = "fastest" ] ; then
  827.                 THIS_CPU_MAXFREQ=`cat $THISCPU/cpufreq/cpuinfo_max_freq`
  828.             fi
  829.             if [ "$CPU_MINFREQ" = "fastest" ] ; then
  830.                 THIS_CPU_MINFREQ=`cat $THISCPU/cpufreq/cpuinfo_max_freq`
  831.             fi
  832.             echo "Setting CPU maximum frequency for cpu $THISCPU to $THIS_CPU_MAXFREQ." >> $OUTPUT
  833.             set_sysctl $THISCPU/cpufreq/scaling_max_freq $THIS_CPU_MAXFREQ
  834.             echo "Setting CPU minimum frequency for cpu $THISCPU to $THIS_CPU_MINFREQ." >> $OUTPUT
  835.             set_sysctl $THISCPU/cpufreq/scaling_min_freq $THIS_CPU_MINFREQ
  836.             echo "Setting CPU frequency governor for cpu $THISCPU to $THIS_CPU_GOVERNOR." >> $OUTPUT
  837.             /sbin/modprobe cpufreq_$THIS_CPU_GOVERNOR >> $OUTPUT
  838.             set_sysctl $THISCPU/cpufreq/scaling_governor $THIS_CPU_GOVERNOR
  839.         fi
  840.     done
  841. fi
  842.  
  843. if [ $CONTROL_CPU_THROTTLING -eq 1 ] ; then
  844.     if [ $ON_AC -eq 1 ] ; then
  845.         if [ "$ACTIVATE" -eq 1 ] ; then
  846.             CPU_THROTTLING="$LM_AC_CPU_THROTTLING"
  847.         else
  848.             CPU_THROTTLING="$NOLM_AC_CPU_THROTTLING"
  849.         fi
  850.     else
  851.         CPU_THROTTLING="$BATT_CPU_THROTTLING"
  852.     fi
  853.     for THISCPU in /proc/acpi/processor/* ; do
  854.         if [ -e $THISCPU/throttling ]; then
  855.             NUM_LEVELS=`cat $THISCPU/throttling | grep "T[0123456789]*\:" | wc -l`
  856.             if [ "$CPU_THROTTLING" = "minimum" ]; then
  857.                 THIS_CPU_THROTTLING=0
  858.             elif [ "$CPU_THROTTLING" = "maximum" ] ; then                
  859.                 THIS_CPU_THROTTLING=$(($NUM_LEVELS - 1))
  860.             elif [ "$CPU_THROTTLING" = "medium" ] ; then
  861.                 # Divide but round up: that way, "medium" on a two-level system will
  862.                 # lead to full throttling -- which is 50% on my system, quite reasonable.
  863.                 THIS_CPU_THROTTLING=$(( ($NUM_LEVELS / 2 ) ))
  864.             else
  865.                 THIS_CPU_THROTTLING="$CPU_THROTTLING"
  866.             fi
  867.             echo "Setting throttling level for cpu $THISCPU to $THIS_CPU_THROTTLING." >> $OUTPUT
  868.             set_sysctl $THISCPU/throttling $THIS_CPU_THROTTLING
  869.         fi
  870.     done
  871. fi
  872.  
  873. if [ "$CONTROL_START_STOP" -ne 0 -a -f /var/run/laptop-mode-start-stop-undo-actions ] ; then
  874.     cat /var/run/laptop-mode-start-stop-undo-actions | \
  875.         while read SCRIPT STARTSTOPACTION ; do
  876.             $SCRIPT $STARTSTOPACTION
  877.         done
  878.        
  879. fi
  880.  
  881.  
  882.  
  883. # Adjust kernel settings and mount options (but only if data loss 
  884. # sensitive features are active)
  885. if [ "$ACTIVATE_WITH_POSSIBLE_DATA_LOSS" -eq 1 ] ; then
  886.     # 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.
  887.     MAX_LOST_WORK_SECONDS=$LM_BATT_MAX_LOST_WORK_SECONDS
  888.     if [ $ON_AC -eq 1 ] ; then
  889.         MAX_LOST_WORK_SECONDS=$LM_AC_MAX_LOST_WORK_SECONDS
  890.     fi
  891.  
  892.     AGE=$((100*$MAX_LOST_WORK_SECONDS))
  893.     XFS_AGE=$(($XFS_HZ*$MAX_LOST_WORK_SECONDS))
  894.  
  895.     if [ -d /proc/sys/vm/pagebuf ] ; then
  896.         # (For 2.4 and early 2.6.)
  897.         # This only needs to be set, not reset -- it is only used when
  898.         # laptop mode is enabled.
  899.         echo "Adjusting XFS kernel parameters for 2.4 and early 2.6 kernels." >> $OUTPUT
  900.         set_sysctl /proc/sys/vm/pagebuf/lm_flush_age  $XFS_AGE
  901.         set_sysctl /proc/sys/fs/xfs/lm_sync_interval  $XFS_AGE
  902.     elif [ -f /proc/sys/fs/xfs/lm_age_buffer ] ; then
  903.         # (A couple of early 2.6 laptop mode patches had these.)
  904.         # This only needs to be set, not reset -- it is only used when
  905.         # laptop mode is enabled.
  906.         echo "Adjusting XFS kernel parameters for early patched 2.6 kernels." >> $OUTPUT
  907.         set_sysctl /proc/sys/fs/xfs/lm_age_buffer    $XFS_AGE
  908.         set_sysctl /proc/sys/fs/xfs/lm_sync_interval $XFS_AGE
  909.     elif [ -f /proc/sys/fs/xfs/age_buffer ] ; then
  910.         # (2.6.6)
  911.         # But not for these -- they are also used in normal
  912.         # operation.
  913.         echo "Adjusting XFS kernel parameters for 2.6.6 kernel." >> $OUTPUT
  914.         set_sysctl /proc/sys/fs/xfs/age_buffer       $XFS_AGE 
  915.         set_sysctl /proc/sys/fs/xfs/sync_interval    $XFS_AGE
  916.     elif [ -f /proc/sys/fs/xfs/age_buffer_centisecs ] ; then
  917.         # (2.6.7 upwards)
  918.         # And not for these either. These are in centisecs,
  919.         # not USER_HZ, so we have to use $AGE, not $XFS_AGE.
  920.         echo "Adjusting XFS kernel parameters for >2.6.7 kernel." >> $OUTPUT
  921.         set_sysctl /proc/sys/fs/xfs/age_buffer_centisecs  $AGE
  922.         set_sysctl /proc/sys/fs/xfs/xfssyncd_centisecs    $AGE
  923.         set_sysctl /proc/sys/fs/xfs/xfsbufd_centisecs     3000
  924.     fi
  925.  
  926.     case "$KLEVEL" in
  927.         "2.4")
  928.             echo "Adjusting 2.4 kernel parameters to enable laptop mode." >> $OUTPUT
  929.             set_sysctl /proc/sys/vm/laptop_mode   1
  930.             set_sysctl /proc/sys/vm/bdflush       "30 500 0 0 $AGE $AGE 60 20 0"
  931.             ;;
  932.         "2.6")
  933.             echo "Adjusting 2.6 kernel parameters to enable laptop mode." >> $OUTPUT
  934.             set_sysctl /proc/sys/vm/laptop_mode          "$LM_SECONDS_BEFORE_SYNC"
  935.             set_sysctl /proc/sys/vm/dirty_writeback_centisecs "$AGE"
  936.             set_sysctl /proc/sys/vm/dirty_expire_centisecs    "$AGE"
  937.             set_sysctl /proc/sys/vm/dirty_ratio          "$LM_DIRTY_RATIO"
  938.             set_sysctl /proc/sys/vm/dirty_background_ratio    "$LM_DIRTY_BACKGROUND_RATIO"
  939.             ;;
  940.     esac
  941.     if [ $CONTROL_MOUNT_OPTIONS -eq 1 ]; then
  942.         echo "Remounting filesystems." >> $OUTPUT
  943.         cat /etc/mtab | while read DEV MP FST OPTS DUMP PASS ; do
  944.             DO=0
  945.             if ( echo " $PARTITIONS " | grep " $DEV " > /dev/null ) ; then
  946.                 DO=1
  947.                 echo "$DEV found in PARTITIONS." >> $OUTPUT
  948.             else
  949.                 echo "$DEV not found in PARTITIONS." >> $OUTPUT
  950.             fi
  951.             if ( echo " $PARTITIONS " | grep " $MP " > /dev/null ) ; then
  952.                 DO=1
  953.                 echo "$MP found in PARTITIONS." >> $OUTPUT
  954.             else
  955.                 echo "$MP not found in PARTITIONS." >> $OUTPUT
  956.             fi
  957.             if ( echo " $PARTITIONS " | grep " auto " > /dev/null ) ; then
  958.                 echo "Checking $DEV against HD because PARTITIONS contains \"auto\"." >> $OUTPUT
  959.                 for THISHD in $HD ; do
  960.                     echo "   Considering $THISHD." >> $OUTPUT
  961.                     if ( echo " $DEV" | grep "$THISHD" > /dev/null ) ; then
  962.                         DO=1
  963.                         echo "   $DEV contains $THISHD, which is in HD, so we will remount it." >> $OUTPUT
  964.                     fi
  965.                 done
  966.             fi
  967.             if [ "$DO" -ne 0 ] ; then
  968.                 echo "Original options: $OPTS" >> $OUTPUT
  969.                 if [ "$WAS_ACTIVE" -eq 0 ] ; then
  970.                     # Coming from inactive state: save last known mount options for the device.
  971.                     echo Updating /var/run/laptop-mode-nolm-mountopts.  >> $OUTPUT
  972.                     if [ -f /var/run/laptop-mode-nolm-mountopts ] ; then 
  973.                         sed -i "s|^$DEV .*$||" /var/run/laptop-mode-nolm-mountopts
  974.                     fi
  975.                     echo $DEV $OPTS >> /var/run/laptop-mode-nolm-mountopts
  976.                 else
  977.                     echo Not updating /var/run/laptop-mode-nolm-mountopts because laptop mode was already active. >> $OUTPUT
  978.                 fi
  979.                 if [ "$FST" = 'unknown' ]; then
  980.                     echo "Deducing fstype for $MP." >> $OUTPUT
  981.                     FST=$(deduce_fstype $MP)
  982.                     echo "Deduced fstype for $MP as $FST." >> $OUTPUT
  983.                 fi
  984.                 # Strip stuff like ext3,ext2 into just ext3.
  985.                 echo Reducing file system type.  >> $OUTPUT
  986.                 FST=`echo $FST | sed s/,.*//`
  987.                 case "$FST" in
  988.                     "ext3"|"reiserfs")
  989.                         echo Removing commit mount option from original options.  >> $OUTPUT
  990.                         PARSEDOPTS="$(remove_numeric_mount_option commit "$OPTS")"
  991.                         echo "Executing: mount $DEV -t $FST $MP -o remount,$PARSEDOPTS,commit=$MAX_LOST_WORK_SECONDS$NOATIME_OPT" >> $OUTPUT
  992.                         if (! mount $DEV -t $FST $MP -o remount,$PARSEDOPTS,commit=$MAX_LOST_WORK_SECONDS$NOATIME_OPT) ; then
  993.                             if [ "$FST" == "ext3" -a "$MP" == "/" ] ; then
  994.                                 echo "BIG FAT WARNING: Your root filesystem mounted as ext3 seems to lack support for"
  995.                                 echo "the commit mount option. This usually means that your root filesystem is"
  996.                                 echo "mounted as ext2 because there is no ext3 support in the kernel at boot time,"
  997.                                 echo "usually because you compiled ext3 as a module and don't load it in an initrd."
  998.                                 echo "Note that on recent 2.6 kernels, /proc/mounts shows the correct fs type for"
  999.                                 echo "the device /dev/root. You can check your actual root filesystem mount type"
  1000.                                 echo "there. To fix the problem, either make ext3 available at boot time by compiling"
  1001.                                 echo "it statically into the kernel, or configure the correct filesystem type in"
  1002.                                 echo "/etc/fstab."
  1003.                             fi
  1004.                         fi
  1005.                         ;;
  1006.                     *)
  1007.                         echo "Executing: mount $DEV -t $FST $MP -o remount,$OPTS$NOATIME_OPT" >> $OUTPUT
  1008.                         mount $DEV -t $FST $MP -o remount,$OPTS$NOATIME_OPT
  1009.                         ;;
  1010.                 esac
  1011.                 if [ -b $DEV -a "$CONTROL_READAHEAD" -ne 0 ] ; then
  1012.                     echo "Executing: /sbin/blockdev --setra $(($LM_READAHEAD * 2)) $DEV" >> $OUTPUT
  1013.                     /sbin/blockdev --setra $(($LM_READAHEAD * 2)) $DEV >> $OUTPUT 2>&1
  1014.                 fi
  1015.             fi
  1016.         done
  1017.     fi
  1018. else
  1019.     # DEACTIVATE w.r.t. kernel options and mount point settings
  1020.     U_AGE=$((100*$DEF_UPDATE))
  1021.     B_AGE=$((100*$DEF_MAX_AGE))
  1022.     set_sysctl /proc/sys/vm/laptop_mode 0
  1023.     if [ -f /proc/sys/fs/xfs/age_buffer -a ! -f /proc/sys/fs/xfs/lm_age_buffer ] ; then
  1024.         # These need to be restored, if there are no lm_*.
  1025.         echo "Restoring default XFS settings (pre-centisecs version)." >> $OUTPUT
  1026.         set_sysctl /proc/sys/fs/xfs/age_buffer    $(($XFS_HZ*$DEF_XFS_AGE_BUFFER))
  1027.         set_sysctl /proc/sys/fs/xfs/sync_interval $(($XFS_HZ*$DEF_XFS_SYNC_INTERVAL))
  1028.     elif [ -f /proc/sys/fs/xfs/age_buffer_centisecs ] ; then
  1029.         # These need to be restored as well.
  1030.         echo "Restoring default XFS settings." >> $OUTPUT
  1031.         set_sysctl /proc/sys/fs/xfs/age_buffer_centisecs  $((100*$DEF_XFS_AGE_BUFFER))
  1032.         set_sysctl /proc/sys/fs/xfs/xfssyncd_centisecs    $((100*$DEF_XFS_SYNC_INTERVAL))
  1033.         set_sysctl /proc/sys/fs/xfs/xfsbufd_centisecs     $((100*$DEF_XFS_BUFD_INTERVAL))
  1034.     fi
  1035.     case "$KLEVEL" in
  1036.         "2.4")
  1037.             echo "Adjusting 2.4 kernel parameters to disable laptop mode." >> $OUTPUT
  1038.             set_sysctl /proc/sys/vm/bdflush "30 500 0 0 $U_AGE $B_AGE 60 20 0"
  1039.             ;;
  1040.         "2.6")
  1041.             echo "Adjusting 2.6 kernel parameters to disable laptop mode." >> $OUTPUT
  1042.             set_sysctl /proc/sys/vm/dirty_writeback_centisecs   "$U_AGE"
  1043.             set_sysctl /proc/sys/vm/dirty_expire_centisecs      "$B_AGE"
  1044.             set_sysctl /proc/sys/vm/dirty_ratio            "$NOLM_DIRTY_RATIO"
  1045.             set_sysctl /proc/sys/vm/dirty_background_ratio        "$NOLM_DIRTY_BACKGROUND_RATIO"
  1046.             ;;
  1047.     esac
  1048.     if [ $CONTROL_MOUNT_OPTIONS -eq 1 ] ; then
  1049.         echo "Remounting filesystems." >> $OUTPUT
  1050.         cat /etc/mtab | while read DEV MP FST OPTS DUMP PASS ; do
  1051.             DO=0
  1052.             if ( echo " $PARTITIONS " | grep " $DEV " > /dev/null ) ; then
  1053.                 DO=1
  1054.                 echo "$DEV found in PARTITIONS." >> $OUTPUT
  1055.             else
  1056.                 echo "$DEV not found in PARTITIONS." >> $OUTPUT
  1057.             fi
  1058.             if ( echo " $PARTITIONS " | grep " $MP " > /dev/null ) ; then
  1059.                 DO=1
  1060.                 echo "$MP found in PARTITIONS." >> $OUTPUT
  1061.             else
  1062.                 echo "$MP not found in PARTITIONS." >> $OUTPUT
  1063.             fi
  1064.             if ( echo " $PARTITIONS " | grep " auto " > /dev/null ) ; then
  1065.                 echo "Checking $DEV against HD because PARTITIONS contains \"auto\"." >> $OUTPUT
  1066.                 for THISHD in $HD ; do
  1067.                     echo "   Considering $THISHD." >> $OUTPUT
  1068.                     if ( echo " $DEV" | grep "$THISHD" > /dev/null ) ; then
  1069.                         DO=1
  1070.                         echo "   $DEV contains $THISHD, which is in HD, so we will remount it." >> $OUTPUT
  1071.                     fi
  1072.                 done
  1073.             fi
  1074.             if [ "$DO" -ne 0 ] ; then
  1075.                 # Reset commit and atime options to defaults.
  1076.                 echo "Original options: $OPTS" >> $OUTPUT
  1077.                 if [ "$FST" = 'unknown' ]; then
  1078.                     echo "Deducing fstype for $MP." >> $OUTPUT
  1079.                     FST=$(deduce_fstype $MP)
  1080.                     echo "Deduced fstype for $MP as $FST." >> $OUTPUT
  1081.                 fi
  1082.                 
  1083.                 # Strip stuff like ext3,ext2 into just ext3.
  1084.                 echo Reducing file system type.  >> $OUTPUT
  1085.                 FST=`echo $FST | sed s/,.*//`
  1086.                 
  1087.                 # Retrieve original non-laptop mode mount options and restore them.
  1088.                 # If the file that stores them doesn't exist, then laptop mode
  1089.                 # has never been started.
  1090.                 if [ "$WAS_ACTIVE" -ne 0 -a -f /var/run/laptop-mode-nolm-mountopts ] ; then                        
  1091.                     SAVED_OPTS=`grep "^$DEV " /var/run/laptop-mode-nolm-mountopts`
  1092.                     SAVED_OPTS=${SAVED_OPTS#* } # trim device name
  1093.                 
  1094.                     case "$FST" in
  1095.                         "ext3"|"reiserfs")                                
  1096.                             PARSEDOPTS="$(replace_numeric_mount_option commit commit=0 $SAVED_OPTS $OPTS)"
  1097.                             PARSEDOPTS="$(replace_yesno_mount_option atime atime $SAVED_OPTS $PARSEDOPTS)"
  1098.                             echo Executing: mount $DEV -t $FST $MP -o remount,$PARSEDOPTS >> $OUTPUT
  1099.                             mount $DEV -t $FST $MP -o remount,$PARSEDOPTS
  1100.                             ;;
  1101.                         *)
  1102.                             PARSEDOPTS="$(replace_yesno_mount_option atime atime $SAVED_OPTS $OPTS)"
  1103.                             echo Executing: mount $DEV -t $FST $MP -o remount,$PARSEDOPTS >> $OUTPUT
  1104.                             mount $DEV -t $FST $MP -o remount,$PARSEDOPTS
  1105.                             ;;
  1106.                     esac
  1107.                 else
  1108.                     echo "No saved mount options, so apparently we never remounted this filesystem during this session." >> $OUTPUT
  1109.                     echo "Not remounting." >> $OUTPUT
  1110.                 fi
  1111.                 if [ -b $DEV -a "$CONTROL_READAHEAD" -ne 0 ] ; then
  1112.                     echo "Executing: /sbin/blockdev --setra $(($NOLM_READAHEAD * 2)) $DEV" >> $OUTPUT
  1113.                     /sbin/blockdev --setra $(($NOLM_READAHEAD * 2)) $DEV >> $OUTPUT 2>&1
  1114.                 fi
  1115.             fi
  1116.         done
  1117.     fi
  1118. fi
  1119.  
  1120.  
  1121.  
  1122. # Adjust hard drive powermanagement
  1123.  
  1124. # Function for drive capability check. This prevents ugly errors in
  1125. # the kernel output about unsupported commands.
  1126. #
  1127. # $1 = drive name
  1128. # $2 = capability (SDPARM/HDPARM or IDLE_TIMEOUT/POWERMGMT/WRITECACHE)
  1129. is_capable() {
  1130.     local dev=${1#/dev/}
  1131.     local MEDIA=
  1132.     local BUS=
  1133.  
  1134.     HAVE_UDEVINFO=0
  1135.     if [ -x "$(which udevinfo 2> /dev/null)" ] ; then
  1136.         UDEVVERSION=$(udevinfo -V | awk '{ print $3; }')
  1137.         if [ "$UDEVVERSION" -gt 70 ] ; then
  1138.             HAVE_UDEVINFO=1
  1139.         else
  1140.             echo "udevinfo present but version not > 070, not using udev" >> $OUTPUT
  1141.         fi
  1142.     fi
  1143.     
  1144.     # If we are running udev, this is the most portable way
  1145.     # It assumes more or less recent udev (> 070)
  1146.     if [ $HAVE_UDEVINFO -ne 0 ] ; then
  1147.         echo -n "Querying $1 media type using udevinfo: " >> $OUTPUT
  1148.         eval "$(udevinfo -q env -n $1 2> $OUTPUT | egrep '(ID_TYPE=|ID_BUS=)' >> $OUTPUT 2>&1)"
  1149.         if [ -n "$ID_TYPE" -a -n "$ID_BUS" ] ; then
  1150.             echo "type '$ID_TYPE on bus '$ID_BUS' detected" >> $OUTPUT
  1151.             MEDIA=$ID_TYPE
  1152.             BUS=$ID_BUS
  1153.         else
  1154.             echo "failed - udev not active?" >> $OUTPUT
  1155.         fi
  1156.     fi
  1157.  
  1158.     if [ -z "$MEDIA" ] ; then
  1159.         echo -n "Querying $1 media type using device name: " >> $OUTPUT
  1160.         case $dev in
  1161.             hd*)    # IDE device
  1162.                 if [ -r /proc/ide/$dev/media ]; then
  1163.                     MEDIA="$(cat /proc/ide/$dev/media)"
  1164.                     BUS=ata
  1165.                     if [ "$MEDIA" = cdrom ] ; then
  1166.                         MEDIA=cd
  1167.                     fi
  1168.                 fi
  1169.             ;;
  1170.             sd*)    # SCSI disk
  1171.                 # No need to check, sd is always SCSI disk
  1172.                 MEDIA=disk
  1173.                 BUS=scsi
  1174.             ;;
  1175.             sr* | scd* )
  1176.                 # No need to check, sr or scd is always SCSI CD-ROM
  1177.                 MEDIA=cd
  1178.                 BUS=scsi
  1179.             ;;
  1180.  
  1181.         esac
  1182.         if [ -n "$MEDIA" ] ; then
  1183.             echo "type '$MEDIA' on bus '$BUS' detected" >> $OUTPUT
  1184.         else
  1185.             echo "failed - unknown name" >> $OUTPUT
  1186.         fi
  1187.     fi
  1188.  
  1189.     if [ -z "$MEDIA" ] ; then
  1190.         if [ -x "$(which hdparm 2> /dev/null)" ]; then
  1191.             echo -n "Querying $1 type using hdparm: " >> $OUTPUT
  1192.             if hdparm -I $1 2> $OUTPUT | grep -q CD-ROM >> $OUTPUT 2>&1 ; then
  1193.                 MEDIA=cd
  1194.             else
  1195.                 MEDIA=disk
  1196.             fi
  1197.             BUS=ata # or acts like it anyway, because hdparm supports it.
  1198.             echo "type '$MEDIA' on bus '$BUS' detected" >> $OUTPUT
  1199.         fi
  1200.     fi
  1201.  
  1202.     # Sanity check
  1203.     if [ -z "$MEDIA" -o -z "$BUS" ] ; then
  1204.         echo "Querying $1 type - unknown type or bus, disabling hdparm/sdparm" >> $OUTPUT
  1205.         return 1
  1206.     fi
  1207.  
  1208.     if [ "$BUS" == "scsi" -a "$ASSUME_SCSI_IS_SATA" -ne 0 ] ;then
  1209.         # Treat scsi disks as SATA devices. Unfortunately they are hard
  1210.         # to recognize -- if anybody has a drive and cares to find out
  1211.         # how to recognize them, please enlighten me!
  1212.         BUS=ata
  1213.     fi
  1214.  
  1215.     # Now check what capabilities we support for the
  1216.     # various media and bus types.
  1217.     case "$MEDIA:$BUS:$2" in
  1218.         # Although CD-ROM drives usually support
  1219.         # idle timeout settings, they don't usually
  1220.         # support very low values, and we don't want
  1221.         # to mess with that. We simply ignore anything
  1222.         # that is a CD player.
  1223.         cd:*:* ) return 1;;
  1224.  
  1225.         # ATA drives support the "hdparm" command but
  1226.         # not normally the "sdparm" command.
  1227.         *:ata:HDPARM ) return 0 ;;
  1228.         *:ata:SDPARM ) return 1 ;;
  1229.         
  1230.         # SCSI drives support the "sdparm" command, but
  1231.         # not normally the "hdparm" command.
  1232.         *:scsi:SDPARM ) return 0 ;;
  1233.         *:scsi:HDPARM ) return 1 ;;
  1234.  
  1235.         # On ATA disks everything is supported.
  1236.         disk:ata:* ) return 0 ;;
  1237.  
  1238.         # For sdparm we only know how to set the idle
  1239.         # timeout, nothing else at the moment.
  1240.         *:scsi:IDLE_TIMEOUT ) return 0 ;;
  1241.  
  1242.         # No other capabilities are supported.
  1243.         * ) return 1 ;;
  1244.     esac
  1245. }
  1246.  
  1247. if [ $CONTROL_HD_POWERMGMT -eq 1 ] ; then
  1248.     if [ $ON_AC -eq 1 ] ; then
  1249.         if [ "$ACTIVATE" -eq 1 ] ; then
  1250.             HD_POWERMGMT=$LM_AC_HD_POWERMGMT
  1251.         else
  1252.             HD_POWERMGMT=$NOLM_AC_HD_POWERMGMT
  1253.         fi
  1254.     else
  1255.         HD_POWERMGMT=$BATT_HD_POWERMGMT
  1256.     fi
  1257.  
  1258.     echo "Setting powermanagement on drives to $HD_POWERMGMT." >> $OUTPUT
  1259.     for THISHD in $HD ; do
  1260.         if is_capable $THISHD POWERMGMT ; then
  1261.             if is_capable $THISHD HDPARM ; then
  1262.                 if [ ! -e `which hdparm 2> /dev/null` ] ; then
  1263.                     echo "ERROR: hdparm not installed."
  1264.                 else
  1265.                     echo "Executing: hdparm -B $HD_POWERMGMT $THISHD" >> $OUTPUT
  1266.                     hdparm -B $HD_POWERMGMT $THISHD >> $OUTPUT 2>&1
  1267.                 fi
  1268.             else
  1269.                 echo "Skipping $THISHD: powermgmt only possible with hdparm but drive does not" >> $OUTPUT
  1270.                 echo "support hdparm." >> $OUTPUT
  1271.             fi
  1272.         else
  1273.             echo "Skipping $THISHD: powermanagement control not supported." >> $OUTPUT
  1274.         fi
  1275.     done
  1276. fi
  1277.  
  1278. if [ $CONTROL_HD_IDLE_TIMEOUT -eq 1 ] ; then
  1279.     # Spindown timeouts may only be set when data-loss sensitive
  1280.     # features are active.
  1281.     if [ "$ACTIVATE_WITH_POSSIBLE_DATA_LOSS" -eq 1 ] ; then
  1282.         if [ $ON_AC -eq 1 ] ; then
  1283.             HD_IDLE_TIMEOUT=$LM_AC_HD_IDLE_TIMEOUT
  1284.             HD_IDLE_TIMEOUT_SECONDS=$LM_AC_HD_IDLE_TIMEOUT_SECONDS
  1285.         else
  1286.             HD_IDLE_TIMEOUT=$LM_BATT_HD_IDLE_TIMEOUT
  1287.             HD_IDLE_TIMEOUT_SECONDS=$LM_BATT_HD_IDLE_TIMEOUT_SECONDS
  1288.         fi
  1289.     else
  1290.         HD_IDLE_TIMEOUT=$NOLM_HD_IDLE_TIMEOUT
  1291.         HD_IDLE_TIMEOUT_SECONDS=$NOLM_HD_IDLE_TIMEOUT_SECONDS
  1292.     fi
  1293.     echo "Setting spindown timeout on drives to $HD_IDLE_TIMEOUT_SECONDS seconds." >> $OUTPUT
  1294.     echo "(hdparm configuration value = $HD_IDLE_TIMEOUT.)" >> $OUTPUT
  1295.     for THISHD in $HD ; do
  1296.         if is_capable $THISHD IDLE_TIMEOUT ; then
  1297.             if is_capable $THISHD HDPARM ; then
  1298.                 if [ ! -e `which hdparm 2> /dev/null` ] ; then
  1299.                     echo "ERROR: hdparm not installed."
  1300.                 else
  1301.                     echo "Executing: hdparm -S $HD_IDLE_TIMEOUT $THISHD" >> $OUTPUT
  1302.                     hdparm -S $HD_IDLE_TIMEOUT $THISHD >> $OUTPUT 2>&1
  1303.                 fi
  1304.             elif is_capable $THISHD SDPARM ; then
  1305.                 if [ ! -e `which sdparm 2> /dev/null` ] ; then
  1306.                     echo "ERROR: sdparm not installed."
  1307.                 else
  1308.                     HD_IDLE_TIMEOUT_DECISECONDS=$(($HD_IDLE_TIMEOUT_SECONDS*10))
  1309.                     echo "Executing: sdparm -q -s SCT=$HD_IDLE_TIMEOUT_DECISECONDS $THISHD" >> $OUTPUT
  1310.                     sdparm -q -s SCT=$HD_IDLE_TIMEOUT_DECISECONDS $THISHD >> $OUTPUT 2>&1
  1311.                 fi
  1312.             else
  1313.                 echo "Skipping $THISHD: drive supports neither hdparm nor sdparm." >> $OUTPUT
  1314.             fi
  1315.         else
  1316.             echo "Skipping $THISHD: idle timeout control not supported." >> $OUTPUT
  1317.         fi
  1318.     done
  1319. fi
  1320.  
  1321. if [ $CONTROL_HD_WRITECACHE -eq 1 ] ; then
  1322.     # The writecache may only be enabled when data-loss sensitive
  1323.     # features are active.
  1324.  
  1325.     if [ "$ACTIVATE" -eq 1 ] ; then
  1326.         if [ "$ACTIVATE_WITH_POSSIBLE_DATA_LOSS" -eq 0 ] ; then
  1327.             HD_WRITECACHE=0
  1328.         else
  1329.             HD_WRITECACHE=$LM_HD_WRITECACHE
  1330.         fi
  1331.     else
  1332.         if [ $ON_AC -eq 1 ] ; then
  1333.             HD_WRITECACHE=$NOLM_AC_HD_WRITECACHE
  1334.         else
  1335.             HD_WRITECACHE=$NOLM_BATT_HD_WRITECACHE
  1336.         fi
  1337.     fi
  1338.     echo "Setting write cache on drives to $HD_WRITECACHE." >> $OUTPUT
  1339.     for THISHD in $HD ; do
  1340.         if is_capable $THISHD WRITECACHE ; then
  1341.             if is_capable $THISHD HDPARM ; then
  1342.                 if [ ! -e `which hdparm 2> /dev/null` ] ; then
  1343.                     echo "ERROR: hdparm not installed."
  1344.                 else
  1345.                     echo "Executing: hdparm -W $HD_WRITECACHE $THISHD" >> $OUTPUT
  1346.                     hdparm -W $HD_WRITECACHE $THISHD >> $OUTPUT 2>&1
  1347.                 fi
  1348.             else
  1349.                 echo "Skipping $THISHD: writecache only possible with hdparm but drive does not" >> $OUTPUT
  1350.                 echo "support hdparm." >> $OUTPUT
  1351.             fi
  1352.         else
  1353.             echo "Skipping $THISHD: writecache control not supported." >> $OUTPUT
  1354.         fi
  1355.     done
  1356. fi
  1357.  
  1358. if [ $CONTROL_SYSLOG_CONF -eq 1 ] ; then
  1359.     echo "Adjusting syslog configuration." >> $OUTPUT
  1360.     if [ "`readlink -f $SYSLOG_CONF`" != "$SYSLOG_CONF" ] ; then
  1361.         echo "$SYSLOG_CONF is a symlink." >> $OUTPUT
  1362.         if [ ! -f "$SYSLOG_CONF.no-lm" ] ; then
  1363.             echo "But there is no $SYSLOG_CONF.no-lm. This must have been done by an earlier" >> $OUTPUT
  1364.             echo "version of laptop-mode-tools." >> $OUTPUT
  1365.             echo "Creating it now from $NOLM_AC_SYSLOG_CONF."
  1366.             cp "$NOLM_AC_SYSLOG_CONF" "$SYSLOG_CONF.no-lm"
  1367.         fi
  1368.     else
  1369.         echo "$SYSLOG_CONF is not a symlink." >> $OUTPUT
  1370.         if [ "$STATE" == "enabled" ] ; then
  1371.             echo "Saving it to $SYSLOG_CONF.no-lm." >> $OUTPUT
  1372.             cp --backup=numbered "$SYSLOG_CONF" "$SYSLOG_CONF.no-lm"
  1373.         fi
  1374.     fi
  1375.  
  1376.     if [ "$STATE" != "enabled" ] ; then
  1377.         echo "Laptop mode is not enabled. Restoring $SYSLOG_CONF." >> $OUTPUT
  1378.         if [ -f "$SYSLOG_CONF.no-lm" ] ; then
  1379.             mv "$SYSLOG_CONF.no-lm" "$SYSLOG_CONF"
  1380.         elif [ "`readlink -f $SYSLOG_CONF`" != "$SYSLOG_CONF" ] ; then
  1381.             echo "ERROR: $SYSLOG_CONF is a symlink but $SYSLOG_CONF.no-lm is not present."
  1382.         fi
  1383.     elif [ $ON_AC -eq 1 ] ; then
  1384.         if [ "$ACTIVATE" -eq 1 ] ; then
  1385.             echo "Setting syslog config to $LM_AC_SYSLOG_CONF." >> $OUTPUT
  1386.             ln -fs "$LM_AC_SYSLOG_CONF" "$SYSLOG_CONF"
  1387.         else
  1388.             echo "Setting syslog config to $NOLM_AC_SYSLOG_CONF." >> $OUTPUT
  1389.             ln -fs "$NOLM_AC_SYSLOG_CONF" "$SYSLOG_CONF"
  1390.         fi
  1391.     else
  1392.         echo "Setting syslog config to $BATT_SYSLOG_CONF." >> $OUTPUT
  1393.         ln -fs "$BATT_SYSLOG_CONF" "$SYSLOG_CONF"
  1394.     fi
  1395.     # Notify syslogd of configuration change.
  1396.     if [ "$SYSLOG_CONF_SIGNAL_PROGRAM" != "" ] ; then
  1397.         echo "Sending SIGHUP to all $SYSLOG_CONF_SIGNAL_PROGRAM processes." >> $OUTPUT
  1398.         killall -q -HUP $SYSLOG_CONF_SIGNAL_PROGRAM
  1399.     fi
  1400. fi
  1401.  
  1402. # Setting X screen standby/suspend/powerdown timing
  1403. if [ $CONTROL_DPMS_STANDBY -eq 1 ] ; then
  1404.     if [ $ON_AC -eq 1 ]; then
  1405.         if [ "$ACTIVATE" -eq 1 ]; then
  1406.             STANDBY="$LM_AC_DPMS_STANDBY"
  1407.             SUSPEND=$((STANDBY+30))
  1408.             OFF=$((STANDBY+60))
  1409.         else
  1410.             STANDBY="$NOLM_AC_DPMS_STANDBY"
  1411.             SUSPEND=$((STANDBY+300))
  1412.             OFF=$((STANDBY+600))
  1413.         fi
  1414.     else
  1415.         STANDBY="$BATT_DPMS_STANDBY"
  1416.         SUSPEND=$((STANDBY+30))
  1417.         OFF=$((STANDBY+60))
  1418.     fi
  1419.  
  1420.     # try all known paths to xset -- its location varies.
  1421.     for PATHBIN in /usr/X11R6/bin /bin /usr/bin /usr/local/bin ; do
  1422.         XSET="$PATHBIN/xset"
  1423.         if [ -x $XSET ]; then
  1424.             # In regular expression match only users having screen 
  1425.             # ( e.g "jerome *:0" match, but "somebodyelse tty1" no)
  1426.             # We set screen only for users using xwindow screen. 
  1427.             # Jerome's note: Yes, I know, there is race condition, 
  1428.             # but have no idea for some simple solution.
  1429.             w -h | while read -r USER SCREEN; do
  1430.                 case "$screen" in *:*)
  1431.                     echo "Set X11 DPMI for user $USER: $XSET -display $SCREEN dpms $STANDBY $SUSPEND $OFF." >> $OUTPUT
  1432.                     su $USER -c "$XSET -display $SCREEN dpms $STANDBY $SUSPEND $OFF 2>&1" >>$OUTPUT
  1433.                 esac
  1434.             done
  1435.             HAVEXSET="1"
  1436.             break
  1437.         fi
  1438.     done
  1439.     if [ -z "$HAVEXSET" ]; then
  1440.         echo "Can't find \"xset\" command, skipping..." >> $OUTPUT
  1441.     fi
  1442. else
  1443.     echo "CONTROL_DPMS_STANDBY is disabled, skipping..." >> $OUTPUT
  1444. fi
  1445.  
  1446. # Set terminal blanking/powerdown timeouts
  1447. if [ $CONTROL_TERMINAL -ne 0 ] ; then
  1448.     if [ $ON_AC -eq 1 ]; then
  1449.         if [ "$ACTIVATE" -eq 1 ]; then
  1450.             BLANK_MINUTES="$LM_AC_BLANK_MINUTES"
  1451.             POWERDOWN_MINUTES="$LM_AC_POWERDOWN_MINUTES"
  1452.         else
  1453.             BLANK_MINUTES="$NOLM_AC_BLANK_MINUTES"
  1454.             POWERDOWN_MINUTES="$NOLM_AC_POWERDOWN_MINUTES"
  1455.         fi
  1456.     else
  1457.         BLANK_MINUTES="$BATT_BLANK_MINUTES"
  1458.         POWERDOWN_MINUTES="$BATT_POWERDOWN_MINUTES"
  1459.     fi
  1460.     setterm -blank "$BLANK_MINUTES"
  1461.     setterm -powerdown "$POWERDOWN_MINUTES"
  1462. else
  1463.     echo "CONTROL_TERMINAL is disabled, skipping..." >> $OUTPUT
  1464. fi
  1465.  
  1466.  
  1467.  
  1468. # Start/stop programs 
  1469. if [ $CONTROL_START_STOP -eq 1 -a "$STATE" == "enabled" ]; then
  1470.     # Empty undo file first. We write the actions we take
  1471.     # into this file, so that we can undo them at the
  1472.     # next state change. Note: we actually
  1473.     # write the actions to the file in reverse order,
  1474.     # so we can execute the commands easily afterwards.
  1475.     echo > /var/run/laptop-mode-start-stop-undo-actions 
  1476.         
  1477.        
  1478.     if [ $ON_AC -eq 1 ] ; then
  1479.         if [ "$ACTIVATE" -eq 1 ] ; then        
  1480.             START_STOP_DIR_PREFIX=/etc/laptop-mode/lm-ac
  1481.         else
  1482.             START_STOP_DIR_PREFIX=/etc/laptop-mode/nolm-ac
  1483.         fi
  1484.     else
  1485.         START_STOP_DIR_PREFIX=/etc/laptop-mode/batt
  1486.     fi
  1487.     START_DIR="$START_STOP_DIR_PREFIX"-start
  1488.     STOP_DIR="$START_STOP_DIR_PREFIX"-stop
  1489.     if [ -d "$STOP_DIR" ] ; then
  1490.         for SCRIPT in "$STOP_DIR"/* ; do
  1491.             if [ -e $SCRIPT ] ; then
  1492.                 "$SCRIPT" stop
  1493.                 # Dereference any links. When people configure
  1494.                 # the directories with links and then they remove
  1495.                 # links while laptop mode is active, the "undo"
  1496.                 # will fail if we don't dereference the links
  1497.                 # before storing them.
  1498.                 LINKTARGET=`readlink -f "$SCRIPT"`
  1499.                 sed -i "1i $LINKTARGET start" /var/run/laptop-mode-start-stop-undo-actions
  1500.             fi
  1501.         done
  1502.     fi
  1503.     if [ -d "$START_DIR" ] ; then
  1504.         for SCRIPT in "$START_DIR"/* ; do
  1505.             if [ -e $SCRIPT ] ; then
  1506.                 "$SCRIPT" start
  1507.                 LINKTARGET=`readlink -f "$SCRIPT"`
  1508.                 sed -i "1i $LINKTARGET stop" /var/run/laptop-mode-start-stop-undo-actions
  1509.             fi
  1510.         done
  1511.     fi
  1512. fi
  1513.  
  1514. exit 0
  1515.  
  1516. # This fi closes the if for "readconfig". If I would have indented this one
  1517. # I would have indented the whole file. :)
  1518. fi
  1519.