예제 #1
0
/* Write out a testlist to a given file descriptor.
 * return # of bytes written on success and -1 on error */
static int bc_testlist_emit(int fd, int *codep, bytecode_info_t *bc)
{
    int len = bc->data[(*codep)++].len;
    int i;
    int ret;
    int begin, end;
    int wrote = 2*sizeof(int);

    /* Write out number of items in the list */
    if(write_int(fd, len)== -1) return -1;

    /* skip one spot for end of list position*/
    begin = lseek(fd, 0, SEEK_CUR);
    lseek(fd, sizeof(int), SEEK_CUR);

    /* Loop through all the items of the list, writing out each
     * test as we reach it in sequence. */
    for(i=0; i < len; i++) {
        int nextcodep = bc->data[(*codep)++].jump;

        ret = bc_test_emit(fd, codep, bc);
        if(ret < 0 ) return -1;

        wrote+=ret;
        *codep = nextcodep;
    }
    end = lseek(fd, 0, SEEK_CUR);
    if (end < 0) return -1;

    /* go back and write the end of list position */
    lseek(fd,begin,SEEK_SET);
    if(write_int(fd, end) == -1) return -1;

    /*return to the end */
    lseek(fd,end,SEEK_SET);

    return wrote;
}
예제 #2
0
/* emit the bytecode to a file descriptor given a flattened parse tree
 * returns -1 on failure, size of emitted bytecode on success.
 *
 * this takes care of everything except the comparisons */
