19 #define INT_TO_STRING_LEN ((sizeof(int)*4*CHAR_BIT)/10 + 6)
21 void __attribute__ ((noreturn))
22 bye(int code, char* msg, ...)
26 if (current_body->tmpfile)
27 unlink(current_body->tmpfile);
31 vfprintf(stderr, msg, args);
48 if ((var_tab[var] != NULL))
49 free_string(var_tab[var]);
53 set_var(int var, char* value)
56 var_tab[var] = xstrdup(value);
63 return xstrdup(const_tab[-var]);
64 return xstrdup(var_tab[var]);
67 /* return var struct or NULL if not found */
68 static struct variable*
69 get_var_struct(char* name, struct list* hash)
74 n = get_bucket_number(name);
75 int nocase = isupper(*name);
76 LIST_FOREACH(p, hash + n)
77 if (!(nocase ? strcasecmp : strcmp)(p->name,name))
84 regex_cmp(char* s, char* r)
89 int ovector[OVECCOUNT];
91 brum = pcre_compile(r,0,&error,&erroroffset,NULL);
95 int res = pcre_exec(brum,NULL,s,strlen(s),0,0,ovector,OVECCOUNT);
101 #define UPPER(a) ((a) >> 8)
102 #define LOWER(a) ((a) & 0xFF)
105 xcat(char* left, char* right)
107 char* res = xmalloc(strlen(left) + strlen(right) + 1);
119 fold(const char* value, int taken)
123 int len = strlen(value);
124 int newlines[len / 78 + 5];
130 if (len + taken <= 78)
131 return xstrdup(value);
132 for(i = 0; i < len; i++) {
133 if (value[i] == ' ' || value[i]=='\t')
138 newlines[newl++] = curr_ws;
140 while(value[i] && (value[i] == '\t'
148 ret = xmalloc(2*newl + len + 1);
149 for (i = 0; i < len; i++) {
150 if (newl_done == newl) {
151 strcpy(ret + pos, value + i);
154 if(i != newlines[newl_done])
155 ret[pos++] = value[i];
166 unfold(const char* u)
172 new = xmalloc(strlen(u)+1);
175 #define IS_WHITE(c) ((c) == '\t' || (c)==' ' || c=='\n')
177 while (IS_WHITE(*pu))
182 while (IS_WHITE(*pu))
195 modify_headers(struct list* headers, struct list* hash)
203 LIST_FOREACH(p, headers){
204 pv = get_var_struct(p->name, hash);
207 u = unfold(p->value);
208 value = get_var(pv->varcode);
209 if (strcmp(u, value)){
211 free_string(p->value);
212 p->value = fold(value,
213 strlen(p->name) + 2);
220 for (i = 0; i < HASHSIZE; i++){
221 LIST_FOREACH(pv, hash + i){
222 if (isupper(pv->name[0]) && pv->modified){
225 p = xmalloc(sizeof(struct hlist));
226 p->name = xstrdup(pv->name);
227 p->value = get_var(pv->varcode);
229 list_add_last(headers,&p->car);
236 copy_headers(struct list* orig)
238 struct list* new = xmalloc(sizeof(struct list));
239 struct hlist* po, *pn;
243 LIST_FOREACH(po, orig){
244 pn = xmalloc(sizeof(struct hlist));
245 pn->name = xstrdup(po->name);
246 pn->value = xstrdup(po->value);
249 list_add_last(new, &pn->car);
256 prepare_email(struct list* hash)
260 modify_headers(current_headers, hash);
261 em.headers = copy_headers(current_headers);
262 em.body_len = current_body->body_len;
263 em.fd = current_body->fd;
264 if (current_body->body) {
265 em.body = xmalloc(em.body_len);
266 memcpy(em.body, current_body->body, em.body_len);
269 em.tmpfile = xstrdup(current_body->tmpfile);
277 destroy_email(struct email em)
280 free_string(em.body);
282 free_string(em.tmpfile);
286 do_string_ternary_op(struct code* p)
288 char* l = get_var(p->u.tpop.l);
289 char* r = get_var(p->u.tpop.r);
294 result = xmalloc(INT_TO_STRING_LEN);
295 sprintf(result, "%d", regex_cmp(l, r));
298 result = xmalloc(INT_TO_STRING_LEN);
299 sprintf(result, "%d", !regex_cmp(l, r));
308 set_var(p->u.tpop.res, result);
312 do_num_ternary_op(struct code* p)
315 char* result = xmalloc(INT_TO_STRING_LEN);
317 sscanf(get_var(p->u.tpop.l),"%d", &l);
318 sscanf(get_var(p->u.tpop.r),"%d", &r);
346 res = ((l || r) && !(l && r));
364 sprintf(result, "%d", res);
365 set_var(p->u.tpop.res, result);
371 char* val = get_var(var);
378 sscanf(val, "%d", &v);
384 deliver(char* where, int copy, struct list* hash)
387 struct email em = prepare_email(hash);
389 res = deliver_local_email(where, &em);
395 bye(EX_TEMPFAIL, "%m");
402 send_mail(char* where, int copy, struct list* hash)
407 struct email em = prepare_email(hash);
413 if ((pid = fork()) < 0)
420 res = execl("/usr/lib/sendmail", "sendmail", where, NULL);
423 write_email_to_fd(pd[1], &em);
430 bye(EX_TEMPFAIL, "%m");
437 interp(struct list* ins, struct list* hash)
443 LIST_FOREACH(p, ins) {
446 set_var(p->u.set.l, get_var(p->u.set.r));
449 p = p->u.jump.target;
453 if (eval_cond(p->u.jump_if.cond))
454 p = p->u.jump_if.target;
457 case OPC_JUMP_UNLESS:
458 if (!eval_cond(p->u.jump_unless.cond))
459 p = p->u.jump_unless.target;
478 do_num_ternary_op(p);
481 result = xmalloc(INT_TO_STRING_LEN);
482 sscanf(get_var(p->u.tpop.l),"%d", &v);
483 sprintf(result, "%d", !v);
484 set_var(p->u.tpop.res, result);
488 do_string_ternary_op(p);
493 send_mail(get_var(p->u.arrow.what),
494 p->u.arrow.copy, hash);
497 deliver(get_var(p->u.arrow.what),
498 p->u.arrow.copy, hash);
506 deliver(default_mailbox, 0, hash);
510 print_vars(struct list* hash)
515 for (i=0; i<HASHSIZE; i++){
516 LIST_FOREACH(p, hash + i)
517 printf("%s=%s\n",p->name, get_var(p->varcode));
522 save_current_headers(struct list* hash)
528 LIST_FOREACH(p, current_headers){
529 pv = get_var_struct(p->name, hash);
532 u = unfold(p->value);
533 set_var(pv->varcode, u);