]> mj.ucw.cz Git - umpf.git/commitdiff
started with filtering mail
authorAnicka Bernathova <anicka@anicka.net>
Sun, 19 Jul 2009 21:48:41 +0000 (23:48 +0200)
committerAnicka Bernathova <anicka@anicka.net>
Sun, 19 Jul 2009 21:48:41 +0000 (23:48 +0200)
code.c
cond.y
ham.c
int.c
lex.c
umpf.h

diff --git a/code.c b/code.c
index 18fde4f9f6676e4d0b0d50dae78bcab8f197a957..59742fc9a8292c7241ca4241dafacacbdde840b6 100644 (file)
--- a/code.c
+++ b/code.c
@@ -297,6 +297,9 @@ do_arrow(struct tree* t, struct list* where)
                case K_DISCARD:
                        ins.opcode = OPC_DISCARD;
                        break;
+               case K_FILTER:
+                       ins.opcode = OPC_FILTER;
+                       break;
                default:
                        die("do_arrow: This cannot happen ;-)");
        }
@@ -428,6 +431,9 @@ print_code(void)
                        case OPC_PIPE:
                                printf("PIPE %d %d\n", p->u.arrow.what, p->u.arrow.copy);
                                break;
+                       case OPC_FILTER:
+                               printf("FILTER %d %d\n", p->u.arrow.what, p->u.arrow.copy);
+                               break;
                        case OPC_DELIVER:
                                printf("DELIVER %d %d\n", p->u.arrow.what, p->u.arrow.copy);
                                break;
diff --git a/cond.y b/cond.y
index 5410156de9db8915290caf5550d866641268f55f..38ec08c759112b110183dc1bebfbead8946fad5c 100644 (file)
--- a/cond.y
+++ b/cond.y
@@ -21,7 +21,7 @@ static struct tree* tree_malloc(int type);
 %token <n> NUM
 %token <str> VAR
 %token <n> KW_DISCARD
-%token <n> KW_PIPE KW_MAIL KW_COPY
+%token <n> KW_PIPE KW_MAIL KW_COPY KW_FILTER
 %token '(' ')' '{' '}' ';'
 %nonassoc KW_IF
 %nonassoc KW_ELSE
@@ -194,6 +194,7 @@ left:       /* empty */ { $$ = K_EMPTY;}
 right: /* empty */ { $$ = K_EMPTY; }
        | KW_PIPE { $$ = K_PIPE; }
        | KW_MAIL { $$ = K_MAIL; }
+       | KW_FILTER { $$ = K_FILTER; }
 ;
 
 ass_right_p:   '(' ass_right ')'       {$$ = $2; }
diff --git a/ham.c b/ham.c
index f8f96bd007fb7994af99b4d5fc2779fac2700f84..93e461c94fd9c5b06930592ac39d5bdb7379c537 100644 (file)
--- a/ham.c
+++ b/ham.c
@@ -297,6 +297,73 @@ write_email_to_fd(int fd, struct email* email)
        return 0;
 }
 
+int email_pos;
+int headers_sent;
+int email_opened;
+
+void
+open_email(void)
+{
+       email_pos = 0;
+       headers_sent = 0;
+       email_opened = 1;
+}
+
+char*
+read_email(struct email* em)
+{
+       char* buf;
+       int r, pos;
+
+       if (! email_opened) {
+               chars_written = 0;      
+               return NULL;
+       }
+
+       if (! headers_sent) {
+               struct hlist* ph;
+               int curbufsize = BUFSIZE;
+               buf = xmalloc(BUFSIZE);
+               pos = 0;
+
+               LIST_FOREACH(ph, em->headers){
+                       int needed = strlen(ph->name) + strlen(ph->value) + 3;
+                       if (curbufsize < pos + needed)
+                               buf = xrealloc(buf, curbufsize*=2);
+                       strcpy(buf + pos, ph->name);
+                       pos += strlen(ph->name);
+                       buf[pos++] = ':';
+                       strcpy(buf + pos, ph->value);
+                       pos += strlen(ph->value);
+                       buf[pos++] = '\n';
+       
+               }
+               buf[pos] = '\n';
+               headers_sent = 1;
+               chars_written = pos;
+               return buf;
+       }
+
+       if (em->body) {
+               buf = xstrdup(em->body);
+               chars_written = em->body_len; 
+               //printf("%d: %s\n", em->body_len, em->body); 
+               email_opened = 0;
+               return buf;
+       }
+
+       if (! email_pos)
+               lseek(em->fd, 0, SEEK_SET);
+
+       buf = xmalloc(MAIL_LEN + 1);
+       r = read(em->fd, buf, MAIL_LEN);
+       if (r < MAIL_LEN)
+               email_opened = 0;
+       chars_written = r;
+       
+       return buf;
+}
+
 int
 deliver_local_email(char* folder, struct email* email)
 {
diff --git a/int.c b/int.c
index e1c906f058342ada6c8d264876d5f4fcc48bed35..265003ee82568b9efd58683089aae82a9793b15e 100644 (file)
--- a/int.c
+++ b/int.c
@@ -8,6 +8,7 @@
 #include <stdarg.h>
 #include <sys/wait.h>
 #include <sysexits.h>
+#include <poll.h>
 
 #include "cond.tab.h"
 #include "umpf.h"
 
 #define INT_TO_STRING_LEN ((sizeof(int)*4*CHAR_BIT)/10 + 6)
 
+struct tmpfile {
+       int fd;
+       char* name;
+};
+
 void __attribute__ ((noreturn)) 
 bye(int code, char* msg, ...)
 {
@@ -433,6 +439,149 @@ end:
        }
 }
 
