source: filterproc.c @ 5aa33fd

release-1.10release-1.6release-1.7release-1.8release-1.9
Last change on this file since 5aa33fd was d564c3d, checked in by Nelson Elhage <nelhage@ksplice.com>, 15 years ago
Replace the built-in zcrypt with shelling out to the zcrypt binary.
  • Property mode set to 100644
File size: 2.3 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  struct sigaction sig = {.sa_handler = SIG_IGN}, old;
20
21  fcntl(rfd, F_SETFL, O_NONBLOCK | fcntl(rfd, F_GETFL));
22  fcntl(wfd, F_SETFL, O_NONBLOCK | fcntl(wfd, F_GETFL));
23
24  fds[0].fd = rfd;
25  fds[0].events = POLLIN;
26  fds[1].fd = wfd;
27  fds[1].events = POLLOUT;
28
29  sigaction(SIGPIPE, &sig, &old);
30 
31  while(1) {
32    if(out && *out) {
33      nfds = 2;
34    } else {
35      nfds = 1;
36    }
37    err = poll(fds, nfds, -1);
38    if(err < 0) {
39      break;
40    }
41    if(out && *out) {
42      if(fds[1].revents & POLLOUT) {
43        err = write(wfd, out, strlen(out));
44        if(err > 0) {
45          out += err;
46        }
47        if(err < 0) {
48          out = NULL;
49        }
50      }
51      if(!out || !*out || fds[1].revents & (POLLERR | POLLHUP)) {
52        close(wfd);
53        out = NULL;
54      }
55    }
56    if(fds[0].revents & POLLIN) {
57      err = read(rfd, buf, sizeof(buf));
58      if(err <= 0) {
59        break;
60      }
61      g_string_append_len(str, buf, err);
62    } else if(fds[0].revents & (POLLHUP | POLLERR)) {
63      err = 0;
64      break;
65    }
66  }
67
68  *in = g_string_free(str, err < 0);
69  sigaction(SIGPIPE, &old, NULL);
70  return err;
71}
72
73int call_filter(const char *prog, const char *const *argv, const char *in, char **out, int *status)
74{
75  int err = 0;
76  pid_t pid;
77  int rfd[2];
78  int wfd[2];
79
80  if((err = pipe(rfd))) goto out;
81  if((err = pipe(wfd))) goto out_close_rfd;
82
83  pid = fork();
84  if(pid < 0) {
85    err = pid;
86    goto out_close_all;
87  }
88  if(pid) {
89    /* parent */
90    close(rfd[1]);
91    close(wfd[0]);
92    err = send_receive(rfd[0], wfd[1], in, out);
93    if(err == 0) {
94      waitpid(pid, status, 0);
95    }
96  } else {
97    /* child */
98    close(rfd[0]);
99    close(wfd[1]);
100    dup2(rfd[1], 1);
101    dup2(wfd[0], 0);
102    close(rfd[1]);
103    close(wfd[0]);
104
105    if(execvp(prog, (char *const *)argv)) {
106      _exit(-1);
107    }
108  }
109
110 out_close_all:
111  close(wfd[0]);
112  close(wfd[1]);
113 out_close_rfd:
114  close(rfd[0]);
115  close(rfd[1]);
116 out:
117  return err;
118}
Note: See TracBrowser for help on using the repository browser.