Add parameter to redirect stderr to shell_exec()

Add a function parameter to allows redirecting stderr in addition to
stdin and stdout. The parameter will be used with a follow-up change.

Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
This commit is contained in:
Lukas Fleischer 2021-04-04 10:43:26 -04:00
parent f41955e491
commit 5710a8bd7f
6 changed files with 37 additions and 18 deletions

View File

@ -1251,9 +1251,9 @@ int parse_date_increment(const char *, unsigned *, time_t);
int parse_datetime(const char *, time_t *, time_t); int parse_datetime(const char *, time_t *, time_t);
void file_close(FILE *, const char *); void file_close(FILE *, const char *);
void psleep(unsigned); void psleep(unsigned);
int fork_exec(int *, int *, const char *, const char *const *); int fork_exec(int *, int *, int *, const char *, const char *const *);
int shell_exec(int *, int *, const char *, const char *const *); int shell_exec(int *, int *, int *, const char *, const char *const *);
int child_wait(int *, int *, int); int child_wait(int *, int *, int *, int);
void press_any_key(void); void press_any_key(void);
void print_apoint(const char *, time_t, struct apoint *); void print_apoint(const char *, time_t, struct apoint *);
void print_event(const char *, time_t, struct event *); void print_event(const char *, time_t, struct event *);

View File

