Beispiel #1
0
/**
 * Receive input buffer, convert to Stream object
 *
 * @return SUCCESS on success, else, -1 on error
 */
cgc_ssize_t cgc_receive_input(void) {
    cgc_ssize_t res;
    Stream tmp;
    // recv Input type and size
    res = cgc_recv_all((char *)&tmp, sizeof(tmp));
    if (res != sizeof(tmp)) {
        cgc__terminate(ERRNO_RECV);
    }

    // check for invalid INPUT_TYPE
    if (cgc_memcmp(cgc_INPUT_TYPE_PLAIN, (const char *)tmp.type, sizeof(cgc_INPUT_TYPE_PLAIN)) &&
        cgc_memcmp(cgc_INPUT_TYPE_SERIALIZED, (const char *)tmp.type, sizeof(cgc_INPUT_TYPE_SERIALIZED))) {
        return -1;
    }

    in = cgc_malloc(sizeof(tmp) + tmp.size);
    MALLOC_OK(in);

    in->size = tmp.size;
    cgc_memcpy(in->type, tmp.type, sizeof(cgc_INPUT_TYPE_SERIALIZED));

    res = cgc_recv_all(in->content, in->size);
    if (res != in->size) {
        cgc__terminate(ERRNO_RECV);
    }

    return SUCCESS;
}
Beispiel #2
0
/**
 * Take the order of one customer
 *
 * @param c 	Customer
 * @return Pointer to a new Order or NULL if no order
 */
static Order *cgc_take_customer_order(Customer *c) {
	Order *o = cgc_malloc(sizeof(Order));
	MALLOC_OK(o);
	cgc_memset(o, '\0', sizeof(Order));

	o->t_id = table.id;
	o->c_id = c->id;
	DBG("Table status: %U\n", table.status);
	switch(table.status) {
		case APP_RTO:	// RTO => ready to order
			o->ftype = APP_TYPE;
			o->item = cgc_select_appetizer(cgc_get_appetizer_list(), c);
			DBG("Customer %U ordering appetizer\n", c->id);
			break;
		case MEAL_RTO:
			o->ftype = MEAL_TYPE;
			o->item = cgc_select_meal(cgc_get_meal_list(), c);
			DBG("Customer %U ordering meal\n", c->id);
			break;
		case DES_RTO:
			o->ftype = DES_TYPE;
			o->item = cgc_select_dessert(cgc_get_dessert_list(), c);
			DBG("Customer %U ordering dessert\n", c->id);
			break;
		default:		// WAIT => already ordered, VACANT, FINISHED
			DBG("Customer %U NOT ordering\n", c->id);
			cgc_free(o);
			return NULL;
	}
	return o;
}
Beispiel #3
0
/**
 * Process the input to set 2 persons as separated
 *
 * @param bytes     Number of bytes available to receive
 * @return SUCCESS on success, else -1
 */
int cgc_cmd_set_separated(cgc_size_t bytes) {
    int ret = SUCCESS;
    cgc_size_t bytes_needed = 2*sizeof(uint32_t);  // IDs for person1 and person2

    if (bytes != bytes_needed) {
        return -1;
    }

    char *buf = cgc_calloc(bytes_needed);
    MALLOC_OK(buf);
    RECV(buf, bytes_needed);

    uint32_t *id = (uint32_t *)buf;

    Person *person1  = cgc_get_person_by_id(cgc_person_list, id[0]);
    Person *person2 = cgc_get_person_by_id(cgc_person_list, id[1]);
    if ((NULL == person1) || (NULL == person2)) {
        ret = -1;
        goto ss_end;
    }

    ret = cgc_separate_two_persons(person1, person2);

ss_end:
    cgc_free(buf);
    return ret;
}
Beispiel #4
0
/**
 * Process the input to determine if there is a relationship between 2 people
 *
 * @param bytes     Number of bytes available to receive
 * @return SUCCESS on success, else -1 on error
 */
