diff options
author | Lukas Fleischer <calcurse@cryptocrack.de> | 2011-07-01 15:25:10 +0200 |
---|---|---|
committer | Lukas Fleischer <calcurse@cryptocrack.de> | 2011-07-02 10:15:36 +0200 |
commit | 6e2b00096dcf2733b58e82cda3510ed638983a20 (patch) | |
tree | 4ec3728aa1b8e63209a6d9a250be48ee8979af79 /src | |
parent | 003431880edfb0c44ae7b7f8e37d5358fb7b5d8e (diff) | |
download | calcurse-6e2b00096dcf2733b58e82cda3510ed638983a20.tar.gz calcurse-6e2b00096dcf2733b58e82cda3510ed638983a20.zip |
Add fork_exec() function
Can be used to execute an external program. Provides the possibility to
optionally create a pipe to the new process.
Signed-off-by: Lukas Fleischer <calcurse@cryptocrack.de>
Diffstat (limited to 'src')
-rw-r--r-- | src/calcurse.h | 1 | ||||
-rw-r--r-- | src/utils.c | 71 |
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; +} |