[FFmpeg-devel] [PATCH 2/2] [RFC-NotForMerge] fftools/graphprint: Inline glibc system() implementation
softworkz
ffmpegagent at gmail.com
Wed May 28 18:24:09 EEST 2025
From: softworkz <softworkz at hotmail.com>
---
fftools/Makefile | 1 +
fftools/graph/_system.c | 213 ++++++++++++++++++++++++++++++++
fftools/graph/_system.h | 27 ++++
fftools/graph/_system_support.h | 199 +++++++++++++++++++++++++++++
fftools/graph/filelauncher.c | 3 +-
5 files changed, 442 insertions(+), 1 deletion(-)
create mode 100644 fftools/graph/_system.c
create mode 100644 fftools/graph/_system.h
create mode 100644 fftools/graph/_system_support.h
diff --git a/fftools/Makefile b/fftools/Makefile
index f6492cb1d7..dba96d3740 100644
--- a/fftools/Makefile
+++ b/fftools/Makefile
@@ -23,6 +23,7 @@ OBJS-ffmpeg += \
fftools/ffmpeg_sched.o \
fftools/graph/graphprint.o \
fftools/graph/filelauncher.o \
+ fftools/graph/_system.o \
fftools/sync_queue.o \
fftools/thread_queue.o \
fftools/textformat/avtextformat.o \
diff --git a/fftools/graph/_system.c b/fftools/graph/_system.c
new file mode 100644
index 0000000000..d1568611ff
--- /dev/null
+++ b/fftools/graph/_system.c
@@ -0,0 +1,213 @@
+/*
+ * Copyright (c) 1991-2018 - Free Software Foundation, Inc.
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+
+ /* Copyright (C) 1991-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include "config.h"
+
+#if defined(_WIN32)
+#elif defined(__APPLE__)
+#else
+
+#include <errno.h>
+#include <signal.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include "_system_support.h"
+#include <sys/types.h> // Add this include to define pid_t
+#include "_system.h"
+
+
+#define SHELL_PATH "/bin/sh" /* Path of the shell. */
+#define SHELL_NAME "sh" /* Name to give it. */
+
+
+#ifdef _LIBC_REENTRANT
+static struct sigaction intr, quit;
+static int sa_refcntr;
+__libc_lock_define_initialized (static, lock);
+
+# define DO_LOCK() __libc_lock_lock (lock)
+# define DO_UNLOCK() __libc_lock_unlock (lock)
+# define INIT_LOCK() ({ __libc_lock_init (lock); sa_refcntr = 0; })
+# define ADD_REF() sa_refcntr++
+# define SUB_REF() --sa_refcntr
+#else
+# define DO_LOCK()
+# define DO_UNLOCK()
+# define INIT_LOCK()
+# define ADD_REF() 0
+# define SUB_REF() 0
+#endif
+
+
+/* Execute LINE as a shell command, returning its status. */
+static int
+do_system (const char *line)
+{
+ int status, save;
+ pid_t pid;
+ struct sigaction sa;
+#ifndef _LIBC_REENTRANT
+ struct sigaction intr, quit;
+#endif
+ sigset_t omask;
+
+ sa.sa_handler = SIG_IGN;
+ sa.sa_flags = 0;
+ __sigemptyset (&sa.sa_mask);
+
+ DO_LOCK ();
+ if (ADD_REF () == 0)
+ {
+ if (__sigaction (SIGINT, &sa, &intr) < 0)
+ {
+ (void) SUB_REF ();
+ goto out;
+ }
+ if (__sigaction (SIGQUIT, &sa, &quit) < 0)
+ {
+ save = errno;
+ (void) SUB_REF ();
+ goto out_restore_sigint;
+ }
+ }
+ DO_UNLOCK ();
+
+ /* We reuse the bitmap in the 'sa' structure. */
+ __sigaddset (&sa.sa_mask, SIGCHLD);
+ save = errno;
+ if (__sigprocmask (SIG_BLOCK, &sa.sa_mask, &omask) < 0)
+ {
+#ifndef _LIBC
+ if (errno == ENOSYS)
+ __set_errno (save);
+ else
+#endif
+ {
+ DO_LOCK ();
+ if (SUB_REF () == 0)
+ {
+ save = errno;
+ (void) __sigaction (SIGQUIT, &quit, (struct sigaction *) NULL);
+ out_restore_sigint:
+ (void) __sigaction (SIGINT, &intr, (struct sigaction *) NULL);
+ __set_errno (save);
+ }
+ out:
+ DO_UNLOCK ();
+ return -1;
+ }
+ }
+
+#ifdef CLEANUP_HANDLER
+ CLEANUP_HANDLER;
+#endif
+
+#ifdef FORK
+ pid = FORK ();
+#else
+ pid = __fork ();
+#endif
+ if (pid == (pid_t) 0)
+ {
+ /* Child side. */
+ const char *new_argv[4];
+ new_argv[0] = SHELL_NAME;
+ new_argv[1] = "-c";
+ new_argv[2] = line;
+ new_argv[3] = NULL;
+
+ /* Restore the signals. */
+ (void) __sigaction (SIGINT, &intr, (struct sigaction *) NULL);
+ (void) __sigaction (SIGQUIT, &quit, (struct sigaction *) NULL);
+ (void) __sigprocmask (SIG_SETMASK, &omask, (sigset_t *) NULL);
+ pthread_mutex_init(&(lock), NULL);
+ sa_refcntr = 0;
+ /* Exec the shell. */
+ (void) __execve (SHELL_PATH, (char *const *) new_argv, __environ);
+ _exit (127);
+ }
+ else if (pid < (pid_t) 0)
+ /* The fork failed. */
+ status = -1;
+ else
+ /* Parent side. */
+ {
+ /* Note the system() is a cancellation point. But since we call
+ waitpid() which itself is a cancellation point we do not
+ have to do anything here. */
+ if (TEMP_FAILURE_RETRY (__waitpid (pid, &status, 0)) != pid)
+ status = -1;
+ }
+
+#ifdef CLEANUP_HANDLER
+ CLEANUP_RESET;
+#endif
+
+ save = errno;
+ DO_LOCK ();
+ if ((SUB_REF () == 0
+ && (__sigaction (SIGINT, &intr, (struct sigaction *) NULL)
+ | __sigaction (SIGQUIT, &quit, (struct sigaction *) NULL)) != 0)
+ || __sigprocmask (SIG_SETMASK, &omask, (sigset_t *) NULL) != 0)
+ {
+#ifndef _LIBC
+ /* glibc cannot be used on systems without waitpid. */
+ if (errno == ENOSYS)
+ __set_errno (save);
+ else
+#endif
+ status = -1;
+ }
+ DO_UNLOCK ();
+
+ return status;
+}
+
+int
+__libc_system (const char *line)
+{
+ if (line == NULL)
+ /* Check that we have a command processor available. It might
+ not be available after a chroot(), for example. */
+ return do_system ("exit 0") == 0;
+
+ return do_system (line);
+}
+////weak_alias (__libc_system, system)
+
+#endif
\ No newline at end of file
diff --git a/fftools/graph/_system.h b/fftools/graph/_system.h
new file mode 100644
index 0000000000..2780f234e0
--- /dev/null
+++ b/fftools/graph/_system.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2025 - softworkz
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef FFTOOLS_GRAPH_SYSTEM_H
+#define FFTOOLS_GRAPH_SYSTEM_H
+
+
+int __libc_system (const char *line);
+
+#endif /* FFTOOLS_GRAPH_SYSTEM_H */
diff --git a/fftools/graph/_system_support.h b/fftools/graph/_system_support.h
new file mode 100644
index 0000000000..6121c9bf2e
--- /dev/null
+++ b/fftools/graph/_system_support.h
@@ -0,0 +1,199 @@
+/*
+ * Copyright (c) 2025 - softworkz
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef FFTOOLS_GRAPH_SYSTEM_SUPPORT_H
+#define FFTOOLS_GRAPH_SYSTEM_SUPPORT_H
+
+#include <signal.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/* Platform-specific includes */
+#ifdef _WIN32
+#include <windows.h>
+#include "../../compat/w32pthreads.h"
+
+/* Windows doesn't have these POSIX headers - provide minimal compatibility */
+/* Visual Studio doesn't define pid_t, so define it ourselves */
+////#ifndef _PID_T_DEFINED
+////typedef int pid_t;
+////#define _PID_T_DEFINED
+////#endif
+
+typedef unsigned int sigset_t;
+
+/* Windows signal compatibility */
+#ifndef SIGQUIT
+#define SIGQUIT 3
+#endif
+#ifndef SIGCHLD
+#define SIGCHLD 0 /* Not used on Windows */
+#endif
+#define SIG_BLOCK 0
+#define SIG_SETMASK 1
+
+/* Windows sigaction compatibility */
+struct sigaction {
+ void (*sa_handler)(int);
+ sigset_t sa_mask;
+ int sa_flags;
+};
+
+/* Windows signal function stubs */
+static inline int sigemptyset(sigset_t *set) { *set = 0; return 0; }
+static inline int sigaddset(sigset_t *set, int sig) { *set |= (1 << sig); return 0; }
+static inline int sigprocmask(int how, const sigset_t *set, sigset_t *oldset) {
+ if (oldset) *oldset = 0;
+ return 0;
+}
+static inline int sigaction(int sig, const struct sigaction *act, struct sigaction *oldact) {
+ if (oldact) {
+ oldact->sa_handler = SIG_DFL;
+ oldact->sa_mask = 0;
+ oldact->sa_flags = 0;
+ }
+ return 0;
+}
+
+/* Windows process function stubs */
+static inline pid_t fork(void) {
+ errno = ENOSYS;
+ return -1;
+}
+
+/* Don't redefine execve if it already exists - use a wrapper name instead */
+static inline int __execve_wrapper(const char *path, char *const argv[], char *const envp[]) {
+ /* Use Windows system() as fallback - argv[2] should be the command */
+ if (argv && argv[2]) {
+ return system(argv[2]);
+ }
+ return -1;
+}
+
+static inline pid_t waitpid(pid_t pid, int *status, int options) {
+ if (status) *status = 0;
+ return pid;
+}
+
+#else
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <pthread.h>
+#endif
+
+/* Ensure environ is declared - but don't conflict with existing declarations */
+#ifndef _WIN32
+extern char **environ;
+#endif
+
+/* glibc compatibility: TEMP_FAILURE_RETRY macro */
+#ifndef TEMP_FAILURE_RETRY
+#ifdef _MSC_VER
+/* Visual Studio compatible version - Windows doesn't have EINTR, so no retry needed */
+#define TEMP_FAILURE_RETRY(expression) (expression)
+#elif defined(__GNUC__)
+/* GCC version with statement expressions */
+#define TEMP_FAILURE_RETRY(expression) \
+ (__extension__ \
+ ({ long int __result; \
+ do __result = (long int) (expression); \
+ while (__result == -1L && errno == EINTR); \
+ __result; }))
+#else
+/* Fallback for other compilers */
+#define TEMP_FAILURE_RETRY(expression) (expression)
+#endif
+#endif
+
+/* glibc compatibility: libc-lock macros */
+#define __libc_lock_define_initialized(CLASS, NAME) \
+ CLASS pthread_mutex_t NAME = PTHREAD_MUTEX_INITIALIZER
+
+#define __libc_lock_lock(NAME) pthread_mutex_lock(&(NAME))
+#define __libc_lock_unlock(NAME) pthread_mutex_unlock(&(NAME))
+#define __libc_lock_init(NAME) pthread_mutex_init(&(NAME), NULL)
+
+/* glibc compatibility: signal functions */
+#define __sigemptyset(set) sigemptyset(set)
+#define __sigaddset(set, sig) sigaddset(set, sig)
+#define __sigprocmask(how, set, oldset) sigprocmask(how, set, oldset)
+#define __sigaction(sig, act, oldact) sigaction(sig, act, oldact)
+
+/* glibc compatibility: process functions */
+#define __fork fork
+#ifdef _WIN32
+#define __execve __execve_wrapper
+#define __environ _environ
+#else
+#define __execve execve
+#define __environ environ
+#endif
+#define __waitpid waitpid
+
+/* glibc compatibility: errno setting */
+#define __set_errno(val) (errno = (val))
+
+/* glibc compatibility: weak alias macro - simplified for Windows */
+#ifdef _WIN32
+#define weak_alias(name, aliasname) \
+ int aliasname(const char *line) { return name(line); }
+#else
+#define weak_alias(name, aliasname) \
+ extern __typeof (name) aliasname __attribute__ ((weak, alias (#name)))
+#endif
+
+/* Threading and cancellation support */
+#ifndef _LIBC_REENTRANT
+#define _LIBC_REENTRANT 1
+#endif
+
+/* Optional cleanup handler support - can be defined by user if needed */
+#ifndef CLEANUP_HANDLER
+#define CLEANUP_HANDLER
+#endif
+
+#ifndef CLEANUP_RESET
+#define CLEANUP_RESET
+#endif
+
+/* Optional fork override - can be defined by user if needed */
+#ifndef FORK
+#define FORK __fork
+#endif
+
+/* Legacy wrappers for compatibility (keeping existing interface) */
+typedef pthread_mutex_t simple_lock_t;
+#define SIMPLE_LOCK_INIT PTHREAD_MUTEX_INITIALIZER
+static inline void simple_lock_lock(simple_lock_t *lock) { pthread_mutex_lock(lock); }
+static inline void simple_lock_unlock(simple_lock_t *lock) { pthread_mutex_unlock(lock); }
+static inline void simple_lock_init(simple_lock_t *lock) { pthread_mutex_init(lock, NULL); }
+
+static inline int sigaction_wrap(int sig, const struct sigaction *act, struct sigaction *oact) {
+ return sigaction(sig, act, oact);
+}
+static inline int sigprocmask_wrap(int how, const sigset_t *set, sigset_t *oldset) {
+ return sigprocmask(how, set, oldset);
+}
+static inline pid_t waitpid_wrap(pid_t pid, int *status, int options) {
+ return waitpid(pid, status, options);
+}
+
+#endif // FFTOOLS_GRAPH_SYSTEM_SUPPORT_H
\ No newline at end of file
diff --git a/fftools/graph/filelauncher.c b/fftools/graph/filelauncher.c
index b46967e334..2214338183 100644
--- a/fftools/graph/filelauncher.c
+++ b/fftools/graph/filelauncher.c
@@ -31,6 +31,7 @@
# include <sys/stat.h>
# include <sys/types.h>
# include <unistd.h>
+# include "_system.h"
#endif
#include "graphprint.h"
#include "libavutil/bprint.h"
@@ -80,7 +81,7 @@ int ff_open_html_in_browser(const char *html_path)
av_bprint_init(&buf, 0, AV_BPRINT_SIZE_AUTOMATIC);
av_bprintf(&buf, "xdg-open '%s' </dev/null 1>/dev/null 2>&1 &", html_path);
- int ret = system(buf.str);
+ int ret = __libc_system(buf.str);
if (ret != -1 && WIFEXITED(ret) && WEXITSTATUS(ret) == 0)
return 0;
--
ffmpeg-codebot
More information about the ffmpeg-devel
mailing list