Some platforms disallow system() due to its perceived insecurity.
Luckily, we can be just as insecure using the more palatable
posix_spawn() instead!
CHECK_FUNCTION_EXISTS_GLIBC(openat HAVE_OPENAT)
CHECK_FUNCTION_EXISTS_GLIBC(pipe HAVE_PIPE)
CHECK_FUNCTION_EXISTS_GLIBC(poll HAVE_POLL)
+CHECK_FUNCTION_EXISTS_GLIBC(posix_spawn HAVE_POSIX_SPAWN)
CHECK_FUNCTION_EXISTS_GLIBC(posix_spawnp HAVE_POSIX_SPAWNP)
CHECK_FUNCTION_EXISTS_GLIBC(readlink HAVE_READLINK)
CHECK_FUNCTION_EXISTS_GLIBC(readpassphrase HAVE_READPASSPHRASE)
AC_CHECK_FUNCS([lchflags lchmod lchown link linkat localtime_r lstat lutimes])
AC_CHECK_FUNCS([mbrtowc memmove memset])
AC_CHECK_FUNCS([mkdir mkfifo mknod mkstemp])
-AC_CHECK_FUNCS([nl_langinfo openat pipe poll posix_spawnp readlink readlinkat])
+AC_CHECK_FUNCS([nl_langinfo openat pipe poll posix_spawn posix_spawnp])
+AC_CHECK_FUNCS([readlink readlinkat])
AC_CHECK_FUNCS([readpassphrase])
AC_CHECK_FUNCS([select setenv setlocale sigaction statfs statvfs])
AC_CHECK_FUNCS([strchr strdup strerror strncpy_s strnlen strrchr symlink])
#if HAVE_MEMBERSHIP_H
#include <membership.h>
#endif
+#if !defined(_WIN32) || defined(__CYGWIN__)
+# if HAVE_POSIX_SPAWN
+# if HAVE_SYS_WAIT_H
+# include <sys/wait.h>
+# endif
+# if HAVE_SPAWN_H
+# include <spawn.h>
+# endif
+extern char **environ;
+# define USE_POSIX_SPAWN 1
+# endif
+#endif
#ifndef nitems
#define nitems(arr) (sizeof(arr) / sizeof((arr)[0]))
systemf(const char *fmt, ...)
{
char buff[8192];
+#if USE_POSIX_SPAWN
+ char *argv[] = { "/bin/sh", "-c", buff, NULL };
+ pid_t pid;
+#endif
va_list ap;
int r;
va_start(ap, fmt);
vsnprintf(buff, sizeof(buff), fmt, ap);
+ va_end(ap);
if (verbosity > VERBOSITY_FULL)
logprintf("Cmd: %s\n", buff);
+#if USE_POSIX_SPAWN
+ if ((r = posix_spawn(&pid, *argv, NULL, NULL, argv, environ)) == 0) {
+ while (waitpid(pid, &r, 0) == -1) {
+ if (errno != EINTR)
+ return (-1);
+ }
+ }
+#else
r = system(buff);
- va_end(ap);
+#endif
return (r);
}