source: filterproc.c @ ef4074b

release-1.10release-1.9
Last change on this file since ef4074b was f271129, checked in by Jason Gross <jgross@mit.edu>, 13 years ago
Fix up headers The additions to owl.h and some of the removals were done by Alejandro Sedeño <asedeno@mit.edu> in commit 77a0258b3919468fc9d7f7602588ac427ab36e6c. Notes: * I think owl.c lost the need for sys/time.h when we punted select() in favor of glib's main loop. * We don't actually need to include things like stdarg.h, stdio.h, glib/gstdio.h, glib-object.h. I think they get indirectly included via owl.h and/or glib.h. They're left in (or added in to) the files that use functions/types from them. * I'm not entirely sure what sys/socket.h is doing in message.c. It is there from the initial commit. I suspect it might have had something to do with the call to getnameinfo. message.c compiles without it, but http://pubs.opengroup.org/onlinepubs/009695399/functions/getnameinfo.html suggests that we're supposed to include it? *shrugs* I'm leaving it in, for now. (Rather, I'll leave one copy of the #include in.)
  • Property mode set to 100644
File size: 2.0 KB
Line 
1#include "owl.h"
2#include <sys/wait.h>
3#include <poll.h>
4
5int send_receive(int rfd, int wfd, const char *out, char **in)
6{
7  GString *str = g_string_new("");
8  char buf[1024];
9  nfds_t nfds;
10  int err = 0;
11  struct pollfd fds[2];
12
13  fcntl(rfd, F_SETFL, O_NONBLOCK | fcntl(rfd, F_GETFL));
14  fcntl(wfd, F_SETFL, O_NONBLOCK | fcntl(wfd, F_GETFL));
15
16  fds[0].fd = rfd;
17  fds[0].events = POLLIN;
18  fds[1].fd = wfd;
19  fds[1].events = POLLOUT;
20
21  while(1) {
22    if(out && *out) {
23      nfds = 2;
24    } else {
25      nfds = 1;
26    }
27    err = poll(fds, nfds, -1);
28    if(err < 0) {
29      break;
30    }
31    if(out && *out) {
32      if(fds[1].revents & POLLOUT) {
33        err = write(wfd, out, strlen(out));
34        if(err > 0) {
35          out += err;
36        }
37        if(err < 0) {
38          out = NULL;
39        }
40      }
41      if(!out || !*out || fds[1].revents & (POLLERR | POLLHUP)) {
42        close(wfd);
43        out = NULL;
44      }
45    }
46    if(fds[0].revents & POLLIN) {
47      err = read(rfd, buf, sizeof(buf));
48      if(err <= 0) {
49        break;
50      }
51      g_string_append_len(str, buf, err);
52    } else if(fds[0].revents & (POLLHUP | POLLERR)) {
53      err = 0;
54      break;
55    }
56  }
57
58  *in = g_string_free(str, err < 0);
59  return err;
60}
61
62int call_filter(const char *prog, const char *const *argv, const char *in, char **out, int *status)
63{
64  int err = 0;
65  pid_t pid;
66  int rfd[2];
67  int wfd[2];
68
69  if((err = pipe(rfd))) goto out;
70  if((err = pipe(wfd))) goto out_close_rfd;
71
72  pid = fork();
73  if(pid < 0) {
74    err = pid;
75    goto out_close_all;
76  }
77  if(pid) {
78    /* parent */
79    close(rfd[1]);
80    close(wfd[0]);
81    err = send_receive(rfd[0], wfd[1], in, out);
82    if(err == 0) {
83      waitpid(pid, status, 0);
84    }
85  } else {
86    /* child */
87    close(rfd[0]);
88    close(wfd[1]);
89    dup2(rfd[1], 1);
90    dup2(wfd[0], 0);
91    close(rfd[1]);
92    close(wfd[0]);
93
94    if(execvp(prog, (char *const *)argv)) {
95      _exit(-1);
96    }
97  }
98
99 out_close_all:
100  close(wfd[0]);
101  close(wfd[1]);
102 out_close_rfd:
103  close(rfd[0]);
104  close(rfd[1]);
105 out:
106  return err;
107}
Note: See TracBrowser for help on using the repository browser.