diff options
author | 2010-10-11 17:20:11 +0200 | |
---|---|---|
committer | 2010-10-11 17:20:11 +0200 | |
commit | f3fee983dd082266cc932df5b248d1a9b1bdd41a (patch) | |
tree | 547d2b6c7e6fc1afed5854568d1a18a2f8331b02 /helpers.c | |
parent | Zero (diff) | |
download | conf-update-f3fee983dd082266cc932df5b248d1a9b1bdd41a.tar.gz conf-update-f3fee983dd082266cc932df5b248d1a9b1bdd41a.tar.bz2 conf-update-f3fee983dd082266cc932df5b248d1a9b1bdd41a.zip |
Add code of conf-update 1.01.0
Diffstat (limited to 'helpers.c')
-rw-r--r-- | helpers.c | 461 |
1 files changed, 461 insertions, 0 deletions
diff --git a/helpers.c b/helpers.c new file mode 100644 index 0000000..a56e65d --- /dev/null +++ b/helpers.c @@ -0,0 +1,461 @@ +#include "conf-update.h" + +char **get_listing(char *cmd, char *delim) { + FILE *pipe; + char *buf = NULL; + size_t bufsize = 0; + ssize_t read; + char **listing; + int count = 1, i = 0; + unsigned int j; + char c; + + pipe = popen(cmd, "r"); + if (pipe) { + read = getdelim(&buf, &bufsize, '\0', pipe); + char *buf_backup = buf; + if (read != -1) { + // determine number of tokens + while ((c = buf[i]) != '\0') { + for (j=0;j<strlen(delim);j++) { + if (c == delim[j]) { + count++; + } + } + i++; + } + + listing = (char **) malloc(sizeof(char *) * count); + char *str; + i=0; + while ((str = strsep(&buf, delim))) { + listing[i] = strdup(str); + i++; + } + free(buf_backup); + // make sure the last one is always LAST_ENTRY + listing[count-1] = LAST_ENTRY; + pclose(pipe); + return listing; + } else { + pclose(pipe); + listing = (char **)malloc(sizeof(char *)); + listing[0] = LAST_ENTRY; + free(buf_backup); + return listing; + } + } else { + exit_error(0, cmd); + } + // just for gcc, that bitch + return NULL; +} + +int compare_updates(const void *a, const void *b) { + char *real_a; + char *real_b; + int result; + signed mod = 1; + + if (is_valid_entry(*(char **)a)) { + real_a = get_real_filename(*(char **)a); + } else { + real_a = NULL; + } + if (is_valid_entry(*(char **)b)) { + real_b = get_real_filename(*(char **)b); + } else { + real_b = NULL; + } + + if (!real_a && !real_b) { + result = -1; + } else if (!real_a) { + result = 1; + } else if (!real_b) { + result = -1; + } else { + // both valid updates + if ((result = strcmp(real_a, real_b)) == 0) { + // same target + if ((result = strncmp(strstr(*(char **)a, "._cfg"), strstr(*(char **)b, "._cfg"), strlen("._cfg????"))) == 0) { + // same update number. interactively merged vs. predefined, 1:0 for the user. + mod = -1; + } + result = mod * strcmp(*(char **)a, *(char **)b); + } + } + + free(real_a); + free(real_b); + + return result; +} + +struct node *fold_updates(char **list) { + struct node *root = malloc(sizeof(struct node)); + struct node *mynode, *newnode; + char *endtok, *curtok; + int i; + int run; + + root->name = strdup("/"); + root->children = malloc(sizeof(struct node *)); + root->ct_children = 0; + root->parent = NULL; + root->dir = TRUE; + root->link = NULL; + + for (i=0;!is_last_entry(list[i]);i++) { + if (is_valid_entry(list[i])) { + endtok = list[i]+1; + run = 1; + while (run) { + if (run == 2) { + // 2 means we're on the last run + run = 0; + endtok = list[i] + strlen(list[i]) + 1; + } else { + if ((endtok = strchr(endtok+1, '/')) == NULL) { + run = 2; + } + } + curtok = strndup(list[i], endtok - list[i]); + + mynode = find_node(root, curtok); + if (mynode == (struct node *)FALSE) { + mynode = root; + } + if (mynode != (struct node *)TRUE) { + // mynode is the parent of the new to be inserted node + newnode = malloc(sizeof(struct node)); + newnode->name = strdup(curtok); + if (!strcmp(curtok,list[i])) { + // it's the file + newnode->dir = FALSE; + newnode->link = &list[i]; + } else { + newnode->name = strdup(curtok); + newnode->dir = TRUE; + newnode->link = NULL; + } + newnode->children = malloc(sizeof(struct node *)); + newnode->ct_children = 0; + newnode->parent = mynode; + + mynode->ct_children++; + mynode->children = realloc(mynode->children, sizeof(struct node *) * mynode->ct_children); + mynode->children[mynode->ct_children-1] = newnode; + } + + free(curtok); + } + } + } + + return root; + +} + +struct node *find_node(struct node *root, char *path) { + int i; + struct node *mynode; + + if (!strcmp(root->name, path)) { + // already exists + return (struct node *)TRUE; + } else if (!strncmp(root->name, path, strlen(root->name)) && root->dir == TRUE) { + // at least it's in the same direction, go through the list of children + for (i=0;i<root->ct_children;i++) { + mynode = find_node(root->children[i], path); + if (mynode == (struct node *)TRUE) { + return (struct node *)TRUE; + } else if (mynode != (struct node *)FALSE) { + return mynode; + } + } + // if we hit this point, nothing was found, meaning that it has to be a child of the current node + return root; + } else { + // completely wrong + return (struct node *)FALSE; + } +} +void sanity_checks() { + extern struct configuration config; + unsigned int i; + FILE *pipe; + char *cmd = NULL; + char *tools[] = { + "diff", + "portageq", + strndup(config.pager, strchrnul(config.pager, ' ') - config.pager), + strndup(config.diff_tool, strchrnul(config.diff_tool, ' ') - config.diff_tool), + strndup(config.merge_tool, strchrnul(config.merge_tool, ' ') - config.merge_tool), + strndup(config.edit_tool, strchrnul(config.edit_tool, ' ') - config.edit_tool) + }; + + if (getuid() != 0) { + fprintf(stderr, "!!! Oops, you're not root!\n"); + exit(EXIT_FAILURE); + } + + for (i=0;i<sizeof(tools)/sizeof(tools[0]);i++) { + // "" is okay for pager + if (strcmp(tools[i], "")) { + if (!g_find_program_in_path((gchar *)tools[i])) { + fprintf(stderr, "!!! ERROR: couldn't find necesary tool: %s\n", tools[i]); + exit(EXIT_FAILURE); + } + } + } + free(cmd); + + mkdir (MD5SUM_INDEX_DIR, 0755); + if ((pipe = fopen(MD5SUM_INDEX, "a"))) { + fclose(pipe); + } else { + fprintf(stderr, "!!! ERROR: Can't write to %s; check permissions", MD5SUM_INDEX); + exit(EXIT_FAILURE); + } +} + +void draw_legend(WINDOW *inner) { + int i; + + wattron(inner, COLOR_PAIR(2)); + wattron(inner, A_BOLD); + box(inner, 0, 0); + for (i=1;i<LINES-5;i++) { + mvwhline(inner, i, 1, ' ', COLS-6); + } + + wattroff(inner, A_BOLD); + wattron(inner, COLOR_PAIR(3)); + mvwprintw(inner, 1, 2, "Select current: !!!!!!! | !!!ll | !!!nselect all"); + mvwprintw(inner, 2, 2, "Show diff: !!!!!!! | !!!dit update | !!!erge interactively"); + mvwprintw(inner, 3, 2, "Actions for all selected: !!!eplace config file(s) | !!!elete update(s)"); // | merge !!!nteractively"); + mvwprintw(inner, 4, 2, "Quit: !!!"); + + wattron(inner, COLOR_PAIR(4)); + mvwprintw(inner, 1, 2 + strlen("Select current: "), "[SPACE]"); + mvwprintw(inner, 1, 2 + strlen("Select current: !!!!!!! | "), "[A]"); + mvwprintw(inner, 1, 2 + strlen("Select current: !!!!!!! | !!!ll | "), "[U]"); + + mvwprintw(inner, 2, 2 + strlen("Show diff: "), "[ENTER]"); + mvwprintw(inner, 2, 2 + strlen("Show diff: !!!!!!! | "), "[E]"); + mvwprintw(inner, 2, 2 + strlen("Show diff: !!!!!!! | !!!dit update | "), "[M]"); + + mvwprintw(inner, 3, 2 + strlen("Actions for all selected: "), "[R]"); + mvwprintw(inner, 3, 2 + strlen("Actions for all selected: !!!eplace config file(s) | "), "[D]"); + //mvwprintw(inner, 3, 2 + strlen("Action shortcuts: !!!erge | !!!elete update | merge "), "[I]"); + + mvwprintw(inner, 4, 2 + strlen("Quit: "), "[Q]"); + + wattron(inner, COLOR_PAIR(2) | A_BOLD); + // TODO: replace COLS - 4/LINES - 7 with a function to determine size of inner + mvwhline(inner, 5, 1, 0, COLS - 4 -2); + mvwhline(inner, LINES - 7, 1, 0, COLS - 4 -2); + + wrefresh(inner); +} + +void draw_background() { + int i; + + attron(A_BOLD); + attron(COLOR_PAIR(1)); + // why does clear() not work here? + for (i=0;i<LINES;i++) { + mvhline(i, 0, ' ', COLS); + } + attron(COLOR_PAIR(5)); + mvhline(LINES-2, 3, ' ', COLS-4); + mvvline(3, COLS-2, ' ', LINES-4); + attron(COLOR_PAIR(1)); + mvprintw(0,1, PROG_NAME); + mvprintw(0,strlen(PROG_NAME) + 2, PROG_VERSION); + mvhline(1, 1, ACS_HLINE, COLS - 2); + + refresh(); +} + +char *get_indent_name(struct node *update, int width) { + int ct_indents = 0; + struct node *mynode = update; + char *start, *name; + char *indent_name; + char number[] = "0000"; + int num, remainder, i; + + while ((mynode = mynode->parent)) { + ct_indents++; + } + indent_name = calloc(width + 1, sizeof(char)); + if ((start = strstr(update->name, "._cfg"))) { + name = start+strlen("._cfg????_"); + while (ct_indents > 0) { + strcat(indent_name, INDENT_STR); + ct_indents--; + } + strcat(indent_name, name); + strcat(indent_name, " ("); + strncpy(number, start+strlen("._cfg"), 4); + num = atoi(number) + 1; + snprintf(indent_name + strlen(indent_name), 4, "%d", num); + strcat(indent_name, ")"); + if (*(name - 1) == '-') { + strcat(indent_name, "(merged)"); + } + } else { + start = strrchr(update->name, '/') + 1; + while (ct_indents > 0) { + strcat(indent_name, INDENT_STR); + ct_indents--; + } + strcat(indent_name, start); + strcat(indent_name, "/"); + } + remainder = width - strlen(indent_name); + for(i=0;i<remainder;i++) { + strcat(indent_name, " "); + } + + return indent_name; +} +int count_array_items(struct node *root) { + int count = 0, i; + + for (i=0;i<root->ct_children;i++) { + count += count_array_items(root->children[i]); + } + return 1 + count; +} + +void build_item_array(ITEM **item_array, struct node *root, int menu_width) { + int i = 0; + + // fast-forward to the next NULL entry + while (item_array[i]) { + i++; + } + item_array[i] = new_item(get_indent_name(root, menu_width), ""); + set_item_userptr(item_array[i], root->link); + + for (i=0;i<root->ct_children;i++) { + build_item_array(item_array, root->children[i], menu_width); + } +} +void free_folded(struct node *root) { + int i; + + for (i=0;i<root->ct_children;i++) { + free_folded(root->children[i]); + } + if (root->dir) { + free(root->name); + } + free(root->children); + free(root); +} + +bool get_confirmation(WINDOW *win, char *action) { + bool result; + echo(); + nocbreak(); + char ret[2] = " "; + wattron(win, COLOR_PAIR(4)); + wattroff(win, A_BOLD); + // TODO: replace COLS - 4/LINES - 7 with a function to determine size of inner + mvwprintw(win, LINES - 6, 2, "Do you really want to "); + wprintw(win, action); + wprintw(win, " all selected updates? [y/n] "); + refresh(); + wgetnstr(win, ret, 1); + if (!strcmp(ret,"y")) { + result = true; + } else { + result = false; + } + mvwhline(win, LINES - 6, 1, ' ', COLS - 4 -2); + noecho(); + cbreak(); + return result; +} +void exit_error(bool expr, char *hint) { + if (!expr) { + endwin(); + char *mystring = calloc(sizeof(char), strlen("!!! ERROR: ") + strlen(hint) + 1); + sprintf(mystring, "!!! ERROR: %s", hint); + perror(mystring); + exit(EXIT_FAILURE); + } +} + +char **get_files_list(char *searchpath, char **index, int *max) { + struct stat mystat, tmpstat; + int i = 0, j; + DIR *dirfd; + struct dirent *file = (struct dirent *)TRUE; + char *absfile; + char *myfile; + bool ignore; + + lstat(searchpath, &mystat); + if (S_ISDIR(mystat.st_mode)) { + dirfd = opendir(searchpath); + if (dirfd) { + while (file) { + file = readdir(dirfd); + if (file && strcmp(file->d_name, ".") && strcmp(file->d_name, "..") && \ + strcmp(file->d_name, ".svn") && strcmp(file->d_name, "CVS")) { + absfile = (char *)calloc((strlen(searchpath) + strlen("/") + strlen(file->d_name) + 1), sizeof(char *)); + strcpy(absfile, searchpath); + strcat(absfile, "/"); + strcat(absfile, file->d_name); + index = get_files_list(absfile, index, max); + free(absfile); + } + } + } else if (errno == ENOENT) { + return index; + } else { + exit_error(0, searchpath); + } + closedir(dirfd); + } else if (S_ISREG(mystat.st_mode)) { + if (!strncmp(strrchr(searchpath, '/')+1, "._cfg", strlen("._cfg"))) { + if (*(searchpath+strlen(searchpath)-1) != '~' && \ + strcmp(searchpath+strlen(searchpath)-4,".bak")) { + myfile = get_real_filename(searchpath); + if (access(myfile, F_OK) != 0) { + // we don't want phantom updates + unlink(searchpath); + } else { + // we don't want duplicates either + ignore = FALSE; + for (j=0;j<(*max);j++) { + lstat(index[j], &tmpstat); + if (tmpstat.st_dev == mystat.st_dev && \ + tmpstat.st_ino == mystat.st_ino) { + ignore = TRUE; + } + } + if (!ignore) { + while (i < (*max) && !is_last_entry(index[i])) { + i++; + } + if (i + 1 >= (*max)) { + (*max)++; + index = (char **)realloc(index, (*max) * sizeof(char *)); + } + index[i] = strdup(searchpath); + index[i+1] = LAST_ENTRY; + } + } + free(myfile); + } + } + } + return index; +} |