summaryrefslogtreecommitdiff
path: root/libudev/libudev-util-private.c
diff options
context:
space:
mode:
Diffstat (limited to 'libudev/libudev-util-private.c')
-rw-r--r--libudev/libudev-util-private.c289
1 files changed, 0 insertions, 289 deletions
diff --git a/libudev/libudev-util-private.c b/libudev/libudev-util-private.c
index 87b9edbc71..2d7f8dc758 100644
--- a/libudev/libudev-util-private.c
+++ b/libudev/libudev-util-private.c
@@ -19,9 +19,6 @@
#include <ctype.h>
#include <pwd.h>
#include <grp.h>
-#include <sys/prctl.h>
-#include <sys/epoll.h>
-#include <sys/wait.h>
#include <sys/param.h>
#include "libudev.h"
@@ -260,289 +257,3 @@ int util_resolve_subsys_kernel(struct udev *udev, const char *string,
udev_device_unref(dev);
return 0;
}
-
-static int run_program_exec(struct udev *udev, int fd_stdout, int fd_stderr,
- char *const argv[], char **envp, const sigset_t *sigmask)
-{
- int err;
- int fd;
-
- /* discard child output or connect to pipe */
- fd = open("/dev/null", O_RDWR);
- if (fd >= 0) {
- dup2(fd, STDIN_FILENO);
- if (fd_stdout < 0)
- dup2(fd, STDOUT_FILENO);
- if (fd_stderr < 0)
- dup2(fd, STDERR_FILENO);
- close(fd);
- } else {
- err(udev, "open /dev/null failed: %m\n");
- }
-
- /* connect pipes to std{out,err} */
- if (fd_stdout >= 0) {
- dup2(fd_stdout, STDOUT_FILENO);
- close(fd_stdout);
- }
- if (fd_stderr >= 0) {
- dup2(fd_stderr, STDERR_FILENO);
- close(fd_stderr);
- }
-
- /* terminate child in case parent goes away */
- prctl(PR_SET_PDEATHSIG, SIGTERM);
-
- /* restore original udev sigmask before exec */
- if (sigmask)
- sigprocmask(SIG_SETMASK, sigmask, NULL);
-
- execve(argv[0], argv, envp);
-
- /* exec failed */
- err = -errno;
- if (err == -ENOENT || err == -ENOTDIR) {
- /* may be on a filesystem which is not mounted right now */
- info(udev, "program '%s' not found\n", argv[0]);
- } else {
- /* other problems */
- err(udev, "exec of program '%s' failed\n", argv[0]);
- }
- return err;
-}
-
-static int run_program_read(struct udev *udev, int fd_stdout, int fd_stderr,
- char *const argv[], char *result, size_t ressize, size_t *reslen)
-{
- size_t respos = 0;
- int fd_ep = -1;
- struct epoll_event ep_outpipe;
- struct epoll_event ep_errpipe;
- int err = 0;
-
- /* read from child if requested */
- if (fd_stdout < 0 && fd_stderr < 0)
- return 0;
-
- fd_ep = epoll_create1(EPOLL_CLOEXEC);
- if (fd_ep < 0) {
- err = -errno;
- err(udev, "error creating epoll fd: %m\n");
- goto out;
- }
-
- if (fd_stdout >= 0) {
- memset(&ep_outpipe, 0, sizeof(struct epoll_event));
- ep_outpipe.events = EPOLLIN;
- ep_outpipe.data.ptr = &fd_stdout;
- if (epoll_ctl(fd_ep, EPOLL_CTL_ADD, fd_stdout, &ep_outpipe) < 0) {
- err(udev, "fail to add fd to epoll: %m\n");
- goto out;
- }
- }
-
- if (fd_stderr >= 0) {
- memset(&ep_errpipe, 0, sizeof(struct epoll_event));
- ep_errpipe.events = EPOLLIN;
- ep_errpipe.data.ptr = &fd_stderr;
- if (epoll_ctl(fd_ep, EPOLL_CTL_ADD, fd_stderr, &ep_errpipe) < 0) {
- err(udev, "fail to add fd to epoll: %m\n");
- goto out;
- }
- }
-
- /* read child output */
- while (fd_stdout >= 0 || fd_stderr >= 0) {
- int fdcount;
- struct epoll_event ev[4];
- int i;
-
- fdcount = epoll_wait(fd_ep, ev, ARRAY_SIZE(ev), -1);
- if (fdcount < 0) {
- if (errno == EINTR)
- continue;
- err(udev, "failed to poll: %m\n");
- err = -errno;
- goto out;
- }
-
- for (i = 0; i < fdcount; i++) {
- int *fd = (int *)ev[i].data.ptr;
-
- if (ev[i].events & EPOLLIN) {
- ssize_t count;
- char buf[4096];
-
- count = read(*fd, buf, sizeof(buf)-1);
- if (count <= 0)
- continue;
- buf[count] = '\0';
-
- /* store stdout result */
- if (result != NULL && *fd == fd_stdout) {
- if (respos + count < ressize) {
- memcpy(&result[respos], buf, count);
- respos += count;
- } else {
- err(udev, "ressize %zd too short\n", ressize);
- err = -ENOBUFS;
- }
- }
-
- /* log debug output only if we watch stderr */
- if (fd_stderr >= 0) {
- char *pos;
- char *line;
-
- pos = buf;
- while ((line = strsep(&pos, "\n"))) {
- if (pos != NULL || line[0] != '\0')
- info(udev, "'%s'(%s) '%s'\n", argv[0], *fd == fd_stdout ? "out" : "err" , line);
- }
- }
- } else if (ev[i].events & EPOLLHUP) {
- if (epoll_ctl(fd_ep, EPOLL_CTL_DEL, *fd, NULL) < 0) {
- err = -errno;
- err(udev, "failed to remove fd from epoll: %m\n");
- goto out;
- }
- *fd = -1;
- }
- }
- }
-
- /* return the child's stdout string */
- if (result != NULL) {
- result[respos] = '\0';
- dbg(udev, "result='%s'\n", result);
- if (reslen != NULL)
- *reslen = respos;
- }
-out:
- if (fd_ep >= 0)
- close(fd_ep);
- return err;
-}
-
-int util_run_program(struct udev *udev, const char *command, char **envp,
- char *result, size_t ressize, size_t *reslen,
- const sigset_t *sigmask)
-{
- int status;
- int outpipe[2] = {-1, -1};
- int errpipe[2] = {-1, -1};
- pid_t pid;
- char arg[UTIL_PATH_SIZE];
- char program[UTIL_PATH_SIZE];
- char *argv[((sizeof(arg) + 1) / 2) + 1];
- int i;
- int err = 0;
-
- info(udev, "'%s' started\n", command);
-
- /* build argv from command */
- util_strscpy(arg, sizeof(arg), command);
- i = 0;
- if (strchr(arg, ' ') != NULL) {
- char *pos = arg;
-
- while (pos != NULL && pos[0] != '\0') {
- if (pos[0] == '\'') {
- /* do not separate quotes */
- pos++;
- argv[i] = strsep(&pos, "\'");
- if (pos != NULL)
- while (pos[0] == ' ')
- pos++;
- } else {
- argv[i] = strsep(&pos, " ");
- if (pos != NULL)
- while (pos[0] == ' ')
- pos++;
- }
- dbg(udev, "arg[%i] '%s'\n", i, argv[i]);
- i++;
- }
- argv[i] = NULL;
- } else {
- argv[0] = arg;
- argv[1] = NULL;
- }
-
- /* pipes from child to parent */
- if (result != NULL || udev_get_log_priority(udev) >= LOG_INFO) {
- if (pipe2(outpipe, O_NONBLOCK) != 0) {
- err = -errno;
- err(udev, "pipe failed: %m\n");
- goto out;
- }
- }
- if (udev_get_log_priority(udev) >= LOG_INFO) {
- if (pipe2(errpipe, O_NONBLOCK) != 0) {
- err = -errno;
- err(udev, "pipe failed: %m\n");
- goto out;
- }
- }
-
- /* allow programs in /lib/udev/ to be called without the path */
- if (argv[0][0] != '/') {
- util_strscpyl(program, sizeof(program), LIBEXECDIR "/", argv[0], NULL);
- argv[0] = program;
- }
-
- pid = fork();
- switch(pid) {
- case 0:
- /* child closes parent's ends of pipes */
- if (outpipe[READ_END] >= 0) {
- close(outpipe[READ_END]);
- outpipe[READ_END] = -1;
- }
- if (errpipe[READ_END] >= 0) {
- close(errpipe[READ_END]);
- errpipe[READ_END] = -1;
- }
-
- err = run_program_exec(udev, outpipe[WRITE_END], errpipe[WRITE_END], argv, envp, sigmask);
-
- _exit(1);
- case -1:
- err(udev, "fork of '%s' failed: %m\n", argv[0]);
- err = -1;
- goto out;
- default:
- /* parent closed child's ends of pipes */
- if (outpipe[WRITE_END] >= 0) {
- close(outpipe[WRITE_END]);
- outpipe[WRITE_END] = -1;
- }
- if (errpipe[WRITE_END] >= 0) {
- close(errpipe[WRITE_END]);
- errpipe[WRITE_END] = -1;
- }
-
- err = run_program_read(udev, outpipe[READ_END], errpipe[READ_END], argv, result, ressize, reslen);
-
- waitpid(pid, &status, 0);
- if (WIFEXITED(status)) {
- info(udev, "'%s' returned with exitcode %i\n", command, WEXITSTATUS(status));
- if (WEXITSTATUS(status) != 0)
- err = -1;
- } else {
- err(udev, "'%s' unexpected exit with status 0x%04x\n", command, status);
- err = -1;
- }
- }
-
-out:
- if (outpipe[READ_END] >= 0)
- close(outpipe[READ_END]);
- if (outpipe[WRITE_END] >= 0)
- close(outpipe[WRITE_END]);
- if (errpipe[READ_END] >= 0)
- close(errpipe[READ_END]);
- if (errpipe[WRITE_END] >= 0)
- close(errpipe[WRITE_END]);
- return err;
-}