summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/calcurse.h1
-rw-r--r--src/utils.c71
2 files changed, 72 insertions, 0 deletions
diff --git a/src/calcurse.h b/src/calcurse.h
index 2c43369..cb9ea93 100644
--- a/src/calcurse.h
+++ b/src/calcurse.h
@@ -879,6 +879,7 @@ int parse_date (char *, enum datefmt, int *, int *, int *,
void str_toupper (char *);
void file_close (FILE *, const char *);
void psleep (unsigned);
+int fork_exec (int *, int *, const char *, char *const *);
/* vars.c */
extern int col, row;
diff --git a/src/utils.c b/src/utils.c
index 1b91609..61c87a1 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -42,6 +42,7 @@
#include <ctype.h>
#include <sys/types.h>
#include <errno.h>
+#include <fcntl.h>
#include "calcurse.h"
@@ -718,3 +719,73 @@ psleep (unsigned secs)
for (unslept = sleep (secs); unslept; unslept = sleep (unslept))
;
}
+
+/*
+ * Fork and execute an external process.
+ *
+ * If pfdin and/or pfdout point to a valid address, a pipe is created and the
+ * appropriate file descriptors are written to pfdin/pfdout.
+ */
+int
+fork_exec (int *pfdin, int *pfdout, const char *path, char *const *arg)
+{
+ int pin[2], pout[2];
+ int pid;
+
+ if (pfdin && (pipe (pin) == -1))
+ return 0;
+ if (pfdout && (pipe (pout) == -1))
+ return 0;
+
+ if ((pid = fork ()) == 0)
+ {
+ if (pfdout)
+ {
+ if (dup2 (pout[0], STDIN_FILENO) < 0)
+ _exit (127);
+ close (pout[0]);
+ close (pout[1]);
+ }
+
+ if (pfdin)
+ {
+ if (dup2 (pin[1], STDOUT_FILENO) < 0)
+ _exit (127);
+ close (pin[0]);
+ close (pin[1]);
+ }
+
+ execvp (path, arg);
+ _exit (127);
+ }
+ else
+ {
+ if (pfdin)
+ close (pin[1]);
+ if (pfdout)
+ close (pout[0]);
+
+ if (pid > 0)
+ {
+ if (pfdin)
+ {
+ fcntl (pin[0], F_SETFD, FD_CLOEXEC);
+ *pfdin = pin[0];
+ }
+ if (pfdout)
+ {
+ fcntl (pout[1], F_SETFD, FD_CLOEXEC);
+ *pfdout = pout[1];
+ }
+ }
+ else
+ {
+ if (pfdin)
+ close (pin[0]);
+ if (pfdout)
+ close (pout[1]);
+ return 0;
+ }
+ }
+ return pid;
+}