#include "conf-update.h" int main(int argc, char **argv) { bool cont, menu_changed, firstrun, doit; bool *tmp_index; char *config_protect = "", *config_protect_mask = ""; char *cmd = "", *myfile = "", *highest = ""; char *esc_highest = "", *esc_myfile = ""; char **result, **envvars, **protected, **masked, **md5_cache; char **md5sum_cache, **myupdate, **merged_updates_report = NULL; char **removed_updates_report = NULL; const char *name, *myname; int indent, myindent, i, j, file_count, c, item_ct, cur; int merged_updates_ct = 0, removed_updates_ct = 0, arglen; ITEM **items_list; MENU *mymenu; WINDOW *inner, *menu_win; read_config(); sanity_checks(); if (argc == 1) { fprintf(stderr, ">>> Getting CONFIG_PROTECT* variables from portage...\n"); #ifdef DEBUG // sandboxing is useful for debugging, believe me envvars = get_listing("portageq envvar CONFIG_PROTECT CONFIG_PROTECT_MASK | sed -e \"s:^/:${SANDBOX}/:\" -e \"s: /: ${SANDBOX}/:g\"", "\n"); #else envvars = get_listing("portageq envvar CONFIG_PROTECT CONFIG_PROTECT_MASK", "\n"); #endif if (is_valid_entry(envvars[0]) && is_valid_entry(envvars[1])) { config_protect = strdup(envvars[0]); config_protect_mask = strdup(envvars[1]); free(envvars[0]); free(envvars[1]); free(envvars); } else { fprintf(stderr, "!!! failed. Aborting.\n"); exit(EXIT_FAILURE); } fprintf(stderr, ">>> Automerging updates in CONFIG_PROTECT_MASK...\n"); masked = find_updates(config_protect_mask); free(config_protect_mask); for (i=0;!is_last_entry(masked[i]);i++) { if (is_valid_entry(masked[i])) { merged_updates_ct++; merged_updates_report = (char **)realloc(merged_updates_report, merged_updates_ct * sizeof(char *)); merged_updates_report[merged_updates_ct-1] = get_real_filename(masked[i]); merge(get_highest_update(masked, masked[i]), masked); } } free(masked); fprintf(stderr, ">>> Searching for updates in CONFIG_PROTECT...\n"); } else { if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) { display_help(); } else { arglen = 0; for (i=1;i>> Searching for updates in specified directories...\n"); } } protected = find_updates(config_protect); // it's important that we do this first if (config.automerge_unmodified) { fprintf(stderr, ">>> Automerging unmodified files...\n"); file_count = 1; md5_cache = (char **) malloc(sizeof(char *) * file_count); md5sum_cache = (char **) malloc(sizeof(char *) * file_count); md5_cache[0] = LAST_ENTRY; md5sum_cache[0] = LAST_ENTRY; for (i=0;!is_last_entry(protected[i]);i++) { if (is_valid_entry(protected[i])) { highest = get_highest_update(protected, protected[i]); if (!strcmp(protected[i], highest)) { md5_cache = (char **) realloc(md5_cache, sizeof(char *) * (file_count + 1)); md5sum_cache = (char **) realloc(md5sum_cache, sizeof(char *) * (file_count + 1)); md5_cache[file_count-1] = strdup(highest); md5sum_cache[file_count-1] = (char *)malloc(sizeof(char) * 32); calc_md5(md5_cache[file_count-1], md5sum_cache[file_count-1]); md5_cache[file_count] = LAST_ENTRY; md5sum_cache[file_count] = LAST_ENTRY; file_count++; } } } for (i=0;!is_last_entry(protected[i]);i++) { if (is_valid_entry(protected[i])) { myfile = get_real_filename(protected[i]); if (!user_modified(myfile)) { merged_updates_ct++; merged_updates_report = (char **)realloc(merged_updates_report, merged_updates_ct * sizeof(char *)); merged_updates_report[merged_updates_ct-1] = get_real_filename(protected[i]); merge(get_highest_update(protected, protected[i]), protected); } free(myfile); } } for (i=0;!is_last_entry(md5_cache[i]);i++) { myfile = get_real_filename(md5_cache[i]); md5sum_update(myfile, md5sum_cache[i]); free(myfile); free(md5_cache[i]); free(md5sum_cache[i]); } free(md5_cache); free(md5sum_cache); } if (config.automerge_trivial) { fprintf(stderr, ">>> Automerging trivial changes...\n"); for (i=0;!is_last_entry(protected[i]);i++) { if (is_valid_entry(protected[i])) { myfile = get_real_filename(protected[i]); esc_myfile = g_shell_quote(myfile); highest = get_highest_update(protected, protected[i]); esc_highest = g_shell_quote(highest); cmd = (char *)calloc(strlen("diff -Nu % % | grep \"^[+-][^+-]\" | grep -v \"^[-+]#\" | grep -v \"^[-+][[:space:]]*$\" " ) + strlen(esc_highest) + strlen(esc_myfile), sizeof(char)); strcpy(cmd, "diff -Nu "); strcat(cmd, esc_myfile); strcat(cmd, " "); strcat(cmd, esc_highest); strcat(cmd, " | grep \"^[+-][^+-]\" | grep -v \"^[-+]#\" | grep -v \"^[-+][[:space:]]*$\""); free(myfile); free(esc_myfile); free(esc_highest); result = get_listing(cmd, "\n"); free(cmd); if (is_last_entry(result[0])) { merged_updates_ct++; merged_updates_report = (char **)realloc(merged_updates_report, merged_updates_ct * sizeof(char *)); merged_updates_report[merged_updates_ct-1] = get_real_filename(highest); merge(highest, protected); } for (j=0;!is_last_entry(result[j]);j++) { free(result[j]); } free(result); } } } /***/ // ncurses n'stuff initscr(); cbreak(); noecho(); keypad(stdscr, TRUE); start_color(); init_pair(1, COLOR_CYAN, COLOR_BLUE); init_pair(2, COLOR_WHITE, COLOR_WHITE); init_pair(3, COLOR_BLACK, COLOR_WHITE); init_pair(4, COLOR_RED, COLOR_WHITE); init_pair(5, COLOR_WHITE, COLOR_BLACK); draw_background(); inner = newwin(LINES - 4, COLS - 4, 2, 2); keypad(inner, TRUE); draw_legend(inner); menu_win = subwin(inner, LINES - 7 - 6, COLS - 4 - 3, 8, 3); mymenu = create_menu(protected); items_list = menu_items(mymenu); set_menu_win(mymenu, inner); set_menu_sub(mymenu, menu_win); post_menu(mymenu); touchwin(inner); wrefresh(inner); menu_changed = FALSE; while ((item_count(mymenu) > 1) && (c = wgetch(inner)) != 'q' && c != 'Q') { switch(c) { // navigation 1up/down case KEY_DOWN: menu_driver(mymenu, REQ_DOWN_ITEM); break; case KEY_UP: menu_driver(mymenu, REQ_UP_ITEM); break; //navigation 1 page up/down case KEY_PPAGE: menu_driver(mymenu, REQ_SCR_UPAGE); break; case KEY_NPAGE: menu_driver(mymenu, REQ_SCR_DPAGE); break; // navigation top/bottom case KEY_HOME: menu_driver(mymenu, REQ_FIRST_ITEM); break; case KEY_END: menu_driver(mymenu, REQ_LAST_ITEM); break; // select single case ' ': if ((strrchr(item_name(current_item(mymenu)), '/'))) { // it's a dir, select all subdirs + files name = item_name(current_item(mymenu)); indent = 0; while (name[indent] == INDENT_CHAR) { indent++; } cont = TRUE; while (cont) { menu_driver(mymenu, REQ_DOWN_ITEM); myname = item_name(current_item(mymenu)); myindent = 0; while (myname[myindent] == INDENT_CHAR) { myindent++; } if (myindent > indent) { if ((!strrchr(myname, '/'))) { set_item_value(current_item(mymenu), TRUE); } } else { menu_driver(mymenu, REQ_UP_ITEM); cont = FALSE; } } } else { menu_driver(mymenu, REQ_TOGGLE_ITEM); } break; // select all case 'a': case 'A': menu_driver(mymenu, REQ_LAST_ITEM); for (i=0;i=0;i--) { if (item_value(items_list[i]) == TRUE || (current_item(mymenu) == items_list[i] && item_userptr(items_list[i]))) { if (firstrun) { doit = get_confirmation(inner, "replace"); firstrun = false; } if (doit) { myupdate = (char **)item_userptr(items_list[i]); if (is_valid_entry(*myupdate)) { merged_updates_ct++; merged_updates_report = (char **)realloc(merged_updates_report, merged_updates_ct * sizeof(char *)); merged_updates_report[merged_updates_ct-1] = get_real_filename(*myupdate); menu_changed = TRUE; merge(*myupdate, protected); } } } } break; // delete update case 'd': case 'D': firstrun = config.check_actions; doit = TRUE; for (i=0;i 13 && COLS > 55) { // we don't want to loose the selection just because of a window resize item_ct = item_count(mymenu); cur = item_index(current_item(mymenu)); tmp_index = malloc(sizeof(bool) * item_ct); for (i=0;i 0) { fprintf(stdout, ">>> Merged updates for the following files:\n"); for (i=0;i 0) { fprintf(stdout, ">>> Deleted updates for the following files:\n"); for (i=0;i>> Nothing left to do... Bye!\n"); exit(EXIT_SUCCESS); }