int cgc_cmd_are_related(cgc_size_t bytes) {
    int ret = SUCCESS;
    cgc_size_t bytes_needed = 2*sizeof(uint32_t);  // IDs for person1 and person2

    if (bytes != bytes_needed) {
        return -1;
    }

    char *buf = cgc_calloc(bytes_needed);
    MALLOC_OK(buf);
    RECV(buf, bytes_needed);

    uint32_t *id = (uint32_t *)buf;

    Person *person1  = cgc_get_person_by_id(cgc_person_list, id[0]);
    Person *person2 = cgc_get_person_by_id(cgc_person_list, id[1]);
    if ((NULL == person1) || (NULL == person2)) {
        ret = -1;
        goto ar_end;
    }

    ret = cgc_find_are_related(person1, person2);
    if ((RELATED == ret) || (NOT_RELATED == ret)) {
        cgc_send((char *)&ret, sizeof(int));
        ret = SUCCESS;
    }

ar_end:
    cgc_free(buf);

    return ret;
}
Beispiel #5
0
/**
 * Process the input to set a person as deceased.
 *
 * @param bytes     Number of bytes available to receive
 * @return SUCCESS on success, else -1
 */
int cgc_cmd_set_deceased(cgc_size_t bytes) {
    int ret = SUCCESS;
    cgc_size_t bytes_needed = sizeof(uint32_t) + sizeof(uint16_t);  // ID, death_year for person1

    if (bytes != bytes_needed) {
        return -1;
    }

    char *buf = cgc_calloc(bytes_needed);
    MALLOC_OK(buf);
    RECV(buf, bytes_needed);

    uint32_t *id = (uint32_t *)buf;
    uint16_t *death_year = (uint16_t *)buf;

    Person *person1  = cgc_get_person_by_id(cgc_person_list, id[0]);
    if (NULL == person1) {
        ret = -1;
        goto die_end;
    }
    person1->lifecycle.death_year = death_year[2];

die_end:
    cgc_free(buf);
    return ret;
}
Beispiel #6
0
/**
 * Add a new person to the family tree
 *
 * @param bytes     Number of bytes available to receive
 * @return SUCCESS on success, else -1
 */
int cgc_cmd_add_person(cgc_size_t bytes) {
    int ret = SUCCESS;
    Person *p;

    if (bytes != PERSON_IN_SZ) {
        return -1;
    }

    char *buf = cgc_calloc(PERSON_IN_SZ);
    MALLOC_OK(buf);
    RECV(buf, PERSON_IN_SZ);

    p = cgc_new_person(buf);
    if (NULL == p) {
        ret = -1;
        goto cap_end;
    }

    cgc_add_person_to_list(&cgc_person_list, p);
    cgc_total_person_count++;

cap_end:
    cgc_free(buf);

    return ret;
}
Beispiel #7
0
/**
 * Process a purchase of one or more products and return the total cost.
 *
 * @return SUCCESS on success, else -1
 */
static int do_buy(void) {
	Product *p = NULL;
	Product *p_copy = NULL;
	char buy_status[4];
	char bc[BARCODE_SZ] = {0};
	double cost = 0.0;
	struct list buy_list;

	// create buy list
	list_init(&buy_list, free);

	RECV(STDIN, buy_status, sizeof(buy_status));
	// BUG: this loop could be used for memory exhaustion, it has no bound on buy_list.
	while (0 == memcmp(buy_status, (void *)BUY_MORE, sizeof(BUY_MORE))) {
		// recv barcode
		RECV(STDIN, bc, BARCODE_SZ);

		// find product in inventory with matching bar code
		p = get_product_by_barcode(bc);

		// if not found, return -1
		if (NULL == p) {
			// clear buy list
			list_destroy(&buy_list);

			return -1;
		}

		// make copy of product
		p_copy = malloc(sizeof(Product));
		MALLOC_OK(p_copy);

		memcpy(p_copy, p, sizeof(Product));

		// add product to buy list		
		list_insert_at_end(&buy_list, p_copy);

		// add to cost sum
		cost += p_copy->sfn(p_copy->model_num, p_copy->cost);

		// recv buy status
		RECV(STDIN, buy_status, sizeof(buy_status));
	}

	if (0 != memcmp(buy_status, (void *)BUY_TERM, sizeof(BUY_TERM))) {
		list_destroy(&buy_list);
		return -1;
	}

	// send total cost
	SEND(STDOUT, (char *)&cost, sizeof(cost));

	// clear buy list
	list_destroy(&buy_list);

	return SUCCESS;
}
Beispiel #8
0
/**
 * Process the addition of one new product to the inventory.
 *
 * @return SUCCESS on success, else -1
 */
