Skip to content

Commit 77efa52

Browse files
committed
Mv termux-api helper functions into new library libtermux-api
Any program can then link against it and get access to the API related functions. Will be useful for simplifying usb access for CLI programs for example. Also rename libexec/termux-api to libexec/termux-api-broadcast, cmake does not like having an executable with the same name as a library.
1 parent 7531d57 commit 77efa52

4 files changed

Lines changed: 109 additions & 46 deletions

File tree

CMakeLists.txt

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,13 @@ cmake_minimum_required(VERSION 3.0.0)
22
project(termux-api)
33
include(GNUInstallDirs)
44

5-
add_executable(termux-api termux-api.c)
6-
75
set(TERMUX_PREFIX ${CMAKE_INSTALL_PREFIX})
86

7+
add_library(termux-api SHARED termux-api.c)
8+
9+
add_executable(termux-api-broadcast termux-api-broadcast.c)
10+
target_link_libraries(termux-api-broadcast termux-api)
11+
912
# TODO: get list through regex or similar
1013
set(script_files
1114
scripts/termux-audio-info
@@ -69,13 +72,32 @@ configure_file(
6972
)
7073

7174
install(
72-
FILES ${CMAKE_BINARY_DIR}/termux-api
75+
FILES ${CMAKE_BINARY_DIR}/termux-api-broadcast
7376
DESTINATION ${CMAKE_INSTALL_PREFIX}/libexec
7477
PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE
7578
GROUP_READ GROUP_EXECUTE
7679
WORLD_READ WORLD_EXECUTE
7780
)
7881

82+
# Create a symlink for termux-api-broadcast->termux-api for backwards
83+
# compatibility
84+
INSTALL(CODE "execute_process( \
85+
COMMAND ${CMAKE_COMMAND} -E create_symlink \
86+
termux-api-broadcast \
87+
${CMAKE_INSTALL_PREFIX}/libexec/termux-api \
88+
)"
89+
)
90+
91+
install(
92+
FILES ${CMAKE_BINARY_DIR}/libtermux-api.so
93+
TYPE LIB
94+
)
95+
96+
install(
97+
FILES ${CMAKE_CURRENT_SOURCE_DIR}/termux-api.h
98+
TYPE INCLUDE
99+
)
100+
79101
foreach(file ${script_files})
80102
install(
81103
FILES ${CMAKE_BINARY_DIR}/${file}

termux-api-broadcast.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
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+
}

termux-api.c

Lines changed: 53 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,3 @@
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-
*/
131
#define _POSIX_SOURCE
142
#define _GNU_SOURCE
153
#include <fcntl.h>
@@ -20,13 +8,20 @@
208
#include <stdio.h>
219
#include <stdlib.h>
2210
#include <string.h>
11+
#include <sys/endian.h>
2312
#include <sys/socket.h>
2413
#include <sys/stat.h>
2514
#include <sys/types.h>
2615
#include <sys/un.h>
2716
#include <time.h>
2817
#include <unistd.h>
2918