static int bc_action_emit(int fd, int codep, int stopcodep,
                          bytecode_info_t *bc, int filelen)
{
    int len; /* Temporary Length Variable */
    int ret; /* Temporary Return Value Variable */
    int start_filelen = filelen;
    int i;

    /*debugging variable to check filelen*/
    /*int location;*/

    syslog(LOG_DEBUG, "entered bc_action_emit with filelen: %d", filelen);

    /* All non-string data MUST be sizeof(int)
       byte alligned so the end of each string may require a pad */
    /*
     * Note that for purposes of jumps you must multiply codep by sizeof(int)
     */
    while(codep < stopcodep) {
        /* Output this opcode */
        if(write_int(fd, bc->data[codep].op) == -1)
            return -1;

        filelen+=sizeof(int);

        switch(bc->data[codep++].op) {

        case B_IF:
        {
            /* IF
             *  test
             *  jump (false condition)
             *  then
             * (if there is an else) jump(finish)
             * (if there is an else) else
             */

            int testEndLoc=-1;
            int testdist, thendist, elsedist;
            int c;

            int jumpFalseLoc=-1;/*this is the location that is being reserved
                                  for the first jump command
                                  we jump to the false condition of the test*/

            int jumpEndLoc=-1; /* this is the location that is being reserved
                                  for the optional jump command
                                  it jumps over the else statement to the end*/
            int jumpto=-1;
            int jumpop= B_JUMP;

            /*leave space to store the location of end of the test*/
            ret = lseek(fd, sizeof(int), SEEK_CUR);
            if(ret == -1) return ret;

            testEndLoc=filelen;
            filelen+=sizeof(int);

            /* spew the test */

            c=codep+3;
            testdist = bc_test_emit(fd, &c, bc);
            if(testdist == -1)return -1;
            filelen +=testdist;

            /*store the location for the end of the test
             *this is important for short circuiting of allof/anyof*/
            jumpto=filelen/4;
            if(lseek(fd, testEndLoc, SEEK_SET) == -1)
                return -1;
            if(write_int(fd,jumpto) == -1)
                return -1;

            if(lseek(fd,filelen,SEEK_SET) == -1)
                return -1;

            /* leave space for jump */
            if(write_int(fd, jumpop) == -1)
                return -1;
            ret = lseek(fd, sizeof(int), SEEK_CUR);
            if(ret == -1)
                return ret;
            jumpFalseLoc=filelen+sizeof(int);

            filelen +=2*sizeof(int); /*jumpop + jump*/

            /* spew the then code */
            thendist = bc_action_emit(fd, bc->data[codep].value,
                                      bc->data[codep+1].value, bc,
                                      filelen);

            filelen+=thendist;

            /* there is an else case */
            if(bc->data[codep+2].value != -1)
            {
                /* leave space for jump */
                if(write_int(fd, jumpop) == -1)
                    return -1;
                ret = lseek(fd, sizeof(int), SEEK_CUR);
                if(ret == -1)
                    return ret;

                jumpEndLoc=filelen+sizeof(int);
                filelen+=2*sizeof(int);/*jumpop + jump*/
            }

            /*put previous jump to the end of the then code,
             *or the end of the jump if there is an else case */
            jumpto=filelen/4;
            if(lseek(fd, jumpFalseLoc, SEEK_SET) == -1)
                return -1;
            if(write_int(fd,jumpto) == -1)
                return -1;
            if(lseek(fd,filelen,SEEK_SET) == -1)
                return -1;

            /* there is an else case */
            if(bc->data[codep+2].value != -1) {
                /* spew the else code */
                elsedist = bc_action_emit(fd, bc->data[codep+1].value,
                                         bc->data[codep+2].value, bc,
                                         filelen);

                filelen+=elsedist;

                /*put jump to the end of the else code*/
                jumpto=filelen/4;
                if(lseek(fd, jumpEndLoc, SEEK_SET) == -1)
                    return -1;
                if(write_int(fd,jumpto) == -1)
                    return -1;
                if(lseek(fd,filelen,SEEK_SET) == -1)
                    return -1;

                codep = bc->data[codep+2].value;
            } else {
                codep = bc->data[codep+1].value;
            }

            break;
        }

        case B_KEEP:
            /* Flags Stringlist, Copy (word) */

            /* Dump a stringlist of flags */
            ret = bc_stringlist_emit(fd, &codep, bc);
            if(ret < 0)
                return -1;
            filelen += ret;

            if(write_int(fd,bc->data[codep++].value) == -1)
                return -1;

            filelen += sizeof(int);
            break;

        case B_FILEINTO:
            /* Flags Stringlist, Copy (word), Folder String */

            /* Dump a stringlist of flags */
            ret = bc_stringlist_emit(fd, &codep, bc);
            if(ret < 0)
                return -1;
            filelen += ret;

            /* Write Copy */
            if(write_int(fd,bc->data[codep++].value) == -1)
                return -1;

            filelen += sizeof(int);

            /* Write string length of Folder */
            len = bc->data[codep++].len;
            if(write_int(fd,len) == -1)
                return -1;

            filelen+=sizeof(int);

            /* Write Folder */
            if(write(fd,bc->data[codep++].str,len) == -1)
                return -1;

            ret = align_string(fd, len);
            if(ret == -1)
                return -1;

            filelen += len + ret;

            break;

        case B_REDIRECT:
            /* Copy (word), Address String */

            if(write_int(fd,bc->data[codep++].value) == -1)
                return -1;

            filelen += sizeof(int);

            len = bc->data[codep++].len;
            if(write_int(fd,len) == -1)
                return -1;

            filelen+=sizeof(int);

            if(write(fd,bc->data[codep++].str,len) == -1)
                return -1;

            ret = align_string(fd, len);
            if(ret == -1)
                return -1;

            filelen += len + ret;

            break;

        case B_REJECT:
            /*just a string*/
            len = bc->data[codep++].len;
            if(write_int(fd,len) == -1)
                return -1;

            filelen+=sizeof(int);

            if(write(fd,bc->data[codep++].str,len) == -1)
                return -1;

            ret = align_string(fd, len);
            if(ret == -1)
                return -1;

            filelen += len + ret;

            break;

        case B_SETFLAG:
        case B_ADDFLAG:
        case B_REMOVEFLAG:
            /* Dump just a stringlist */
            ret = bc_stringlist_emit(fd, &codep, bc);
            if(ret < 0)
                return -1;
            filelen += ret;
            break;

        case B_NOTIFY:
            /* method string, id string, options string list,
               priotity, Message String */
            /*method and id*/
            for(i=0; i<2; i++) {
                len = bc->data[codep++].len;
                if(write_int(fd,len) == -1)
                    return -1;
                filelen += sizeof(int);
                if(len == -1)
                {
                    /* this will probably only happen for the id */
                    /* this is a nil string */
                    /* skip the null pointer and make up for it
                     * by adjusting the offset */
                    codep++;
                }
                else
                {
                    if(write(fd,bc->data[codep++].str,len) == -1)
                        return -1;

                    ret = align_string(fd, len);
                    if(ret == -1)
                        return -1;

                    filelen += len + ret;
                }

            }
            /*options */
            ret = bc_stringlist_emit(fd, &codep, bc);
            if(ret < 0)
                return -1;
            filelen+=ret;

            /*priority*/
            if(write_int(fd, bc->data[codep].value) == -1)
                return -1;
            codep++;
            filelen += sizeof(int);

            len = bc->data[codep++].len;
            if(write_int(fd,len) == -1)
                return -1;
            filelen += sizeof(int);

            if(write(fd,bc->data[codep++].str,len) == -1)
                return -1;

            ret = align_string(fd, len);
            if(ret == -1) return -1;

            filelen += len + ret;
            break;


        case B_DENOTIFY:
            /* priority num,comptype  num,relat num, comp string*/

            /* priority*/
            if(write_int(fd, bc->data[codep].value) == -1)
                return -1;
            filelen += sizeof(int);
            codep++;
            /* comptype */
            if(write_int(fd, bc->data[codep].value) == -1)
                return -1;
            filelen += sizeof(int);
            codep++;
            /* relational*/
            if(write_int(fd, bc->data[codep].value) == -1)
                return -1;
            filelen += sizeof(int);
            codep++;
            /* comp string*/

            len = bc->data[codep++].len;
            if(write_int(fd,len) == -1)
                return -1;
            filelen += sizeof(int);

            if(len == -1)
            {
                /* this is a nil string */
                /* skip the null pointer and make up for it
                 * by adjusting the offset */
                codep++;
            }
            else
            {
                if(write(fd,bc->data[codep++].str,len) == -1)
                    return -1;

                ret = align_string(fd, len);
                if(ret == -1) return -1;

                filelen += len + ret;
            }
                    break;
        case B_VACATION:
            /* Address list, Subject String, Message String,
               Seconds (word), Mime (word), From String, Handle String */

                /*new code-this might be broken*/
            ret = bc_stringlist_emit(fd, &codep, bc);
            if(ret < 0) return -1;
            filelen += ret;
            /*end of new code*/

            for(i=0; i<2; i++) {/*writing strings*/

                /*write length of string*/
                len = bc->data[codep++].len;
                if(write_int(fd,len) == -1)
                    return -1;
                filelen += sizeof(int);

                if(len == -1)
                {
                    /* this is a nil string */
                    /* skip the null pointer and make up for it
                     * by adjusting the offset */
                    codep++;
                }
                else
                {
                    /*write string*/
                    if(write(fd,bc->data[codep++].str,len) == -1)
                        return -1;

                    ret = align_string(fd, len);
                    if(ret == -1) return -1;

                    filelen += len + ret;
                }

            }
            /* Seconds*/
            if(write_int(fd,bc->data[codep].value) == -1)
                return -1;
            codep++;
            filelen += sizeof(int);
            /*Mime */
            if(write_int(fd,bc->data[codep].value) == -1)
                return -1;
            codep++;

            for(i=0; i<2; i++) {/*writing strings*/

                /*write length of string*/
                len = bc->data[codep++].len;
                if(write_int(fd,len) == -1)
                    return -1;
                filelen += sizeof(int);

                if(len == -1)
                {
                    /* this is a nil string */
                    /* skip the null pointer and make up for it
                     * by adjusting the offset */
                    codep++;
                }
                else
                {
                    /*write string*/
                    if(write(fd,bc->data[codep++].str,len) == -1)
                        return -1;

                    ret = align_string(fd, len);
                    if(ret == -1) return -1;

                    filelen += len + ret;
                }

            }
            filelen += sizeof(int);

            break;
        case B_INCLUDE:
            /* Location + (Once<<6) + (Optional<<7) (word), Filename String */

            /* Location + (Once<<6) + (Optional<<7) */
            if(write_int(fd, bc->data[codep].value) == -1)
                return -1;
            filelen += sizeof(int);
            codep++;
            /* Filename */
            len = bc->data[codep++].len;
            if(write_int(fd,len) == -1)
                return -1;

            filelen += sizeof(int);

            if(write(fd,bc->data[codep++].str,len) == -1)
                return -1;

            ret = align_string(fd, len);
            if(ret == -1) return -1;

            filelen += len + ret;
            break;
        case B_NULL:
        case B_STOP:
        case B_DISCARD:
        case B_MARK:
        case B_UNMARK:
        case B_RETURN:
            /* No Parameters! */
            break;

        default:
            /* Unknown opcode? */
            return -1;
        }
    }
    return filelen - start_filelen;
}
예제 #3
0
/* emit the bytecode for a test.  returns -1 on failure or size of
 * emitted bytecode on success */