static int do_add(void) {
	Product *p = NULL;
	Product *p2 = NULL;
	int bytes_recvd = 0;

	// create product struct
	p = malloc(sizeof(Product));
	MALLOC_OK(p);

	// set sfn to not on sale
	p->sfn = onsale_fn[0];
	p->update_serial = 0;

	// recv barcode
	RECV(STDIN, (char *)p->barcode, BARCODE_SZ);

	// if barcode already exists, return -1
	p2 = get_product_by_barcode((char *)p->barcode);
	if (NULL != p2) {
		free(p);
		return -1;
	}

	// recv model_num
	RECV(STDIN, (char *)&p->model_num, sizeof(unsigned int));

	// recv cost
	RECV(STDIN, (char *)&p->cost, sizeof(float));

	// recv desc
	// VULN: sizeof(Product) is > MAX_DESC_LEN, so can overflow 24 bytes
	// 	(4 model_num, 4 cost, 4 sfn and 12 heap meta).
#ifdef PATCHED_1
	bytes_recvd = recv_until_delim_n(STDIN, DESC_TERM[0], (char *)p->desc, MAX_DESC_LEN);
#else
	bytes_recvd = recv_until_delim_n(STDIN, DESC_TERM[0], (char *)p->desc, sizeof(Product));
#endif
	if (0 >= bytes_recvd) _terminate(ERRNO_RECV);

	// make desc NULL terminated
	p->desc[bytes_recvd - 1] = '\0';

	// add to Inventory
    list_insert_at_end(&inv, p);

	return SUCCESS;
}
Beispiel #9
0
/**
 * Create a new search map
 *
 * @return SUCCESS on succeess, else -1 on error
 */
int cgc_new_search_map(void) {
    if (cgc_total_person_count > (SIZE_MAX / sizeof(Search) - 1))
        return -1; // prevent overflow calloc size

    if (NULL != cgc_search_map) cgc_free_search_map();

    cgc_search_map = cgc_calloc(cgc_total_person_count * sizeof(Search));
    MALLOC_OK(cgc_search_map);

    Person *p = cgc_person_list;
    uint32_t idx = 0;
    while (NULL != p) {
        cgc_search_map[idx++].p = p;
        p = p->next;
    }

    return SUCCESS;
}
Beispiel #10
0
/**
 * Process the input to set a biological child relationship between child 
 * and its father and/or mother.
 *
 * @param bytes     Number of bytes available to receive
 * @return SUCCESS on success, else -1
 */
int cgc_cmd_set_biological_child(cgc_size_t bytes) {
    int ret = SUCCESS;
    cgc_size_t bytes_needed = 3*sizeof(uint32_t);  // IDs for child, mother, and father

    if (bytes != bytes_needed) {
        return -1;
    }

    char *buf = cgc_calloc(bytes_needed);
    MALLOC_OK(buf);
    RECV(buf, bytes_needed);

    uint32_t *id = (uint32_t *)buf;

    Person *child  = cgc_get_person_by_id(cgc_person_list, id[0]);
    Person *mother = cgc_get_person_by_id(cgc_person_list, id[1]);
    Person *father = cgc_get_person_by_id(cgc_person_list, id[2]);

    // parent and children relations default to PERSON_UNKNOWN, so only change
    // if a known person is given as each parent.
    // Also, make sure both parents can have more biological children
    if ((NULL == child) || (NULL == mother) || (NULL == father) ||
        (FALSE == cgc_can_have_more_biological_children(mother)) ||
        (FALSE == cgc_can_have_more_biological_children(father))) {
        ret = -1;
        goto sbc_end;
    }

    // set child first, because it can fail; althrough it shouldn't if we got this far
    ret = cgc_set_biological_child(child, mother);
    if (-1 == ret) goto sbc_end;        
    cgc_set_biological_mother(child, mother);

    // set child first, because it can fail; althrough it shouldn't if we got this far
    ret = cgc_set_biological_child(child, father);
    if (-1 == ret) goto sbc_end; 
    cgc_set_biological_father(child, father);

sbc_end:
    cgc_free(buf);

    return ret;
}
Beispiel #11
0
int replace_deck(unsigned int count, unsigned char *values) {
	if (NULL != deck) {
		free(deck);
	}
	if (0 == count) {
		return -1;
	}

	deck = malloc(sizeof(Deck) + count * sizeof(Card));
	MALLOC_OK(deck);

	deck->count = count;
	for (int i = 0; i < count; i++) {
		if (FALSE == is_valid_value(values[i])) {
			DBG("invaild card %H\n", values[i]);
			return -1;
		}
		deck->cards[i].value = values[i];
	}

	return SUCCESS;
}
Beispiel #12
0
/**
 * Process the input to determine the degrees of separation between 2 people
 *
 * @param bytes     Number of bytes available to receive
 * @return SUCCESS on success, else -1 on error
 */
