//void do_install(opkg_conf* conf, char* pkg_name, char* install_root_name, char* link_root_name, char** version_criteria) void do_install(opkg_conf* conf, string_map* pkgs, char* install_root_name, char* link_root_name, int is_upgrade, int overwrite_config, int overwrite_other_package_files, int force_reinstall, char* tmp_root) { string_map* package_data = initialize_string_map(1); string_map* matching_packages = initialize_string_map(1); string_map* pkgs_from_file = initialize_string_map(1); unsigned long num_destroyed; char* install_root_path = (char*)get_string_map_element(conf->dest_names, install_root_name); char* overlay_path = NULL; // no special treatment of overlay, can be reenabled by setting this variable here if we ever need it char* test_dir = dynamic_strcat(2, (overlay_path != NULL ? overlay_path : install_root_path), "/usr/lib/opkg/info"); if(!create_dir_and_test_writable(test_dir)) { fprintf(stderr, "ERROR: Specified install destination is not writable, exiting\n"); exit(1); } free(test_dir); if(install_root_path == NULL) { printf("ERROR: No destination %s found, cannot install\n\n", install_root_name); exit(1); } char* tmp_dir = (char*)malloc(1024); if(create_tmp_dir(tmp_root == NULL ? "/tmp" : tmp_root, &tmp_dir) != 0) { fprintf(stderr, "ERROR: Could not create tmp dir, exiting\n"); exit(1); } /* Determine all packages to install by first loading all package names, status & dependencies (and no other variables) */ load_all_package_data(conf, package_data, matching_packages, NULL, LOAD_MINIMAL_PKG_VARIABLES_FOR_ALL, install_root_name, 1, NULL ); destroy_string_map(matching_packages, DESTROY_MODE_FREE_VALUES, &num_destroyed); /* determine list of all packiages we are about to install, including dependencies */ string_map* install_pkgs_map = initialize_string_map(1); char** install_pkg_list = NULL; unsigned long install_pkg_list_len = 0; char* unsatisfied_dep_err = NULL; /* new string map var with all pkgs to install = pkgs, keys = version */ unsigned long num_pkg_names; char** pkg_names = get_string_map_keys(pkgs, &num_pkg_names); int pkg_name_index; /* * Load data for any packages being installed via ipk and * determine if any packages we are about to install * provide anything, and if so set package we are installing to preferred */ string_map* preferred_provides = initialize_string_map(1); for(pkg_name_index=0;pkg_name_index < num_pkg_names; pkg_name_index++) { char* pkg_name = pkg_names[pkg_name_index]; char** version_criteria = get_string_map_element(pkgs, pkg_name); char* install_pkg_version = NULL; int install_pkg_is_current; /* deal with case where we're installing from file */ if(path_exists(pkg_name)) { //installing from file char* pkg_file = pkg_name; //extract control files int err = 0; char* tmp_control = dynamic_strcat(2, tmp_dir, "/tmp_ctrl"); char* tmp_control_prefix = dynamic_strcat(2, tmp_control, "/tmp."); char* tmp_control_name = dynamic_strcat(2, tmp_control_prefix, "control"); mkdir_p(tmp_control, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH ); deb_extract( pkg_file, stderr, extract_control_tar_gz | extract_all_to_fs| extract_preserve_date | extract_unconditional, tmp_control_prefix, NULL, &err); if(err != 0) { fprintf(stderr, "ERROR: %s is not a valid package file, cannot install\n", pkg_file); rm_r(tmp_dir); exit(1); } string_map* tmp_control_pkg_data = initialize_string_map(1); matching_packages = initialize_string_map(1); load_package_data(tmp_control_name, 0, tmp_control_pkg_data, matching_packages, NULL, LOAD_ALL_PKG_VARIABLES, NULL, NULL); unsigned long num_ctrl_names; char** ctrl_name_list = get_string_map_keys(tmp_control_pkg_data, &num_ctrl_names); destroy_string_map(matching_packages, DESTROY_MODE_FREE_VALUES, &num_destroyed); err = 1; //set back to 0 when data successfully loaded if(num_ctrl_names > 0) { int ctrl_name_index; for(ctrl_name_index=0; ctrl_name_list[ctrl_name_index] != NULL; ctrl_name_index++) { if( strcmp(ctrl_name_list[ctrl_name_index], PROVIDES_STRING) != 0) { pkg_name = strdup(ctrl_name_list[ctrl_name_index]); } } char* version = NULL; int is_current; string_map* pkg_info = get_package_current_or_latest(tmp_control_pkg_data, pkg_name, &is_current, &version); if(pkg_info != NULL) { err = 0; set_string_map_element(pkg_info, "Install-File-Location", strdup(pkg_file)); set_string_map_element(pkg_info, "Version", version); //we need to save this, since we are going to set a special version to make sure data doesn't get over-written later, also no need to free version now char* special_version = dynamic_strcat(2, version, "@@_FILE_INSTALL_VERSION_@@"); char** new_version_criteria = malloc(3*sizeof(char*)); new_version_criteria[0] = strdup("="); new_version_criteria[1] = special_version; new_version_criteria[2] = NULL; version_criteria = new_version_criteria; string_map* all_current_versions = get_string_map_element(package_data, pkg_name); if(all_current_versions == NULL) { all_current_versions=initialize_string_map(1); set_string_map_element(package_data, pkg_name, all_current_versions); } set_string_map_element(all_current_versions, special_version, pkg_info); set_string_map_element(all_current_versions, LATEST_VERSION_STRING, special_version); free(pkg_names[pkg_name_index]); pkg_names[pkg_name_index] = strdup(pkg_name); set_string_map_element(pkgs, pkg_name, copy_null_terminated_string_array(new_version_criteria)); set_string_map_element(pkgs_from_file, pkg_name, strdup("D")); } } free_null_terminated_string_array(ctrl_name_list); if(err != 0) { fprintf(stderr, "ERROR: %s is not a valid package file, cannot install\n", pkg_file); rm_r(tmp_dir); exit(1); } free_if_not_null(tmp_control); free_if_not_null(tmp_control_prefix); free_if_not_null(tmp_control_name); rm_r(tmp_control); } /* determine if package provides anything, and set this package to preferred if so*/ string_map* install_pkg_data = get_package_current_or_latest_matching(package_data, pkg_name, version_criteria, &install_pkg_is_current, &install_pkg_version); if(install_pkg_data != NULL) { char* provides_str = get_string_map_element(install_pkg_data, "Provides"); if(provides_str != NULL) { if(strlen(provides_str) > 0) { unsigned long num_provides; char package_separators[] = {' ', ',', ':', ';', '\'', '\"', '\t', '\r', '\n'}; char** provides_list = split_on_separators(provides_str, package_separators, 9, -1, 0, &num_provides); int provides_index; char* provides_unique_key = dynamic_strcat(3, pkg_name, "@", install_pkg_version); for(provides_index=0; provides_index < num_provides; provides_index++) { char* provides_name = strdup(provides_list[provides_index]); char* eq = strchr(provides_name, '='); if(eq != NULL) { *eq = '\0' ; } if(strlen(provides_name) > 0) { set_string_map_element(preferred_provides, provides_name, strdup(provides_unique_key)); } } } } } } /* reload with new preferred_provides */ free_recursive_package_vars(package_data); matching_packages = initialize_string_map(1); load_all_package_data(conf, package_data, matching_packages, NULL, LOAD_MINIMAL_PKG_VARIABLES_FOR_ALL, install_root_name, 1, preferred_provides ); destroy_string_map(matching_packages, DESTROY_MODE_FREE_VALUES, &num_destroyed); /* load data and do sanity checks for packages we are about to install */ for(pkg_name_index=0;pkg_name_index < num_pkg_names; pkg_name_index++) { char* pkg_name = pkg_names[pkg_name_index]; char** version_criteria = get_string_map_element(pkgs, pkg_name); char* install_pkg_version = NULL; int install_pkg_is_current; load_recursive_package_data_variables(package_data, pkg_name, 1, 0, 0); // load required-depends for package of interest only string_map* install_pkg_data = get_package_current_or_latest_matching(package_data, pkg_name, version_criteria, &install_pkg_is_current, &install_pkg_version); char* install_status = install_pkg_data == NULL ? NULL : get_string_map_element(install_pkg_data, "Status"); if(install_status != NULL) { char** old_el = set_string_map_element(install_pkgs_map, pkg_name, copy_null_terminated_string_array(version_criteria) ); if(old_el != NULL){ free_null_terminated_string_array(old_el); } string_map* install_pkg_depend_map = get_string_map_element(install_pkg_data, "Required-Depends"); if(install_pkg_depend_map != NULL) { unsigned long num_keys; char** load_detail_pkgs = get_string_map_keys(install_pkg_depend_map, &num_keys); int ldp_index; for(ldp_index=0;ldp_index < num_keys && unsatisfied_dep_err == NULL; ldp_index++) { char* dep_name = load_detail_pkgs[ldp_index]; char** dep_def= get_string_map_element(install_pkg_depend_map, dep_name); if(get_string_map_element(install_pkgs_map, dep_name) != NULL) { /* * We really should check here whether old dependency def can be reconciled with the new one, and report an error if it can't * Right now we just use the heuristic that top-level (user specified, not dependency) package defs get preference, followed * by first dependency encountered. * * Since right now versioning features aren't really being used very much other than kernel dependencies in Gargoyle/OpenWrt * I'm just leaving this comment here as a reminder that this should be addressed at some point rather than messing with it now * */ dep_def = get_string_map_element(install_pkgs_map, dep_name); } else { set_string_map_element(install_pkgs_map, dep_name, copy_null_terminated_string_array(dep_def)); } //error checking, check that dependency definition exists char* latest_version = NULL; int latest_is_current = 0; string_map* dep_info = get_package_current_or_latest_matching(package_data, dep_name, dep_def, &latest_is_current, &latest_version); //check if we have a version installed different than what is required int have_current; char* current_version = NULL; string_map* cur_info = get_package_current_or_latest(package_data, dep_name, &have_current, ¤t_version); if(have_current && (latest_is_current == 0 || dep_info == NULL)) { //should only get here if dep_def[1] is not null (version mismatch doesn't make sense if no version is specified) char* cur_status = get_string_map_element(cur_info, "Status"); if(strstr(cur_status, " hold ") != NULL) { unsatisfied_dep_err = dynamic_strcat(11, "ERROR: Dependency ", dep_name, " (", dep_def[0], " ", dep_def[1], ") of package ", pkg_name, " is installed,\n\t\tbut has incompatible version ", current_version, " and is marked as 'hold'"); } else { unsatisfied_dep_err = dynamic_strcat(10, "ERROR: Dependency ", dep_name, " (", dep_def[0], " ", dep_def[1], ") of package ", pkg_name, " is installed,\n\t\tbut has incompatible version ", current_version); } } free_if_not_null(current_version); free_if_not_null(latest_version); // check that dependency definition exists if(unsatisfied_dep_err == NULL && dep_info == NULL) { if(dep_def[1] != NULL) { unsatisfied_dep_err = dynamic_strcat(9, "ERROR: Dependency ", dep_name, " (", dep_def[0], " ", dep_def[1], ") of package ", pkg_name, " cannot be found, try updating your package lists"); } else { unsatisfied_dep_err = dynamic_strcat(5, "ERROR: Dependency ", dep_name, " of package ", pkg_name, " cannot be found, try updating your package lists"); } } } free_null_terminated_string_array(load_detail_pkgs); } } install_status = install_pkg_data == NULL ? NULL : get_string_map_element(install_pkg_data, "Status"); /* error checking before we start install */ if(install_pkg_data == NULL || install_status == NULL) { fprintf(stderr, "ERROR: No package named %s found, try updating your package lists\n\n", pkg_name); rm_r(tmp_dir); exit(1); } if(strstr(install_status, " installed") != NULL) { if(force_reinstall) { fprintf(stderr, "WARNING: Package %s is already installed, forcing removal and reinstallation\n\n", pkg_name); free_package_data(package_data); string_map* rm_pkg = initialize_string_map(1); set_string_map_element(rm_pkg, pkg_name, alloc_depend_def(NULL)); do_remove(conf, rm_pkg, (overwrite_config ? 0 : 1), 0, 1, 0, tmp_root); //restart install return do_install(conf, pkgs, install_root_name, link_root_name, is_upgrade, overwrite_config, overwrite_other_package_files, force_reinstall, tmp_root); } else { fprintf(stderr, "WARNING: Package %s is already installed, ignoring\n", pkg_name); fprintf(stderr, " Use --force-reinstall to force reinstallation\n\n"); char** old_el = remove_string_map_element(install_pkgs_map, pkg_name); if(old_el != NULL){ free_null_terminated_string_array(old_el); }; } } if(unsatisfied_dep_err != NULL) { fprintf(stderr, "%s\n", unsatisfied_dep_err); rm_r(tmp_dir); exit(1); } } /* load more detailed data on packages we are about to install */ free_recursive_package_vars(package_data); /* note: whacks install_pkg_depend_map */ string_map* parameters = initialize_string_map(1); matching_packages = initialize_string_map(1); set_string_map_element(parameters, "package-list", install_pkgs_map); load_all_package_data(conf, package_data, matching_packages, parameters, LOAD_MINIMAL_FOR_ALL_PKGS_ALL_FOR_MATCHING, install_root_name, 0, preferred_provides); unsigned long from_file_pkg_list_len; char** from_file_pkg_list = get_string_map_keys(pkgs_from_file, &from_file_pkg_list_len); int from_file_index; for(from_file_index=0; from_file_index < from_file_pkg_list_len; from_file_index++) { char* old = set_string_map_element(matching_packages, from_file_pkg_list[from_file_index], strdup("D")); free_if_not_null(old); } free_null_terminated_string_array(from_file_pkg_list); install_pkg_list = get_string_map_keys(matching_packages, &install_pkg_list_len); destroy_string_map(matching_packages, DESTROY_MODE_FREE_VALUES, &num_destroyed); destroy_string_map(parameters, DESTROY_MODE_IGNORE_VALUES, &num_destroyed); char* all_pkg_list_str = join_strs(", ", install_pkg_list, install_pkg_list_len, 0, 0); uint64_t combined_size = 0; int pkg_index; for(pkg_index=0; pkg_index < install_pkg_list_len; pkg_index++) { char** match_criteria = get_string_map_element(install_pkgs_map, install_pkg_list[pkg_index]); string_map* pkg = get_package_current_or_latest_matching(package_data, install_pkg_list[pkg_index], match_criteria, NULL, NULL); char* next_size_str = get_string_map_element(pkg, "Installed-Size"); uint64_t next_size = 0; if(sscanf(next_size_str, SCANFU64, &next_size) > 0) { combined_size = combined_size + next_size; } } uint64_t root_size = destination_bytes_free(conf, install_root_name); if(combined_size >= root_size ) { fprintf(stderr, "ERROR: Not enough space in destination %s to install specified packages:\n\t%s\n\n", install_root_name, all_pkg_list_str); rm_r(tmp_dir); exit(1); } if(all_pkg_list_str != NULL) { printf("Preparing to install the following packages, which will require " SCANFU64 " bytes:\n\t%s\n\n", combined_size, all_pkg_list_str); } else { fprintf(stderr, "No packages to install.\n\n"); } /* Set status of new required packages to half-installed, set user-installed on requested package, installed time on all */ char* install_root_status_path = dynamic_strcat(2, install_root_path, "/usr/lib/opkg/status"); string_map* install_root_status = initialize_string_map(1); matching_packages = initialize_string_map(1); if(path_exists(install_root_status_path)) { load_package_data(install_root_status_path, 0, install_root_status, matching_packages, NULL, LOAD_ALL_PKG_VARIABLES, install_root_name, preferred_provides); } destroy_string_map(matching_packages, DESTROY_MODE_FREE_VALUES, &num_destroyed); time_t now = time(NULL); char install_time[20]; sprintf(install_time, "%lu", now); for(pkg_index=0; pkg_index < install_pkg_list_len; pkg_index++) { int is_installed; char* install_version = NULL; char** match_criteria = get_string_map_element(install_pkgs_map, install_pkg_list[pkg_index]); string_map* pkg = get_package_current_or_latest_matching(package_data, install_pkg_list[pkg_index], match_criteria, &is_installed, &install_version); if(is_installed == 0) /* should never be true, but check anyway */ { char* old_status = remove_string_map_element(pkg, "Status"); free(old_status); char* status_parts[3] = { "install", "ok", "half-installed" }; status_parts[1] = get_string_map_element(pkgs, install_pkg_list[pkg_index]) != NULL ? "user" : status_parts[1]; char* new_status = dynamic_strcat(5, status_parts[0], " ", status_parts[1], " ", status_parts[2]); set_string_map_element(pkg, "Status", new_status); set_string_map_element(pkg, "Installed-Time", strdup(install_time)); set_string_map_element(pkg, "Install-Destination", strdup(install_root_name)); if(link_root_name != NULL) { set_string_map_element(pkg, "Link-Destination", strdup(link_root_name)); } add_package_data(install_root_status, &pkg, install_pkg_list[pkg_index], install_version, NULL); /* Note: we just added pkg data structure from package_data to install_root_status, Be careful on cleanup! */ } } save_package_data_as_status_file(install_root_status, install_root_status_path); string_map* install_called_pkgs = initialize_string_map(1); int err = 0; for(pkg_name_index=0;pkg_name_index < num_pkg_names; pkg_name_index++) { char* pkg_name = pkg_names[pkg_name_index]; if(get_string_map_element(install_pkgs_map, pkg_name) != NULL && get_string_map_element(install_called_pkgs, pkg_name) == NULL) { int install_pkg_is_current; char* install_pkg_version = NULL; char** version_criteria = get_string_map_element(pkgs, pkg_name); get_package_current_or_latest_matching(package_data, pkg_name, version_criteria, &install_pkg_is_current, &install_pkg_version); err = recursively_install(pkg_name, install_pkg_version, install_root_name, link_root_name, overlay_path, is_upgrade, overwrite_config, overwrite_other_package_files, tmp_dir, conf, package_data, install_called_pkgs); free_if_not_null(install_pkg_version); } } if(err) { fprintf(stderr, "An error occurred during Installation, removing partially installed packages.\n"); unsigned long num_install_called_pkgs; char** install_called_pkg_list = get_string_map_keys(install_called_pkgs, &num_install_called_pkgs); int pkg_index; for(pkg_index=0; pkg_index < num_install_called_pkgs; pkg_index++) { remove_individual_package(install_called_pkg_list[pkg_index], conf, package_data, tmp_dir, 0, 0); } free_null_terminated_string_array(install_called_pkg_list); //call remove function to do cleanup of partial install //DO NOT EXIT HERE, fixup status file below } //remove tmp dir -- need to do this whether or not there is an error rm_r(tmp_dir); free(tmp_dir); //set status of new packages to installed on success, and remove on failure for(pkg_index=0; pkg_index < install_pkg_list_len; pkg_index++) { /* no need to check version, should only be one installed version at a time... */ string_map* pkg = get_package_current_or_latest(install_root_status, install_pkg_list[pkg_index], NULL, NULL); if(pkg != NULL) { if(!err) { char* status = get_string_map_element(pkg, "Status"); if(strstr(status, " half-installed") != NULL) { char* status_parts[3] = { "install", "ok", "installed" }; status_parts[1] = get_string_map_element(pkgs, install_pkg_list[pkg_index]) != NULL ? "user" : status_parts[1]; char* new_status = dynamic_strcat(5, status_parts[0], " ", status_parts[1], " ", status_parts[2]); char* old_status = set_string_map_element(pkg, "Status", new_status); free_if_not_null(old_status); } } else { string_map* all_pkg_versions = remove_string_map_element(install_root_status, install_pkg_list[pkg_index]); free_all_package_versions(all_pkg_versions); } } } save_package_data_as_status_file(install_root_status, install_root_status_path); if(!err) { if(all_pkg_list_str != NULL) { printf("Installation of packages successful.\n\n"); } } else { printf("Finished removing partially installed packages.\n\n"); } }
ip_bw* load_usage_from_file(char* in_file_path, unsigned long* num_ips, time_t* last_backup) { ip_bw* data = NULL; *num_ips = 0; *last_backup = 0; FILE* in_file = fopen(in_file_path, "r"); if(in_file != NULL) { unsigned long num_data_parts = 0; char* file_data = read_entire_file(in_file, 4086, &num_data_parts); fclose(in_file); char whitespace[] = {'\n', '\r', '\t', ' '}; char** data_parts = split_on_separators(file_data, whitespace, 4, -1, 0, &num_data_parts); free(file_data); *num_ips = (num_data_parts/2) + 1; data = (ip_bw*)malloc( (*num_ips) * sizeof(ip_bw) ); *num_ips = 0; unsigned long data_index = 0; unsigned long data_part_index = 0; while(data_part_index < num_data_parts) { ip_bw next; struct in_addr ipaddr; int valid = inet_aton(data_parts[data_part_index], &ipaddr); if(!valid) { sscanf(data_parts[data_part_index], "%ld", last_backup); //printf("last_backup = %ld\n", *last_backup); } data_part_index++; if(valid && data_index < num_data_parts) { next.ip = ipaddr.s_addr; valid = sscanf(data_parts[data_part_index], "%lld", (long long int*)&(next.bw) ); data_part_index++; } else { valid = 0; } if(valid) { //printf("next.bw = %lld\n", next.bw); //printf("next.ip = %d\n", next.ip); data[data_index] = next; data_index++; *num_ips = *num_ips + 1; } } /* cleanup by freeing data_parts */ for(data_part_index = 0; data_part_index < num_data_parts; data_part_index++) { free(data_parts[data_part_index]); } free(data_parts); } return data; }
string_map* parse_parameters(int argc, char** argv) { string_map* parameters = initialize_string_map(1); if(argc == 1) { print_usage(); //exits } char* run_type = argv[1]; if( strcmp(run_type, "list") != 0 && strcmp(run_type, "list-installed") != 0 && strcmp(run_type, "list_installed") != 0 && strcmp(run_type, "dest-info") != 0 && strcmp(run_type, "dest_info") != 0 && strcmp(run_type, "info") != 0 && strcmp(run_type, "update") != 0 && strcmp(run_type, "install") != 0 && strcmp(run_type, "remove") != 0 && strcmp(run_type, "upgrade") != 0 ) { print_usage(); //exits } set_string_map_element(parameters, "run-type", run_type); static struct option long_options[] = { {"force-depends", 0, 0, 'p'}, {"force_depends", 0, 0, 'p'}, {"force-overwrite", 0, 0, 'w'}, {"force_overwrite", 0, 0, 'w'}, {"force-maintainer", 0, 0, 'm'}, {"force_maintainer", 0, 0, 'm'}, {"force-overwrite-configs", 0, 0, 'm'}, {"force_overwrite-configs", 0, 0, 'm'}, {"force-reinstall", 0, 0, 'e'}, {"force_reinstall", 0, 0, 'e'}, {"autoremove", 0, 0, 'a'}, {"autoremove-same-dest", 0, 0, 's'}, {"autoremove_same_dest", 0, 0, 's'}, {"conf", 1, 0, 'c'}, {"dest", 1, 0, 'd'}, {"link-dest", 1, 0, 'l'}, {"link_dest", 1, 0, 'l'}, {"only-dest", 1, 0, 'n'}, {"only_dest", 1, 0, 'n'}, {"tmp-dir", 1, 0, 't'}, {"tmp_dir", 1, 0, 't'}, {"output-format", 1, 0, 'o'}, {"output_format", 1, 0, 'o'}, {"matching-regex", 0, 0, 'r'}, {"matching_regex", 0, 0, 'r'}, {"regex", 0, 0, 'r'}, {"package-variables", 1, 0, 'v'}, {"package_variables", 1, 0, 'v'}, {"help", 0, 0, 'h'}, {NULL, 0, NULL, 0} }; int expect_regex =0; int option_index = 0; int c; while ((c = getopt_long(argc, argv, "pwmeasc:d:l:n:t:o:rv:h", long_options, &option_index)) != -1) { switch(c) { case 'p': set_string_map_element(parameters, "force-depends", strdup("D")); break; case 'w': set_string_map_element(parameters, "force-overwrite", strdup("D")); break; case 'm': set_string_map_element(parameters, "force-overwrite-configs", strdup("D")); break; case 'e': set_string_map_element(parameters, "force-reinstall", strdup("D")); break; case 'a': set_string_map_element(parameters, "autoremove", strdup("D")); break; case 's': set_string_map_element(parameters, "autoremove-same-destination", strdup("D")); break; case 'c': set_string_map_element(parameters, "conf", strdup(optarg)); break; case 'd': set_string_map_element(parameters, "install-destination", strdup(optarg)); break; case 'l': set_string_map_element(parameters, "link-destination", strdup(optarg)); break; case 'n': set_string_map_element(parameters, "only-destination", strdup(optarg)); break; case 't': set_string_map_element(parameters, "tmp-dir", strdup(optarg)); break; case 'o': set_string_map_element(parameters, "output-format", strdup(optarg)); break; case 'v': if(strlen(optarg) >0) { unsigned long num_pieces=0; char seps[] = {',', ';', ':', ' ', '\r', '\n', '\t' }; //include newlines to strip them off end of line char** split_line = split_on_separators(optarg, seps, 7, -1, 0, &num_pieces); if(num_pieces > 0) { string_map* package_variables = initialize_string_map(1); int piece_index; for(piece_index=0; piece_index < num_pieces; piece_index++) { if(strlen(split_line[piece_index]) > 0) { set_string_map_element(package_variables, split_line[piece_index], strdup("D")); } } if(package_variables->num_elements > 0) { set_string_map_element(parameters, "package-variables", package_variables); } } free_null_terminated_string_array(split_line); } break; case 'r': //--matching-regex, or just --regex expect_regex = 1; break; case 'h': default: print_usage(); //exits break; } } if( expect_regex == 1 && strcmp(run_type, "info") != 0 && strcmp(run_type, "list") != 0 && strcmp(run_type, "list-installed") != 0 && strcmp(run_type, "list_installed") ) { fprintf(stderr, "ERROR: package list can only specified with regular expression when using 'list', 'list-installed' or 'info' commands\n\n"); exit(1); } string_map* pkg_list = initialize_string_map(1); set_string_map_element(parameters, "package-list", pkg_list); for(option_index=1; option_index < argc; option_index++) { int option_str_len = strlen(argv[option_index]); if(argv[option_index][0] == '-' && option_str_len > 1) { int has_arg=0; int test_index; const char* name; const char* test_name = argv[option_index] + 1; int is_long_opt=0; if(argv[option_index][1] == '-') { test_name = argv[option_index] + 2; is_long_opt = 1; } for(test_index=0; (name = (long_options[test_index]).name) != NULL ; test_index++) { if( (is_long_opt == 1 && strcmp(test_name, name) == 0) || (is_long_opt == 0 && test_name[0] == (long_options[test_index]).val) ) { has_arg = (long_options[test_index]).has_arg; } } if(has_arg) { option_index++; } } else if(strcmp(argv[option_index], run_type) != 0) { if(expect_regex) { regex_t* packages_matching_regex = (regex_t*)malloc(sizeof(regex_t)); char* regex_str = strdup(argv[option_index]); int regex_len = strlen(regex_str); if(get_string_map_element(parameters, "package-regex") != NULL) { fprintf(stderr, "ERROR: Only one regular expression can be specified at a time.\n\n"); exit(1); } if(regex_str[0] != '/' || regex_str[regex_len-1] != '/') { free(regex_str); regex_str=dynamic_strcat(3, "/", argv[option_index], "/"); } if( convert_to_regex(regex_str, packages_matching_regex) ) { set_string_map_element(parameters, "package-regex", packages_matching_regex); } else { fprintf(stderr, "ERROR: Invalid regular expression \"%s\"\n\n", regex_str); exit(1); } free(regex_str); } else { set_string_map_element(pkg_list, argv[option_index], alloc_depend_def(NULL)); } } } if( strcmp(run_type, "install") == 0 || strcmp(run_type, "remove") == 0 || strcmp(run_type, "upgrade") == 0 ) { if(pkg_list->num_elements == 0) { printf("ERROR: No packages specified to %s.\n\n", run_type); exit(1); } } return parameters; }
int main(int argc, char **argv) { char *table = argv[1]; char *delete_chain = argv[2]; if(argc != 3) { printf("USAGE: %s [TABLE] [CHAIN TO DELETE]\n\n", argv[0]); return 0; } char *command = dynamic_strcat(3, "iptables -t ", table, " -L -n --line-numbers 2>/dev/null"); unsigned long num_lines = 0; char** table_dump = get_shell_command_output_lines(command, &num_lines); free(command); unsigned long line_index; char* current_chain = NULL; list* delete_commands = initialize_list(); for(line_index=0; line_index < num_lines; line_index++) { char* line = table_dump[line_index]; unsigned long num_pieces = 0; char whitespace[] = { '\t', ' ', '\r', '\n' }; char** line_pieces = split_on_separators(line, whitespace, 4, -1, 0, &num_pieces); if(strcmp(line_pieces[0], "Chain") == 0) { if(current_chain != NULL) { free(current_chain); } current_chain = strdup(line_pieces[1]); } else { unsigned long line_num; int read = sscanf(line_pieces[0], "%ld", &line_num); if(read > 0 && current_chain != NULL && num_pieces >1) { if(strcmp(line_pieces[1], delete_chain) == 0) { char* delete_command = dynamic_strcat(7, "iptables -t ", table, " -D ", current_chain, " ", line_pieces[0], " 2>/dev/null"); push_list(delete_commands, delete_command); } } } //free line_pieces free_null_terminated_string_array(line_pieces); } free_null_terminated_string_array(table_dump); /* final two commands to flush chain being deleted and whack it */ unshift_list(delete_commands, dynamic_strcat(5, "iptables -t ", table, " -F ", delete_chain, " 2>/dev/null")); unshift_list(delete_commands, dynamic_strcat(5, "iptables -t ", table, " -X ", delete_chain, " 2>/dev/null")); /* run delete commands */ while(delete_commands->length > 0) { char *next_command = (char*)pop_list(delete_commands); char **out = get_shell_command_output_lines(next_command, &num_lines); free_null_terminated_string_array(out); } return 0; }
/* * assumes 24hr time, not am/pm, in format: * (Day of week) hours:minutes:seconds * if day of week is present, returns seconds since midnight on Sunday * otherwise, seconds since midnight */ unsigned long parse_time(char* time_str) { while((*time_str == ' ' || *time_str == '\t') && *time_str != '\0') { time_str++; } int weekday = -1; if(strlen(time_str) > 3) { char wday_test[4]; memcpy(wday_test, time_str, 3); wday_test[3] = '\0'; to_lowercase(wday_test); if(strcmp(wday_test, "sun") == 0) { weekday = 0; } else if(strcmp(wday_test, "mon") == 0) { weekday = 1; } else if(strcmp(wday_test, "tue") == 0) { weekday = 2; } else if(strcmp(wday_test, "wed") == 0) { weekday = 3; } else if(strcmp(wday_test, "thu") == 0) { weekday = 4; } else if(strcmp(wday_test, "fri") == 0) { weekday = 5; } else if(strcmp(wday_test, "sat") == 0) { weekday = 6; } } if(weekday >= 0) { time_str = time_str + 3; while( (*time_str < 48 || *time_str > 57) && *time_str != '\0') { time_str++; } } char** time_parts=split_on_separators(time_str, ":", 1, -1, 0); unsigned long seconds = weekday < 0 ? 0 : ( ((unsigned long)(weekday))*60*60*24 ); unsigned long tmp; unsigned long multiple = 60*60; int tp_index = 0; for(tp_index=0; time_parts[tp_index] != NULL; tp_index++) { sscanf(time_parts[tp_index], "%ld", &tmp); seconds = seconds + (tmp*multiple); multiple = (unsigned long)(multiple/60); free(time_parts[tp_index]); } free(time_parts); return seconds; }
/* is_weekly_range indicates whether we're parsing hours within a single day or a range over a whole week */ long* parse_time_ranges(char* time_ranges, unsigned char is_weekly_range) { char** pieces = split_on_separators(time_ranges, ",", 1, -1, 0); int num_pieces = 0; for(num_pieces = 0; pieces[num_pieces] != NULL; num_pieces++) {}; long *parsed = (long*)malloc( (1+(num_pieces*2)) * sizeof(long)); int piece_index = 0; for(piece_index = 0; pieces[piece_index] != NULL; piece_index++) { trim_flanking_whitespace(pieces[piece_index]); char** times=split_on_separators(pieces[piece_index], "-", 1, 2, 0); int time_count = 0; for(time_count = 0; times[time_count] != 0 ; time_count++){} if( time_count == 2 ) { unsigned long start = parse_time(trim_flanking_whitespace(times[0])); unsigned long end = parse_time(trim_flanking_whitespace(times[1])); parsed[ piece_index*2 ] = (long)start; parsed[ (piece_index*2)+1 ] = (long)end; free( times[1] ); } if( time_count > 0) { free(times[0]); } free(times); free(pieces[piece_index]); } free(pieces); parsed[ (num_pieces*2) ] = -1; // terminated with -1 // make sure there is no overlap -- this will invalidate ranges int range_index = 0; char overlap_found = 0; for(range_index = 0; range_index < num_pieces; range_index++) { // now test for overlap long start1 = parsed[ (range_index*2) ]; long end1 = parsed[ (range_index*2)+1 ]; end1= end1 < start1 ? end1 + (is_weekly_range ? 7*24*60*60 : 24*60*60) : end1; int range_index2 = 0; for(range_index2 = 0; range_index2 < num_pieces; range_index2++) { if(range_index2 != range_index) { long start2 = parsed[ (range_index2*2) ]; long end2 = parsed[ (range_index2*2)+1 ]; end2= end2 < start2 ? end2 + (is_weekly_range ? 7*24*60*60 : 24*60*60) : end2; overlap_found = overlap_found || (start1 < end2 && end1 > start2 ); } } } if(!overlap_found) { // sort ranges int sorted_index = 0; while(parsed[sorted_index] != -1) { int next_start=-1; int next_start_index=-1; int test_index; long tmp1; long tmp2; for(test_index=sorted_index; parsed[test_index] != -1; test_index=test_index+2) { next_start_index = next_start < 0 || next_start > parsed[test_index] ? test_index : next_start_index; next_start = next_start < 0 || next_start > parsed[test_index] ? parsed[test_index] : next_start; } tmp1 = parsed[next_start_index]; tmp2 = parsed[next_start_index+1]; parsed[next_start_index] = parsed[sorted_index]; parsed[next_start_index+1] = parsed[sorted_index+1]; parsed[sorted_index] = tmp1; parsed[sorted_index+1] = tmp2; sorted_index = sorted_index + 2; } } else { // de-allocate parsed, set to NULL free(parsed); parsed = NULL; } // merge time ranges where end of first = start of second merge_adjacent_time_ranges(parsed, is_weekly_range); // if always active, free & return NULL int max_multiple = is_weekly_range ? 7 : 1; if(parsed[0] == 0 && parsed[1] == max_multiple*24*60*60) { free(parsed); parsed = NULL; } //adjust so any range that crosses end of range is split in two int num_range_indices=0; for(num_range_indices=0; parsed[num_range_indices] != -1; num_range_indices++){} long* adjusted_range = (long*)malloc((3+num_range_indices)*sizeof(long)); int ar_index = 0; int old_index = 0; if(parsed[num_range_indices-1] < parsed[0]) { adjusted_range[0] = 0; adjusted_range[1] = parsed[num_range_indices-1]; ar_index = ar_index + 2; parsed[num_range_indices-1] = -1; } for(old_index=0; parsed[old_index] != -1; old_index++) { adjusted_range[ar_index] = parsed[old_index]; ar_index++; } if(ar_index % 2 == 1 ) { adjusted_range[ar_index] = is_weekly_range ? 7*24*60*60 : 24*60*60; ar_index++; } adjusted_range[ar_index] = -1; free(parsed); return adjusted_range; }
/* takes a string of days e.g. "Monday, Tuesday, Friday", and turns into an array of 7 longs * each 0 or 1, one for each weekday starting with sunday, e.g. [0,1,1,0,0,1,0] for our example */ long* parse_weekdays(char* wd_str) { long* weekdays = (long*)malloc(7*sizeof(long)); weekdays[0] = weekdays[1] = weekdays[2] = weekdays[3] = weekdays[4] = weekdays[5] = weekdays[6] = 0; char** days = split_on_separators(wd_str, ",", 1, -1, 0); int day_index; int found = 0; for(day_index=0; days[day_index] != NULL; day_index++) { char day[4]; trim_flanking_whitespace(days[day_index]); memcpy(day, days[day_index], 3); free(days[day_index]); day[3] = '\0'; to_lowercase(day); if(strcmp(day, "sun") == 0) { weekdays[0] = 1; found = 1; } else if(strcmp(day, "mon") ==0) { weekdays[1] = 1; found = 1; } else if(strcmp(day, "tue") ==0) { weekdays[2] = 1; found = 1; } else if(strcmp(day, "wed") ==0) { weekdays[3] = 1; found = 1; } else if(strcmp(day, "thu") ==0) { weekdays[4] = 1; found = 1; } else if(strcmp(day, "fri") ==0) { weekdays[5] = 1; found = 1; } else if(strcmp(day, "sat") ==0) { weekdays[6] = 1; found = 1; } else if(strcmp(day, "all") ==0) { weekdays[0] = weekdays[1] = weekdays[2] = weekdays[3] = weekdays[4] = weekdays[5] = weekdays[6] = 1; found = 1; } } free(days); if(found == 0) { free(weekdays); weekdays = NULL; } return weekdays; }