static int bc_test_emit(int fd, int *codep, bytecode_info_t *bc)
{
    int opcode;
    int wrote=0;/* Relative offset to account for interleaved strings */

    int ret; /* Temporary Return Value Variable */

    /* Output this opcode */
    opcode = bc->data[(*codep)++].op;
    if(write_int(fd, opcode) == -1)
        return -1;
    wrote += sizeof(int);

    switch(opcode) {
    case BC_TRUE:
    case BC_FALSE:
        /* No parameter opcodes */
        break;

    case BC_NOT:
    {
        /* Single parameter: another test */
        ret = bc_test_emit(fd, codep, bc);
        if(ret < 0)
            return -1;
        else
            wrote+=ret;
        break;
    }

    case BC_ALLOF:
    case BC_ANYOF:
        /*where we jump to?*/
        /* Just drop a testlist */
        ret = bc_testlist_emit(fd, codep, bc);
        if(ret < 0)
            return -1;
        else
            wrote+=ret;
        break;

    case BC_SIZE:
        /* Drop tag and number */
        if(write_int(fd, bc->data[(*codep)].value) == -1)
            return -1;
        if(write_int(fd, bc->data[(*codep)+1].value) == -1)
            return -1;

        wrote += 2 * sizeof(int);
        (*codep) += 2;
        break;

    case BC_EXISTS:
    {
        int ret;
        ret = bc_stringlist_emit(fd, codep, bc);
        if(ret < 0) return -1;
        wrote += ret;
        break;
    }

    case BC_HEADER:
    case BC_HASFLAG:
    {
        int ret;
        if (BC_HEADER == opcode) {
        /* drop index */
        if(write_int(fd, bc->data[(*codep)].value) == -1)
            return -1;
        wrote += sizeof(int);
        (*codep)++;
        }
        /* Drop match type */
        if(write_int(fd, bc->data[(*codep)].value) == -1)
            return -1;
        wrote += sizeof(int);
        (*codep)++;
        /*now drop relation*/
        if(write_int(fd, bc->data[(*codep)].value) == -1)
            return -1;
        wrote += sizeof(int);
        (*codep)++;
        /*drop comparator */
        if(write_int(fd, bc->data[(*codep)].value) == -1)
            return -1;
        wrote += sizeof(int);
        (*codep)++;
        /* Now drop haystacks */
        ret = bc_stringlist_emit(fd, codep, bc);
        if(ret < 0) return -1;
        wrote+=ret;
        /* Now drop needles */
        ret = bc_stringlist_emit(fd, codep, bc);
        if(ret < 0) return -1;
        wrote+=ret;
        break;
    }

    case BC_ADDRESS:
        /* drop index */
        if(write_int(fd, bc->data[(*codep)].value) == -1)
            return -1;
        wrote += sizeof(int);
        (*codep)++;

        /* fall-through */
    case BC_ENVELOPE:
    {
        int ret;
        /* Drop match type */
        if(write_int(fd, bc->data[(*codep)].value) == -1)
            return -1;
        wrote += sizeof(int);
        (*codep)++;
        /*drop comparator */
        if(write_int(fd, bc->data[(*codep)].value) == -1)
            return -1;
        wrote += sizeof(int);
        (*codep)++;
        /*now drop relation*/
        if(write_int(fd, bc->data[(*codep)].value) == -1)
            return -1;
        wrote += sizeof(int);
        (*codep)++;
        /*now drop address part*/
        if(write_int(fd, bc->data[(*codep)].value) == -1)
            return -1;
        wrote += sizeof(int);
        (*codep)++;
        /* Now drop headers */
        ret = bc_stringlist_emit(fd, codep, bc);
        if(ret < 0) return -1;
        wrote+=ret;
        /* Now drop data */
        ret = bc_stringlist_emit(fd, codep, bc);
        if(ret < 0) return -1;
        wrote+=ret;
        break;
    }

    case BC_BODY:
    {
        int ret;
        /* Drop match type */
        if(write_int(fd, bc->data[(*codep)].value) == -1)
            return -1;
        wrote += sizeof(int);
        (*codep)++;
        /*drop comparator */
        if(write_int(fd, bc->data[(*codep)].value) == -1)
            return -1;
        wrote += sizeof(int);
        (*codep)++;
        /*now drop relation*/
        if(write_int(fd, bc->data[(*codep)].value) == -1)
            return -1;
        wrote += sizeof(int);
        (*codep)++;
        /*now drop transform*/
        if(write_int(fd, bc->data[(*codep)].value) == -1)
            return -1;
        wrote += sizeof(int);
        (*codep)++;
        /*now drop offset*/
        if(write_int(fd, bc->data[(*codep)].value) == -1)
            return -1;
        wrote += sizeof(int);
        (*codep)++;
        /*now drop content-types*/
        ret = bc_stringlist_emit(fd, codep, bc);
        if(ret < 0) return -1;
        wrote+=ret;
        /* Now drop data */
        ret = bc_stringlist_emit(fd, codep, bc);
        if(ret < 0) return -1;
        wrote+=ret;
        break;
    }

    case BC_DATE:
    case BC_CURRENTDATE:
    {
        int ret;
        int datalen;
        int tmp;

        /* drop index */
        if(BC_DATE == opcode) {
                if(write_int(fd, bc->data[(*codep)].value) == -1)
                    return -1;
                wrote += sizeof(int);
                (*codep)++;
        }

        /* drop zone tag */
        tmp = bc->data[(*codep)].value;
        if(write_int(fd, bc->data[(*codep)].value) == -1)
            return -1;
        wrote += sizeof(int);
        (*codep)++;

        /* drop timezone offset */
        if (tmp == B_TIMEZONE) {
                if(write_int(fd, bc->data[(*codep)].value) == -1)
                    return -1;
                wrote += sizeof(int);
                (*codep)++;
        }

        /* drop match type */
        if(write_int(fd, bc->data[(*codep)].value) == -1)
            return -1;
        wrote += sizeof(int);
        (*codep)++;

        /* drop relation */
        if(write_int(fd, bc->data[(*codep)].value) == -1)
            return -1;
        wrote += sizeof(int);
        (*codep)++;

        /* drop comparator */
        if(write_int(fd, bc->data[(*codep)].value) == -1)
            return -1;
        wrote += sizeof(int);
        (*codep)++;

        /* drop date-part */
        if(write_int(fd, bc->data[(*codep)].value) == -1)
            return -1;
        wrote += sizeof(int);
        (*codep)++;

        if (BC_DATE == opcode) {
                /* drop header-name */
                datalen = bc->data[(*codep)++].len;

                if(write_int(fd, datalen) == -1) return -1;
                wrote += sizeof(int);

                if(write(fd, bc->data[(*codep)++].str, datalen) == -1) return -1;
                wrote += datalen;

                ret = align_string(fd,datalen);
                if(ret == -1) return -1;

                wrote+=ret;
        }

        /* drop keywords */
        ret = bc_stringlist_emit(fd, codep, bc);
        if(ret < 0) return -1;
        wrote+=ret;

        break;
    }

    default:
        /* Unknown testcode? */
        return -1;
    }
    return wrote;
}
예제 #4
0
/* emit the bytecode for a test.  returns -1 on failure or size of
 * emitted bytecode on success */
