20 #define INT_TO_STRING_LEN ((sizeof(int)*4*CHAR_BIT)/10 + 6)
27 void __attribute__ ((noreturn))
28 bye(int code, char* msg, ...)
32 if (current_body->tmpfile)
33 unlink(current_body->tmpfile);
37 vfprintf(stderr, msg, args);
54 if ((var_tab[var] != NULL))
55 free_string(var_tab[var]);
59 set_var(int var, char* value)
62 var_tab[var] = xstrdup(value);
69 return xstrdup(const_tab[-var]);
70 return xstrdup(var_tab[var]);
73 /* return var struct or NULL if not found */
74 static struct variable*
75 get_var_struct(char* name, struct list* hash)
80 n = get_bucket_number(name);
81 int nocase = isupper(*name);
82 LIST_FOREACH(p, hash + n)
83 if (!(nocase ? strcasecmp : strcmp)(p->name,name))
90 regex_cmp(char* s, char* r)
95 int ovector[OVECCOUNT];
97 brum = pcre_compile(r,0,&error,&erroroffset,NULL);
101 int res = pcre_exec(brum,NULL,s,strlen(s),0,0,ovector,OVECCOUNT);
107 #define UPPER(a) ((a) >> 8)
108 #define LOWER(a) ((a) & 0xFF)
111 xcat(char* left, char* right)
113 char* res = xmalloc(strlen(left) + strlen(right) + 1);
125 fold(const char* value, int taken)
129 int len = strlen(value);
130 int newlines[len / 78 + 5];
136 if (len + taken <= 78)
137 return xstrdup(value);
138 for(i = 0; i < len; i++) {
139 if (value[i] == ' ' || value[i]=='\t')
144 newlines[newl++] = curr_ws;
146 while(value[i] && (value[i] == '\t'
154 ret = xmalloc(2*newl + len + 1);
155 for (i = 0; i < len; i++) {
156 if (newl_done == newl) {
157 strcpy(ret + pos, value + i);
160 if(i != newlines[newl_done])
161 ret[pos++] = value[i];
172 unfold(const char* u)
178 new = xmalloc(strlen(u)+1);
181 #define IS_WHITE(c) ((c) == '\t' || (c)==' ' || c=='\n')
183 while (IS_WHITE(*pu))
188 while (IS_WHITE(*pu))
201 modify_headers(struct list* headers, struct list* hash)
209 LIST_FOREACH(p, headers){
210 pv = get_var_struct(p->name, hash);
213 u = unfold(p->value);
214 value = get_var(pv->varcode);
215 if (strcmp(u, value)){
217 free_string(p->value);
218 p->value = fold(value,
219 strlen(p->name) + 2);
226 for (i = 0; i < HASHSIZE; i++){
227 LIST_FOREACH(pv, hash + i){
228 if (isupper(pv->name[0]) && pv->modified){
231 p = xmalloc(sizeof(struct hlist));
232 p->name = xstrdup(pv->name);
233 p->value = get_var(pv->varcode);
235 list_add_last(headers,&p->car);
242 copy_headers(struct list* orig)
244 struct list* new = xmalloc(sizeof(struct list));
245 struct hlist* po, *pn;
249 LIST_FOREACH(po, orig){
250 pn = xmalloc(sizeof(struct hlist));
251 pn->name = xstrdup(po->name);
252 pn->value = xstrdup(po->value);
255 list_add_last(new, &pn->car);
262 prepare_email(struct list* hash)
266 modify_headers(current_headers, hash);
267 em.headers = copy_headers(current_headers);
268 em.body_len = current_body->body_len;
269 em.fd = current_body->fd;
270 if (current_body->body) {
271 em.body = xmalloc(em.body_len);
272 memcpy(em.body, current_body->body, em.body_len);
275 em.tmpfile = xstrdup(current_body->tmpfile);
283 destroy_email(struct email em)
286 free_string(em.body);
288 free_string(em.tmpfile);
292 do_string_ternary_op(struct code* p)
294 char* l = get_var(p->u.tpop.l);
295 char* r = get_var(p->u.tpop.r);
300 result = xmalloc(INT_TO_STRING_LEN);
301 sprintf(result, "%d", regex_cmp(l, r));
304 result = xmalloc(INT_TO_STRING_LEN);
305 sprintf(result, "%d", !regex_cmp(l, r));
314 set_var(p->u.tpop.res, result);
318 do_num_ternary_op(struct code* p)
321 char* result = xmalloc(INT_TO_STRING_LEN);
323 sscanf(get_var(p->u.tpop.l),"%d", &l);
324 sscanf(get_var(p->u.tpop.r),"%d", &r);
352 res = ((l || r) && !(l && r));
370 sprintf(result, "%d", res);
371 set_var(p->u.tpop.res, result);
377 char* val = get_var(var);
384 sscanf(val, "%d", &v);
390 deliver(char* where, int copy, struct list* hash)
393 struct email em = prepare_email(hash);
395 res = deliver_local_email(where, &em);
401 bye(EX_TEMPFAIL, "%m");
408 send_mail(char* where, int copy, struct list* hash)
413 struct email em = prepare_email(hash);
419 if ((pid = fork()) < 0)
426 res = execl("/usr/lib/sendmail", "sendmail", where, NULL);
429 write_email_to_fd(pd[1], &em);
436 bye(EX_TEMPFAIL, "%m");
442 static struct tmpfile*
443 pipe_to(char* program, struct email* em)
448 struct pollfd pfd[2];
449 char* name = xstrdup("/tmp/umpf.XXXXXX");
454 int fd = mkstemp(name);
455 struct tmpfile* tmp = xmalloc(sizeof(struct tmpfile));
463 int res = pipe(pd_in);
470 if ((pid = fork()) < 0)
483 res = execl("/bin/sh", "sh", "-c", program, NULL);
488 pfd[1].fd = pd_in[1];
489 pfd[0].fd = pd_out[0];
490 pfd[1].events = POLLOUT;
491 pfd[0].events = POLLIN;
495 if (poll(pfd, nfds, -1) < 0)
497 if ((pfd[0].revents & POLLERR) || (pfd[1].revents & POLLERR))
500 if (pfd[0].revents & POLLIN) {
501 r = read(pfd[0].fd, buf, BUFSIZE);
506 if (pfd[0].revents & POLLHUP)
512 if (pfd[1].revents & POLLOUT) {
513 if (!chars_written) {
516 if (!chars_written) {
522 if (data_pos < chars_written) {
523 r = write(pfd[1].fd, e + data_pos,
524 chars_written - data_pos);
545 do_filter(char* program, int copy, struct list* hash)
547 struct email em = prepare_email(hash);
552 f = pipe_to(program, &em);
557 pos = lseek(f->fd, 0, SEEK_END);
558 lseek(f->fd, 0, SEEK_SET);
561 FIXME: do some real work ;)
563 printf("Tmp filename %s, file is long %d\n", f->name, (int) pos);
567 for (i = 0; i < pos; i++) {
579 bye(EX_TEMPFAIL, "%m");
586 interp(struct list* ins, struct list* hash)
592 LIST_FOREACH(p, ins) {
595 set_var(p->u.set.l, get_var(p->u.set.r));
598 p = p->u.jump.target;
602 if (eval_cond(p->u.jump_if.cond))
603 p = p->u.jump_if.target;
606 case OPC_JUMP_UNLESS:
607 if (!eval_cond(p->u.jump_unless.cond))
608 p = p->u.jump_unless.target;
627 do_num_ternary_op(p);
630 result = xmalloc(INT_TO_STRING_LEN);
631 sscanf(get_var(p->u.tpop.l),"%d", &v);
632 sprintf(result, "%d", !v);
633 set_var(p->u.tpop.res, result);
637 do_string_ternary_op(p);
642 do_filter(get_var(p->u.arrow.what),
643 p->u.arrow.copy, hash);
646 send_mail(get_var(p->u.arrow.what),
647 p->u.arrow.copy, hash);
650 deliver(get_var(p->u.arrow.what),
651 p->u.arrow.copy, hash);
657 deliver(default_mailbox, 0, hash);
661 print_vars(struct list* hash)
666 for (i=0; i<HASHSIZE; i++){
667 LIST_FOREACH(p, hash + i)
668 printf("%s=%s\n",p->name, get_var(p->varcode));
673 save_current_headers(struct list* hash)
679 LIST_FOREACH(p, current_headers){
680 pv = get_var_struct(p->name, hash);
683 u = unfold(p->value);
684 set_var(pv->varcode, u);