blob: ac6a15f81235a88e261e024b54bed7f5683f1ec7 [file] [log] [blame]
#!/bin/dash
# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
#
# NOTE: This script works in dash, but is not as featureful. Specifically,
# dash omits readline support (history & command line editing). So we try
# to run through bash if it exists, otherwise we stick to dash. All other
# code should be coded to the POSIX standard and avoid bashisms.
#
# Please test that any changes continue to work in dash by running
# '/build/$BOARD/bin/dash crosh --dash' before checking them in.
# Disable path expansion at the command line. None of our builtins need or want
# it, and it's safer/saner to disallow it in the first place.
set -f
# Don't allow SIGHUP to terminate crosh. This guarantees that even if the user
# closes the crosh window, we make our way back up to the main loop, which gives
# cleanup code in command handlers a chance to run.
trap '' HUP
# Do not let CTRL+C kill crosh itself. This does let the user kill commands
# that are run by crosh (like `ping`).
trap : INT
# If it exists, use $DATA_DIR to define the $HOME location, as a first step
# to entirely removing the use of $HOME. (Though HOME should be used as
# fall-back when DATA_DIR is unset.)
# TODO(keescook): remove $HOME entirely crbug.com/333031
if [ "${DATA_DIR+set}" = "set" ]; then
export HOME="${DATA_DIR}/user"
fi
IS_BASH=0
try_bash() {
# If dash was explicitly requested, then nothing to do.
case " $* " in
*" --dash "*) return 0;;
esac
# If we're already bash, then nothing to do.
if type "history" 2>/dev/null | grep -q "shell builtin"; then
IS_BASH=1
return 0
fi
# Still here? Relaunch in bash.
exec /bin/bash $0 "$@"
}
try_bash "$@"
#
# Please keep the help text in alphabetical order!
#
HELP='
exit
Exit crosh.
help
Display this help.
help_advanced
Display the help for more advanced commands, mainly used for debugging.
ping [-c count] [-i interval] [-n] [-s packetsize] [-W waittime] <destination>
Send ICMP ECHO_REQUEST packets to a network host. If <destination> is "gw"
then the next hop gateway for the default route is used.
top
Run top.
'
HELP_ADVANCED='
battery_firmware <info|check|update>
info : query battery info
check : checks AC Adapter is connnected or not.
also checks the battery firmware is the latest or not.
update : trigger battery firmware update
battery_test [<test length>]
Tests battery discharge rate for given number of seconds. Without an argument,
defaults to 300 seconds.
bt_console [<agent capability>]
Enters a Bluetooth debugging console. Optional argument specifies the
capability of a pairing agent the console will provide; see the Bluetooth
Core specification for valid options.
chaps_debug [start|stop|<log_level>]
Sets the chapsd logging level. No arguments will start verbose logging.
connectivity
Shows connectivity status. "connectivity help" for more details
ff_debug [<tag_expr>] [--help] [--list_valid_tags] [--reset]
Add and remove flimflam debugging tags.
inputcontrol
Manually adjust advanced touchpad and mouse settings. Run
"inputcontrol -h" for full list of options.
memory_test
Performs extensive memory testing on the available free memory.
modem <command> [args...]
Interact with the 3G modem. Run "modem help" for detailed help.
modem_set_carrier carrier-name
Configures the modem for the specified carrier.
network_diag [--date] [--flimflam] [--link] [--show-macs] [--wifi] [--help]
[--wifi-mon] <host>
A function that performs a suite of network diagnostics. Saves a copy
of the output to your download directory.
network_logging <wifi | cellular | ethernet>
A function that enables a predefined set of tags useful for
debugging the specified device.
p2p_update [enable|disable]
Enables or disables the peer-to-peer (P2P) sharing of updates over the local
network. This will both, attempt to get updates from other peers in the
network and share the downloaded updates with them. Run this command without
arguments to see the current state.
rlz < status | enable | disable >
Enable or disable RLZ.
rollback
Attempt to rollback to the previous update cached on your system. Only
available on non-stable channels and non-enterprise enrolled devices. Please
note that this will powerwash your device.
route [-6]
Display the routing tables.
set_apn [-n <network-id>] [-u <username>] [-p <password>] <apn>
Set the APN to use when connecting to the network specified by <network-id>.
If <network-id> is not specified, use the network-id of the currently
registered network.
set_apn -c
Clear the APN to be used, so that the default APN will be used instead.
set_arpgw <true | false>
Turn on extra network state checking to make sure the default gateway
is reachable.
set_cellular_ppp [-u <username>] [-p <password>]
Set the PPP username and/or password for an existing cellular connection.
If neither -u nor -p is provided, show the existing PPP username for
the cellular connection.
set_cellular_ppp -c
Clear any existing PPP username and PPP password for an existing cellular
connection.
set_time [<time string>]
Sets the system time if the the system has been unable to get it from the
network. The <time string> uses the format of the GNU coreutils date command.
set_wake_on_lan <true | false>
Enable or disable Wake on LAN for Ethernet devices. This command takes
effect after re-connecting to Ethernet and is not persistent across system
restarts.
storage_test_1
Performs a short offline SMART test.
storage_test_2
Performs an extensive readability test.
syslog <message>
Logs a message to syslog.
time_info
Returns the current synchronization state for the time service.
tpm_status
Prints TPM status information.
tracepath [-n] <destination>[/port]
Trace the path/route to a network host.
update_over_cellular [enable|disable]
Enables or disables the auto updates over cellular networks. Run without
arguments to see the current state.
upload_crashes
Uploads available crash reports to the crash server.
upload_devcoredumps [enable|disable]
Enable or disable the upload of devcoredump reports.
wpa_debug [<debug_level>] [--help] [--list_valid_level] [--reset]
Set wpa_supplicant debugging level.
'
INTRO_TEXT="Welcome to crosh, the Chrome OS developer shell.
If you got here by mistake, don't panic! Just close this tab and carry on.
Type 'help' for a list of commands.
"
CHROMEOS_INSTALL=/usr/sbin/chromeos-install
check_digits() {
expr "$1" : '^[[:digit:]]*$' > /dev/null
}
load_extra_crosh() {
# Keep `local` decl split from assignment so return code is checked.
local crosh_dir devmode removable src
crosh_dir=$(dirname "$0")
if [ -e /usr/share/misc/chromeos-common.sh ]; then
. "/usr/share/misc/chromeos-common.sh" || exit 1
src=$(get_block_dev_from_partition_dev $(rootdev -s))
if [ "$(cat /sys/block/${src#/dev/}/removable)" = "1" ]; then
removable=1
fi
fi
case "${removable}: $* " in
1:*|\
*:*" --usb "*)
. "${crosh_dir}/crosh-usb"
;;
esac
# Force dev behavior on dev images.
if type crossystem >/dev/null 2>&1; then
crossystem "cros_debug?1"
devmode=$((!$?))
else
echo "Could not locate 'crossystem'; assuming devmode is off."
fi
case "${devmode}: $* " in
1:*|\
*:*" --dev "*)
. "${crosh_dir}/crosh-dev"
;;
esac
}
shell_read() {
local prompt="$1"
shift
if [ "$IS_BASH" -eq "1" ]; then
# In bash, -e gives readline support.
read -p "$prompt" -e $@
else
read -p "$prompt" $@
fi
}
shell_history() {
if [ "$IS_BASH" -eq "1" ]; then
# In bash, the history builtin can be used to manage readline history
history $@
fi
}
# Prints the value corresponding to the passed-in field in the output from
# dump_power_status.
get_power_status_field() {
local field="$1"
dump_power_status | awk -v field="${field}" '$1 == field { print $2 }'
}
cmd_help() (
echo "$HELP"
)
cmd_help_advanced() (
echo "$HELP_ADVANCED"
)
# We move the trailing brace to the next line so that we avoid the style
# checker from rejecting the use of braces. We cannot use subshells here
# as we want the set the exit variable in crosh itself.
# http://crbug.com/318368
cmd_exit()
{
exit='y'
}
cmd_set_time() (
local spec="$*"
if [ -z "${spec}" ]; then
echo "A date/time specification is required."
echo "E.g., set_time 10 February 2012 11:21am"
echo "(Remember to set your timezone in Settings first.)"
return
fi
local sec status
sec=$(date +%s --date="${spec}" 2>&1)
status=$?
if [ ${status} -ne 0 -o -z "${sec}" ]; then
echo "Unable to understand the specified time:"
echo "${sec}"
return
fi
local reply
reply=$(dbus-send --system --type=method_call --print-reply \
--dest=org.torproject.tlsdate /org/torproject/tlsdate \
org.torproject.tlsdate.SetTime "int64:$((sec))" 2>/dev/null)
status=$?
if [ ${status} -ne 0 ]; then
echo "Time not set. Unable to communicate with the time service."
return
fi
# Reply format: <dbus response header>\n uint32 <code>\n
local code
code=$(echo "${reply}" | sed -n -e '$s/.*uint32 \([0-9]\).*/\1/p')
case "${code}" in
0)
echo "Time has been set."
;;
1)
echo "Requested time was invalid (too large or too small): ${sec}"
;;
2)
echo "Time not set. Network time cannot be overriden."
;;
3)
echo "Time not set. There was a communication error."
;;
*)
echo "An unexpected response was received: ${code}"
echo "Details: ${reply}"
esac
)
cmd_ssh() (
cat <<EOF
The 'ssh' command has been removed. Please install the official SSH extension:
https://chrome.google.com/webstore/detail/pnhechapfaindjhompbnflcldabbghjo
EOF
)
cmd_swap() (
local swap_enable_file="/home/chronos/.swap_enabled"
case "$1" in
"enable")
if [ -z "$2" ]; then
# remove file in case root owns it
rm -f $swap_enable_file
touch $swap_enable_file
elif ! echo "$2" | grep -q "^[0-9]*$"; then
echo "$2 is not a valid integer literal"
cmd_swap usage
return 1
elif [ "$2" -ne 500 -a \
"$2" -ne 1000 -a \
"$2" -ne 2000 -a \
"$2" -ne 3000 -a \
"$2" -ne 4000 -a \
"$2" -ne 4500 -a \
"$2" -ne 6000 ]; then
echo "invalid size $2."
echo "Valid choices: 500, 1000, 2000, 3000, 4000, 4500 or 6000."
cmd_swap usage
return 1
else
# remove file in case root owns it
rm -f $swap_enable_file
echo "$2" > $swap_enable_file
echo "You have selected a size of $2 MB for compressed swap."
echo "Your choice may affect system performance in various ways."
echo "Presumably you know what you are doing."
fi
echo "Swap will be ON at next reboot."
;;
"disable")
# remove file in case root owns it
rm -f $swap_enable_file
echo 0 > $swap_enable_file
echo "You are turning compressed swap off."
echo "This may impact system performance in various ways."
echo "Presumably you know what you are doing."
echo "Swap will be OFF at next reboot."
;;
"status")
/sbin/swapon -s
;;
*)
echo "Usage:"
echo " swap status print swap device max and current size (if on)"
echo " swap enable [<optional swap size (MB)>]"
echo " swap disable"
return 1
;;
esac
)
cmd_time_info() (
echo "Last time synchronization information:"
dbus-send --system --type=method_call --print-reply \
--dest=org.torproject.tlsdate /org/torproject/tlsdate \
org.torproject.tlsdate.LastSyncInfo 2>/dev/null |
sed -n \
-e 's/boolean/network-synchronized:/p' \
-e 's/string/last-source:/p' \
-e 's/int64/last-synced-time:/p'
)
cmd_bt_console() (
if [ -x /usr/bin/bluetoothctl ]; then
/usr/bin/bluetoothctl "${1:+--agent=$1}"
else
echo "Bluetooth console not available"
fi
)
cmd_ff_debug() (
/usr/bin/ff_debug "$@"
)
cmd_wpa_debug() (
/usr/bin/wpa_debug "$@"
)
cmd_set_arpgw() (
case "$1" in
"true"|"false")
/usr/bin/set_arpgw "$1"
;;
"")
/usr/bin/set_arpgw
;;
*)
echo "Unknown option: $1"
return 1
;;
esac
)
cmd_set_wake_on_lan() (
case "$1" in
"true"|"false")
/usr/bin/set_wake_on_lan "$1"
;;
"")
/usr/bin/set_wake_on_lan
;;
*)
echo "Unknown option: $1"
return 1
;;
esac
)
cmd_network_logging() (
if [ -n "$1" ]; then
case "$1" in
"wifi")
echo; /usr/bin/ff_debug service+wifi+inet+device+manager
echo; /usr/bin/wpa_debug msgdump
echo; /usr/bin/modem set-logging info
;;
"cellular")
echo; /usr/bin/ff_debug service+cellular+modem+device+manager
echo; /usr/bin/wpa_debug info
echo; /usr/bin/modem set-logging debug
;;
"ethernet")
echo; /usr/bin/ff_debug service+ethernet+device+manager
echo; /usr/bin/wpa_debug info
echo; /usr/bin/modem set-logging info
;;
"--help")
echo "Usage: network_logging <wifi | cellular | ethernet>"
;;
*)
echo "Invalid parameter $1"
;;
esac
else
echo "Missing parameter wifi | cellular | ethernet"
fi
)
cmd_network_diag() (
/usr/bin/network_diag "$@"
)
debugd() {
# Default timeout 30 seconds.
local timeout="--reply-timeout=30000"
case $1 in
--reply-timeout=*) timeout=$1; shift;;
esac
local method="$1"; shift
dbus-send ${timeout} --system --print-reply --fixed --dest=org.chromium.debugd \
/org/chromium/debugd "org.chromium.debugd.$method" "$@"
}
# Run a debugd command for a long time and poll its output.
# This expects Start & Stop methods.
debugd_poll() (
local methodbase="$1"; shift
local pid fifo
# Make sure we clean up the background process and temp files when the
# user kills us with CTRL+C.
cleanup() {
# Don't let the user kill us while cleaning up.
trap : INT
if [ -n "${pid}" ]; then
if ! debugd "${methodbase}Stop" "string:${pid}"; then
echo "warning: could not stop ${methodbase}"
fi
pid=''
fi
if [ -n "${fifo}" ]; then
dir=$(dirname "${fifo}")
rm -rf "${dir}"
fifo=''
fi
}
trap cleanup INT
if ! fifo="$(mk_fifo)"; then
# The mk_fifo command already showed a warning.
return 1
fi
debugd "${methodbase}Start" "$@" 2>&1 >"${fifo}" &
read pid < "${fifo}"
cat "${fifo}"
cleanup
)
cmd_ping() (
local option="dict:string:variant:"
# NB: use printf to avoid echo interpreting -n
while [ "$(printf '%s' "$1" | cut -c1)" = "-" ]; do
# Do just enough parsing to filter/map options; we
# depend on ping to handle final validation
if [ "$1" = "-i" ]; then
shift; option="${option}interval,int32:$1,"
elif [ "$1" = "-c" ]; then
shift; option="${option}count,int32:$1,"
elif [ "$1" = "-W" ]; then
shift; option="${option}waittime,int32:$1,"
elif [ "$1" = "-s" ]; then
shift; option="${option}packetsize,int32:$1,"
elif [ "$1" = "-n" ]; then
option="${option}numeric,boolean:true,"
elif [ "$1" = "-b" ]; then
option="${option}broadcast,boolean:true,"
else
echo "Unknown option: $1"
return 1
fi
shift
done
if [ -z "$1" ]; then
echo "Missing parameter: destination"
return 1
fi
local dest="$1"
if [ "$dest" = "gw" ]; then
# Convenient shorthand for the next-hop gateway attached
# to the default route; this means if you have a host named
# "gw" then you'll need to specify a FQDN or IP address.
dest=$(ip route show | awk '$1 == "default" { print $3 }')
if [ -z "$dest" ]; then
echo "Cannot determine primary gateway; routing table is:"
cmd_route
return 1
fi
fi
option=$(echo "$option" | sed 's/,$//')
debugd_poll Ping "fd:1" "string:${dest}" "${option}"
)
cmd_progressive_scan() (
local flag_file="/home/chronos/.progressive_scan"
local enabled=0
local changed=0
if [ -r ${flag_file} ]; then
enabled=1
fi
if [ -z "$1" ]; then
if [ ${enabled} -eq 1 ]; then
echo "Currently enabled"
else
echo "Currently disabled"
fi
return
fi
if [ "$1" = "on" ]; then
if [ $enabled -eq 0 ]; then
changed=1;
fi
touch "${flag_file}"
else
if [ $enabled -eq 1 ]; then
changed=1
fi
rm -f "${flag_file}"
fi
if [ $changed -eq 1 ]; then
echo "You must reboot (or restart shill) for this to take effect."
else
echo "No change."
fi
)
cmd_chaps_debug() (
local level=${1:--2}
if [ "$1" = "stop" ]; then
level=0
fi
if [ "$1" = "start" ]; then
level=-2
fi
rm -f /home/chronos/.chaps_debug_1 /home/chronos/.chaps_debug_2
if [ "${level}" = "-1" ]; then
touch /home/chronos/.chaps_debug_1
elif [ "${level}" = "-2" ]; then
touch /home/chronos/.chaps_debug_2
fi
/usr/bin/chaps_client --set_log_level=${level} 2> /dev/null
if [ $? -eq 0 ]; then
echo "Logging level set to ${level}."
else
echo "Failed to set logging level."
fi
)
cmd_route() (
local option="dict:string:variant:"
while [ $# -gt 0 ]; do
case $1 in
-6) option="${option}v6,boolean:true," ;;
*)
echo "Unknown option: $1"
return 1
esac
shift
done
debugd GetRoutes "${option%,}"
)
cmd_tracepath() (
local option="dict:string:variant:"
# NB: use printf to avoid echo interpreting -n
while [ "$(printf '%s' "$1" | cut -c1)" = "-" ]; do
if [ "$1" = "-n" ]; then
option="${option}numeric,boolean:true,"
else
echo "Unknown option: $1"
return 1
fi
shift
done
option=$(echo "$option" | sed 's/,$//')
if [ -z "$1" ]; then
echo "Missing parameter: destination"
return 1
fi
debugd_poll TracePath "fd:1" "string:$1" "${option}"
)
cmd_top() (
# -s is "secure" mode, which disables kill, renice, and change display/sleep
# interval.
top -s
)
cmd_modem() (
/usr/bin/modem "$@"
)
cmd_modem_set_carrier() (
/usr/bin/modem set-carrier "$@"
)
cmd_set_apn() (
/usr/bin/set_apn "$@"
)
cmd_set_cellular_ppp() (
/usr/bin/set_cellular_ppp "$@"
)
cmd_connectivity() (
/usr/bin/connectivity "$@"
)
cmd_autest() (
local omaha_url="autest"
if [ "$1" = "-scheduled" ]; then
# pretend that this is a scheduled check as opposed to an user-initiated
# check for testing features that get enabled only on scheduled checks.
omaha_url="autest-scheduled"
fi
echo "Calling update_engine_client with omaha_url = $omaha_url"
/usr/bin/update_engine_client --omaha_url=$omaha_url
)
cmd_p2p_update() (
case "$1" in
"enable")
param="-p2p_update=yes"
;;
"disable")
param="-p2p_update=no"
;;
"")
param=""
;;
*)
echo "Usage: p2p_update [enable|disable]
Enables or disables the peer-to-peer (P2P) sharing of updates over the local
network. This will both, attempt to get updates from other peers in the
network and share the downloaded updates with them. Run this command without
arguments to see the current state."
return 1
;;
esac
/usr/bin/update_engine_client $param -show_p2p_update
)
cmd_rollback() (
if /usr/bin/update_engine_client --rollback; then
echo "Rollback attempt succeeded -- after a couple minutes you will" \
"get an update available and you should reboot to complete rollback."
else
echo "Rollback attempt failed. Check chrome://system for more information."
fi
)
cmd_update_over_cellular() (
case "$1" in
"enable")
param="-update_over_cellular=yes"
echo "When available, auto-updates download in the background any time " \
"the computer is powered on. Note: this may incur additional " \
"cellular charges, including roaming and/or data charges, as per " \
"your carrier arrangement."
;;
"disable")
param="-update_over_cellular=no"
;;
"")
param=""
;;
*)
echo "Usage: update_over_cellular [enable|disable]
Enables or disables the auto updates over cellular networks. Run without
arguments to see the current state."
return 1
;;
esac
/usr/bin/update_engine_client $param -show_update_over_cellular
)
cmd_upload_crashes() (
debugd UploadCrashes
echo "Check chrome://crashes for status updates"
)
cmd_upload_devcoredumps() (
case "$1" in
"enable")
debugd EnableDevCoredumpUpload
;;
"disable")
debugd DisableDevCoredumpUpload
;;
*)
echo "Usage: upload_devcoredumps [enable|disable]
Enable or disable the upload of devcoredump reports."
return 1
;;
esac
)
cmd_tpcontrol() (
echo "tpcontrol is deprecated. Please use inputcontrol instead."
)
cmd_try_touch_experiment() (
/usr/sbin/try_touch_experiment "$@"
)
cmd_inputcontrol() (
/opt/google/input/inputcontrol "$@"
)
cmd_rlz() (
local flag_file="$HOME/.rlz_disabled"
local enabled=1
local changed=0
if [ -r "${flag_file}" ]; then
enabled=0
fi
case "$1" in
"status")
if [ $enabled -eq 1 ]; then
echo "Currently enabled"
else
echo "Currently disabled"
fi
return
;;
"enable")
if [ $enabled -eq 0 ]; then
changed=1
fi
rm -f "${flag_file}"
;;
"disable")
if [ $enabled -eq 1 ]; then
changed=1
fi
touch "${flag_file}"
;;
*)
echo "Usage: rlz < status | enable | disable >"
return 1
;;
esac
if [ $changed -eq 1 ]; then
echo "You must reboot for this to take effect."
else
echo "No change."
fi
)
cmd_syslog() (
logger -t crosh -- "$*"
)
mk_fifo() {
local dir fifo
# We want C-c to terminate the running test so that the UI stays the same.
# Therefore, create a fifo to direct the output of the test to, and have a
# subshell read from the fifo and emit to stdout. When the subshell ends (at a
# C-c), we stop the test and clean up the fifo.
# no way to mktemp a fifo, so make a dir to hold it instead
dir=$(mktemp -d "/tmp/crosh-test-XXXXXXXXXX")
if [ $? -ne 0 ]; then
echo "Can't create temporary directory"
return 1
fi
fifo="${dir}/fifo"
if ! mkfifo "${fifo}"; then
echo "Can't create fifo at ${fifo}"
return 1
fi
echo "${fifo}"
}
cmd_storage_test_1() (
option="$1"
debugd Smartctl "string:abort_test" >/dev/null
test=$(debugd Smartctl "string:short_test")
if [ "$option" != "-v" ]; then
echo "$test" | sed -n '1p;2p'
echo ""
echo "$test" | grep "Please wait"
else
echo "$test"
fi
echo ""
while debugd Smartctl "string:capabilities" |
grep -q "of test remaining"; do
true
done
result=$(debugd Smartctl "string:selftest")
if [ "$option" != "-v" ]; then
echo "$result" | grep -e "Num" -e "# 1"
else
echo "$result"
fi
debugd Smartctl "string:abort_test" >/dev/null
)
cmd_storage_test_2() (
debugd_poll Badblocks "fd:1"
)
cmd_storage_status() (
echo "Removed. See storage_info section in chrome://system"
)
cmd_memory_test() (
# Getting total free memory in KB.
mem=$(cat /proc/meminfo | grep MemFree | tr -s " " | cut -d" " -f 2)
# Converting to MB.
mem=$(($mem / 1024))
# Giving OS 200MB free memory before hogging the rest of it.
mem=$(($mem - 200))
debugd_poll Memtester "fd:1" "uint32:${mem}"
)
cmd_battery_firmware() (
option="$1"
case "${option}" in
info|check)
debugd --reply-timeout=$(( 10 * 60 * 1000 )) BatteryFirmware "string:${option}"
echo ""
;;
update)
# Increased the reply-timeout to 10 min for Battery Firmware update process.
# Battery Firmware Update process time includes the following:
# 1 setup delay time before entery battery firmware update mode.
# 2 battery flash erase time.
# 3 data transfer time from AP to EC, and then to Batttery.
# 4 battery flash program/write time.
# 5 re-try time on errors.
# Note: take ~2 min on a success battery firmware update case.
echo ""
echo "================================================================================"
echo " Battery firmware update is in progress."
echo "================================================================================"
echo "Please DO NOT remove the power adapter cable, otherwise the update will fail."
echo ""
echo "To recover from a failed battery firmware update,"
echo " please plug in the power adapter cable, reboot and run this command again."
echo ""
echo "================================================================================"
echo ""
debugd --reply-timeout=$(( 10 * 60 * 1000 )) BatteryFirmware "string:${option}"
echo ""
;;
*)
echo "Unknown option: ${option}"
;;
esac
)
cmd_battery_test() (
local test_length="$1"
if [ -z "$test_length" ]; then
echo "No test length specified. Defaulting to 300 seconds."
test_length=300
fi
if ! check_digits "${test_length}"; then
echo "Invalid test length."
return 1
fi
if [ "$(get_power_status_field 'battery_present')" != '1' ]; then
echo "No battery found."
return 1
fi
if [ "$(get_power_status_field 'battery_discharging')" = '1' ]; then
local bat_status='discharging'
local bat_discharging=1
else
local bat_status='charging or full'
local bat_discharging=0
fi
local bat_pct="$(get_power_status_field 'battery_percent')"
local bat_full="$(get_power_status_field 'battery_charge_full')"
local bat_full_design="$(get_power_status_field 'battery_charge_full_design')"
local bat_health="$(echo "${bat_full}" "${bat_full_design}" | \
awk '{ printf "%.2f", 100.0 * $1 / $2 }')"
echo "Battery is ${bat_status} (${bat_pct}% left)"
echo "Battery health: ${bat_health}%"
if [ "${bat_discharging}" != '1' ]; then
echo "Please make sure the power supply is unplugged and retry the test."
return 1
fi
echo "Please wait..."
sleep "${test_length}"
local bat_after="$(get_power_status_field 'battery_percent')"
local bat_diff="$(echo "${bat_pct}" "${bat_after}" | \
awk '{ printf "%.2f", $1 - $2 }')"
echo "Battery discharged ${bat_diff}% in ${test_length} second(s)."
)
cmd_dump_emk() (
/usr/sbin/cryptohome --action=tpm_attestation_key_status \
--name=attest-ent-machine
)
cmd_tpm_status() (
/usr/sbin/cryptohome --action=tpm_more_status
)
substr() {
local str="$1"
local start="$2"
local end="$3"
if [ "$IS_BASH" = "1" ]; then
# NB: use printf to avoid echo interpreting -n
if [ -z "$end" ]; then
printf '%s\n' ${str:$start}
else
printf '%s\n' ${str:$start:$end}
fi
return
fi
start=$(expr "$start" + 1)
if [ ! -z "$end" ]; then
end=$(expr "$end" - 1)
fi
echo "$str" | cut -c${start}-${end}
}
dispatch() {
local line="$1"
local command=""
local params=""
local space_pos=$(expr index "$line" ' ')
if [ $space_pos = 0 ]; then
command=$line
else
command=$(substr "$line" "0" "$space_pos")
command=${command% *}
params=$(substr "$line" "$space_pos")
fi
if ! type "cmd_$command" 2>/dev/null | head -1 | grep -q "function"; then
echo "Unknown command: '$command'"
else
command="cmd_$command"
$command $params
fi
}
repl() {
echo "${INTRO_TEXT}"
if [ "$IS_BASH" != "1" ]; then
echo "Sorry, line editing and command history disabled due to" \
"shell limitations."
fi
# This will be set by the 'exit' command to tell us to quit.
local exit
while [ -z "${exit}" ]; do
if shell_read "crosh> " LINE_; then
if [ ! -z "$LINE_" ]; then
shell_history -s "$LINE_"
dispatch "$LINE_"
fi
else
echo
return 1
fi
done
}
main() {
load_extra_crosh "$@"
INPUTRC="/usr/share/misc/inputrc.crosh"
if [ ! -e "${INPUTRC}" ]; then
# We aren't installed; use local copy for testing.
INPUTRC="$(dirname "$0")/inputrc.crosh"
fi
HISTFILE="${HOME}/.crosh_history"
shell_history -r "${HISTFILE}"
# Initialize pseudo completion support.
if [ ${IS_BASH} -eq 1 ]; then
local f
for f in $(declare -F | sed -n '/-f cmd_/s:.*cmd_::p'); do
# Do not add duplicates to avoid ballooning history.
grep -qs "^${f}$" $HISTFILE || shell_history -s $f
done
fi
repl
shell_history -w $HISTFILE
}
main "$@"