+ if (pfd[0].revents & POLLHUP) {
+ if (e)
+ free_string(e);
+ break;
+ }
+
+ if (nfds < 2)
+ continue;
+
+ if (pfd[1].revents & POLLOUT) {
+ if (!chars_written) {
+ e = read_email(em);
+ data_pos = 0;
+ if (!chars_written) {
+ close(pfd[1].fd);
+ nfds = 1;
+ continue;
+ }
+ }
+ if (data_pos < chars_written) {
+ r = write(pfd[1].fd, e + data_pos,
+ chars_written - data_pos);
+ data_pos += r;
+ } else {
+ free_string(e);
+ data_pos = 0;
+ e = read_email(em);
+ }
+ }
+ }
+
+ close(pd_out[0]);
+ wait(&status);
+
+ tmp->exit = WEXITSTATUS(status);
+ return tmp;
+bad:
+ close(fd);
+ unlink(name);
+ return NULL;
+}
+
+static void
+fix_content_length(struct list* h, int len)
+{
+ struct hlist* ph;
+ int found = 0;
+ char* clheader = "Content-Length: ";
+
+ LIST_FOREACH(ph, h) {
+ if (!strcasecmp("Content-Length", ph->name)) {
+ found = 1;
+ free_string(ph->value);
+ ph->value = xmalloc(INT_TO_STRING_LEN);
+ sprintf(ph->value, "%d", len);
+ break;
+ }
+ }
+ if (! found) {
+ char* buf, * tmpbuf;
+ buf = xmalloc(INT_TO_STRING_LEN + strlen(clheader));
+ tmpbuf = xmalloc(INT_TO_STRING_LEN);
+ sprintf(tmpbuf, "%d", len);
+ strcpy(buf, clheader);
+ strcat(buf, tmpbuf);
+ new_header(buf, h);
+ free_string(buf);
+ free_string(tmpbuf);
+ }
+}
+
+static void
+do_filter(char* program, struct list* hash)
+{
+ struct email em = prepare_email(hash);
+ struct procstat* f;
+ int res = 0;
+
+ f = pipe_to(program, &em);
+ if (!f) {
+ res++;
+ goto end;
+ }
+ lseek(f->fd, 0, SEEK_SET);
+
+ destroy_headers(current_headers);
+ destroy_body(current_body);
+ current_headers = make_hlist(f->fd);
+ current_body = get_body(f->fd);
+ fix_content_length(current_headers, current_body->body_len);
+ save_current_headers(hash);
+ set_cur_mail_length_var(curr_email_len, hash);
+ set_exit_code_var(f->exit, hash);
+
+ unlink(f->name);
+ free(f);
+end:
+ //FIXME: what to do with exit code when pipe failed?
+ destroy_email(em);
+}
+
+static void
+do_pipe(char* program, struct list* hash)
+{
+ struct email em = prepare_email(hash);
+ struct procstat* f;
+ int res = 0;
+ char* buf;
+ off_t pos;
+
+ f = pipe_to(program, &em);
+ if (!f) {
+ res++;
+ goto end;
+ }
+ pos = lseek(f->fd, 0, SEEK_END);
+ lseek(f->fd, 0, SEEK_SET);
+ buf = xmalloc(pos);
+
+ read(f->fd, buf, pos);
+ set_exit_code_var(f->exit, hash);
+ set_last_pipe_var(buf, hash);
+ free(buf);
+
+ unlink(f->name);
+ free(f);
+end:
+ destroy_email(em);
+}