source: filterproc.c @ 6829afc

release-1.10release-1.8release-1.9
Last change on this file since 6829afc was e2cc848, checked in by David Benjamin <davidben@mit.edu>, 13 years ago
Just ignore SIGPIPE altogether There's not much point in switching back and forth from ignoring it and mostly ignoring it. Also, we don't handle SIGCHLD so remove the code for it. (We actually also disable it in the Jabber module because XML::Stream sets $SIG{PIPE}. Meh.)
  • Property mode set to 100644
File size: 2.1 KB
Line 
1#include <signal.h>
2#include <unistd.h>
3#include <sys/select.h>
4#include <sys/types.h>
5#include <sys/wait.h>
6#include <poll.h>
7#include <fcntl.h>
8#include <string.h>
9
10#include <glib.h>
11
12int send_receive(int rfd, int wfd, const char *out, char **in)
13{
14  GString *str = g_string_new("");
15  char buf[1024];
16  nfds_t nfds;
17  int err = 0;
18  struct pollfd fds[2];
19
20  fcntl(rfd, F_SETFL, O_NONBLOCK | fcntl(rfd, F_GETFL));
21  fcntl(wfd, F_SETFL, O_NONBLOCK | fcntl(wfd, F_GETFL));
22
23  fds[0].fd = rfd;
24  fds[0].events = POLLIN;
25  fds[1].fd = wfd;
26  fds[1].events = POLLOUT;
27
28  while(1) {
29    if(out && *out) {
30      nfds = 2;
31    } else {
32      nfds = 1;
33    }
34    err = poll(fds, nfds, -1);
35    if(err < 0) {
36      break;
37    }
38    if(out && *out) {
39      if(fds[1].revents & POLLOUT) {
40        err = write(wfd, out, strlen(out));
41        if(err > 0) {
42          out += err;
43        }
44        if(err < 0) {
45          out = NULL;
46        }
47      }
48      if(!out || !*out || fds[1].revents & (POLLERR | POLLHUP)) {
49        close(wfd);
50        out = NULL;
51      }
52    }
53    if(fds[0].revents & POLLIN) {
54      err = read(rfd, buf, sizeof(buf));
55      if(err <= 0) {
56        break;
57      }
58      g_string_append_len(str, buf, err);
59    } else if(fds[0].revents & (POLLHUP | POLLERR)) {
60      err = 0;
61      break;
62    }
63  }
64
65  *in = g_string_free(str, err < 0);
66  return err;
67}
68
69int call_filter(const char *prog, const char *const *argv, const char *in, char **out, int *status)
70{
71  int err = 0;
72  pid_t pid;
73  int rfd[2];
74  int wfd[2];
75
76  if((err = pipe(rfd))) goto out;
77  if((err = pipe(wfd))) goto out_close_rfd;
78
79  pid = fork();
80  if(pid < 0) {
81    err = pid;
82    goto out_close_all;
83  }
84  if(pid) {
85    /* parent */
86    close(rfd[1]);
87    close(wfd[0]);
88    err = send_receive(rfd[0], wfd[1], in, out);
89    if(err == 0) {
90      waitpid(pid, status, 0);
91    }
92  } else {
93    /* child */
94    close(rfd[0]);
95    close(wfd[1]);
96    dup2(rfd[1], 1);
97    dup2(wfd[0], 0);
98    close(rfd[1]);
99    close(wfd[0]);
100
101    if(execvp(prog, (char *const *)argv)) {
102      _exit(-1);
103    }
104  }
105
106 out_close_all:
107  close(wfd[0]);
108  close(wfd[1]);
109 out_close_rfd:
110  close(rfd[0]);
111  close(rfd[1]);
112 out:
113  return err;
114}
Note: See TracBrowser for help on using the repository browser.