| #!/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 "$@" |