├── .github └── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── .gitignore ├── CMakeLists.txt ├── LICENSE ├── README.md ├── scripts ├── termux-api-start.in ├── termux-api-stop.in ├── termux-audio-info.in ├── termux-battery-status.in ├── termux-brightness.in ├── termux-call-log.in ├── termux-camera-info.in ├── termux-camera-photo.in ├── termux-clipboard-get.in ├── termux-clipboard-set.in ├── termux-contact-list.in ├── termux-dialog.in ├── termux-download.in ├── termux-fingerprint.in ├── termux-infrared-frequencies.in ├── termux-infrared-transmit.in ├── termux-job-scheduler.in ├── termux-keystore.in ├── termux-location.in ├── termux-media-player.in ├── termux-media-scan.in ├── termux-microphone-record.in ├── termux-nfc.in ├── termux-notification-channel.in ├── termux-notification-list.in ├── termux-notification-remove.in ├── termux-notification.in ├── termux-saf-create.in ├── termux-saf-dirs.in ├── termux-saf-ls.in ├── termux-saf-managedir.in ├── termux-saf-mkdir.in ├── termux-saf-read.in ├── termux-saf-rm.in ├── termux-saf-stat.in ├── termux-saf-write.in ├── termux-sensor.in ├── termux-share.in ├── termux-sms-inbox.in ├── termux-sms-list.in ├── termux-sms-send.in ├── termux-speech-to-text.in ├── termux-storage-get.in ├── termux-telephony-call.in ├── termux-telephony-cellinfo.in ├── termux-telephony-deviceinfo.in ├── termux-toast.in ├── termux-torch.in ├── termux-tts-engines.in ├── termux-tts-speak.in ├── termux-usb.in ├── termux-vibrate.in ├── termux-volume.in ├── termux-wallpaper.in ├── termux-wifi-connectioninfo.in ├── termux-wifi-enable.in └── termux-wifi-scaninfo.in ├── termux-api-broadcast.c ├── termux-api.c ├── termux-api.h └── termux-callback.in /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve termux-api-package 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | 11 | 12 | **Problem description** 13 | A clear and concise description of what the problem with termux-api-package is. You may post screenshots or paste error messages in addition to description. 14 | 15 | **Steps to reproduce** 16 | Please post all steps that are needed to reproduce the issue. 17 | 18 | **Expected behavior** 19 | A clear and concise description of what you expected to happen. 20 | 21 | **Additional information** 22 | Post output of command `termux-info`. 23 | If you are rooted or have access to adb then capture a logcat with `logcat -d "*:W"`, from a adb or root shell. 24 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest a new feature in termux-api-package 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Feature description** 11 | Describe the feature and why you want it. 12 | 13 | **Background information** 14 | Have you checked if the feature is accessible through the android API? 15 | Do you know of other open-source apps that has a similar feature as the one you want? (Provide links) 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | termux-api 2 | *~ 3 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0.0) 2 | project(termux-api) 3 | include(GNUInstallDirs) 4 | 5 | set(TERMUX_PREFIX ${CMAKE_INSTALL_PREFIX}) 6 | 7 | add_library(termux-api SHARED termux-api.c) 8 | add_library(termux-api-static STATIC termux-api.c) 9 | set_target_properties(termux-api-static PROPERTIES OUTPUT_NAME termux-api) 10 | 11 | add_executable(termux-api-broadcast termux-api-broadcast.c) 12 | target_link_libraries(termux-api-broadcast termux-api-static) 13 | 14 | # TODO: get list through regex or similar 15 | set(script_files 16 | scripts/termux-api-start 17 | scripts/termux-api-stop 18 | scripts/termux-audio-info 19 | scripts/termux-battery-status 20 | scripts/termux-brightness 21 | scripts/termux-call-log 22 | scripts/termux-camera-info 23 | scripts/termux-camera-photo 24 | scripts/termux-clipboard-get 25 | scripts/termux-clipboard-set 26 | scripts/termux-contact-list 27 | scripts/termux-dialog 28 | scripts/termux-download 29 | scripts/termux-fingerprint 30 | scripts/termux-infrared-frequencies 31 | scripts/termux-infrared-transmit 32 | scripts/termux-job-scheduler 33 | scripts/termux-keystore 34 | scripts/termux-location 35 | scripts/termux-media-player 36 | scripts/termux-media-scan 37 | scripts/termux-microphone-record 38 | scripts/termux-nfc 39 | scripts/termux-notification 40 | scripts/termux-notification-channel 41 | scripts/termux-notification-list 42 | scripts/termux-notification-remove 43 | scripts/termux-saf-create 44 | scripts/termux-saf-dirs 45 | scripts/termux-saf-ls 46 | scripts/termux-saf-managedir 47 | scripts/termux-saf-mkdir 48 | scripts/termux-saf-read 49 | scripts/termux-saf-rm 50 | scripts/termux-saf-stat 51 | scripts/termux-saf-write 52 | scripts/termux-sensor 53 | scripts/termux-share 54 | scripts/termux-sms-inbox 55 | scripts/termux-sms-list 56 | scripts/termux-sms-send 57 | scripts/termux-speech-to-text 58 | scripts/termux-storage-get 59 | scripts/termux-telephony-call 60 | scripts/termux-telephony-cellinfo 61 | scripts/termux-telephony-deviceinfo 62 | scripts/termux-toast 63 | scripts/termux-torch 64 | scripts/termux-tts-engines 65 | scripts/termux-tts-speak 66 | scripts/termux-usb 67 | scripts/termux-vibrate 68 | scripts/termux-volume 69 | scripts/termux-wallpaper 70 | scripts/termux-wifi-connectioninfo 71 | scripts/termux-wifi-enable 72 | scripts/termux-wifi-scaninfo 73 | ) 74 | 75 | make_directory(scripts) 76 | foreach(file ${script_files}) 77 | configure_file( 78 | ${CMAKE_CURRENT_SOURCE_DIR}/${file}.in 79 | ${file} @ONLY 80 | ) 81 | endforeach() 82 | 83 | configure_file( 84 | ${CMAKE_CURRENT_SOURCE_DIR}/termux-callback.in 85 | termux-callback @ONLY 86 | ) 87 | 88 | install( 89 | FILES ${CMAKE_BINARY_DIR}/termux-api-broadcast 90 | DESTINATION ${CMAKE_INSTALL_PREFIX}/libexec 91 | PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE 92 | GROUP_READ GROUP_EXECUTE 93 | WORLD_READ WORLD_EXECUTE 94 | ) 95 | 96 | # Create a symlink for termux-api-broadcast->termux-api for backwards 97 | # compatibility 98 | INSTALL(CODE "execute_process( \ 99 | COMMAND ${CMAKE_COMMAND} -E create_symlink \ 100 | termux-api-broadcast \ 101 | ${CMAKE_INSTALL_PREFIX}/libexec/termux-api \ 102 | )" 103 | ) 104 | 105 | install( 106 | FILES 107 | ${CMAKE_BINARY_DIR}/libtermux-api.so 108 | ${CMAKE_BINARY_DIR}/libtermux-api.a 109 | TYPE LIB 110 | ) 111 | 112 | install( 113 | FILES ${CMAKE_CURRENT_SOURCE_DIR}/termux-api.h 114 | TYPE INCLUDE 115 | ) 116 | 117 | foreach(file ${script_files}) 118 | install( 119 | FILES ${CMAKE_BINARY_DIR}/${file} 120 | TYPE BIN 121 | PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE 122 | ) 123 | endforeach() 124 | 125 | install( 126 | FILES ${CMAKE_BINARY_DIR}/termux-callback 127 | DESTINATION ${CMAKE_INSTALL_PREFIX}/libexec 128 | PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE 129 | GROUP_READ GROUP_EXECUTE 130 | WORLD_READ WORLD_EXECUTE 131 | ) 132 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017-2021 Termux 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # termux-api-package 2 | Termux package containing scripts to call exposed API methods in the [Termux:API](https://github.com/termux/termux-api) app. 3 | -------------------------------------------------------------------------------- /scripts/termux-api-start.in: -------------------------------------------------------------------------------- 1 | #!@TERMUX_PREFIX@/bin/sh 2 | am startservice -n com.termux.api/.KeepAliveService 3 | -------------------------------------------------------------------------------- /scripts/termux-api-stop.in: -------------------------------------------------------------------------------- 1 | #!@TERMUX_PREFIX@/bin/sh 2 | am stopservice -n com.termux.api/.KeepAliveService 3 | -------------------------------------------------------------------------------- /scripts/termux-audio-info.in: -------------------------------------------------------------------------------- 1 | #!@TERMUX_PREFIX@/bin/sh 2 | set -e -u 3 | 4 | SCRIPTNAME=termux-audio-info 5 | show_usage () { 6 | echo "Usage: $SCRIPTNAME" 7 | echo "Get information about audio capabilities." 8 | exit 0 9 | } 10 | 11 | while getopts :h option 12 | do 13 | case "$option" in 14 | h) show_usage;; 15 | ?) echo "$SCRIPTNAME: illegal option -$OPTARG"; exit 1; 16 | esac 17 | done 18 | shift $((OPTIND-1)) 19 | 20 | if [ $# != 0 ]; then echo "$SCRIPTNAME: too many arguments"; exit 1; fi 21 | 22 | @TERMUX_PREFIX@/libexec/termux-api AudioInfo 23 | -------------------------------------------------------------------------------- /scripts/termux-battery-status.in: -------------------------------------------------------------------------------- 1 | #!@TERMUX_PREFIX@/bin/sh 2 | set -e -u 3 | 4 | SCRIPTNAME=termux-battery-status 5 | show_usage () { 6 | echo "Usage: $SCRIPTNAME" 7 | echo "Get the status of the device battery." 8 | exit 0 9 | } 10 | 11 | while getopts :h option 12 | do 13 | case "$option" in 14 | h) show_usage;; 15 | ?) echo "$SCRIPTNAME: illegal option -$OPTARG"; exit 1; 16 | esac 17 | done 18 | shift $((OPTIND-1)) 19 | 20 | if [ $# != 0 ]; then echo "$SCRIPTNAME: too many arguments"; exit 1; fi 21 | 22 | @TERMUX_PREFIX@/libexec/termux-api BatteryStatus 23 | -------------------------------------------------------------------------------- /scripts/termux-brightness.in: -------------------------------------------------------------------------------- 1 | #!@TERMUX_PREFIX@/bin/bash 2 | set -e -u 3 | 4 | SCRIPTNAME=termux-brightness 5 | show_usage() { 6 | echo "Usage: $SCRIPTNAME brightness" 7 | echo "Set the screen brightness between 0 and 255 or auto" 8 | exit 0 9 | } 10 | 11 | if [ $# != 1 ]; then 12 | show_usage 13 | fi 14 | 15 | if ! [[ $1 =~ ^([0-9]+)|auto$ ]]; then 16 | echo "ERROR: Arg must be a number between 0 - 255 or auto!" 17 | show_usage 18 | fi 19 | 20 | if [ "$1" == auto ]; then 21 | ARGS="--ez auto true" 22 | else 23 | ARGS="--ei brightness $1 --ez auto false" 24 | fi 25 | 26 | @TERMUX_PREFIX@/libexec/termux-api Brightness $ARGS 27 | -------------------------------------------------------------------------------- /scripts/termux-call-log.in: -------------------------------------------------------------------------------- 1 | #!@TERMUX_PREFIX@/bin/bash 2 | set -u 3 | 4 | PARAM_LIMIT_DEFAULT=10 5 | PARAM_LIMIT="$PARAM_LIMIT_DEFAULT" 6 | 7 | PARAM_OFFSET_DEFAULT=0 8 | PARAM_OFFSET="$PARAM_OFFSET_DEFAULT" 9 | 10 | PARAMS="" 11 | 12 | SCRIPTNAME=termux-call-log 13 | 14 | validate_is_postive_number() { 15 | if [[ ! "${2:-}" =~ ^[0-9]+$ ]]; then 16 | echo "ERROR: The -$1 value '${2:-}' is not a positive number." 1>&2 17 | show_usage || return $? 18 | exit 1 19 | fi 20 | } 21 | 22 | show_usage () { 23 | echo "Usage: $SCRIPTNAME [-l ] [-o ]" 24 | echo "List call log history" 25 | echo " -l limit in call log list (default: $PARAM_LIMIT_DEFAULT)" 26 | echo " -o offset in call log list (default: $PARAM_OFFSET_DEFAULT)" 27 | } 28 | 29 | while getopts :hl:o: option 30 | do 31 | case "$option" in 32 | h) show_usage; exit 0;; 33 | l) PARAM_LIMIT="$OPTARG";; 34 | o) PARAM_OFFSET="$OPTARG";; 35 | ?) echo "$SCRIPTNAME: illegal option -$OPTARG"; exit 1; 36 | esac 37 | done 38 | shift $((OPTIND-1)) 39 | 40 | validate_is_postive_number l "$PARAM_LIMIT" 41 | validate_is_postive_number o "$PARAM_OFFSET" 42 | 43 | if [ $# != 0 ]; then echo "$SCRIPTNAME: too many arguments"; exit 1; fi 44 | 45 | PARAMS="$PARAMS --ei offset $PARAM_OFFSET --ei limit $PARAM_LIMIT" 46 | @TERMUX_PREFIX@/libexec/termux-api CallLog $PARAMS 47 | -------------------------------------------------------------------------------- /scripts/termux-camera-info.in: -------------------------------------------------------------------------------- 1 | #!@TERMUX_PREFIX@/bin/sh 2 | set -e -u 3 | 4 | SCRIPTNAME=termux-camera-info 5 | show_usage () { 6 | echo "Usage: $SCRIPTNAME" 7 | echo "Get information about device camera(s)." 8 | exit 0 9 | } 10 | 11 | while getopts :h option 12 | do 13 | case "$option" in 14 | h) show_usage;; 15 | ?) echo "$SCRIPTNAME: illegal option -$OPTARG"; exit 1; 16 | esac 17 | done 18 | shift $((OPTIND-1)) 19 | 20 | if [ $# != 0 ]; then echo "$SCRIPTNAME: too many arguments"; exit 1; fi 21 | 22 | @TERMUX_PREFIX@/libexec/termux-api CameraInfo 23 | -------------------------------------------------------------------------------- /scripts/termux-camera-photo.in: -------------------------------------------------------------------------------- 1 | #!@TERMUX_PREFIX@/bin/sh 2 | set -e -u 3 | 4 | SCRIPTNAME=termux-camera-photo 5 | show_usage () { 6 | echo "Usage: termux-camera-photo [-c camera-id] output-file" 7 | echo "Take a photo and save it to a file in JPEG format." 8 | echo " -c camera-id ID of the camera to use (see termux-camera-info), default: 0" 9 | exit 0 10 | } 11 | 12 | 13 | PARAMS="" 14 | while getopts :hc: option 15 | do 16 | case "$option" in 17 | h) show_usage;; 18 | c) PARAMS="--es camera $OPTARG";; 19 | ?) echo "$SCRIPTNAME: illegal option -$OPTARG"; exit 1; 20 | esac 21 | done 22 | shift $((OPTIND-1)) 23 | 24 | if [ $# = 0 ]; then echo "$SCRIPTNAME: missing file argument"; exit 1; fi 25 | if [ $# != 1 ]; then echo "$SCRIPTNAME: too many arguments"; exit 1; fi 26 | 27 | touch "$1" 28 | PARAMS="$PARAMS --es file `realpath $1`" 29 | 30 | @TERMUX_PREFIX@/libexec/termux-api CameraPhoto $PARAMS 31 | -------------------------------------------------------------------------------- /scripts/termux-clipboard-get.in: -------------------------------------------------------------------------------- 1 | #!@TERMUX_PREFIX@/bin/sh 2 | set -e -u 3 | 4 | SCRIPTNAME=termux-clipboard-get 5 | show_usage () { 6 | echo "Usage: $SCRIPTNAME" 7 | echo "Get the system clipboard text." 8 | exit 0 9 | } 10 | 11 | while getopts :h option 12 | do 13 | case "$option" in 14 | h) show_usage;; 15 | ?) echo "$SCRIPTNAME: illegal option -$OPTARG"; exit 1; 16 | esac 17 | done 18 | shift $((OPTIND-1)) 19 | 20 | if [ $# != 0 ]; then echo "$SCRIPTNAME: too many arguments"; exit 1; fi 21 | 22 | @TERMUX_PREFIX@/libexec/termux-api Clipboard 23 | -------------------------------------------------------------------------------- /scripts/termux-clipboard-set.in: -------------------------------------------------------------------------------- 1 | #!@TERMUX_PREFIX@/bin/sh 2 | set -e -u 3 | 4 | SCRIPTNAME=termux-clipboard-set 5 | show_usage () { 6 | echo "Usage: $SCRIPTNAME [text]" 7 | echo "Set the system clipboard text. The text to set is either supplied as arguments or read from stdin if no arguments are given." 8 | exit 0 9 | } 10 | 11 | while getopts :h option 12 | do 13 | case "$option" in 14 | h) show_usage;; 15 | ?) echo "$SCRIPTNAME: illegal option -$OPTARG"; exit 1; 16 | esac 17 | done 18 | shift $((OPTIND-1)) 19 | 20 | CMD="@TERMUX_PREFIX@/libexec/termux-api Clipboard -e api_version 2 --ez set true" 21 | if [ $# = 0 ]; then 22 | $CMD 23 | else 24 | echo -n "$@" | $CMD 25 | fi 26 | 27 | -------------------------------------------------------------------------------- /scripts/termux-contact-list.in: -------------------------------------------------------------------------------- 1 | #!@TERMUX_PREFIX@/bin/sh 2 | set -e -u 3 | 4 | SCRIPTNAME=termux-contact-list 5 | show_usage () { 6 | echo "Usage: $SCRIPTNAME" 7 | echo "List all contacts." 8 | exit 0 9 | } 10 | 11 | while getopts :h option 12 | do 13 | case "$option" in 14 | h) show_usage;; 15 | ?) echo "$SCRIPTNAME: illegal option -$OPTARG"; exit 1; 16 | esac 17 | done 18 | shift $((OPTIND-1)) 19 | 20 | if [ $# != 0 ]; then echo "$SCRIPTNAME: too many arguments"; exit 1; fi 21 | 22 | @TERMUX_PREFIX@/libexec/termux-api ContactList 23 | -------------------------------------------------------------------------------- /scripts/termux-dialog.in: -------------------------------------------------------------------------------- 1 | #!@TERMUX_PREFIX@/bin/bash 2 | set -e -u 3 | 4 | DEFAULT_WIDGET="text" 5 | 6 | SCRIPTNAME=termux-dialog 7 | show_usage() { 8 | echo "Usage: $SCRIPTNAME widget [options]" 9 | echo "Get user input w/ different widgets! Default: $DEFAULT_WIDGET" 10 | echo " -h, help Show this help" 11 | echo " -l, list List all widgets and their options" 12 | echo " -t, title Set title of input dialog (optional)" 13 | exit 0 14 | } 15 | 16 | declare -a widgets=("confirm" "checkbox" "counter" "date" "radio" "sheet" "spinner" "speech" "text" "time") 17 | 18 | # Descriptions for various options that multiple widgets can use 19 | OPT_HINT_DESC="[-i hint] text hint (optional)" 20 | OPT_MULTI_LINE_DESC="[-m] multiple lines instead of single (optional)" 21 | OPT_PASS_DESC="[-p] enter input as password (optional)" 22 | OPT_NUMERIC_DESC="[-n] enter input as numbers (optional)" 23 | OPT_TITLE_DESC="[-t title] set title of dialog (optional)" 24 | OPT_RANGE_DESC="[-r min,max,start] comma delim of (3) numbers to use (optional)" 25 | OPT_VALUES_DESC="[-v \",,,\"] comma delim values to use (required)" 26 | OPT_DATEFORMAT_DESC="[-d \"dd-MM-yyyy k:m:s\"] SimpleDateFormat Pattern for date widget output (optional)" 27 | 28 | # Widget hints 29 | ARG_I="" 30 | OPT_I="" 31 | 32 | # Text widget multiline 33 | ARG_M="" 34 | OPT_M="" 35 | 36 | # Text widget numeric 37 | ARG_N="" 38 | OPT_N="" 39 | 40 | # Counter range 41 | ARG_R="" 42 | OPT_R="" 43 | 44 | # Text widget input as password 45 | ARG_P="" 46 | OPT_P="" 47 | 48 | # Dialog title (supported by all widgets) 49 | ARG_T="" 50 | OPT_T="" 51 | 52 | # Values for list-type widgets 53 | OPT_V="" 54 | ARG_V="" 55 | 56 | # Date output format (supported by date widget) 57 | ARG_D="" 58 | OPT_D="" 59 | 60 | # Widget type 61 | ARG_W="" 62 | WIDGET="" 63 | 64 | # Flags for detecting invalid option combinations 65 | HINT_FLAG=1 66 | MULTI_LINE_FLAG=2 67 | PASS_FLAG=4 68 | RANGE_FLAG=8 69 | VALUES_FLAG=16 70 | NUM_FLAG=32 71 | 72 | FLAGS=0 73 | 74 | 75 | # Show usage help for specific widget 76 | widget_usage () { 77 | echo -n -e "$1 - " 78 | 79 | case "$1" in 80 | "confirm") 81 | echo "Show confirmation dialog" 82 | echo " $OPT_HINT_DESC" 83 | echo " $OPT_TITLE_DESC" 84 | ;; 85 | "checkbox") 86 | echo "Select multiple values using checkboxes" 87 | echo " $OPT_VALUES_DESC" 88 | echo " $OPT_TITLE_DESC" 89 | ;; 90 | "counter") 91 | echo "Pick a number in specified range" 92 | echo " $OPT_RANGE_DESC" 93 | echo " $OPT_TITLE_DESC" 94 | ;; 95 | "date") 96 | echo "Pick a date" 97 | echo " $OPT_TITLE_DESC" 98 | echo " $OPT_DATEFORMAT_DESC" 99 | ;; 100 | "radio") 101 | echo "Pick a single value from radio buttons" 102 | echo " $OPT_VALUES_DESC" 103 | echo " $OPT_TITLE_DESC" 104 | ;; 105 | "sheet") 106 | echo "Pick a value from sliding bottom sheet" 107 | echo " $OPT_VALUES_DESC" 108 | echo " $OPT_TITLE_DESC" 109 | ;; 110 | "speech") 111 | echo "Obtain speech using device microphone" 112 | echo " $OPT_HINT_DESC" 113 | echo " $OPT_TITLE_DESC" 114 | ;; 115 | "spinner") 116 | echo "Pick a single value from a dropdown spinner" 117 | echo " $OPT_VALUES_DESC" 118 | echo " $OPT_TITLE_DESC" 119 | ;; 120 | "text") 121 | echo "Input text (default if no widget specified)" 122 | echo " $OPT_HINT_DESC" 123 | echo " $OPT_MULTI_LINE_DESC*" 124 | echo " $OPT_NUMERIC_DESC*" 125 | echo " $OPT_PASS_DESC" 126 | echo " $OPT_TITLE_DESC" 127 | echo " * cannot use [-m] with [-n]" 128 | ;; 129 | "time") 130 | echo "Pick a time value" 131 | echo " $OPT_TITLE_DESC" 132 | ;; 133 | *) 134 | echo "\tUnknown usage for '$1'" 135 | ;; 136 | esac 137 | } 138 | 139 | # List all widgets 140 | list_widgets() { 141 | echo "Supported widgets:" 142 | echo 143 | 144 | for w in "${widgets[@]}"; do 145 | widget_usage "$w" 146 | echo 147 | done 148 | } 149 | 150 | # Checks to see if widgets array contains specified widget 151 | has_widget () { 152 | for w in "${widgets[@]}"; do 153 | [ "$w" == "$1" ] && return 0 154 | done 155 | return 1 156 | } 157 | 158 | set_flag () { 159 | FLAGS=$((FLAGS | $1)); 160 | } 161 | 162 | # Convenience method to get all supported options, regardless of specified widget 163 | # NOTE: Option combination validation doesn't occur here 164 | parse_options() { 165 | while getopts :hlmnpr:i:t:d:v: option 166 | do 167 | case "$option" in 168 | h) show_usage ;; 169 | l) list_widgets; exit 0;; 170 | i) ARG_I="--es input_hint"; OPT_I="$OPTARG"; set_flag $HINT_FLAG; ;; 171 | m) ARG_M="--ez multiple_lines"; OPT_M="true"; set_flag $MULTI_LINE_FLAG; ;; 172 | p) ARG_P="--ez password"; OPT_P="true"; set_flag $PASS_FLAG; ;; 173 | n) ARG_N="--ez numeric"; OPT_N="true"; set_flag $NUM_FLAG; ;; 174 | t) ARG_T="--es input_title"; OPT_T="$OPTARG" ;; 175 | d) ARG_D="--es date_format"; OPT_D="$OPTARG";; 176 | v) ARG_V="--es input_values"; OPT_V="$OPTARG"; set_flag $VALUES_FLAG; ;; 177 | r) ARG_R="--eia input_range"; OPT_R=$OPTARG; set_flag $RANGE_FLAG; ;; 178 | ?) echo "$SCRIPTNAME: illegal option -$OPTARG"; exit 1; 179 | esac 180 | done 181 | } 182 | 183 | options_error () { 184 | echo -e "ERROR: Invalid option(s) detected for '$1'\n" 185 | echo "Usage '$1'" 186 | widget_usage "$1" 187 | exit 1 188 | } 189 | 190 | if [ $# -eq 0 ]; then 191 | WIDGET=$DEFAULT_WIDGET 192 | # First argument wasn't a widget 193 | elif ! has_widget "$1"; then 194 | # we didn't receive a widget as an argument, check to see if we 195 | # at least options (even if they're illegal) 196 | if ! [[ $1 =~ -[a-z] ]]; then 197 | echo -e "ERROR: Illegal argument $1\n" 198 | show_usage 199 | fi 200 | WIDGET="$DEFAULT_WIDGET" 201 | else 202 | WIDGET="$1" 203 | shift 204 | fi 205 | 206 | parse_options "$@" 207 | shift $((OPTIND - 1)) 208 | 209 | # Ensure proper option combinations for the specific type of widget 210 | case "$WIDGET" in 211 | # Text (default) if no widget specified 212 | "text") 213 | if [ $((FLAGS & (RANGE_FLAG | VALUES_FLAG))) -ne 0 ]; then 214 | options_error "$WIDGET" 215 | fi 216 | 217 | if [ $((FLAGS & MULTI_LINE_FLAG)) -ne 0 ] && [ $((FLAGS & NUM_FLAG)) -ne 0 ]; then 218 | options_error "$WIDGET" 219 | fi 220 | ;; 221 | 222 | "confirm") 223 | if [ $((FLAGS & (MULTI_LINE_FLAG | PASS_FLAG | RANGE_FLAG | VALUES_FLAG | NUM_FLAG))) -ne 0 ]; then 224 | options_error "$WIDGET" 225 | fi 226 | ;; 227 | 228 | "counter") 229 | if [ $((FLAGS & (MULTI_LINE_FLAG | PASS_FLAG | VALUES_FLAG | NUM_FLAG))) -ne 0 ]; then 230 | options_error "$WIDGET" 231 | fi 232 | ;; 233 | 234 | "speech") 235 | if [ $((FLAGS & (MULTI_LINE_FLAG | PASS_FLAG | RANGE_FLAG | VALUES_FLAG | NUM_FLAG))) -ne 0 ]; then 236 | options_error "$WIDGET" 237 | fi 238 | ;; 239 | 240 | "date" | "time") 241 | if [ $((FLAGS & (HINT_FLAG | MULTI_LINE_FLAG | PASS_FLAG | RANGE_FLAG | VALUES_FLAG | NUM_FLAG))) -ne 0 ]; then 242 | options_error "$WIDGET" 243 | fi 244 | ;; 245 | 246 | "checkbox" | "radio" | "sheet" | "spinner") 247 | if [ "$ARG_V" == "" ]; then 248 | echo "ERROR: '$WIDGET' must be called with $OPT_VALUES_DESC" 249 | exit 1 250 | fi 251 | 252 | if [ $((FLAGS & (HINT_FLAG | MULTI_LINE_FLAG | PASS_FLAG | RANGE_FLAG | NUM_FLAG))) -ne 0 ]; then 253 | options_error "$WIDGET" 254 | fi 255 | ;; 256 | 257 | *) 258 | echo "$SCRIPTNAME: unsupported widget '$WIDGET'"; show_usage ;; 259 | esac 260 | 261 | # All valid args should be consumed by this point 262 | if [ $# -gt 0 ]; then 263 | echo "ERROR: Too many arguments!" 264 | show_usage 265 | fi 266 | 267 | ARG_W="--es input_method" 268 | 269 | # Set options, ensuring whitespace isn't lost 270 | if [ -n "$ARG_W" ]; then set -- "$@" $ARG_W "$WIDGET"; fi 271 | if [ -n "$ARG_I" ]; then set -- "$@" $ARG_I "$OPT_I"; fi 272 | if [ -n "$ARG_T" ]; then set -- "$@" $ARG_T "$OPT_T"; fi 273 | if [ -n "$ARG_R" ]; then set -- "$@" $ARG_R "$OPT_R"; fi 274 | if [ -n "$ARG_V" ]; then set -- "$@" $ARG_V "$OPT_V"; fi 275 | if [ -n "$ARG_M" ]; then set -- "$@" $ARG_M "$OPT_M"; fi 276 | if [ -n "$ARG_P" ]; then set -- "$@" $ARG_P "$OPT_P"; fi 277 | if [ -n "$ARG_N" ]; then set -- "$@" $ARG_N "$OPT_N"; fi 278 | if [ -n "$ARG_D" ]; then set -- "$@" $ARG_D "$OPT_D"; fi 279 | 280 | @TERMUX_PREFIX@/libexec/termux-api Dialog "$@" 281 | -------------------------------------------------------------------------------- /scripts/termux-download.in: -------------------------------------------------------------------------------- 1 | #!@TERMUX_PREFIX@/bin/sh 2 | set -e -u 3 | 4 | SCRIPTNAME=termux-download 5 | show_usage () { 6 | echo "Usage: $SCRIPTNAME [-d description] [-t title] url-to-download" 7 | echo "Download a resource using the system download manager." 8 | echo " -d description description for the download request notification" 9 | echo " -t title title for the download request notification" 10 | echo " -p path full path to which the file should be downloaded" 11 | exit 0 12 | } 13 | 14 | ARG_D="" 15 | OPT_D="" 16 | ARG_T="" 17 | OPT_T="" 18 | ARG_P="" 19 | OPT_P="" 20 | 21 | while getopts :hd:t:p: option 22 | do 23 | case "$option" in 24 | h) show_usage;; 25 | d) ARG_D="--es description"; OPT_D="$OPTARG";; 26 | t) ARG_T="--es title"; OPT_T="$OPTARG";; 27 | p) ARG_P="--es path"; OPT_P="$OPTARG";; 28 | ?) echo "$SCRIPTNAME: illegal option -$OPTARG"; exit 1; 29 | esac 30 | done 31 | shift $((OPTIND-1)) 32 | 33 | if [ $# -lt 1 ]; then echo "$SCRIPTNAME: no url specified"; exit 1; fi 34 | if [ $# -gt 1 ]; then echo "$SCRIPTNAME: too many arguments"; exit 1; fi 35 | 36 | URL_TO_DOWNLOAD="$1" 37 | 38 | set -- 39 | if [ -n "$ARG_D" ]; then set -- "$@" $ARG_D "$OPT_D"; fi 40 | if [ -n "$ARG_T" ]; then set -- "$@" $ARG_T "$OPT_T"; fi 41 | if [ -n "$ARG_P" ]; then set -- "$@" $ARG_P "$OPT_P"; fi 42 | set -- "$@" "$URL_TO_DOWNLOAD" 43 | 44 | @TERMUX_PREFIX@/libexec/termux-api Download "$@" 45 | -------------------------------------------------------------------------------- /scripts/termux-fingerprint.in: -------------------------------------------------------------------------------- 1 | #!@TERMUX_PREFIX@/bin/sh 2 | set -e -u 3 | 4 | SCRIPTNAME=termux-fingerprint 5 | show_usage () { 6 | echo "Usage: $SCRIPTNAME [-t title] [-d description] [-s subtitle] [-c cancel]" 7 | echo "Use fingerprint sensor on device to check for authentication" 8 | echo "NOTE: Only available on Marshmallow and later" 9 | exit 0 10 | } 11 | 12 | ARG_T="" 13 | OPT_T="" 14 | ARG_D="" 15 | OPT_D="" 16 | ARG_S="" 17 | OPT_S="" 18 | ARG_C="" 19 | OPT_C="" 20 | 21 | while getopts :ht:d:s:c: option 22 | do 23 | case "$option" in 24 | h) show_usage;; 25 | t) ARG_T="--es title";OPT_T="$OPTARG";; 26 | d) ARG_D="--es description";OPT_D="$OPTARG";; 27 | s) ARG_S="--es subtitle";OPT_S="$OPTARG";; 28 | c) ARG_C="--es cancel";OPT_C="$OPTARG";; 29 | ?) echo "$SCRIPTNAME: illegal option -$OPTARG"; exit 1; 30 | esac 31 | done 32 | 33 | set -- 34 | if [ -n "$ARG_T" ]; then set -- "$@" $ARG_T "$OPT_T"; fi 35 | if [ -n "$ARG_D" ]; then set -- "$@" $ARG_D "$OPT_D"; fi 36 | if [ -n "$ARG_S" ]; then set -- "$@" $ARG_S "$OPT_S"; fi 37 | if [ -n "$ARG_C" ]; then set -- "$@" $ARG_C "$OPT_C"; fi 38 | 39 | @TERMUX_PREFIX@/libexec/termux-api Fingerprint "$@" 40 | -------------------------------------------------------------------------------- /scripts/termux-infrared-frequencies.in: -------------------------------------------------------------------------------- 1 | #!@TERMUX_PREFIX@/bin/sh 2 | set -e -u 3 | 4 | SCRIPTNAME=termux-infrared-frequencies 5 | show_usage () { 6 | echo "Usage: $SCRIPTNAME" 7 | echo "Query the infrared transmitter's supported carrier frequencies." 8 | exit 0 9 | } 10 | 11 | while getopts :h option 12 | do 13 | case "$option" in 14 | h) show_usage;; 15 | ?) echo "$SCRIPTNAME: illegal option -$OPTARG"; exit 1; 16 | esac 17 | done 18 | shift $((OPTIND-1)) 19 | 20 | if [ $# != 0 ]; then echo "$SCRIPTNAME: too many arguments"; exit 1; fi 21 | 22 | @TERMUX_PREFIX@/libexec/termux-api InfraredFrequencies 23 | -------------------------------------------------------------------------------- /scripts/termux-infrared-transmit.in: -------------------------------------------------------------------------------- 1 | #!@TERMUX_PREFIX@/bin/sh 2 | set -e -u 3 | 4 | SCRIPTNAME=termux-infrared-transmit 5 | show_usage () { 6 | echo "Usage: $SCRIPTNAME -f frequency pattern" 7 | echo "Transmit an infrared pattern. The pattern is specified in comma-separated on/off intervals, such as '20,50,20,30'. Only patterns shorter than 2 seconds will be transmitted." 8 | echo " -f frequency IR carrier frequency in Hertz" 9 | exit 0 10 | } 11 | 12 | FREQUENCY="" 13 | while getopts :hf: option 14 | do 15 | case "$option" in 16 | h) show_usage;; 17 | f) FREQUENCY="--ei frequency $OPTARG";; 18 | ?) echo "$SCRIPTNAME: illegal option -$OPTARG"; exit 1; 19 | esac 20 | done 21 | shift $((OPTIND-1)) 22 | 23 | if [ -z "$FREQUENCY" ]; then echo "$SCRIPTNAME: No frequency specified"; exit 1; fi 24 | 25 | if [ $# -lt 1 ]; then echo "$SCRIPTNAME: too few arguments"; exit 1; fi 26 | if [ $# -gt 1 ]; then echo "$SCRIPTNAME: too many arguments"; exit 1; fi 27 | 28 | @TERMUX_PREFIX@/libexec/termux-api InfraredTransmit $FREQUENCY --eia pattern $1 29 | -------------------------------------------------------------------------------- /scripts/termux-job-scheduler.in: -------------------------------------------------------------------------------- 1 | #!@TERMUX_PREFIX@/bin/bash 2 | set -e -u -f 3 | 4 | SCRIPTNAME=termux-job-scheduler 5 | 6 | show_usage () { 7 | echo "Usage: termux-job-scheduler [options]" 8 | echo "Schedule a script to run at specified intervals." 9 | echo " -p/--pending list pending jobs and exit" 10 | echo " --cancel-all cancel all pending jobs and exit" 11 | echo " --cancel cancel given job-id and exit" 12 | echo "Options for scheduling:" 13 | echo " -s/--script path path to the script to be called" 14 | echo " --job-id int job id (will overwrite any previous job with the same id)" 15 | echo " --period-ms int schedule job approximately every period-ms milliseconds (default 0 means once)." 16 | echo " Note that since Android N, the minimum period is 900,000ms (15 minutes)." 17 | echo " --network text run only when this type of network available (default any): any|unmetered|cellular|not_roaming|none" 18 | echo " --battery-not-low boolean run only when battery is not low, default true (at least Android O)" 19 | echo " --storage-not-low boolean run only when storage is not low, default false (at least Android O)" 20 | echo " --charging boolean run only when charging, default false" 21 | echo " --persisted boolean should the job survive reboots, default false" 22 | echo " --trigger-content-uri text (at least Android N)" 23 | echo " --trigger-content-flag int default 1, (at least Android N)" 24 | exit 0 25 | } 26 | 27 | OPT_SCRIPT="" 28 | OPT_JOB_ID="" 29 | OPT_PENDING="" 30 | OPT_CANCEL="" 31 | OPT_CANCEL_ALL="" 32 | 33 | OPT_PERIOD_MS="" 34 | OPT_NETWORK="" 35 | OPT_BATTERY_NOT_LOW="" 36 | OPT_STORAGE_NOT_LOW="" 37 | OPT_CHARGING="" 38 | OPT_PERSISTED="" 39 | OPT_TRIGGER_CONTENT_URI="" 40 | OPT_TRIGGER_CONTENT_FLAG="" 41 | 42 | TEMP=`getopt \ 43 | -n $SCRIPTNAME \ 44 | -o hs:p \ 45 | --long script:,\ 46 | job-id:,pending,\ 47 | cancel,cancel-all,\ 48 | period-ms:,network:,\ 49 | battery-not-low:,storage-not-low:,\ 50 | charging:,persisted:,help,\ 51 | trigger-content-flag:,trigger-content-uri: \ 52 | -s bash \ 53 | -- "$@"` 54 | eval set -- "$TEMP" 55 | 56 | while true; do 57 | case "$1" in 58 | -s | --script) OPT_SCRIPT="$2"; shift 2;; 59 | --job-id) OPT_JOB_ID="$2"; shift 2;; 60 | -p | --pending) OPT_PENDING=1; shift;; 61 | --cancel) OPT_CANCEL=1; shift;; 62 | --cancel-all) OPT_CANCEL_ALL=1; shift;; 63 | --period-ms) OPT_PERIOD_MS="$2"; shift 2;; 64 | --network) OPT_NETWORK="$2"; shift 2;; 65 | --battery-not-low) OPT_BATTERY_NOT_LOW="$2"; shift 2;; 66 | --storage-not-low) OPT_STORAGE_NOT_LOW="$2"; shift 2;; 67 | --charging) OPT_CHARGING="$2"; shift 2;; 68 | --persisted) OPT_PERSISTED="$2"; shift 2;; 69 | --trigger-content-flag) OPT_TRIGGER_CONTENT_FLAG="$2"; shift 2;; 70 | --trigger-content-uri) OPT_TRIGGER_CONTENT_URI="$2"; shift 2;; 71 | -h | --help) show_usage;; 72 | --) shift; break ;; 73 | esac 74 | done 75 | 76 | if [ $# != 0 ]; then echo "$SCRIPTNAME: too many arguments"; exit 1; fi 77 | 78 | set -- 79 | if [ -n "$OPT_SCRIPT" ]; then set -- "$@" --es script "$OPT_SCRIPT"; fi 80 | if [ -n "$OPT_JOB_ID" ]; then set -- "$@" --ei job_id "$OPT_JOB_ID"; fi 81 | if [ -n "$OPT_PENDING" ]; then set -- "$@" --ez pending "$OPT_PENDING"; fi 82 | if [ -n "$OPT_CANCEL" ]; then set -- "$@" --ez cancel "$OPT_CANCEL"; fi 83 | if [ -n "$OPT_CANCEL_ALL" ]; then set -- "$@" --ez cancel_all "$OPT_CANCEL_ALL"; fi 84 | if [ -n "$OPT_PERIOD_MS" ]; then set -- "$@" --ei period_ms "$OPT_PERIOD_MS"; fi 85 | if [ -n "$OPT_NETWORK" ]; then set -- "$@" --es network "$OPT_NETWORK"; fi 86 | if [ -n "$OPT_BATTERY_NOT_LOW" ]; then set -- "$@" --ez battery_not_low "$OPT_BATTERY_NOT_LOW"; fi 87 | if [ -n "$OPT_STORAGE_NOT_LOW" ]; then set -- "$@" --ez storage_not_low "$OPT_STORAGE_NOT_LOW"; fi 88 | if [ -n "$OPT_CHARGING" ]; then set -- "$@" --ez charging "$OPT_CHARGING"; fi 89 | if [ -n "$OPT_PERSISTED" ]; then set -- "$@" --ez persisted "$OPT_PERSISTED"; fi 90 | if [ -n "$OPT_TRIGGER_CONTENT_URI" ]; then set -- "$@" --es trigger_content_uri "$OPT_TRIGGER_CONTENT_URI"; fi 91 | if [ -n "$OPT_TRIGGER_CONTENT_FLAG" ]; then set -- "$@" --ez trigger_content_flag "$OPT_TRIGGER_CONTENT_FLAG"; fi 92 | 93 | @TERMUX_PREFIX@/libexec/termux-api JobScheduler "$@" 94 | -------------------------------------------------------------------------------- /scripts/termux-keystore.in: -------------------------------------------------------------------------------- 1 | #!@TERMUX_PREFIX@/bin/sh 2 | set -e -u 3 | 4 | readonly CMD_BASE="@TERMUX_PREFIX@/libexec/termux-api Keystore" 5 | 6 | SCRIPTNAME=termux-keystore 7 | show_usage () { 8 | echo "Usage: $SCRIPTNAME command" 9 | echo "These commands are supported:" 10 | echo " list [-d]" 11 | echo " delete " 12 | echo " generate [-a alg] [-s size] [-u validity]" 13 | echo " sign " 14 | echo " verify " 15 | echo 16 | echo "list: List the keys stored inside the keystore." 17 | echo " -d Detailed results (includes key parameters)." 18 | echo 19 | echo "delete: Permanently delete a given key from the keystore." 20 | echo " alias Alias of the key to delete." 21 | echo 22 | echo "generate: Create a new key inside the hardware keystore." 23 | echo " alias Alias of the key." 24 | echo " -a alg Algorithm to use (either 'RSA' or 'EC'). Defaults to RSA." 25 | echo " -s size Key size to use. For RSA, the options are 2048, 3072" 26 | echo " and 4096. For EC, the options are 256, 384 and 521." 27 | echo " -u validity User validity duration in seconds. Omit to disable." 28 | echo " When enabled, the key can only be used for the" 29 | echo " duration specified after the device unlocks. After" 30 | echo " the duration has passed, the user needs to re-lock" 31 | echo " and unlock the device again to be able to use this key." 32 | echo 33 | echo "sign: Sign using the given key, the data is read from stdin and the" 34 | echo "signature is output to stdout." 35 | echo " alias Alias of the key to use for signing." 36 | echo " algorithm Algorithm to use, e.g. 'SHA256withRSA'. This should" 37 | echo " match the algorithm of the key." 38 | echo 39 | echo "verify: Verify a signature. The data (original file) is read from stdin." 40 | echo " alias Alias of the key to use for verify." 41 | echo " algorithm Algorithm that was used to sign this data." 42 | echo " signature Signature file to use in verification." 43 | } 44 | 45 | 46 | check_args () { 47 | if [ "$2" != "$3" ]; then 48 | echo "$SCRIPTNAME: $1 needs exactly $2 arguments" 49 | exit 1 50 | fi 51 | } 52 | 53 | list_keys () { 54 | if [ "$#" -gt 0 ] && [ "$1" = "-d" ]; then 55 | $CMD_BASE -e command list --ez detailed true 56 | else 57 | $CMD_BASE -e command list 58 | fi 59 | } 60 | 61 | delete_key () { 62 | check_args delete 1 $# 63 | $CMD_BASE -e command delete -e alias "$1" 64 | } 65 | 66 | sign_data () { 67 | check_args sign 2 $# 68 | $CMD_BASE -e command sign -e alias "$1" -e algorithm "$2" | base64 -d 69 | } 70 | 71 | verify_data () { 72 | check_args verify 3 $# 73 | $CMD_BASE -e command verify -e alias "$1" -e algorithm "$2" \ 74 | -e signature "$(realpath "$3")" 75 | } 76 | 77 | generate_key () { 78 | if [ $# -lt 1 ]; then 79 | echo "$SCRIPTNAME generate: alias argument is required" 80 | exit 1 81 | fi 82 | ALIAS=$1; shift 83 | ALGORITHM=RSA; SIZE=-1; CURVE=secp256r1; VALIDITY=0 84 | while getopts a:s:c:u: NAME; do 85 | case "$NAME" in 86 | a) ALGORITHM=$OPTARG ;; 87 | s) SIZE=$OPTARG ;; 88 | u) VALIDITY=$OPTARG ;; 89 | ?) ;; 90 | esac 91 | done 92 | 93 | if [ "$ALGORITHM" = "RSA" ]; then 94 | case "$SIZE" in 95 | -1) SIZE=2048 ;; 96 | 2048|3072|4096) ;; 97 | *) echo "$SCRIPTNAME: invalid RSA key size $SIZE"; exit 1 ;; 98 | esac 99 | elif [ "$ALGORITHM" = "EC" ]; then 100 | case "$SIZE" in 101 | -1|256) CURVE=secp256r1 ;; 102 | 384) CURVE=secp384r1 ;; 103 | 521) CURVE=secp521r1 ;; 104 | *) echo "$SCRIPTNAME: invalid EC key size $SIZE"; exit 1 ;; 105 | esac 106 | else 107 | echo "$SCRIPTNAME: invalid algorithm $ALGORITHM"; exit 1 108 | fi 109 | 110 | # purpose 12 is SIGN+VERIFY 111 | $CMD_BASE -e command generate -e alias "$ALIAS" -e algorithm "$ALGORITHM" \ 112 | --ei purposes 12 --esa digests NONE,SHA-1,SHA-256,SHA-384,SHA-512 \ 113 | --ei size "$SIZE" -e curve "$CURVE" --ei validity "$VALIDITY" 114 | } 115 | 116 | ACTION="${1-}" 117 | if [ "$#" -gt 0 ]; then shift; fi 118 | 119 | case "$ACTION" in 120 | list) list_keys "$@" ;; 121 | generate) generate_key "$@" ;; 122 | delete) delete_key "$@" ;; 123 | sign) sign_data "$@" ;; 124 | verify) verify_data "$@" ;; 125 | *) show_usage ;; 126 | esac 127 | -------------------------------------------------------------------------------- /scripts/termux-location.in: -------------------------------------------------------------------------------- 1 | #!@TERMUX_PREFIX@/bin/sh 2 | set -e -u 3 | 4 | SCRIPTNAME=termux-location 5 | show_usage () { 6 | echo "usage: $SCRIPTNAME [-p provider] [-r request]" 7 | echo "Get the device location." 8 | echo " -p provider location provider [gps/network/passive] (default: gps)" 9 | echo " -r request kind of request to make [once/last/updates] (default: once)" 10 | exit 0 11 | } 12 | 13 | validate_provider () { 14 | PROVIDER=$1 15 | case "$PROVIDER" in 16 | gps) ;; 17 | network) ;; 18 | passive) ;; 19 | *) echo "$SCRIPTNAME: Unsupported provider: '$PROVIDER'"; exit 1;; 20 | esac 21 | } 22 | 23 | validate_request () { 24 | REQUEST=$1 25 | case "$REQUEST" in 26 | once) ;; 27 | last) ;; 28 | updates) ;; 29 | *) echo "$SCRIPTNAME: Unsupported request: '$REQUEST'"; exit 1;; 30 | esac 31 | } 32 | 33 | PARAMS="" 34 | 35 | while getopts :hr:p: option 36 | do 37 | case "$option" in 38 | h) show_usage;; 39 | r) validate_request "$OPTARG"; PARAMS="$PARAMS --es request $OPTARG";; 40 | p) validate_provider "$OPTARG"; PARAMS="$PARAMS --es provider $OPTARG";; 41 | ?) echo "$SCRIPTNAME: illegal option -$OPTARG"; exit 1; 42 | esac 43 | done 44 | shift $((OPTIND-1)) 45 | 46 | if [ $# != 0 ]; then echo "$SCRIPTNAME: too many arguments"; exit 1; fi 47 | 48 | @TERMUX_PREFIX@/libexec/termux-api Location $PARAMS 49 | -------------------------------------------------------------------------------- /scripts/termux-media-player.in: -------------------------------------------------------------------------------- 1 | #!@TERMUX_PREFIX@/bin/bash 2 | set -e 3 | 4 | SCRIPTNAME=termux-media-player 5 | 6 | show_usage () { 7 | echo "Usage: $SCRIPTNAME cmd [args]" 8 | echo 9 | echo "help Shows this help" 10 | echo "info Displays current playback information" 11 | echo "play Resumes playback if paused" 12 | echo "play Plays specified media file" 13 | echo "pause Pauses playback" 14 | echo "stop Quits playback" 15 | } 16 | 17 | main() { 18 | @TERMUX_PREFIX@/libexec/termux-api MediaPlayer "$@" 19 | } 20 | 21 | case "$1" in 22 | "play" ) 23 | if [ $# -gt 2 ]; then 24 | echo "Error! $SCRIPTNAME can only play one file at a time!" 25 | exit 1 26 | elif [ $# -gt 1 ]; then 27 | if [ ! -f "$2" ]; then 28 | echo "Error: '$2' is not a file!" 29 | exit 1 30 | else 31 | main -a play --es file "$(realpath "$2")" 32 | fi 33 | else 34 | main -a resume 35 | fi 36 | ;; 37 | "info" | "pause" | "stop" ) 38 | if [ $# -gt 1 ]; then 39 | echo "Error! '$1' takes no arguments!" 40 | exit 1 41 | else 42 | main -a "$1" 43 | fi 44 | ;; 45 | "help" | "" ) 46 | show_usage 47 | ;; 48 | * ) 49 | echo "$SCRIPTNAME: Invalid cmd: '$1'" 50 | show_usage 51 | exit 1 52 | ;; 53 | esac 54 | -------------------------------------------------------------------------------- /scripts/termux-media-scan.in: -------------------------------------------------------------------------------- 1 | #!@TERMUX_PREFIX@/bin/bash 2 | set -e -u 3 | 4 | SCRIPTNAME=termux-media-scan 5 | show_usage () { 6 | echo "Usage: $SCRIPTNAME [-v] [-r] file [file...]" 7 | echo "Scan the specified file(s) and add it to the media content provider." 8 | echo " -r scan directories recursively" 9 | echo " -v verbose mode" 10 | exit 0 11 | } 12 | 13 | get_paths() { 14 | for ARG in "$@"; do 15 | if [[ -e "$ARG" ]]; then 16 | realpath "$ARG" 17 | else 18 | if [[ "$ARG" =~ ^/ ]]; then 19 | echo "$ARG" 20 | else 21 | echo "$(pwd)/$ARG" 22 | fi 23 | fi 24 | done 25 | } 26 | 27 | PARAMS="--esa paths" 28 | while getopts :hrv option 29 | do 30 | case "$option" in 31 | h) show_usage;; 32 | r) PARAMS="--ez recursive true $PARAMS";; 33 | v) PARAMS="--ez verbose true $PARAMS";; 34 | ?) echo "$SCRIPTNAME: illegal option -$OPTARG"; exit 1; 35 | esac 36 | done 37 | shift $((OPTIND-1)) 38 | 39 | if [ $# = 0 ]; then echo "$SCRIPTNAME: missing file argument"; exit 1; fi 40 | 41 | PATHS=`get_paths "$@" | sed ':a;N;$!ba;s/,/\\\\,/g;s/\n/,/g'` 42 | @TERMUX_PREFIX@/libexec/termux-api MediaScanner $PARAMS "$PATHS" 43 | -------------------------------------------------------------------------------- /scripts/termux-microphone-record.in: -------------------------------------------------------------------------------- 1 | #!@TERMUX_PREFIX@/bin/bash 2 | set -e 3 | 4 | SCRIPTNAME=termux-microphone-record 5 | 6 | show_usage () { 7 | echo "Usage: $SCRIPTNAME [args]" 8 | echo "Record using microphone on your device" 9 | echo 10 | echo "-h Shows this help" 11 | echo "-d Start recording w/ defaults" 12 | echo "-f Start recording to specific file" 13 | echo "-l Start recording w/ specified limit (in seconds, unlimited for 0)" 14 | echo "-e Start recording w/ specified encoder (aac, amr_wb, amr_nb, opus)" 15 | echo "-b Start recording w/ specified bitrate (in kbps)" 16 | echo "-r Start recording w/ specified sampling rate (in Hz)" 17 | echo "-c Start recording w/ specified channel count (1, 2, ...)" 18 | echo "-i Get info about current recording" 19 | echo "-q Quits recording" 20 | } 21 | 22 | usage_error () { 23 | echo 24 | show_usage 25 | exit 1 26 | } 27 | 28 | sole() { 29 | if [ "$1 $2" != "-$option $OPTARG" ] || [ $# -gt 2 ]; then 30 | echo "ERROR: No other options should be specified with -$option!" 31 | usage_error 32 | fi 33 | } 34 | 35 | add_params() { 36 | for i in "$@"; do 37 | params[index++]="$i" 38 | done 39 | } 40 | 41 | call_api () { 42 | @TERMUX_PREFIX@/libexec/termux-api MicRecorder "$@" 43 | } 44 | 45 | while getopts h,f:,l:,e:,b:,r:,c:,d,i,q option 46 | do 47 | case "$option" in 48 | h) sole "$@" 49 | ;; 50 | f) record=yes 51 | dir="$(dirname "$OPTARG")" 52 | file="$(basename "$OPTARG")" 53 | dir="$(realpath "$dir")" 54 | add_params --es file "$dir/$file" 55 | ;; 56 | # API takes limit in milliseconds 57 | l) record=yes 58 | add_params --ei limit $((OPTARG * 1000)) 59 | ;; 60 | d) record=yes 61 | ;; 62 | e) record=yes 63 | add_params --es encoder "$OPTARG" 64 | ;; 65 | # API takes bitrate in bps 66 | b) record=yes 67 | add_params --ei bitrate $((OPTARG * 1000)) 68 | ;; 69 | r) record=yes 70 | add_params --ei srate $((OPTARG)) 71 | ;; 72 | c) record=yes 73 | add_params --ei channels $((OPTARG)) 74 | ;; 75 | i) sole "$@" 76 | add_params -a info 77 | ;; 78 | q) sole "$@" 79 | add_params -a quit 80 | ;; 81 | *) usage_error 82 | ;; 83 | esac 84 | done 85 | 86 | if [ -v record ]; then 87 | add_params -a record 88 | fi 89 | 90 | if [ -v params ]; then 91 | call_api "${params[@]}" 92 | else 93 | show_usage 94 | fi 95 | -------------------------------------------------------------------------------- /scripts/termux-nfc.in: -------------------------------------------------------------------------------- 1 | #!@TERMUX_PREFIX@/bin/bash 2 | 3 | set -e -u 4 | 5 | show_usage() { 6 | echo "Usage: termux-nfc [-r [short|full]] [-w] [-t [text for TAG] " 7 | echo " read/write data from/to NDEF tag " 8 | echo " -r, read tag " 9 | echo " short, read short information from tag " 10 | echo " full, read full information from tag " 11 | echo " -w, write information on tag " 12 | echo " -t, text for tag" 13 | exit 0 14 | } 15 | 16 | ARG_R="" 17 | OPT_R="" 18 | ARG_W="" 19 | OPT_T="" 20 | ARG_T="" 21 | 22 | PARAM="" 23 | 24 | if [ $# -eq 0 ];then show_usage;fi 25 | 26 | while getopts ":r:t:w" opt 27 | do 28 | case "$opt" in 29 | r) ARG_R="--es mode read"; OPT_R="--es param $OPTARG"; ;; 30 | w) ARG_W="--es mode write";; 31 | t) ARG_T="--es param text --es value"; OPT_T="$OPTARG"; ;; 32 | ?) echo "Error: unknown parameters: $opt $OPTARG;";show_usage; ;; 33 | esac 34 | done 35 | 36 | 37 | shift $((OPTIND-1)) 38 | 39 | if [ "$#" != 0 ]; then echo "Error: too many parameters!"; show_usage;fi 40 | if [ -n "$ARG_R" ]; then if [ -n "$ARG_W" ]; then echo "Error: Incompatible parameters! \"-r and \"-n";show_usage;fi;fi 41 | 42 | 43 | 44 | if [ -n "$ARG_R" ]; then set -- "$@" $ARG_R $OPT_R;fi 45 | if [ -n "$ARG_W" ]; then set -- "$@" $ARG_W;fi 46 | if [ -n "$ARG_T" ]; then set -- "$@" $ARG_T "$OPT_T";fi 47 | @TERMUX_PREFIX@/libexec/termux-api Nfc "$@" 48 | -------------------------------------------------------------------------------- /scripts/termux-notification-channel.in: -------------------------------------------------------------------------------- 1 | #!@TERMUX_PREFIX@/bin/bash 2 | set -e -u 3 | 4 | SCRIPTNAME=termux-notification-channel 5 | show_usage () { 6 | echo "Usage: $SCRIPTNAME -d channel-id" 7 | echo " $SCRIPTNAME channel-id channel-name" 8 | echo "Create or delete a notification channel." 9 | echo "Only usable on Android 8.0 and higher." 10 | echo "Use -d to delete a channel." 11 | echo "Creating a channel requires a channel id and a channel name." 12 | echo "The name will be visible in the options, the id is used to send notifications on that specific channel." 13 | echo "Creating a channel with the same id again will change the name." 14 | echo "Creating a channel with the same id as a deleted channel will restore the user settings of the deleted channel." 15 | echo "Use termux-notification --channel channel-id to send a notification on a custom channel." 16 | exit 0 17 | } 18 | 19 | ARGS="" 20 | 21 | if [ "$1" = "-d" ]; then 22 | shift 23 | if [ $# == 1 ]; then 24 | ARGS="--ez delete true --es id $1" 25 | else 26 | show_usage 27 | fi 28 | else 29 | if [ $# == 2 ]; then 30 | ARGS="--es id $1 --es name $2" 31 | else 32 | show_usage 33 | fi 34 | fi 35 | 36 | 37 | @TERMUX_PREFIX@/libexec/termux-api NotificationChannel $ARGS 38 | -------------------------------------------------------------------------------- /scripts/termux-notification-list.in: -------------------------------------------------------------------------------- 1 | #!@TERMUX_PREFIX@/bin/sh 2 | set -e -u 3 | 4 | SCRIPTNAME=termux-notification-list 5 | show_usage () { 6 | echo "Usage: $SCRIPTNAME" 7 | echo "Show the list of currently shown notifications." 8 | exit 0 9 | } 10 | 11 | while getopts :h option 12 | do 13 | case "$option" in 14 | h) show_usage;; 15 | ?) echo "$SCRIPTNAME: illegal option -$OPTARG"; exit 1; 16 | esac 17 | done 18 | shift $((OPTIND-1)) 19 | 20 | if [ $# != 0 ]; then echo "$SCRIPTNAME: too many arguments"; exit 1; fi 21 | 22 | @TERMUX_PREFIX@/libexec/termux-api NotificationList 23 | -------------------------------------------------------------------------------- /scripts/termux-notification-remove.in: -------------------------------------------------------------------------------- 1 | #!@TERMUX_PREFIX@/bin/sh 2 | set -e -u 3 | 4 | SCRIPTNAME=termux-notification-remove 5 | show_usage () { 6 | echo "Usage: $SCRIPTNAME notification-id" 7 | echo "Remove a notification previously shown with termux-notification --id." 8 | exit 0 9 | } 10 | 11 | while getopts :h option 12 | do 13 | case "$option" in 14 | h) show_usage;; 15 | ?) echo "$SCRIPTNAME: illegal option -$OPTARG"; exit 1; 16 | esac 17 | done 18 | shift $((OPTIND-1)) 19 | 20 | if [ $# != 1 ]; then echo "$SCRIPTNAME: no notification id specified"; exit 1; fi 21 | 22 | @TERMUX_PREFIX@/libexec/termux-api NotificationRemove --es id "$1" 23 | -------------------------------------------------------------------------------- /scripts/termux-notification.in: -------------------------------------------------------------------------------- 1 | #!@TERMUX_PREFIX@/bin/bash 2 | set -e -u -f 3 | 4 | SCRIPTNAME=termux-notification 5 | show_usage () { 6 | echo "Usage: termux-notification [options]" 7 | echo "Display a system notification. Content text is specified using -c/--content or read from stdin." 8 | echo "Please read --help-actions for help with action arguments." 9 | echo " --action action action to execute when pressing the notification" 10 | echo " --alert-once do not alert when the notification is edited" 11 | echo " --button1 text text to show on the first notification button" 12 | echo " --button1-action action action to execute on the first notification button" 13 | echo " --button2 text text to show on the second notification button" 14 | echo " --button2-action action action to execute on the second notification button" 15 | echo " --button3 text text to show on the third notification button" 16 | echo " --button3-action action action to execute on the third notification button" 17 | echo " -c/--content content content to show in the notification. Will take" 18 | echo " precedence over stdin. If content is not passed as" 19 | echo " an argument or with stdin, then there will be a 3s delay." 20 | echo " --channel channel-id Specifies the notification channel id this notification should be send on." 21 | echo " On Android versions lower than 8.0 this is a no-op." 22 | echo " Create custom channels with termux-notification-channel." 23 | echo " If the channel id is invalid, the notification will not be send." 24 | echo " --group group notification group (notifications with the same" 25 | echo " group are shown together)" 26 | echo " -h/--help show this help" 27 | echo " --help-actions show the help for actions" 28 | echo " -i/--id id notification id (will overwrite any previous notification" 29 | echo " with the same id)" 30 | echo " --icon icon-name set the icon that shows up in the status bar. View" 31 | echo " available icons at https://material.io/resources/icons/" 32 | echo " (default icon: event_note)" 33 | echo " --image-path path absolute path to an image which will be shown in the" 34 | echo " notification" 35 | echo " --led-color rrggbb color of the blinking led as RRGGBB (default: none)" 36 | echo " --led-off milliseconds number of milliseconds for the LED to be off while" 37 | echo " it's flashing (default: 800)" 38 | echo " --led-on milliseconds number of milliseconds for the LED to be on while" 39 | echo " it's flashing (default: 800)" 40 | echo " --on-delete action action to execute when the the notification is cleared" 41 | echo " --ongoing pin the notification" 42 | echo " --priority prio notification priority (high/low/max/min/default)" 43 | echo " --sound play a sound with the notification" 44 | echo " -t/--title title notification title to show" 45 | echo " --vibrate pattern vibrate pattern, comma separated as in 500,1000,200" 46 | echo " --type type notification style to use (default/media)" 47 | echo "Media actions (available with --type \"media\"):" 48 | echo " --media-next action to execute on the media-next button" 49 | echo " --media-pause action to execute on the media-pause button" 50 | echo " --media-play action to execute on the media-play button" 51 | echo " --media-previous action to execute on the media-previous button" 52 | exit 0 53 | } 54 | 55 | show_help_actions () { 56 | echo "This help refers to the arguments to options like --action, --on-delete, --button-1-action and --media-next." 57 | echo 58 | echo "All these commands take an action string as their argument, which is fed to \`dash -c\`." 59 | echo "A few important things must be kept in mind when using actions:" 60 | echo 61 | echo "You should use actions that do things outside of the terminal, like --action \"termux-toast hello\"." 62 | echo "Anything that outputs to the terminal is useless, so the output should either be redirected (--action \"ls > ~/ls.txt\") or shown to the user in a different way (--action \"ls|termux-toast\")." 63 | echo 64 | echo "Running more than one command in a single action is as easy as" 65 | echo "--action \"command1; command2; command3\"" 66 | echo "or" 67 | echo "--action \"if [ -e file ]; then termux-toast yes; else termux-toast no; fi\"." 68 | echo 69 | echo "For anything more complex, you should put your script in a file, make it executable, and use that as the action:" 70 | echo "--action ~/bin/script" 71 | echo 72 | echo "The action is run in a different environment (not a subshell). Thus your environment is lost (most notably \$PATH), and ~/.profile is not sourced either. So if you need your \$PATH you should either:" 73 | echo " - if the action is a script, set it explicitly in the script (e.g. export PATH=\"\$HOME/bin:\$PATH\")" 74 | echo " - or use something like --action \"bash -l -c 'command1; command2'\")." 75 | echo 76 | echo "On Android N or above, you can use the special variable \$REPLY in your actions to use Android's Direct Reply feature." 77 | echo "This prompts the user to enter some text directly in the notification, which is then substituted into your action." 78 | echo " - termux-notification --button1 \"Answer\" --button1-action \"termux-toast \\\$REPLY\"" 79 | echo "will call the action:" 80 | echo " - termux-toast \"Some text entered by the user\"" 81 | echo "Be careful to escape shell commands correctly for single or double quotes, e.g." 82 | echo " --button1-action 'something \$REPLY' or --button1-action \"something \\\$REPLY\"" 83 | } 84 | 85 | OPT_ACTION="" 86 | OPT_ALERT_ONCE="" 87 | OPT_BUTTON1_ACTION="" 88 | OPT_BUTTON1_TEXT="" 89 | OPT_BUTTON2_ACTION="" 90 | OPT_BUTTON2_TEXT="" 91 | OPT_BUTTON3_ACTION="" 92 | OPT_BUTTON3_TEXT="" 93 | OPT_CONTENT="" 94 | OPT_CONTENT_PASSED="" 95 | OPT_CHANNEL="" 96 | OPT_GROUP="" 97 | OPT_ID="" 98 | OPT_ICON="" 99 | OPT_IMAGE_PATH="" 100 | OPT_LED_COLOR="" 101 | OPT_LED_OFF="" 102 | OPT_LED_ON="" 103 | OPT_MEDIA_NEXT="" 104 | OPT_MEDIA_PAUSE="" 105 | OPT_MEDIA_PLAY="" 106 | OPT_MEDIA_PREVIOUS="" 107 | OPT_ONGOING="" 108 | OPT_ON_DELETE_ACTION="" 109 | OPT_PRIORITY="" 110 | OPT_SOUND="" 111 | OPT_TITLE="" 112 | OPT_TYPE="" 113 | OPT_VIBRATE="" 114 | 115 | TEMP=`getopt \ 116 | -n $SCRIPTNAME \ 117 | -o hc:i:t: \ 118 | --long action:,alert-once,\ 119 | button1:,button1-action:,\ 120 | button2:,button2-action:,\ 121 | button3:,button3-action:,\ 122 | content:,channel:,group:,help,help-actions,\ 123 | id:,icon:,image-path:,\ 124 | led-color:,led-on:,led-off:,\ 125 | media-previous:,media-next:,media-play:,media-pause:,\ 126 | on-delete:,ongoing,\ 127 | priority:,\ 128 | sound,title:,type:,vibrate: \ 129 | -s bash \ 130 | -- "$@"` 131 | eval set -- "$TEMP" 132 | 133 | while true; do 134 | case "$1" in 135 | --action) OPT_ACTION="$2"; shift 2;; 136 | --alert-once) OPT_ALERT_ONCE="true"; shift 1;; 137 | --button1) OPT_BUTTON1_TEXT="$2"; shift 2;; 138 | --button1-action) OPT_BUTTON1_ACTION="$2"; shift 2;; 139 | --button2) OPT_BUTTON2_TEXT="$2"; shift 2;; 140 | --button2-action) OPT_BUTTON2_ACTION="$2"; shift 2;; 141 | --button3) OPT_BUTTON3_TEXT="$2"; shift 2;; 142 | --button3-action) OPT_BUTTON3_ACTION="$2"; shift 2;; 143 | -c | --content) OPT_CONTENT_PASSED=1; OPT_CONTENT="$2"; shift 2;; 144 | --channel) OPT_CHANNEL="$2"; shift 2;; 145 | --group) OPT_GROUP="$2"; shift 2;; 146 | -h | --help) show_usage;; 147 | --help-actions) show_help_actions; exit 0;; 148 | -i | --id) OPT_ID="$2"; shift 2;; 149 | --icon) OPT_ICON="$2"; shift 2;; 150 | --image-path) OPT_IMAGE_PATH="$2"; shift 2;; 151 | --led-color) OPT_LED_COLOR="$2"; shift 2;; 152 | --led-off) OPT_LED_OFF="$2"; shift 2;; 153 | --led-on) OPT_LED_ON="$2"; shift 2;; 154 | --media-next) OPT_MEDIA_NEXT="$2"; shift 2;; 155 | --media-pause) OPT_MEDIA_PAUSE="$2"; shift 2;; 156 | --media-play) OPT_MEDIA_PLAY="$2"; shift 2;; 157 | --media-previous) OPT_MEDIA_PREVIOUS="$2"; shift 2;; 158 | --on-delete) OPT_ON_DELETE_ACTION="$2"; shift 2;; 159 | --ongoing) OPT_ONGOING="true"; shift 1;; 160 | --priority) OPT_PRIORITY="$2"; shift 2;; 161 | --sound) OPT_SOUND="true"; shift 1;; 162 | -t | --title) OPT_TITLE="$2"; shift 2;; 163 | --type) OPT_TYPE="$2"; shift 2;; 164 | --vibrate) OPT_VIBRATE="$2"; shift 2;; 165 | --) shift; break ;; 166 | esac 167 | done 168 | 169 | if [ $# != 0 ]; then echo "$SCRIPTNAME: too many arguments"; exit 1; fi 170 | 171 | if [ "$OPT_ONGOING" == true ] && [ -z "$OPT_ID" ]; then 172 | echo "Ongoing notifications without an ID are not removable." 173 | echo "Please set an id with --id \"string\"." 174 | exit 1 175 | fi 176 | 177 | set -- 178 | if [ -n "$OPT_ACTION" ]; then set -- "$@" --es action "$OPT_ACTION"; fi 179 | if [ -n "$OPT_ALERT_ONCE" ]; then set -- "$@" --ez alert-once "$OPT_ALERT_ONCE"; fi 180 | if [ -n "$OPT_BUTTON1_ACTION" ]; then set -- "$@" --es button_action_1 "$OPT_BUTTON1_ACTION"; fi 181 | if [ -n "$OPT_BUTTON1_TEXT" ]; then set -- "$@" --es button_text_1 "$OPT_BUTTON1_TEXT"; fi 182 | if [ -n "$OPT_BUTTON2_ACTION" ]; then set -- "$@" --es button_action_2 "$OPT_BUTTON2_ACTION"; fi 183 | if [ -n "$OPT_BUTTON2_TEXT" ]; then set -- "$@" --es button_text_2 "$OPT_BUTTON2_TEXT"; fi 184 | if [ -n "$OPT_BUTTON3_ACTION" ]; then set -- "$@" --es button_action_3 "$OPT_BUTTON3_ACTION"; fi 185 | if [ -n "$OPT_BUTTON3_TEXT" ]; then set -- "$@" --es button_text_3 "$OPT_BUTTON3_TEXT"; fi 186 | if [ -n "$OPT_CHANNEL" ]; then set -- "$@" --es channel "$OPT_CHANNEL"; fi 187 | if [ -n "$OPT_GROUP" ]; then set -- "$@" --es group "$OPT_GROUP"; fi 188 | if [ -n "$OPT_ID" ]; then set -- "$@" --es id "$OPT_ID"; fi 189 | if [ -n "$OPT_ICON" ]; then set -- "$@" --es icon "$OPT_ICON"; fi 190 | if [ -n "$OPT_IMAGE_PATH" ]; then set -- "$@" --es image-path "$OPT_IMAGE_PATH"; fi 191 | if [ -n "$OPT_LED_COLOR" ]; then set -- "$@" --es led-color "$OPT_LED_COLOR"; fi 192 | if [ -n "$OPT_LED_OFF" ]; then set -- "$@" --ei led-off "$OPT_LED_OFF"; fi 193 | if [ -n "$OPT_LED_ON" ]; then set -- "$@" --ei led-on "$OPT_LED_ON"; fi 194 | if [ -n "$OPT_MEDIA_NEXT" ]; then set -- "$@" --es media-next "$OPT_MEDIA_NEXT"; fi 195 | if [ -n "$OPT_MEDIA_PAUSE" ]; then set -- "$@" --es media-pause "$OPT_MEDIA_PAUSE"; fi 196 | if [ -n "$OPT_MEDIA_PLAY" ]; then set -- "$@" --es media-play "$OPT_MEDIA_PLAY"; fi 197 | if [ -n "$OPT_MEDIA_PREVIOUS" ]; then set -- "$@" --es media-previous "$OPT_MEDIA_PREVIOUS"; fi 198 | if [ -n "$OPT_ONGOING" ]; then set -- "$@" --ez ongoing "$OPT_ONGOING"; fi 199 | if [ -n "$OPT_ON_DELETE_ACTION" ]; then set -- "$@" --es on_delete_action "$OPT_ON_DELETE_ACTION"; fi 200 | if [ -n "$OPT_PRIORITY" ]; then set -- "$@" --es priority "$OPT_PRIORITY"; fi 201 | if [ -n "$OPT_SOUND" ]; then set -- "$@" --ez sound "$OPT_SOUND"; fi 202 | if [ -n "$OPT_TITLE" ]; then set -- "$@" --es title "$OPT_TITLE"; fi 203 | if [ -n "$OPT_TYPE" ]; then set -- "$@" --es type "$OPT_TYPE"; fi 204 | if [ -n "$OPT_VIBRATE" ]; then set -- "$@" --ela vibrate "$OPT_VIBRATE"; fi 205 | 206 | # If content was not passed as an argument, then attempt to read from STDIN with a 3s timeout 207 | # Content argumOPT_CONTENT="$(echo "$OPT_CONTENT")" # trim trailing newlinesent takes precedence over STDIN 208 | if [[ "$OPT_CONTENT_PASSED" != "1" ]]; then 209 | set +e; IFS= read -t 3 -r -d '' OPT_CONTENT; set -e; 210 | fi 211 | 212 | # Trim trailing newlines 213 | OPT_CONTENT="$(echo "$OPT_CONTENT")" 214 | 215 | echo "$OPT_CONTENT" | @TERMUX_PREFIX@/libexec/termux-api Notification "$@" 216 | -------------------------------------------------------------------------------- /scripts/termux-saf-create.in: -------------------------------------------------------------------------------- 1 | #!@TERMUX_PREFIX@/bin/sh 2 | set -e -u 3 | 4 | SCRIPTNAME=termux-saf-create 5 | show_usage () { 6 | echo "Usage: $SCRIPTNAME [-t mime-type] folder-uri name" 7 | echo "Creates a file in a folder managed by Termux:API." 8 | echo "Returns the URI you can use to read and write the file with termux-saf-read and termux-saf-write." 9 | echo "You can specify the mime type explicitly or let it be guessed based on the file extension." 10 | echo "As the folder URI you can use the URI of a directory listed by termux-saf-dirs or by termux-saf-ls." 11 | echo "Android doesn't allow creating files with the same name, so the name may be changed if a file or folder with that name already exists." 12 | echo "You can use termux-saf-stat with the returned URI to get the name it was really given." 13 | echo " -h show this help" 14 | echo " -t specify the mime type of the file. The mime type is required for other apps to recognize the content as e.g. a video. If not specified, 'application/octet-stream' is assumed, that means raw binary data." 15 | exit 0 16 | } 17 | 18 | mime='' 19 | 20 | while getopts :ht: option 21 | do 22 | case "$option" in 23 | h) show_usage;; 24 | t) mime="$OPTARG";; 25 | ?) echo "$SCRIPTNAME: illegal option -$OPTARG"; exit 1; 26 | esac 27 | done 28 | shift $((OPTIND-1)) 29 | 30 | if [ $# != 2 ]; then echo "$SCRIPTNAME: Invalid argument count"; exit 1; fi 31 | 32 | @TERMUX_PREFIX@/libexec/termux-api SAF --es safmethod createDocument --es treeuri "$1" --es filename "$2" --es mimetype "$mime" 33 | 34 | -------------------------------------------------------------------------------- /scripts/termux-saf-dirs.in: -------------------------------------------------------------------------------- 1 | #!@TERMUX_PREFIX@/bin/sh 2 | set -e -u 3 | 4 | SCRIPTNAME=termux-saf-dirs 5 | show_usage () { 6 | echo "Usage: $SCRIPTNAME" 7 | echo "Lists all directories you gave Termux:API in the same format as termux-saf-ls." 8 | echo "That meas this lists the 'directory' that contains all directories you can access with the other termux-saf-* commands." 9 | echo "The URIs can be used with the other termux-saf-* commands to create files and folders and list the directory contents." 10 | echo "See termux-saf-managedir to give Termux:API access to a folder." 11 | echo " -h show this help" 12 | exit 0 13 | } 14 | 15 | while getopts :h option 16 | do 17 | case "$option" in 18 | h) show_usage;; 19 | ?) echo "$SCRIPTNAME: illegal option -$OPTARG"; exit 1; 20 | esac 21 | done 22 | shift $((OPTIND-1)) 23 | 24 | if [ $# != 0 ]; then echo "$SCRIPTNAME: too many arguments"; exit 1; fi 25 | 26 | @TERMUX_PREFIX@/libexec/termux-api SAF --es safmethod getManagedDocumentTrees 27 | 28 | -------------------------------------------------------------------------------- /scripts/termux-saf-ls.in: -------------------------------------------------------------------------------- 1 | #!@TERMUX_PREFIX@/bin/sh 2 | set -e -u 3 | 4 | SCRIPTNAME=termux-saf-ls 5 | show_usage () { 6 | echo "Usage: $SCRIPTNAME folder-uri" 7 | echo "Lists the files and folders in a folder identified by a URI." 8 | echo "You can get a folder URI by:" 9 | echo "- Listing folders with termux-saf-ls" 10 | echo "- Giving Termux:API access to folders with termux-saf-managedir" 11 | echo "- Listing the folders you gave Termux:API access to with termux-saf-dirs" 12 | echo "- Creating a folder with termux-saf-mkdir" 13 | echo "The list is returned as a JSON array with one JSON object per entry." 14 | echo "The objects have the keys:" 15 | echo "- 'name' for the human-readable name" 16 | echo "- 'uri' for URI you can use with the other termux-saf-* commands" 17 | echo "- 'type' for the mime type" 18 | echo "- 'length' for size in bytes if it's a file" 19 | echo "You can recognize folders by the special mime type 'vnd.android.document/directory'." 20 | echo " -h show this help" 21 | exit 0 22 | } 23 | 24 | while getopts :h option 25 | do 26 | case "$option" in 27 | h) show_usage;; 28 | ?) echo "$SCRIPTNAME: illegal option -$OPTARG"; exit 1; 29 | esac 30 | done 31 | shift $((OPTIND-1)) 32 | 33 | if [ $# != 1 ]; then echo "$SCRIPTNAME: Invalid argument count"; exit 1; fi 34 | 35 | @TERMUX_PREFIX@/libexec/termux-api SAF --es safmethod listDirectory --es treeuri "$1" 36 | 37 | -------------------------------------------------------------------------------- /scripts/termux-saf-managedir.in: -------------------------------------------------------------------------------- 1 | #!@TERMUX_PREFIX@/bin/sh 2 | set -e -u 3 | 4 | SCRIPTNAME=termux-saf-managedir 5 | show_usage () { 6 | echo "Usage: $SCRIPTNAME" 7 | echo "Opens the system file explorer and lets you specify a folder Termux:API get access to." 8 | echo "You can then use the termux-saf-* utilities to manage the contents in that folder." 9 | echo "Returns a URI identifying the directory, this URI can be used with the other termux-saf-* commands to create files and folders and list the directory contents." 10 | echo "If you close the file manager instead, an empty string will be returned." 11 | echo "You can use termux-saf-dirs to list out all directories you gave Termux:API access to like this." 12 | echo " -h show this help" 13 | exit 0 14 | } 15 | 16 | while getopts :h option 17 | do 18 | case "$option" in 19 | h) show_usage;; 20 | ?) echo "$SCRIPTNAME: illegal option -$OPTARG"; exit 1; 21 | esac 22 | done 23 | shift $((OPTIND-1)) 24 | 25 | if [ $# != 0 ]; then echo "$SCRIPTNAME: too many arguments"; exit 1; fi 26 | 27 | @TERMUX_PREFIX@/libexec/termux-api SAF --es safmethod manageDocumentTree 28 | 29 | -------------------------------------------------------------------------------- /scripts/termux-saf-mkdir.in: -------------------------------------------------------------------------------- 1 | #!@TERMUX_PREFIX@/bin/sh 2 | set -e -u 3 | 4 | SCRIPTNAME=termux-saf-mkdir 5 | show_usage () { 6 | echo "Usage: $SCRIPTNAME parent-uri name" 7 | echo "Creates a directory via SAF." 8 | echo "This behaves like termux-saf-create, just for directories." 9 | echo " -h show this help" 10 | exit 0 11 | } 12 | 13 | while getopts :h option 14 | do 15 | case "$option" in 16 | h) show_usage;; 17 | ?) echo "$SCRIPTNAME: illegal option -$OPTARG"; exit 1; 18 | esac 19 | done 20 | shift $((OPTIND-1)) 21 | 22 | if [ $# != 2 ]; then echo "$SCRIPTNAME: Invalid argument count"; exit 1; fi 23 | 24 | @TERMUX_PREFIX@/libexec/termux-api SAF --es safmethod createDocument --es treeuri "$1" --es filename "$2" --es mimetype 'vnd.android.document/directory' 25 | 26 | -------------------------------------------------------------------------------- /scripts/termux-saf-read.in: -------------------------------------------------------------------------------- 1 | #!@TERMUX_PREFIX@/bin/sh 2 | set -e -u 3 | 4 | SCRIPTNAME=termux-saf-read 5 | show_usage () { 6 | echo "Usage: $SCRIPTNAME uri" 7 | echo "Reads from a file identified by a URI and writes the data to sstandard output." 8 | echo "You can use pipes to process the data or redirect it into a file to make a local copy." 9 | echo "See termux-saf-list to get the URIs to files." 10 | echo " -h show this help" 11 | exit 0 12 | } 13 | 14 | while getopts :h option 15 | do 16 | case "$option" in 17 | h) show_usage;; 18 | ?) echo "$SCRIPTNAME: illegal option -$OPTARG"; exit 1; 19 | esac 20 | done 21 | shift $((OPTIND-1)) 22 | 23 | if [ $# != 1 ]; then echo "$SCRIPTNAME: Invalid argument count"; exit 1; fi 24 | 25 | @TERMUX_PREFIX@/libexec/termux-api SAF --es safmethod readDocument --es uri "$1" 26 | 27 | -------------------------------------------------------------------------------- /scripts/termux-saf-rm.in: -------------------------------------------------------------------------------- 1 | #!@TERMUX_PREFIX@/bin/sh 2 | set -e -u 3 | 4 | SCRIPTNAME=termux-saf-rm 5 | show_usage () { 6 | echo "Usage: $SCRIPTNAME uri" 7 | echo "Removes the file or folder at the given URI. See other termux-saf-* commands for more info." 8 | echo "Returns 0 on success, 1 if the file or folder couldn't be deleted and 2 if another error occurred." 9 | echo " -h show this help" 10 | exit 0 11 | } 12 | 13 | while getopts :h option 14 | do 15 | case "$option" in 16 | h) show_usage;; 17 | ?) echo "$SCRIPTNAME: illegal option -$OPTARG"; exit 1; 18 | esac 19 | done 20 | shift $((OPTIND-1)) 21 | 22 | if [ $# != 1 ]; then echo "$SCRIPTNAME: Invalid argument count"; exit 1; fi 23 | 24 | exit "$(@TERMUX_PREFIX@/libexec/termux-api SAF --es safmethod removeDocument --es uri "$1")" 25 | 26 | -------------------------------------------------------------------------------- /scripts/termux-saf-stat.in: -------------------------------------------------------------------------------- 1 | #!@TERMUX_PREFIX@/bin/sh 2 | set -e -u 3 | 4 | SCRIPTNAME=termux-saf-stat 5 | show_usage () { 6 | echo "Usage: $SCRIPTNAME uri" 7 | echo "Returns the file or folder info as a JSON object." 8 | echo "The format is the same as an entry from termux-saf-ls." 9 | echo " -h show this help" 10 | exit 0 11 | } 12 | 13 | while getopts :h option 14 | do 15 | case "$option" in 16 | h) show_usage;; 17 | ?) echo "$SCRIPTNAME: illegal option -$OPTARG"; exit 1; 18 | esac 19 | done 20 | shift $((OPTIND-1)) 21 | 22 | if [ $# != 1 ]; then echo "$SCRIPTNAME: Invalid argument count"; exit 1; fi 23 | 24 | @TERMUX_PREFIX@/libexec/termux-api SAF --es safmethod statURI --es uri "$1" 25 | 26 | -------------------------------------------------------------------------------- /scripts/termux-saf-write.in: -------------------------------------------------------------------------------- 1 | #!@TERMUX_PREFIX@/bin/sh 2 | set -e -u 3 | 4 | SCRIPTNAME=termux-saf-write 5 | show_usage () { 6 | echo "Usage: $SCRIPTNAME uri" 7 | echo "Writes the standard input into an existing file identified by a URI. The previous contents are erased. To create a new file, use termux-saf-create." 8 | echo " -h show this help" 9 | exit 0 10 | } 11 | 12 | while getopts :h option 13 | do 14 | case "$option" in 15 | h) show_usage;; 16 | ?) echo "$SCRIPTNAME: illegal option -$OPTARG"; exit 1; 17 | esac 18 | done 19 | shift $((OPTIND-1)) 20 | 21 | if [ $# != 1 ]; then echo "$SCRIPTNAME: Invalid argument count"; exit 1; fi 22 | 23 | @TERMUX_PREFIX@/libexec/termux-api SAF --es safmethod writeDocument --es uri "$1" 24 | 25 | -------------------------------------------------------------------------------- /scripts/termux-sensor.in: -------------------------------------------------------------------------------- 1 | #!@TERMUX_PREFIX@/bin/bash 2 | set -e -u 3 | 4 | SCRIPTNAME=termux-sensor 5 | show_usage () { 6 | echo "Usage: $SCRIPTNAME" 7 | echo "Get information about types of sensors as well as live data" 8 | echo " -h, help Show this help" 9 | echo " -a, all Listen to all sensors (WARNING! may have battery impact)" 10 | echo " -c, cleanup Perform cleanup (release sensor resources)" 11 | echo " -l, list Show list of available sensors" 12 | echo " -s, sensors [,,,] Sensors to listen to (can contain just partial name)" 13 | echo " -d, delay [ms] Delay time in milliseconds before receiving new sensor update" 14 | echo " -n, limit [num] Number of times to read sensor(s) (default: continuous) (min: 1)" 15 | exit 0 16 | } 17 | 18 | # ensure we properly release resources if needed on ^C 19 | trap handle_interrupt SIGTERM SIGINT 20 | 21 | if [ $# -eq 0 ]; then 22 | echo "No arguments supplied!" 23 | show_usage 24 | exit 1; 25 | fi 26 | 27 | SENSOR_FLAG=1 28 | ALL_SENSORS_FLAG=2 29 | LIST_FLAG=4 30 | CLEANUP_FLAG=8 31 | DELAY_FLAG=16 32 | LIMIT_FLAG=32 33 | FLAGS=0 34 | 35 | handle_interrupt () { 36 | echo "Caught interrupt.. Finishing..." 37 | cleanup 38 | } 39 | 40 | cleanup () { 41 | if [ $((FLAGS & (ALL_SENSORS_FLAG | SENSOR_FLAG))) != 0 ]; then 42 | echo "Performing sensor cleanup" 43 | call_api -a cleanup 44 | else 45 | echo "No cleanup necessary" 46 | fi 47 | } 48 | 49 | get_sensors () { 50 | if [ $# -gt 1 ]; then 51 | usage_error "Sensor arg should be a comma delimited string!" 52 | fi 53 | } 54 | 55 | get_delay () { 56 | if [ $# -gt 1 ]; then 57 | usage_error "Too many arguments for -d delay" 58 | elif ! [[ $1 =~ ^[0-9]+$ ]]; then 59 | usage_error "Illegal argument! -d delay arg should be a number!" 60 | fi 61 | } 62 | 63 | get_limit () { 64 | if [ $# -gt 1 ]; then 65 | usage_error "Too many arguments for -n limit" 66 | elif ! [[ $1 =~ ^[0-9]+$ ]]; then 67 | usage_error "Illegal argument! -n limit arg should be a number!" 68 | fi 69 | } 70 | 71 | call_api () { 72 | @TERMUX_PREFIX@/libexec/termux-api Sensor "$@" 73 | } 74 | 75 | set_flag () { 76 | FLAGS=$((FLAGS | $1)); 77 | } 78 | 79 | usage_error () { 80 | echo "ERROR: $*" 81 | show_usage 82 | exit 1 83 | } 84 | 85 | 86 | PARAMS=() 87 | while getopts :h,a,c,l,s:d:n: option 88 | do 89 | case "$option" in 90 | h) show_usage ;; 91 | a) set_flag $ALL_SENSORS_FLAG; PARAMS+=(-a sensors --ez all true);; 92 | c) set_flag $CLEANUP_FLAG; PARAMS=(-a cleanup) ;; 93 | l) set_flag $LIST_FLAG; PARAMS=(-a list) ;; 94 | s) set_flag $SENSOR_FLAG; get_sensors "$OPTARG"; PARAMS+=(-a sensors --es sensors "$OPTARG") ;; 95 | d) set_flag $DELAY_FLAG; get_delay "$OPTARG"; PARAMS+=(--ei delay "$OPTARG") ;; 96 | n) set_flag $LIMIT_FLAG; get_limit "$OPTARG"; PARAMS+=(--ei limit "$OPTARG") ;; 97 | ?) echo "$SCRIPTNAME: illegal option -$OPTARG"; exit 1; 98 | esac 99 | done 100 | shift $((OPTIND -1)) 101 | 102 | # Validate options were set properly 103 | 104 | if [ $((FLAGS & CLEANUP_FLAG)) -ne 0 ] && [ $FLAGS -ne $CLEANUP_FLAG ]; then 105 | usage_error "No other options should be specified with -c cleanup!" 106 | elif [ $((FLAGS & LIST_FLAG)) -ne 0 ] && [ $FLAGS -ne $LIST_FLAG ]; then 107 | usage_error "No other options should be specified with -l list!" 108 | elif [ $((FLAGS & DELAY_FLAG)) -ne 0 ] && [ $((FLAGS & (ALL_SENSORS_FLAG | SENSOR_FLAG))) -eq 0 ]; then 109 | usage_error "Use -s or -a option when using -d delay!" 110 | elif [ $((FLAGS & ALL_SENSORS_FLAG)) -ne 0 ] && [ $((FLAGS & SENSOR_FLAG)) -ne 0 ]; then 111 | usage_error "Listed sensors will be ignored with -a all option!" 112 | fi 113 | 114 | call_api "${PARAMS[@]}" 115 | -------------------------------------------------------------------------------- /scripts/termux-share.in: -------------------------------------------------------------------------------- 1 | #!@TERMUX_PREFIX@/bin/sh 2 | set -e -u 3 | 4 | SCRIPTNAME=termux-share 5 | show_usage () { 6 | echo "Usage: $SCRIPTNAME [-a action] [-c content-type] [-d] [-t title] [file]" 7 | echo "Share a file specified as argument or the text received on stdin if no file argument is given." 8 | echo " -a action which action to performed on the shared content:" 9 | echo " edit/send/view (default:view)" 10 | echo " -c content-type content-type to use (default: guessed from file extension," 11 | echo " text/plain for stdin)" 12 | echo " -d share to the default receiver if one is selected" 13 | echo " instead of showing a chooser" 14 | echo " -t title title to use for shared content (default: shared file name)" 15 | exit 0 16 | } 17 | 18 | validate_share () { 19 | SHARETYPE=$1 20 | case "$SHARETYPE" in 21 | edit) ;; 22 | send) ;; 23 | view) ;; 24 | *) echo "$SCRIPTNAME: Unsupported action: '$SHARETYPE'"; exit 1;; 25 | esac 26 | } 27 | 28 | PARAMS="" 29 | while getopts :ha:c:dt: option 30 | do 31 | case "$option" in 32 | h) show_usage;; 33 | a) validate_share "$OPTARG"; PARAMS="$PARAMS --es action $OPTARG";; 34 | c) PARAMS="$PARAMS --es content-type $OPTARG";; 35 | d) PARAMS="$PARAMS --ez default-receiver true";; 36 | t) PARAMS="$PARAMS --es title $OPTARG";; 37 | ?) echo "$SCRIPTNAME: illegal option -$OPTARG"; exit 1; 38 | esac 39 | done 40 | shift $((OPTIND-1)) 41 | 42 | if [ $# -gt 1 ]; then echo "$SCRIPTNAME: too many arguments"; exit 1; fi 43 | 44 | if [ $# != 0 ]; then 45 | if [ ! -f "$1" ]; then 46 | echo "$1 is not a file" 47 | exit 1 48 | fi 49 | 50 | # Note that the file path can contain whitespace. 51 | @TERMUX_PREFIX@/libexec/termux-api Share $PARAMS --es file "$(realpath "$1")" 52 | else 53 | @TERMUX_PREFIX@/libexec/termux-api Share $PARAMS 54 | fi 55 | -------------------------------------------------------------------------------- /scripts/termux-sms-inbox.in: -------------------------------------------------------------------------------- 1 | #!@TERMUX_PREFIX@/bin/sh 2 | 3 | echo "termux-sms-inbox: This script has been replaced by termux-sms-list." 4 | exit 1 5 | -------------------------------------------------------------------------------- /scripts/termux-sms-list.in: -------------------------------------------------------------------------------- 1 | #!@TERMUX_PREFIX@/bin/bash 2 | # shellcheck shell=bash 3 | 4 | set -u 5 | 6 | if [ -z "${BASH_VERSION:-}" ]; then 7 | echo "The 'termux-sms-list' script must be run from a 'bash' shell."; return 64 2>/dev/null|| exit 64 # EX__USAGE 8 | fi 9 | 10 | termux_api__sms_list__init() { 11 | 12 | # Any and all global variables used by this script must be set to 13 | # default values here so that old/wrong values are not used as the 14 | # `termux_api__*__main()` function of this script or some other API 15 | # script may be called (repeatedly) after sourcing the respective 16 | # scripts. 17 | 18 | TERMUX_API__SCRIPT_NAME="termux-sms-list" 19 | TERMUX_API__API_CONTROLLER="SmsInbox" 20 | 21 | TERMUX_API__COMMAND_TYPE_NOOP="false" # Default: `false` 22 | 23 | 24 | TERMUX_API__CONVERSATION_LIST="" # Default: `` 25 | TERMUX_API__CONVERSATION_LIMIT="" # Default: `` 26 | TERMUX_API__CONVERSATION_OFFSET="" # Default: `` 27 | TERMUX_API__CONVERSATION_SELECTION="" # Default: `` 28 | TERMUX_API__CONVERSATION_SORT_ORDER="" # Default: `` 29 | TERMUX_API__CONVERSATION_RETURN_MULTIPLE_MESSAGES="" # Default: `` 30 | TERMUX_API__CONVERSATION_RETURN_NESTED_VIEW="" # Default: `` 31 | TERMUX_API__CONVERSATION_RETURN_NO_ORDER_REVERSE="" # Default: `` 32 | 33 | 34 | TERMUX_API__MESSASGE_LIMIT___DEFAULT_VALUE=10 # Default: `10` 35 | TERMUX_API__MESSASGE_LIMIT="$TERMUX_API__MESSASGE_LIMIT___DEFAULT_VALUE" # Default: `10` 36 | TERMUX_API__MESSASGE_OFFSET___DEFAULT_VALUE=0 # Default: `0` 37 | TERMUX_API__MESSASGE_OFFSET="$TERMUX_API__MESSASGE_OFFSET___DEFAULT_VALUE" # Default: `0` 38 | TERMUX_API__MESSASGE_SELECTION="" # Default: `` 39 | TERMUX_API__MESSASGE_ADDRESS="" # Default: `` 40 | TERMUX_API__MESSAGE_SORT_ORDER="" # Default: `` 41 | TERMUX_API__MESSASGE_TYPE_NAME___DEFAULT_VALUE="all" # Default: `all` 42 | TERMUX_API__MESSASGE_TYPE_NAME___SUPPORTED_VALUES="all|inbox|sent|draft|outbox|failed|queued" # Default: `all|inbox|sent|draft|outbox|failed|queued` 43 | TERMUX_API__MESSASGE_TYPE_NAME="$TERMUX_API__MESSASGE_TYPE_NAME___DEFAULT_VALUE" # Default: `all` 44 | TERMUX_API__MESSAGE_RETURN_NO_ORDER_REVERSE="" # Default: `` 45 | 46 | # Backward compatibility. 47 | TERMUX_API__MESSAGE_SHOW_DATES="" # Default: `` 48 | TERMUX_API__MESSAGE_SHOW_PHONE_NUMBERS="" # Default: `` 49 | 50 | 51 | unset TERMUX_API__API_ARGS; declare -a TERMUX_API__API_ARGS=() 52 | 53 | 54 | # FIXME: 55 | #TERMUX__PREFIX___N="@TERMUX_ENV__S_TERMUX@PREFIX" 56 | #TERMUX__PREFIX="${!TERMUX__PREFIX___N:-}" 57 | #[[ ! "$TERMUX__PREFIX" =~ ^(/[^/]+)+$ ]] && \ 58 | #TERMUX__PREFIX="@TERMUX__PREFIX@" 59 | TERMUX__PREFIX="@TERMUX_PREFIX@" 60 | 61 | 62 | # FIXME: 63 | #TERMUX_API__LOG_LEVEL___N="@TERMUX_ENV__S_TERMUX_API@LOG_LEVEL" 64 | TERMUX_API__LOG_LEVEL___N="TERMUX_API__LOG_LEVEL" 65 | TERMUX_API__LOG_LEVEL="${!TERMUX_API__LOG_LEVEL___N:-}" 66 | export "${TERMUX_API__LOG_LEVEL___N?}" || return $? 67 | 68 | TERMUX_API__MAX_LOG_LEVEL=5 # Default: `5` (VVVERBOSE=5) 69 | { [[ ! "$TERMUX_API__LOG_LEVEL" =~ ^[0-9]+$ ]] || [[ "$TERMUX_API__LOG_LEVEL" -gt "$TERMUX_API__MAX_LOG_LEVEL" ]]; } && \ 70 | TERMUX_API__LOG_LEVEL=1 # Default: `1` (OFF=0, NORMAL=1, DEBUG=2, VERBOSE=3, VVERBOSE=4 and VVVERBOSE=5) 71 | 72 | } 73 | 74 | 75 | 76 | termux_api__log() { local log_level="${1:-}"; shift; if [[ "${TERMUX_API__LOG_LEVEL:-1}" -ge "$log_level" ]]; then echo "${TERMUX_API__SCRIPT_NAME:-termux-api}:" "$@"; fi } 77 | termux_api__log_literal() { local log_level="${1:-}"; shift; if [[ "${TERMUX_API__LOG_LEVEL:-1}" -ge "$log_level" ]]; then echo -e "${TERMUX_API__SCRIPT_NAME:-termux-api}:" "$@"; fi } 78 | termux_api__log_error() { echo "${TERMUX_API__SCRIPT_NAME:-termux-api}:" "$@" 1>&2; } 79 | 80 | 81 | 82 | ## 83 | # `termux_api__sms_list__main` [``] 84 | ## 85 | termux_api__sms_list__main() { 86 | 87 | local return_value 88 | 89 | termux_api__sms_list__init || return $? 90 | 91 | # Process the command arguments passed to the script. 92 | termux_api__sms_list__process_script_arguments "$@" || return $? 93 | if [ "$TERMUX_API__COMMAND_TYPE_NOOP" = "true" ]; then return 0; fi 94 | 95 | 96 | termux_api__log 2 "Running command" 97 | 98 | 99 | local messasge_type_column 100 | case "$TERMUX_API__MESSASGE_TYPE_NAME" in 101 | all) messasge_type_column=0 ;; 102 | inbox) messasge_type_column=1 ;; 103 | sent) messasge_type_column=2 ;; 104 | draft) messasge_type_column=3 ;; 105 | outbox) messasge_type_column=4 ;; 106 | failed) messasge_type_column=5 ;; 107 | queued) messasge_type_column=6 ;; 108 | *) 109 | termux_api__log_error "Unsupported message type '$TERMUX_API__MESSASGE_TYPE_NAME'. It must one of following: $TERMUX_API__MESSASGE_TYPE_NAME___SUPPORTED_VALUES" 110 | return 1 111 | ;; 112 | esac 113 | 114 | 115 | if [[ -n "$TERMUX_API__CONVERSATION_LIST" ]]; then 116 | TERMUX_API__API_ARGS+=(--ez "conversation-list" "$TERMUX_API__CONVERSATION_LIST") 117 | 118 | if [[ "$TERMUX_API__CONVERSATION_LIST" == "true" ]]; then 119 | if [[ -n "$TERMUX_API__CONVERSATION_LIMIT" ]]; then 120 | TERMUX_API__API_ARGS+=(--ei "conversation-limit" "$TERMUX_API__CONVERSATION_LIMIT") 121 | fi 122 | 123 | if [[ -n "$TERMUX_API__CONVERSATION_OFFSET" ]]; then 124 | TERMUX_API__API_ARGS+=(--ei "conversation-offset" "$TERMUX_API__CONVERSATION_OFFSET") 125 | fi 126 | 127 | if [[ -n "$TERMUX_API__CONVERSATION_SELECTION" ]]; then 128 | TERMUX_API__API_ARGS+=(--es "conversation-selection" "$TERMUX_API__CONVERSATION_SELECTION") 129 | fi 130 | 131 | if [[ -n "$TERMUX_API__CONVERSATION_SORT_ORDER" ]]; then 132 | TERMUX_API__API_ARGS+=(--es "conversation-sort-order" "$TERMUX_API__CONVERSATION_SORT_ORDER") 133 | fi 134 | 135 | if [[ -n "$TERMUX_API__CONVERSATION_RETURN_MULTIPLE_MESSAGES" ]]; then 136 | TERMUX_API__API_ARGS+=(--ez "conversation-return-multiple-messages" "$TERMUX_API__CONVERSATION_RETURN_MULTIPLE_MESSAGES") 137 | fi 138 | 139 | if [[ -n "$TERMUX_API__CONVERSATION_RETURN_NESTED_VIEW" ]]; then 140 | TERMUX_API__API_ARGS+=(--ez "conversation-return-nested-view" "$TERMUX_API__CONVERSATION_RETURN_NESTED_VIEW") 141 | fi 142 | 143 | if [[ -n "$TERMUX_API__CONVERSATION_SORT_ORDER" ]]; then 144 | TERMUX_API__API_ARGS+=(--ez "conversation-return-no-order-reverse" "$TERMUX_API__CONVERSATION_RETURN_NO_ORDER_REVERSE") 145 | fi 146 | fi 147 | fi 148 | 149 | 150 | TERMUX_API__API_ARGS+=( 151 | --ei "limit" "$TERMUX_API__MESSASGE_LIMIT" 152 | --ei "offset" "$TERMUX_API__MESSASGE_OFFSET" 153 | --ei "type" "$messasge_type_column" 154 | ) 155 | 156 | if [[ -n "$TERMUX_API__MESSASGE_SELECTION" ]]; then 157 | TERMUX_API__API_ARGS+=(--es "message-selection" "$TERMUX_API__MESSASGE_SELECTION") 158 | fi 159 | 160 | if [[ -n "$TERMUX_API__MESSASGE_ADDRESS" ]]; then 161 | TERMUX_API__API_ARGS+=(--es "from" "$TERMUX_API__MESSASGE_ADDRESS") 162 | fi 163 | 164 | if [[ -n "$TERMUX_API__MESSAGE_SORT_ORDER" ]]; then 165 | TERMUX_API__API_ARGS+=(--es "message-sort-order" "$TERMUX_API__MESSAGE_SORT_ORDER") 166 | fi 167 | 168 | if [[ -n "$TERMUX_API__MESSAGE_RETURN_NO_ORDER_REVERSE" ]]; then 169 | TERMUX_API__API_ARGS+=(--ez "message-return-no-order-reverse" "$TERMUX_API__MESSAGE_RETURN_NO_ORDER_REVERSE") 170 | fi 171 | 172 | # Backward compatibility. 173 | if [[ -n "$TERMUX_API__MESSAGE_SHOW_DATES" ]]; then 174 | TERMUX_API__API_ARGS+=(--ez "show-dates" "$TERMUX_API__MESSAGE_SHOW_DATES") 175 | fi 176 | 177 | # Backward compatibility. 178 | if [[ -n "$TERMUX_API__MESSAGE_SHOW_PHONE_NUMBERS" ]]; then 179 | TERMUX_API__API_ARGS+=(--ez "show-phone-numbers" "$TERMUX_API__MESSAGE_SHOW_PHONE_NUMBERS") 180 | fi 181 | 182 | 183 | if [[ $TERMUX_API__LOG_LEVEL -ge 2 ]]; then 184 | local api_args_string="termux-api $TERMUX_API__API_CONTROLLER" 185 | local i=1 186 | for ((i = 0; i < ${#TERMUX_API__API_ARGS[@]}; i++)); do 187 | api_args_string="$api_args_string \`${TERMUX_API__API_ARGS[$i]}\`" 188 | done 189 | termux_api__log 2 "$api_args_string" 190 | fi 191 | 192 | 193 | return_value=0 194 | "$TERMUX__PREFIX/libexec/termux-api" "$TERMUX_API__API_CONTROLLER" "${TERMUX_API__API_ARGS[@]}" || return_value=$? 195 | if [ $return_value -ne 0 ]; then 196 | termux_api__log_error "Command failed with exit code $return_value" 197 | else 198 | termux_api__log 2 "Command successful" 199 | fi 200 | return $return_value 201 | 202 | } 203 | 204 | ## 205 | # `termux_api__sms_list__process_script_arguments` [``] 206 | ## 207 | termux_api__sms_list__process_script_arguments() { 208 | 209 | local opt; local opt_arg; local OPTARG; local OPTIND 210 | 211 | # Parse options to main command. 212 | while getopts ":hqvcdf:l:no:t:-:" opt; do 213 | opt_arg="${OPTARG:-}" 214 | case "${opt}" in 215 | -) 216 | case "${OPTARG}" in *?=*) opt_arg="${OPTARG#*=}";; *) opt_arg="";; esac 217 | case "${OPTARG}" in 218 | help) 219 | TERMUX_API__COMMAND_TYPE_NOOP="true" 220 | termux_api__sms_list__show_help; return $? 221 | ;; 222 | # FIXME: 223 | #version) 224 | # TERMUX_API__COMMAND_TYPE_NOOP="true" 225 | # echo "@TERMUX_API_PKG__VERSION@"; return $? 226 | # ;; 227 | # [ --version ] Display version. 228 | quiet) 229 | TERMUX_API__LOG_LEVEL=0 230 | ;; 231 | conversation-list) 232 | TERMUX_API__CONVERSATION_LIST="true" 233 | ;; 234 | conversation-limit=?*) 235 | TERMUX_API__CONVERSATION_LIMIT="$opt_arg" 236 | ;; 237 | conversation-limit | conversation-limit=) 238 | termux_api__log_error "No argument set for arg option '--${OPTARG%=*}'." 239 | return 64 # EX__USAGE 240 | ;; 241 | conversation-offset=?*) 242 | TERMUX_API__CONVERSATION_OFFSET="$opt_arg" 243 | ;; 244 | conversation-offset | conversation-offset=) 245 | termux_api__log_error "No argument set for arg option '--${OPTARG%=*}'." 246 | return 64 # EX__USAGE 247 | ;; 248 | conversation-return-multiple-messages) 249 | TERMUX_API__CONVERSATION_RETURN_MULTIPLE_MESSAGES="true" 250 | ;; 251 | conversation-return-nested-view) 252 | TERMUX_API__CONVERSATION_RETURN_NESTED_VIEW="true" 253 | ;; 254 | conversation-return-no-order-reverse) 255 | TERMUX_API__CONVERSATION_RETURN_NO_ORDER_REVERSE="true" 256 | ;; 257 | conversation-selection=?*) 258 | TERMUX_API__CONVERSATION_SELECTION="$opt_arg" 259 | ;; 260 | conversation-selection | conversation-selection=) 261 | termux_api__log_error "No argument set for arg option '--${OPTARG%=*}'." 262 | return 64 # EX__USAGE 263 | ;; 264 | conversation-sort-order=?*) 265 | TERMUX_API__CONVERSATION_SORT_ORDER="$opt_arg" 266 | ;; 267 | conversation-sort-order | conversation-sort-order=) 268 | termux_api__log_error "No argument set for arg option '--${OPTARG%=*}'." 269 | return 64 # EX__USAGE 270 | ;; 271 | message-address=?*) 272 | TERMUX_API__MESSASGE_ADDRESS="$opt_arg" 273 | ;; 274 | message-address | message-address=) 275 | termux_api__log_error "No argument set for arg option '--${OPTARG%=*}'." 276 | return 64 # EX__USAGE 277 | ;; 278 | message-limit=?*) 279 | TERMUX_API__MESSASGE_LIMIT="$opt_arg" 280 | ;; 281 | message-limit | message-limit=) 282 | termux_api__log_error "No argument set for arg option '--${OPTARG%=*}'." 283 | return 64 # EX__USAGE 284 | ;; 285 | message-offset=?*) 286 | TERMUX_API__MESSASGE_OFFSET="$opt_arg" 287 | ;; 288 | message-offset | message-offset=) 289 | termux_api__log_error "No argument set for arg option '--${OPTARG%=*}'." 290 | return 64 # EX__USAGE 291 | ;; 292 | message-return-no-order-reverse) 293 | TERMUX_API__MESSAGE_RETURN_NO_ORDER_REVERSE="true" 294 | ;; 295 | message-selection=?*) 296 | TERMUX_API__MESSASGE_SELECTION="$opt_arg" 297 | ;; 298 | message-selection | message-selection=) 299 | termux_api__log_error "No argument set for arg option '--${OPTARG%=*}'." 300 | return 64 # EX__USAGE 301 | ;; 302 | message-sort-order=?*) 303 | TERMUX_API__MESSAGE_SORT_ORDER="$opt_arg" 304 | ;; 305 | message-sort-order | message-sort-order=) 306 | termux_api__log_error "No argument set for arg option '--${OPTARG%=*}'." 307 | return 64 # EX__USAGE 308 | ;; 309 | message-type=?*) 310 | TERMUX_API__MESSASGE_TYPE_NAME="$opt_arg" 311 | ;; 312 | message-type | message-type=) 313 | termux_api__log_error "No argument set for arg option '--${OPTARG%=*}'." 314 | return 64 # EX__USAGE 315 | ;; 316 | '') 317 | # End of options `--`. 318 | break 319 | ;; 320 | *) 321 | termux_api__log_error "Unknown option: '--${OPTARG:-}'." 322 | termux_api__sms_list__exit_on_args_error || return $? 323 | 324 | ;; 325 | esac 326 | ;; 327 | h) 328 | TERMUX_API__COMMAND_TYPE_NOOP="true" 329 | termux_api__sms_list__show_help; return $? 330 | ;; 331 | q) 332 | TERMUX_API__LOG_LEVEL=0 333 | ;; 334 | v) 335 | if [ "$TERMUX_API__LOG_LEVEL" -lt "$TERMUX_API__MAX_LOG_LEVEL" ]; then 336 | TERMUX_API__LOG_LEVEL=$((TERMUX_API__LOG_LEVEL+1)); 337 | else 338 | termux_api__log_error "Invalid option, max log level is $TERMUX_API__MAX_LOG_LEVEL." 339 | return 64 # EX__USAGE 340 | fi 341 | ;; 342 | c) 343 | TERMUX_API__CONVERSATION_LIST="true" 344 | ;; 345 | d) 346 | TERMUX_API__MESSAGE_SHOW_DATES="true" 347 | ;; 348 | f) 349 | TERMUX_API__MESSASGE_ADDRESS="$opt_arg" 350 | ;; 351 | l) 352 | TERMUX_API__MESSASGE_LIMIT="$opt_arg" 353 | ;; 354 | n) 355 | TERMUX_API__MESSAGE_SHOW_PHONE_NUMBERS="true" 356 | ;; 357 | o) 358 | TERMUX_API__MESSASGE_OFFSET="$opt_arg" 359 | ;; 360 | t) 361 | TERMUX_API__MESSASGE_TYPE_NAME="$opt_arg" 362 | ;; 363 | :) 364 | termux_api__log_error "No argument passed for arg option '-$OPTARG'." 365 | termux_api__sms_list__exit_on_args_error || return $? 366 | ;; 367 | \?) 368 | termux_api__log_error "Unknown option${OPTARG:+": '-${OPTARG:-}'"}." 369 | termux_api__sms_list__exit_on_args_error || return $? 370 | ;; 371 | esac 372 | done 373 | shift $((OPTIND - 1)) # Remove already processed arguments from argument list 374 | 375 | # If a non-option argument is given to main command. 376 | if [ $# -ne 0 ]; then 377 | logger__log_error "Unknown argument(s) to command: $*" 378 | return 64 # EX__USAGE 379 | fi 380 | 381 | return 0; 382 | 383 | } 384 | 385 | ## 386 | # `termux_api__sms_list__exit_on_args_error` 387 | ## 388 | termux_api__sms_list__exit_on_args_error() { 389 | 390 | termux_api__sms_list__show_help || return $? 391 | 392 | return 64 # EX__USAGE 393 | 394 | } 395 | 396 | ## 397 | # `termux_api__sms_list__show_help` 398 | ## 399 | termux_api__sms_list__show_help() { 400 | 401 | # FIXME: CMake `configure_file` `@ONLY` will replace `@VAR@` style 402 | # placeholders, so use `!VAR!` until we shift to make. 403 | 404 | cat <<'HELP_EOF' | \ 405 | sed \ 406 | -e "s%[!]TERMUX_API__SCRIPT_NAME[!]%${TERMUX_API__SCRIPT_NAME}%g" \ 407 | -e "s%[!]TERMUX_API__MESSASGE_LIMIT___DEFAULT_VALUE[!]%${TERMUX_API__MESSASGE_LIMIT___DEFAULT_VALUE}%g" \ 408 | -e "s%[!]TERMUX_API__MESSASGE_OFFSET___DEFAULT_VALUE[!]%${TERMUX_API__MESSASGE_OFFSET___DEFAULT_VALUE}%g" \ 409 | -e "s%[!]TERMUX_API__MESSASGE_TYPE_NAME___DEFAULT_VALUE[!]%${TERMUX_API__MESSASGE_TYPE_NAME___DEFAULT_VALUE}%g" \ 410 | -e "s%[!]TERMUX_API__MESSASGE_TYPE_NAME___SUPPORTED_VALUES[!]%${TERMUX_API__MESSASGE_TYPE_NAME___SUPPORTED_VALUES}%g" 411 | !TERMUX_API__SCRIPT_NAME! command lists SMS conversations and messages. 412 | 413 | Usage: 414 | !TERMUX_API__SCRIPT_NAME! [command_options] 415 | 416 | Available command_options: 417 | [ -h | --help ] Display this help screen. 418 | # [ --version ] Display version. 419 | [ -q | --quiet ] Set log level to 'OFF'. 420 | [ -v | -vv | -vvv | -vvvvv ] 421 | Set log level to 'DEBUG', 'VERBOSE', 422 | 'VVERBOSE' and 'VVVERBOSE'. 423 | [ -c | --conversation-list ] 424 | Show SMS conversations list instead of 425 | messages list. 426 | By default only one SMS message per 427 | conversation is returned unless the 428 | '--conversation-return-multiple-messages' 429 | option is passed. 430 | By default all SMS messages are returned 431 | as a single array without nesting 432 | unless the 433 | '--conversation-return-nested-view' 434 | option is passed. 435 | [ --conversation-limit= ] 436 | The SQL limit for returned SMS 437 | conversations. 438 | [ --conversation-offset= ] 439 | The SQL offset for returned SMS 440 | conversations. 441 | [ --conversation-return-multiple-messages ] 442 | Return multiple SMS messages per 443 | conversation. 444 | [ --conversation-return-nested-view ] 445 | Return a nested object view of 446 | conversations where each conversation 447 | contains an array of SMS messages with 448 | the conversation id as the key. 449 | [ --conversation-return-no-order-reverse ] 450 | Return SMS conversations without 451 | reversing order of conversation sort. 452 | [ --conversation-selection= ] 453 | The SQL selection for returned SMS 454 | conversations. 455 | [ --conversation-sort-order= ] 456 | The SMS conversations sort order as per 457 | SQL 'ORDER BY col1, col2, ... ASC|DESC' 458 | clause. 459 | Default value: 'date DESC'. 460 | [ -f address | --message-address=
] 461 | The address or phone number of the 462 | sender to return SMS messages for. 463 | The '--conversation-selection' option 464 | will override this if passed. 465 | [ -l limit | --message-limit= ] 466 | The limit for returned SMS messages. 467 | Default value: '!TERMUX_API__MESSASGE_LIMIT___DEFAULT_VALUE!'. 468 | [ -o offset | --message-offset= ] 469 | The offset for returned SMS messages. 470 | Default value: '!TERMUX_API__MESSASGE_OFFSET___DEFAULT_VALUE!'. 471 | [ --message-return-no-order-reverse ] 472 | Return SMS messages without reversing 473 | order of message sort. 474 | [ --message-selection= ] 475 | The SQL selection for returned SMS 476 | messages. 477 | [ --message-sort-order= ] 478 | The SMS messages sort order as per 479 | SQL 'ORDER BY col1, col2, ... ASC|DESC' 480 | clause. 481 | Default value: 'date DESC'. 482 | [ -t type | --message-type= ] 483 | The type of returned SMS messages. 484 | Default value: '!TERMUX_API__MESSASGE_TYPE_NAME___DEFAULT_VALUE!'. 485 | Supported values: '!TERMUX_API__MESSASGE_TYPE_NAME___SUPPORTED_VALUES!'. 486 | 487 | 488 | 489 | # Sort and Print Order 490 | 491 | When conversation or messages are queried from the Android database, 492 | first the sort order is applied, and then any offset and limit values 493 | are used to filter the entries. Since the default sort order is 494 | 'date DESC', Android returns the latest dated conversations or 495 | messages first, but the API reverses the order by default so that 496 | the latest entries are printed at the end. If the order should not be 497 | reversed, then pass the respective `--*-return-no-order-reverse` 498 | options. 499 | 500 | 501 | 502 | # Message Type 503 | 504 | The following numbers can be used to match a message 'type' with 505 | the '--message-selection' option. 506 | - all: 0 507 | - inbox: 1 508 | - sent: 2 509 | - draft: 3 510 | - outbox: 4 511 | - failed: 5 512 | - queued: 6 513 | 514 | 515 | 516 | ### Examples 517 | 518 | # Get lastest 10 messages with latest dated message printed at end. 519 | !TERMUX_API__SCRIPT_NAME! 520 | 521 | # Get lastest 10 messages with latest dated message printed at start. 522 | !TERMUX_API__SCRIPT_NAME! --message-return-no-order-reverse 523 | 524 | # Get latest message of any type. 525 | !TERMUX_API__SCRIPT_NAME! --message-limit=1 526 | 527 | # Get latest inbox message. 528 | !TERMUX_API__SCRIPT_NAME! --message-selection="type == 1" \ 529 | --message-limit=1 530 | 531 | # Get latest sent message. 532 | !TERMUX_API__SCRIPT_NAME! --message-selection="type == 2" \ 533 | --message-limit=1 534 | 535 | # Get oldest 10 messages with latest dated message printed at end. 536 | !TERMUX_API__SCRIPT_NAME! --message-sort-order="date ASC" \ 537 | --message-return-no-order-reverse 538 | 539 | # Get the latest inbox message received from the address '666' that 540 | # starts with the text 'Foo '. 541 | !TERMUX_API__SCRIPT_NAME! \ 542 | --message-selection="type == 1 and address == '666' and body LIKE 'Foo %'" \ 543 | --message-limit=1 544 | 545 | # Get the latest sent message sent to the address '666' that 546 | # starts with the text 'Bar '. 547 | !TERMUX_API__SCRIPT_NAME! \ 548 | --message-selection="type == 2 and address == '666' and body LIKE 'Bar %'" \ 549 | --message-limit=1 550 | 551 | 552 | # Get list view for conversations with default conversation limit and 553 | # 1 message per conversastion. 554 | !TERMUX_API__SCRIPT_NAME! --conversation-list 555 | 556 | # Get list view for conversations with default conversation limit and 557 | # 10 messages per conversation. 558 | !TERMUX_API__SCRIPT_NAME! --conversation-list \ 559 | --conversation-return-multiple-messages 560 | 561 | 562 | # Get nested view for conversations with default conversation and 563 | # message limits. 564 | !TERMUX_API__SCRIPT_NAME! --conversation-list \ 565 | --conversation-return-multiple-messages \ 566 | --conversation-return-nested-view 567 | 568 | # Get nested view for latest conversation with latest 5 messages. 569 | !TERMUX_API__SCRIPT_NAME! --conversation-list \ 570 | --conversation-return-multiple-messages \ 571 | --conversation-return-nested-view \ 572 | --conversation-limit=1 \ 573 | --message-limit=5 574 | 575 | # Get nested view for conversations sorted on thread id with highest 576 | # conversation id printed at end. 577 | !TERMUX_API__SCRIPT_NAME! --conversation-list \ 578 | --conversation-return-multiple-messages \ 579 | --conversation-return-nested-view \ 580 | --conversation-sort-order="thread_id ASC" \ 581 | --conversation-return-no-order-reverse 582 | 583 | # Get nested view for conversations for conversation with address 584 | # equal to '666'. 585 | !TERMUX_API__SCRIPT_NAME! --conversation-list \ 586 | --conversation-return-multiple-messages \ 587 | --conversation-return-nested-view \ 588 | --conversation-selection="address == '666'" 589 | 590 | # Get nested view for conversations for conversation with thread id 591 | # equal to '6'. 592 | !TERMUX_API__SCRIPT_NAME! --conversation-list \ 593 | --conversation-return-multiple-messages \ 594 | --conversation-return-nested-view \ 595 | --conversation-selection="thread_id == 6" 596 | 597 | 598 | 599 | **See Also:** 600 | - https://developer.android.com/reference/android/provider/Telephony 601 | - https://developer.android.com/reference/android/provider/Telephony.Sms.Conversations 602 | - https://developer.android.com/reference/android/provider/Telephony.TextBasedSmsColumns 603 | - https://developer.android.com/reference/android/provider/BaseColumns 604 | HELP_EOF 605 | 606 | } 607 | 608 | # If script is sourced, return with success, otherwise call main function. 609 | # - https://stackoverflow.com/a/28776166/14686958 610 | # - https://stackoverflow.com/a/29835459/14686958 611 | if (return 0 2>/dev/null); then 612 | return 0 # EX__SUCCESS 613 | else 614 | termux_api__sms_list__main "$@" 615 | exit $? 616 | fi 617 | -------------------------------------------------------------------------------- /scripts/termux-sms-send.in: -------------------------------------------------------------------------------- 1 | #!@TERMUX_PREFIX@/bin/sh 2 | set -e -u 3 | 4 | SCRIPTNAME=termux-sms-send 5 | show_usage () { 6 | echo "Usage: $SCRIPTNAME -n number[,number2,number3,...] [-s slot] [text]" 7 | echo "Send a SMS message to the specified recipient number(s). The text to send is either supplied as arguments or read from stdin if no arguments are given." 8 | echo " -n number(s) recipient number(s) - separate multiple numbers by commas" 9 | echo " -s slot sim slot to use - silently fails if slot number is invalid or if missing READ_PHONE_STATE permission" 10 | exit 0 11 | } 12 | 13 | RECIPIENTS="" 14 | SLOT="" 15 | while getopts :hn:s: option 16 | do 17 | case "$option" in 18 | h) show_usage;; 19 | n) RECIPIENTS="--esa recipients $OPTARG";; 20 | s) SLOT="--ei slot $OPTARG ";; 21 | ?) echo "$SCRIPTNAME: illegal option -$OPTARG"; exit 1; 22 | esac 23 | done 24 | shift $((OPTIND-1)) 25 | 26 | if [ -z "$RECIPIENTS" ]; then 27 | echo "$SCRIPTNAME: no recipient number given"; exit 1; 28 | fi 29 | 30 | CMD="@TERMUX_PREFIX@/libexec/termux-api SmsSend $RECIPIENTS $SLOT" 31 | if [ $# = 0 ]; then 32 | $CMD 33 | else 34 | echo "$@" | $CMD 35 | fi 36 | -------------------------------------------------------------------------------- /scripts/termux-speech-to-text.in: -------------------------------------------------------------------------------- 1 | #!@TERMUX_PREFIX@/bin/sh 2 | set -e -u 3 | 4 | SCRIPTNAME=termux-speech-to-text 5 | show_usage () { 6 | echo "Usage: $SCRIPTNAME" 7 | echo "Converts speech to text, sending partial matches to stdout." 8 | exit 0 9 | } 10 | 11 | show_progress=false 12 | while getopts :hp option 13 | do 14 | case "$option" in 15 | h) show_usage;; 16 | p) show_progress=true;; 17 | ?) echo "$SCRIPTNAME: illegal option -$OPTARG"; exit 1; 18 | esac 19 | done 20 | shift $((OPTIND-1)) 21 | 22 | if [ $# != 0 ]; then echo "$SCRIPTNAME: too many arguments"; exit 1; fi 23 | 24 | CMD=@TERMUX_PREFIX@/libexec/termux-api 25 | if [ $show_progress = true ]; then 26 | $CMD SpeechToText 27 | else 28 | $CMD SpeechToText | tail -1 29 | fi 30 | -------------------------------------------------------------------------------- /scripts/termux-storage-get.in: -------------------------------------------------------------------------------- 1 | #!@TERMUX_PREFIX@/bin/sh 2 | set -e -u 3 | 4 | SCRIPTNAME=termux-storage-get 5 | show_usage () { 6 | echo "Usage: $SCRIPTNAME output-file" 7 | echo "Request a file from the system and output it to the specified file." 8 | exit 0 9 | } 10 | 11 | 12 | while getopts :h option 13 | do 14 | case "$option" in 15 | h) show_usage;; 16 | ?) echo "$SCRIPTNAME: illegal option -$OPTARG"; exit 1; 17 | esac 18 | done 19 | shift $((OPTIND-1)) 20 | 21 | if [ $# -gt 1 ]; then echo "$SCRIPTNAME: too many arguments"; exit 1; fi 22 | if [ $# -lt 1 ]; then echo "$SCRIPTNAME: no output file specified"; exit 1; fi 23 | 24 | @TERMUX_PREFIX@/libexec/termux-api StorageGet --es file "$(realpath "$1")" 25 | -------------------------------------------------------------------------------- /scripts/termux-telephony-call.in: -------------------------------------------------------------------------------- 1 | #!@TERMUX_PREFIX@/bin/sh 2 | set -e -u 3 | 4 | SCRIPTNAME=termux-telephony-call 5 | show_usage () { 6 | echo "Usage: $SCRIPTNAME " 7 | echo "Call a telephony number." 8 | exit 0 9 | } 10 | 11 | while getopts :h option 12 | do 13 | case "$option" in 14 | h) show_usage;; 15 | ?) echo "$SCRIPTNAME: illegal option -$OPTARG"; exit 1; 16 | esac 17 | done 18 | shift $((OPTIND-1)) 19 | 20 | if [ $# = 1 ]; then 21 | @TERMUX_PREFIX@/libexec/termux-api TelephonyCall --es number "$1" 22 | else 23 | echo "$SCRIPTNAME: No single number to call specified." >&2 24 | exit 1 25 | fi 26 | -------------------------------------------------------------------------------- /scripts/termux-telephony-cellinfo.in: -------------------------------------------------------------------------------- 1 | #!@TERMUX_PREFIX@/bin/sh 2 | set -e -u 3 | 4 | SCRIPTNAME=termux-telephony-cellinfo 5 | show_usage () { 6 | echo "Usage: $SCRIPTNAME" 7 | echo "Get information about all observed cell information from all radios on the device including the primary and neighboring cells." 8 | exit 0 9 | } 10 | 11 | while getopts :h option 12 | do 13 | case "$option" in 14 | h) show_usage;; 15 | ?) echo "$SCRIPTNAME: illegal option -$OPTARG"; exit 1; 16 | esac 17 | done 18 | shift $((OPTIND-1)) 19 | 20 | if [ $# != 0 ]; then echo "$SCRIPTNAME: too many arguments"; exit 1; fi 21 | 22 | @TERMUX_PREFIX@/libexec/termux-api TelephonyCellInfo 23 | -------------------------------------------------------------------------------- /scripts/termux-telephony-deviceinfo.in: -------------------------------------------------------------------------------- 1 | #!@TERMUX_PREFIX@/bin/sh 2 | set -e -u 3 | 4 | SCRIPTNAME=termux-telephony-deviceinfo 5 | show_usage () { 6 | echo "Usage: $SCRIPTNAME" 7 | echo "Get information about the telephony device." 8 | exit 0 9 | } 10 | 11 | while getopts :h option 12 | do 13 | case "$option" in 14 | h) show_usage;; 15 | ?) echo "$SCRIPTNAME: illegal option -$OPTARG"; exit 1; 16 | esac 17 | done 18 | shift $((OPTIND-1)) 19 | 20 | if [ $# != 0 ]; then echo "$SCRIPTNAME: too many arguments"; exit 1; fi 21 | 22 | @TERMUX_PREFIX@/libexec/termux-api TelephonyDeviceInfo 23 | -------------------------------------------------------------------------------- /scripts/termux-toast.in: -------------------------------------------------------------------------------- 1 | #!@TERMUX_PREFIX@/bin/bash 2 | set -e -u 3 | 4 | SCRIPTNAME=termux-toast 5 | show_usage () { 6 | echo "Usage: termux-toast [-b bgcolor] [-c color] [-g gravity] [-s] [text]" 7 | echo "Show text in a Toast (a transient popup)." 8 | echo "The toast text is either supplied as arguments or read from stdin" 9 | echo "if no arguments are given. Arguments will take precedence over stdin." 10 | echo "If toast text is not passed as arguments or with stdin, then there will" 11 | echo "be a 3s delay." 12 | echo " -h show this help" 13 | echo " -b set background color (default: gray)" 14 | echo " -c set text color (default: white)" 15 | echo " -g set position of toast: [top, middle, or bottom] (default: middle)" 16 | echo " -s only show the toast for a short while" 17 | echo "NOTE: color can be a standard name (i.e. red) or 6 / 8 digit hex value (i.e. \"#FF0000\" or \"#FFFF0000\") where order is (AA)RRGGBB. Invalid color will revert to default value" 18 | exit 0 19 | } 20 | 21 | PARAMS="" 22 | while getopts :hsc:b:g: option 23 | do 24 | case "$option" in 25 | h) show_usage;; 26 | s) PARAMS+=" --ez short true";; 27 | c) PARAMS+=" --es text_color $OPTARG";; 28 | b) PARAMS+=" --es background $OPTARG";; 29 | g) PARAMS+=" --es gravity $OPTARG";; 30 | ?) echo "$SCRIPTNAME: illegal option -$OPTARG"; exit 1; 31 | esac 32 | done 33 | shift $((OPTIND-1)) 34 | 35 | CMD="@TERMUX_PREFIX@/libexec/termux-api Toast $PARAMS" 36 | 37 | # If toast text was not passed as an argument, then attempt to read from STDIN with a 3s timeout 38 | # Toast text arguments takes precedence over STDIN 39 | if [ $# = 0 ]; then 40 | set +e; IFS= read -t 3 -r -d '' TOAST_TEXT; set -e; 41 | else 42 | TOAST_TEXT="$*" 43 | fi 44 | 45 | # Trim trailing newlines 46 | TOAST_TEXT="$(echo "$TOAST_TEXT")" 47 | 48 | echo "$TOAST_TEXT" | $CMD 49 | -------------------------------------------------------------------------------- /scripts/termux-torch.in: -------------------------------------------------------------------------------- 1 | #!@TERMUX_PREFIX@/bin/sh 2 | set -e -u 3 | 4 | SCRIPTNAME=termux-torch 5 | 6 | show_usage () { 7 | echo "Usage: $SCRIPTNAME [on | off]" 8 | echo "Toggle LED Torch on device" 9 | exit 1 10 | } 11 | 12 | if [ "$#" -ne 1 ]; then 13 | echo "Illegal param count" 14 | show_usage 15 | fi 16 | 17 | PARAMS="" 18 | 19 | if [ "$1" = on ]; then 20 | PARAMS="--ez enabled true" 21 | elif [ "$1" = off ]; then 22 | PARAMS="--ez enabled false" 23 | else 24 | echo "Illegal parameter: $1" 25 | show_usage 26 | fi 27 | 28 | @TERMUX_PREFIX@/libexec/termux-api Torch $PARAMS 29 | -------------------------------------------------------------------------------- /scripts/termux-tts-engines.in: -------------------------------------------------------------------------------- 1 | #!@TERMUX_PREFIX@/bin/sh 2 | set -e -u 3 | 4 | SCRIPTNAME=termux-tts-engines 5 | show_usage () { 6 | echo "Usage: $SCRIPTNAME" 7 | echo "Get information about the available text-to-speech (TTS) engines. The name of an engine may be given to the termux-tts-speak command using the -e option." 8 | exit 0 9 | } 10 | 11 | while getopts :h option 12 | do 13 | case "$option" in 14 | h) show_usage;; 15 | ?) echo "$SCRIPTNAME: illegal option -$OPTARG"; exit 1; 16 | esac 17 | done 18 | shift $((OPTIND-1)) 19 | 20 | if [ $# != 0 ]; then echo "$SCRIPTNAME: too many arguments"; exit 1; fi 21 | 22 | @TERMUX_PREFIX@/libexec/termux-api TextToSpeech --es engine LIST_AVAILABLE 23 | -------------------------------------------------------------------------------- /scripts/termux-tts-speak.in: -------------------------------------------------------------------------------- 1 | #!@TERMUX_PREFIX@/bin/sh 2 | set -e -u 3 | 4 | SCRIPTNAME=termux-tts-speak 5 | show_usage () { 6 | echo "Usage: $SCRIPTNAME [-e engine] [-l language] [-n region] [-v variant] [-p pitch] [-r rate] [-s stream] [text-to-speak]" 7 | echo "Speak text with a system text-to-speech (TTS) engine. The text to speak is either supplied as arguments or read from stdin if no arguments are given." 8 | echo " -e engine TTS engine to use (see termux-tts-engines)" 9 | echo " -l language language to speak in (may be unsupported by the engine)" 10 | echo " -n region region of language to speak in" 11 | echo " -v variant variant of the language to speak in" 12 | echo " -p pitch pitch to use in speech. 1.0 is the normal pitch," 13 | echo " lower values lower the tone of the synthesized voice," 14 | echo " greater values increase it." 15 | echo " -r rate speech rate to use. 1.0 is the normal speech rate," 16 | echo " lower values slow down the speech" 17 | echo " (0.5 is half the normal speech rate)" 18 | echo " while greater values accelerates it" 19 | echo " (2.0 is twice the normal speech rate)." 20 | echo " -s stream audio stream to use (default:NOTIFICATION), one of:" 21 | echo " ALARM, MUSIC, NOTIFICATION, RING, SYSTEM, VOICE_CALL" 22 | exit 0 23 | } 24 | 25 | PARAMS="" 26 | 27 | while getopts :he:l:n:v:p:r:s: option 28 | do 29 | case "$option" in 30 | h) show_usage;; 31 | e) PARAMS="$PARAMS --es engine $OPTARG";; 32 | l) PARAMS="$PARAMS --es language $OPTARG";; 33 | n) PARAMS="$PARAMS --es region $OPTARG";; 34 | v) PARAMS="$PARAMS --es variant $OPTARG";; 35 | p) PARAMS="$PARAMS --ef pitch $OPTARG";; 36 | r) PARAMS="$PARAMS --ef rate $OPTARG";; 37 | s) PARAMS="$PARAMS --es stream $OPTARG";; 38 | ?) echo "$SCRIPTNAME: illegal option -$OPTARG"; exit 1; 39 | esac 40 | done 41 | shift $((OPTIND-1)) 42 | 43 | CMD="@TERMUX_PREFIX@/libexec/termux-api TextToSpeech $PARAMS" 44 | if [ $# = 0 ]; then 45 | $CMD 46 | else 47 | echo "$@" | $CMD 48 | fi 49 | 50 | -------------------------------------------------------------------------------- /scripts/termux-usb.in: -------------------------------------------------------------------------------- 1 | #!@TERMUX_PREFIX@/bin/bash 2 | set -e -u 3 | 4 | SCRIPTNAME=termux-usb 5 | show_usage () { 6 | echo "Usage: $SCRIPTNAME [-l | [-r] [-E] [-e command] [device | vendorId productId]]" 7 | echo "List or access USB devices. Devices cannot be accessed directly," 8 | echo " only using $SCRIPTNAME." 9 | echo " -l list available devices" 10 | echo " -r show permission request dialog if necessary" 11 | echo " -e command execute the specified command with a file descriptor" 12 | echo " referring to the device as an argument (unless -E" 13 | echo " argument is given)" 14 | echo " -E transfer file descriptor as TERMUX_USB_FD env var" 15 | echo " instead of as command line argument" 16 | exit 0 17 | } 18 | 19 | ACTION="permission" 20 | PARAMS="" 21 | while getopts :hlre:E option 22 | do 23 | case "$option" in 24 | h) show_usage;; 25 | l) ACTION="list";; 26 | r) PARAMS="$PARAMS --ez request true";; 27 | e) ACTION="open"; export TERMUX_CALLBACK="$OPTARG";; 28 | E) export TERMUX_EXPORT_FD=true;; 29 | ?) echo "$SCRIPTNAME: illegal option -$OPTARG"; exit 1; 30 | esac 31 | done 32 | shift $((OPTIND-1)) 33 | 34 | if [ "$ACTION" == "list" ] 35 | then 36 | if [ $# -gt 0 ]; then echo "$SCRIPTNAME: too many arguments"; exit 1; fi 37 | else 38 | if [ $# -lt 1 ]; then 39 | echo "$SCRIPTNAME: missing -l or device path" 40 | exit 1 41 | elif [ $# -eq 1 ]; then 42 | # The device's usbfs path has been provided 43 | PARAMS="$PARAMS --es device $1" 44 | elif [ $# -eq 2 ]; then 45 | # A vendorId and ProductId of the device has been provided 46 | PARAMS="$PARAMS --es vendorId $1" 47 | PARAMS="$PARAMS --es productId $2" 48 | else 49 | echo "$SCRIPTNAME: too many arguments" 50 | exit 1 51 | fi 52 | fi 53 | 54 | CMD="@TERMUX_PREFIX@/libexec/termux-api Usb -a $ACTION $PARAMS" 55 | 56 | if [[ "$ACTION" == "list" ]]; then 57 | $CMD 58 | elif [[ "$ACTION" == "permission" ]]; then 59 | OUTPUT="$($CMD)" 60 | case "$OUTPUT" in 61 | "No such device"|"No such device.") echo "No such device."; exit 1;; 62 | "yes") echo "Permission granted."; exit 0;; 63 | "no"|"Permission denied.") echo "Permission denied."; exit 1;; 64 | "Permission request timeout.") echo "Permission request timeout."; exit 1;; 65 | *) printf "%s\n" "$OUTPUT"; exit 0;; 66 | esac 67 | elif [[ "$ACTION" == "open" ]]; then 68 | OUTPUT="$($CMD)" 69 | case "$OUTPUT" in 70 | "No such device"|"No such device.") echo "No such device."; exit 1;; 71 | "No permission"|"Permission denied.") echo "Permission denied."; exit 1;; 72 | "Permission request timeout.") echo "Permission request timeout."; exit 1;; 73 | "Failed to open device"|"Open device failed.") echo "Open device failed."; exit 1;; 74 | *) printf "%s\n" "$OUTPUT"; exit 0;; 75 | esac 76 | fi 77 | 78 | exit 0 79 | -------------------------------------------------------------------------------- /scripts/termux-vibrate.in: -------------------------------------------------------------------------------- 1 | #!@TERMUX_PREFIX@/bin/sh 2 | set -e -u 3 | 4 | SCRIPTNAME=termux-vibrate 5 | show_usage () { 6 | echo "Usage: $SCRIPTNAME [-d duration] [-f]" 7 | echo "Vibrate the device." 8 | echo " -d duration the duration to vibrate in ms (default:1000)" 9 | echo " -f force vibration even in silent mode" 10 | exit 0 11 | } 12 | 13 | PARAMS="" 14 | 15 | while getopts :hfd: option 16 | do 17 | case "$option" in 18 | h) show_usage;; 19 | d) PARAMS="$PARAMS --ei duration_ms $OPTARG";; 20 | f) PARAMS="$PARAMS --ez force true";; 21 | ?) echo "$SCRIPTNAME: illegal option -$OPTARG"; exit 1; 22 | esac 23 | done 24 | shift $((OPTIND-1)) 25 | 26 | if [ $# != 0 ]; then echo "$SCRIPTNAME: too many arguments"; exit 1; fi 27 | 28 | @TERMUX_PREFIX@/libexec/termux-api Vibrate $PARAMS 29 | -------------------------------------------------------------------------------- /scripts/termux-volume.in: -------------------------------------------------------------------------------- 1 | #!@TERMUX_PREFIX@/bin/bash 2 | set -e -u 3 | 4 | SCRIPTNAME=termux-volume 5 | show_usage () { 6 | echo "Usage: $SCRIPTNAME stream volume" 7 | echo "Change volume of audio stream" 8 | echo "Valid audio streams are: alarm, music, notification, ring, system, call" 9 | echo "Call w/o arguments to show information about each audio stream" 10 | exit 0 11 | } 12 | 13 | ARGS="" 14 | 15 | # If we have arguments, we must have 2 16 | # Otherwise we will just return JSON info to user 17 | if [ $# -gt 0 ]; then 18 | if [ $# -ne 2 ]; then 19 | echo "Invalid argument count" 20 | show_usage 21 | fi 22 | 23 | if ! [[ $2 =~ ^[0-9]+$ ]]; then 24 | echo "ERROR: Volume must be a number" 25 | show_usage 26 | fi 27 | ARGS="-a set-volume --es stream $1 --ei volume $2" 28 | fi 29 | 30 | @TERMUX_PREFIX@/libexec/termux-api Volume $ARGS 31 | -------------------------------------------------------------------------------- /scripts/termux-wallpaper.in: -------------------------------------------------------------------------------- 1 | #!@TERMUX_PREFIX@/bin/bash 2 | 3 | set -e 4 | 5 | SCRIPTNAME=termux-wallpaper 6 | show_usage () { 7 | echo "Change wallpaper on your device" 8 | echo 9 | echo "Usage: $SCRIPTNAME [options]" 10 | echo "-h show this help" 11 | echo "-f set wallpaper from file" 12 | echo "-u set wallpaper from url resource" 13 | echo "-l set wallpaper for lockscreen (Nougat and later)" 14 | exit 1 15 | } 16 | 17 | OPT_LS="" 18 | OPT_FILE="" 19 | OPT_URL="" 20 | 21 | while getopts :h,:l,f:,u: option 22 | do 23 | case "$option" in 24 | h) show_usage ;; 25 | l) OPT_LS="true" ;; 26 | f) path="$(realpath "$OPTARG")" 27 | if [[ ! -f "$path" ]]; then 28 | echo "$SCRIPTNAME: $path is not a file!" 29 | exit 1 30 | fi 31 | OPT_FILE="$path" ;; 32 | u) OPT_URL="$OPTARG" ;; 33 | ?) echo "$SCRIPTNAME: illegal option -$OPTARG"; exit 1 ;; 34 | esac 35 | done 36 | 37 | if [[ -z "$OPT_FILE""$OPT_URL" ]]; then 38 | echo "$SCRIPTNAME: you must specify either -f or -u" 39 | exit 1 40 | elif [[ -n "$OPT_FILE" ]] && [[ -n "$OPT_URL" ]]; then 41 | echo "$SCRIPTNAME: you must specify either -f or -u, but not both" 42 | exit 1 43 | fi 44 | 45 | shift $((OPTIND - 1)) 46 | if [ $# != 0 ]; then echo "$SCRIPTNAME: too many arguments"; exit 1; fi 47 | 48 | set -- 49 | [ -n "$OPT_LS" ] && set -- "$@" --ez lockscreen "$OPT_LS" 50 | [ -n "$OPT_FILE" ] && set -- "$@" --es file "$OPT_FILE" 51 | [ -n "$OPT_URL" ] && set -- "$@" --es url "$OPT_URL" 52 | @TERMUX_PREFIX@/libexec/termux-api Wallpaper "$@" 53 | -------------------------------------------------------------------------------- /scripts/termux-wifi-connectioninfo.in: -------------------------------------------------------------------------------- 1 | #!@TERMUX_PREFIX@/bin/sh 2 | set -e -u 3 | 4 | SCRIPTNAME=termux-wifi-connectioninfo 5 | show_usage () { 6 | echo "Usage: $SCRIPTNAME" 7 | echo "Get information about the current wifi connection." 8 | exit 0 9 | } 10 | 11 | while getopts :h option 12 | do 13 | case "$option" in 14 | h) show_usage;; 15 | ?) echo "$SCRIPTNAME: illegal option -$OPTARG"; exit 1; 16 | esac 17 | done 18 | shift $((OPTIND-1)) 19 | 20 | if [ $# != 0 ]; then echo "$SCRIPTNAME: too many arguments"; exit 1; fi 21 | 22 | @TERMUX_PREFIX@/libexec/termux-api WifiConnectionInfo 23 | -------------------------------------------------------------------------------- /scripts/termux-wifi-enable.in: -------------------------------------------------------------------------------- 1 | #!@TERMUX_PREFIX@/bin/sh 2 | set -e -u 3 | 4 | SCRIPTNAME=termux-wifi-enable 5 | 6 | show_usage () { 7 | echo "Usage: $SCRIPTNAME [true | false]" 8 | echo "Toggle Wi-Fi On/Off" 9 | exit 1 10 | } 11 | 12 | if [ "$#" -ne 1 ]; then 13 | show_usage 14 | fi 15 | 16 | case $1 in 17 | true|false);; 18 | *) show_usage;; 19 | esac 20 | 21 | @TERMUX_PREFIX@/libexec/termux-api WifiEnable --ez enabled "$1" 22 | -------------------------------------------------------------------------------- /scripts/termux-wifi-scaninfo.in: -------------------------------------------------------------------------------- 1 | #!@TERMUX_PREFIX@/bin/sh 2 | set -e -u 3 | 4 | SCRIPTNAME=termux-wifi-scaninfo 5 | show_usage () { 6 | echo "Usage: $SCRIPTNAME" 7 | echo "Get information about the last wifi scan." 8 | exit 0 9 | } 10 | 11 | while getopts :h option 12 | do 13 | case "$option" in 14 | h) show_usage;; 15 | ?) echo "$SCRIPTNAME: illegal option -$OPTARG"; exit 1; 16 | esac 17 | done 18 | shift $((OPTIND-1)) 19 | 20 | if [ $# != 0 ]; then echo "$SCRIPTNAME: too many arguments"; exit 1; fi 21 | 22 | @TERMUX_PREFIX@/libexec/termux-api WifiScanInfo 23 | -------------------------------------------------------------------------------- /termux-api-broadcast.c: -------------------------------------------------------------------------------- 1 | /* termux-api.c - helper binary for calling termux api classes 2 | * Usage: termux-api ${API_METHOD} ${ADDITIONAL_FLAGS} 3 | * This executes 4 | * am broadcast com.termux.api/.TermuxApiReceiver \ 5 | * --es socket_input ${INPUT_SOCKET} \ 6 | * --es socket_output ${OUTPUT_SOCKET} \ 7 | * --es api_method ${API_METHOD} \ 8 | * ${ADDITIONAL_FLAGS} 9 | * where ${INPUT_SOCKET} and ${OUTPUT_SOCKET} are addresses to linux 10 | * abstract namespace sockets, used to pass on stdin to the java 11 | * implementation and pass back output from java to stdout. 12 | */ 13 | 14 | #include "termux-api.h" 15 | 16 | int main(int argc, char** argv) { 17 | /* Run the api command */ 18 | int fd = run_api_command(argc, argv); 19 | 20 | if (fd != -1) { exec_callback(fd); } 21 | 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /termux-api.c: -------------------------------------------------------------------------------- 1 | #define _POSIX_SOURCE 2 | #define _GNU_SOURCE 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #ifdef __ANDROID__ 20 | #include 21 | #endif 22 | 23 | #include "termux-api.h" 24 | 25 | #define TERMUX_API_PACKAGE_VERSION "0.59.1" 26 | 27 | #ifndef PREFIX 28 | # define PREFIX "/data/data/com.termux/files/usr" 29 | #endif 30 | 31 | #define LISTEN_SOCKET_ADDRESS "com.termux.api://listen" 32 | 33 | /* passes the arguments to the plugin via the unix socket, falling 34 | * back to exec_am_broadcast() if that doesn't work 35 | */ 36 | _Noreturn void contact_plugin(int argc, char** argv, 37 | char* input_address_string, 38 | char* output_address_string) 39 | { 40 | // Redirect stdout to /dev/null (but leave stderr open): 41 | close(STDOUT_FILENO); 42 | open("/dev/null", O_RDONLY); 43 | // Close stdin: 44 | close(STDIN_FILENO); 45 | 46 | // ignore SIGPIPE, so am will be called when the connection is closed unexpectedly 47 | struct sigaction sigpipe_action = { 48 | .sa_handler = SIG_IGN, 49 | .sa_flags = 0 50 | }; 51 | sigaction(SIGPIPE, &sigpipe_action, NULL); 52 | 53 | // Try to connect over the listen socket first if running on Android `< 14`. 54 | // On Android `>= 14`, if termux-api app process was started previously 55 | // and it started the socket server, but later Android froze the 56 | // process, the socket will still be connectable, but no response 57 | // will be received until the app process is unfrozen agin and 58 | // `read()` call below will hang indefinitely until that happens, 59 | // so use legacy `am broadcast` command, which will also unfreeze 60 | // the app process to deliver the intent. 61 | // - https://github.com/termux/termux-api/issues/638#issuecomment-1813233924 62 | int listenfd = -1; 63 | #ifdef __ANDROID__ 64 | if (android_get_device_api_level() < 34) { 65 | listenfd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0); 66 | } 67 | #endif 68 | if (listenfd != -1) { 69 | struct sockaddr_un listen_addr = { .sun_family = AF_UNIX }; 70 | memcpy(listen_addr.sun_path+1, LISTEN_SOCKET_ADDRESS, strlen(LISTEN_SOCKET_ADDRESS)); 71 | if (connect(listenfd, (struct sockaddr*) &listen_addr, sizeof(sa_family_t) + strlen(LISTEN_SOCKET_ADDRESS) + 1) == 0) { 72 | socklen_t optlen = sizeof(struct ucred); 73 | // check the uid to see if the socket is actually provided by the plugin 74 | struct ucred cred; 75 | if (getsockopt(listenfd, SOL_SOCKET, SO_PEERCRED, &cred, &optlen) == 0 && cred.uid == getuid()) { 76 | 77 | const char insock_str[] = "--es socket_input \""; 78 | const char outsock_str[] = "--es socket_output \""; 79 | const char method_str[] = "--es api_method \""; 80 | 81 | int len = 0; 82 | len += sizeof(insock_str)-1 + strlen(output_address_string)+2; 83 | len += sizeof(outsock_str)-1 + strlen(input_address_string)+2; 84 | len += sizeof(method_str)-1 + strlen(argv[1])+2; 85 | for (int i = 2; i 0) { 185 | int ret = send(listenfd, transmit, totransmit, 0); 186 | if (ret == -1) { 187 | err = true; 188 | break; 189 | } 190 | totransmit -= ret; 191 | } 192 | 193 | // transmit the argument list 194 | if (! err) { 195 | totransmit = len; 196 | transmit = buffer; 197 | while (totransmit > 0) { 198 | int ret = send(listenfd, transmit, totransmit, 0); 199 | if (ret == -1) { 200 | err = true; 201 | break; 202 | } 203 | totransmit -= ret; 204 | } 205 | } 206 | 207 | if (! err) { 208 | char readbuffer[100]; 209 | int ret; 210 | bool first = true; 211 | err = true; 212 | while ((ret = read(listenfd, readbuffer, 99)) > 0) { 213 | // if a single null byte is received as the first message, the call was successful 214 | if (ret == 1 && readbuffer[0] == 0 && first) { 215 | err = false; 216 | break; 217 | } 218 | // otherwise it's an error message 219 | readbuffer[ret] = '\0'; 220 | // printing out the error is good for debug purposes, but feel free to disable this 221 | fprintf(stderr, "%s", readbuffer); 222 | fflush(stderr); 223 | first = false; 224 | } 225 | } 226 | 227 | // if everything went well, there is no need to call am 228 | if (! err) { 229 | exit(0); 230 | } 231 | } 232 | } 233 | } 234 | 235 | exec_am_broadcast(argc, argv, input_address_string, output_address_string); 236 | } 237 | 238 | // Function which execs "am broadcast ..". 239 | _Noreturn void exec_am_broadcast(int argc, char** argv, 240 | char* input_address_string, 241 | char* output_address_string) 242 | { 243 | // Redirect stdout to /dev/null (but leave stderr open): 244 | close(STDOUT_FILENO); 245 | open("/dev/null", O_RDONLY); 246 | // Close stdin: 247 | close(STDIN_FILENO); 248 | 249 | const int child_pre_argc = 14; 250 | const int child_post_argc = argc - 1; // Except `argv[0]`. 251 | const int child_argc = child_pre_argc + child_post_argc; 252 | 253 | size_t child_argv_size = (sizeof(char*)) * (child_argc + 1); // Including trailing `NULL`. 254 | // Do not directly cast, otherwise can trigger null pointer dereference if `NULL` is returned. 255 | void* result = malloc(child_argv_size); 256 | if (result == NULL) { 257 | perror("malloc failed for am child args"); 258 | exit(1); 259 | } 260 | 261 | char **child_argv = (char **) result; 262 | 263 | child_argv[0] = "am"; 264 | child_argv[1] = "broadcast"; 265 | child_argv[2] = "--user"; 266 | child_argv[3] = "0"; 267 | child_argv[4] = "-n"; 268 | child_argv[5] = "com.termux.api/.TermuxApiReceiver"; 269 | child_argv[6] = "--es"; 270 | // Input/output are reversed for the java process (our output is its input): 271 | child_argv[7] = "socket_input"; 272 | child_argv[8] = output_address_string; 273 | child_argv[9] = "--es"; 274 | child_argv[10] = "socket_output"; 275 | child_argv[11] = input_address_string; 276 | child_argv[12] = "--es"; 277 | child_argv[13] = "api_method"; 278 | 279 | // Copy the remaining arguments except `argv[0]`, `argv[1]` should be `api_method` extra value: 280 | memcpy(child_argv + child_pre_argc, argv + 1, child_post_argc * sizeof(char*)); 281 | 282 | // End with NULL: 283 | child_argv[child_argc] = NULL; 284 | 285 | // Use an a executable taking care of PATH and LD_LIBRARY_PATH: 286 | execv(PREFIX "/bin/am", child_argv); 287 | 288 | // We should not reach here, if we do, then free memory we malloc'ed 289 | free(child_argv); 290 | perror("execv(\"" PREFIX "/bin/am\")"); 291 | exit(1); 292 | } 293 | 294 | _Noreturn void exec_callback(int fd) 295 | { 296 | char *fds; 297 | if (asprintf(&fds, "%d", fd) == -1) 298 | perror("asprintf"); 299 | 300 | /* TERMUX_EXPORT_FD and TERMUX_USB_FD are (currently) specific for 301 | termux-usb, so there's some room for improvement here (this 302 | function should be generic) */ 303 | char errmsg[256]; 304 | char *export_to_env = getenv("TERMUX_EXPORT_FD"); 305 | if (export_to_env && strncmp(export_to_env, "true", 4) == 0) { 306 | if (setenv("TERMUX_USB_FD", fds, true) == -1) 307 | perror("setenv"); 308 | execl(PREFIX "/libexec/termux-callback", "termux-callback", NULL); 309 | sprintf(errmsg, "execl(\"" PREFIX "/libexec/termux-callback\")"); 310 | } else { 311 | execl(PREFIX "/libexec/termux-callback", "termux-callback", fds, NULL); 312 | sprintf(errmsg, "execl(\"" PREFIX "/libexec/termux-callback\", %s)", fds); 313 | } 314 | perror(errmsg); 315 | exit(1); 316 | } 317 | 318 | void generate_uuid(char* str) { 319 | sprintf(str, "%x%x-%x-%x-%x-%x%x%x", 320 | /* 64-bit Hex number */ 321 | arc4random(), arc4random(), 322 | /* 32-bit Hex number */ 323 | (uint32_t) getpid(), 324 | /* 32-bit Hex number of the form 4xxx (4 is the UUID version) */ 325 | ((arc4random() & 0x0fff) | 0x4000), 326 | /* 32-bit Hex number in the range [0x8000, 0xbfff] */ 327 | arc4random() % 0x3fff + 0x8000, 328 | /* 96-bit Hex number */ 329 | arc4random(), arc4random(), arc4random()); 330 | } 331 | 332 | // Thread function which reads from stdin and writes to socket. 333 | void* transmit_stdin_to_socket(void* arg) { 334 | int output_server_socket = *((int*) arg); 335 | struct sockaddr_un remote_addr; 336 | socklen_t addrlen = sizeof(remote_addr); 337 | int output_client_socket = accept(output_server_socket, 338 | (struct sockaddr*) &remote_addr, 339 | &addrlen); 340 | 341 | ssize_t len; 342 | char buffer[1024]; 343 | while (len = read(STDIN_FILENO, &buffer, sizeof(buffer)), len > 0) { 344 | if (write(output_client_socket, buffer, len) < 0) break; 345 | } 346 | // Close output socket on end of input: 347 | close(output_client_socket); 348 | return NULL; 349 | } 350 | 351 | // Main thread function which reads from input socket and writes to stdout. 352 | int transmit_socket_to_stdout(int input_socket_fd) { 353 | ssize_t len; 354 | char buffer[1024]; 355 | char cbuf[256]; 356 | struct iovec io = { .iov_base = buffer, .iov_len = sizeof(buffer) }; 357 | struct msghdr msg = { 0 }; 358 | int fd = -1; // An optional file descriptor received through the socket 359 | msg.msg_iov = &io; 360 | msg.msg_iovlen = 1; 361 | msg.msg_control = cbuf; 362 | msg.msg_controllen = sizeof(cbuf); 363 | while ((len = recvmsg(input_socket_fd, &msg, 0)) > 0) { 364 | struct cmsghdr * cmsg = CMSG_FIRSTHDR(&msg); 365 | if (cmsg && cmsg->cmsg_len == CMSG_LEN(sizeof(int))) { 366 | if (cmsg->cmsg_type == SCM_RIGHTS) { 367 | fd = *((int *) CMSG_DATA(cmsg)); 368 | } 369 | } 370 | // A file descriptor must be accompanied by a non-empty message, 371 | // so we use "@" when we don't want any output. 372 | if (fd != -1 && len == 1 && buffer[0] == '@') { len = 0; } 373 | write(STDOUT_FILENO, buffer, len); 374 | msg.msg_controllen = sizeof(cbuf); 375 | } 376 | if (len < 0) perror("recvmsg()"); 377 | return fd; 378 | } 379 | 380 | int run_api_command(int argc, char **argv) { 381 | // If only `--version` argument is passed 382 | if (argc == 2 && strcmp(argv[1], "--version") == 0) { 383 | fprintf(stdout, "%s\n", TERMUX_API_PACKAGE_VERSION); 384 | fflush(stdout); 385 | exit(0); 386 | } 387 | 388 | // Do not transform children into zombies when they terminate: 389 | struct sigaction sigchld_action = { 390 | .sa_handler = SIG_DFL, 391 | .sa_flags = SA_RESTART | SA_NOCLDSTOP | SA_NOCLDWAIT 392 | }; 393 | sigaction(SIGCHLD, &sigchld_action, NULL); 394 | 395 | char input_addr_str[100]; // This program reads from it. 396 | char output_addr_str[100]; // This program writes to it. 397 | 398 | generate_uuid(input_addr_str); 399 | generate_uuid(output_addr_str); 400 | 401 | struct sockaddr_un input_addr = { .sun_family = AF_UNIX }; 402 | struct sockaddr_un output_addr = { .sun_family = AF_UNIX }; 403 | // Leave struct sockaddr_un.sun_path[0] as 0 and use the UUID 404 | // string as abstract linux namespace: 405 | strncpy(&input_addr.sun_path[1], input_addr_str, strlen(input_addr_str)); 406 | strncpy(&output_addr.sun_path[1], output_addr_str, strlen(output_addr_str)); 407 | 408 | int input_server_socket = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0); 409 | if (input_server_socket == -1) { 410 | perror("socket()"); 411 | return -1; 412 | } 413 | int output_server_socket = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0); 414 | if (output_server_socket == -1) { 415 | perror("socket()"); 416 | return -1; 417 | } 418 | 419 | int ret; 420 | ret = bind(input_server_socket, (struct sockaddr*) &input_addr, 421 | sizeof(sa_family_t) + strlen(input_addr_str) + 1); 422 | if (ret == -1) { 423 | perror("bind(input)"); 424 | return ret; 425 | } 426 | 427 | ret = bind(output_server_socket, (struct sockaddr*) &output_addr, 428 | sizeof(sa_family_t) + strlen(output_addr_str) + 1); 429 | if (ret == -1) { 430 | perror("bind(output)"); 431 | return ret; 432 | } 433 | 434 | if (listen(input_server_socket, 1) == -1) { 435 | perror("listen()"); 436 | return -1; 437 | } 438 | 439 | if (listen(output_server_socket, 1) == -1) { 440 | perror("listen()"); 441 | return -1; 442 | } 443 | 444 | pid_t fork_result = fork(); 445 | if (fork_result == -1) { 446 | perror("fork()"); 447 | return -1; 448 | } else if (fork_result == 0) 449 | contact_plugin(argc, argv, input_addr_str, output_addr_str); 450 | 451 | struct sockaddr_un remote_addr; 452 | socklen_t addrlen = sizeof(remote_addr); 453 | int input_client_socket = accept(input_server_socket, 454 | (struct sockaddr*) &remote_addr, 455 | &addrlen); 456 | 457 | pthread_t transmit_thread; 458 | pthread_create(&transmit_thread, NULL, transmit_stdin_to_socket, 459 | &output_server_socket); 460 | 461 | /* Device has been opened, time to actually get the fd */ 462 | int fd = transmit_socket_to_stdout(input_client_socket); 463 | close(input_client_socket); 464 | return fd; 465 | } 466 | -------------------------------------------------------------------------------- /termux-api.h: -------------------------------------------------------------------------------- 1 | #ifndef TERMUX_API_H 2 | #define TERMUX_API_H 3 | 4 | #include 5 | 6 | #if defined(__cplusplus) 7 | extern "C" { 8 | #endif 9 | 10 | _Noreturn void exec_am_broadcast(int, char**, char*, char*); 11 | _Noreturn void contact_plugin(int, char**, char*, char*); 12 | _Noreturn void exec_callback(int); 13 | void generate_uuid(char*); 14 | void* transmit_stdin_to_socket(void*); 15 | int transmit_socket_to_stdout(int); 16 | int run_api_command(int, char**); 17 | 18 | #if defined(__cplusplus) 19 | } 20 | #endif 21 | 22 | #endif /* TERMUX_API_H */ 23 | -------------------------------------------------------------------------------- /termux-callback.in: -------------------------------------------------------------------------------- 1 | #!@TERMUX_PREFIX@/bin/bash 2 | set -e -u 3 | $TERMUX_CALLBACK "$@" 4 | --------------------------------------------------------------------------------