+static struct tmpfile* 
+pipe_to(char* program, struct email* em)
+{
+       int pd_in[2];
+       int pd_out[2];
+       int pid, status;
+       struct pollfd pfd[2];
+       char* name = xstrdup("/tmp/umpf.XXXXXX");
+       char buf[BUFSIZE];
+       int r;
+       int nfds = 2;
+       int data_pos = 0;
+       int fd = mkstemp(name);
+       struct tmpfile* tmp = xmalloc(sizeof(struct tmpfile));
+       char* e = NULL;
+       if (fd < 0)
+               return NULL;
+       
+       tmp->name = name;
+       tmp->fd = fd;
+
+       int res = pipe(pd_in);
+       if (res < 0)
+               goto bad;
+       res = pipe(pd_out);
+       if (res < 0)
+               goto bad;       
+
+       if ((pid = fork()) < 0)
+               goto bad;       
+       else if (pid == 0) {
+               close(0);
+               dup(pd_in[0]);
+
+               close(1);       
+               dup(pd_out[1]);
+
+               close(pd_in[0]);
+               close(pd_out[1]);
+               close(pd_in[1]);
+               close(pd_out[0]);
+               res = execl("/bin/sh", "sh", "-c", program, NULL);
+       }
+       close(pd_in[0]);
+       close(pd_out[1]);
+
+       pfd[1].fd = pd_in[1];
+       pfd[0].fd = pd_out[0];
+       pfd[1].events = POLLOUT;
+       pfd[0].events = POLLIN;
+
+       open_email();
+       for (;;) {
+               if (poll(pfd, nfds, -1) < 0)
+                       goto bad;
+               if ((pfd[0].revents & POLLERR) || (pfd[1].revents & POLLERR))
+                       goto bad;
+
+               if (pfd[0].revents & POLLIN) {
+                       r = read(pfd[0].fd, buf, BUFSIZE);
+                       if (r <= 0)
+                               break;
+                       write(fd, buf, r);
+               }
+               if (pfd[0].revents & POLLHUP)
+                       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);
+
+       return tmp;
+bad:
+       close(fd);
+       unlink(name);
+       return NULL;
+}
+
+static void
+do_filter(char* program, int copy, struct list* hash)
+{
+       struct email em = prepare_email(hash);
+       struct tmpfile* f;
+       int res = 0;
+       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);
+
+/*
+       FIXME: do some real work ;)
+
+       printf("Tmp filename %s, file is long %d\n", f->name, (int) pos);
+       
+       int i;
+       char c; 
+       for (i = 0; i < pos; i++) {
+               read(f->fd, &c, 1);
+               write(1, &c, 1);
+       }
+
+*/
+       unlink(f->name);
+       free(f);
+end:
+       destroy_email(em);
+       if (!copy) {
+               if (!res)
+                       bye(EX_TEMPFAIL, "%m");
+               else
+                       bye(0, NULL);
+       }
+}
+
 void
 interp(struct list* ins, struct list* hash)
 {
@@ -489,6 +638,10 @@ interp(struct list* ins, struct list* hash)
                        break;
                case OPC_PIPE:
                        break;
+               case OPC_FILTER:
+                       do_filter(get_var(p->u.arrow.what), 
+                               p->u.arrow.copy, hash);
+                       break;
                case OPC_MAIL:
                        send_mail(get_var(p->u.arrow.what), 
                                p->u.arrow.copy, hash);
@@ -497,8 +650,6 @@ interp(struct list* ins, struct list* hash)
                        deliver(get_var(p->u.arrow.what), 
                                p->u.arrow.copy, hash);
                        break;
-               case OPC_CALL_EXT:
-                       break;
                case OPC_DISCARD:
                        bye(0, NULL);
                        break;
diff --git a/lex.c b/lex.c
index 9f0201319dfa47818beeef380a1786f45e8992a5..4e4a10334ab08dcc502570d8a5d3398fa2213a33 100644 (file)
--- a/lex.c
+++ b/lex.c
@@ -19,7 +19,8 @@ static struct keys kwds[] =
                {"if", KW_IF}, 
                {"mail", KW_MAIL}, 
                {"pipe", KW_PIPE},
-               {"discard", KW_DISCARD}
+               {"discard", KW_DISCARD},
+               {"filter", KW_FILTER}
        };
 
 void
diff --git a/umpf.h b/umpf.h
index 7947ef37224a5424882aede606a26f92e72ddf65..32cd804e174d93edaa74863b07d8705e8d48e881 100644 (file)
--- a/umpf.h
+++ b/umpf.h
@@ -9,7 +9,8 @@ enum keyword {
        K_COPY,
        K_MAIL,
        K_PIPE,
-       K_EMPTY
+       K_EMPTY,
+       K_FILTER
 };
 
 struct tree {
@@ -100,7 +101,6 @@ struct code {
                OPC_JUMP_IF,
                OPC_JUMP_UNLESS,
                OPC_DELIVER,
-               OPC_CALL_EXT,
                OPC_NOP,
                OPC_CAT,
                OPC_GT,
@@ -121,6 +121,7 @@ struct code {
                OPC_DIV,
                OPC_PIPE,
                OPC_MAIL,
+               OPC_FILTER,
                OPC_DISCARD
        } opcode;
 
@@ -208,6 +209,7 @@ void __attribute__ ((noreturn)) bye(int code, char* msg, ...);
 
 /* ham.c */
 char* default_mailbox;
+int chars_written;
 
 struct list* current_headers;
 struct email* current_body;
@@ -216,6 +218,8 @@ void print_headers(struct list* l);
 struct email* get_body(void);
 int deliver_local_email(char* folder, struct email* email);
 int write_email_to_fd(int fd, struct email* email);
+char* read_email(struct email* em);
+void open_email(void);
 
 /* lock.c */
 void save_gids(void);