diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4473321 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +termux-api diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..ce7868e --- /dev/null +++ b/Makefile @@ -0,0 +1,11 @@ +CFLAGS += -std=c11 -Wall -Wextra -pedantic -Werror +PREFIX ?= /data/data/com.termux/files/usr + +termux-api: termux-api.c + +install: termux-api + mkdir -p $(PREFIX)/bin/ $(PREFIX)/libexec/ + install termux-api $(PREFIX)/libexec/ + install scripts/* $(PREFIX)/bin/ + +.PHONY: install diff --git a/scripts/termux-battery-status b/scripts/termux-battery-status new file mode 100755 index 0000000..bbd8b64 --- /dev/null +++ b/scripts/termux-battery-status @@ -0,0 +1,22 @@ +#!/bin/sh +set -e -u + +SCRIPTNAME=termux-battery-status +show_usage () { + echo "Usage: $SCRIPTNAME" + echo "Get the status of the device battery." + exit 0 +} + +while getopts :h option +do + case "$option" in + h) show_usage;; + ?) echo "$SCRIPTNAME: illegal option -$OPTARG"; exit 1; + esac +done +shift $(($OPTIND-1)) + +if [ $# != 0 ]; then echo "$SCRIPTNAME: too many arguments"; exit 1; fi + +@TERMUX_API@ BatteryStatus diff --git a/scripts/termux-camera-info b/scripts/termux-camera-info new file mode 100755 index 0000000..daaec08 --- /dev/null +++ b/scripts/termux-camera-info @@ -0,0 +1,22 @@ +#!/bin/sh +set -e -u + +SCRIPTNAME=termux-camera-info +show_usage () { + echo "Usage: $SCRIPTNAME" + echo "Get information about device camera(s)." + exit 0 +} + +while getopts :h option +do + case "$option" in + h) show_usage;; + ?) echo "$SCRIPTNAME: illegal option -$OPTARG"; exit 1; + esac +done +shift $(($OPTIND-1)) + +if [ $# != 0 ]; then echo "$SCRIPTNAME: too many arguments"; exit 1; fi + +@TERMUX_API@ CameraInfo diff --git a/scripts/termux-camera-photo b/scripts/termux-camera-photo new file mode 100755 index 0000000..4d3051b --- /dev/null +++ b/scripts/termux-camera-photo @@ -0,0 +1,30 @@ +#!/bin/sh +set -e -u + +SCRIPTNAME=termux-camera-photo +show_usage () { + echo "Usage: termux-camera-photo [-c camera-id] output-file" + echo "Take a photo and save it to a file in JPEG format." + echo " -c camera-id ID of the camera to use (see termux-camera-info), default: 0" + exit 0 +} + + +PARAMS="" +while getopts :hc: option +do + case "$option" in + h) show_usage;; + c) PARAMS="--es camera $OPTARG";; + ?) echo "$SCRIPTNAME: illegal option -$OPTARG"; exit 1; + esac +done +shift $(($OPTIND-1)) + +if [ $# = 0 ]; then echo "$SCRIPTNAME: missing file argument"; exit 1; fi +if [ $# != 1 ]; then echo "$SCRIPTNAME: too many arguments"; exit 1; fi + +touch $1 +PARAMS="$PARAMS --es file `realpath $1`" + +@TERMUX_API@ CameraPhoto $PARAMS diff --git a/scripts/termux-clipboard-get b/scripts/termux-clipboard-get new file mode 100755 index 0000000..de5e448 --- /dev/null +++ b/scripts/termux-clipboard-get @@ -0,0 +1,22 @@ +#!/bin/sh +set -e -u + +SCRIPTNAME=termux-clipboard-get +show_usage () { + echo "Usage: $SCRIPTNAME" + echo "Get the system clipboard text." + exit 0 +} + +while getopts :h option +do + case "$option" in + h) show_usage;; + ?) echo "$SCRIPTNAME: illegal option -$OPTARG"; exit 1; + esac +done +shift $(($OPTIND-1)) + +if [ $# != 0 ]; then echo "$SCRIPTNAME: too many arguments"; exit 1; fi + +@TERMUX_API@ Clipboard diff --git a/scripts/termux-clipboard-set b/scripts/termux-clipboard-set new file mode 100755 index 0000000..c2a3a84 --- /dev/null +++ b/scripts/termux-clipboard-set @@ -0,0 +1,26 @@ +#!/bin/sh +set -e -u + +SCRIPTNAME=termux-clipboard-set +show_usage () { + echo "Usage: $SCRIPTNAME [text]" + echo "Set the system clipboard text. The text to set is either supplied as arguments or read from stdin if no arguments are given." + exit 0 +} + +while getopts :h option +do + case "$option" in + h) show_usage;; + ?) echo "$SCRIPTNAME: illegal option -$OPTARG"; exit 1; + esac +done +shift $(($OPTIND-1)) + +CMD="@TERMUX_API@ Clipboard -e api_version 2 --ez set true" +if [ $# = 0 ]; then + $CMD +else + echo $@ | $CMD +fi + diff --git a/scripts/termux-contact-list b/scripts/termux-contact-list new file mode 100755 index 0000000..7679ffe --- /dev/null +++ b/scripts/termux-contact-list @@ -0,0 +1,22 @@ +#!/bin/sh +set -e -u + +SCRIPTNAME=termux-contact-list +show_usage () { + echo "Usage: $SCRIPTNAME" + echo "List all contacts." + exit 0 +} + +while getopts :h option +do + case "$option" in + h) show_usage;; + ?) echo "$SCRIPTNAME: illegal option -$OPTARG"; exit 1; + esac +done +shift $(($OPTIND-1)) + +if [ $# != 0 ]; then echo "$SCRIPTNAME: too many arguments"; exit 1; fi + +@TERMUX_API@ ContactList diff --git a/scripts/termux-dialog b/scripts/termux-dialog new file mode 100755 index 0000000..4f662d8 --- /dev/null +++ b/scripts/termux-dialog @@ -0,0 +1,43 @@ +#!/bin/sh +set -e -u + +SCRIPTNAME=termux-dialog +show_usage () { + echo "Usage: $SCRIPTNAME [-i hint] [-m] [-p] [-t title]" + echo "Show a text entry dialog." + echo " -i hint the input hint to show when the input is empty" + echo " -m use a textarea with multiple lines instead of a single" + echo " -p enter the input as a password" + echo " -t title the title to show for the input prompt" + exit 0 +} + +PARAMS="" + +ARG_I="" +OPT_I="" +ARG_M="" +ARG_P="" +ARG_T="" +OPT_T="" + +while getopts :hi:mpt: option +do + case "$option" in + h) show_usage;; + i) ARG_I="--es input_hint"; OPT_I="$OPTARG";; + m) ARG_M="--ez multiple_lines true";; + p) ARG_P="--es input_type password";; + t) ARG_T="--es input_title"; OPT_T="$OPTARG";; + ?) echo "$SCRIPTNAME: illegal option -$OPTARG"; exit 1; + esac +done +shift $(($OPTIND-1)) + +if [ $# != 0 ]; then echo "$SCRIPTNAME: too many arguments"; exit 1; fi + +set -- $ARG_M $ARG_P +if [ -n "$ARG_I" ]; then set -- "$@" $ARG_I "$OPT_I"; fi +if [ -n "$ARG_T" ]; then set -- "$@" $ARG_T "$OPT_T"; fi + +@TERMUX_API@ Dialog "$@" diff --git a/scripts/termux-download b/scripts/termux-download new file mode 100755 index 0000000..88471e3 --- /dev/null +++ b/scripts/termux-download @@ -0,0 +1,39 @@ +#!/bin/sh +set -e -u + +SCRIPTNAME=termux-download +show_usage () { + echo "Usage: $SCRIPTNAME [-d description] [-t title] url-to-download" + echo "Download a resource using the system download manager." + echo " -d description description for the download request notification" + echo " -t title title for the download request notification" + exit 0 +} + +ARG_D="" +OPT_D="" +ARG_T="" +OPT_T="" + +while getopts :hd:t: option +do + case "$option" in + h) show_usage;; + d) ARG_D="--es description"; OPT_D="$OPTARG";; + t) ARG_T="--es title"; OPT_T="$OPTARG";; + ?) echo "$SCRIPTNAME: illegal option -$OPTARG"; exit 1; + esac +done +shift $(($OPTIND-1)) + +if [ $# -lt 1 ]; then echo "$SCRIPTNAME: no url specified"; exit 1; fi +if [ $# -gt 1 ]; then echo "$SCRIPTNAME: too many arguments"; exit 1; fi + +URL_TO_DOWNLOAD="$1" + +set -- +if [ -n "$ARG_D" ]; then set -- "$@" $ARG_D "$OPT_D"; fi +if [ -n "$ARG_T" ]; then set -- "$@" $ARG_T "$OPT_T"; fi +set -- "$@" $URL_TO_DOWNLOAD + +@TERMUX_API@ Download "$@" diff --git a/scripts/termux-infrared-frequencies b/scripts/termux-infrared-frequencies new file mode 100755 index 0000000..0442e28 --- /dev/null +++ b/scripts/termux-infrared-frequencies @@ -0,0 +1,22 @@ +#!/bin/sh +set -e -u + +SCRIPTNAME=termux-infrared-frequencies +show_usage () { + echo "Usage: $SCRIPTNAME" + echo "Query the infrared transmitter's supported carrier frequencies." + exit 0 +} + +while getopts :h option +do + case "$option" in + h) show_usage;; + ?) echo "$SCRIPTNAME: illegal option -$OPTARG"; exit 1; + esac +done +shift $(($OPTIND-1)) + +if [ $# != 0 ]; then echo "$SCRIPTNAME: too many arguments"; exit 1; fi + +@TERMUX_API@ InfraredFrequencies diff --git a/scripts/termux-infrared-transmit b/scripts/termux-infrared-transmit new file mode 100755 index 0000000..404faa3 --- /dev/null +++ b/scripts/termux-infrared-transmit @@ -0,0 +1,28 @@ +#!/bin/sh +set -e -u + +SCRIPTNAME=termux-infrared-transmit +show_usage () { + echo "Usage: $SCRIPTNAME -f frequency pattern" + 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." + echo " -f frequency IR carrier frequency in Hertz" + exit 0 +} + +FREQUENCY="" +while getopts :hf: option +do + case "$option" in + h) show_usage;; + f) FREQUENCY="--ei frequency $OPTARG";; + ?) echo "$SCRIPTNAME: illegal option -$OPTARG"; exit 1; + esac +done +shift $(($OPTIND-1)) + +if [ -z "$FREQUENCY" ]; then echo "$SCRIPTNAME: No frequency specified"; exit 1; fi + +if [ $# -lt 1 ]; then echo "$SCRIPTNAME: too few arguments"; exit 1; fi +if [ $# -gt 1 ]; then echo "$SCRIPTNAME: too many arguments"; exit 1; fi + +@TERMUX_API@ InfraredTransmit $FREQUENCY --eia pattern $1 diff --git a/scripts/termux-location b/scripts/termux-location new file mode 100755 index 0000000..bbe8fa2 --- /dev/null +++ b/scripts/termux-location @@ -0,0 +1,48 @@ +#!/bin/sh +set -e -u + +SCRIPTNAME=termux-location +show_usage () { + echo "usage: $SCRIPTNAME [-p provider] [-r request]" + echo "Get the device location." + echo " -p provider location provider [gps/network/passive] (default: gps)" + echo " -r request kind of request to make [once/last/updates] (default: once)" + exit 0 +} + +validate_provider () { + PROVIDER=$1 + case "$PROVIDER" in + gps) ;; + network) ;; + passive) ;; + *) echo "$SCRIPTNAME: Unsupported provider: '$PROVIDER'"; exit 1;; + esac +} + +validate_request () { + REQUEST=$1 + case "$REQUEST" in + once) ;; + last) ;; + updates) ;; + *) echo "$SCRIPTNAME: Unsupported request: '$REQUEST'"; exit 1;; + esac +} + +PARAMS="" + +while getopts :hr:p: option +do + case "$option" in + h) show_usage;; + r) validate_request $OPTARG; PARAMS="$PARAMS --es request $OPTARG";; + p) validate_provider $OPTARG; PARAMS="$PARAMS --es provider $OPTARG";; + ?) echo "$SCRIPTNAME: illegal option -$OPTARG"; exit 1; + esac +done +shift $(($OPTIND-1)) + +if [ $# != 0 ]; then echo "$SCRIPTNAME: too many arguments"; exit 1; fi + +@TERMUX_API@ Location $PARAMS diff --git a/scripts/termux-notification b/scripts/termux-notification new file mode 100755 index 0000000..dc77f29 --- /dev/null +++ b/scripts/termux-notification @@ -0,0 +1,104 @@ +#!/data/data/com.termux/files/usr/bin/bash +set -e -u + +SCRIPTNAME=termux-notification +show_usage () { + echo "Usage: termux-notification [options]" + echo "Display a system notification. Context text is read from stdin or specified using --content." + echo " --action action action to execute when pressing the notification" + echo " --button1 text text to show on the first notification button" + echo " --button1-action action action to execute on the first notification button" + echo " --button2 text text to show on the second notification button" + echo " --button2-action action action to execute on the second notification button" + echo " --button3 text text to show on the third notification button" + echo " --button3-action action action to execute on the third notification button" + echo " --content content contnet to show in the notification. Read from stdin not specified here." + echo " --id id notification id (will overwrite any previous notification with the same id)" + echo " --led-color rrggbb color of the blinking led as RRGGBB (default: none)" + echo " --led-on milliseconds number of milliseconds for the LED to be on while it's flashing (default: 800)" + echo " --led-off milliseconds number of milliseconds for the LED to be off while it's flashing (default: 800)" + echo " --priority prio notification priority (high/low/max/min/default)" + echo " --sound play a sound with the notification" + echo " --title title notification title to show" + echo " --vibrate pattern vibrate pattern, comma separated as in 500,1000,200" + exit 0 +} + +OPT_ACTION="" +OPT_ID="" +OPT_LED_COLOR="" +OPT_LED_OFF="" +OPT_LED_ON="" +OPT_PRIORITY="" +OPT_SOUND="" +OPT_TITLE="" +OPT_VIBRATE="" +OPT_BUTTON1_TEXT="" +OPT_BUTTON1_ACTION="" +OPT_BUTTON2_TEXT="" +OPT_BUTTON2_ACTION="" +OPT_BUTTON3_TEXT="" +OPT_BUTTON3_ACTION="" + +TEMP=`busybox getopt \ + -n $SCRIPTNAME \ + -o hc:i:t: \ + --long action:,\ +button1:,button1-action:,\ +button2:,button2-action:,\ +button3:,button3-action:,\ +content:,help,id:,\ +led-color:,led-on:,led-off:,\ +priority:,sound,title:,vibrate: \ + -s bash \ + -- "$@"` +eval set -- "$TEMP" + +while true; do + case "$1" in + --action) OPT_ACTION="$2"; shift 2;; + --button1) OPT_BUTTON1_TEXT="$2"; shift 2;; + --button1-action) OPT_BUTTON1_ACTION="$2"; shift 2;; + --button2) OPT_BUTTON2_TEXT="$2"; shift 2;; + --button2-action) OPT_BUTTON2_ACTION="$2"; shift 2;; + --button3) OPT_BUTTON3_TEXT="$2"; shift 2;; + --button3-action) OPT_BUTTON3_ACTION="$2"; shift 2;; + -c | --content) OPT_CONTENT="$2"; shift 2;; + -h | --help) show_usage;; + -i | --id) OPT_ID="$2"; shift 2;; + --led-color) OPT_LED_COLOR="$2"; shift 2;; + --led-on) OPT_LED_ON="$2"; shift 2;; + --led-off) OPT_LED_OFF="$2"; shift 2;; + --priority) OPT_PRIORITY="$2"; shift 2;; + --sound) OPT_SOUND="true"; shift 1;; + -t | --title) OPT_TITLE="$2"; shift 2;; + --vibrate) OPT_VIBRATE="$2"; shift 2;; + --) shift; break ;; + esac +done + +if [ $# != 0 ]; then echo "$SCRIPTNAME: too many arguments"; exit 1; fi + +set -- +if [ -n "$OPT_ACTION" ]; then set -- "$@" --es action "$OPT_ACTION"; fi +if [ -n "$OPT_BUTTON1_ACTION" ]; then set -- "$@" --es button_action_1 "$OPT_BUTTON1_ACTION"; fi +if [ -n "$OPT_BUTTON1_TEXT" ]; then set -- "$@" --es button_text_1 "$OPT_BUTTON1_TEXT"; fi +if [ -n "$OPT_BUTTON2_ACTION" ]; then set -- "$@" --es button_action_2 "$OPT_BUTTON2_ACTION"; fi +if [ -n "$OPT_BUTTON2_TEXT" ]; then set -- "$@" --es button_text_2 "$OPT_BUTTON2_TEXT"; fi +if [ -n "$OPT_BUTTON3_ACTION" ]; then set -- "$@" --es button_action_3 "$OPT_BUTTON3_ACTION"; fi +if [ -n "$OPT_BUTTON3_TEXT" ]; then set -- "$@" --es button_text_3 "$OPT_BUTTON3_TEXT"; fi +if [ -n "$OPT_ID" ]; then set -- "$@" --es id "$OPT_ID"; fi +if [ -n "$OPT_LED_COLOR" ]; then set -- "$@" --es led-color "$OPT_LED_COLOR"; fi +if [ -n "$OPT_LED_OFF" ]; then set -- "$@" --ei led-off "$OPT_LED_OFF"; fi +if [ -n "$OPT_LED_ON" ]; then set -- "$@" --ei led-on "$OPT_LED_ON"; fi +if [ -n "$OPT_PRIORITY" ]; then set -- "$@" --es priority "$OPT_PRIORITY"; fi +if [ -n "$OPT_SOUND" ]; then set -- "$@" --ez sound "$OPT_SOUND"; fi +if [ -n "$OPT_TITLE" ]; then set -- "$@" --es title "$OPT_TITLE"; fi +if [ -n "$OPT_VIBRATE" ]; then set -- "$@" --ela vibrate "$OPT_VIBRATE"; fi + +if [ -v OPT_CONTENT ]; then + # Note that we want to accept an empty content (--content ""). + echo ${OPT_CONTENT:=""} | /data/data/com.termux/files/usr/libexec/termux-api Notification "$@" +else + /data/data/com.termux/files/usr/libexec/termux-api Notification "$@" +fi diff --git a/scripts/termux-notification-remove b/scripts/termux-notification-remove new file mode 100755 index 0000000..8146ed2 --- /dev/null +++ b/scripts/termux-notification-remove @@ -0,0 +1,22 @@ +#!/data/data/com.termux/files/usr/bin/sh +set -e -u + +SCRIPTNAME=termux-notification-remove +show_usage () { + echo "Usage: $SCRIPTNAME notification-id" + echo "Remove a notification previously shown with termux-notification --id." + exit 0 +} + +while getopts :h option +do + case "$option" in + h) show_usage;; + ?) echo "$SCRIPTNAME: illegal option -$OPTARG"; exit 1; + esac +done +shift $(($OPTIND-1)) + +if [ $# != 1 ]; then echo "$SCRIPTNAME: no notification id specified"; exit 1; fi + +/data/data/com.termux/files/usr/libexec/termux-api NotificationRemove --es id $1 diff --git a/scripts/termux-share b/scripts/termux-share new file mode 100755 index 0000000..79cadaa --- /dev/null +++ b/scripts/termux-share @@ -0,0 +1,49 @@ +#!/bin/sh +set -e -u + +SCRIPTNAME=termux-share +show_usage () { + echo "Usage: $SCRIPTNAME [-a action] [-c content-type] [-d] [-t title] [file]" + echo "Share a file specified as argument or the text received on stdin if no file argument is given." + echo " -a action which action to performed on the shared content:" + echo " edit/send/view (default:view)" + echo " -c content-type content-type to use (default: guessed from file extension," + echo " text/plain for stdin)" + echo " -d share to the default receiver if one is selected" + echo " instead of showing a chooser" + echo " -t title title to use for shared content (default: shared file name)" + exit 0 +} + +validate_share () { + SHARETYPE=$1 + case "$SHARETYPE" in + edit) ;; + send) ;; + view) ;; + *) echo "$SCRIPTNAME: Unsupported action: '$SHARETYPE'"; exit 1;; + esac +} + +PARAMS="" +while getopts :ha:c:dt: option +do + case "$option" in + h) show_usage;; + a) validate_share $OPTARG; PARAMS="$PARAMS --es action $OPTARG";; + c) PARAMS="$PARAMS --es content-type $OPTARG";; + d) PARAMS="$PARAMS --ez default-receiver true";; + t) PARAMS="$PARAMS --es title $OPTARG";; + ?) echo "$SCRIPTNAME: illegal option -$OPTARG"; exit 1; + esac +done +shift $(($OPTIND-1)) + +if [ $# -gt 1 ]; then echo "$SCRIPTNAME: too many arguments"; exit 1; fi + +if [ $# != 0 ]; then + # Note that the file path can contain whitespace. + @TERMUX_API@ Share $PARAMS --es file "`realpath "$1"`" +else + @TERMUX_API@ Share $PARAMS +fi diff --git a/scripts/termux-sms-inbox b/scripts/termux-sms-inbox new file mode 100755 index 0000000..2e409fc --- /dev/null +++ b/scripts/termux-sms-inbox @@ -0,0 +1,35 @@ +#!/bin/sh +set -u + +PARAM_LIMIT=10 +PARAM_OFFSET=0 +PARAMS="" + +SCRIPTNAME=termux-sms-inbox +show_usage () { + echo "Usage: termux-sms-inbox [-d] [-l limit] [-n] [-o offset]" + echo "List received SMS messages." + echo " -d show dates when messages were created" + echo " -l limit offset in sms list (default: $PARAM_LIMIT)" + echo " -n show phone numbers" + echo " -o offset offset in sms list (default: $PARAM_OFFSET)" + exit 0 +} + +while getopts :hdl:no: option +do + case "$option" in + h) show_usage;; + d) PARAMS="$PARAMS --ez show-dates true";; + l) PARAM_LIMIT=$OPTARG;; + n) PARAMS="$PARAMS --ez show-phone-numbers true";; + o) PARAM_OFFSET=$OPTARG;; + ?) echo "$SCRIPTNAME: illegal option -$OPTARG"; exit 1; + esac +done +shift $(($OPTIND-1)) + +if [ $# != 0 ]; then echo "$SCRIPTNAME: too many arguments"; exit 1; fi + +PARAMS="$PARAMS --ei offset $PARAM_OFFSET --ei limit $PARAM_LIMIT" +@TERMUX_API@ SmsInbox $PARAMS diff --git a/scripts/termux-sms-send b/scripts/termux-sms-send new file mode 100755 index 0000000..dcd2810 --- /dev/null +++ b/scripts/termux-sms-send @@ -0,0 +1,32 @@ +#!/bin/sh +set -e -u + +SCRIPTNAME=termux-sms-send +show_usage () { + echo "Usage: $SCRIPTNAME -n number[,number2,number3,...] [text]" + 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." + echo " -n number(s) recipient number(s) - separate multiple numbers by commas" + exit 0 +} + +RECIPIENTS="" +while getopts :hn: option +do + case "$option" in + h) show_usage;; + n) RECIPIENTS="--esa recipients $OPTARG";; + ?) echo "$SCRIPTNAME: illegal option -$OPTARG"; exit 1; + esac +done +shift $(($OPTIND-1)) + +if [ -z "$RECIPIENTS" ]; then + echo "$SCRIPTNAME: no recipient number given"; exit 1; +fi + +CMD="@TERMUX_API@ SmsSend $RECIPIENTS" +if [ $# = 0 ]; then + $CMD +else + echo $@ | $CMD +fi diff --git a/scripts/termux-storage-get b/scripts/termux-storage-get new file mode 100755 index 0000000..54c03e6 --- /dev/null +++ b/scripts/termux-storage-get @@ -0,0 +1,24 @@ +#!/bin/sh +set -e -u + +SCRIPTNAME=termux-storage-get +show_usage () { + echo "Usage: $SCRIPTNAME output-file" + echo "Request a file from the system and output it to the specified file." + exit 0 +} + + +while getopts :h option +do + case "$option" in + h) show_usage;; + ?) echo "$SCRIPTNAME: illegal option -$OPTARG"; exit 1; + esac +done +shift $(($OPTIND-1)) + +if [ $# -gt 1 ]; then echo "$SCRIPTNAME: too many arguments"; exit 1; fi +if [ $# -lt 1 ]; then echo "$SCRIPTNAME: no output file specified"; exit 1; fi + +@TERMUX_API@ StorageGet --es file "`realpath "$1"`" diff --git a/scripts/termux-telephony-cellinfo b/scripts/termux-telephony-cellinfo new file mode 100755 index 0000000..1aa110c --- /dev/null +++ b/scripts/termux-telephony-cellinfo @@ -0,0 +1,22 @@ +#!/bin/sh +set -e -u + +SCRIPTNAME=termux-telephony-cellinfo +show_usage () { + echo "Usage: $SCRIPTNAME" + echo "Get information about all observed cell information from all radios on the device including the primary and neighboring cells." + exit 0 +} + +while getopts :h option +do + case "$option" in + h) show_usage;; + ?) echo "$SCRIPTNAME: illegal option -$OPTARG"; exit 1; + esac +done +shift $(($OPTIND-1)) + +if [ $# != 0 ]; then echo "$SCRIPTNAME: too many arguments"; exit 1; fi + +@TERMUX_API@ TelephonyCellInfo diff --git a/scripts/termux-telephony-deviceinfo b/scripts/termux-telephony-deviceinfo new file mode 100755 index 0000000..f031245 --- /dev/null +++ b/scripts/termux-telephony-deviceinfo @@ -0,0 +1,22 @@ +#!/bin/sh +set -e -u + +SCRIPTNAME=termux-telephony-deviceinfo +show_usage () { + echo "Usage: $SCRIPTNAME" + echo "Get information about the telephony device." + exit 0 +} + +while getopts :h option +do + case "$option" in + h) show_usage;; + ?) echo "$SCRIPTNAME: illegal option -$OPTARG"; exit 1; + esac +done +shift $(($OPTIND-1)) + +if [ $# != 0 ]; then echo "$SCRIPTNAME: too many arguments"; exit 1; fi + +@TERMUX_API@ TelephonyDeviceInfo diff --git a/scripts/termux-toast b/scripts/termux-toast new file mode 100755 index 0000000..c1bca23 --- /dev/null +++ b/scripts/termux-toast @@ -0,0 +1,28 @@ +#!/bin/sh +set -e -u + +SCRIPTNAME=termux-toast +show_usage () { + echo "Usage: termux-toast [-s] [text]" + echo "Show text in a Toast (a transient popup). The text to show is either supplied as arguments or read from stdin if no arguments are given." + echo " -s only show the toast for a short while" + exit 0 +} + +PARAMS="" +while getopts :hs option +do + case "$option" in + h) show_usage;; + s) PARAMS="--ez short true";; + ?) echo "$SCRIPTNAME: illegal option -$OPTARG"; exit 1; + esac +done +shift $(($OPTIND-1)) + +CMD="@TERMUX_API@ Toast $PARAMS" +if [ $# = 0 ]; then + $CMD +else + echo $@ | $CMD +fi diff --git a/scripts/termux-tts-engines b/scripts/termux-tts-engines new file mode 100755 index 0000000..3afa52b --- /dev/null +++ b/scripts/termux-tts-engines @@ -0,0 +1,22 @@ +#!/bin/sh +set -e -u + +SCRIPTNAME=termux-tts-engines +show_usage () { + echo "Usage: $SCRIPTNAME" + 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." + exit 0 +} + +while getopts :h option +do + case "$option" in + h) show_usage;; + ?) echo "$SCRIPTNAME: illegal option -$OPTARG"; exit 1; + esac +done +shift $(($OPTIND-1)) + +if [ $# != 0 ]; then echo "$SCRIPTNAME: too many arguments"; exit 1; fi + +@TERMUX_API@ TextToSpeech --es engine LIST_AVAILABLE diff --git a/scripts/termux-tts-speak b/scripts/termux-tts-speak new file mode 100755 index 0000000..fe7cb2c --- /dev/null +++ b/scripts/termux-tts-speak @@ -0,0 +1,49 @@ +#!/bin/sh +set -e -u + +SCRIPTNAME=termux-tts-speak +show_usage () { + echo "Usage: $SCRIPTNAME [-e engine] [-l language] [-n region] [-v variant] [-p pitch] [-r rate] [-s stream] [text-to-speak]" + 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." + echo " -e engine TTS engine to use (see termux-tts-engines)" + echo " -l language language to speak in (may be unsupported by the engine)" + echo " -n region region of language to speak in" + echo " -v variant variant of the language to speak in" + echo " -p pitch pitch to use in speech. 1.0 is the normal pitch," + echo " lower values lower the tone of the synthesized voice," + echo " greater values increase it." + echo " -r rate speech rate to use. 1.0 is the normal speech rate," + echo " lower values slow down the speech" + echo " (0.5 is half the normal speech rate)" + echo " while greater values accelerates it" + echo " (2.0 is twice the normal speech rate)." + echo " -s stream audio stream to use (default:NOTIFICATION), one of:" + echo " ALARM, MUSIC, NOTIFICATION, RING, SYSTEM, VOICE_CALL" + exit 0 +} + +PARAMS="" + +while getopts :he:l:n:v:p:r:s: option +do + case "$option" in + h) show_usage;; + e) PARAMS="$PARAMS --es engine $OPTARG";; + l) PARAMS="$PARAMS --es language $OPTARG";; + n) PARAMS="$PARAMS --es region $OPTARG";; + v) PARAMS="$PARAMS --es variant $OPTARG";; + p) PARAMS="$PARAMS --ef pitch $OPTARG";; + r) PARAMS="$PARAMS --ef rate $OPTARG";; + s) PARAMS="$PARAMS --es stream $OPTARG";; + ?) echo "$SCRIPTNAME: illegal option -$OPTARG"; exit 1; + esac +done +shift $(($OPTIND-1)) + +CMD="@TERMUX_API@ TextToSpeech $PARAMS" +if [ $# = 0 ]; then + $CMD +else + echo $@ | $CMD +fi + diff --git a/scripts/termux-vibrate b/scripts/termux-vibrate new file mode 100755 index 0000000..2ed8b67 --- /dev/null +++ b/scripts/termux-vibrate @@ -0,0 +1,28 @@ +#!/bin/sh +set -e -u + +SCRIPTNAME=termux-vibrate +show_usage () { + echo "Usage: $SCRIPTNAME [-d duration] [-f]" + echo "Vibrate the device." + echo " -d duration the duration to vibrate in ms (default:1000)" + echo " -f force vibration even in silent mode" + exit 0 +} + +PARAMS="" + +while getopts :hfd: option +do + case "$option" in + h) show_usage;; + d) PARAMS="$PARAMS --ei duration_ms $OPTARG";; + f) PARAMS="$PARAMS --ez force true";; + ?) echo "$SCRIPTNAME: illegal option -$OPTARG"; exit 1; + esac +done +shift $(($OPTIND-1)) + +if [ $# != 0 ]; then echo "$SCRIPTNAME: too many arguments"; exit 1; fi + +@TERMUX_API@ Vibrate $PARAMS diff --git a/scripts/termux-wifi-connectioninfo b/scripts/termux-wifi-connectioninfo new file mode 100755 index 0000000..b1a6c58 --- /dev/null +++ b/scripts/termux-wifi-connectioninfo @@ -0,0 +1,22 @@ +#!/data/data/com.termux/files/usr/bin/sh +set -e -u + +SCRIPTNAME=termux-wifi-connectioninfo +show_usage () { + echo "Usage: $SCRIPTNAME" + echo "Get information about the current wifi connection." + exit 0 +} + +while getopts :h option +do + case "$option" in + h) show_usage;; + ?) echo "$SCRIPTNAME: illegal option -$OPTARG"; exit 1; + esac +done +shift $(($OPTIND-1)) + +if [ $# != 0 ]; then echo "$SCRIPTNAME: too many arguments"; exit 1; fi + +/data/data/com.termux/files/usr/libexec/termux-api WifiConnectionInfo diff --git a/scripts/termux-wifi-scaninfo b/scripts/termux-wifi-scaninfo new file mode 100755 index 0000000..646579d --- /dev/null +++ b/scripts/termux-wifi-scaninfo @@ -0,0 +1,22 @@ +#!/data/data/com.termux/files/usr/bin/sh +set -e -u + +SCRIPTNAME=termux-wifi-scaninfo +show_usage () { + echo "Usage: $SCRIPTNAME" + echo "Get information about the last wifi scan." + exit 0 +} + +while getopts :h option +do + case "$option" in + h) show_usage;; + ?) echo "$SCRIPTNAME: illegal option -$OPTARG"; exit 1; + esac +done +shift $(($OPTIND-1)) + +if [ $# != 0 ]; then echo "$SCRIPTNAME: too many arguments"; exit 1; fi + +/data/data/com.termux/files/usr/libexec/termux-api WifiScanInfo diff --git a/termux-api.c b/termux-api.c new file mode 100644 index 0000000..115c450 --- /dev/null +++ b/termux-api.c @@ -0,0 +1,156 @@ +// termux-api.c - helper binary for calling termux api classes +// Usage: termux-api ${API_METHOD} ${ADDITIONAL_FLAGS} +// This executes +// am broadcast com.termux.api/.TermuxApiReceiver --es socket_input ${INPUT_SOCKET} +// --es socket_output ${OUTPUT_SOCKET} +// --es ${API_METHOD} +// ${ADDITIONAL_FLAGS} +// where ${INPUT_SOCKET} and ${OUTPUT_SOCKET} are addresses to linux abstract namespace sockets, +// used to pass on stdin to the java implementation and pass back output from java to stdout. +#define _POSIX_SOURCE +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Function which execs "am broadcast ..". +_Noreturn void exec_am_broadcast(int argc, char** argv, char* input_address_string, char* output_address_string) +{ + // Redirect stdout to /dev/null (but leave stderr open): + close(STDOUT_FILENO); + open("/dev/null", O_RDONLY); + // Close stdin: + close(STDIN_FILENO); + + int const extra_args = 15; // Including ending NULL. + char** child_argv = malloc((sizeof(char*)) * (argc + extra_args)); + + child_argv[0] = "am"; + child_argv[1] = "broadcast"; + child_argv[2] = "--user"; + child_argv[3] = "0"; + child_argv[4] = "-n"; + child_argv[5] = "com.termux.api/.TermuxApiReceiver"; + child_argv[6] = "--es"; + // Input/output are reversed for the java process (our output is its input): + child_argv[7] = "socket_input"; + child_argv[8] = output_address_string; + child_argv[9] = "--es"; + child_argv[10] = "socket_output"; + child_argv[11] = input_address_string; + child_argv[12] = "--es"; + child_argv[13] = "api_method"; + child_argv[14] = argv[1]; + + // Copy the remaining arguments -2 for first binary and second api name: + memcpy(child_argv + extra_args, argv + 2, (argc-1) * sizeof(char*)); + + // End with NULL: + child_argv[argc + extra_args] = NULL; + + // Use an a executable taking care of PATH and LD_LIBRARY_PATH: + execv("/data/data/com.termux/files/usr/bin/am", child_argv); + + perror("execv(\"/data/data/com.termux/files/usr/bin/am\")"); + exit(1); +} + +void generate_uuid(char* str) { + sprintf(str, "%x%x-%x-%x-%x-%x%x%x", + arc4random(), arc4random(), // Generates a 64-bit Hex number + (uint32_t) getpid(), // Generates a 32-bit Hex number + ((arc4random() & 0x0fff) | 0x4000), // Generates a 32-bit Hex number of the form 4xxx (4 indicates the UUID version) + arc4random() % 0x3fff + 0x8000, // Generates a 32-bit Hex number in the range [0x8000, 0xbfff] + arc4random(), arc4random(), arc4random()); // Generates a 96-bit Hex number +} + +// Thread function which reads from stdin and writes to socket. +void* transmit_stdin_to_socket(void* arg) { + int output_server_socket = *((int*) arg); + struct sockaddr_un remote_addr; + socklen_t addrlen = sizeof(remote_addr); + int output_client_socket = accept(output_server_socket, (struct sockaddr*) &remote_addr, &addrlen); + + ssize_t len; + char buffer[1024]; + while (len = read(STDIN_FILENO, &buffer, sizeof(buffer)), len > 0) { + if (write(output_client_socket, buffer, len) < 0) break; + } + // Close output socket on end of input: + close(output_client_socket); + return NULL; +} + +// Main thread function which reads from input socket and writes to stdout. +void transmit_socket_to_stdout(int input_socket_fd) { + ssize_t len; + char buffer[1024]; + while ((len = read(input_socket_fd, &buffer, sizeof(buffer))) > 0) { + write(STDOUT_FILENO, buffer, len); + } + if (len < 0) perror("read()"); +} + +int main(int argc, char** argv) { + // Do not transform children into zombies when they terminate: + struct sigaction sigchld_action = { .sa_handler = SIG_DFL, .sa_flags = SA_RESTART | SA_NOCLDSTOP | SA_NOCLDWAIT }; + sigaction(SIGCHLD, &sigchld_action, NULL); + + char input_address_string[100]; // This program reads from it. + char output_address_string[100]; // This program writes to it. + + generate_uuid(input_address_string); + generate_uuid(output_address_string); + + struct sockaddr_un input_address = { .sun_family = AF_UNIX }; + struct sockaddr_un output_address = { .sun_family = AF_UNIX }; + // Leave struct sockaddr_un.sun_path[0] as 0 and use the UUID string as abstract linux namespace: + strncpy(&input_address.sun_path[1], input_address_string, strlen(input_address_string)); + strncpy(&output_address.sun_path[1], output_address_string, strlen(output_address_string)); + + int input_server_socket = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0); + if (input_server_socket == -1) { perror("socket()"); return 1; } + int output_server_socket = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0); + if (output_server_socket == -1) { perror("socket()"); return 1; } + + if (bind(input_server_socket, (struct sockaddr*) &input_address, sizeof(sa_family_t) + strlen(input_address_string) + 1) == -1) { + perror("bind(input)"); + return 1; + } + if (bind(output_server_socket, (struct sockaddr*) &output_address, sizeof(sa_family_t) + strlen(output_address_string) + 1) == -1) { + perror("bind(output)"); + return 1; + } + + if (listen(input_server_socket, 1) == -1) { perror("listen()"); return 1; } + if (listen(output_server_socket, 1) == -1) { perror("listen()"); return 1; } + + pid_t fork_result = fork(); + switch (fork_result) { + case -1: perror("fork()"); return 1; + case 0: exec_am_broadcast(argc, argv, input_address_string, output_address_string); + } + + struct sockaddr_un remote_addr; + socklen_t addrlen = sizeof(remote_addr); + int input_client_socket = accept(input_server_socket, (struct sockaddr*) &remote_addr, &addrlen); + + pthread_t transmit_thread; + pthread_create(&transmit_thread, NULL, transmit_stdin_to_socket, &output_server_socket); + + transmit_socket_to_stdout(input_client_socket); + + return 0; +} +