static int bc_test_emit(int fd, int *codep, bytecode_info_t *bc) 
{
    int wrote=0;/* Relative offset to account for interleaved strings */
    
    
    int ret; /* Temporary Return Value Variable */
    
    /* Output this opcode */
    if(write_int(fd, bc->data[(*codep)].op) == -1)
	return -1;
    wrote += sizeof(int);
    
    switch(bc->data[(*codep)++].op) {
    case BC_TRUE:
    case BC_FALSE:
	/* No parameter opcodes */
	break;
	
    case BC_NOT:
    {
	/* Single parameter: another test */
	ret = bc_test_emit(fd, codep, bc);
	if(ret < 0)
	    return -1;
	else
	    wrote+=ret;
	break;
    }
    
    case BC_ALLOF:
    case BC_ANYOF:
	/*where we jump to?*/
	/* Just drop a testlist */
	ret = bc_testlist_emit(fd, codep, bc);
	if(ret < 0)
	    return -1;
	else
	    wrote+=ret;
	break;
	
    case BC_SIZE:
	/* Drop tag and number */
	if(write_int(fd, bc->data[(*codep)].value) == -1)
	    return -1;
	if(write_int(fd, bc->data[(*codep)+1].value) == -1)
	    return -1;
	
	wrote += 2 * sizeof(int);
	(*codep) += 2;
	break;
	
    case BC_EXISTS:
    {
	int ret;
	ret = bc_stringlist_emit(fd, codep, bc);
	if(ret < 0) return -1;
	wrote += ret;
	break;
    }
    
    case BC_HEADER:
    {
	int ret;
	/* Drop match type */
	if(write_int(fd, bc->data[(*codep)].value) == -1)
	    return -1;
	wrote += sizeof(int);
	(*codep)++;
	/*drop comparator */
	if(write_int(fd, bc->data[(*codep)].value) == -1)
	    return -1;
	wrote += sizeof(int);
	(*codep)++;    
	/*now drop relation*/
	if(write_int(fd, bc->data[(*codep)].value) == -1)
	    return -1;
	wrote += sizeof(int);
	(*codep)++;
	/* Now drop headers */
	ret = bc_stringlist_emit(fd, codep, bc);
	if(ret < 0) return -1;
	wrote+=ret;
	/* Now drop data */
	ret = bc_stringlist_emit(fd, codep, bc);
	if(ret < 0) return -1;
	wrote+=ret;
	break;
    }
    
    case BC_ADDRESS:
    case BC_ENVELOPE:
    {
	int ret;
	/* Drop match type */
	if(write_int(fd, bc->data[(*codep)].value) == -1)
	    return -1;
	wrote += sizeof(int);
	(*codep)++;
	/*drop comparator */
	if(write_int(fd, bc->data[(*codep)].value) == -1)
	    return -1;
	wrote += sizeof(int);
	(*codep)++;
	/*now drop relation*/
	if(write_int(fd, bc->data[(*codep)].value) == -1)
	    return -1;
	wrote += sizeof(int);
	(*codep)++;
	/*now drop address part*/
	if(write_int(fd, bc->data[(*codep)].value) == -1)
	    return -1;
	wrote += sizeof(int);
	(*codep)++;
	/* Now drop headers */
	ret = bc_stringlist_emit(fd, codep, bc);
	if(ret < 0) return -1;
	wrote+=ret;
	/* Now drop data */
	ret = bc_stringlist_emit(fd, codep, bc);
	if(ret < 0) return -1;
	wrote+=ret;
	break;
    }
    
    case BC_BODY:
    {
	int ret;
	/* Drop match type */
	if(write_int(fd, bc->data[(*codep)].value) == -1)
	    return -1;
	wrote += sizeof(int);
	(*codep)++;
	/*drop comparator */
	if(write_int(fd, bc->data[(*codep)].value) == -1)
	    return -1;
	wrote += sizeof(int);
	(*codep)++;
	/*now drop relation*/
	if(write_int(fd, bc->data[(*codep)].value) == -1)
	    return -1;
	wrote += sizeof(int);
	(*codep)++;
	/*now drop transform*/
	if(write_int(fd, bc->data[(*codep)].value) == -1)
	    return -1;
	wrote += sizeof(int);
	(*codep)++;
	/*now drop offset*/
	if(write_int(fd, bc->data[(*codep)].value) == -1)
	    return -1;
	wrote += sizeof(int);
	(*codep)++;
	/*now drop content-types*/
	ret = bc_stringlist_emit(fd, codep, bc);
	if(ret < 0) return -1;
	wrote+=ret;
	/* Now drop data */
	ret = bc_stringlist_emit(fd, codep, bc);
	if(ret < 0) return -1;
	wrote+=ret;
	break;
    }
    
    default:
	/* Unknown testcode? */
	return -1;
    }
    return wrote;
}