这是indexloc提供的服务,不要输入任何密码
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
# along with termux-tools. If not, see
# <https://www.gnu.org/licenses/>.

SUBDIRS = . scripts doc mirrors motds
SUBDIRS = . scripts doc mirrors motds src

CONFFILES = \
etc/motd \
Expand Down
4 changes: 3 additions & 1 deletion configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ AC_INIT([termux-tools], [1.43.3], [support@termux.dev])
AM_INIT_AUTOMAKE([foreign])

AC_PROG_MAKE_SET
AC_PROG_CC
AC_LANG(C)

copyright="Copyright (C) 2022-2024 Termux."
if test "${TERMUX_APP_PACKAGE+set}" = set; then
Expand Down Expand Up @@ -93,6 +95,6 @@ AC_SUBST(termux_package_manager)
AC_PROG_LN_S

AC_CONFIG_FILES([Makefile scripts/Makefile doc/Makefile
mirrors/Makefile motds/Makefile])
mirrors/Makefile motds/Makefile src/Makefile])

AC_OUTPUT
3 changes: 1 addition & 2 deletions scripts/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ termux-setup-package-manager termux-setup-storage termux-wake-lock \
termux-wake-unlock

# wrappers around tools in /system/bin:
bin_SCRIPTS += cmd df getprop logcat ping ping6 pm settings top
bin_SCRIPTS += df getprop logcat ping ping6 pm settings top

CLEANFILES = $(bin_SCRIPTS)

Expand Down Expand Up @@ -90,4 +90,3 @@ $(eval $(call wrapper-rule,pm))
$(eval $(call wrapper-rule,settings))
$(eval $(call wrapper-rule,top))
$(eval $(call wrapper-rule,umount))
$(eval $(call wrapper-rule,cmd))
23 changes: 23 additions & 0 deletions src/Makefile.am
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Copyright (C) 2024 Termux

# This file is part of termux-tools.

# termux-tools is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.

# termux-tools is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with termux-tools. If not, see
# <https://www.gnu.org/licenses/>.

AM_CFLAGS = -Wall -Wextra -pedantic

bin_PROGRAMS = cmd

cmd_SOURCES = cmd.c
112 changes: 112 additions & 0 deletions src/cmd.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
/* cmd.c
Copyright (C) 2024 5ec1cff
This file is part of termux-tools.
termux-tools is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at
your option) any later version.
termux-tools is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with termux-tools. If not, see
<https://www.gnu.org/licenses/>. */

#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/wait.h>

void pump(int in_fd, int out_fd) {
char buf[4096];
ssize_t sz, t;
for (;;) {
sz = TEMP_FAILURE_RETRY(read(in_fd, buf, sizeof(buf)));
if (sz <= 0) return;
while (sz) {
t = TEMP_FAILURE_RETRY(write(out_fd, buf, sz));
if (t <= 0) return;
sz -= t;
}
}
}

int p_std_in[2], p_std_out[2], p_std_err[2];

void *pump_stdin(void *ignore) {
pump(STDIN_FILENO, p_std_in[1]);
close(p_std_in[1]);
return NULL;
}

void *pump_stdout(void *ignore) {
pump(p_std_out[0], STDOUT_FILENO);
close(p_std_out[0]);
return NULL;
}

void *pump_stderr(void *ignore) {
pump(p_std_err[0], STDERR_FILENO);
close(p_std_err[0]);
return NULL;
}

void replace_fd(int fd, int target_fd) {
if (dup2(fd, target_fd) == -1) err(EXIT_FAILURE, "dup");
close(fd);
if (fcntl(target_fd, F_SETFD, fcntl(target_fd, F_GETFD) & ~FD_CLOEXEC) == -1)
err(EXIT_FAILURE, "replace_fd");
}

int main(int argc, char **argv) {
if (pipe(p_std_in) == -1) err(EXIT_FAILURE, "pipe");
if (pipe(p_std_out) == -1) err(EXIT_FAILURE, "pipe");
if (pipe(p_std_err) == -1) err(EXIT_FAILURE, "pipe");

pid_t pid = fork();

if (pid < 0) {
err(EXIT_FAILURE, "fork");
} else if (pid > 0) {
close(p_std_in[0]);
close(p_std_out[1]);
close(p_std_err[1]);

signal(SIGPIPE, SIG_IGN);

pthread_t t_stdin;
pthread_create(&t_stdin, NULL, pump_stdin, NULL);
pthread_detach(t_stdin);

pthread_t t_stdout;
pthread_create(&t_stdout, NULL, pump_stdout, NULL);

pthread_t t_stderr;
pthread_create(&t_stderr, NULL, pump_stderr, NULL);

int status;
if (TEMP_FAILURE_RETRY(waitpid(pid, &status, 0)) < 0) err(EXIT_FAILURE, "wait");

pthread_join(t_stdout, NULL);
pthread_join(t_stderr, NULL);

if (WIFEXITED(status))
exit(WEXITSTATUS(status));
else
exit(EXIT_FAILURE);
} else {
replace_fd(p_std_in[0], STDIN_FILENO);
replace_fd(p_std_out[1], STDOUT_FILENO);
replace_fd(p_std_err[1], STDERR_FILENO);

execv("/system/bin/cmd", argv);
err(EXIT_FAILURE, "exec");
}
}