-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #163 from grondo/input-plugin
imp: support helper to get input to exec command
- Loading branch information
Showing
13 changed files
with
619 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
/************************************************************\ | ||
* Copyright 2023 Lawrence Livermore National Security, LLC | ||
* (c.f. AUTHORS, NOTICE.LLNS, COPYING) | ||
* | ||
* This file is part of the Flux resource manager framework. | ||
* For details, see https://github.com/flux-framework. | ||
* | ||
* SPDX-License-Identifier: LGPL-3.0 | ||
\************************************************************/ | ||
|
||
#ifndef HAVE_CONFIG_H | ||
#include "config.h" | ||
#endif | ||
|
||
#include <sys/types.h> | ||
#include <sys/wait.h> | ||
#include <signal.h> | ||
#include <stdlib.h> | ||
#include <unistd.h> | ||
#include <string.h> | ||
#include <errno.h> | ||
|
||
#include "src/libutil/argsplit.h" | ||
#include "safe_popen.h" | ||
#include "imp_log.h" | ||
|
||
struct safe_popen { | ||
pid_t pid; | ||
FILE *fp; | ||
}; | ||
|
||
void safe_popen_destroy (struct safe_popen *sp) | ||
{ | ||
if (sp) { | ||
int saved_errno = errno; | ||
fclose (sp->fp); | ||
free (sp); | ||
errno = saved_errno; | ||
} | ||
} | ||
|
||
struct safe_popen * safe_popen (const char *cmd) | ||
{ | ||
struct safe_popen *sp; | ||
int pfds[2] = {-1, -1}; | ||
|
||
if (cmd == NULL || strlen (cmd) == 0) { | ||
errno = EINVAL; | ||
return NULL; | ||
} | ||
|
||
if (!(sp = calloc (1, sizeof (*sp))) | ||
|| pipe (pfds) < 0 | ||
|| !(sp->fp = fdopen (pfds[0], "r")) | ||
|| (sp->pid = fork ()) < 0) { | ||
imp_warn ("Failed to setup child for popen: %s", strerror (errno)); | ||
goto error; | ||
} | ||
|
||
if (sp->pid == 0) { | ||
/* Child process: Use pfds[1] as stdout | ||
*/ | ||
char **argv = argsplit (cmd); | ||
if (!argv) { | ||
fprintf (stderr, "imp: popen: failed to tokenize '%s'\n", cmd); | ||
_exit (126); | ||
} | ||
if (dup2 (pfds[1], STDOUT_FILENO) < 0) { | ||
fprintf (stderr, "imp: popen: dup2: %s\n", strerror (errno)); | ||
_exit (126); | ||
} | ||
(void) close (pfds[0]); | ||
(void) close (pfds[1]); | ||
setsid (); | ||
execvp (argv[0], argv); | ||
fprintf (stderr, "imp: popen: %s: %s\n", argv[0], strerror (errno)); | ||
if (errno == ENOENT) | ||
_exit (127); | ||
_exit (126); | ||
} | ||
|
||
/* Parent | ||
*/ | ||
(void) close (pfds[1]); | ||
|
||
return sp; | ||
error: | ||
safe_popen_destroy (sp); | ||
if (pfds[0] > 0) { | ||
(void) close (pfds[0]); | ||
(void) close (pfds[1]); | ||
} | ||
return NULL; | ||
} | ||
|
||
FILE *safe_popen_fp (struct safe_popen *sp) | ||
{ | ||
if (!sp || !sp->fp) { | ||
errno = EINVAL; | ||
return NULL; | ||
} | ||
return sp->fp; | ||
} | ||
|
||
int safe_popen_wait (struct safe_popen *sp, int *statusp) | ||
{ | ||
pid_t pid; | ||
|
||
if (!sp || sp->pid <= (pid_t) 0) { | ||
errno = EINVAL; | ||
return -1; | ||
} | ||
do { | ||
pid = waitpid (sp->pid, statusp, 0); | ||
} while (pid == -1 && errno == EINTR); | ||
|
||
return pid == -1 ? -1 : 0; | ||
} | ||
|
||
/* vi: ts=4 sw=4 expandtab | ||
*/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
/************************************************************\ | ||
* Copyright 2023 Lawrence Livermore National Security, LLC | ||
* (c.f. AUTHORS, NOTICE.LLNS, COPYING) | ||
* | ||
* This file is part of the Flux resource manager framework. | ||
* For details, see https://github.com/flux-framework. | ||
* | ||
* SPDX-License-Identifier: LGPL-3.0 | ||
\************************************************************/ | ||
|
||
#ifndef HAVE_IMP_EXEC_SAFE_POPEN_H | ||
#define HAVE_IMP_EXEC_SAFE_POPEN_H 1 | ||
|
||
#include <stdio.h> | ||
|
||
struct safe_popen; | ||
|
||
/* Safer and simpler version of popen(3): | ||
* - does not invoke shell | ||
* - splits `cmd` on whitespace only | ||
* | ||
* Returns a new safe_popen object on success, NULL with errno set | ||
* on failure. | ||
* EINVAL - cmd is NULL or an empty string. | ||
* ENOMEM - out of memory | ||
*/ | ||
struct safe_popen *safe_popen (const char *cmd); | ||
|
||
/* Return FILE * associated with safe_popen object */ | ||
FILE *safe_popen_fp (struct safe_popen *sp); | ||
|
||
/* Call waitpid(2) on process spawned by safe_popen(), placing process | ||
* status in `status` if non-NULL. | ||
* Returns 0 on success or -1 with errno set on error. | ||
* Special exit codes: | ||
* - 127: exec failed to find command | ||
* - 126: exec failed for other reason | ||
* - 125: internal error in child process before exec | ||
*/ | ||
int safe_popen_wait (struct safe_popen *sp, int *status); | ||
|
||
/* Destroy safe_popen object. Close open file descriptor and free | ||
* associated memory. | ||
*/ | ||
void safe_popen_destroy (struct safe_popen *sp); | ||
|
||
#endif /* !HAVE_IMP_EXEC_SAFE_POPEN_H */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.