#include "sieve_interface.h"
#include "bytecode.h"
#include "script.h"
#include "xmalloc.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <netinet/in.h>
#include <string.h>
#include "map.h"
void dump2(bytecode_input_t *d, int len);
int dump2_test(bytecode_input_t * d, int i);
int unwrap_string(bytecode_input_t *bc, int pos, const char **str, int *len);
void fatal(const char *s, int code)
{
printf("Fatal error: %s (%d)\r\n", s, code);
exit(1);
}
int load(int fd, bytecode_input_t ** d)
{
const char * data=NULL;
struct stat sbuf;
unsigned long len=0;
if (fstat(fd, &sbuf) == -1) {
printf("IOERROR: fstating sieve script: %m");
return SIEVE_FAIL;
}
map_refresh(fd, 1, &(data), &len, sbuf.st_size,
"sievescript", "");
*d=(bytecode_input_t *)data;
printf("\n");
return (len/sizeof(int));
}
int main(int argc, char * argv[])
{
bytecode_input_t * bc;
int script_fd;
unsigned long len;
if (argc!=2) {
fprintf(stderr, "usage:\n %s script\n", argv[0]);
exit(1);
}
script_fd = open(argv[1], O_RDONLY);
if (script_fd == -1)
{
printf("can not open script '%s'\n", argv[1]);
exit(1);
}
len=load(script_fd,&bc);
close(script_fd);
if (bc) {
dump2(bc, len );
exit(0);
} else {
exit(1);
}
}
int write_list(int list_len, int i, bytecode_input_t * d)
{
int x;
i++;
for (x=0; x<list_len; x++)
{
const char *data;
int len;
i = unwrap_string(d, i, &data, &len);
printf("{%d}%s\n", len, data);
}
return i;
}
int printComparison(bytecode_input_t *d ,int i)
{
printf("Comparison: ");
switch(ntohl(d[i].value))
{
case B_IS: printf("Is"); break;
case B_CONTAINS:printf("Contains"); break;
case B_MATCHES: printf("Matches"); break;
case B_REGEX: printf("Regex"); break;
case B_COUNT:
printf("Count");
switch(ntohl(d[i+1].value))
{
case B_GT: printf(" greater than "); break;
case B_GE: printf(" greater than or equal "); break;
case B_LT: printf(" less than "); break;
case B_LE: printf(" less than or equal "); break;
case B_NE: printf(" not equal "); break;
case B_EQ: printf(" equal "); break;
}
break;
case B_VALUE:
printf("Value");
switch(ntohl(d[i+1].value))
{
case B_GT: printf(" greater than "); break;
case B_GE: printf(" greater than or equal ");break;
case B_LT: printf(" less than "); break;
case B_LE: printf(" less than or equal ");break;
case B_NE: printf(" not equal "); break;
case B_EQ: printf(" equal ");break;
}
break;
default:
exit(1);
}
switch (ntohl(d[i+2].value))
{
case B_ASCIICASEMAP: printf(" (ascii-casemap) "); break;
case B_OCTET: printf(" (octet) "); break;
case B_ASCIINUMERIC: printf(" (ascii-numeric) "); break;
default: exit(1);
}
printf("\n");
return i+3;
}
int dump2_test(bytecode_input_t * d, int i)
{
int l,x;
switch(ntohl(d[i].value)) {
case BC_FALSE:
printf("false");
i++;
break;
case BC_TRUE:
printf("true");
i++;
break;
case BC_NOT:
printf(" not(");
i=dump2_test(d, i+1);
printf(")\n");
break;
case BC_EXISTS:
printf("exists");
i=write_list(ntohl(d[i+1].len), i+2, d);
break;
case BC_SIZE:
printf("size");
if (ntohl(d[i+1].value)==B_OVER) {
printf("over %d", ntohl(d[i+2].value));
} else {
printf("under %d", ntohl(d[i+2].value));
}
i+=3;
break;
case BC_ANYOF:
printf("any of \n(");
l=ntohl(d[i+1].len);
i+=3;
for (x=0; x<l; x++)
{
i=dump2_test(d,i);
if((x+1)<l)
printf(" OR ");
}
printf(")\n");
break;
case BC_ALLOF:
printf("all of \n(");
l=ntohl(d[i+1].len);
i+=3;
for (x=0; x<l; x++)
{
i=dump2_test(d,i);
if((x+1)<l)
printf(" AND ");
}
printf(")\n");
break;
case BC_ADDRESS:
printf("Address (");
i=printComparison(d, i+1);
printf(" type: ");
switch(ntohl(d[i++].value))
{
case B_ALL: printf("all"); break;
case B_LOCALPART:printf("localpart"); break;
case B_DOMAIN:printf("domain"); break;
case B_USER:printf("user"); break;
case B_DETAIL:printf("detail"); break;
}
printf(" Headers:");
i=write_list(ntohl(d[i].len), i+1, d);
printf(" Data:");
i=write_list(ntohl(d[i].len), i+1, d);
printf(" ]\n");
break;
case BC_ENVELOPE:
printf("Envelope (");
i=printComparison(d, i+1);
printf(" type: ");
switch(ntohl(d[i++].value))
{
case B_ALL: printf("all"); break;
case B_LOCALPART:printf("localpart"); break;
case B_DOMAIN:printf("domain"); break;
case B_USER:printf("user"); break;
case B_DETAIL:printf("detail"); break;
}
printf(" Headers:");
i=write_list(ntohl(d[i].len), i+1, d);
printf(" Data:");
i=write_list(ntohl(d[i].len), i+1, d);
printf(" ]\n");
break;
case BC_HEADER:
printf("Header [");
i= printComparison(d, i+1);
printf(" Headers: ");
i=write_list(ntohl(d[i].len), i+1, d);
printf(" Data: ");
i=write_list(ntohl(d[i].len), i+1, d);
printf(" ]\n");
break;
default:
printf("WERT %d ", ntohl(d[i].value));
}
return i;
}
void dump2(bytecode_input_t *d, int bc_len)
{
int i;
const char *data;
int len;
if(memcmp(d, BYTECODE_MAGIC, BYTECODE_MAGIC_LEN)) {
printf("not a bytecode file [magic number test failed]\n");
return;
}
i = BYTECODE_MAGIC_LEN / sizeof(bytecode_input_t);
printf("Sievecode version %d\n", ntohl(d[i].op));
if(!d) return;
for(i++; i<bc_len;)
{
switch(ntohl(d[i].op)) {
case B_STOP:
printf("%d: STOP\n",i);
i++;
break;
case B_KEEP:
printf("%d: KEEP\n",i);
i++;
break;
case B_DISCARD:
printf("%d: DISCARD\n",i);
i++;
break;
case B_REJECT:
i = unwrap_string(d, i+1, &data, &len);
printf("%d: REJECT {%d}%s\n", i, len, data);
break;
case B_FILEINTO:
i = unwrap_string(d, i+1, &data, &len);
printf("%d: FILEINTO {%d}%s\n",i, len, data);
break;
case B_REDIRECT:
i = unwrap_string(d, i+1, &data, &len);
printf("%d: REDIRECT {%d}%s\n",i,len,data);
break;
case B_IF:
printf("%d: IF (ends at %d)",i, ntohl(d[i+1].value));
i = dump2_test(d,i+2);
printf("\n");
break;
case B_MARK:
printf("%d: MARK\n",i);
i++;
break;
case B_UNMARK:
printf("%d: UNMARK\n",i);
i++;
break;
case B_ADDFLAG:
printf("%d: ADDFLAG {%d}\n",i,ntohl(d[i+1].len));
i=write_list(ntohl(d[i+1].len),i+2,d);
break;
case B_SETFLAG:
printf("%d: SETFLAG {%d}\n",i,ntohl(d[i+1].len));
i=write_list(ntohl(d[i+1].len),i+2,d);
break;
case B_REMOVEFLAG:
printf("%d: REMOVEFLAG {%d}\n",i,ntohl(d[i+1].len));
i=write_list(ntohl(d[i+1].len),i+2,d);
break;
case B_DENOTIFY:
printf("%d: DENOTIFY\n",i);
i++;
printf(" PRIORITY(%d) Comparison type %d (relat %d)\n",
ntohl(d[i].value), ntohl(d[i+1].value), ntohl(d[i+2].value));
i+=3;
i = unwrap_string(d, i+1, &data, &len);
printf(" ({%d}%s)\n", len, (!data ? "[nil]" : data));
break;
case B_NOTIFY:
i = unwrap_string(d, i+1, &data, &len);
printf("%d: NOTIFY METHOD({%d}%s)\n",i,len,data);
i = unwrap_string(d, i, &data, &len);
printf(" ID({%d}%s) OPTIONS ", len,
(!data ? "[nil]" : data));
i=write_list(ntohl(d[i].len),i+1,d);
printf(" PRIORITY(%d)\n", ntohl(d[i].value));
i++;
i = unwrap_string(d, i, &data, &len);
printf(" MESSAGE({%d}%s)\n", len, data);
break;
case B_VACATION:
printf("%d: VACATION\n",i);
i=write_list(ntohl(d[i+1].len),i+2,d);
i = unwrap_string(d, i, &data, &len);
printf("%d SUBJ({%d}%s) \n",i, len, (!data ? "[nil]" : data));
i = unwrap_string(d, i, &data, &len);
printf("%d MESG({%d}%s) \n", i, len, (!data ? "[nil]" : data));
printf("DAYS(%d) MIME(%d)\n", ntohl(d[i].value), ntohl(d[i+1].value));
i+=2;
break;
case B_NULL:
printf("%d:NULL\n",i);
i++;
break;
case B_JUMP:
printf("%d:JUMP %d\n",i, ntohl(d[i+1].jump));
i+=2;
break;
default:
printf("%d: %d (NOT AN OP)\n",i,ntohl(d[i].op));
exit(1);
}
}
printf("full len is: %d\n", bc_len);
}