20 #define INT_TO_STRING_LEN ((sizeof(int)*4*CHAR_BIT)/10 + 6)
28 void __attribute__ ((noreturn))
29 bye(int code, char* msg, ...)
33 if (current_body->tmpfile)
34 unlink(current_body->tmpfile);
38 vfprintf(stderr, msg, args);
55 if ((var_tab[var] != NULL))
56 free_string(var_tab[var]);
60 set_var(int var, char* value)
63 var_tab[var] = xstrdup(value);
70 return xstrdup(const_tab[-var]);
71 return xstrdup(var_tab[var]);
75 regex_cmp(char* s, char* r)
80 int ovector[OVECCOUNT];
82 brum = pcre_compile(r,0,&error,&erroroffset,NULL);
86 int res = pcre_exec(brum,NULL,s,strlen(s),0,0,ovector,OVECCOUNT);
92 #define UPPER(a) ((a) >> 8)
93 #define LOWER(a) ((a) & 0xFF)
96 xcat(char* left, char* right)
98 char* res = xmalloc(strlen(left) + strlen(right) + 1);
110 fold(const char* value, int taken)
114 int len = strlen(value);
115 int newlines[len / 78 + 5];
121 if (len + taken <= 78)
122 return xstrdup(value);
123 for(i = 0; i < len; i++) {
124 if (value[i] == ' ' || value[i]=='\t')
129 newlines[newl++] = curr_ws;
131 while(value[i] && (value[i] == '\t'
139 ret = xmalloc(2*newl + len + 1);
140 for (i = 0; i < len; i++) {
141 if (newl_done == newl) {
142 strcpy(ret + pos, value + i);
145 if(i != newlines[newl_done])
146 ret[pos++] = value[i];
157 unfold(const char* u)
163 new = xmalloc(strlen(u)+1);
166 #define IS_WHITE(c) ((c) == '\t' || (c)==' ' || c=='\n')
168 while (IS_WHITE(*pu))
173 while (IS_WHITE(*pu))
186 modify_headers(struct list* headers, struct list* hash)
194 LIST_FOREACH(p, headers){
195 pv = get_var_struct(p->name, VAR_HEADER, hash);
198 u = unfold(p->value);
199 value = get_var(pv->varcode);
200 if (strcmp(u, value)){
202 free_string(p->value);
203 p->value = fold(value,
204 strlen(p->name) + 2);
211 for (i = 0; i < HASHSIZE; i++){
212 LIST_FOREACH(pv, hash + i){
213 if (pv->type == VAR_HEADER && pv->modified){
216 p = xmalloc(sizeof(struct hlist));
217 p->name = xstrdup(pv->name);
218 p->value = get_var(pv->varcode);
220 list_add_last(headers, &p->car);
227 copy_headers(struct list* orig)
229 struct list* new = xmalloc(sizeof(struct list));
230 struct hlist* po, *pn;
234 LIST_FOREACH(po, orig){
235 pn = xmalloc(sizeof(struct hlist));
236 pn->name = xstrdup(po->name);
237 pn->value = xstrdup(po->value);
240 list_add_last(new, &pn->car);
247 prepare_email(struct list* hash)
251 modify_headers(current_headers, hash);
252 em.headers = copy_headers(current_headers);
253 em.body_len = current_body->body_len;
254 em.fd = current_body->fd;
255 if (current_body->body) {
256 em.body = xmalloc(em.body_len);
257 memcpy(em.body, current_body->body, em.body_len);
260 em.tmpfile = xstrdup(current_body->tmpfile);
268 destroy_headers(struct list* h)
272 while ((p = list_del_last(h))) {
281 destroy_body(struct email* b)
292 destroy_email(struct email em)
294 destroy_headers(em.headers);
299 do_string_ternary_op(struct code* p)
301 char* l = get_var(p->u.tpop.l);
302 char* r = get_var(p->u.tpop.r);
307 result = xmalloc(INT_TO_STRING_LEN);
308 sprintf(result, "%d", regex_cmp(l, r));
311 result = xmalloc(INT_TO_STRING_LEN);
312 sprintf(result, "%d", !regex_cmp(l, r));
321 set_var(p->u.tpop.res, result);
325 do_num_ternary_op(struct code* p)
328 char* result = xmalloc(INT_TO_STRING_LEN);
330 sscanf(get_var(p->u.tpop.l),"%d", &l);
331 sscanf(get_var(p->u.tpop.r),"%d", &r);
359 res = ((l || r) && !(l && r));
377 sprintf(result, "%d", res);
378 set_var(p->u.tpop.res, result);
384 char* val = get_var(var);
391 sscanf(val, "%d", &v);
397 deliver(char* where, int copy, struct list* hash)
400 struct email em = prepare_email(hash);
402 res = deliver_local_email(where, &em);
408 bye(EX_TEMPFAIL, "%m");
415 send_mail(char* where, int copy, struct list* hash)
420 struct email em = prepare_email(hash);
426 if ((pid = fork()) < 0)
433 res = execl("/usr/lib/sendmail", "sendmail", where, NULL);
436 write_email_to_fd(pd[1], &em);
443 bye(EX_TEMPFAIL, "%m");
449 static struct procstat*
450 pipe_to(char* program, struct email* em)
455 struct pollfd pfd[2];
456 char* name = xstrdup("/tmp/umpf.XXXXXX");
461 int fd = mkstemp(name);
462 struct procstat* tmp = xmalloc(sizeof(struct procstat));
470 int res = pipe(pd_in);
477 if ((pid = fork()) < 0)
490 res = execl("/bin/sh", "sh", "-c", program, NULL);
495 pfd[1].fd = pd_in[1];
496 pfd[0].fd = pd_out[0];
497 pfd[1].events = POLLOUT;
498 pfd[0].events = POLLIN;
502 if (poll(pfd, nfds, -1) < 0)
504 if ((pfd[0].revents & POLLERR) || (pfd[1].revents & POLLERR))
507 if (pfd[0].revents & POLLIN) {
508 r = read(pfd[0].fd, buf, BUFSIZE);
513 if (pfd[0].revents & POLLHUP)
519 if (pfd[1].revents & POLLOUT) {
520 if (!chars_written) {
523 if (!chars_written) {
529 if (data_pos < chars_written) {
530 r = write(pfd[1].fd, e + data_pos,
531 chars_written - data_pos);
544 tmp->exit = WEXITSTATUS(status);
553 do_filter(char* program, struct list* hash)
555 struct email em = prepare_email(hash);
559 f = pipe_to(program, &em);
564 lseek(f->fd, 0, SEEK_SET);
566 destroy_headers(current_headers);
567 destroy_body(current_body);
568 current_headers = make_hlist(f->fd);
569 current_body = get_body(f->fd);
570 // set_cur_mail_length_var(current_email_len);
571 // set_exit_code_var(f->exit);
576 //FIXME: what to do with exit code when pipe failed?
581 do_pipe(char* program, struct list* hash)
583 struct email em = prepare_email(hash);
589 f = pipe_to(program, &em);
594 pos = lseek(f->fd, 0, SEEK_END);
595 lseek(f->fd, 0, SEEK_SET);
598 read(f->fd, buf, pos);
599 //set_last_pipe_var(buf);
609 interp(struct list* ins, struct list* hash)
615 LIST_FOREACH(p, ins) {
618 set_var(p->u.set.l, get_var(p->u.set.r));
621 p = p->u.jump.target;
625 if (eval_cond(p->u.jump_if.cond))
626 p = p->u.jump_if.target;
629 case OPC_JUMP_UNLESS:
630 if (!eval_cond(p->u.jump_unless.cond))
631 p = p->u.jump_unless.target;
650 do_num_ternary_op(p);
653 result = xmalloc(INT_TO_STRING_LEN);
654 sscanf(get_var(p->u.tpop.l),"%d", &v);
655 sprintf(result, "%d", !v);
656 set_var(p->u.tpop.res, result);
660 do_string_ternary_op(p);
663 do_pipe(get_var(p->u.arrow.what), hash);
666 do_filter(get_var(p->u.arrow.what), hash);
669 send_mail(get_var(p->u.arrow.what),
670 p->u.arrow.copy, hash);
673 deliver(get_var(p->u.arrow.what),
674 p->u.arrow.copy, hash);
680 deliver(default_mailbox, 0, hash);
684 print_vars(struct list* hash)
689 for (i=0; i<HASHSIZE; i++){
690 LIST_FOREACH(p, hash + i)
691 printf("%s=%s\n",p->name, get_var(p->varcode));
696 save_current_headers(struct list* hash)
702 LIST_FOREACH(p, current_headers){
703 pv = get_var_struct(p->name, VAR_HEADER, hash);
706 u = unfold(p->value);
707 set_var(pv->varcode, u);