/** * 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; }
/** * 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; }
/** * 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; }
/** * 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; }
/** * 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; }
/** * 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; }
/** * 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; }
/** * 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; }
/** * 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; }
/** * 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; }
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; }
/** * 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; }
/** * 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; }