|
|
|
@ -1,7 +1,7 @@
@@ -1,7 +1,7 @@
|
|
|
|
|
//
|
|
|
|
|
// Definition of Apple Darwin system driver.
|
|
|
|
|
// Definition of Posix system driver (used by both the X11 and macOS platforms).
|
|
|
|
|
//
|
|
|
|
|
// Copyright 1998-2020 by Bill Spitzak and others.
|
|
|
|
|
// Copyright 1998-2021 by Bill Spitzak and others.
|
|
|
|
|
//
|
|
|
|
|
// This library is free software. Distribution and use rights are outlined in
|
|
|
|
|
// the file "COPYING" which should have been included with this file. If this
|
|
|
|
@ -33,6 +33,11 @@
@@ -33,6 +33,11 @@
|
|
|
|
|
#include <pwd.h> |
|
|
|
|
#include <unistd.h> |
|
|
|
|
#include <time.h> |
|
|
|
|
#include <unistd.h> |
|
|
|
|
#include <sys/wait.h> |
|
|
|
|
#include <signal.h> |
|
|
|
|
#include <fcntl.h> |
|
|
|
|
#include <errno.h> |
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Define missing POSIX/XPG4 macros as needed...
|
|
|
|
@ -93,3 +98,76 @@ void Fl_Posix_System_Driver::gettime(time_t *sec, int *usec) {
@@ -93,3 +98,76 @@ void Fl_Posix_System_Driver::gettime(time_t *sec, int *usec) {
|
|
|
|
|
*sec = tv.tv_sec; |
|
|
|
|
*usec = tv.tv_usec; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Run the specified program, returning 1 on success and 0 on failure
|
|
|
|
|
int Fl_Posix_System_Driver::run_program(const char *program, char **argv, char *msg, int msglen) { |
|
|
|
|
pid_t pid; // Process ID of first child
|
|
|
|
|
int status; // Exit status from first child
|
|
|
|
|
sigset_t set, oldset; // Signal masks
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Block SIGCHLD while we run the program...
|
|
|
|
|
//
|
|
|
|
|
// Note that I only use the POSIX signal APIs, however older operating
|
|
|
|
|
// systems may either not support POSIX signals or have side effects.
|
|
|
|
|
// IRIX, for example, provides three separate and incompatible signal
|
|
|
|
|
// APIs, so it is possible that an application setting a signal handler
|
|
|
|
|
// via signal() or sigset() will not have its SIGCHLD signals blocked...
|
|
|
|
|
|
|
|
|
|
sigemptyset(&set); |
|
|
|
|
sigaddset(&set, SIGCHLD); |
|
|
|
|
sigprocmask(SIG_BLOCK, &set, &oldset); |
|
|
|
|
|
|
|
|
|
// Create child processes that actually run the program for us...
|
|
|
|
|
if ((pid = fork()) == 0) { |
|
|
|
|
// First child comes here, fork a second child and exit...
|
|
|
|
|
if (!fork()) { |
|
|
|
|
// Second child comes here, redirect stdin/out/err to /dev/null...
|
|
|
|
|
close(0); |
|
|
|
|
::open("/dev/null", O_RDONLY); |
|
|
|
|
|
|
|
|
|
close(1); |
|
|
|
|
::open("/dev/null", O_WRONLY); |
|
|
|
|
|
|
|
|
|
close(2); |
|
|
|
|
::open("/dev/null", O_WRONLY); |
|
|
|
|
|
|
|
|
|
// Detach from the current process group...
|
|
|
|
|
setsid(); |
|
|
|
|
|
|
|
|
|
// Run the program...
|
|
|
|
|
execv(program, argv); |
|
|
|
|
_exit(0); |
|
|
|
|
} else { |
|
|
|
|
// First child gets here, exit immediately...
|
|
|
|
|
_exit(0); |
|
|
|
|
} |
|
|
|
|
} else if (pid < 0) { |
|
|
|
|
// Restore signal handling...
|
|
|
|
|
sigprocmask(SIG_SETMASK, &oldset, NULL); |
|
|
|
|
|
|
|
|
|
// Return indicating failure...
|
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Wait for the first child to exit...
|
|
|
|
|
while (waitpid(pid, &status, 0) < 0) { |
|
|
|
|
if (errno != EINTR) { |
|
|
|
|
// Someone else grabbed the child status...
|
|
|
|
|
if (msg) snprintf(msg, msglen, "waitpid(%ld) failed: %s", (long)pid, |
|
|
|
|
strerror(errno)); |
|
|
|
|
|
|
|
|
|
// Restore signal handling...
|
|
|
|
|
sigprocmask(SIG_SETMASK, &oldset, NULL); |
|
|
|
|
|
|
|
|
|
// Return indicating failure...
|
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Restore signal handling...
|
|
|
|
|
sigprocmask(SIG_SETMASK, &oldset, NULL); |
|
|
|
|
|
|
|
|
|
// Return indicating success...
|
|
|
|
|
return 1; |
|
|
|
|
} |
|
|
|
|