/** @brief Application entry point. * * @param args contains the parsed cmd-line options & arguments. * @param argc number of cmd-line arguments. * @param argv list of cmd-line arguments * @param optind index of the first non-option cmd-line argument. * * @return exit status for main() to return. */ int hashjoin (struct cmdargs *args, int argc, char *argv[], int optind) { hashtbl_t dimension; FILE *infile; dbfr_t *datareader; char *keybuffer = NULL; size_t keybuffer_sz = 0; char *value, *empty_value; size_t n_values, i; int *key_fields = NULL; size_t n_key_fields = 0; if (! args->key_labels && ! (args->data_key_fields && args->dimension_key_fields)) { fprintf(stderr, "%s: missing key field argument(s)\n", getenv("_")); return EXIT_FAILURE; } if (! args->dimension_field_labels && ! args->dimension_fields) { fprintf(stderr, "%s: missing dimension field argument\n", getenv("_")); return EXIT_FAILURE; } if (! args->delim) { args->delim = getenv("DELIMITER"); if (! args->delim) { args->delim = default_delim; } } expand_chars(args->delim); if (! args->dimension_delim) { args->dimension_delim = args->delim; } ht_init(&dimension, 1024, NULL, NULL); n_values = hash_dimension_file(args, &dimension); empty_value = xmalloc(strlen(args->delim) * n_values); empty_value[0] = '\0'; for (i = 0; i < n_values - 1; i++) { strcat(empty_value, args->delim); } if (argc > optind) infile = nextfile(argc, argv, &optind, "r"); else infile = stdin; if (! args->key_labels) { n_key_fields = expand_nums(args->data_key_fields, &key_fields, &n_key_fields); decrement(key_fields, n_key_fields); } while (infile) { datareader = dbfr_init(infile); if (args->key_labels) { n_key_fields = expand_label_list(args->key_labels, datareader->next_line, args->delim, &key_fields, &n_key_fields); decrement(key_fields, n_key_fields); } /* Add user-supplied dimension labels to the header row. */ if (args->dimension_labels && ! args->dimension_field_labels) { dbfr_getline(datareader); chomp(datareader->current_line); printf("%s%s%s\n", datareader->current_line, args->delim, args->dimension_labels); } if (! keybuffer) { keybuffer = xmalloc(datareader->next_line_len); keybuffer_sz = datareader->next_line_len; } while (dbfr_getline(datareader) > 0) { if (datareader->current_line_len > keybuffer_sz) { keybuffer = xrealloc(keybuffer, datareader->current_line_len); keybuffer_sz = datareader->current_line_len; } chomp(datareader->current_line); extract_fields(key_fields, n_key_fields, datareader->current_line, keybuffer, keybuffer_sz, args->delim, args->delim); value = ht_get(&dimension, keybuffer); if (! value) value = empty_value; printf("%s%s%s\n", datareader->current_line, args->delim, value); } infile = nextfile(argc, argv, &optind, "r"); } return EXIT_OKAY; }
static void set_option(char *line, struct conf *conf) { char key[KEY_SIZE]; char value[VALUE_SIZE]; if (extract_fields(line, key, value) != 0) { return; } if (strncmp(key, "PORT", 4) == 0) { conf->port = strtol(value, NULL, 10); } if (strncmp(key, "FINGER_PORT", 11) == 0) { conf->finger_port = strtol(value, NULL, 10); } if (strncmp(key, "DUMP_FILE", 9) == 0) { free(conf->dump_file); conf->dump_file = malloc(strlen(value)+1); if (!conf->dump_file) { exit(ENOMEM); } strncpy(conf->dump_file, value, strlen(value)+1); } if (strncmp(key, "MAX_MSG_SIZE", 12) == 0) { conf->max_msg_size = strtol(value, NULL, 10); } if (strncmp(key, "MAX_CLIENTS", 11) == 0) { conf->max_clients = strtol(value, NULL, 10); } if (strncmp(key, "TIMEOUT_UPDATE", 14) == 0) { conf->timeout_update = strtol(value, NULL, 10); } if (strncmp(key, "TIMEOUT_DUMP", 12) == 0) { conf->timeout_dump = strtol(value, NULL, 10); } if (strncmp(key, "CLIENT_LIFETIME", 12) == 0) { conf->client_lifetime = strtol(value, NULL, 10); } if (strncmp(key, "SERVER_ADDR", 11) == 0) { free(conf->host_addr); conf->host_addr = malloc(strlen(value)); strncpy(conf->host_addr, value, strlen(value)); } if (strncmp(key, "IS_CLIENT", 9) == 0) { conf->is_client = strtol(value, NULL, 10); } if (strncmp(key, "IS_SERVER", 9) == 0) { conf->is_server = strtol(value, NULL, 10); } if (strncmp(key, "NUM_RECORDS", 11) == 0) { conf->num_records = strtol(value, NULL, 10); } if (strncmp(key, "ARCHIVE_TIME", 13) == 0) { conf->archive_time = strtol(value, NULL, 10); } }
/** @brief Stores key and value fields from a dimension file in a hashtable. * * @param args commandline options. * @param ht the hashtable to hold the data. * @param filename the name of the dimension file. * * @return the number of value fields. Hackish, but hashjoin() needs to know * and has no other reason to parse the value arguments. */ static size_t hash_dimension_file(struct cmdargs *args, hashtbl_t *ht) { char *value; char *field_buffer = NULL; size_t field_buffer_len = 0, field_buffer_sz = 0; int *key_fields = NULL, *val_fields = NULL; size_t key_fields_sz = 0, val_fields_sz = 0; int n_key_fields = 0, n_val_fields = 0; dbfr_t *dim_file = dbfr_open(args->dimension_file); if (! dim_file) { warn(args->dimension_file); exit(EXIT_FAILURE); } if (args->key_labels) { n_key_fields = expand_label_list(args->key_labels, dim_file->next_line, args->dimension_delim, &key_fields, &key_fields_sz); } else { n_key_fields = expand_nums(args->dimension_key_fields, &key_fields, &key_fields_sz); } if (n_key_fields <= 0) { fprintf(stderr, "%s: error parsing dimension key field list.\n", getenv("_")); exit(EXIT_FAILURE); } if (args->dimension_field_labels) { n_val_fields = expand_label_list(args->dimension_field_labels, dim_file->next_line, args->dimension_delim, &val_fields, &val_fields_sz); } else { n_val_fields = expand_nums(args->dimension_fields, &val_fields, &val_fields_sz); } if (n_val_fields <= 0) { fprintf(stderr, "%s: error parsing dimension value field list.\n", getenv("_")); exit(EXIT_FAILURE); } decrement(key_fields, n_key_fields); decrement(val_fields, n_val_fields); field_buffer = xmalloc(dim_file->next_line_len); field_buffer_sz = dim_file->next_line_len; while (dbfr_getline(dim_file) > 0) { if (dim_file->current_line_len > field_buffer_sz) { field_buffer = xrealloc(field_buffer, dim_file->current_line_len); field_buffer_sz = dim_file->current_line_len; } extract_fields(val_fields, n_val_fields, dim_file->current_line, field_buffer, field_buffer_sz, args->dimension_delim, args->delim); value = xstrdup(field_buffer); extract_fields(key_fields, n_key_fields, dim_file->current_line, field_buffer, field_buffer_sz, args->dimension_delim, args->delim); ht_put(ht, field_buffer, value); } dbfr_close(dim_file); free(field_buffer); return n_val_fields; }