19+
#include "termux-api.h"
20+
21+
#ifndef PREFIX
22+
# define PREFIX "/data/data/com.termux/files/usr"
23+
#endif
24+
3025
// Function which execs "am broadcast ..".
3126
_Noreturn void exec_am_broadcast(int argc, char** argv,
3227
char* input_address_string,
@@ -77,6 +72,9 @@ _Noreturn void exec_callback(int fd)
7772
if (asprintf(&fds, "%d", fd) == -1)
7873
perror("asprintf");
7974

75+
/* TERMUX_EXPORT_FD and TERMUX_USB_FD are (currently) specific for
76+
termux-usb, so there's some room for improvement here (this
77+
function should be generic) */
8078
char errmsg[256];
8179
char *export_to_env = getenv("TERMUX_EXPORT_FD");
8280
if (export_to_env && strncmp(export_to_env, "true", 4) == 0) {
@@ -154,70 +152,82 @@ int transmit_socket_to_stdout(int input_socket_fd) {
154152
return fd;
155153
}
156154

157-
int main(int argc, char** argv) {
155+
int run_api_command(int argc, char **argv) {
158156
// Do not transform children into zombies when they terminate:
159157
struct sigaction sigchld_action = {
160158
.sa_handler = SIG_DFL,
161159
.sa_flags = SA_RESTART | SA_NOCLDSTOP | SA_NOCLDWAIT
162160
};
163161
sigaction(SIGCHLD, &sigchld_action, NULL);
164162

165-
char input_address_string[100]; // This program reads from it.
166-
char output_address_string[100]; // This program writes to it.
163+
char input_addr_str[100]; // This program reads from it.
164+
char output_addr_str[100]; // This program writes to it.
167165

168-
generate_uuid(input_address_string);
169-
generate_uuid(output_address_string);
166+
generate_uuid(input_addr_str);
167+
generate_uuid(output_addr_str);
170168

171-
struct sockaddr_un input_address = { .sun_family = AF_UNIX };
172-
struct sockaddr_un output_address = { .sun_family = AF_UNIX };
169+
struct sockaddr_un input_addr = { .sun_family = AF_UNIX };
170+
struct sockaddr_un output_addr = { .sun_family = AF_UNIX };
173171
// Leave struct sockaddr_un.sun_path[0] as 0 and use the UUID
174172
// string as abstract linux namespace:
175-
strncpy(&input_address.sun_path[1], input_address_string,
176-
strlen(input_address_string));
177-
strncpy(&output_address.sun_path[1], output_address_string,
178-
strlen(output_address_string));
173+
strncpy(&input_addr.sun_path[1], input_addr_str, strlen(input_addr_str));
174+
strncpy(&output_addr.sun_path[1], output_addr_str, strlen(output_addr_str));
179175

180176
int input_server_socket = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0);
181-
if (input_server_socket == -1) { perror("socket()"); return 1; }
177+
if (input_server_socket == -1) {
178+
perror("socket()");
179+
return -1;
180+
}
182181
int output_server_socket = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0);
183-
if (output_server_socket == -1) { perror("socket()"); return 1; }
182+
if (output_server_socket == -1) {
183+
perror("socket()");
184+
return -1;
185+
}
184186

185-
int ret = bind(input_server_socket, (struct sockaddr*) &input_address,
186-
sizeof(sa_family_t) + strlen(input_address_string) + 1);
187+
int ret;
188+
ret = bind(input_server_socket, (struct sockaddr*) &input_addr,
189+
sizeof(sa_family_t) + strlen(input_addr_str) + 1);
187190
if (ret == -1) {
188191
perror("bind(input)");
189-
return 1;
192+
return ret;
190193
}
191194

192-
ret = bind(output_server_socket, (struct sockaddr*) &output_address,
193-
sizeof(sa_family_t) + strlen(output_address_string) + 1);
195+
ret = bind(output_server_socket, (struct sockaddr*) &output_addr,
196+
sizeof(sa_family_t) + strlen(output_addr_str) + 1);
194197
if (ret == -1) {
195198
perror("bind(output)");
196-
return 1;
199+
return ret;
200+
}
201+
202+
if (listen(input_server_socket, 1) == -1) {
203+
perror("listen()");
204+
return -1;
197205
}
198206

199-
if (listen(input_server_socket, 1) == -1) { perror("listen()"); return 1; }
200-
if (listen(output_server_socket, 1) == -1) { perror("listen()"); return 1; }
207+
if (listen(output_server_socket, 1) == -1) {
208+
perror("listen()");
209+
return -1;
210+
}
201211

202212
pid_t fork_result = fork();
203-
switch (fork_result) {
204-
case -1: perror("fork()"); return 1;
205-
case 0: exec_am_broadcast(argc, argv, input_address_string,
206-
output_address_string);
207-
}
213+
if (fork_result == -1) {
214+
perror("fork()");
215+
return -1;
216+
} else if (fork_result == 0)
217+
exec_am_broadcast(argc, argv, input_addr_str, output_addr_str);
208218

209219
struct sockaddr_un remote_addr;
210220
socklen_t addrlen = sizeof(remote_addr);
211-
int input_client_socket = accept(input_server_socket, (struct sockaddr*)
212-
&remote_addr, &addrlen);
221+
int input_client_socket = accept(input_server_socket,
222+
(struct sockaddr*) &remote_addr,
223+
&addrlen);
213224

214225
pthread_t transmit_thread;
215226
pthread_create(&transmit_thread, NULL, transmit_stdin_to_socket,
216227
&output_server_socket);
217228

229+
/* Device has been opened, time to actually get the fd */
218230
int fd = transmit_socket_to_stdout(input_client_socket);
219231
close(input_client_socket);
220-
if (fd != -1) { exec_callback(fd); }
221-
222-
return 0;
232+
return fd;
223233
}

termux-api.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#include <stdlib.h>
2+
3+
_Noreturn void exec_am_broadcast(int, char**, char*, char*);
4+
_Noreturn void exec_callback(int);
5+
void generate_uuid(char*);
6+
void* transmit_stdin_to_socket(void*);
7+
int transmit_socket_to_stdout(int);
8+
int run_api_command(int, char**);

0 commit comments

Comments
 (0)