source: filterproc.c @ 3624a2c

release-1.10
Last change on this file since 3624a2c was 7155955, checked in by Anders Kaseorg <andersk@mit.edu>, 12 years ago
filterproc.c: Sever owl.h dependency This fixes ‘make zcrypt’, which currently has no dependency on owl_prototypes.h listed in Makefile.am. (We could instead add one, but that would be just as pointless.) Signed-off-by: Anders Kaseorg <andersk@mit.edu>
  • Property mode set to 100644
File size: 2.2 KB
RevLine 
[7155955]1#include "filterproc.h"
[d564c3d]2#include <sys/wait.h>
[7155955]3#include <fcntl.h>
4#include <glib.h>
[d564c3d]5#include <poll.h>
[7155955]6#include <string.h>
7#include <unistd.h>
[d564c3d]8
[97cdbaf5]9/* Even in case of error, send_receive is responsible for closing wfd
10 * (to EOF the child) and rfd (for consistency). */
11static int send_receive(int rfd, int wfd, const char *out, char **in)
[d564c3d]12{
13  GString *str = g_string_new("");
14  char buf[1024];
15  nfds_t nfds;
16  int err = 0;
17  struct pollfd fds[2];
18
19  fcntl(rfd, F_SETFL, O_NONBLOCK | fcntl(rfd, F_GETFL));
20  fcntl(wfd, F_SETFL, O_NONBLOCK | fcntl(wfd, F_GETFL));
21
22  fds[0].fd = rfd;
23  fds[0].events = POLLIN;
24  fds[1].fd = wfd;
25  fds[1].events = POLLOUT;
26
[1f39ded]27  if(!out || !*out) {
28    /* Nothing to write. Close our end so the child doesn't hang waiting. */
[97cdbaf5]29    close(wfd); wfd = -1;
[1f39ded]30    out = NULL;
31  }
32
[d564c3d]33  while(1) {
34    if(out && *out) {
35      nfds = 2;
36    } else {
37      nfds = 1;
38    }
39    err = poll(fds, nfds, -1);
40    if(err < 0) {
41      break;
42    }
43    if(out && *out) {
44      if(fds[1].revents & POLLOUT) {
45        err = write(wfd, out, strlen(out));
46        if(err > 0) {
47          out += err;
48        }
49        if(err < 0) {
50          out = NULL;
51        }
52      }
53      if(!out || !*out || fds[1].revents & (POLLERR | POLLHUP)) {
[97cdbaf5]54        close(wfd); wfd = -1;
[d564c3d]55        out = NULL;
56      }
57    }
58    if(fds[0].revents & POLLIN) {
59      err = read(rfd, buf, sizeof(buf));
60      if(err <= 0) {
61        break;
62      }
63      g_string_append_len(str, buf, err);
64    } else if(fds[0].revents & (POLLHUP | POLLERR)) {
65      err = 0;
66      break;
67    }
68  }
69
[97cdbaf5]70  if (wfd >= 0) close(wfd);
71  close(rfd);
[d564c3d]72  *in = g_string_free(str, err < 0);
73  return err;
74}
75
[97cdbaf5]76int call_filter(const char *const *argv, const char *in, char **out, int *status)
[d564c3d]77{
[97cdbaf5]78  int err;
79  GPid child_pid;
80  int child_stdin, child_stdout;
[d564c3d]81
[97cdbaf5]82  if (!g_spawn_async_with_pipes(NULL, (char**)argv, NULL,
83                                G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD,
84                                NULL, NULL,
85                                &child_pid, &child_stdin, &child_stdout, NULL,
86                                NULL)) {
[3496369]87    *out = NULL;
[97cdbaf5]88    return 1;
[d564c3d]89  }
90
[97cdbaf5]91  err = send_receive(child_stdout, child_stdin, in, out);
92  if (err == 0) {
93    waitpid(child_pid, status, 0);
[d564c3d]94  }
95  return err;
96}
Note: See TracBrowser for help on using the repository browser.