int cgc_cmd_degrees_of_separation(cgc_size_t bytes) {
    int ret = SUCCESS;
    cgc_size_t bytes_needed = 2*sizeof(uint32_t);  // IDs for person1 and person2

    if (bytes != bytes_needed) {
        return -1;
    }

    char *buf = cgc_calloc(bytes_needed);
    MALLOC_OK(buf);
    RECV(buf, bytes_needed);

    uint32_t *id = (uint32_t *)buf;

    Person *person1  = cgc_get_person_by_id(cgc_person_list, id[0]);
    Person *person2 = cgc_get_person_by_id(cgc_person_list, id[1]);
    if ((NULL == person1) || (NULL == person2)) {
        ret = -1;
        goto ds_end;
    }

    ret = cgc_new_search_map();
    if (-1 == ret) goto ds_end;

    // ret -> 0 == self, >0 == related, -1 == error
    ret = cgc_degrees_of_separation(person1, person2);
    cgc_free_search_map();

    // send -1 for not related, 0 if self, >0 if related by some degree
    cgc_send((char *)&ret, sizeof(int));
    ret = SUCCESS;

ds_end:
    cgc_free(buf);

    return ret;

}
Beispiel #13
0
/**
 * Process the input to set an adopted child relationship between child 
 * and its one or two parents.
 *
 * @param bytes     Number of bytes available to receive
 * @return SUCCESS on success, else -1
 */
int cgc_cmd_set_adopted_child(cgc_size_t bytes) {
    int ret = SUCCESS;
    cgc_size_t bytes_needed = 3*sizeof(uint32_t);  // IDs for child, parent1, and parent2

    if (bytes != bytes_needed) {
        return -1;
    }

    char *buf = cgc_calloc(bytes_needed);
    MALLOC_OK(buf);
    RECV(buf, bytes_needed);

    uint32_t *id = (uint32_t *)buf;

    Person *child  = cgc_get_person_by_id(cgc_person_list, id[0]);
    Person *parent1 = cgc_get_person_by_id(cgc_person_list, id[1]);
    Person *parent2 = cgc_get_person_by_id(cgc_person_list, id[2]);

    // parent and children relations default to PERSON_UNKNOWN, so only change
    // if an existing/valid person is given as at least one parent.
    // Also, make sure valid parents can have more adopted children
    if ((NULL == child) || 
        ((NULL == parent1) && (NULL == parent2)) ||
        ((NULL != parent1) && (FALSE == cgc_can_have_more_adopted_children(parent1))) ||
        ((NULL != parent2) && (FALSE == cgc_can_have_more_adopted_children(parent2)))) {
        ret = -1;
        goto sac_end;
    }

    // if this child has existing adopting parents, remove this child from those parents
    if (PERSON_UNKNOWN != child->parents.adopting[0].person_id) {
        ret = cgc_unset_adopted_child(child, child->parents.adopting[0].person);
        if (-1 == ret) {
            goto sac_end;
        }
    }

    if (PERSON_UNKNOWN != child->parents.adopting[1].person_id) {
        ret = cgc_unset_adopted_child(child, child->parents.adopting[1].person);
        if (-1 == ret) {
            goto sac_end;
        }
    }

    // set child first, because it can fail; although it shouldn't if we got this far
    if (NULL != parent1) {
        ret = cgc_set_adopted_child(child, parent1);
        if (-1 == ret) goto sac_end;
        cgc_set_adopting_parent(child, parent1, 0);
    }

    // set child first, because it can fail; although it shouldn't if we got this far
    if (NULL != parent2) {
        ret = cgc_set_adopted_child(child, parent2);
        if (-1 == ret) goto sac_end;
        cgc_set_adopting_parent(child, parent2, 1);
    }

sac_end:
    cgc_free(buf);

    return ret;
}