@ -53,8 +53,8 @@ int run_hook(const char *name)
arg[0] = hook_cmd; arg[0] = hook_cmd;
arg[1] = NULL; arg[1] = NULL;
if ((pid = shell_exec(NULL, NULL, *arg, arg))) { if ((pid = shell_exec(NULL, NULL, NULL, *arg, arg))) {
ret = child_wait(NULL, NULL, pid); ret = child_wait(NULL, NULL, NULL, pid);
if (ret > 0 && WIFEXITED(ret)) { if (ret > 0 && WIFEXITED(ret)) {
asprintf(&mesg, "%s hook: exit status %d", asprintf(&mesg, "%s hook: exit status %d",
name, name,

View File

@ -1067,7 +1067,7 @@ void ui_day_item_pipe(void)
return; return;
wins_prepare_external(); wins_prepare_external();
if ((pid = shell_exec(NULL, &pout, *arg, arg))) { if ((pid = shell_exec(NULL, &pout, NULL, *arg, arg))) {
fpout = fdopen(pout, "w"); fpout = fdopen(pout, "w");
switch (p->type) { switch (p->type) {
@ -1088,7 +1088,7 @@ void ui_day_item_pipe(void)
} }
fclose(fpout); fclose(fpout);
child_wait(NULL, &pout, pid); child_wait(NULL, &pout, NULL, pid);
press_any_key(); press_any_key();
} }
wins_unprepare_external(); wins_unprepare_external();

View File

@ -158,11 +158,11 @@ void ui_todo_pipe(void)
return; return;
wins_prepare_external(); wins_prepare_external();
if ((pid = shell_exec(NULL, &pout, *arg, arg))) { if ((pid = shell_exec(NULL, &pout, NULL, *arg, arg))) {
fpout = fdopen(pout, "w"); fpout = fdopen(pout, "w");
todo_write(item, fpout); todo_write(item, fpout);
fclose(fpout); fclose(fpout);
child_wait(NULL, &pout, pid); child_wait(NULL, &pout, NULL, pid);
press_any_key(); press_any_key();
} }
wins_unprepare_external(); wins_unprepare_external();

View File

@ -1317,21 +1317,30 @@ void psleep(unsigned secs)
/* /*
* Fork and execute an external process. * Fork and execute an external process.
* *
* If pfdin and/or pfdout point to a valid address, a pipe is created and the * If pfdin/pfdout/pfderr point to a valid address, a pipe is created and the
* appropriate file descriptors are written to pfdin/pfdout. * appropriate file descriptors are written to pfdin/pfdout/pfderr.
*/ */
int fork_exec(int *pfdin, int *pfdout, const char *path, int fork_exec(int *pfdin, int *pfdout, int *pfderr, const char *path,
const char *const *arg) const char *const *arg)
{ {
int pin[2], pout[2]; int pin[2], pout[2], perr[2];
int pid; int pid;
if (pfdin && (pipe(pin) == -1)) if (pfdin && (pipe(pin) == -1))
return 0; return 0;
if (pfdout && (pipe(pout) == -1)) if (pfdout && (pipe(pout) == -1))
return 0; return 0;
if (pfderr && (pipe(perr) == -1))
return 0;
if ((pid = fork()) == 0) { if ((pid = fork()) == 0) {
if (pfderr) {
if (dup2(perr[0], STDERR_FILENO) < 0)
_exit(127);
close(perr[0]);
close(perr[1]);
}
if (pfdout) { if (pfdout) {
if (dup2(pout[0], STDIN_FILENO) < 0) if (dup2(pout[0], STDIN_FILENO) < 0)
_exit(127); _exit(127);
@ -1353,6 +1362,8 @@ int fork_exec(int *pfdin, int *pfdout, const char *path,
close(pin[1]); close(pin[1]);
if (pfdout) if (pfdout)
close(pout[0]); close(pout[0]);
if (pfderr)
close(perr[0]);
if (pid > 0) { if (pid > 0) {
if (pfdin) { if (pfdin) {
@ -1363,11 +1374,17 @@ int fork_exec(int *pfdin, int *pfdout, const char *path,
fcntl(pout[1], F_SETFD, FD_CLOEXEC); fcntl(pout[1], F_SETFD, FD_CLOEXEC);
*pfdout = pout[1]; *pfdout = pout[1];
} }
if (pfderr) {
fcntl(perr[1], F_SETFD, FD_CLOEXEC);
*pfderr = perr[1];
}
} else { } else {
if (pfdin) if (pfdin)
close(pin[0]); close(pin[0]);
if (pfdout) if (pfdout)
close(pout[1]); close(pout[1]);
if (pfderr)
close(perr[1]);
return 0; return 0;
} }
} }
@ -1376,7 +1393,7 @@ int fork_exec(int *pfdin, int *pfdout, const char *path,
/* Execute an external program in a shell. */ /* Execute an external program in a shell. */
int int
shell_exec(int *pfdin, int *pfdout, const char *path, shell_exec(int *pfdin, int *pfdout, int *pfderr, const char *path,
const char *const *arg) const char *const *arg)
{ {
int argc, i; int argc, i;
@ -1406,7 +1423,7 @@ shell_exec(int *pfdin, int *pfdout, const char *path,
narg[3] = NULL; narg[3] = NULL;
} }
ret = fork_exec(pfdin, pfdout, *narg, narg); ret = fork_exec(pfdin, pfdout, pfderr, *narg, narg);
if (arg0) if (arg0)
mem_free(arg0); mem_free(arg0);
@ -1416,7 +1433,7 @@ shell_exec(int *pfdin, int *pfdout, const char *path,
} }
/* Wait for a child process to terminate. */ /* Wait for a child process to terminate. */
int child_wait(int *pfdin, int *pfdout, int pid) int child_wait(int *pfdin, int *pfdout, int *pfderr, int pid)
{ {
int stat; int stat;
@ -1424,6 +1441,8 @@ int child_wait(int *pfdin, int *pfdout, int pid)
close(*pfdin); close(*pfdin);
if (pfdout) if (pfdout)
close(*pfdout); close(*pfdout);
if (pfderr)
close(*pfderr);
if (waitpid(pid, &stat, 0) == pid) if (waitpid(pid, &stat, 0) == pid)
return stat; return stat;

View File

@ -624,8 +624,8 @@ void wins_launch_external(const char *arg[])
int pid; int pid;
wins_prepare_external(); wins_prepare_external();
if ((pid = shell_exec(NULL, NULL, *arg, arg))) if ((pid = shell_exec(NULL, NULL, NULL, *arg, arg)))
child_wait(NULL, NULL, pid); child_wait(NULL, NULL, NULL, pid);
wins_unprepare_external(); wins_unprepare_external();
} }